5914-transferInvoiceOut #1761
|
@ -6,10 +6,35 @@ module.exports = Self => {
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: [
|
accepts: [
|
||||||
{
|
{
|
||||||
arg: 'data',
|
arg: 'id',
|
||||||
type: 'Object',
|
type: 'number',
|
||||||
required: true
|
required: true
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
arg: 'ref',
|
||||||
|
type: 'string',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'newClientFk',
|
||||||
|
type: 'number',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'cplusRectificationId',
|
||||||
|
type: 'number',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'cplusInvoiceType477Id',
|
||||||
|
type: 'number',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'invoiceCorrectionTypeId',
|
||||||
|
type: 'number',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
],
|
],
|
||||||
returns: {
|
returns: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
|
@ -21,7 +46,7 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.transferInvoiceOut = async(ctx, params, options) => {
|
Self.transferInvoiceOut = async(ctx, id, ref, newClientFk, cplusRectificationId, cplusInvoiceType477Id, invoiceCorrectionTypeId, options) => {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const myOptions = {};
|
const myOptions = {};
|
||||||
let tx;
|
let tx;
|
||||||
|
@ -34,16 +59,12 @@ module.exports = Self => {
|
||||||
myOptions.transaction = tx;
|
myOptions.transaction = tx;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const {id, ref, newClientFk, cplusRectificationId, cplusInvoiceType477FkId, invoiceCorrectionTypeId} = params;
|
|
||||||
if (!id || !ref || !newClientFk || !cplusRectificationId || !cplusInvoiceType477FkId || !invoiceCorrectionTypeId)
|
|
||||||
throw new UserError(`There are missing fields.`);
|
|
||||||
|
|
||||||
// Refund tickets and group
|
// Refund tickets and group
|
||||||
const filter = {where: {refFk: ref}};
|
const filter = {where: {refFk: ref}};
|
||||||
const tickets = await models.Ticket.find(filter, myOptions);
|
const tickets = await models.Ticket.find(filter, myOptions);
|
||||||
const ticketsIds = tickets.map(ticket => ticket.id);
|
const ticketsIds = tickets.map(ticket => ticket.id);
|
||||||
await models.Ticket.refund(ctx, ticketsIds, null, myOptions);
|
await models.Ticket.refund(ctx, ticketsIds, null, myOptions);
|
||||||
|
console.log('Ticket refunded');
|
||||||
// Clone tickets
|
// Clone tickets
|
||||||
const refundAgencyMode = await models.AgencyMode.findOne({
|
const refundAgencyMode = await models.AgencyMode.findOne({
|
||||||
include: {
|
include: {
|
||||||
|
@ -58,25 +79,20 @@ module.exports = Self => {
|
||||||
const refoundZoneId = refundAgencyMode.zones()[0].id;
|
const refoundZoneId = refundAgencyMode.zones()[0].id;
|
||||||
const services = await models.TicketService.find(filter, myOptions);
|
const services = await models.TicketService.find(filter, myOptions);
|
||||||
const servicesIds = services.map(service => service.id);
|
const servicesIds = services.map(service => service.id);
|
||||||
const salesFilter = {
|
const salesFilter = {where: {ticketFk: {inq: ticketsIds}}};
|
||||||
where: {id: {inq: salesIds}},
|
|
||||||
include: {
|
|
||||||
relation: 'components',
|
|
||||||
scope: {
|
|
||||||
fields: ['saleFk', 'componentFk', 'value']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const sales = await models.Sale.find(salesFilter, myOptions);
|
const sales = await models.Sale.find(salesFilter, myOptions);
|
||||||
const isRefund = false;
|
const clonedTickets = await models.Sale.clone(sales, refundAgencyMode, refoundZoneId, servicesIds, null, false, false, myOptions);
|
||||||
const clonedTicketIds = await models.Sale.clone(sales, refundAgencyMode, refoundZoneId, servicesIds, null, isRefund, myOptions);
|
console.log('cloned tickets');
|
||||||
|
|
||||||
// Update client
|
// Update client
|
||||||
for (const clonedTicketId of clonedTicketIds) {
|
for (const clonedTicket of clonedTickets) {
|
||||||
const ticket = await models.Ticket.findById(clonedTicketId, myOptions);
|
// const ticket = await models.Ticket.findById(clonedTicketId, myOptions);
|
||||||
await ticket.updateAttributes({clientFk: newClientFk});
|
console.log(clonedTicket);
|
||||||
|
await clonedTicket.updateAttributes({clientFk: newClientFk}, myOptions);
|
||||||
|
console.log(clonedTicket);
|
||||||
}
|
}
|
||||||
// Quick invoice
|
// Quick invoice
|
||||||
|
const clonedTicketIds = clonedTickets.map(clonedTicket => clonedTicket.id);
|
||||||
|
console.log(clonedTicketIds);
|
||||||
const invoiceIds = await models.Ticket.invoiceTickets(ctx, clonedTicketIds, myOptions);
|
const invoiceIds = await models.Ticket.invoiceTickets(ctx, clonedTicketIds, myOptions);
|
||||||
|
|
||||||
// Insert InvoiceCorrection
|
// Insert InvoiceCorrection
|
||||||
|
@ -85,7 +101,7 @@ module.exports = Self => {
|
||||||
correctingFk: invoiceId,
|
correctingFk: invoiceId,
|
||||||
correctedFk: id,
|
correctedFk: id,
|
||||||
cplusRectificationTypeFk: cplusRectificationId,
|
cplusRectificationTypeFk: cplusRectificationId,
|
||||||
cplusInvoiceType477Fk: cplusInvoiceType477FkId,
|
cplusInvoiceType477Fk: cplusInvoiceType477Id,
|
||||||
invoiceCorrectionType: invoiceCorrectionTypeId
|
invoiceCorrectionType: invoiceCorrectionTypeId
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,12 +222,13 @@
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-autocomplete
|
<vn-autocomplete
|
||||||
vn-one
|
vn-one
|
||||||
vn-id="cplusInvoiceType477"
|
vn-id="cplusInvoiceType"
|
||||||
data="cplusInvoiceType477"
|
data="cplusInvoiceType477"
|
||||||
show-field="description"
|
show-field="description"
|
||||||
value-field="id"
|
value-field="id"
|
||||||
required="true"
|
required="true"
|
||||||
ng-model="$ctrl.cplusInvoiceType477"
|
ng-model="$ctrl.cplusInvoiceType477"
|
||||||
|
search-function="{or: [{id: $search}, {description: {like: '%'+ $search +'%'}}]}"
|
||||||
label="Class">
|
label="Class">
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
<vn-autocomplete
|
<vn-autocomplete
|
||||||
|
|
|
@ -128,14 +128,12 @@ class Controller extends Section {
|
||||||
|
|
||||||
transferInvoice() {
|
transferInvoice() {
|
||||||
const params = {
|
const params = {
|
||||||
data: {
|
|
||||||
id: this.invoiceOut.id,
|
id: this.invoiceOut.id,
|
||||||
ref: this.invoiceOut.ref,
|
ref: this.invoiceOut.ref,
|
||||||
newClientFk: this.invoiceOut.client.id,
|
newClientFk: this.invoiceOut.client.id,
|
||||||
cplusRectificationId: this.cplusRectificationType,
|
cplusRectificationId: this.cplusRectificationType,
|
||||||
cplusInvoiceType477Id: this.cplusInvoiceType477,
|
cplusInvoiceType477Id: this.cplusInvoiceType477,
|
||||||
invoiceCorrectionTypeId: this.invoiceCorrectionType
|
invoiceCorrectionTypeId: this.invoiceCorrectionType
|
||||||
}
|
|
||||||
};
|
};
|
||||||
this.$http.post(`InvoiceOuts/transferInvoice`, params).then(res => console.log(res.data));
|
this.$http.post(`InvoiceOuts/transferInvoice`, params).then(res => console.log(res.data));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,32 @@
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
jorgep marked this conversation as resolved
|
|||||||
Self.clone = async(sales, refundAgencyMode, refoundZoneId, servicesIds, withWarehouse, isRefund, myOptions) => {
|
Self.clone = async(sales, refundAgencyMode, refoundZoneId, servicesIds, withWarehouse, group, negative, myOptions) => {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const ticketsIds = [...new Set(sales.map(sale => sale.ticketFk))];
|
let tx;
|
||||||
|
|
||||||
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ticketsIds = [...new Set(sales.map(sale => sale.ticketFk))];
|
||||||
|
const [firstTicketId] = ticketsIds;
|
||||||
const now = Date.vnNew();
|
const now = Date.vnNew();
|
||||||
let updatedTickets = [];
|
let updatedTickets = [];
|
||||||
|
let newTicket;
|
||||||
for (const ticketId of ticketsIds) {
|
const filter = {
|
||||||
const filter = {include: {relation: 'address'}};
|
include: [
|
||||||
|
{relation: 'address'},
|
||||||
|
{
|
||||||
|
relation: 'sale',
|
||||||
|
inq: sales,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
for (const [index, ticketId] of ticketsIds.entries()) {
|
||||||
const ticket = await models.Ticket.findById(ticketId, filter, myOptions);
|
const ticket = await models.Ticket.findById(ticketId, filter, myOptions);
|
||||||
|
if (!group || !index) {
|
||||||
const ticketUpdated = await models.Ticket.create({
|
newTicket = await models.Ticket.create({
|
||||||
clientFk: ticket.clientFk,
|
clientFk: ticket.clientFk,
|
||||||
shipped: now,
|
shipped: now,
|
||||||
jorgep marked this conversation as resolved
Outdated
alexm
commented
y te ahorres fer if y else ```
if(group) ticketsIds = ticketsIds[0]
for (let ticketId of ticketsIds) {
await createTicketRefund(
ticketId,
withWarehouse,
refundTickets,
mappedTickets,
now,
myOptions
);
}
```
y te ahorres fer if y else
|
|||||||
addressFk: ticket.address().id,
|
addressFk: ticket.address().id,
|
||||||
|
@ -21,26 +37,33 @@ module.exports = Self => {
|
||||||
landed: now,
|
landed: now,
|
||||||
zoneFk: refoundZoneId
|
zoneFk: refoundZoneId
|
||||||
}, myOptions);
|
}, myOptions);
|
||||||
jorgep marked this conversation as resolved
alexm
commented
Aqui Aqui
|
|||||||
updatedTickets.push(ticketUpdated);
|
updatedTickets.push(newTicket);
|
||||||
}
|
}
|
||||||
|
const sales = ticket.sale();
|
||||||
|
const saleIds = sales.map(sale => sale.id);
|
||||||
|
const saleComponentsFilter = {
|
||||||
|
where: {saleFk: {inq: saleIds}},
|
||||||
|
scope: {
|
||||||
|
fields: ['saleFk', 'componentFk', 'value']
|
||||||
jorgep marked this conversation as resolved
Outdated
alexm
commented
El map de mappedTickets realment el pots omplir fer el bucle El map de mappedTickets realment el pots omplir fer el bucle
|
|||||||
|
}
|
||||||
|
};
|
||||||
for (const sale of sales) {
|
for (const sale of sales) {
|
||||||
const createdSale = await models.Sale.create({
|
const createdSale = await models.Sale.create({
|
||||||
ticketFk: sale.ticketFk,
|
ticketFk: newTicket.id,
|
||||||
itemFk: sale.itemFk,
|
itemFk: sale.itemFk,
|
||||||
quantity: (isRefund) ? - sale.quantity : sale.quantity,
|
quantity: (negative) ? - sale.quantity : sale.quantity,
|
||||||
concept: sale.concept,
|
concept: sale.concept,
|
||||||
price: sale.price,
|
price: sale.price,
|
||||||
discount: sale.discount,
|
discount: sale.discount,
|
||||||
}, myOptions);
|
}, myOptions);
|
||||||
|
const components = await models.SaleComponent.find(saleComponentsFilter, myOptions);
|
||||||
const components = sale.components();
|
// const components = sale.components();
|
||||||
for (const component of components)
|
for (const component of components)
|
||||||
component.saleFk = createdSale.id;
|
component.saleFk = createdSale.id;
|
||||||
|
|
||||||
await models.SaleComponent.create(components, myOptions);
|
await models.SaleComponent.create(components, myOptions);
|
||||||
}
|
}
|
||||||
jorgep marked this conversation as resolved
Outdated
alexm
commented
if (servicesIds && servicesIds.length) if (servicesIds && servicesIds.length)
|
|||||||
|
}
|
||||||
if (servicesIds && servicesIds.length > 0) {
|
if (servicesIds && servicesIds.length > 0) {
|
||||||
const servicesFilter = {
|
const servicesFilter = {
|
||||||
where: {id: {inq: servicesIds}}
|
where: {id: {inq: servicesIds}}
|
||||||
|
@ -49,7 +72,7 @@ module.exports = Self => {
|
||||||
for (const service of services) {
|
for (const service of services) {
|
||||||
await models.TicketService.create({
|
await models.TicketService.create({
|
||||||
description: service.description,
|
description: service.description,
|
||||||
quantity: (isRefund) ? - service.quantity : service.quantity,
|
quantity: (negative) ? - service.quantity : service.quantity,
|
||||||
price: service.price,
|
price: service.price,
|
||||||
taxClassFk: service.taxClassFk,
|
taxClassFk: service.taxClassFk,
|
||||||
ticketFk: service.ticketFk,
|
ticketFk: service.ticketFk,
|
||||||
|
@ -60,8 +83,22 @@ module.exports = Self => {
|
||||||
|
|
||||||
const query = `CALL vn.ticket_recalc(?, NULL)`;
|
const query = `CALL vn.ticket_recalc(?, NULL)`;
|
||||||
|
|
||||||
|
if (group) {
|
||||||
|
await Self.rawSql(query, [newTicket.id], myOptions);
|
||||||
|
if (tx) await tx.commit();
|
||||||
|
return {
|
||||||
|
refundTicket: newTicket,
|
||||||
|
originalTicketFk: firstTicketId
|
||||||
jorgep marked this conversation as resolved
Outdated
alexm
commented
Pero no quedarem en que clone.js no debia tindre res relacionat en refund Pero no quedarem en que clone.js no debia tindre res relacionat en refund
|
|||||||
|
};
|
||||||
|
} else {
|
||||||
for (const updatedTicket of updatedTickets)
|
for (const updatedTicket of updatedTickets)
|
||||||
await Self.rawSql(query, [updatedTicket.id], myOptions);
|
await Self.rawSql(query, [updatedTicket.id], myOptions);
|
||||||
return updatedTickets.map(updatedTicket => updatedTicket.id);
|
if (tx) await tx.commit();
|
||||||
|
return updatedTickets/* updatedTickets.map(updatedTicket => updatedTicket.id) */;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (tx) await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -155,19 +155,23 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const sales = await models.Sale.find(salesFilter, myOptions);
|
const sales = await models.Sale.find(salesFilter, myOptions);
|
||||||
const group = true;
|
const clonedTicket = await models.Sale.clone(
|
||||||
const isRefund = true;
|
|
||||||
|
|
||||||
const refundTicket = await cloneAndGroup(
|
|
||||||
sales,
|
sales,
|
||||||
refundAgencyMode,
|
refundAgencyMode,
|
||||||
refoundZoneId,
|
refoundZoneId,
|
||||||
servicesIds,
|
servicesIds,
|
||||||
withWarehouse,
|
withWarehouse,
|
||||||
group,
|
true,
|
||||||
isRefund,
|
true,
|
||||||
myOptions
|
myOptions
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const refundTicket = clonedTicket.refundTicket;
|
||||||
|
|
||||||
|
await models.TicketRefund.create({
|
||||||
|
refundTicketFk: refundTicket.id,
|
||||||
|
originalTicketFk: clonedTicket.originalTicketFk,
|
||||||
|
}, myOptions);
|
||||||
if (tx) await tx.commit();
|
if (tx) await tx.commit();
|
||||||
|
|
||||||
return refundTicket;
|
return refundTicket;
|
||||||
|
@ -177,74 +181,7 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
async function cloneAndGroup(sales, refundAgencyMode, refoundZoneId, servicesIds, withWarehouse, group, isRefund, myOptions) {
|
/* async function createTicketRefund(ticketId, now, refundAgencyMode, refoundZoneId, withWarehouse, myOptions) {
|
||||||
if (!group) {
|
|
||||||
const tickets = await models.Sale.clone(sales,
|
|
||||||
refundAgencyMode,
|
|
||||||
refoundZoneId, servicesIds,
|
|
||||||
withWarehouse,
|
|
||||||
isRefund,
|
|
||||||
myOptions);
|
|
||||||
return tickets;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ticketsIds = [...new Set(sales.map(sale => sale.ticketFk))];
|
|
||||||
const [firstTicketId] = ticketsIds;
|
|
||||||
const filter = {include: {relation: 'address'}};
|
|
||||||
const ticket = await models.Ticket.findById(firstTicketId, filter, myOptions);
|
|
||||||
|
|
||||||
const ticketUpdated = await models.Ticket.create({
|
|
||||||
clientFk: ticket.clientFk,
|
|
||||||
shipped: now,
|
|
||||||
addressFk: ticket.address().id,
|
|
||||||
agencyModeFk: refundAgencyMode.id,
|
|
||||||
nickname: ticket.address().nickname,
|
|
||||||
warehouseFk: withWarehouse ? ticket.warehouseFk : null,
|
|
||||||
companyFk: ticket.companyFk,
|
|
||||||
landed: now,
|
|
||||||
zoneFk: refoundZoneId
|
|
||||||
}, myOptions);
|
|
||||||
|
|
||||||
for (const sale of sales) {
|
|
||||||
const createdSale = await models.Sale.create({
|
|
||||||
ticketFk: ticketUpdated.id,
|
|
||||||
itemFk: sale.itemFk,
|
|
||||||
quantity: (isRefund) ? - sale.quantity : sale.quantity,
|
|
||||||
concept: sale.concept,
|
|
||||||
price: sale.price,
|
|
||||||
discount: sale.discount,
|
|
||||||
}, myOptions);
|
|
||||||
|
|
||||||
const components = sale.components();
|
|
||||||
for (const component of components)
|
|
||||||
component.saleFk = createdSale.id;
|
|
||||||
|
|
||||||
await models.SaleComponent.create(components, myOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (servicesIds && servicesIds.length > 0) {
|
|
||||||
const servicesFilter = {
|
|
||||||
where: {id: {inq: servicesIds}}
|
|
||||||
};
|
|
||||||
const services = await models.TicketService.find(servicesFilter, myOptions);
|
|
||||||
for (const service of services) {
|
|
||||||
await models.TicketService.create({
|
|
||||||
description: service.description,
|
|
||||||
quantity: (isRefund) ? - service.quantity : service.quantity,
|
|
||||||
price: service.price,
|
|
||||||
taxClassFk: service.taxClassFk,
|
|
||||||
ticketFk: ticketUpdated.id,
|
|
||||||
ticketServiceTypeFk: service.ticketServiceTypeFk,
|
|
||||||
}, myOptions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const query = `CALL vn.ticket_recalc(?, NULL)`;
|
|
||||||
await Self.rawSql(query, [refundTicket.id], myOptions);
|
|
||||||
return ticketUpdated;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function createTicketRefund(ticketId, now, refundAgencyMode, refoundZoneId, withWarehouse, myOptions) {
|
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
|
|
||||||
const filter = {include: {relation: 'address'}};
|
const filter = {include: {relation: 'address'}};
|
||||||
|
@ -268,5 +205,5 @@ module.exports = Self => {
|
||||||
}, myOptions);
|
}, myOptions);
|
||||||
|
|
||||||
return refundTicket;
|
return refundTicket;
|
||||||
}
|
} */
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
const LoopBackContext = require('loopback-context');
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('Sale refund()', () => {
|
fdescribe('Sale refund()', () => {
|
||||||
const userId = 5;
|
const userId = 5;
|
||||||
const ctx = {req: {accessToken: userId}};
|
const ctx = {req: {accessToken: userId}};
|
||||||
const activeCtx = {
|
const activeCtx = {
|
||||||
|
|
|
@ -39,7 +39,6 @@ module.exports = Self => {
|
||||||
|
|
||||||
jorgep marked this conversation as resolved
Outdated
jgallego
commented
modules/ticket/back/methods/ticket/invoiceTicketsWithPdf.js este porque sale?
modules/ticket/back/methods/ticket/invoiceTicketsWithPdf.js este porque sale?
jorgep
commented
Se me olvidó borrarlo Se me olvidó borrarlo
|
|||||||
try {
|
try {
|
||||||
const filter = {where: {ticketFk: {inq: ticketsIds}}};
|
const filter = {where: {ticketFk: {inq: ticketsIds}}};
|
||||||
|
|
||||||
const sales = await models.Sale.find(filter, myOptions);
|
const sales = await models.Sale.find(filter, myOptions);
|
||||||
const salesIds = sales.map(sale => sale.id);
|
const salesIds = sales.map(sale => sale.id);
|
||||||
|
|
||||||
|
|
|
@ -136,6 +136,11 @@
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "Zone",
|
"model": "Zone",
|
||||||
"foreignKey": "zoneFk"
|
"foreignKey": "zoneFk"
|
||||||
|
},
|
||||||
jorgep marked this conversation as resolved
Outdated
jgallego
commented
esta repetido arriba con ticketSales esta repetido arriba con ticketSales
|
|||||||
|
"sale": {
|
||||||
|
"type": "hasMany",
|
||||||
|
"model": "Sale",
|
||||||
|
"foreignKey": "ticketFk"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Si quieres usar refundTickets en varios sitios no seria mejor ponerlo fuera de las funciones? (No estoy seguro de que funcione)
Mirado juntos.