#6942 toUnbook #2135

Merged
jorgep merged 46 commits from 6942-improveInvoiceIn into dev 2024-05-29 07:03:35 +00:00
9 changed files with 277 additions and 3 deletions

View File

@ -0,0 +1,24 @@
REVOKE UPDATE ON vn. invoiceIn FROM administrative, hrBoss, buyer, logistic;
GRANT UPDATE (id,
serialNumber,
serial,
supplierFk,
issued,
supplierRef,
currencyFk,
created,
companyFk,
docFk,
booked,
operated,
siiTypeInvoiceInFk,
cplusRectificationTypeFk,
cplusSubjectOpFk,
cplusTaxBreakFk,
siiTrascendencyInvoiceInFk,
bookEntried,
isVatDeductible,
withholdingSageFk,
expenseFkDeductible,
editorFk
) ON vn.invoiceIn TO administrative, hrBoss, buyer, logistic;
jorgep marked this conversation as resolved Outdated

grafana SOLO debe tener permisos de select en cualquier tabla

grafana SOLO debe tener permisos de select en cualquier tabla

No hacía falta hacer el revoke, sobre grafana. Gestionado.

No hacía falta hacer el revoke, sobre grafana. Gestionado.

View File

@ -0,0 +1,23 @@
UPDATE salix.ACL
SET accessType = 'READ'
WHERE principalId IN ('administrative','buyer')
AND model = 'invoiceIn'
AND property = '*';
INSERT INTO salix.ACL (model, property, accessType, permission, principalType, principalId)
VALUES
('InvoiceIn', 'updateInvoiceIn', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
('InvoiceIn', 'clone', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
('InvoiceIn', 'corrective', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
('InvoiceIn', 'exchangeRateUpdate', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
('InvoiceIn', 'invoiceInEmail', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
('InvoiceIn', 'toBook', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
('InvoiceIn', 'toUnbook', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
('InvoiceIn', 'deleteById', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
('InvoiceIn', 'updateInvoiceIn', 'WRITE', 'ALLOW', 'ROLE', 'buyer'),
('InvoiceIn', 'clone', 'WRITE', 'ALLOW', 'ROLE', 'buyer'),
('InvoiceIn', 'corrective', 'WRITE', 'ALLOW', 'ROLE', 'buyer'),
('InvoiceIn', 'exchangeRateUpdate', 'WRITE', 'ALLOW', 'ROLE', 'buyer'),
('InvoiceIn', 'invoiceInEmail', 'WRITE', 'ALLOW', 'ROLE', 'buyer'),
('InvoiceIn', 'toBook', 'WRITE', 'ALLOW', 'ROLE', 'buyer'),
('InvoiceIn', 'deleteById', 'WRITE', 'ALLOW', 'ROLE', 'buyer');

View File

@ -76,7 +76,16 @@
}, },
"enlazadoSage": { "enlazadoSage": {
"type": "boolean" "type": "boolean"
} },
"enlazado": {
"type": "boolean"
},
"key": {
"type": "number",
"mysql": {
jorgep marked this conversation as resolved Outdated

El campo CLAVE está en mayúsculas en la base de datos

El campo CLAVE está en mayúsculas en la base de datos
Outdated
Review

Li pots fer un rename per a que nosaltres ho gastem normal.
En ticket.json hi ha un exemple:

 "updated": {
            "type": "date",
            "mysql": {
                "columnName": "created"
            }
        },
Li pots fer un rename per a que nosaltres ho gastem normal. En ticket.json hi ha un exemple: ``` "updated": { "type": "date", "mysql": { "columnName": "created" } }, ```
"columnName": "CLAVE"
}
}
}, },
"relations": { "relations": {
"company": { "company": {

View File

@ -0,0 +1,32 @@
const models = require('vn-loopback/server/server').models;
describe('invoiceIn toUnbook()', () => {
it('should check that invoiceIn is unbooked', async() => {
const userId = 1;
const ctx = {
req: {
accessToken: {userId: userId},
headers: {origin: 'http://localhost:5000'},
}
};
const invoiceInId = 1;
const tx = await models.InvoiceIn.beginTransaction({});
const options = {transaction: tx};
try {
await models.InvoiceIn.toBook(ctx, invoiceInId, options);
const bookEntry = await models.InvoiceIn.toUnbook(ctx, invoiceInId, options);
const invoiceIn = await models.InvoiceIn.findById(invoiceInId, null, options);
expect(bookEntry.accountingEntries).toEqual(4);
expect(bookEntry.isLinked).toBeFalsy();
expect(invoiceIn.isBooked).toEqual(false);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -0,0 +1,80 @@
module.exports = Self => {
Self.remoteMethodCtx('toUnbook', {
description: 'To unbook the invoiceIn',
accessType: 'WRITE',
accepts: {
arg: 'id',
type: 'number',
required: true,
description: 'The invoiceIn id',
http: {source: 'path'}
},
returns: {
type: 'object',
root: true
},
http: {
path: '/:id/toUnbook',
verb: 'POST'
}
});
Self.toUnbook = async(ctx, invoiceInId, options) => {
let tx;
const models = Self.app.models;
const myOptions = {userId: ctx.req.accessToken.userId};
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
let isLinked;
let accountingEntries;
let bookEntry = await models.Xdiario.findOne({
fields: ['ASIEN'],
where: {
and: [
{key: invoiceInId},
{enlazado: false},
{enlazadoSage: false}
]
}
}, myOptions);
jorgep marked this conversation as resolved
Review

El numero de ocurrencias de bookEntry.ASIEN es medio-alto.
Propongo crear una variable representativa de este valor y reemplazar donde toque.
Otro enfoque puede ser que en el if, reemplazar bookEntry.ASIEN porque ya es true

El numero de ocurrencias de bookEntry.ASIEN es medio-alto. Propongo crear una variable representativa de este valor y reemplazar donde toque. Otro enfoque puede ser que en el if, reemplazar bookEntry.ASIEN porque ya es true
Review

Me parece bien.

Me parece bien.
let asien = bookEntry?.ASIEN;
jgallego marked this conversation as resolved Outdated
Outdated
Review

@jgallego veus be la logica?

@jgallego veus be la logica?

esta ok

esta ok
if (asien) {
accountingEntries = await models.Xdiario.count({ASIEN: asien}, myOptions);
await models.Xdiario.destroyAll({ASIEN: asien}, myOptions);
await Self.updateAll({id: invoiceInId}, {isBooked: false}, myOptions);
} else {
const linkedBookEntry = await models.Xdiario.findOne({
fields: ['ASIEN'],
where: {
key: invoiceInId,
and: [{or: [{enlazado: true, enlazadoSage: true}]}]
}
}, myOptions);
asien = linkedBookEntry?.ASIEN;
isLinked = true;
}
if (tx) await tx.commit();
return {
isLinked,
bookEntry: asien,
accountingEntries
};
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};

View File

@ -0,0 +1,104 @@
module.exports = Self => {
Review

Se llama desde basic-data para actualizar los campos de la factura. Tras hablar con @alex se ha decidido usar any. Ya que hay parametros que pueden ser number| null o string| null ... y en loopback no hay manera de ponerle 2 tipos a un argumento.

Se llama desde basic-data para actualizar los campos de la factura. Tras hablar con @alex se ha decidido usar any. Ya que hay parametros que pueden ser number| null o string| null ... y en loopback no hay manera de ponerle 2 tipos a un argumento.
Self.remoteMethodCtx('updateInvoiceIn', {
jorgep marked this conversation as resolved
Review

porque no usas el nativo?

porque no usas el nativo?
Review

Porque con el nativo no se puede evitar la modificación de 1 solo campo de una tabla. En este caso, queremos evitar la modificación de isBooked desde salix. Lo hablé con Juan y me dijo que creará un back.

Porque con el nativo no se puede evitar la modificación de 1 solo campo de una tabla. En este caso, queremos evitar la modificación de isBooked desde salix. Lo hablé con Juan y me dijo que creará un back.
description: 'To update the invoiceIn attributes',
accessType: 'WRITE',
accepts: [{
arg: 'id',
type: 'number',
required: true,
description: 'The invoiceIn id',
http: {source: 'path'}
}, {
arg: 'supplierFk',
type: 'number',
required: true
}, {
arg: 'supplierRef',
type: 'any',
}, {
arg: 'issued',
type: 'any',
}, {
arg: 'operated',
type: 'any',
}, {
arg: 'deductibleExpenseFk',
type: 'any',
}, {
arg: 'dmsFk',
type: 'any',
}, {
arg: 'bookEntried',
type: 'any',
}, {
arg: 'booked',
type: 'any',
}, {
arg: 'currencyFk',
type: 'number',
required: true
}, {
arg: 'companyFk',
type: 'any',
}, {
arg: 'withholdingSageFk',
type: 'any',
},
],
returns: {
type: 'object',
root: true
},
http: {
path: '/:id/updateInvoiceIn',
verb: 'PATCH'
}
});
Self.updateInvoiceIn = async(ctx,
id,
supplierFk,
supplierRef,
issued,
operated,
deductibleExpenseFk,
dmsFk,
bookEntried,
booked,
currencyFk,
companyFk,
withholdingSageFk,
options
) => {
let tx;
const myOptions = {userId: ctx.req.accessToken.userId};
if (typeof options == 'object') Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const invoiceIn = await Self.findById(id, null, myOptions);
invoiceIn.updateAttributes({supplierFk,
supplierRef,
issued,
operated,
deductibleExpenseFk,
dmsFk,
bookEntried,
booked,
currencyFk,
companyFk,
withholdingSageFk
}, myOptions);
if (tx) await tx.commit();
return invoiceIn;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};

View File

@ -11,6 +11,8 @@ module.exports = Self => {
require('../methods/invoice-in/getSerial')(Self); require('../methods/invoice-in/getSerial')(Self);
require('../methods/invoice-in/corrective')(Self); require('../methods/invoice-in/corrective')(Self);
require('../methods/invoice-in/exchangeRateUpdate')(Self); require('../methods/invoice-in/exchangeRateUpdate')(Self);
require('../methods/invoice-in/toUnbook')(Self);
require('../methods/invoice-in/updateInvoiceIn')(Self);
Self.rewriteDbError(function(err) { Self.rewriteDbError(function(err) {
if (err.code === 'ER_ROW_IS_REFERENCED_2' && err.sqlMessage.includes('vehicleInvoiceIn')) if (err.code === 'ER_ROW_IS_REFERENCED_2' && err.sqlMessage.includes('vehicleInvoiceIn'))

View File

@ -1,4 +1,4 @@
<mg-ajax path="InvoiceIns/{{patch.params.id}}" options="vnPatch"></mg-ajax> <mg-ajax path="InvoiceIns/{{patch.params.id}}/updateInvoiceIn" options="vnPatch"></mg-ajax>
<vn-watcher <vn-watcher
vn-id="watcher" vn-id="watcher"
data="$ctrl.invoiceIn" data="$ctrl.invoiceIn"

View File

@ -9,7 +9,7 @@
"properties": { "properties": {
"id": { "id": {
"id": true, "id": true,
"type": "number", "type": "string",
Review

En la base de datos está como varchar

En la base de datos está como varchar
"description": "Identifier" "description": "Identifier"
}, },
"name": { "name": {