Merge branch '5858-fiscalData-validations' of https://gitea.verdnatura.es/verdnatura/salix into 5858-fiscalData-validations

This commit is contained in:
Javier Segarra 2023-12-15 10:14:41 +01:00
commit 9cc2588bf4
30 changed files with 1401 additions and 68 deletions

View File

@ -11,6 +11,9 @@
"[javascript]": { "[javascript]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint" "editor.defaultFormatter": "dbaeumer.vscode-eslint"
}, },
"[json]": {
"editor.defaultFormatter": "vscode.json-language-features"
},
"cSpell.words": [ "cSpell.words": [
"salix", "salix",
"fdescribe" "fdescribe"

View File

@ -7,6 +7,10 @@ process.on('warning', warning => {
console.log(warning.stack); console.log(warning.stack);
}); });
process.on('SIGUSR2', async() => {
if (container) await container.rm();
});
process.on('exit', async function() { process.on('exit', async function() {
if (container) await container.rm(); if (container) await container.rm();
}); });

View File

@ -0,0 +1,46 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`delivery_beforeInsert`
BEFORE INSERT ON `delivery`
FOR EACH ROW
BEGIN
IF (NEW.longitude IS NOT NULL AND NEW.latitude IS NOT NULL AND NEW.ticketFK IS NOT NULL)
THEN
UPDATE address
SET longitude = NEW.longitude,
latitude = NEW.latitude
WHERE id IN (
SELECT addressFK
FROM ticket
WHERE id = NEW.ticketFk
);
END IF;
END$$
DELIMITER ;
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`delivery_beforeUpdate`
BEFORE UPDATE ON `delivery`
FOR EACH ROW
BEGIN
IF (NEW.longitude IS NOT NULL AND NEW.latitude IS NOT NULL AND NEW.ticketFK IS NOT NULL)
THEN
UPDATE address
SET longitude = NEW.longitude,
latitude = NEW.latitude
WHERE id IN (
SELECT addressFK
FROM ticket
WHERE id = NEW.ticketFk
);
END IF;
END$$
DELIMITER ;
ALTER TABLE `vn`.`address` MODIFY COLUMN longitude decimal(11,7) DEFAULT NULL NULL COMMENT 'Indica la última longitud proporcionada por tabla delivery';
ALTER TABLE `vn`.`address` MODIFY COLUMN latitude decimal(11,7) DEFAULT NULL NULL COMMENT 'Indica la última latitud proporcionada por tabla delivery';

View File

@ -0,0 +1 @@
ALTER TABLE `vn`.`ticketTracking` CHANGE `workerFk` `userFk` int(10) unsigned DEFAULT NULL NULL;

View File

@ -0,0 +1,4 @@
RENAME TABLE `vn`.`clientCreditLimit` TO `vn`.`roleCreditLimit`;
ALTER TABLE `vn`.`clientCreditLimit` DROP FOREIGN KEY `clientCreditLimit_FK`;
ALTER TABLE `vn`.`roleCreditLimit` ADD CONSTRAINT `roleCreditLimit_FK` FOREIGN KEY (`roleFk`) REFERENCES `account`.`role`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,52 @@
CREATE OR REPLACE DEFINER=`root`@`localhost`
SQL SECURITY DEFINER
VIEW `vn`.`ticketState`
AS SELECT `tt`.`created` AS `updated`,
`tt`.`stateFk` AS `stateFk`,
`tt`.`userFk` AS `userFk`,
`tls`.`ticketFk` AS `ticketFk`,
`s`.`id` AS `state`,
`s`.`order` AS `productionOrder`,
`s`.`alertLevel` AS `alertLevel`,
`s`.`code` AS `code`,
`tls`.`ticketFk` AS `ticket`,
`tt`.`userFk` AS `worker`,
`s`.`isPreviousPreparable` AS `isPreviousPreparable`,
`s`.`isPicked` AS `isPicked`
FROM (
(
`vn`.`ticketLastState` `tls`
JOIN `vn`.`ticketTracking` `tt` ON(`tt`.`id` = `tls`.`ticketTrackingFk`)
)
JOIN `vn`.`state` `s` ON(`s`.`id` = `tt`.`stateFk`)
);
CREATE OR REPLACE DEFINER=`root`@`localhost`
SQL SECURITY DEFINER
VIEW `vn2008`.`v_inter`
AS SELECT `tt`.`id` AS `inter_id`,
`tt`.`stateFk` AS `state_id`,
`tt`.`notes` AS `nota`,
`tt`.`created` AS `odbc_date`,
`tt`.`ticketFk` AS `Id_Ticket`,
`tt`.`userFk` AS `Id_Trabajador`,
`tt`.`supervisorFk` AS `Id_supervisor`
FROM `vn`.`ticketTracking` `tt`;
CREATE OR REPLACE
ALGORITHM = UNDEFINED VIEW `ticketStateToday` AS
SELECT
`ts`.`ticket` AS `ticket`,
`ts`.`state` AS `state`,
`ts`.`productionOrder` AS `productionOrder`,
`ts`.`alertLevel` AS `alertLevel`,
`ts`.`userFk` AS `userFk`,
`ts`.`code` AS `code`,
`ts`.`updated` AS `updated`,
`ts`.`isPicked` AS `isPicked`
FROM
(`ticketState` `ts`
JOIN `ticket` `t` ON
(`t`.`id` = `ts`.`ticket`))
WHERE
`t`.`shipped` BETWEEN `util`.`VN_CURDATE`() AND `MIDNIGHT`(`util`.`VN_CURDATE`());

