5097-item.summary_available #1312
|
@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
## [2306.01] - 2023-02-23
|
## [2306.01] - 2023-02-23
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
-
|
- (Tickets -> Datos Básicos) Mensaje de confirmación al intentar generar tickets con negativos
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- (General -> Inicio) Ahora permite recuperar la contraseña tanto con el correo de recuperación como el usuario
|
- (General -> Inicio) Ahora permite recuperar la contraseña tanto con el correo de recuperación como el usuario
|
||||||
|
|
|
@ -1,2 +1,173 @@
|
||||||
DELETE FROM `salix`.`ACL` WHERE model="SaleChecked";
|
DELETE FROM `salix`.`ACL` WHERE model="SaleChecked";
|
||||||
DROP TABLE IF EXISTS `vn`.`saleChecked`;
|
DROP TABLE IF EXISTS `vn`.`saleChecked`;
|
||||||
|
DROP PROCEDURE IF EXISTS `vn`.`clean`;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
$$
|
||||||
|
CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`clean`()
|
||||||
|
BEGIN
|
||||||
|
DECLARE vDateShort DATETIME;
|
||||||
|
DECLARE vOneYearAgo DATE;
|
||||||
|
DECLARE vFourYearsAgo DATE;
|
||||||
|
DECLARE v18Month DATE;
|
||||||
|
DECLARE v26Month DATE;
|
||||||
|
DECLARE v3Month DATE;
|
||||||
|
DECLARE vTrashId VARCHAR(15);
|
||||||
|
|
||||||
|
SET vDateShort = util.VN_CURDATE() - INTERVAL 2 MONTH;
|
||||||
|
SET vOneYearAgo = util.VN_CURDATE() - INTERVAL 1 YEAR;
|
||||||
|
SET vFourYearsAgo = util.VN_CURDATE() - INTERVAL 4 YEAR;
|
||||||
|
SET v18Month = util.VN_CURDATE() - INTERVAL 18 MONTH;
|
||||||
|
SET v26Month = util.VN_CURDATE() - INTERVAL 26 MONTH;
|
||||||
|
SET v3Month = util.VN_CURDATE() - INTERVAL 3 MONTH;
|
||||||
|
|
||||||
|
DELETE FROM ticketParking WHERE created < vDateShort;
|
||||||
|
DELETE FROM routesMonitor WHERE dated < vDateShort;
|
||||||
|
DELETE FROM workerTimeControlLog WHERE created < vDateShort;
|
||||||
|
DELETE FROM `message` WHERE sendDate < vDateShort;
|
||||||
|
DELETE FROM messageInbox WHERE sendDate < vDateShort;
|
||||||
|
DELETE FROM messageInbox WHERE sendDate < vDateShort;
|
||||||
|
DELETE FROM workerTimeControl WHERE timed < vFourYearsAgo;
|
||||||
|
DELETE FROM itemShelving WHERE created < util.VN_CURDATE() AND visible = 0;
|
||||||
|
DELETE FROM ticketDown WHERE created < TIMESTAMPADD(DAY,-1,util.VN_CURDATE());
|
||||||
|
DELETE FROM entryLog WHERE creationDate < vDateShort;
|
||||||
|
DELETE IGNORE FROM expedition WHERE created < v26Month;
|
||||||
|
DELETE FROM sms WHERE created < v18Month;
|
||||||
|
DELETE FROM saleTracking WHERE created < vOneYearAgo;
|
||||||
|
DELETE FROM ticketTracking WHERE created < v18Month;
|
||||||
|
DELETE tobs FROM ticketObservation tobs
|
||||||
|
JOIN ticket t ON tobs.ticketFk = t.id WHERE t.shipped < TIMESTAMPADD(YEAR,-2,util.VN_CURDATE());
|
||||||
|
DELETE sc.* FROM saleCloned sc JOIN sale s ON s.id = sc.saleClonedFk JOIN ticket t ON t.id = s.ticketFk WHERE t.shipped < vOneYearAgo;
|
||||||
|
DELETE FROM sharingCart where ended < vDateShort;
|
||||||
|
DELETE FROM sharingClient where ended < vDateShort;
|
||||||
|
DELETE tw.* FROM ticketWeekly tw
|
||||||
|
LEFT JOIN sale s ON s.ticketFk = tw.ticketFk WHERE s.itemFk IS NULL;
|
||||||
|
DELETE FROM claim WHERE ticketCreated < vFourYearsAgo;
|
||||||
|
DELETE FROM message WHERE sendDate < vDateShort;
|
||||||
|
-- Robert ubicacion anterior de trevelLog comentario para debug
|
||||||
|
DELETE FROM zoneEvent WHERE `type` = 'day' AND dated < v3Month;
|
||||||
|
DELETE bm
|
||||||
|
FROM buyMark bm
|
||||||
|
JOIN buy b ON b.id = bm.id
|
||||||
|
JOIN entry e ON e.id = b.entryFk
|
||||||
|
JOIN travel t ON t.id = e.travelFk
|
||||||
|
WHERE t.landed <= vDateShort;
|
||||||
|
DELETE FROM vn.buy WHERE created < vDateShort AND entryFk = 9200;
|
||||||
|
DELETE FROM vn.itemShelvingLog WHERE created < vDateShort;
|
||||||
|
DELETE FROM vn.stockBuyed WHERE creationDate < vDateShort;
|
||||||
|
DELETE FROM vn.itemCleanLog WHERE created < util.VN_NOW() - INTERVAL 1 YEAR;
|
||||||
|
DELETE FROM printQueue WHERE statusCode = 'printed' AND created < vDateShort;
|
||||||
|
|
||||||
|
-- Equipos duplicados
|
||||||
|
DELETE w.*
|
||||||
|
FROM workerTeam w
|
||||||
|
JOIN (SELECT id, team, workerFk, COUNT(*) - 1 as duplicated
|
||||||
|
FROM workerTeam
|
||||||
|
GROUP BY team,workerFk
|
||||||
|
HAVING duplicated
|
||||||
|
) d ON d.team = w.team AND d.workerFk = w.workerFk AND d.id != w.id;
|
||||||
|
|
||||||
|
DELETE sc
|
||||||
|
FROM saleComponent sc
|
||||||
|
JOIN sale s ON s.id= sc.saleFk
|
||||||
|
JOIN ticket t ON t.id= s.ticketFk
|
||||||
|
WHERE t.shipped < v18Month;
|
||||||
|
|
||||||
|
DELETE c
|
||||||
|
FROM vn.claim c
|
||||||
|
JOIN vn.claimState cs ON cs.id = c.claimStateFk
|
||||||
|
WHERE cs.description = "Anulado" AND
|
||||||
|
c.created < vDateShort;
|
||||||
|
DELETE
|
||||||
|
FROM vn.expeditionTruck
|
||||||
|
WHERE ETD < v3Month;
|
||||||
|
|
||||||
|
-- borrar travels sin entradas
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.thermographToDelete;
|
||||||
|
CREATE TEMPORARY TABLE tmp.thermographToDelete
|
||||||
|
SELECT th.id,th.dmsFk
|
||||||
|
FROM vn.travel t
|
||||||
|
LEFT JOIN vn.entry e ON e.travelFk = t.id
|
||||||
|
JOIN vn.travelThermograph th ON th.travelFk = t.id
|
||||||
|
WHERE t.shipped < TIMESTAMPADD(MONTH, -3, util.VN_CURDATE()) AND e.travelFk IS NULL;
|
||||||
|
|
||||||
|
SELECT dt.id INTO vTrashId
|
||||||
|
FROM vn.dmsType dt
|
||||||
|
WHERE dt.code = 'trash';
|
||||||
|
|
||||||
|
UPDATE tmp.thermographToDelete th
|
||||||
|
JOIN vn.dms d ON d.id = th.dmsFk
|
||||||
|
SET d.dmsTypeFk = vTrashId;
|
||||||
|
|
||||||
|
DELETE th
|
||||||
|
FROM tmp.thermographToDelete tmp
|
||||||
|
JOIN vn.travelThermograph th ON th.id = tmp.id;
|
||||||
|
|
||||||
|
DELETE t
|
||||||
|
FROM vn.travel t
|
||||||
|
LEFT JOIN vn.entry e ON e.travelFk = t.id
|
||||||
|
WHERE t.shipped < TIMESTAMPADD(MONTH, -3, util.VN_CURDATE()) AND e.travelFk IS NULL;
|
||||||
|
|
||||||
|
UPDATE dms d
|
||||||
|
JOIN dmsType dt ON dt.id = d.dmsTypeFk
|
||||||
|
SET d.dmsTypeFk = vTrashId
|
||||||
|
WHERE created < TIMESTAMPADD(MONTH, -dt.monthToDelete, util.VN_CURDATE());
|
||||||
|
|
||||||
|
-- borrar entradas sin compras
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.entryToDelete;
|
||||||
|
CREATE TEMPORARY TABLE tmp.entryToDelete
|
||||||
|
SELECT e.*
|
||||||
|
FROM vn.entry e
|
||||||
|
LEFT JOIN vn.buy b ON b.entryFk = e.id
|
||||||
|
JOIN vn.entryConfig ec ON e.id != ec.defaultEntry
|
||||||
|
WHERE e.dated < TIMESTAMPADD(MONTH, -3, util.VN_CURDATE()) AND b.entryFK IS NULL;
|
||||||
|
|
||||||
|
DELETE e
|
||||||
|
FROM vn.entry e
|
||||||
|
JOIN tmp.entryToDelete tmp ON tmp.id = e.id;
|
||||||
|
|
||||||
|
-- borrar de route registros menores a 4 años
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.routeToDelete;
|
||||||
|
CREATE TEMPORARY TABLE tmp.routeToDelete
|
||||||
|
SELECT *
|
||||||
|
FROM vn.route r
|
||||||
|
WHERE created < TIMESTAMPADD(YEAR,-4,util.VN_CURDATE());
|
||||||
|
|
||||||
|
UPDATE tmp.routeToDelete tmp
|
||||||
|
JOIN vn.dms d ON d.id = tmp.gestdocFk
|
||||||
|
SET d.dmsTypeFk = vTrashId;
|
||||||
|
|
||||||
|
DELETE r
|
||||||
|
FROM tmp.routeToDelete tmp
|
||||||
|
JOIN vn.route r ON r.id = tmp.id;
|
||||||
|
|
||||||
|
-- borrar registros de dua y awb menores a 2 años
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.duaToDelete;
|
||||||
|
CREATE TEMPORARY TABLE tmp.duaToDelete
|
||||||
|
SELECT *
|
||||||
|
FROM vn.dua
|
||||||
|
WHERE operated < TIMESTAMPADD(YEAR,-2,util.VN_CURDATE());
|
||||||
|
|
||||||
|
UPDATE tmp.duaToDelete tm
|
||||||
|
JOIN vn.dms d ON d.id = tm.gestdocFk
|
||||||
|
SET d.dmsTypeFk = vTrashId;
|
||||||
|
|
||||||
|
DELETE d
|
||||||
|
FROM tmp.duaToDelete tmp
|
||||||
|
JOIN vn.dua d ON d.id = tmp.id;
|
||||||
|
|
||||||
|
DELETE FROM vn.awb WHERE created < TIMESTAMPADD(YEAR,-2,util.VN_CURDATE());
|
||||||
|
|
||||||
|
-- Borra los registros de collection y ticketcollection
|
||||||
|
DELETE FROM vn.collection WHERE created < vDateShort;
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.thermographToDelete;
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.entryToDelete;
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.duaToDelete;
|
||||||
|
|
||||||
|
DELETE FROM travelLog WHERE creationDate < v3Month;
|
||||||
|
|
||||||
|
CALL shelving_clean;
|
||||||
|
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
ALTER TABLE `vn`.`itemConfig` ADD defaultTag INT DEFAULT 56 NOT NULL;
|
||||||
|
ALTER TABLE `vn`.`itemConfig` ADD CONSTRAINT itemConfig_FK FOREIGN KEY (defaultTag) REFERENCES vn.tag(id);
|
||||||
|
ALTER TABLE `vn`.`itemConfig` ADD validPriorities varchar(50) DEFAULT '[1,2,3]' NOT NULL;
|
||||||
|
ALTER TABLE `vn`.`itemConfig` ADD defaultPriority INT DEFAULT 2 NOT NULL;
|
||||||
|
ALTER TABLE `vn`.`item` MODIFY COLUMN relevancy tinyint(1) DEFAULT 0 NOT NULL COMMENT 'La web ordena de forma descendiente por este campo para mostrar los artículos';
|
||||||
|
|
||||||
|
INSERT INTO `salix`.`ACL`
|
||||||
|
(model, property, accessType, permission, principalType, principalId)
|
||||||
|
VALUES('ItemConfig', '*', 'READ', 'ALLOW', 'ROLE', 'buyer');
|
|
@ -26286,6 +26286,7 @@ CREATE TABLE `entry` (
|
||||||
`typeFk` varchar(100) COLLATE utf8mb3_unicode_ci DEFAULT NULL COMMENT 'Tipo de entrada',
|
`typeFk` varchar(100) COLLATE utf8mb3_unicode_ci DEFAULT NULL COMMENT 'Tipo de entrada',
|
||||||
`reference` varchar(50) COLLATE utf8mb3_unicode_ci DEFAULT NULL COMMENT 'Referencia para eti',
|
`reference` varchar(50) COLLATE utf8mb3_unicode_ci DEFAULT NULL COMMENT 'Referencia para eti',
|
||||||
`ref` varchar(50) GENERATED ALWAYS AS (`invoiceNumber`) VIRTUAL COMMENT 'Columna virtual provisional para Salix',
|
`ref` varchar(50) GENERATED ALWAYS AS (`invoiceNumber`) VIRTUAL COMMENT 'Columna virtual provisional para Salix',
|
||||||
|
`observationEditorFk` INT(10) unsigned NULL COMMENT 'Último usuario que ha modificado el campo evaNotes',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
KEY `Id_Proveedor` (`supplierFk`),
|
KEY `Id_Proveedor` (`supplierFk`),
|
||||||
KEY `Fecha` (`dated`),
|
KEY `Fecha` (`dated`),
|
||||||
|
@ -26300,7 +26301,8 @@ CREATE TABLE `entry` (
|
||||||
CONSTRAINT `entry_FK_1` FOREIGN KEY (`typeFk`) REFERENCES `entryType` (`code`) ON UPDATE CASCADE,
|
CONSTRAINT `entry_FK_1` FOREIGN KEY (`typeFk`) REFERENCES `entryType` (`code`) ON UPDATE CASCADE,
|
||||||
CONSTRAINT `entry_ibfk_1` FOREIGN KEY (`supplierFk`) REFERENCES `supplier` (`id`) ON UPDATE CASCADE,
|
CONSTRAINT `entry_ibfk_1` FOREIGN KEY (`supplierFk`) REFERENCES `supplier` (`id`) ON UPDATE CASCADE,
|
||||||
CONSTRAINT `entry_ibfk_6` FOREIGN KEY (`travelFk`) REFERENCES `travel` (`id`) ON UPDATE CASCADE,
|
CONSTRAINT `entry_ibfk_6` FOREIGN KEY (`travelFk`) REFERENCES `travel` (`id`) ON UPDATE CASCADE,
|
||||||
CONSTRAINT `entry_ibfk_7` FOREIGN KEY (`companyFk`) REFERENCES `company` (`id`) ON UPDATE CASCADE
|
CONSTRAINT `entry_ibfk_7` FOREIGN KEY (`companyFk`) REFERENCES `company` (`id`) ON UPDATE CASCADE,
|
||||||
|
CONSTRAINT `entry_observationEditorFk` FOREIGN KEY (`observationEditorFk`) REFERENCES `account`.`user`(`id`) ON UPDATE CASCADE
|
||||||
) ENGINE=InnoDBDEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='InnoDB free: 88064 kB; (`Id_Proveedor`) REFER `vn2008/Provee';
|
) ENGINE=InnoDBDEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='InnoDB free: 88064 kB; (`Id_Proveedor`) REFER `vn2008/Provee';
|
||||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
|
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
|
||||||
|
|
|
@ -82,8 +82,6 @@
|
||||||
}
|
}
|
||||||
&[type=time],
|
&[type=time],
|
||||||
&[type=date] {
|
&[type=date] {
|
||||||
clip-path: inset(0 20px 0 0);
|
|
||||||
|
|
||||||
&::-webkit-inner-spin-button,
|
&::-webkit-inner-spin-button,
|
||||||
&::-webkit-clear-button {
|
&::-webkit-clear-button {
|
||||||
display: none;
|
display: none;
|
||||||
|
@ -99,7 +97,7 @@
|
||||||
}
|
}
|
||||||
&[type=number] {
|
&[type=number] {
|
||||||
-moz-appearance: textfield;
|
-moz-appearance: textfield;
|
||||||
|
|
||||||
&::-webkit-outer-spin-button,
|
&::-webkit-outer-spin-button,
|
||||||
&::-webkit-inner-spin-button {
|
&::-webkit-inner-spin-button {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
|
|
||||||
<vn-dialog
|
<vn-dialog
|
||||||
vn-id="instanceLog">
|
vn-id="instanceLog">
|
||||||
<tpl-body>
|
<tpl-body>
|
||||||
<vn-log
|
<vn-log
|
||||||
|
class="vn-instance-log"
|
||||||
url="{{$ctrl.url}}"
|
url="{{$ctrl.url}}"
|
||||||
origin-id="$ctrl.originId"
|
origin-id="$ctrl.originId"
|
||||||
changed-model="$ctrl.changedModel"
|
changed-model="$ctrl.changedModel"
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
.vn-dialog {
|
vn-log.vn-instance-log {
|
||||||
& > .window:not(:has(.empty-rows)) {
|
vn-card {
|
||||||
width:60%;
|
width: 900px;
|
||||||
vn-log {
|
visibility: hidden;
|
||||||
vn-card {
|
& > * {
|
||||||
visibility: hidden;
|
visibility: visible;
|
||||||
& > * {
|
|
||||||
visibility: visible;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ module.exports = () => {
|
||||||
if (!env || env === 'development')
|
if (!env || env === 'development')
|
||||||
return new Date(Date.UTC(2001, 0, 1, 11));
|
return new Date(Date.UTC(2001, 0, 1, 11));
|
||||||
|
|
||||||
return new Date(Date.UTC());
|
return new Date();
|
||||||
};
|
};
|
||||||
|
|
||||||
Date.vnNew = () => {
|
Date.vnNew = () => {
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
const base64url = require('base64url');
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('confirm', {
|
||||||
|
description: 'Confirms electronic payment transaction',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'Ds_SignatureVersion',
|
||||||
|
type: 'string',
|
||||||
|
required: false,
|
||||||
|
}, {
|
||||||
|
arg: 'Ds_MerchantParameters',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
}, {
|
||||||
|
arg: 'Ds_Signature',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: 'Boolean',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/confirm`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.confirm = async(signatureVersion, merchantParameters, signature) => {
|
||||||
|
const $ = Self.app.models;
|
||||||
|
|
||||||
|
const decodedParams = JSON.parse(
|
||||||
|
base64url.decode(merchantParameters, 'utf8'));
|
||||||
|
const params = {};
|
||||||
|
|
||||||
|
for (const param in decodedParams)
|
||||||
|
params[param] = decodeURIComponent(decodedParams[param]);
|
||||||
|
|
||||||
|
const orderId = params['Ds_Order'];
|
||||||
|
const merchantId = parseInt(params['Ds_MerchantCode']);
|
||||||
|
|
||||||
|
if (!orderId)
|
||||||
|
throw new UserError('Order id not found');
|
||||||
|
if (!merchantId)
|
||||||
|
throw new UserError('Mechant id not found');
|
||||||
|
|
||||||
|
const merchant = await $.TpvMerchant.findById(merchantId, {
|
||||||
|
fields: ['id', 'secretKey']
|
||||||
|
});
|
||||||
|
|
||||||
|
const base64hmac = Self.createSignature(
|
||||||
|
orderId,
|
||||||
|
merchant.secretKey,
|
||||||
|
merchantParameters
|
||||||
|
);
|
||||||
|
|
||||||
|
if (base64hmac !== base64url.toBase64(signature))
|
||||||
|
throw new UserError('Invalid signature');
|
||||||
|
|
||||||
|
await Self.rawSql(
|
||||||
|
'CALL hedera.tpvTransaction_confirm(?, ?, ?, ?, ?, ?)', [
|
||||||
|
params['Ds_Amount'],
|
||||||
|
orderId,
|
||||||
|
merchantId,
|
||||||
|
params['Ds_Currency'],
|
||||||
|
params['Ds_Response'],
|
||||||
|
params['Ds_ErrorCode']
|
||||||
|
]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,39 @@
|
||||||
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('end', {
|
||||||
|
description: 'Ends electronic payment transaction',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'orderId',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
}, {
|
||||||
|
arg: 'status',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
http: {
|
||||||
|
path: `/end`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.end = async(ctx, orderId, status) => {
|
||||||
|
const userId = ctx.req.accessToken.userId;
|
||||||
|
const transaction = await Self.findById(orderId, {
|
||||||
|
fields: ['id', 'clientFk']
|
||||||
|
});
|
||||||
|
|
||||||
|
if (transaction?.clientFk != userId)
|
||||||
|
throw new UserError('Transaction not owned by user');
|
||||||
|
|
||||||
|
await Self.rawSql(
|
||||||
|
'CALL hedera.tpvTransaction_end(?, ?)', [
|
||||||
|
orderId,
|
||||||
|
status
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,85 @@
|
||||||
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('start', {
|
||||||
|
description: 'Starts electronic payment transaction',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'amount',
|
||||||
|
type: 'Number',
|
||||||
|
required: true,
|
||||||
|
}, {
|
||||||
|
arg: 'companyId',
|
||||||
|
type: 'Number',
|
||||||
|
required: false,
|
||||||
|
}, {
|
||||||
|
arg: 'urlOk',
|
||||||
|
type: 'String',
|
||||||
|
required: false,
|
||||||
|
}, {
|
||||||
|
arg: 'urlKo',
|
||||||
|
type: 'String',
|
||||||
|
required: false,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: 'Object',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/start`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.start = async(ctx, amount, companyId, urlOk, urlKo) => {
|
||||||
|
const userId = ctx.req.accessToken.userId;
|
||||||
|
const [[row]] = await Self.rawSql(
|
||||||
|
'CALL hedera.tpvTransaction_start(?, ?, ?)', [
|
||||||
|
amount,
|
||||||
|
companyId,
|
||||||
|
userId
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!row)
|
||||||
|
throw new UserError('Transaction error');
|
||||||
|
|
||||||
|
const orderId = row.transactionId.padStart(12, '0');
|
||||||
|
const merchantUrl = row.merchantUrl ? row.merchantUrl : '';
|
||||||
|
urlOk = urlOk ? urlOk.replace('_transactionId_', orderId) : '';
|
||||||
|
urlKo = urlKo ? urlKo.replace('_transactionId_', orderId) : '';
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
'Ds_Merchant_Amount': amount,
|
||||||
|
'Ds_Merchant_Order': orderId,
|
||||||
|
'Ds_Merchant_MerchantCode': row.merchant,
|
||||||
|
'Ds_Merchant_Currency': row.currency,
|
||||||
|
'Ds_Merchant_TransactionType': row.transactionType,
|
||||||
|
'Ds_Merchant_Terminal': row.terminal,
|
||||||
|
'Ds_Merchant_MerchantURL': merchantUrl,
|
||||||
|
'Ds_Merchant_UrlOK': urlOk,
|
||||||
|
'Ds_Merchant_UrlKO': urlKo
|
||||||
|
};
|
||||||
|
for (const param in params)
|
||||||
|
params[param] = encodeURIComponent(params[param]);
|
||||||
|
|
||||||
|
const json = JSON.stringify(params);
|
||||||
|
const merchantParameters = Buffer.from(json).toString('base64');
|
||||||
|
|
||||||
|
const signature = Self.createSignature(
|
||||||
|
orderId,
|
||||||
|
row.secretKey,
|
||||||
|
merchantParameters
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: row.url,
|
||||||
|
postValues: {
|
||||||
|
'Ds_SignatureVersion': 'HMAC_SHA256_V1',
|
||||||
|
'Ds_MerchantParameters': merchantParameters,
|
||||||
|
'Ds_Signature': signature
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,29 @@
|
||||||
|
const crypto = require('crypto');
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
require('../methods/tpv-transaction/confirm')(Self);
|
||||||
|
require('../methods/tpv-transaction/start')(Self);
|
||||||
|
require('../methods/tpv-transaction/end')(Self);
|
||||||
|
|
||||||
|
Self.createSignature = function(orderId, secretKey, merchantParameters) {
|
||||||
|
secretKey = Buffer.from(secretKey, 'base64');
|
||||||
|
const iv = Buffer.alloc(8, 0);
|
||||||
|
|
||||||
|
const cipher = crypto.createCipheriv('des-ede3-cbc', secretKey, iv);
|
||||||
|
cipher.setAutoPadding(false);
|
||||||
|
const orderKey = Buffer.concat([
|
||||||
|
cipher.update(zeroPad(orderId, 8)),
|
||||||
|
cipher.final()
|
||||||
|
]);
|
||||||
|
|
||||||
|
return crypto.createHmac('sha256', orderKey)
|
||||||
|
.update(merchantParameters)
|
||||||
|
.digest('base64');
|
||||||
|
};
|
||||||
|
|
||||||
|
function zeroPad(buf, blocksize) {
|
||||||
|
const buffer = typeof buf === 'string' ? Buffer.from(buf, 'utf8') : buf;
|
||||||
|
const pad = Buffer.alloc((blocksize - (buffer.length % blocksize)) % blocksize, 0);
|
||||||
|
return Buffer.concat([buffer, pad]);
|
||||||
|
}
|
||||||
|
};
|
|
@ -4,7 +4,6 @@ import Dialog from 'core/components/dialog';
|
||||||
class Controller extends Dialog {
|
class Controller extends Dialog {
|
||||||
constructor($element, $, $transclude, vnReport) {
|
constructor($element, $, $transclude, vnReport) {
|
||||||
super($element, $, $transclude);
|
super($element, $, $transclude);
|
||||||
this.viewReceipt = true;
|
|
||||||
this.vnReport = vnReport;
|
this.vnReport = vnReport;
|
||||||
this.receipt = {};
|
this.receipt = {};
|
||||||
}
|
}
|
||||||
|
@ -61,6 +60,7 @@ class Controller extends Dialog {
|
||||||
const accountingType = value.accountingType;
|
const accountingType = value.accountingType;
|
||||||
|
|
||||||
this.receipt.description = [];
|
this.receipt.description = [];
|
||||||
|
this.viewReceipt = accountingType.code == 'cash';
|
||||||
if (accountingType.receiptDescription != null && accountingType.receiptDescription != '')
|
if (accountingType.receiptDescription != null && accountingType.receiptDescription != '')
|
||||||
this.receipt.description.push(accountingType.receiptDescription);
|
this.receipt.description.push(accountingType.receiptDescription);
|
||||||
if (this.originalDescription)
|
if (this.originalDescription)
|
||||||
|
|
|
@ -75,7 +75,6 @@ describe('Client', () => {
|
||||||
jest.spyOn(controller.vnReport, 'show');
|
jest.spyOn(controller.vnReport, 'show');
|
||||||
|
|
||||||
controller.$params = {id: 1101};
|
controller.$params = {id: 1101};
|
||||||
controller.viewReceipt = false;
|
|
||||||
|
|
||||||
$httpBackend.expect('POST', `Clients/1101/createReceipt`).respond({id: 1});
|
$httpBackend.expect('POST', `Clients/1101/createReceipt`).respond({id: 1});
|
||||||
controller.responseHandler('accept');
|
controller.responseHandler('accept');
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
require('../methods/entry/filter')(Self);
|
require('../methods/entry/filter')(Self);
|
||||||
require('../methods/entry/getEntry')(Self);
|
require('../methods/entry/getEntry')(Self);
|
||||||
|
@ -7,4 +8,41 @@ module.exports = Self => {
|
||||||
require('../methods/entry/importBuysPreview')(Self);
|
require('../methods/entry/importBuysPreview')(Self);
|
||||||
require('../methods/entry/lastItemBuys')(Self);
|
require('../methods/entry/lastItemBuys')(Self);
|
||||||
require('../methods/entry/entryOrderPdf')(Self);
|
require('../methods/entry/entryOrderPdf')(Self);
|
||||||
|
|
||||||
|
Self.observe('before save', async function(ctx, options) {
|
||||||
|
if (ctx.isNewInstance) return;
|
||||||
|
|
||||||
|
const changes = ctx.data || ctx.instance;
|
||||||
|
const orgData = ctx.currentInstance;
|
||||||
|
|
||||||
|
const observation = changes.observation || orgData.observation;
|
||||||
|
const hasChanges = orgData && changes;
|
||||||
|
const observationChanged = hasChanges
|
||||||
|
&& orgData.observation != observation;
|
||||||
|
|
||||||
|
if (observationChanged) {
|
||||||
|
let tx;
|
||||||
|
const myOptions = {};
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const loopbackContext = LoopBackContext.getCurrentContext();
|
||||||
|
const userId = loopbackContext.active.accessToken.userId;
|
||||||
|
const id = changes.id || orgData.id;
|
||||||
|
const entry = await Self.app.models.Entry.findById(id, null, myOptions);
|
||||||
|
await entry.updateAttribute('observationEditorFk', userId, myOptions);
|
||||||
|
if (tx) await tx.commit();
|
||||||
|
} catch (e) {
|
||||||
|
if (tx) await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -77,6 +77,9 @@
|
||||||
"companyFk": {
|
"companyFk": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"required": true
|
"required": true
|
||||||
|
},
|
||||||
|
"observationEditorFk": {
|
||||||
|
"type": "number"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"relations": {
|
"relations": {
|
||||||
|
@ -99,6 +102,11 @@
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "Currency",
|
"model": "Currency",
|
||||||
"foreignKey": "currencyFk"
|
"foreignKey": "currencyFk"
|
||||||
|
},
|
||||||
|
"observationEditor": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Account",
|
||||||
|
"foreignKey": "observationEditorFk"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,11 +94,6 @@
|
||||||
"model": "Supplier",
|
"model": "Supplier",
|
||||||
"foreignKey": "supplierFk"
|
"foreignKey": "supplierFk"
|
||||||
},
|
},
|
||||||
"supplierContact": {
|
|
||||||
"type": "hasMany",
|
|
||||||
"model": "SupplierContact",
|
|
||||||
"foreignKey": "supplierFk"
|
|
||||||
},
|
|
||||||
"currency": {
|
"currency": {
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "Currency",
|
"model": "Currency",
|
||||||
|
|
|
@ -6,13 +6,15 @@ class Controller extends ModuleCard {
|
||||||
const filter = {
|
const filter = {
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
relation: 'supplier'
|
relation: 'supplier',
|
||||||
},
|
|
||||||
{
|
|
||||||
relation: 'supplierContact',
|
|
||||||
scope: {
|
scope: {
|
||||||
where: {
|
include: {
|
||||||
email: {neq: null}
|
relation: 'contacts',
|
||||||
|
scope: {
|
||||||
|
where: {
|
||||||
|
email: {neq: null},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
</vn-item>
|
</vn-item>
|
||||||
<vn-item
|
<vn-item
|
||||||
ng-if="$ctrl.isAgricultural()"
|
ng-if="$ctrl.isAgricultural()"
|
||||||
ng-click="sendPdfConfirmation.show({email: $ctrl.entity.supplierContact[0].email})"
|
ng-click="sendPdfConfirmation.show({email: $ctrl.entity.supplier.contacts[0].email})"
|
||||||
translate>
|
translate>
|
||||||
Send agricultural receipt as PDF
|
Send agricultural receipt as PDF
|
||||||
</vn-item>
|
</vn-item>
|
||||||
|
|
|
@ -72,4 +72,45 @@ describe('upsertFixedPrice()', () => {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it(`should recalculate rate2 if change rate3`, async() => {
|
||||||
|
const tx = await models.FixedPrice.beginTransaction({});
|
||||||
|
|
||||||
|
const tomorrow = new Date(now);
|
||||||
|
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||||
|
|
||||||
|
const rate2 = 2;
|
||||||
|
const firstRate3 = 1;
|
||||||
|
const secondRate3 = 2;
|
||||||
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
const ctx = {args: {
|
||||||
|
id: undefined,
|
||||||
|
itemFk: 1,
|
||||||
|
warehouseFk: 1,
|
||||||
|
started: tomorrow,
|
||||||
|
ended: tomorrow,
|
||||||
|
rate2: rate2,
|
||||||
|
rate3: firstRate3,
|
||||||
|
minPrice: 0,
|
||||||
|
hasMinPrice: false
|
||||||
|
}};
|
||||||
|
|
||||||
|
// create new fixed price
|
||||||
|
const newFixedPrice = await models.FixedPrice.upsertFixedPrice(ctx, options);
|
||||||
|
|
||||||
|
// change rate3 to same fixed price id
|
||||||
|
ctx.args.id = newFixedPrice.id;
|
||||||
|
ctx.args.rate3 = secondRate3;
|
||||||
|
|
||||||
|
const result = await models.FixedPrice.upsertFixedPrice(ctx, options);
|
||||||
|
|
||||||
|
expect(result.rate2).not.toEqual(rate2);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -72,6 +72,16 @@ module.exports = Self => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
delete args.ctx; // removed unwanted data
|
delete args.ctx; // removed unwanted data
|
||||||
|
|
||||||
|
if (args.id) {
|
||||||
|
const beforeFixedPrice = await models.FixedPrice.findById(args.id, {fields: ['rate3']}, myOptions);
|
||||||
|
const [result] = await Self.rawSql(`SELECT vn.priceFixed_getRate2(?, ?) as rate2`,
|
||||||
|
[args.id, args.rate3], myOptions);
|
||||||
|
|
||||||
|
if (beforeFixedPrice.rate3 != args.rate3 && result && result.rate2)
|
||||||
|
args.rate2 = result.rate2;
|
||||||
|
}
|
||||||
|
|
||||||
const fixedPrice = await models.FixedPrice.upsert(args, myOptions);
|
const fixedPrice = await models.FixedPrice.upsert(args, myOptions);
|
||||||
const targetItem = await models.Item.findById(args.itemFk, null, myOptions);
|
const targetItem = await models.Item.findById(args.itemFk, null, myOptions);
|
||||||
|
|
||||||
|
|
|
@ -131,7 +131,7 @@
|
||||||
class="dense"
|
class="dense"
|
||||||
vn-focus
|
vn-focus
|
||||||
ng-model="price.rate3"
|
ng-model="price.rate3"
|
||||||
on-change="$ctrl.upsertPrice(price); $ctrl.recalculateRate2(price)"
|
on-change="$ctrl.upsertPrice(price);"
|
||||||
step="0.01"s>
|
step="0.01"s>
|
||||||
</vn-input-number>
|
</vn-input-number>
|
||||||
</field>
|
</field>
|
||||||
|
|
|
@ -113,24 +113,6 @@ export default class Controller extends Section {
|
||||||
return {[param]: value};
|
return {[param]: value};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
recalculateRate2(price) {
|
|
||||||
if (!price.id || !price.rate3) return;
|
|
||||||
|
|
||||||
const query = 'FixedPrices/getRate2';
|
|
||||||
const params = {
|
|
||||||
fixedPriceId: price.id,
|
|
||||||
rate3: price.rate3
|
|
||||||
};
|
|
||||||
this.$http.get(query, {params})
|
|
||||||
.then(res => {
|
|
||||||
const rate2 = res.data.rate2;
|
|
||||||
if (rate2) {
|
|
||||||
price.rate2 = rate2;
|
|
||||||
this.upsertPrice(price);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngModule.vnComponent('vnFixedPrice', {
|
ngModule.vnComponent('vnFixedPrice', {
|
||||||
|
|
|
@ -85,25 +85,5 @@ describe('fixed price', () => {
|
||||||
expect(controller.$.model.remove).toHaveBeenCalled();
|
expect(controller.$.model.remove).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('recalculateRate2()', () => {
|
|
||||||
it(`should rate2 recalculate`, () => {
|
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
|
||||||
const price = {
|
|
||||||
id: 1,
|
|
||||||
itemFk: 1,
|
|
||||||
rate2: 2,
|
|
||||||
rate3: 2
|
|
||||||
};
|
|
||||||
const response = {rate2: 1};
|
|
||||||
controller.recalculateRate2(price);
|
|
||||||
|
|
||||||
const query = `FixedPrices/getRate2?fixedPriceId=${price.id}&rate3=${price.rate3}`;
|
|
||||||
$httpBackend.expectGET(query).respond(response);
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(price.rate2).toEqual(response.rate2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -26,6 +26,11 @@ module.exports = Self => {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
required: true,
|
required: true,
|
||||||
description: `The old version number`
|
description: `The old version number`
|
||||||
|
}, {
|
||||||
|
arg: 'description',
|
||||||
|
type: 'string',
|
||||||
|
required: false,
|
||||||
|
description: `The description of changes`
|
||||||
}, {
|
}, {
|
||||||
arg: 'unlock',
|
arg: 'unlock',
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
|
@ -42,8 +47,7 @@ module.exports = Self => {
|
||||||
verb: 'POST'
|
verb: 'POST'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Self.upload = async(ctx, options) => {
|
||||||
Self.upload = async(ctx, appName, toVersion, branch, fromVersion, unlock, options) => {
|
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const myOptions = {};
|
const myOptions = {};
|
||||||
const $t = ctx.req.__; // $translate
|
const $t = ctx.req.__; // $translate
|
||||||
|
@ -51,6 +55,12 @@ module.exports = Self => {
|
||||||
const AccessContainer = models.AccessContainer;
|
const AccessContainer = models.AccessContainer;
|
||||||
const fileOptions = {};
|
const fileOptions = {};
|
||||||
let tx;
|
let tx;
|
||||||
|
const appName = ctx.args.appName;
|
||||||
|
const toVersion = ctx.args.toVersion;
|
||||||
|
const branch = ctx.args.branch;
|
||||||
|
const fromVersion = ctx.args.fromVersion;
|
||||||
|
let description = ctx.args.description;
|
||||||
|
const unlock = ctx.args.unlock;
|
||||||
|
|
||||||
if (typeof options == 'object')
|
if (typeof options == 'object')
|
||||||
Object.assign(myOptions, options);
|
Object.assign(myOptions, options);
|
||||||
|
@ -132,13 +142,46 @@ module.exports = Self => {
|
||||||
await fs.symlink(rootRelative, destinationRoot);
|
await fs.symlink(rootRelative, destinationRoot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (description) {
|
||||||
|
let formatDesc;
|
||||||
|
const mainBranches = new Set(['master', 'test', 'dev']);
|
||||||
|
if (mainBranches.has(branch))
|
||||||
|
formatDesc = `> :branch_${branch}: `;
|
||||||
|
else
|
||||||
|
formatDesc = `> :branch: `;
|
||||||
|
|
||||||
|
formatDesc += `*${appName.toUpperCase()}* v.${toVersion} `;
|
||||||
|
|
||||||
|
const oldVersion = await models.MdbVersionTree.findOne({
|
||||||
|
where: {version: fromVersion},
|
||||||
|
fields: ['branchFk']
|
||||||
|
}, myOptions);
|
||||||
|
|
||||||
|
if (branch == oldVersion.branchFk)
|
||||||
|
formatDesc += `[*${branch}*]: `;
|
||||||
|
else
|
||||||
|
formatDesc += `[*${oldVersion.branchFk}* » *${branch}*]: `;
|
||||||
|
|
||||||
|
const params = await models.MdbConfig.findOne(myOptions);
|
||||||
|
const issueTrackerUrl = params.issueTrackerUrl;
|
||||||
|
const issueNumberRegex = params.issueNumberRegex;
|
||||||
|
const chatDestination = params.chatDestination;
|
||||||
|
|
||||||
|
const regex = new RegExp(issueNumberRegex, 'g');
|
||||||
|
formatDesc += description.replace(regex, (match, issueId) => {
|
||||||
|
const newUrl = issueTrackerUrl.replace('{index}', issueId);
|
||||||
|
return `[#${issueId}](${newUrl})`;
|
||||||
|
});
|
||||||
|
|
||||||
|
await models.Chat.send(ctx, chatDestination, formatDesc, myOptions);
|
||||||
|
}
|
||||||
await models.MdbVersionTree.create({
|
await models.MdbVersionTree.create({
|
||||||
app: appName,
|
app: appName,
|
||||||
version: toVersion,
|
version: toVersion,
|
||||||
branchFk: branch,
|
branchFk: branch,
|
||||||
fromVersion,
|
fromVersion,
|
||||||
userFk: userId
|
userFk: userId,
|
||||||
|
description,
|
||||||
}, myOptions);
|
}, myOptions);
|
||||||
|
|
||||||
await models.MdbVersion.upsert({
|
await models.MdbVersion.upsert({
|
||||||
|
|
|
@ -11,6 +11,9 @@
|
||||||
"MdbVersionTree": {
|
"MdbVersionTree": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"MdbConfig": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"AccessContainer": {
|
"AccessContainer": {
|
||||||
"dataSource": "accessStorage"
|
"dataSource": "accessStorage"
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,11 @@
|
||||||
"id": true,
|
"id": true,
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Identifier"
|
"description": "Identifier"
|
||||||
|
},
|
||||||
|
"dsName": {
|
||||||
|
"id": true,
|
||||||
|
"type": "string",
|
||||||
|
"description": "ODBC name"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"name": "MdbConfig",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "mdbConfig"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"id": true
|
||||||
|
},
|
||||||
|
"issueTrackerUrl": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"issueNumberRegex": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"chatDestination": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,6 +23,9 @@
|
||||||
},
|
},
|
||||||
"userFk": {
|
"userFk": {
|
||||||
"type": "number"
|
"type": "number"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"relations": {
|
"relations": {
|
||||||
|
|
|
@ -29,5 +29,12 @@
|
||||||
"pickingOrder": {
|
"pickingOrder": {
|
||||||
"type": "number"
|
"type": "number"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"saleGroup": {
|
||||||
|
"type": "hasMany",
|
||||||
|
"model": "saleGroup",
|
||||||
|
"foreignKey": "parkingFk"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,3 +21,5 @@ companyFk: empresa
|
||||||
agencyModeFk: agencia
|
agencyModeFk: agencia
|
||||||
ticketFk: ticket
|
ticketFk: ticket
|
||||||
mergedTicket: ticket fusionado
|
mergedTicket: ticket fusionado
|
||||||
|
withWarningAccept: aviso negativos
|
||||||
|
isWithoutNegatives: sin negativos
|
||||||
|
|
|
@ -83,6 +83,11 @@ module.exports = Self => {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
description: 'Is whithout negatives',
|
description: 'Is whithout negatives',
|
||||||
required: true
|
required: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'withWarningAccept',
|
||||||
|
type: 'boolean',
|
||||||
|
description: 'Has pressed in confirm message',
|
||||||
}],
|
}],
|
||||||
returns: {
|
returns: {
|
||||||
type: ['object'],
|
type: ['object'],
|
||||||
|
|
|
@ -71,7 +71,7 @@ module.exports = Self => {
|
||||||
}, {
|
}, {
|
||||||
relation: 'address',
|
relation: 'address',
|
||||||
scope: {
|
scope: {
|
||||||
fields: ['street', 'city', 'provinceFk', 'phone', 'mobile', 'postalCode'],
|
fields: ['street', 'city', 'provinceFk', 'phone', 'mobile', 'postalCode', 'isEqualizated'],
|
||||||
include: {
|
include: {
|
||||||
relation: 'province',
|
relation: 'province',
|
||||||
scope: {
|
scope: {
|
||||||
|
|
|
@ -41,6 +41,12 @@
|
||||||
"SaleComponent": {
|
"SaleComponent": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"SaleGroup": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
|
"SaleGroupDetail": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"SaleTracking": {
|
"SaleTracking": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
|
|
@ -75,6 +75,11 @@
|
||||||
"type": "hasOne",
|
"type": "hasOne",
|
||||||
"model": "ItemShelvingSale",
|
"model": "ItemShelvingSale",
|
||||||
"foreignKey": "saleFk"
|
"foreignKey": "saleFk"
|
||||||
|
},
|
||||||
|
"saleGroupDetail": {
|
||||||
|
"type": "hasOne",
|
||||||
|
"model": "SaleGroupDetail",
|
||||||
|
"foreignKey": "saleFk"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"name": "SaleGroup",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "saleGroup"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"id": true,
|
||||||
|
"type": "number",
|
||||||
|
"description": "Identifier"
|
||||||
|
},
|
||||||
|
"parkingFk": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"saleGroupDetail": {
|
||||||
|
"type": "hasMany",
|
||||||
|
"model": "SaleGroupDetail",
|
||||||
|
"foreignKey": "saleGroupFk"
|
||||||
|
},
|
||||||
|
"parking": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Parking",
|
||||||
|
"foreignKey": "parkingFk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"name": "SaleGroupDetail",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "saleGroupDetail"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"id": true,
|
||||||
|
"type": "number",
|
||||||
|
"description": "Identifier"
|
||||||
|
},
|
||||||
|
"saleFk": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"sale": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Sale",
|
||||||
|
"foreignKey": "saleFk"
|
||||||
|
},
|
||||||
|
"saleGroup": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "SaleGroup",
|
||||||
|
"foreignKey": "saleGroupFk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -66,12 +66,15 @@ export default class Controller extends Section {
|
||||||
let today = Date.vnNew();
|
let today = Date.vnNew();
|
||||||
const tomorrow = new Date(today);
|
const tomorrow = new Date(today);
|
||||||
tomorrow.setDate(tomorrow.getDate() + 1);
|
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||||
this.filterParams = {
|
this.$http.get(`UserConfigs/getUserConfig`)
|
||||||
dateFuture: tomorrow,
|
.then(res => {
|
||||||
dateToAdvance: today,
|
this.filterParams = {
|
||||||
warehouseFk: this.vnConfig.warehouseFk
|
dateFuture: tomorrow,
|
||||||
};
|
dateToAdvance: today,
|
||||||
this.$.model.applyFilter(null, this.filterParams);
|
warehouseFk: res.data.warehouseFk
|
||||||
|
};
|
||||||
|
this.$.model.addFilter({}, this.filterParams);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
compareDate(date) {
|
compareDate(date) {
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
</vn-fetched-tags>
|
</vn-fetched-tags>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td ng-if="$ctrl.ticket.sale.haveDifferences" number>
|
<vn-td ng-if="$ctrl.ticket.sale.haveDifferences" number>
|
||||||
<span
|
<span
|
||||||
class="chip"
|
class="chip"
|
||||||
ng-class="{'alert': sale.quantity>sale.movable}">
|
ng-class="{'alert': sale.quantity>sale.movable}">
|
||||||
{{::sale.movable}}
|
{{::sale.movable}}
|
||||||
|
@ -64,14 +64,14 @@
|
||||||
<vn-side-menu side="right">
|
<vn-side-menu side="right">
|
||||||
<div class="vn-pa-md">
|
<div class="vn-pa-md">
|
||||||
<div class="totalBox align-left">
|
<div class="totalBox align-left">
|
||||||
<h6 class="align-center" translate>Total</h6>
|
<h6 class="align-center" translate>Total</h6>
|
||||||
<div> <vn-label translate>Price</vn-label> {{$ctrl.totalPrice | currency: 'EUR': 2}} </div>
|
<div> <vn-label translate>Price</vn-label> {{$ctrl.totalPrice | currency: 'EUR': 2}} </div>
|
||||||
<div> <vn-label translate>New price</vn-label> {{$ctrl.totalNewPrice | currency: 'EUR': 2}} </div>
|
<div> <vn-label translate>New price</vn-label> {{$ctrl.totalNewPrice | currency: 'EUR': 2}} </div>
|
||||||
<div> <vn-label translate>Difference</vn-label> {{$ctrl.totalPriceDifference | currency: 'EUR': 2}} </div>
|
<div> <vn-label translate>Difference</vn-label> {{$ctrl.totalPriceDifference | currency: 'EUR': 2}} </div>
|
||||||
</div>
|
</div>
|
||||||
<vn-card ng-show="::$ctrl.totalPriceDifference">
|
<vn-card ng-show="::$ctrl.totalPriceDifference">
|
||||||
<div class="totalBox align-left" >
|
<div class="totalBox align-left" >
|
||||||
<h6 class="align-center" translate>Charge difference to</h6>
|
<h6 class="align-center" translate>Charge difference to</h6>
|
||||||
<div ng-repeat="action in ticketUpdateActions">
|
<div ng-repeat="action in ticketUpdateActions">
|
||||||
<vn-radio
|
<vn-radio
|
||||||
ng-model="$ctrl.ticket.option"
|
ng-model="$ctrl.ticket.option"
|
||||||
|
@ -82,7 +82,7 @@
|
||||||
</div>
|
</div>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
<div class="totalBox align-left" ng-show="::$ctrl.haveNegatives">
|
<div class="totalBox align-left" ng-show="::$ctrl.haveNegatives">
|
||||||
<vn-check
|
<vn-check
|
||||||
ng-model="$ctrl.ticket.withoutNegatives"
|
ng-model="$ctrl.ticket.withoutNegatives"
|
||||||
label="Create without negatives"
|
label="Create without negatives"
|
||||||
info="Clone this ticket with the changes and only sales availables">
|
info="Clone this ticket with the changes and only sales availables">
|
||||||
|
@ -95,4 +95,10 @@
|
||||||
warehouse-fk="$ctrl.ticket.warehouseFk"
|
warehouse-fk="$ctrl.ticket.warehouseFk"
|
||||||
ticket-fk="$ctrl.ticket.id">
|
ticket-fk="$ctrl.ticket.id">
|
||||||
</vn-item-descriptor-popover>
|
</vn-item-descriptor-popover>
|
||||||
|
<vn-confirm
|
||||||
|
vn-id="negativesConfirm"
|
||||||
|
on-accept="$ctrl.onConfirmAccept()"
|
||||||
|
question="Negatives are going to be generated, are you sure you want to advance all the lines?"
|
||||||
|
message="Edit basic data">
|
||||||
|
</vn-confirm>
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,17 @@ class Controller extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
|
if (this.haveNegatives && !this.ticket.withoutNegatives)
|
||||||
|
this.$.negativesConfirm.show();
|
||||||
|
else this.applyChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
onConfirmAccept() {
|
||||||
|
this.ticket.withWarningAccept = true;
|
||||||
|
this.applyChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
applyChanges() {
|
||||||
if (!this.ticket.option) {
|
if (!this.ticket.option) {
|
||||||
return this.vnApp.showError(
|
return this.vnApp.showError(
|
||||||
this.$t('Choose an option')
|
this.$t('Choose an option')
|
||||||
|
@ -102,7 +113,8 @@ class Controller extends Component {
|
||||||
landed: this.ticket.landed,
|
landed: this.ticket.landed,
|
||||||
isDeleted: this.ticket.isDeleted,
|
isDeleted: this.ticket.isDeleted,
|
||||||
option: parseInt(this.ticket.option),
|
option: parseInt(this.ticket.option),
|
||||||
isWithoutNegatives: this.ticket.withoutNegatives
|
isWithoutNegatives: this.ticket.withoutNegatives,
|
||||||
|
withWarningAccept: this.ticket.withWarningAccept
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$http.post(query, params)
|
this.$http.post(query, params)
|
||||||
|
|
|
@ -8,4 +8,6 @@ New price: Nuevo precio
|
||||||
Price difference: Diferencia de precio
|
Price difference: Diferencia de precio
|
||||||
Create without negatives: Crear sin negativos
|
Create without negatives: Crear sin negativos
|
||||||
Clone this ticket with the changes and only sales availables: Clona este ticket con los cambios y solo las ventas disponibles.
|
Clone this ticket with the changes and only sales availables: Clona este ticket con los cambios y solo las ventas disponibles.
|
||||||
Movable: Movible
|
Movable: Movible
|
||||||
|
Negatives are going to be generated, are you sure you want to advance all the lines?: Se van a generar negativos, ¿seguro que quieres adelantar todas las líneas?
|
||||||
|
Edit basic data: Editar datos básicos
|
||||||
|
|
|
@ -59,12 +59,15 @@ export default class Controller extends Section {
|
||||||
setDefaultFilter() {
|
setDefaultFilter() {
|
||||||
const today = Date.vnNew();
|
const today = Date.vnNew();
|
||||||
|
|
||||||
this.filterParams = {
|
this.$http.get(`UserConfigs/getUserConfig`)
|
||||||
originDated: today,
|
.then(res => {
|
||||||
futureDated: today,
|
this.filterParams = {
|
||||||
warehouseFk: this.vnConfig.warehouseFk
|
originDated: today,
|
||||||
};
|
futureDated: today,
|
||||||
this.$.model.applyFilter(null, this.filterParams);
|
warehouseFk: res.data.warehouseFk
|
||||||
|
};
|
||||||
|
this.$.model.applyFilter(null, this.filterParams);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
compareDate(date) {
|
compareDate(date) {
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
<vn-th field="itemFk" number>Item</vn-th>
|
<vn-th field="itemFk" number>Item</vn-th>
|
||||||
<vn-th field="concept">Description</vn-th>
|
<vn-th field="concept">Description</vn-th>
|
||||||
<vn-th field="quantity" number>Quantity</vn-th>
|
<vn-th field="quantity" number>Quantity</vn-th>
|
||||||
|
<vn-th field="parking" center>Parking</vn-th>
|
||||||
<vn-th></vn-th>
|
<vn-th></vn-th>
|
||||||
</vn-tr>
|
</vn-tr>
|
||||||
</vn-thead>
|
</vn-thead>
|
||||||
|
@ -50,6 +51,7 @@
|
||||||
</vn-fetched-tags>
|
</vn-fetched-tags>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td number>{{::sale.quantity}}</vn-td>
|
<vn-td number>{{::sale.quantity}}</vn-td>
|
||||||
|
<vn-td center>{{::sale.saleGroupDetail.saleGroup.parking.code | dashIfEmpty}}</vn-td>
|
||||||
<vn-td actions>
|
<vn-td actions>
|
||||||
<vn-icon-button
|
<vn-icon-button
|
||||||
vn-click-stop="$ctrl.showSaleTracking(sale)"
|
vn-click-stop="$ctrl.showSaleTracking(sale)"
|
||||||
|
|
|
@ -9,11 +9,30 @@ class Controller extends Section {
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
relation: 'item'
|
relation: 'item'
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
relation: 'saleTracking',
|
relation: 'saleTracking',
|
||||||
scope: {
|
scope: {
|
||||||
fields: ['isChecked']
|
fields: ['isChecked']
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
relation: 'saleGroupDetail',
|
||||||
|
scope: {
|
||||||
|
fields: ['saleGroupFk'],
|
||||||
|
include: {
|
||||||
|
relation: 'saleGroup',
|
||||||
|
scope: {
|
||||||
|
fields: ['parkingFk'],
|
||||||
|
include: {
|
||||||
|
relation: 'parking',
|
||||||
|
scope: {
|
||||||
|
fields: ['code']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
|
@ -105,7 +105,10 @@
|
||||||
</vn-one>
|
</vn-one>
|
||||||
<vn-one class="taxes">
|
<vn-one class="taxes">
|
||||||
<p><vn-label translate>Subtotal</vn-label> {{$ctrl.summary.totalWithoutVat | currency: 'EUR':2}}</p>
|
<p><vn-label translate>Subtotal</vn-label> {{$ctrl.summary.totalWithoutVat | currency: 'EUR':2}}</p>
|
||||||
<p><vn-label translate>VAT</vn-label> {{$ctrl.summary.totalWithVat - $ctrl.summary.totalWithoutVat | currency: 'EUR':2}}</p>
|
<p><vn-label translate ng-if="$ctrl.summary.address.isEqualizated">VAT + RE</vn-label>
|
||||||
|
<vn-label translate ng-if="!$ctrl.summary.address.isEqualizated">VAT</vn-label>
|
||||||
|
{{$ctrl.summary.totalWithVat - $ctrl.summary.totalWithoutVat | currency: 'EUR':2}}
|
||||||
|
</p>
|
||||||
<p><vn-label><strong>Total</strong></vn-label> <strong>{{$ctrl.summary.totalWithVat | currency: 'EUR':2}}</strong></p>
|
<p><vn-label><strong>Total</strong></vn-label> <strong>{{$ctrl.summary.totalWithVat | currency: 'EUR':2}}</strong></p>
|
||||||
</vn-one>
|
</vn-one>
|
||||||
<vn-auto name="sales">
|
<vn-auto name="sales">
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
{
|
{
|
||||||
"name": "salix-back",
|
"name": "salix-back",
|
||||||
"version": "9.0.0",
|
"version": "23.02.03",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "salix-back",
|
"name": "salix-back",
|
||||||
"version": "9.0.0",
|
"version": "23.02.03",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.2.2",
|
"axios": "^1.2.2",
|
||||||
|
"base64url": "^3.0.1",
|
||||||
"bcrypt": "^5.0.1",
|
"bcrypt": "^5.0.1",
|
||||||
"bmp-js": "^0.1.0",
|
"bmp-js": "^0.1.0",
|
||||||
"compression": "^1.7.3",
|
"compression": "^1.7.3",
|
||||||
|
@ -4200,6 +4201,14 @@
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/base64url": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/batch": {
|
"node_modules/batch": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
@ -29057,6 +29066,11 @@
|
||||||
"base64-js": {
|
"base64-js": {
|
||||||
"version": "1.0.2"
|
"version": "1.0.2"
|
||||||
},
|
},
|
||||||
|
"base64url": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A=="
|
||||||
|
},
|
||||||
"batch": {
|
"batch": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"dev": true
|
"dev": true
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.2.2",
|
"axios": "^1.2.2",
|
||||||
|
"base64url": "^3.0.1",
|
||||||
"bcrypt": "^5.0.1",
|
"bcrypt": "^5.0.1",
|
||||||
"bmp-js": "^0.1.0",
|
"bmp-js": "^0.1.0",
|
||||||
"compression": "^1.7.3",
|
"compression": "^1.7.3",
|
||||||
|
|
|
@ -8,5 +8,4 @@ SELECT
|
||||||
r.payed
|
r.payed
|
||||||
FROM client c
|
FROM client c
|
||||||
JOIN receipt r ON r.clientFk = c.id
|
JOIN receipt r ON r.clientFk = c.id
|
||||||
JOIN supplier s ON c.fi = s.nif
|
WHERE r.id = ?
|
||||||
WHERE r.id = ?
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<td id="outline" class="ellipsize">{{labelData.code == 'V' ? (labelData.size || 0) + 'cm' : (labelData.volume || 0) + 'm³'}}</td>
|
<td id="outline" class="ellipsize">{{labelData.code == 'V' ? (labelData.size || 0) + 'cm' : (labelData.volume || 0) + 'm³'}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><div id="agencyDescripton" class="ellipsize">{{labelData.agencyDescription ? labelData.agencyDescription.toUpperCase() : '---'}}</div></td>
|
<td><div id="agencyDescripton" class="ellipsize">{{getAgencyDescripton(labelData)}}</div></td>
|
||||||
<td id="bold">{{labelData.lineCount || 0}}</td>
|
<td id="bold">{{labelData.lineCount || 0}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -59,5 +59,17 @@ module.exports = {
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
},
|
},
|
||||||
|
getAgencyDescripton(labelData) {
|
||||||
|
let value;
|
||||||
|
if (labelData.agencyDescription)
|
||||||
|
value = labelData.agencyDescription.toUpperCase().substring(0, 11);
|
||||||
|
else
|
||||||
|
value = '---';
|
||||||
|
|
||||||
|
if (labelData.routeFk)
|
||||||
|
value = `${value} [${labelData.routeFk.toString().substring(0, 3)}]`;
|
||||||
|
|
||||||
|
return value;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,37 +1,38 @@
|
||||||
SELECT c.itemPackingTypeFk code,
|
SELECT c.itemPackingTypeFk code,
|
||||||
tc.collectionFk,
|
tc.collectionFk,
|
||||||
SUBSTRING('ABCDEFGH', tc.wagon, 1) wagon,
|
SUBSTRING('ABCDEFGH', tc.wagon, 1) wagon,
|
||||||
tc.`level`,
|
tc.`level`,
|
||||||
t.id ticketFk,
|
t.id ticketFk,
|
||||||
COALESCE(et.description, zo.name, am.name) agencyDescription,
|
COALESCE(et.description, zo.name, am.name) agencyDescription,
|
||||||
cc.code color,
|
cc.code color,
|
||||||
t.clientFk,
|
t.clientFk,
|
||||||
CAST(SUM(sv.volume) AS DECIMAL(5, 2)) volume,
|
CAST(SUM(sv.volume) AS DECIMAL(5, 2)) volume,
|
||||||
MAX(i.`size`) `size`,
|
MAX(i.`size`) `size`,
|
||||||
w.code workerCode,
|
w.code workerCode,
|
||||||
TIME_FORMAT(t.shipped, '%H:%i') shippedHour,
|
TIME_FORMAT(t.shipped, '%H:%i') shippedHour,
|
||||||
TIME_FORMAT(zo.`hour`, '%H:%i') zoneHour,
|
TIME_FORMAT(zo.`hour`, '%H:%i') zoneHour,
|
||||||
DATE_FORMAT(t.shipped, '%d/%m/%y') shipped,
|
DATE_FORMAT(t.shipped, '%d/%m/%y') shipped,
|
||||||
tt.labelCount,
|
tt.labelCount,
|
||||||
t.nickName,
|
t.nickName,
|
||||||
COUNT(*) lineCount
|
COUNT(*) lineCount,
|
||||||
FROM vn.ticket t
|
rm.routeFk
|
||||||
JOIN vn.ticketCollection tc ON tc.ticketFk = t.id
|
FROM vn.ticket t
|
||||||
JOIN vn.collection c ON c.id = tc.collectionFk
|
JOIN vn.ticketCollection tc ON tc.ticketFk = t.id
|
||||||
LEFT JOIN vn.collectionColors cc ON cc.shelve = tc.`level`
|
JOIN vn.collection c ON c.id = tc.collectionFk
|
||||||
AND cc.wagon = tc.wagon
|
LEFT JOIN vn.collectionColors cc ON cc.shelve = tc.`level`
|
||||||
AND cc.trainFk = c.trainFk
|
AND cc.wagon = tc.wagon
|
||||||
JOIN vn.sale s ON s.ticketFk = t.id
|
AND cc.trainFk = c.trainFk
|
||||||
LEFT JOIN vn.saleVolume sv ON sv.saleFk = s.id
|
JOIN vn.sale s ON s.ticketFk = t.id
|
||||||
JOIN vn.item i ON i.id = s.itemFk
|
LEFT JOIN vn.saleVolume sv ON sv.saleFk = s.id
|
||||||
JOIN vn.itemType it ON it.id = i.typeFk
|
JOIN vn.item i ON i.id = s.itemFk
|
||||||
JOIN vn.itemCategory ic ON ic.id = it.categoryFk
|
JOIN vn.itemType it ON it.id = i.typeFk
|
||||||
JOIN vn.worker w ON w.id = c.workerFk
|
JOIN vn.itemCategory ic ON ic.id = it.categoryFk
|
||||||
JOIN vn.agencyMode am ON am.id = t.agencyModeFk
|
JOIN vn.worker w ON w.id = c.workerFk
|
||||||
LEFT JOIN vn.ticketTrolley tt ON tt.ticket = t.id
|
JOIN vn.agencyMode am ON am.id = t.agencyModeFk
|
||||||
LEFT JOIN vn.`zone` zo ON t.zoneFk = zo.id
|
LEFT JOIN vn.ticketTrolley tt ON tt.ticket = t.id
|
||||||
LEFT JOIN vn.routesMonitor rm ON rm.routeFk = t.routeFk
|
LEFT JOIN vn.`zone` zo ON t.zoneFk = zo.id
|
||||||
LEFT JOIN vn.expeditionTruck et ON et.id = rm.expeditionTruckFk
|
LEFT JOIN vn.routesMonitor rm ON rm.routeFk = t.routeFk
|
||||||
WHERE t.id IN (?)
|
LEFT JOIN vn.expeditionTruck et ON et.id = rm.expeditionTruckFk
|
||||||
GROUP BY t.id
|
WHERE t.id IN (?)
|
||||||
ORDER BY cc.`code`;
|
GROUP BY t.id
|
||||||
|
ORDER BY cc.`code`;
|
Loading…
Reference in New Issue