Merge pull request 'fixes #4547 check compensation and tests' (!1161) from 4547-fix-compensation into dev
gitea/salix/pipeline/head There was a failure building this commit
Details
gitea/salix/pipeline/head There was a failure building this commit
Details
Reviewed-on: #1161 Reviewed-by: Joan Sanchez <joan@verdnatura.es>
This commit is contained in:
commit
a2e08c5907
|
@ -0,0 +1,4 @@
|
||||||
|
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||||
|
VALUES
|
||||||
|
('Receipt', 'balanceCompensationEmail', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Receipt', 'balanceCompensationPdf', 'READ', 'ALLOW', 'ROLE', 'employee');
|
|
@ -1859,7 +1859,8 @@ INSERT INTO `vn`.`receipt`(`id`, `invoiceFk`, `amountPaid`, `payed`, `workerFk`,
|
||||||
(1, 'Cobro web', 100.50, util.VN_CURDATE(), 9, 1, 1101, util.VN_CURDATE(), 442, 1),
|
(1, 'Cobro web', 100.50, util.VN_CURDATE(), 9, 1, 1101, util.VN_CURDATE(), 442, 1),
|
||||||
(2, 'Cobro web', 200.50, DATE_ADD(util.VN_CURDATE(), INTERVAL -5 DAY), 9, 1, 1101, DATE_ADD(util.VN_CURDATE(), INTERVAL -5 DAY), 442, 1),
|
(2, 'Cobro web', 200.50, DATE_ADD(util.VN_CURDATE(), INTERVAL -5 DAY), 9, 1, 1101, DATE_ADD(util.VN_CURDATE(), INTERVAL -5 DAY), 442, 1),
|
||||||
(3, 'Cobro en efectivo', 300.00, DATE_ADD(util.VN_CURDATE(), INTERVAL -10 DAY), 9, 1, 1102, DATE_ADD(util.VN_CURDATE(), INTERVAL -10 DAY), 442, 0),
|
(3, 'Cobro en efectivo', 300.00, DATE_ADD(util.VN_CURDATE(), INTERVAL -10 DAY), 9, 1, 1102, DATE_ADD(util.VN_CURDATE(), INTERVAL -10 DAY), 442, 0),
|
||||||
(4, 'Cobro en efectivo', 400.00, DATE_ADD(util.VN_CURDATE(), INTERVAL -15 DAY), 9, 1, 1103, DATE_ADD(util.VN_CURDATE(), INTERVAL -15 DAY), 442, 0);
|
(4, 'Cobro en efectivo', 400.00, DATE_ADD(util.VN_CURDATE(), INTERVAL -15 DAY), 9, 1, 1103, DATE_ADD(util.VN_CURDATE(), INTERVAL -15 DAY), 442, 0),
|
||||||
|
(5, 'Compensación', 400.00, DATE_ADD(util.VN_CURDATE(), INTERVAL -15 DAY), 9, 3, 1103, DATE_ADD(util.VN_CURDATE(), INTERVAL -15 DAY), 442, 0);
|
||||||
|
|
||||||
INSERT INTO `vn`.`workerTeam`(`id`, `team`, `workerFk`)
|
INSERT INTO `vn`.`workerTeam`(`id`, `team`, `workerFk`)
|
||||||
VALUES
|
VALUES
|
||||||
|
|
|
@ -324,7 +324,8 @@ export default {
|
||||||
anyBalanceLine: 'vn-client-balance-index vn-tbody > vn-tr',
|
anyBalanceLine: 'vn-client-balance-index vn-tbody > vn-tr',
|
||||||
firstLineBalance: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(8)',
|
firstLineBalance: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(8)',
|
||||||
firstLineReference: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable',
|
firstLineReference: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable',
|
||||||
firstLineReferenceInput: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable > div > field > vn-textfield'
|
firstLineReferenceInput: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable > div > field > vn-textfield',
|
||||||
|
compensationButton: 'vn-client-balance-index vn-icon-button[vn-dialog="send_compensation"]'
|
||||||
},
|
},
|
||||||
webPayment: {
|
webPayment: {
|
||||||
confirmFirstPaymentButton: 'vn-client-web-payment vn-tr:nth-child(1) vn-icon-button[icon="done_all"]',
|
confirmFirstPaymentButton: 'vn-client-web-payment vn-tr:nth-child(1) vn-icon-button[icon="done_all"]',
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
import selectors from '../../helpers/selectors';
|
||||||
|
import getBrowser from '../../helpers/puppeteer';
|
||||||
|
|
||||||
|
describe('Client Send balance compensation', () => {
|
||||||
|
let browser;
|
||||||
|
let page;
|
||||||
|
beforeAll(async() => {
|
||||||
|
browser = await getBrowser();
|
||||||
|
page = browser.page;
|
||||||
|
await page.loginAndModule('employee', 'client');
|
||||||
|
await page.accessToSearchResult('Clark Kent');
|
||||||
|
await page.accessToSection('client.card.balance.index');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async() => {
|
||||||
|
await browser.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should click on send compensation button`, async() => {
|
||||||
|
await page.autocompleteSearch(selectors.clientBalance.company, 'VNL');
|
||||||
|
await page.waitToClick(selectors.clientBalance.compensationButton);
|
||||||
|
await page.waitToClick(selectors.clientBalance.saveButton);
|
||||||
|
const message = await page.waitForSnackbar();
|
||||||
|
|
||||||
|
expect(message.text).toContain('Notification sent!');
|
||||||
|
});
|
||||||
|
});
|
|
@ -138,5 +138,8 @@
|
||||||
"You don't have grant privilege": "You don't have grant privilege",
|
"You don't have grant privilege": "You don't have grant privilege",
|
||||||
"You don't own the role and you can't assign it to another user": "You don't own the role and you can't assign it to another user",
|
"You don't own the role and you can't assign it to another user": "You don't own the role and you can't assign it to another user",
|
||||||
"Ticket merged": "Ticket [{{id}}]({{{fullPath}}}) ({{{originDated}}}) merged with [{{tfId}}]({{{fullPathFuture}}}) ({{{futureDated}}})",
|
"Ticket merged": "Ticket [{{id}}]({{{fullPath}}}) ({{{originDated}}}) merged with [{{tfId}}]({{{fullPathFuture}}}) ({{{futureDated}}})",
|
||||||
"Sale(s) blocked, please contact production": "Sale(s) blocked, please contact production"
|
"Sale(s) blocked, please contact production": "Sale(s) blocked, please contact production",
|
||||||
|
"Receipt's bank was not found": "Receipt's bank was not found",
|
||||||
|
"This receipt was not compensated": "This receipt was not compensated",
|
||||||
|
"Client's email was not found": "Client's email was not found"
|
||||||
}
|
}
|
||||||
|
|
|
@ -244,5 +244,8 @@
|
||||||
"Ticket merged": "Ticket [{{id}}]({{{fullPath}}}) ({{{originDated}}}) fusionado con [{{tfId}}]({{{fullPathFuture}}}) ({{{futureDated}}})",
|
"Ticket merged": "Ticket [{{id}}]({{{fullPath}}}) ({{{originDated}}}) fusionado con [{{tfId}}]({{{fullPathFuture}}}) ({{{futureDated}}})",
|
||||||
"Already has this status": "Ya tiene este estado",
|
"Already has this status": "Ya tiene este estado",
|
||||||
"There aren't records for this week": "No existen registros para esta semana",
|
"There aren't records for this week": "No existen registros para esta semana",
|
||||||
"Empty data source": "Origen de datos vacio"
|
"Empty data source": "Origen de datos vacio",
|
||||||
|
"Receipt's bank was not found": "No se encontró el banco del recibo",
|
||||||
|
"This receipt was not compensated": "Este recibo no ha sido compensado",
|
||||||
|
"Client's email was not found": "No se encontró el email del cliente"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
const {Email} = require('vn-print');
|
const {Email} = require('vn-print');
|
||||||
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('balanceCompensationEmail', {
|
Self.remoteMethodCtx('balanceCompensationEmail', {
|
||||||
|
@ -10,7 +11,7 @@ module.exports = Self => {
|
||||||
type: 'Number',
|
type: 'Number',
|
||||||
required: true,
|
required: true,
|
||||||
description: 'The receipt id',
|
description: 'The receipt id',
|
||||||
http: { source: 'path' }
|
http: {source: 'path'}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
returns: {
|
returns: {
|
||||||
|
@ -23,18 +24,29 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.balanceCompensationEmail = async (ctx, id) => {
|
Self.balanceCompensationEmail = async(ctx, id) => {
|
||||||
|
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const receipt = await models.Receipt.findById(id, {fields: ['clientFk']});
|
const receipt = await models.Receipt.findById(id, {fields: ['clientFk', 'bankFk']});
|
||||||
const client = await models.Client.findById(receipt.clientFk, {fields:['email']});
|
|
||||||
|
|
||||||
const email = new Email('balance-compensation', {
|
const bank = await models.Bank.findById(receipt.bankFk);
|
||||||
lang: ctx.req.getLocale(),
|
if (!bank)
|
||||||
recipient: client.email+',administracion@verdnatura.es',
|
throw new UserError(`Receipt's bank was not found`);
|
||||||
id
|
|
||||||
});
|
|
||||||
|
|
||||||
return email.send();
|
const accountingType = await models.AccountingType.findById(bank.accountingTypeFk);
|
||||||
|
if (!(accountingType && accountingType.code == 'compensation'))
|
||||||
|
throw new UserError(`This receipt was not compensated`);
|
||||||
|
|
||||||
|
const client = await models.Client.findById(receipt.clientFk, {fields: ['email']});
|
||||||
|
|
||||||
|
if (!client.email)
|
||||||
|
throw new UserError(`Client's email was not found`);
|
||||||
|
else {
|
||||||
|
const email = new Email('balance-compensation', {
|
||||||
|
lang: ctx.req.getLocale(),
|
||||||
|
recipient: client.email + ',administracion@verdnatura.es',
|
||||||
|
id
|
||||||
|
});
|
||||||
|
return email.send();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -42,7 +42,7 @@ module.exports = Self => {
|
||||||
|
|
||||||
const stmt = new ParameterizedSQL(
|
const stmt = new ParameterizedSQL(
|
||||||
`SELECT * FROM (
|
`SELECT * FROM (
|
||||||
SELECT
|
SELECT
|
||||||
r.id,
|
r.id,
|
||||||
r.isConciliate,
|
r.isConciliate,
|
||||||
r.payed,
|
r.payed,
|
||||||
|
@ -56,13 +56,16 @@ module.exports = Self => {
|
||||||
u.name userName,
|
u.name userName,
|
||||||
r.clientFk,
|
r.clientFk,
|
||||||
FALSE hasPdf,
|
FALSE hasPdf,
|
||||||
FALSE isInvoice
|
FALSE isInvoice,
|
||||||
|
CASE WHEN at2.code LIKE 'compensation' THEN True ELSE False END as isCompensation
|
||||||
FROM vn.receipt r
|
FROM vn.receipt r
|
||||||
LEFT JOIN vn.worker w ON w.id = r.workerFk
|
LEFT JOIN vn.worker w ON w.id = r.workerFk
|
||||||
LEFT JOIN account.user u ON u.id = w.userFk
|
LEFT JOIN account.user u ON u.id = w.userFk
|
||||||
JOIN vn.company c ON c.id = r.companyFk
|
JOIN vn.company c ON c.id = r.companyFk
|
||||||
|
JOIN vn.accounting a ON a.id = r.bankFk
|
||||||
|
JOIN vn.accountingType at2 ON at2.id = a.accountingTypeFk
|
||||||
WHERE r.clientFk = ? AND r.companyFk = ?
|
WHERE r.clientFk = ? AND r.companyFk = ?
|
||||||
UNION ALL
|
UNION ALL
|
||||||
SELECT
|
SELECT
|
||||||
i.id,
|
i.id,
|
||||||
TRUE,
|
TRUE,
|
||||||
|
@ -77,9 +80,12 @@ module.exports = Self => {
|
||||||
NULL,
|
NULL,
|
||||||
i.clientFk,
|
i.clientFk,
|
||||||
i.hasPdf,
|
i.hasPdf,
|
||||||
TRUE isInvoice
|
TRUE isInvoice,
|
||||||
|
CASE WHEN at2.code LIKE 'compensation' THEN True ELSE False END as isCompensation
|
||||||
FROM vn.invoiceOut i
|
FROM vn.invoiceOut i
|
||||||
JOIN vn.company c ON c.id = i.companyFk
|
JOIN vn.company c ON c.id = i.companyFk
|
||||||
|
JOIN vn.accounting a ON a.id = i.bankFk
|
||||||
|
JOIN vn.accountingType at2 ON at2.id = a.accountingTypeFk
|
||||||
WHERE i.clientFk = ? AND i.companyFk = ?
|
WHERE i.clientFk = ? AND i.companyFk = ?
|
||||||
ORDER BY payed DESC, created DESC
|
ORDER BY payed DESC, created DESC
|
||||||
) t ORDER BY payed DESC, created DESC`,
|
) t ORDER BY payed DESC, created DESC`,
|
||||||
|
|
|
@ -121,7 +121,7 @@
|
||||||
</vn-icon-button>
|
</vn-icon-button>
|
||||||
</a>
|
</a>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td center shrink ng-if="!balance.isInvoice">
|
<vn-td center shrink ng-if="balance.isCompensation">
|
||||||
<vn-icon-button
|
<vn-icon-button
|
||||||
vn-dialog="send_compensation"
|
vn-dialog="send_compensation"
|
||||||
icon="outgoing_mail"
|
icon="outgoing_mail"
|
||||||
|
@ -144,7 +144,7 @@
|
||||||
vn-acl="salesAssistant"
|
vn-acl="salesAssistant"
|
||||||
vn-acl-action="remove"
|
vn-acl-action="remove"
|
||||||
icon="add"
|
icon="add"
|
||||||
vn-tooltip="New payment"
|
vn-tooltip="New payment"
|
||||||
vn-bind="+"
|
vn-bind="+"
|
||||||
fixed-bottom-right
|
fixed-bottom-right
|
||||||
ng-click="balanceCreate.show()">
|
ng-click="balanceCreate.show()">
|
||||||
|
@ -155,9 +155,9 @@
|
||||||
company-fk="$ctrl.companyId"
|
company-fk="$ctrl.companyId"
|
||||||
client-fk="$ctrl.$params.id">
|
client-fk="$ctrl.$params.id">
|
||||||
</vn-client-balance-create>
|
</vn-client-balance-create>
|
||||||
<vn-worker-descriptor-popover
|
<vn-worker-descriptor-popover
|
||||||
vn-id="workerDescriptor">
|
vn-id="workerDescriptor">
|
||||||
</vn-worker-descriptor-popover>
|
</vn-worker-descriptor-popover>
|
||||||
<vn-invoice-out-descriptor-popover
|
<vn-invoice-out-descriptor-popover
|
||||||
vn-id="invoiceOutDescriptor">
|
vn-id="invoiceOutDescriptor">
|
||||||
</vn-invoice-out-descriptor-popover>
|
</vn-invoice-out-descriptor-popover>
|
||||||
|
|
|
@ -55,41 +55,41 @@ class Controller extends Section {
|
||||||
}
|
}
|
||||||
})).then(() => this.getBalances());
|
})).then(() => this.getBalances());
|
||||||
}
|
}
|
||||||
|
|
||||||
getCurrentBalance() {
|
getCurrentBalance() {
|
||||||
const clientRisks = this.$.riskModel.data;
|
const clientRisks = this.$.riskModel.data;
|
||||||
const selectedCompany = this.companyId;
|
const selectedCompany = this.companyId;
|
||||||
const currentBalance = clientRisks.find(balance => {
|
const currentBalance = clientRisks.find(balance => {
|
||||||
return balance.companyFk === selectedCompany;
|
return balance.companyFk === selectedCompany;
|
||||||
});
|
});
|
||||||
|
|
||||||
return currentBalance && currentBalance.amount;
|
return currentBalance && currentBalance.amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
getBalances() {
|
getBalances() {
|
||||||
const balances = this.$.model.data;
|
const balances = this.$.model.data;
|
||||||
balances.forEach((balance, index) => {
|
balances.forEach((balance, index) => {
|
||||||
if (index === 0)
|
if (index === 0)
|
||||||
balance.balance = this.getCurrentBalance();
|
balance.balance = this.getCurrentBalance();
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
let previousBalance = balances[index - 1];
|
let previousBalance = balances[index - 1];
|
||||||
balance.balance = previousBalance.balance - (previousBalance.debit - previousBalance.credit);
|
balance.balance = previousBalance.balance - (previousBalance.debit - previousBalance.credit);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
showInvoiceOutDescriptor(event, balance) {
|
showInvoiceOutDescriptor(event, balance) {
|
||||||
if (!balance.isInvoice) return;
|
if (!balance.isInvoice) return;
|
||||||
if (event.defaultPrevented) return;
|
if (event.defaultPrevented) return;
|
||||||
|
|
||||||
this.$.invoiceOutDescriptor.show(event.target, balance.id);
|
this.$.invoiceOutDescriptor.show(event.target, balance.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
changeDescription(balance) {
|
changeDescription(balance) {
|
||||||
const params = {description: balance.description};
|
const params = {description: balance.description};
|
||||||
const endpoint = `Receipts/${balance.id}`;
|
const endpoint = `Receipts/${balance.id}`;
|
||||||
this.$http.patch(endpoint, params)
|
this.$http.patch(endpoint, params)
|
||||||
.then(() => this.vnApp.showSuccess(this.$t('Data saved!')));
|
.then(() => this.vnApp.showSuccess(this.$t('Data saved!')));
|
||||||
}
|
}
|
||||||
|
|
||||||
sendEmail(balance) {
|
sendEmail(balance) {
|
||||||
|
|
|
@ -151,5 +151,19 @@ describe('Client', () => {
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('sendEmail()', () => {
|
||||||
|
it('should send an email', () => {
|
||||||
|
jest.spyOn(controller.vnEmail, 'send');
|
||||||
|
|
||||||
|
const $data = {id: 1103};
|
||||||
|
|
||||||
|
controller.sendEmail($data);
|
||||||
|
|
||||||
|
const expectedPath = `Receipts/${$data.id}/balance-compensation-email`;
|
||||||
|
|
||||||
|
expect(controller.vnEmail.send).toHaveBeenCalledWith(expectedPath);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1 +1,3 @@
|
||||||
BILL: N/INV {{ref}}
|
BILL: N/INV {{ref}}
|
||||||
|
Notify compensation: Do you want to report compensation to the client by mail?
|
||||||
|
Send compensation: Send compensation
|
||||||
|
|
Loading…
Reference in New Issue