View File

@ -5,10 +5,6 @@ SET DEFAULT ROLE 'salix' FOR 'root'@'%';
CREATE SCHEMA IF NOT EXISTS `vn2008`; CREATE SCHEMA IF NOT EXISTS `vn2008`;
CREATE SCHEMA IF NOT EXISTS `tmp`; CREATE SCHEMA IF NOT EXISTS `tmp`;
CREATE ROLE 'salix';
GRANT 'salix' TO 'root'@'%';
SET DEFAULT ROLE 'salix' FOR 'root'@'%';
UPDATE `util`.`config` UPDATE `util`.`config`
SET `environment`= 'development'; SET `environment`= 'development';
@ -497,7 +493,7 @@ INSERT INTO `vn`.`clientCredit`(`clientFk`, `workerFk`, `amount`, `created`)
(1104, 9, 90 , util.VN_CURDATE()), (1104, 9, 90 , util.VN_CURDATE()),
(1105, 9, 90 , util.VN_CURDATE()); (1105, 9, 90 , util.VN_CURDATE());
INSERT INTO `vn`.`clientCreditLimit`(`id`, `maxAmount`, `roleFk`) INSERT INTO `vn`.`roleCreditLimit`(`id`, `maxAmount`, `roleFk`)
VALUES VALUES
(1, 9999999, 20), (1, 9999999, 20),
(2, 10000, 21), (2, 10000, 21),
@ -775,7 +771,7 @@ INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `des
-- FIX for state hours on local, inter_afterInsert -- FIX for state hours on local, inter_afterInsert
-- UPDATE vncontrol.inter SET odbc_date = DATE_ADD(util.VN_CURDATE(), INTERVAL -10 SECOND); -- UPDATE vncontrol.inter SET odbc_date = DATE_ADD(util.VN_CURDATE(), INTERVAL -10 SECOND);
INSERT INTO `vn`.`ticketTracking`(`ticketFk`, `stateFk`, `workerFk`, `created`) INSERT INTO `vn`.`ticketTracking`(`ticketFk`, `stateFk`, `userFk`, `created`)
VALUES VALUES
(1, 16, 5 , DATE_ADD(util.VN_NOW(), INTERVAL -1 MONTH)), (1, 16, 5 , DATE_ADD(util.VN_NOW(), INTERVAL -1 MONTH)),
(2, 16, 5 , DATE_ADD(util.VN_NOW(), INTERVAL -1 MONTH)), (2, 16, 5 , DATE_ADD(util.VN_NOW(), INTERVAL -1 MONTH)),
@ -819,6 +815,7 @@ INSERT INTO `vn`.`config`(`id`, `mdbServer`, `fakeEmail`, `defaultersMaxAmount`,
VALUES VALUES
(1, 'beta-server', 'nightmare@mydomain.com', '200', DATE_ADD(util.VN_CURDATE(),INTERVAL -1 MONTH)); (1, 'beta-server', 'nightmare@mydomain.com', '200', DATE_ADD(util.VN_CURDATE(),INTERVAL -1 MONTH));
INSERT INTO `vn`.`greugeType`(`id`, `name`, `code`) INSERT INTO `vn`.`greugeType`(`id`, `name`, `code`)
VALUES VALUES
(1, 'Diff', 'diff'), (1, 'Diff', 'diff'),

View File

@ -18,6 +18,7 @@ Show summary: Mostrar vista previa
What is new: Novedades de la versión What is new: Novedades de la versión
Settings: Ajustes Settings: Ajustes
There is a new version, click here to reload: Hay una nueva versión, pulse aquí para recargar There is a new version, click here to reload: Hay una nueva versión, pulse aquí para recargar
This ticket is locked.: Este ticket está bloqueado
# Actions # Actions

View File

@ -120,7 +120,7 @@ function $exceptionHandler(vnApp, $window, $state, $injector) {
messageT = 'Invalid login'; messageT = 'Invalid login';
break; break;
case 403: case 403:
messageT = 'Access denied'; messageT = exception.data?.error?.message || 'Access denied';
break; break;
case 502: case 502:
messageT = 'It seems that the server has fall down'; messageT = 'It seems that the server has fall down';

View File

@ -123,7 +123,7 @@ module.exports = Self => {
await models.TicketTracking.create({ await models.TicketTracking.create({
ticketFk: newRefundTicket.id, ticketFk: newRefundTicket.id,
stateFk: state.id, stateFk: state.id,
workerFk: worker.id userFk: worker.id
}, myOptions); }, myOptions);
const salesToRefund = await models.ClaimBeginning.find(salesFilter, myOptions); const salesToRefund = await models.ClaimBeginning.find(salesFilter, myOptions);

View File

@ -29,7 +29,7 @@
"ClientCredit": { "ClientCredit": {
"dataSource": "vn" "dataSource": "vn"
}, },
"ClientCreditLimit": { "RoleCreditLimit": {
"dataSource": "vn" "dataSource": "vn"
}, },
"ClientConsumptionQueue": { "ClientConsumptionQueue": {

View File

@ -463,7 +463,7 @@ module.exports = Self => {
throw new UserError(`You can't change the credit set to zero from a financialBoss`); throw new UserError(`You can't change the credit set to zero from a financialBoss`);
} }
const creditLimits = await models.ClientCreditLimit.find({ const creditLimits = await models.RoleCreditLimit.find({
fields: ['roleFk'], fields: ['roleFk'],
where: { where: {
maxAmount: {gte: changes.credit} maxAmount: {gte: changes.credit}

View File

@ -1,9 +1,9 @@
{ {
"name": "ClientCreditLimit", "name": "RoleCreditLimit",
"base": "VnModel", "base": "VnModel",
"options": { "options": {
"mysql": { "mysql": {
"table": "clientCreditLimit" "table": "roleCreditLimit"
} }
}, },
"properties": { "properties": {

View File

@ -130,13 +130,15 @@ module.exports = Self => {
am.name agencyName, am.name agencyName,
u.name AS workerUserName, u.name AS workerUserName,
v.numberPlate AS vehiclePlateNumber, v.numberPlate AS vehiclePlateNumber,
Date_format(r.time, '%H:%i') hour Date_format(r.time, '%H:%i') hour,
eu.email
FROM route r FROM route r
LEFT JOIN agencyMode am ON am.id = r.agencyModeFk LEFT JOIN agencyMode am ON am.id = r.agencyModeFk
LEFT JOIN agency a ON a.id = am.agencyFk LEFT JOIN agency a ON a.id = am.agencyFk
LEFT JOIN vehicle v ON v.id = r.vehicleFk LEFT JOIN vehicle v ON v.id = r.vehicleFk
LEFT JOIN worker w ON w.id = r.workerFk LEFT JOIN worker w ON w.id = r.workerFk
LEFT JOIN account.user u ON u.id = w.id` LEFT JOIN account.user u ON u.id = w.id
LEFT JOIN account.emailUser eu ON eu.userFk = r.workerFk`
); );
stmt.merge(conn.makeSuffix(filter)); stmt.merge(conn.makeSuffix(filter));

View File

@ -0,0 +1,64 @@
module.exports = Self => {
Self.remoteMethod('getExpeditionSummary', {
description: 'Get summary of expeditions for a given route',
accepts: [
{
arg: 'routeFk',
type: 'number',
required: true,
description: 'Foreign key for Route'
}
],
returns: {
type: 'object',
root: true
},
http: {
path: '/getExpeditionSummary',
verb: 'get'
}
});
Self.getExpeditionSummary = async(routeFk, options) => {
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const query = `
SELECT routeFk,
addressFk,
SUM(total) total,
SUM(delivery) delivery,
SUM(lost) lost,
SUM(delivered) delivered,
GROUP_CONCAT(totalPacking ORDER BY total DESC SEPARATOR ' ') itemPackingType
FROM (
SELECT r.id AS routeFk,
t.addressFk,
CONCAT (IFNULL(e.itemPackingTypeFk,'-'), '', COUNT(*)) totalPacking,
COUNT(*) total,
SUM(est.code = 'ON DELIVERY') delivery,
SUM(est.code = 'LOST') lost,
SUM(est.code = 'DELIVERED') delivered,
t.priority
FROM vn.ticket t
JOIN vn.route r ON r.id = t.routeFk
JOIN vn.expedition e ON e.ticketFk = t.id
LEFT JOIN vn.expeditionStateType est ON est.id = e.stateTypeFk
JOIN vn.agencyMode am ON am.id = r.agencyModeFk
JOIN vn.agency ag ON ag.id = am.agencyFk
LEFT JOIN vn.userConfig uc ON uc.userFk = account.myUser_getId()
WHERE (r.created = util.VN_CURDATE() OR r.created = util.yesterday())
AND t.routeFk = ?
GROUP BY t.addressFk, e.itemPackingTypeFk
) sub
GROUP BY addressFk
ORDER BY priority DESC
`;
const results = await Self.rawSql(query, [routeFk], myOptions);
return results;
};
};

View File

@ -3,7 +3,7 @@ const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
module.exports = Self => { module.exports = Self => {
Self.remoteMethod('getTickets', { Self.remoteMethod('getTickets', {
description: 'Return the tickets information displayed on the route module', description: 'Find all instances of the model matched by filter from the data source.',
accessType: 'READ', accessType: 'READ',
accepts: [ accepts: [
{ {
@ -40,22 +40,32 @@ module.exports = Self => {
t.clientFk, t.clientFk,
t.priority, t.priority,
t.addressFk, t.addressFk,
st.code AS ticketStateCode, st.code ticketStateCode,
st.name AS ticketStateName, st.name ticketStateName,
wh.name AS warehouseName, wh.name warehouseName,
tob.description AS ticketObservation, tob.description ticketObservation,
a.street, a.street,
a.postalCode, a.postalCode,
a.city, a.city,
am.name AS agencyModeName, am.name agencyModeName,
u.nickname AS userNickname, u.nickname userNickname,
vn.ticketTotalVolume(t.id) AS volume, vn.ticketTotalVolume(t.id) volume,
tob.description, tob.description,
GROUP_CONCAT(DISTINCT i.itemPackingTypeFk ORDER BY i.itemPackingTypeFk) ipt GROUP_CONCAT(DISTINCT i.itemPackingTypeFk ORDER BY i.itemPackingTypeFk) ipt,
c.phone clientPhone,
c.mobile clientMobile,
a.phone addressPhone,
a.mobile addressMobile,
a.longitude,
a.latitude,
wm.mediaValue salePersonPhone,
t.cmrFk,
t.isSigned signed
FROM vn.route r FROM vn.route r
JOIN ticket t ON t.routeFk = r.id JOIN ticket t ON t.routeFk = r.id
JOIN vn.sale s ON s.ticketFk = t.id JOIN client c ON t.clientFk = c.id
JOIN vn.item i ON i.id = s.itemFk LEFT JOIN vn.sale s ON s.ticketFk = t.id
LEFT JOIN vn.item i ON i.id = s.itemFk
LEFT JOIN ticketState ts ON ts.ticketFk = t.id LEFT JOIN ticketState ts ON ts.ticketFk = t.id
LEFT JOIN state st ON st.id = ts.stateFk LEFT JOIN state st ON st.id = ts.stateFk
LEFT JOIN warehouse wh ON wh.id = t.warehouseFk LEFT JOIN warehouse wh ON wh.id = t.warehouseFk
@ -65,7 +75,8 @@ module.exports = Self => {
LEFT JOIN address a ON a.id = t.addressFk LEFT JOIN address a ON a.id = t.addressFk
LEFT JOIN agencyMode am ON am.id = t.agencyModeFk LEFT JOIN agencyMode am ON am.id = t.agencyModeFk
LEFT JOIN account.user u ON u.id = r.workerFk LEFT JOIN account.user u ON u.id = r.workerFk
LEFT JOIN vehicle v ON v.id = r.vehicleFk` LEFT JOIN vehicle v ON v.id = r.vehicleFk
LEFT JOIN workerMedia wm ON wm.workerFk = c.salesPersonFk`
); );
if (!filter.where) filter.where = {}; if (!filter.where) filter.where = {};

View File

@ -0,0 +1,10 @@
const app = require('vn-loopback/server/server');
describe('route getExpeditionSummary()', () => {
const routeId = 1;
it('should return a summary of expeditions for a route', async() => {
const result = await app.models.Route.getExpeditionSummary(routeId);
expect(result.every(route => route.id = routeId)).toBeTruthy();
});
});

View File

@ -17,6 +17,7 @@ module.exports = Self => {
require('../methods/route/cmr')(Self); require('../methods/route/cmr')(Self);
require('../methods/route/getExternalCmrs')(Self); require('../methods/route/getExternalCmrs')(Self);
require('../methods/route/downloadCmrsZip')(Self); require('../methods/route/downloadCmrsZip')(Self);
require('../methods/route/getExpeditionSummary')(Self);
require('../methods/route/getByWorker')(Self); require('../methods/route/getByWorker')(Self);
Self.validate('kmStart', validateDistance, { Self.validate('kmStart', validateDistance, {

View File

@ -94,10 +94,10 @@ describe('ticket state()', () => {
const ticketTracking = await models.Ticket.state(ctx, params, options); const ticketTracking = await models.Ticket.state(ctx, params, options);
expect(ticketTracking.__data.ticketFk).toBe(params.ticketFk); expect(ticketTracking.ticketFk).toBe(params.ticketFk);
expect(ticketTracking.__data.stateFk).toBe(params.stateFk); expect(ticketTracking.stateFk).toBe(params.stateFk);
expect(ticketTracking.__data.workerFk).toBe(49); expect(ticketTracking.userFk).toBe(49);
expect(ticketTracking.__data.id).toBeDefined(); expect(ticketTracking.id).toBeDefined();
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
@ -116,14 +116,14 @@ describe('ticket state()', () => {
const ticket = await models.Ticket.create(sampleTicket, options); const ticket = await models.Ticket.create(sampleTicket, options);
const ctx = {req: {accessToken: {userId: 18}}}; const ctx = {req: {accessToken: {userId: 18}}};
const assignedState = await models.State.findOne({where: {code: 'PICKER_DESIGNED'}}, options); const assignedState = await models.State.findOne({where: {code: 'PICKER_DESIGNED'}}, options);
const params = {ticketFk: ticket.id, stateFk: assignedState.id, workerFk: 1}; const params = {ticketFk: ticket.id, stateFk: assignedState.id, userFk: 1};
const res = await models.Ticket.state(ctx, params, options); const res = await models.Ticket.state(ctx, params, options);
expect(res.__data.ticketFk).toBe(params.ticketFk); expect(res.ticketFk).toBe(params.ticketFk);
expect(res.__data.stateFk).toBe(params.stateFk); expect(res.stateFk).toBe(params.stateFk);
expect(res.__data.workerFk).toBe(params.workerFk); expect(res.userFk).toBe(params.userFk);
expect(res.__data.workerFk).toBe(1); expect(res.userFk).toBe(1);
expect(res.__data.id).toBeDefined(); expect(res.id).toBeDefined();
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {

View File

@ -51,12 +51,12 @@ module.exports = Self => {
params.stateFk = state.id; params.stateFk = state.id;
} }
if (!params.workerFk) { if (!params.userFk) {
const worker = await models.Worker.findOne({ const worker = await models.Worker.findOne({
where: {id: userId} where: {id: userId}
}, myOptions); }, myOptions);
params.workerFk = worker.id; params.userFk = worker.id;
} }
const ticketState = await models.TicketState.findById(params.ticketFk, { const ticketState = await models.TicketState.findById(params.ticketFk, {

View File

@ -24,5 +24,12 @@
"userFk": { "userFk": {
"type": "number" "type": "number"
} }
},
"relations": {
"expeditionStateType": {
"type": "belongsTo",
"model": "ExpeditionStateType",
"foreignKey": "typeFk"
}
} }
} }

View File

@ -33,10 +33,10 @@
"model": "State", "model": "State",
"foreignKey": "stateFk" "foreignKey": "stateFk"
}, },
"worker": { "user": {
"type": "belongsTo", "type": "belongsTo",
"model": "Worker", "model": "VnUser",
"foreignKey": "workerFk" "foreignKey": "userFk"
} }
} }
} }

View File

@ -2,5 +2,5 @@ module.exports = function(Self) {
require('../methods/ticket-tracking/setDelivered')(Self); require('../methods/ticket-tracking/setDelivered')(Self);
Self.validatesPresenceOf('stateFk', {message: 'State cannot be blank'}); Self.validatesPresenceOf('stateFk', {message: 'State cannot be blank'});
Self.validatesPresenceOf('workerFk', {message: 'Worker cannot be blank'}); Self.validatesPresenceOf('userFk', {message: 'Worker cannot be blank'});
}; };

View File

@ -21,7 +21,7 @@
"stateFk": { "stateFk": {
"type": "number" "type": "number"
}, },
"workerFk": { "userFk": {
"type": "number" "type": "number"
} }
}, },
@ -36,10 +36,10 @@
"model": "State", "model": "State",
"foreignKey": "stateFk" "foreignKey": "stateFk"
}, },
"worker": { "user": {
"type": "belongsTo", "type": "belongsTo",
"model": "Worker", "model": "VnUser",
"foreignKey": "workerFk" "foreignKey": "userFk"
} }
} }
} }

View File

@ -7,16 +7,10 @@ class Controller extends Section {
this.filter = { this.filter = {
include: [ include: [
{ {
relation: 'worker',
scope: {
fields: ['id'],
include: {
relation: 'user', relation: 'user',
scope: { scope: {
fields: ['name'] fields: ['name']
} }
}
}
}, { }, {
relation: 'state', relation: 'state',
scope: { scope: {

View File

@ -64,7 +64,7 @@ module.exports = Self => {
promises.push(models.TicketTracking.create({ promises.push(models.TicketTracking.create({
ticketFk: ticket.id, ticketFk: ticket.id,
stateFk: fixingState.id, stateFk: fixingState.id,
workerFk: worker.id userFk: worker.id
}, myOptions)); }, myOptions));
} }
} }

View File

@ -20,7 +20,7 @@ SELECT
u.nickName salesPersonName, u.nickName salesPersonName,
ipkg.itemPackingTypes ipkg.itemPackingTypes
FROM route r FROM route r
LEFT JOIN ticket t ON t.routeFk = r.id JOIN ticket t ON t.routeFk = r.id
LEFT JOIN address a ON a.id = t.addressFk LEFT JOIN address a ON a.id = t.addressFk
LEFT JOIN client c ON c.id = t.clientFk LEFT JOIN client c ON c.id = t.clientFk
LEFT JOIN worker w ON w.id = client_getSalesPerson(t.clientFk, CURDATE()) LEFT JOIN worker w ON w.id = client_getSalesPerson(t.clientFk, CURDATE())

View File

@ -16,6 +16,7 @@
<tr> <tr>
<td class="font gray uppercase">{{$t('clientId')}}</td> <td class="font gray uppercase">{{$t('clientId')}}</td>
<th>{{client.id}}</th> <th>{{client.id}}</th>
</tr> </tr>
<tr> <tr>
<td class="font gray uppercase">{{$t('invoice')}}</td> <td class="font gray uppercase">{{$t('invoice')}}</td>
@ -80,6 +81,9 @@
<span>{{formatDate(ticket.shipped, '%d-%m-%Y')}}</span> <span>{{formatDate(ticket.shipped, '%d-%m-%Y')}}</span>
</div> </div>
</div> </div>
<span class="pull-right">
<h2>{{ticket.street}}</h2>
</span>
<span id="nickname" class="pull-right"> <span id="nickname" class="pull-right">
<h2>{{ticket.nickname}}</h2> <h2>{{ticket.nickname}}</h2>
</span> </span>

View File

@ -2,9 +2,12 @@ SELECT
t.id, t.id,
t.shipped, t.shipped,
t.nickname, t.nickname,
tto.description tto.description,
t.addressFk,
a.street
FROM invoiceOut io FROM invoiceOut io
JOIN ticket t ON t.refFk = io.REF JOIN ticket t ON t.refFk = io.REF
JOIN `address` a ON a.id = t.addressFk
LEFT JOIN observationType ot ON ot.code = 'invoiceOut' LEFT JOIN observationType ot ON ot.code = 'invoiceOut'
LEFT JOIN ticketObservation tto ON tto.ticketFk = t.id LEFT JOIN ticketObservation tto ON tto.ticketFk = t.id
AND tto.observationTypeFk = ot.id AND tto.observationTypeFk = ot.id