diff --git a/db/changes/10491-august/00-aclInvoiceOut.sql b/db/changes/10491-august/00-aclInvoiceOut.sql
new file mode 100644
index 000000000..b129b7201
--- /dev/null
+++ b/db/changes/10491-august/00-aclInvoiceOut.sql
@@ -0,0 +1,3 @@
+INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
+ VALUES
+ ('InvoiceOut', 'clientToInvoice', 'WRITE', 'ALLOW', 'ROLE', 'invoicing');
\ No newline at end of file
diff --git a/modules/invoiceOut/back/methods/invoiceOut/clientToInvoice.js b/modules/invoiceOut/back/methods/invoiceOut/clientToInvoice.js
new file mode 100644
index 000000000..16c999e73
--- /dev/null
+++ b/modules/invoiceOut/back/methods/invoiceOut/clientToInvoice.js
@@ -0,0 +1,173 @@
+module.exports = Self => {
+ Self.remoteMethodCtx('clientToInvoice', {
+ description: 'Get the clients to make global invoicing',
+ accessType: 'WRITE',
+ accepts: [
+ {
+ arg: 'invoiceDate',
+ type: 'date',
+ description: 'The invoice date'
+ },
+ {
+ arg: 'maxShipped',
+ type: 'date',
+ description: 'The maximum shipped date'
+ },
+ {
+ arg: 'fromClientId',
+ type: 'number',
+ description: 'The minimum client id'
+ },
+ {
+ arg: 'toClientId',
+ type: 'number',
+ description: 'The maximum client id',
+ required: false
+ },
+ {
+ arg: 'companyFk',
+ type: 'number',
+ description: 'The company id to invoice'
+ }
+ ],
+ returns: {
+ type: 'object',
+ root: true
+ },
+ http: {
+ path: '/clientToInvoice',
+ verb: 'POST'
+ }
+ });
+
+ Self.clientToInvoice = async(ctx, options) => {
+ const args = ctx.args;
+ let tx;
+ const myOptions = {};
+
+ if (typeof options == 'object')
+ Object.assign(myOptions, options);
+
+ if (!myOptions.transaction) {
+ tx = await Self.beginTransaction({});
+ myOptions.transaction = tx;
+ }
+
+ const clientToInvoideIds = [];
+ let query;
+ try {
+ query = `
+ SELECT MAX(issued) issued
+ FROM vn.invoiceOut io
+ JOIN vn.time t ON t.dated = io.issued
+ WHERE io.serial = 'A'
+ AND t.year = YEAR(?)
+ AND io.companyFk = ?`;
+ const [maxIssued] = await Self.rawSql(query, [
+ args.invoiceDate,
+ args.companyFk
+ ], myOptions);
+
+ const maxSerialDate = maxIssued.issued || args.invoiceDate;
+ if (args.invoiceDate < maxSerialDate)
+ args.invoiceDate = maxSerialDate;
+
+ if (args.invoiceDate < args.maxShipped)
+ args.maxShipped = args.invoiceDate;
+
+ const minShipped = new Date();
+ minShipped.setFullYear(minShipped.getFullYear() - 1);
+ minShipped.setMonth(1);
+ minShipped.setDate(1);
+ minShipped.setHours(0, 0, 0, 0);
+
+ // Packaging liquidation
+ const vIsAllInvoiceable = false;
+ const clientsWithPackaging = await getClientsWithPackaging(ctx, myOptions);
+ for (let client of clientsWithPackaging) {
+ await Self.rawSql('CALL packageInvoicing(?, ?, ?, ?, @newTicket)', [
+ client.id,
+ args.invoiceDate,
+ args.companyFk,
+ vIsAllInvoiceable
+ ], myOptions);
+ }
+
+ const invoiceableClients = await getInvoiceableClients(ctx, myOptions);
+
+ if (!invoiceableClients.length) return;
+
+ const clientToInvoiceIds = invoiceableClients.map(invoiceableClient => invoiceableClient.id);
+ const dataArr = new Set(clientToInvoiceIds);
+ const clientNotRepeatedIds = [...dataArr];
+
+ if (tx) await tx.commit();
+
+ console.log(invoiceableClients, clientToInvoiceIds, clientNotRepeatedIds);
+ return clientNotRepeatedIds;
+ } catch (e) {
+ if (tx) await tx.rollback();
+ throw e;
+ }
+ };
+
+ async function getClientsWithPackaging(ctx, options) {
+ const models = Self.app.models;
+ const args = ctx.args;
+ const query = `SELECT DISTINCT clientFk AS id
+ FROM ticket t
+ JOIN ticketPackaging tp ON t.id = tp.ticketFk
+ JOIN client c ON c.id = t.clientFk
+ WHERE t.shipped BETWEEN '2017-11-21' AND ?
+ AND t.clientFk >= ?
+ AND (t.clientFk <= ? OR ? IS NULL)
+ AND c.isActive`;
+ return models.InvoiceOut.rawSql(query, [
+ args.maxShipped,
+ args.fromClientId,
+ args.toClientId,
+ args.toClientId
+ ], options);
+ }
+
+ async function getInvoiceableClients(ctx, options) {
+ const models = Self.app.models;
+ const args = ctx.args;
+ const minShipped = new Date();
+ minShipped.setFullYear(minShipped.getFullYear() - 1);
+
+ const query = `SELECT
+ c.id,
+ SUM(IFNULL
+ (
+ s.quantity *
+ s.price * (100-s.discount)/100,
+ 0)
+ + IFNULL(ts.quantity * ts.price,0)
+ ) AS sumAmount,
+ c.hasToInvoiceByAddress,
+ c.email,
+ c.isToBeMailed,
+ a.id addressFk
+ FROM ticket t
+ LEFT JOIN sale s ON s.ticketFk = t.id
+ LEFT JOIN ticketService ts ON ts.ticketFk = t.id
+ JOIN address a ON a.id = t.addressFk
+ JOIN client c ON c.id = t.clientFk
+ WHERE ISNULL(t.refFk) AND c.id >= ?
+ AND (t.clientFk <= ? OR ? IS NULL)
+ AND t.shipped BETWEEN ? AND util.dayEnd(?)
+ AND t.companyFk = ? AND c.hasToInvoice
+ AND c.isTaxDataChecked AND c.isActive
+ GROUP BY c.id, IF(c.hasToInvoiceByAddress,a.id,TRUE) HAVING sumAmount > 0`;
+
+ return models.InvoiceOut.rawSql(query, [
+ args.fromClientId,
+ args.toClientId,
+ args.toClientId,
+ minShipped,
+ args.maxShipped,
+ args.companyFk
+ ], options);
+ }
+};
diff --git a/modules/invoiceOut/back/methods/invoiceOut/globalInvoicing.js b/modules/invoiceOut/back/methods/invoiceOut/globalInvoicing.js
index dae6a0c33..bee79746a 100644
--- a/modules/invoiceOut/back/methods/invoiceOut/globalInvoicing.js
+++ b/modules/invoiceOut/back/methods/invoiceOut/globalInvoicing.js
@@ -1,35 +1,13 @@
module.exports = Self => {
Self.remoteMethodCtx('globalInvoicing', {
- description: 'Make a global invoice',
+ description: 'Make a global invoice of a client',
accessType: 'WRITE',
- accepts: [
- {
- arg: 'invoiceDate',
- type: 'date',
- description: 'The invoice date'
- },
- {
- arg: 'maxShipped',
- type: 'date',
- description: 'The maximum shipped date'
- },
- {
- arg: 'fromClientId',
- type: 'number',
- description: 'The minimum client id'
- },
- {
- arg: 'toClientId',
- type: 'number',
- description: 'The maximum client id',
- required: false
- },
- {
- arg: 'companyFk',
- type: 'number',
- description: 'The company id to invoice'
- }
- ],
+ accepts: [{
+ arg: 'clientId',
+ type: 'number',
+ description: 'The client id to invoice',
+ required: true
+ }],
returns: {
type: 'object',
root: true
@@ -40,10 +18,10 @@ module.exports = Self => {
}
});
- Self.globalInvoicing = async(ctx, options) => {
- const args = ctx.args;
- let tx;
+ Self.globalInvoicing = async(ctx, clientId, options) => {
+ const models = Self.app.models;
const myOptions = {};
+ let tx;
if (typeof options == 'object')
Object.assign(myOptions, options);
@@ -55,108 +33,65 @@ module.exports = Self => {
const invoicesIds = [];
const failedClients = [];
- let query;
try {
- query = `
- SELECT MAX(issued) issued
- FROM vn.invoiceOut io
- JOIN vn.time t ON t.dated = io.issued
- WHERE io.serial = 'A'
- AND t.year = YEAR(?)
- AND io.companyFk = ?`;
- const [maxIssued] = await Self.rawSql(query, [
- args.invoiceDate,
- args.companyFk
- ], myOptions);
-
- const maxSerialDate = maxIssued.issued || args.invoiceDate;
- if (args.invoiceDate < maxSerialDate)
- args.invoiceDate = maxSerialDate;
-
- if (args.invoiceDate < args.maxShipped)
- args.maxShipped = args.invoiceDate;
-
- const minShipped = new Date();
- minShipped.setFullYear(minShipped.getFullYear() - 1);
- minShipped.setMonth(1);
- minShipped.setDate(1);
- minShipped.setHours(0, 0, 0, 0);
-
- // Packaging liquidation
- const vIsAllInvoiceable = false;
- const clientsWithPackaging = await getClientsWithPackaging(ctx, myOptions);
- for (let client of clientsWithPackaging) {
- await Self.rawSql('CALL packageInvoicing(?, ?, ?, ?, @newTicket)', [
- client.id,
- args.invoiceDate,
- args.companyFk,
- vIsAllInvoiceable
- ], myOptions);
- }
-
- const invoiceableClients = await getInvoiceableClients(ctx, myOptions);
-
- if (!invoiceableClients.length) return;
-
- for (let client of invoiceableClients) {
- try {
- if (client.hasToInvoiceByAddress) {
- await Self.rawSql('CALL ticketToInvoiceByAddress(?, ?, ?, ?)', [
- minShipped,
- args.maxShipped,
- client.addressFk,
- args.companyFk
- ], myOptions);
- } else {
- await Self.rawSql('CALL invoiceFromClient(?, ?, ?)', [
- args.maxShipped,
- client.id,
- args.companyFk
- ], myOptions);
- }
-
- // Make invoice
- const isSpanishCompany = await getIsSpanishCompany(args.companyFk, myOptions);
-
- // Validates ticket nagative base
- const hasAnyNegativeBase = await getNegativeBase(myOptions);
- if (hasAnyNegativeBase && isSpanishCompany)
- continue;
-
- query = `SELECT invoiceSerial(?, ?, ?) AS serial`;
- const [invoiceSerial] = await Self.rawSql(query, [
+ const client = await models.Client.findById(clientId, {
+ fields: ['id', 'hasToInvoiceByAddress', 'addressFk']
+ }, myOptions);
+ try {
+ if (client.hasToInvoiceByAddress) {
+ await Self.rawSql('CALL ticketToInvoiceByAddress(?, ?, ?, ?)', [
+ minShipped,
+ args.maxShipped,
+ client.addressFk,
+ args.companyFk
+ ], myOptions);
+ } else {
+ await Self.rawSql('CALL invoiceFromClient(?, ?, ?)', [
+ args.maxShipped,
client.id,
- args.companyFk,
- 'G'
+ args.companyFk
], myOptions);
- const serialLetter = invoiceSerial.serial;
-
- query = `CALL invoiceOut_new(?, ?, NULL, @invoiceId)`;
- await Self.rawSql(query, [
- serialLetter,
- args.invoiceDate
- ], myOptions);
-
- const [newInvoice] = await Self.rawSql(`SELECT @invoiceId id`, null, myOptions);
- if (newInvoice.id) {
- await Self.rawSql('CALL invoiceOutBooking(?)', [newInvoice.id], myOptions);
-
- query = `INSERT IGNORE INTO invoiceOutQueue(invoiceFk) VALUES(?)`;
- await Self.rawSql(query, [newInvoice.id], myOptions);
-
- invoicesIds.push(newInvoice.id);
- }
- } catch (e) {
- failedClients.push({
- id: client.id,
- stacktrace: e
- });
- continue;
}
- }
- if (failedClients.length > 0)
- await notifyFailures(ctx, failedClients, myOptions);
+ // Make invoice
+ const isSpanishCompany = await getIsSpanishCompany(args.companyFk, myOptions);
+
+ // Validates ticket nagative base
+ const hasAnyNegativeBase = await getNegativeBase(myOptions);
+ if (hasAnyNegativeBase && isSpanishCompany)
+ return notifyFailures(ctx, failedClients, myOptions); // continue
+
+ query = `SELECT invoiceSerial(?, ?, ?) AS serial`;
+ const [invoiceSerial] = await Self.rawSql(query, [
+ client.id,
+ args.companyFk,
+ 'G'
+ ], myOptions);
+ const serialLetter = invoiceSerial.serial;
+
+ query = `CALL invoiceOut_new(?, ?, NULL, @invoiceId)`;
+ await Self.rawSql(query, [
+ serialLetter,
+ args.invoiceDate
+ ], myOptions);
+
+ const [newInvoice] = await Self.rawSql(`SELECT @invoiceId id`, null, myOptions);
+ if (newInvoice.id) {
+ await Self.rawSql('CALL invoiceOutBooking(?)', [newInvoice.id], myOptions);
+
+ query = `INSERT IGNORE INTO invoiceOutQueue(invoiceFk) VALUES(?)`;
+ await Self.rawSql(query, [newInvoice.id], myOptions);
+
+ invoicesIds.push(newInvoice.id);
+ }
+ } catch (e) {
+ failedClients.push({
+ id: client.id,
+ stacktrace: e
+ });
+ return notifyFailures(ctx, failedClients, myOptions); // continue
+ }
+ // }
if (tx) await tx.commit();
} catch (e) {
@@ -189,66 +124,6 @@ module.exports = Self => {
return supplierCompany && supplierCompany.total;
}
- async function getClientsWithPackaging(ctx, options) {
- const models = Self.app.models;
- const args = ctx.args;
- const query = `SELECT DISTINCT clientFk AS id
- FROM ticket t
- JOIN ticketPackaging tp ON t.id = tp.ticketFk
- JOIN client c ON c.id = t.clientFk
- WHERE t.shipped BETWEEN '2017-11-21' AND ?
- AND t.clientFk >= ?
- AND (t.clientFk <= ? OR ? IS NULL)
- AND c.isActive`;
- return models.InvoiceOut.rawSql(query, [
- args.maxShipped,
- args.fromClientId,
- args.toClientId,
- args.toClientId
- ], options);
- }
-
- async function getInvoiceableClients(ctx, options) {
- const models = Self.app.models;
- const args = ctx.args;
- const minShipped = new Date();
- minShipped.setFullYear(minShipped.getFullYear() - 1);
-
- const query = `SELECT
- c.id,
- SUM(IFNULL
- (
- s.quantity *
- s.price * (100-s.discount)/100,
- 0)
- + IFNULL(ts.quantity * ts.price,0)
- ) AS sumAmount,
- c.hasToInvoiceByAddress,
- c.email,
- c.isToBeMailed,
- a.id addressFk
- FROM ticket t
- LEFT JOIN sale s ON s.ticketFk = t.id
- LEFT JOIN ticketService ts ON ts.ticketFk = t.id
- JOIN address a ON a.id = t.addressFk
- JOIN client c ON c.id = t.clientFk
- WHERE ISNULL(t.refFk) AND c.id >= ?
- AND (t.clientFk <= ? OR ? IS NULL)
- AND t.shipped BETWEEN ? AND util.dayEnd(?)
- AND t.companyFk = ? AND c.hasToInvoice
- AND c.isTaxDataChecked AND c.isActive
- GROUP BY c.id, IF(c.hasToInvoiceByAddress,a.id,TRUE) HAVING sumAmount > 0`;
-
- return models.InvoiceOut.rawSql(query, [
- args.fromClientId,
- args.toClientId,
- args.toClientId,
- minShipped,
- args.maxShipped,
- args.companyFk
- ], options);
- }
-
async function notifyFailures(ctx, failedClients, options) {
const models = Self.app.models;
const userId = ctx.req.accessToken.userId;
diff --git a/modules/invoiceOut/back/models/invoice-out.js b/modules/invoiceOut/back/models/invoice-out.js
index 5af64de2b..7ac1246cf 100644
--- a/modules/invoiceOut/back/models/invoice-out.js
+++ b/modules/invoiceOut/back/models/invoice-out.js
@@ -7,6 +7,7 @@ module.exports = Self => {
require('../methods/invoiceOut/book')(Self);
require('../methods/invoiceOut/createPdf')(Self);
require('../methods/invoiceOut/createManualInvoice')(Self);
+ require('../methods/invoiceOut/clientToInvoice')(Self);
require('../methods/invoiceOut/globalInvoicing')(Self);
require('../methods/invoiceOut/refund')(Self);
require('../methods/invoiceOut/invoiceEmail')(Self);
diff --git a/modules/invoiceOut/front/index/global-invoicing/index.html b/modules/invoiceOut/front/index/global-invoicing/index.html
index 3d245b8d8..dbb780b7c 100644
--- a/modules/invoiceOut/front/index/global-invoicing/index.html
+++ b/modules/invoiceOut/front/index/global-invoicing/index.html
@@ -20,6 +20,8 @@
Adding invoices to queue...
+ {{$ctrl.lastClientId}}
+ {{::$ctrl.lastClientId || 'VacĂo'}}
diff --git a/modules/invoiceOut/front/index/global-invoicing/index.js b/modules/invoiceOut/front/index/global-invoicing/index.js
index 1b1ae5ec9..66c2e698a 100644
--- a/modules/invoiceOut/front/index/global-invoicing/index.js
+++ b/modules/invoiceOut/front/index/global-invoicing/index.js
@@ -58,8 +58,18 @@ class Controller extends Dialog {
throw new Error('Choose a valid clients range');
this.isInvoicing = true;
- return this.$http.post(`InvoiceOuts/globalInvoicing`, this.invoice)
- .then(() => super.responseHandler(response))
+ return this.$http.post(`InvoiceOuts/clientToInvoice`, this.invoice)
+ .then(res => {
+ this.lastClientId = res.data[res.data.length - 1];
+ console.log(this.lastClientId);
+ })
+ // .then(() => {
+ // for (let clientId of res.data) {
+ // const params = {clientId: clientId};
+ // this.$http.post(`InvoiceOuts/globalInvoicing`, params);
+ // }
+ // })
+ // .then(() => super.responseHandler(response))
.then(() => this.vnApp.showSuccess(this.$t('Data saved!')))
.finally(() => this.isInvoicing = false);
} catch (e) {