fixes #4547 check compensation and tests #1161
|
@ -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),
|
||||
(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),
|
||||
(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`)
|
||||
VALUES
|
||||
|
|
|
@ -324,7 +324,8 @@ export default {
|
|||
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)',
|
||||
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: {
|
||||
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 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}}})",
|
||||
"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}}})",
|
||||
"Already has this status": "Ya tiene este estado",
|
||||
"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 UserError = require('vn-loopback/util/user-error');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('balanceCompensationEmail', {
|
||||
|
@ -10,7 +11,7 @@ module.exports = Self => {
|
|||
type: 'Number',
|
||||
required: true,
|
||||
description: 'The receipt id',
|
||||
http: { source: 'path' }
|
||||
http: {source: 'path'}
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
|
@ -23,18 +24,29 @@ module.exports = Self => {
|
|||
}
|
||||
});
|
||||
|
||||
Self.balanceCompensationEmail = async (ctx, id) => {
|
||||
|
||||
Self.balanceCompensationEmail = async(ctx, id) => {
|
||||
const models = Self.app.models;
|
||||
const receipt = await models.Receipt.findById(id, {fields: ['clientFk']});
|
||||
const client = await models.Client.findById(receipt.clientFk, {fields:['email']});
|
||||
const receipt = await models.Receipt.findById(id, {fields: ['clientFk', 'bankFk']});
|
||||
|
||||
const email = new Email('balance-compensation', {
|
||||
lang: ctx.req.getLocale(),
|
||||
recipient: client.email+',administracion@verdnatura.es',
|
||||
id
|
||||
});
|
||||
const bank = await models.Bank.findById(receipt.bankFk);
|
||||
|
||||
if (!bank)
|
||||
throw new UserError(`Receipt's bank was not found`);
|
||||
joan
commented
Para evitar escapar las comillas se puede poner la cadena entre template strings Receipt's bank was not found Para evitar escapar las comillas se puede poner la cadena entre template strings
Receipt's bank was not found
|
||||
|
||||
return email.send();
|
||||
const accountingType = await models.AccountingType.findById(bank.accountingTypeFk);
|
||||
if (!(accountingType && accountingType.code == 'compensation'))
|
||||
throw new UserError(`This receipt was not compensated`);
|
||||
joan
commented
This receipt was not compensated? 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`);
|
||||
joan
commented
Faltan las traducciones en la carpeta loopback Faltan las traducciones en la carpeta loopback
|
||||
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(
|
||||
`SELECT * FROM (
|
||||
SELECT
|
||||
SELECT
|
||||
r.id,
|
||||
r.isConciliate,
|
||||
r.payed,
|
||||
|
@ -56,13 +56,16 @@ module.exports = Self => {
|
|||
u.name userName,
|
||||
r.clientFk,
|
||||
FALSE hasPdf,
|
||||
FALSE isInvoice
|
||||
FALSE isInvoice,
|
||||
CASE WHEN at2.code LIKE 'compensation' THEN True ELSE False END as isCompensation
|
||||
FROM vn.receipt r
|
||||
LEFT JOIN vn.worker w ON w.id = r.workerFk
|
||||
LEFT JOIN account.user u ON u.id = w.userFk
|
||||
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 = ?
|
||||
UNION ALL
|
||||
UNION ALL
|
||||
SELECT
|
||||
i.id,
|
||||
TRUE,
|
||||
|
@ -77,9 +80,12 @@ module.exports = Self => {
|
|||
NULL,
|
||||
i.clientFk,
|
||||
i.hasPdf,
|
||||
TRUE isInvoice
|
||||
TRUE isInvoice,
|
||||
CASE WHEN at2.code LIKE 'compensation' THEN True ELSE False END as isCompensation
|
||||
FROM vn.invoiceOut i
|
||||
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 = ?
|
||||
ORDER BY payed DESC, created DESC
|
||||
) t ORDER BY payed DESC, created DESC`,
|
||||
|
|
|
@ -121,7 +121,7 @@
|
|||
</vn-icon-button>
|
||||
</a>
|
||||
</vn-td>
|
||||
<vn-td center shrink ng-if="!balance.isInvoice">
|
||||
<vn-td center shrink ng-if="balance.isCompensation">
|
||||
<vn-icon-button
|
||||
vn-dialog="send_compensation"
|
||||
icon="outgoing_mail"
|
||||
|
@ -144,7 +144,7 @@
|
|||
vn-acl="salesAssistant"
|
||||
vn-acl-action="remove"
|
||||
icon="add"
|
||||
vn-tooltip="New payment"
|
||||
vn-tooltip="New payment"
|
||||
vn-bind="+"
|
||||
fixed-bottom-right
|
||||
ng-click="balanceCreate.show()">
|
||||
|
@ -155,9 +155,9 @@
|
|||
company-fk="$ctrl.companyId"
|
||||
client-fk="$ctrl.$params.id">
|
||||
</vn-client-balance-create>
|
||||
<vn-worker-descriptor-popover
|
||||
<vn-worker-descriptor-popover
|
||||
vn-id="workerDescriptor">
|
||||
</vn-worker-descriptor-popover>
|
||||
<vn-invoice-out-descriptor-popover
|
||||
<vn-invoice-out-descriptor-popover
|
||||
vn-id="invoiceOutDescriptor">
|
||||
</vn-invoice-out-descriptor-popover>
|
||||
</vn-invoice-out-descriptor-popover>
|
||||
|
|
|
@ -55,41 +55,41 @@ class Controller extends Section {
|
|||
}
|
||||
})).then(() => this.getBalances());
|
||||
}
|
||||
|
||||
|
||||
getCurrentBalance() {
|
||||
const clientRisks = this.$.riskModel.data;
|
||||
const selectedCompany = this.companyId;
|
||||
const currentBalance = clientRisks.find(balance => {
|
||||
return balance.companyFk === selectedCompany;
|
||||
});
|
||||
|
||||
|
||||
return currentBalance && currentBalance.amount;
|
||||
}
|
||||
|
||||
|
||||
getBalances() {
|
||||
const balances = this.$.model.data;
|
||||
balances.forEach((balance, index) => {
|
||||
if (index === 0)
|
||||
balance.balance = this.getCurrentBalance();
|
||||
balance.balance = this.getCurrentBalance();
|
||||
if (index > 0) {
|
||||
let previousBalance = balances[index - 1];
|
||||
balance.balance = previousBalance.balance - (previousBalance.debit - previousBalance.credit);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
showInvoiceOutDescriptor(event, balance) {
|
||||
if (!balance.isInvoice) return;
|
||||
if (event.defaultPrevented) return;
|
||||
|
||||
|
||||
this.$.invoiceOutDescriptor.show(event.target, balance.id);
|
||||
}
|
||||
|
||||
|
||||
changeDescription(balance) {
|
||||
const params = {description: balance.description};
|
||||
const endpoint = `Receipts/${balance.id}`;
|
||||
this.$http.patch(endpoint, params)
|
||||
.then(() => this.vnApp.showSuccess(this.$t('Data saved!')));
|
||||
.then(() => this.vnApp.showSuccess(this.$t('Data saved!')));
|
||||
}
|
||||
|
||||
sendEmail(balance) {
|
||||
|
|
|
@ -151,5 +151,19 @@ describe('Client', () => {
|
|||
$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
No es necesario el null si no se le pasa el tercer argumento.