7953-devToTest_2438 #2942
|
@ -29,18 +29,8 @@ module.exports = Self => {
|
||||||
return token;
|
return token;
|
||||||
|
|
||||||
// Schedule to remove current token
|
// Schedule to remove current token
|
||||||
setTimeout(async() => {
|
setTimeout(() => {
|
||||||
let exists;
|
Self.logout(token.id);
|
||||||
try {
|
|
||||||
exists = await models.AccessToken.findById(token.id);
|
|
||||||
exists && await Self.logout(token.id);
|
|
||||||
} catch (error) {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.error(error);
|
|
||||||
const body = {error: error.message, now: Date.now(), userId: token?.userId ?? null, exists};
|
|
||||||
await handleError(body);
|
|
||||||
throw new Error(error);
|
|
||||||
}
|
|
||||||
}, courtesyTime * 1000);
|
}, courtesyTime * 1000);
|
||||||
|
|
||||||
// Get scopes
|
// Get scopes
|
||||||
|
@ -53,14 +43,20 @@ module.exports = Self => {
|
||||||
|
|
||||||
return {id: accessToken.id, ttl: accessToken.ttl};
|
return {id: accessToken.id, ttl: accessToken.ttl};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const body = {error: error.message, now: Date.now(), userId: token?.userId ?? null, createTokenOptions, isNotExceeded};
|
const body = {
|
||||||
await handleError(body);
|
error: error.message,
|
||||||
|
userId: token?.userId ?? null,
|
||||||
|
token: token?.id,
|
||||||
|
scopes: token?.scopes,
|
||||||
|
createTokenOptions,
|
||||||
|
isNotExceeded
|
||||||
|
};
|
||||||
|
await handleError(JSON.stringify(body));
|
||||||
throw new Error(error);
|
throw new Error(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
async function handleError(body, tag = 'renewToken') {
|
async function handleError(body) {
|
||||||
body = JSON.stringify(body);
|
await models.Application.rawSql('CALL util.debugAdd(?,?);', ['renewToken', body]);
|
||||||
await models.Application.rawSql('CALL util.debugAdd(?,?);', [tag, body]);
|
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1455,6 +1455,11 @@ INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','accountingType','gu
|
||||||
INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','bankPolicyDetail','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select','');
|
INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','bankPolicyDetail','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select','');
|
||||||
INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','bankPolicyReview','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select','');
|
INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','bankPolicyReview','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select','');
|
||||||
INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','bankPolicy','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select','');
|
INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','bankPolicy','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select','');
|
||||||
|
INSERT IGNORE INTO `tables_priv` VALUES ('','edi','hedera-web','imapMultiConfig','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select','');
|
||||||
|
INSERT IGNORE INTO `tables_priv` VALUES ('','hedera','salesAssistant','orderConfig','root@localhost','0000-00-00 00:00:00','Select','');
|
||||||
|
INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','itemEntryOut','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select','');
|
||||||
|
INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','itemEntryIn','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select','');
|
||||||
|
INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','itemShelvingSale','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select','');
|
||||||
/*!40000 ALTER TABLE `tables_priv` ENABLE KEYS */;
|
/*!40000 ALTER TABLE `tables_priv` ENABLE KEYS */;
|
||||||
|
|
||||||
/*!40000 ALTER TABLE `columns_priv` DISABLE KEYS */;
|
/*!40000 ALTER TABLE `columns_priv` DISABLE KEYS */;
|
||||||
|
@ -2160,9 +2165,7 @@ INSERT IGNORE INTO `procs_priv` VALUES ('','vn','buyer','buy_recalcPricesByAwb'
|
||||||
INSERT IGNORE INTO `procs_priv` VALUES ('','vn','buyer','buy_recalcPricesByEntry','PROCEDURE','jenkins@db-proxy2.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00');
|
INSERT IGNORE INTO `procs_priv` VALUES ('','vn','buyer','buy_recalcPricesByEntry','PROCEDURE','jenkins@db-proxy2.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00');
|
||||||
INSERT IGNORE INTO `procs_priv` VALUES ('','util','hr','accountNumberToIban','FUNCTION','jenkins@db-proxy1.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00');
|
INSERT IGNORE INTO `procs_priv` VALUES ('','util','hr','accountNumberToIban','FUNCTION','jenkins@db-proxy1.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00');
|
||||||
INSERT IGNORE INTO `procs_priv` VALUES ('','util','financial','accountNumberToIban','FUNCTION','jenkins@db-proxy1.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00');
|
INSERT IGNORE INTO `procs_priv` VALUES ('','util','financial','accountNumberToIban','FUNCTION','jenkins@db-proxy1.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00');
|
||||||
INSERT IGNORE INTO `procs_priv` VALUES ('','vn','administrative','supplier_statement','PROCEDURE','jenkins@db-proxy1.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00');
|
INSERT IGNORE INTO `procs_priv` VALUES ('','vn','buyer','supplier_statementWithEntries','PROCEDURE','guillermo@db-proxy1.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00');
|
||||||
INSERT IGNORE INTO `procs_priv` VALUES ('','vn','buyer','supplier_statement','PROCEDURE','jenkins@db-proxy1.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00');
|
|
||||||
INSERT IGNORE INTO `procs_priv` VALUES ('','vn','hrBoss','supplier_statement','PROCEDURE','jenkins@db-proxy1.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00');
|
|
||||||
INSERT IGNORE INTO `procs_priv` VALUES ('','vn','adminBoss','XDiario_check','PROCEDURE','jenkins@db-proxy1.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00');
|
INSERT IGNORE INTO `procs_priv` VALUES ('','vn','adminBoss','XDiario_check','PROCEDURE','jenkins@db-proxy1.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00');
|
||||||
INSERT IGNORE INTO `procs_priv` VALUES ('','vn','buyer','travel_getDetailFromContinent','PROCEDURE','jenkins@db-proxy1.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00');
|
INSERT IGNORE INTO `procs_priv` VALUES ('','vn','buyer','travel_getDetailFromContinent','PROCEDURE','jenkins@db-proxy1.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00');
|
||||||
INSERT IGNORE INTO `procs_priv` VALUES ('','vn','claimManager','entry_getTransfer','PROCEDURE','jenkins@db-proxy1.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00');
|
INSERT IGNORE INTO `procs_priv` VALUES ('','vn','claimManager','entry_getTransfer','PROCEDURE','jenkins@db-proxy1.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00');
|
||||||
|
@ -2193,6 +2196,8 @@ INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','itemShelvingSale_
|
||||||
INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','sectorCollection_getMyPartial','PROCEDURE','carlosap@db-proxy1.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00');
|
INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','sectorCollection_getMyPartial','PROCEDURE','carlosap@db-proxy1.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00');
|
||||||
INSERT IGNORE INTO `procs_priv` VALUES ('','vn','grafana-write','item_ValuateInventory','PROCEDURE','guillermo@db-proxy1.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00');
|
INSERT IGNORE INTO `procs_priv` VALUES ('','vn','grafana-write','item_ValuateInventory','PROCEDURE','guillermo@db-proxy1.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00');
|
||||||
INSERT IGNORE INTO `procs_priv` VALUES ('','vn','guest','ticketCalculatePurge','PROCEDURE','jenkins@db-proxy2.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00');
|
INSERT IGNORE INTO `procs_priv` VALUES ('','vn','guest','ticketCalculatePurge','PROCEDURE','jenkins@db-proxy2.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00');
|
||||||
|
INSERT IGNORE INTO `procs_priv` VALUES ('','vn','buyer','buy_getUltimate','PROCEDURE','guillermo@db-proxy2.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00');
|
||||||
|
INSERT IGNORE INTO `procs_priv` VALUES ('','vn','cooler','buy_getUltimate','PROCEDURE','guillermo@db-proxy2.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00');
|
||||||
/*!40000 ALTER TABLE `procs_priv` ENABLE KEYS */;
|
/*!40000 ALTER TABLE `procs_priv` ENABLE KEYS */;
|
||||||
|
|
||||||
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||||
|
@ -2237,7 +2242,7 @@ INSERT IGNORE INTO `global_priv` VALUES ('','grafana-write','{\"access\":0,\"ve
|
||||||
INSERT IGNORE INTO `global_priv` VALUES ('','greenhouseBoss','{\"access\":0,\"version_id\":101106,\"is_role\":true}');
|
INSERT IGNORE INTO `global_priv` VALUES ('','greenhouseBoss','{\"access\":0,\"version_id\":101106,\"is_role\":true}');
|
||||||
INSERT IGNORE INTO `global_priv` VALUES ('','guest','{\"access\": 0, \"max_questions\": 40000, \"max_updates\": 1000, \"max_connections\": 150000, \"max_user_connections\": 200, \"max_statement_time\": 0.000000, \"is_role\": true, \"version_id\": 101106}');
|
INSERT IGNORE INTO `global_priv` VALUES ('','guest','{\"access\": 0, \"max_questions\": 40000, \"max_updates\": 1000, \"max_connections\": 150000, \"max_user_connections\": 200, \"max_statement_time\": 0.000000, \"is_role\": true, \"version_id\": 101106}');
|
||||||
INSERT IGNORE INTO `global_priv` VALUES ('','handmadeBoss','{\"access\":0,\"version_id\":101106,\"is_role\":true}');
|
INSERT IGNORE INTO `global_priv` VALUES ('','handmadeBoss','{\"access\":0,\"version_id\":101106,\"is_role\":true}');
|
||||||
INSERT IGNORE INTO `global_priv` VALUES ('','hedera-web','{\"access\":0,\"version_id\":100707,\"is_role\":true}');
|
INSERT IGNORE INTO `global_priv` VALUES ('','hedera-web','{\"access\":0,\"version_id\":101106,\"is_role\":true}');
|
||||||
INSERT IGNORE INTO `global_priv` VALUES ('','hr','{\"access\": 0, \"is_role\": true, \"version_id\": 101106}');
|
INSERT IGNORE INTO `global_priv` VALUES ('','hr','{\"access\": 0, \"is_role\": true, \"version_id\": 101106}');
|
||||||
INSERT IGNORE INTO `global_priv` VALUES ('','hrBoss','{\"access\":0,\"version_id\":101106,\"is_role\":true}');
|
INSERT IGNORE INTO `global_priv` VALUES ('','hrBoss','{\"access\":0,\"version_id\":101106,\"is_role\":true}');
|
||||||
INSERT IGNORE INTO `global_priv` VALUES ('','invoicing','{\"access\":0,\"version_id\":100707,\"is_role\":true}');
|
INSERT IGNORE INTO `global_priv` VALUES ('','invoicing','{\"access\":0,\"version_id\":100707,\"is_role\":true}');
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1423,6 +1423,70 @@ DELIMITER ;
|
||||||
--
|
--
|
||||||
|
|
||||||
USE `salix`;
|
USE `salix`;
|
||||||
|
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
|
||||||
|
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
|
||||||
|
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
|
||||||
|
/*!50003 SET character_set_client = utf8mb4 */ ;
|
||||||
|
/*!50003 SET character_set_results = utf8mb4 */ ;
|
||||||
|
/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ;
|
||||||
|
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
|
||||||
|
/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ;
|
||||||
|
DELIMITER ;;
|
||||||
|
/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `salix`.`ACL_beforeInsert`
|
||||||
|
BEFORE INSERT ON `ACL`
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
SET NEW.editorFk = account.myUser_getId();
|
||||||
|
END */;;
|
||||||
|
DELIMITER ;
|
||||||
|
/*!50003 SET sql_mode = @saved_sql_mode */ ;
|
||||||
|
/*!50003 SET character_set_client = @saved_cs_client */ ;
|
||||||
|
/*!50003 SET character_set_results = @saved_cs_results */ ;
|
||||||
|
/*!50003 SET collation_connection = @saved_col_connection */ ;
|
||||||
|
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
|
||||||
|
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
|
||||||
|
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
|
||||||
|
/*!50003 SET character_set_client = utf8mb4 */ ;
|
||||||
|
/*!50003 SET character_set_results = utf8mb4 */ ;
|
||||||
|
/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ;
|
||||||
|
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
|
||||||
|
/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ;
|
||||||
|
DELIMITER ;;
|
||||||
|
/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `salix`.`ACL_beforeUpdate`
|
||||||
|
BEFORE UPDATE ON `ACL`
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
SET NEW.editorFk = account.myUser_getId();
|
||||||
|
END */;;
|
||||||
|
DELIMITER ;
|
||||||
|
/*!50003 SET sql_mode = @saved_sql_mode */ ;
|
||||||
|
/*!50003 SET character_set_client = @saved_cs_client */ ;
|
||||||
|
/*!50003 SET character_set_results = @saved_cs_results */ ;
|
||||||
|
/*!50003 SET collation_connection = @saved_col_connection */ ;
|
||||||
|
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
|
||||||
|
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
|
||||||
|
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
|
||||||
|
/*!50003 SET character_set_client = utf8mb4 */ ;
|
||||||
|
/*!50003 SET character_set_results = utf8mb4 */ ;
|
||||||
|
/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ;
|
||||||
|
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
|
||||||
|
/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ;
|
||||||
|
DELIMITER ;;
|
||||||
|
/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `salix`.`ACL_afterDelete`
|
||||||
|
AFTER DELETE ON `ACL`
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO ACLLog
|
||||||
|
SET `action` = 'delete',
|
||||||
|
`changedModel` = 'Acl',
|
||||||
|
`changedModelId` = OLD.id,
|
||||||
|
`userFk` = account.myUser_getId();
|
||||||
|
END */;;
|
||||||
|
DELIMITER ;
|
||||||
|
/*!50003 SET sql_mode = @saved_sql_mode */ ;
|
||||||
|
/*!50003 SET character_set_client = @saved_cs_client */ ;
|
||||||
|
/*!50003 SET character_set_results = @saved_cs_results */ ;
|
||||||
|
/*!50003 SET collation_connection = @saved_col_connection */ ;
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Current Database: `srt`
|
-- Current Database: `srt`
|
||||||
|
@ -9220,7 +9284,13 @@ BEGIN
|
||||||
SET NEW.editorFk = account.myUser_getId();
|
SET NEW.editorFk = account.myUser_getId();
|
||||||
|
|
||||||
IF NOT (NEW.routeFk <=> OLD.routeFk) THEN
|
IF NOT (NEW.routeFk <=> OLD.routeFk) THEN
|
||||||
IF NEW.isSigned THEN
|
IF NEW.isSigned AND NOT (
|
||||||
|
SELECT (COUNT(s.id) = COUNT(cb.saleFk)
|
||||||
|
AND SUM(s.quantity) = SUM(cb.quantity))
|
||||||
|
FROM sale s
|
||||||
|
LEFT JOIN claimBeginning cb ON cb.saleFk = s.id
|
||||||
|
WHERE s.ticketFk = NEW.id
|
||||||
|
) THEN
|
||||||
CALL util.throw('A signed ticket cannot be rerouted');
|
CALL util.throw('A signed ticket cannot be rerouted');
|
||||||
END IF;
|
END IF;
|
||||||
INSERT IGNORE INTO routeRecalc(routeFk)
|
INSERT IGNORE INTO routeRecalc(routeFk)
|
||||||
|
@ -11142,4 +11212,4 @@ USE `vn2008`;
|
||||||
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||||
|
|
||||||
-- Dump completed on 2024-08-06 6:03:19
|
-- Dump completed on 2024-08-20 7:45:23
|
||||||
|
|
|
@ -412,7 +412,7 @@ INSERT INTO `vn`.`clientManaCache`(`clientFk`, `mana`, `dated`)
|
||||||
(1103, 0, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH)),
|
(1103, 0, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH)),
|
||||||
(1104, -30, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH));
|
(1104, -30, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH));
|
||||||
|
|
||||||
INSERT INTO `vn`.`mandateType`(`id`, `name`)
|
INSERT INTO `vn`.`mandateType`(`id`, `code`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 'B2B'),
|
(1, 'B2B'),
|
||||||
(2, 'CORE'),
|
(2, 'CORE'),
|
||||||
|
@ -632,7 +632,7 @@ INSERT INTO `vn`.`invoiceOutSerial` (`code`, `description`, `isTaxed`, `taxAreaF
|
||||||
('A', 'Global nacional', 1, 'NATIONAL', 0, 'global'),
|
('A', 'Global nacional', 1, 'NATIONAL', 0, 'global'),
|
||||||
('T', 'Española rapida', 1, 'NATIONAL', 0, 'quick'),
|
('T', 'Española rapida', 1, 'NATIONAL', 0, 'quick'),
|
||||||
('V', 'Intracomunitaria global', 0, 'CEE', 1, 'global'),
|
('V', 'Intracomunitaria global', 0, 'CEE', 1, 'global'),
|
||||||
('M', 'Múltiple nacional', 1, 'NATIONAL', 0, 'quick'),
|
('M', 'Múltiple nacional', 1, 'NATIONAL', 0, 'multiple'),
|
||||||
('R', 'Rectificativa', 1, 'NATIONAL', 0, NULL),
|
('R', 'Rectificativa', 1, 'NATIONAL', 0, NULL),
|
||||||
('E', 'Exportación rápida', 0, 'WORLD', 0, 'quick');
|
('E', 'Exportación rápida', 0, 'WORLD', 0, 'quick');
|
||||||
|
|
||||||
|
@ -3945,11 +3945,11 @@ VALUES
|
||||||
(35, 'ES12346B12345679', 3, 241);
|
(35, 'ES12346B12345679', 3, 241);
|
||||||
|
|
||||||
INSERT INTO vn.accountDetailType
|
INSERT INTO vn.accountDetailType
|
||||||
(id, description)
|
(id, description, code)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 'IBAN'),
|
(1, 'IBAN', 'iban'),
|
||||||
(2, 'SWIFT'),
|
(2, 'SWIFT', 'swift'),
|
||||||
(3, 'Referencia Remesas'),
|
(3, 'Referencia Remesas', 'remRef'),
|
||||||
(4, 'Referencia Transferencias'),
|
(4, 'Referencia Transferencias', 'trnRef'),
|
||||||
(5, 'Referencia Nominas'),
|
(5, 'Referencia Nominas', 'payRef'),
|
||||||
(6, 'ABA');
|
(6, 'ABA', 'aba');
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
DELIMITER $$
|
DELIMITER $$
|
||||||
CREATE OR REPLACE DEFINER=`root`@`localhost` EVENT `srt`.`moving_clean`
|
CREATE OR REPLACE DEFINER=`root`@`localhost` EVENT `srt`.`moving_clean`
|
||||||
ON SCHEDULE EVERY 5 MINUTE
|
ON SCHEDULE EVERY 15 MINUTE
|
||||||
STARTS '2022-01-21 00:00:00.000'
|
STARTS '2022-01-21 00:00:00.000'
|
||||||
ON COMPLETION PRESERVE
|
ON COMPLETION PRESERVE
|
||||||
ENABLE
|
ENABLE
|
||||||
COMMENT 'Llama a srt.moving_clean para que elimine y notifique de registr'
|
COMMENT 'Llama a srt.moving_clean para que elimine y notifique de registr'
|
||||||
DO BEGIN
|
DO CALL srt.moving_clean()$$
|
||||||
|
|
||||||
CALL srt.moving_clean();
|
|
||||||
|
|
||||||
END$$
|
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
|
@ -3,61 +3,69 @@ CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `srt`.`moving_clean`()
|
||||||
BEGIN
|
BEGIN
|
||||||
/**
|
/**
|
||||||
* Elimina movimientos por inactividad
|
* Elimina movimientos por inactividad
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
DECLARE vExpeditionFk INT;
|
DECLARE vExpeditionFk INT;
|
||||||
DECLARE vBufferToFk INT;
|
|
||||||
DECLARE vBufferFromFk INT;
|
DECLARE vBufferFromFk INT;
|
||||||
DECLARE done BOOL DEFAULT FALSE;
|
DECLARE vStateOutFk INT
|
||||||
|
DEFAULT (SELECT id FROM expeditionState WHERE `description` = 'OUT');
|
||||||
DECLARE cur CURSOR FOR
|
DECLARE vDone BOOL;
|
||||||
SELECT m.expeditionFk, m.bufferToFk, m.bufferFromFk
|
DECLARE vSorter CURSOR FOR
|
||||||
FROM srt.moving m
|
SELECT m.expeditionFk, m.bufferFromFk
|
||||||
JOIN srt.config c
|
FROM moving m
|
||||||
JOIN (SELECT bufferFk, SUM(isActive) hasBox
|
JOIN (
|
||||||
FROM srt.photocell
|
SELECT bufferFk, SUM(isActive) hasBox
|
||||||
GROUP BY bufferFk) sub ON sub.bufferFk = m.bufferFromFk
|
FROM photocell
|
||||||
WHERE m.created < TIMESTAMPADD(MINUTE, - c.movingMaxLife , util.VN_NOW())
|
GROUP BY bufferFk
|
||||||
|
) sub ON sub.bufferFk = m.bufferFromFk
|
||||||
|
WHERE m.created < (util.VN_NOW() - INTERVAL (SELECT movingMaxLife FROM config) MINUTE)
|
||||||
AND NOT sub.hasBox;
|
AND NOT sub.hasBox;
|
||||||
|
|
||||||
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
|
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
||||||
|
|
||||||
OPEN cur;
|
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||||
|
BEGIN
|
||||||
|
ROLLBACK;
|
||||||
|
RESIGNAL;
|
||||||
|
END;
|
||||||
|
|
||||||
bucle: LOOP
|
OPEN vSorter;
|
||||||
|
l: LOOP
|
||||||
|
SET vDone = FALSE;
|
||||||
|
FETCH vSorter INTO vExpeditionFk, vBufferFromFk;
|
||||||
|
|
||||||
FETCH cur INTO vExpeditionFk, vBufferToFk, vBufferFromFk;
|
IF vDone THEN
|
||||||
|
LEAVE l;
|
||||||
IF done THEN
|
|
||||||
LEAVE bucle;
|
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
DELETE FROM srt.moving
|
START TRANSACTION;
|
||||||
|
|
||||||
|
SELECT id
|
||||||
|
FROM moving
|
||||||
|
WHERE expeditionFk = vExpeditionFk
|
||||||
|
FOR UPDATE;
|
||||||
|
|
||||||
|
DELETE FROM moving
|
||||||
WHERE expeditionFk = vExpeditionFk;
|
WHERE expeditionFk = vExpeditionFk;
|
||||||
|
|
||||||
UPDATE srt.expedition e
|
SELECT id
|
||||||
JOIN srt.expeditionState es ON es.description = 'OUT'
|
FROM expedition
|
||||||
SET
|
WHERE id = vExpeditionFk
|
||||||
bufferFk = NULL,
|
OR (bufferFk = vBufferFromFk AND `position` > 0)
|
||||||
|
FOR UPDATE;
|
||||||
|
|
||||||
|
UPDATE expedition
|
||||||
|
SET bufferFk = NULL,
|
||||||
`position` = NULL,
|
`position` = NULL,
|
||||||
stateFk = es.id
|
stateFk = vStateOutFk
|
||||||
WHERE e.id = vExpeditionFk;
|
WHERE id = vExpeditionFk;
|
||||||
|
|
||||||
UPDATE srt.expedition e
|
UPDATE expedition
|
||||||
SET e.`position` = e.`position` - 1
|
SET `position` = `position` - 1
|
||||||
WHERE e.bufferFk = vBufferFromFk
|
WHERE bufferFk = vBufferFromFk
|
||||||
AND e.`position` > 0;
|
AND `position` > 0;
|
||||||
|
|
||||||
CALL vn.mail_insert(
|
|
||||||
'pako@verdnatura.es, carles@verdnatura.es',
|
|
||||||
NULL,
|
|
||||||
CONCAT('Moving_clean. Expedition: ', vExpeditionFk, ' estaba parada'),
|
|
||||||
CONCAT('Expedition: ', vExpeditionFk,' vBufferToFk: ', vBufferToFk)
|
|
||||||
);
|
|
||||||
|
|
||||||
END LOOP bucle;
|
|
||||||
|
|
||||||
CLOSE cur;
|
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
END LOOP l;
|
||||||
|
CLOSE vSorter;
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `srt`.`buffer_afterDelete`
|
||||||
|
AFTER DELETE ON `buffer`
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO buffer
|
||||||
|
SET `action` = 'delete',
|
||||||
|
`changedModel` = 'Buffer',
|
||||||
|
`changedModelId` = OLD.id,
|
||||||
|
`userFk` = account.myUser_getId();
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,8 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `srt`.`buffer_beforeInsert`
|
||||||
|
BEFORE INSERT ON `buffer`
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
SET NEW.editorFk = account.myUser_getId();
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,8 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `srt`.`buffer_beforeUpdate`
|
||||||
|
BEFORE UPDATE ON `buffer`
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
SET NEW.editorFk = account.myUser_getId();
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,12 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `srt`.`config_afterDelete`
|
||||||
|
AFTER DELETE ON `config`
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO config
|
||||||
|
SET `action` = 'delete',
|
||||||
|
`changedModel` = 'Config',
|
||||||
|
`changedModelId` = OLD.id,
|
||||||
|
`userFk` = account.myUser_getId();
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,8 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `srt`.`config_beforeInsert`
|
||||||
|
BEFORE INSERT ON `config`
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
SET NEW.editorFk = account.myUser_getId();
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,8 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `srt`.`config_beforeUpdate`
|
||||||
|
BEFORE UPDATE ON `config`
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
SET NEW.editorFk = account.myUser_getId();
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -1,26 +1,32 @@
|
||||||
DELIMITER $$
|
DELIMITER $$
|
||||||
CREATE OR REPLACE DEFINER=`root`@`localhost` FUNCTION `vn`.`invoiceSerial`(vClientFk INT, vCompanyFk INT, vType CHAR(1))
|
CREATE OR REPLACE DEFINER=`root`@`localhost` FUNCTION `vn`.`invoiceSerial`(vClientFk INT, vCompanyFk INT, vType CHAR(15))
|
||||||
RETURNS char(1) CHARSET utf8mb3 COLLATE utf8mb3_general_ci
|
RETURNS char(2) CHARSET utf8mb3 COLLATE utf8mb3_general_ci
|
||||||
DETERMINISTIC
|
DETERMINISTIC
|
||||||
BEGIN
|
BEGIN
|
||||||
/**
|
/**
|
||||||
* Obtiene la serie de de una factura
|
* Obtiene la serie de una factura
|
||||||
* dependiendo del area del cliente.
|
* dependiendo del area del cliente.
|
||||||
*
|
*
|
||||||
* @param vClientFk Id del cliente
|
* @param vClientFk Id del cliente
|
||||||
* @param vCompanyFk Id de la empresa
|
* @param vCompanyFk Id de la empresa
|
||||||
* @param vType Tipo de factura ["R", "M", "G"]
|
* @param vType Tipo de factura ['global','multiple','quick']
|
||||||
* @return Serie de la factura
|
* @return vSerie de la factura
|
||||||
*/
|
*/
|
||||||
DECLARE vTaxArea VARCHAR(25);
|
DECLARE vTaxArea VARCHAR(25) COLLATE utf8mb3_general_ci;
|
||||||
DECLARE vSerie CHAR(1);
|
DECLARE vSerie CHAR(2);
|
||||||
|
|
||||||
IF (SELECT hasInvoiceSimplified FROM client WHERE id = vClientFk) THEN
|
IF (SELECT hasInvoiceSimplified FROM client WHERE id = vClientFk) THEN
|
||||||
RETURN 'S';
|
RETURN 'S';
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
SELECT clientTaxArea(vClientFk, vCompanyFk) INTO vTaxArea;
|
SELECT addressTaxArea(defaultAddressFk, vCompanyFk) INTO vTaxArea
|
||||||
SELECT invoiceSerialArea(vType,vTaxArea) INTO vSerie;
|
FROM client
|
||||||
|
WHERE id = vClientFk;
|
||||||
|
|
||||||
|
SELECT code INTO vSerie
|
||||||
|
FROM invoiceOutSerial
|
||||||
|
WHERE `type` = vType AND taxAreaFk = vTaxArea;
|
||||||
|
|
||||||
RETURN vSerie;
|
RETURN vSerie;
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
DELIMITER $$
|
|
||||||
CREATE OR REPLACE DEFINER=`root`@`localhost` FUNCTION `vn`.`invoiceSerialArea`(vType CHAR(1), vTaxArea VARCHAR(25))
|
|
||||||
RETURNS char(1) CHARSET utf8mb3 COLLATE utf8mb3_unicode_ci
|
|
||||||
DETERMINISTIC
|
|
||||||
BEGIN
|
|
||||||
DECLARE vSerie CHAR(1);
|
|
||||||
|
|
||||||
IF vType = 'R' THEN
|
|
||||||
SELECT
|
|
||||||
CASE vTaxArea
|
|
||||||
WHEN 'CEE' THEN 'H'
|
|
||||||
WHEN 'WORLD' THEN 'E'
|
|
||||||
ELSE 'T'
|
|
||||||
END INTO vSerie;
|
|
||||||
-- Factura multiple
|
|
||||||
ELSEIF vType = 'M' THEN
|
|
||||||
SELECT
|
|
||||||
CASE vTaxArea
|
|
||||||
WHEN 'CEE' THEN 'H'
|
|
||||||
WHEN 'WORLD' THEN 'E'
|
|
||||||
ELSE 'M'
|
|
||||||
END INTO vSerie;
|
|
||||||
-- Factura global
|
|
||||||
ELSEIF vType = 'G' THEN
|
|
||||||
SELECT
|
|
||||||
CASE vTaxArea
|
|
||||||
WHEN 'CEE' THEN 'V'
|
|
||||||
WHEN 'WORLD' THEN 'X'
|
|
||||||
ELSE 'A'
|
|
||||||
END INTO vSerie;
|
|
||||||
END IF;
|
|
||||||
RETURN vSerie;
|
|
||||||
END$$
|
|
||||||
DELIMITER ;
|
|
|
@ -97,7 +97,7 @@ BEGIN
|
||||||
AND (vCorrectingSerial = vSerial OR NOT hasAnyNegativeBase())
|
AND (vCorrectingSerial = vSerial OR NOT hasAnyNegativeBase())
|
||||||
THEN
|
THEN
|
||||||
|
|
||||||
-- el trigger añade el siguiente Id_Factura correspondiente a la vSerial
|
-- el trigger añade el siguiente ref correspondiente a la vSerial
|
||||||
INSERT INTO invoiceOut(
|
INSERT INTO invoiceOut(
|
||||||
ref,
|
ref,
|
||||||
serial,
|
serial,
|
||||||
|
|
|
@ -189,7 +189,7 @@ BEGIN
|
||||||
SELECT * FROM sales
|
SELECT * FROM sales
|
||||||
UNION ALL
|
UNION ALL
|
||||||
SELECT * FROM orders
|
SELECT * FROM orders
|
||||||
ORDER BY shipped DESC,
|
ORDER BY shipped,
|
||||||
(inventorySupplierFk = entityId) DESC,
|
(inventorySupplierFk = entityId) DESC,
|
||||||
alertLevel DESC,
|
alertLevel DESC,
|
||||||
isTicket,
|
isTicket,
|
||||||
|
|
|
@ -2,7 +2,7 @@ DELIMITER $$
|
||||||
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_close`()
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_close`()
|
||||||
BEGIN
|
BEGIN
|
||||||
/**
|
/**
|
||||||
* Realiza el cierre de todos los
|
* Realiza el cierre de todos los
|
||||||
* tickets de la tabla tmp.ticket_close.
|
* tickets de la tabla tmp.ticket_close.
|
||||||
*
|
*
|
||||||
* @table tmp.ticket_close(ticketFk) Identificadores de los tickets a cerrar
|
* @table tmp.ticket_close(ticketFk) Identificadores de los tickets a cerrar
|
||||||
|
@ -20,7 +20,7 @@ BEGIN
|
||||||
|
|
||||||
DECLARE cur CURSOR FOR
|
DECLARE cur CURSOR FOR
|
||||||
SELECT ticketFk FROM tmp.ticket_close;
|
SELECT ticketFk FROM tmp.ticket_close;
|
||||||
|
|
||||||
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
||||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN
|
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN
|
||||||
RESIGNAL;
|
RESIGNAL;
|
||||||
|
@ -30,7 +30,7 @@ BEGIN
|
||||||
|
|
||||||
proc: LOOP
|
proc: LOOP
|
||||||
SET vDone = FALSE;
|
SET vDone = FALSE;
|
||||||
|
|
||||||
FETCH cur INTO vCurTicketFk;
|
FETCH cur INTO vCurTicketFk;
|
||||||
|
|
||||||
IF vDone THEN
|
IF vDone THEN
|
||||||
|
@ -47,12 +47,12 @@ BEGIN
|
||||||
c.hasToInvoice
|
c.hasToInvoice
|
||||||
INTO vClientFk,
|
INTO vClientFk,
|
||||||
vIsTaxDataChecked,
|
vIsTaxDataChecked,
|
||||||
vCompanyFk,
|
vCompanyFk,
|
||||||
vShipped,
|
vShipped,
|
||||||
vHasDailyInvoice,
|
vHasDailyInvoice,
|
||||||
vWithPackage,
|
vWithPackage,
|
||||||
vHasToInvoice
|
vHasToInvoice
|
||||||
FROM ticket t
|
FROM ticket t
|
||||||
JOIN `client` c ON c.id = t.clientFk
|
JOIN `client` c ON c.id = t.clientFk
|
||||||
JOIN province p ON p.id = c.provinceFk
|
JOIN province p ON p.id = c.provinceFk
|
||||||
LEFT JOIN autonomy a ON a.id = p.autonomyFk
|
LEFT JOIN autonomy a ON a.id = p.autonomyFk
|
||||||
|
@ -62,7 +62,7 @@ BEGIN
|
||||||
|
|
||||||
INSERT INTO ticketPackaging (ticketFk, packagingFk, quantity)
|
INSERT INTO ticketPackaging (ticketFk, packagingFk, quantity)
|
||||||
(SELECT vCurTicketFk, p.id, COUNT(*)
|
(SELECT vCurTicketFk, p.id, COUNT(*)
|
||||||
FROM expedition e
|
FROM expedition e
|
||||||
JOIN packaging p ON p.id = e.packagingFk
|
JOIN packaging p ON p.id = e.packagingFk
|
||||||
JOIN ticket t ON t.id = e.ticketFk
|
JOIN ticket t ON t.id = e.ticketFk
|
||||||
LEFT JOIN agencyMode am ON am.id = t.agencyModeFk
|
LEFT JOIN agencyMode am ON am.id = t.agencyModeFk
|
||||||
|
@ -73,15 +73,15 @@ BEGIN
|
||||||
GROUP BY p.itemFk);
|
GROUP BY p.itemFk);
|
||||||
|
|
||||||
-- No retornables o no catalogados
|
-- No retornables o no catalogados
|
||||||
INSERT INTO sale (itemFk, ticketFk, concept, quantity, price, isPriceFixed)
|
INSERT INTO sale (itemFk, ticketFk, concept, quantity, price, isPriceFixed)
|
||||||
(SELECT e.freightItemFk, vCurTicketFk, i.name, COUNT(*) AS amount, getSpecialPrice(e.freightItemFk, vClientFk), 1
|
(SELECT e.freightItemFk, vCurTicketFk, i.name, COUNT(*) AS amount, getSpecialPrice(e.freightItemFk, vClientFk), 1
|
||||||
FROM expedition e
|
FROM expedition e
|
||||||
JOIN item i ON i.id = e.freightItemFk
|
JOIN item i ON i.id = e.freightItemFk
|
||||||
LEFT JOIN packaging p ON p.itemFk = i.id
|
LEFT JOIN packaging p ON p.itemFk = i.id
|
||||||
WHERE e.ticketFk = vCurTicketFk AND IFNULL(p.isPackageReturnable, 0) = 0
|
WHERE e.ticketFk = vCurTicketFk AND IFNULL(p.isPackageReturnable, 0) = 0
|
||||||
AND getSpecialPrice(e.freightItemFk, vClientFk) > 0
|
AND getSpecialPrice(e.freightItemFk, vClientFk) > 0
|
||||||
GROUP BY e.freightItemFk);
|
GROUP BY e.freightItemFk);
|
||||||
|
|
||||||
IF(vHasDailyInvoice) AND vHasToInvoice THEN
|
IF(vHasDailyInvoice) AND vHasToInvoice THEN
|
||||||
|
|
||||||
-- Facturacion rapida
|
-- Facturacion rapida
|
||||||
|
@ -89,10 +89,10 @@ BEGIN
|
||||||
-- Facturar si está contabilizado
|
-- Facturar si está contabilizado
|
||||||
IF vIsTaxDataChecked THEN
|
IF vIsTaxDataChecked THEN
|
||||||
CALL invoiceOut_newFromClient(
|
CALL invoiceOut_newFromClient(
|
||||||
vClientFk,
|
vClientFk,
|
||||||
(SELECT invoiceSerial(vClientFk, vCompanyFk, 'M')),
|
(SELECT invoiceSerial(vClientFk, vCompanyFk, 'multiple')),
|
||||||
vShipped,
|
vShipped,
|
||||||
vCompanyFk,
|
vCompanyFk,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
vNewInvoiceId);
|
vNewInvoiceId);
|
||||||
|
|
|
@ -14,16 +14,28 @@ BEGIN
|
||||||
DECLARE vTicketFk INT;
|
DECLARE vTicketFk INT;
|
||||||
|
|
||||||
DECLARE cTickets CURSOR FOR
|
DECLARE cTickets CURSOR FOR
|
||||||
SELECT id FROM ticket
|
SELECT DISTINCT t.id
|
||||||
WHERE refFk IS NULL
|
FROM ticket t
|
||||||
AND ((vScope = 'client' AND clientFk = vId)
|
LEFT JOIN tItems ti ON ti.id = t.id
|
||||||
OR (vScope = 'address' AND addressFk = vId));
|
WHERE t.refFk IS NULL
|
||||||
|
AND ((vScope = 'client' AND t.clientFk = vId)
|
||||||
|
OR (vScope = 'address' AND t.addressFk = vId)
|
||||||
|
OR (vScope = 'item' AND ti.id)
|
||||||
|
);
|
||||||
|
|
||||||
DECLARE CONTINUE HANDLER FOR NOT FOUND
|
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
||||||
SET vDone = TRUE;
|
|
||||||
|
CREATE OR REPLACE TEMPORARY TABLE tItems
|
||||||
|
(PRIMARY KEY (id))
|
||||||
|
ENGINE = MEMORY
|
||||||
|
SELECT DISTINCT t.id
|
||||||
|
FROM ticket t
|
||||||
|
JOIN sale s ON s.ticketFk = t.id
|
||||||
|
JOIN itemTaxCountry itc ON itc.itemFk = s.itemFk
|
||||||
|
WHERE t.refFk IS NULL
|
||||||
|
AND (vScope = 'item' AND itc.itemFk = vId);
|
||||||
|
|
||||||
OPEN cTickets;
|
OPEN cTickets;
|
||||||
|
|
||||||
myLoop: LOOP
|
myLoop: LOOP
|
||||||
SET vDone = FALSE;
|
SET vDone = FALSE;
|
||||||
FETCH cTickets INTO vTicketFk;
|
FETCH cTickets INTO vTicketFk;
|
||||||
|
@ -34,7 +46,8 @@ BEGIN
|
||||||
|
|
||||||
CALL ticket_recalc(vTicketFk, NULL);
|
CALL ticket_recalc(vTicketFk, NULL);
|
||||||
END LOOP;
|
END LOOP;
|
||||||
|
|
||||||
CLOSE cTickets;
|
CLOSE cTickets;
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE tItems;
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`roadmap_beforeInsert`
|
||||||
|
BEFORE INSERT ON `roadmap`
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
IF NEW.driver1Fk IS NOT NULL THEN
|
||||||
|
SET NEW.driverName = (SELECT firstName FROM worker WHERE id = NEW.driver1Fk);
|
||||||
|
ELSE
|
||||||
|
SET NEW.driverName = NULL;
|
||||||
|
END IF;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,12 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`roadmap_beforeUpdate`
|
||||||
|
BEFORE UPDATE ON `roadmap`
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
IF NEW.driver1Fk IS NOT NULL THEN
|
||||||
|
SET NEW.driverName = (SELECT firstName FROM worker WHERE id = NEW.driver1Fk);
|
||||||
|
ELSE
|
||||||
|
SET NEW.driverName = NULL;
|
||||||
|
END IF;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -2,5 +2,5 @@ CREATE OR REPLACE DEFINER=`root`@`localhost`
|
||||||
SQL SECURITY DEFINER
|
SQL SECURITY DEFINER
|
||||||
VIEW `vn2008`.`mandato_tipo`
|
VIEW `vn2008`.`mandato_tipo`
|
||||||
AS SELECT `m`.`id` AS `idmandato_tipo`,
|
AS SELECT `m`.`id` AS `idmandato_tipo`,
|
||||||
`m`.`name` AS `Nombre`
|
`m`.`code` AS `Nombre`
|
||||||
FROM `vn`.`mandateType` `m`
|
FROM `vn`.`mandateType` `m`
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE srt.moving DROP INDEX moving_fk1_idx;
|
|
@ -0,0 +1,4 @@
|
||||||
|
ALTER TABLE vn.invoiceOutSerial
|
||||||
|
MODIFY COLUMN `type` enum('global','quick','multiple') CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci DEFAULT NULL NULL;
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX invoiceOutSerial_taxAreaFk_IDX USING BTREE ON vn.invoiceOutSerial (taxAreaFk,`type`);
|
|
@ -0,0 +1,3 @@
|
||||||
|
UPDATE vn.invoiceOutSerial
|
||||||
|
SET `type`='multiple'
|
||||||
|
WHERE `description` LIKE '%Múltiple%';
|
|
@ -0,0 +1,3 @@
|
||||||
|
ALTER TABLE vn.mandateType
|
||||||
|
CHANGE name code VARCHAR(45) NOT NULL,
|
||||||
|
ADD UNIQUE (code);
|
|
@ -0,0 +1,3 @@
|
||||||
|
ALTER TABLE vn.accountDetailType
|
||||||
|
ADD COLUMN code VARCHAR(45),
|
||||||
|
ADD UNIQUE (code);
|
|
@ -0,0 +1,9 @@
|
||||||
|
UPDATE vn.accountDetailType
|
||||||
|
SET code = CASE description
|
||||||
|
WHEN 'IBAN' THEN 'iban'
|
||||||
|
WHEN 'SWIFT' THEN 'swift'
|
||||||
|
WHEN 'Referencia Remesas' THEN 'remRef'
|
||||||
|
WHEN 'Referencia Transferencias' THEN 'trnRef'
|
||||||
|
WHEN 'Referencia Nominas' THEN 'payRef'
|
||||||
|
WHEN 'ABA' THEN 'aba'
|
||||||
|
END;
|
|
@ -0,0 +1,3 @@
|
||||||
|
ALTER TABLE hedera.tpvMerchantEnable
|
||||||
|
MODIFY COLUMN companyFk int(10) unsigned NOT NULL,
|
||||||
|
ADD CONSTRAINT tpvMerchantEnable_company_FK FOREIGN KEY (companyFk) REFERENCES vn.company(id) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
@ -0,0 +1,19 @@
|
||||||
|
CREATE OR REPLACE TABLE `srt`.`bufferLog` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`originFk` int(11) DEFAULT NULL,
|
||||||
|
`userFk` int(10) unsigned DEFAULT NULL,
|
||||||
|
`action` set('insert','update','delete','select') NOT NULL,
|
||||||
|
`creationDate` timestamp NULL DEFAULT current_timestamp(),
|
||||||
|
`description` text CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
|
||||||
|
`changedModel` enum('Buffer', 'Config') NOT NULL DEFAULT 'Buffer',
|
||||||
|
`oldInstance` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`oldInstance`)),
|
||||||
|
`newInstance` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`newInstance`)),
|
||||||
|
`changedModelId` int(11) NOT NULL,
|
||||||
|
`changedModelValue` varchar(45) DEFAULT NULL,
|
||||||
|
`summaryId` varchar(30) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `logBufferUserFk` (`userFk`),
|
||||||
|
KEY `bufferLog_changedModel` (`changedModel`,`changedModelId`,`creationDate`),
|
||||||
|
KEY `bufferLog_originFk` (`originFk`,`creationDate`),
|
||||||
|
CONSTRAINT `bufferUserFk` FOREIGN KEY (`userFk`) REFERENCES `account`.`user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE srt.buffer ADD editorFk int(10) unsigned DEFAULT NULL NULL;
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE srt.config ADD editorFk int(10) unsigned DEFAULT NULL NULL;
|
|
@ -0,0 +1,9 @@
|
||||||
|
CREATE TABLE vn.quadMindsApiConfig (
|
||||||
|
id int(10) unsigned NULL PRIMARY KEY,
|
||||||
|
`url` varchar(255) DEFAULT NULL NULL,
|
||||||
|
`key` varchar(255) DEFAULT NULL NULL,
|
||||||
|
CONSTRAINT quadMindsConfig_check CHECK (id = 1)
|
||||||
|
)
|
||||||
|
ENGINE=InnoDB
|
||||||
|
DEFAULT CHARSET=utf8mb3
|
||||||
|
COLLATE=utf8mb3_unicode_ci;
|
|
@ -0,0 +1,6 @@
|
||||||
|
ALTER TABLE vn.roadmap
|
||||||
|
ADD COLUMN m3 INT UNSIGNED NULL,
|
||||||
|
ADD COLUMN driver2Fk INT UNSIGNED NULL,
|
||||||
|
ADD COLUMN driver1Fk INT UNSIGNED NULL,
|
||||||
|
ADD CONSTRAINT roadmap_worker_FK FOREIGN KEY (driver1Fk) REFERENCES vn.worker(id) ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||||
|
ADD CONSTRAINT roadmap_worker_FK_2 FOREIGN KEY (driver2Fk) REFERENCES vn.worker(id) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
@ -0,0 +1,24 @@
|
||||||
|
DELETE FROM `salix`.`ACL`
|
||||||
|
WHERE `model` = 'Ticket'
|
||||||
|
AND `property` = 'refund'
|
||||||
|
AND `accessType` = 'WRITE'
|
||||||
|
AND `permission` = 'ALLOW'
|
||||||
|
AND `principalType` = 'ROLE'
|
||||||
|
AND `principalId` = 'salesAssistant';
|
||||||
|
|
||||||
|
UPDATE `salix`.`ACL`
|
||||||
|
SET `property` = 'cloneAll'
|
||||||
|
WHERE `model` = 'Ticket'
|
||||||
|
AND `property` = 'refund'
|
||||||
|
AND `accessType` = 'WRITE'
|
||||||
|
AND `permission` = 'ALLOW'
|
||||||
|
AND `principalType` = 'ROLE'
|
||||||
|
AND `principalId` IN ('invoicing', 'claimManager', 'logistic');
|
||||||
|
|
||||||
|
DELETE FROM `salix`.`ACL`
|
||||||
|
WHERE `model` = 'Ticket'
|
||||||
|
AND `property` = 'clone'
|
||||||
|
AND `accessType` = 'WRITE'
|
||||||
|
AND `permission` = 'ALLOW'
|
||||||
|
AND `principalType` = 'ROLE'
|
||||||
|
AND `principalId` = 'administrative';
|
|
@ -108,7 +108,7 @@ module.exports = Self => {
|
||||||
|
|
||||||
async function notifyStateChange(ctx, workerId, claim, newState) {
|
async function notifyStateChange(ctx, workerId, claim, newState) {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const url = await models.Url.getUrl();
|
const url = await models.Url.getUrl('lilium');
|
||||||
const $t = ctx.req.__;
|
const $t = ctx.req.__;
|
||||||
|
|
||||||
const message = $t(`Claim state has changed to`, {
|
const message = $t(`Claim state has changed to`, {
|
||||||
|
@ -122,7 +122,7 @@ module.exports = Self => {
|
||||||
|
|
||||||
async function notifyPickUp(ctx, workerId, claim) {
|
async function notifyPickUp(ctx, workerId, claim) {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const url = await models.Url.getUrl();
|
const url = await models.Url.getUrl('lilium');
|
||||||
const $t = ctx.req.__; // $translate
|
const $t = ctx.req.__; // $translate
|
||||||
|
|
||||||
const message = $t('Claim will be picked', {
|
const message = $t('Claim will be picked', {
|
||||||
|
|
|
@ -27,7 +27,7 @@ module.exports = Self => {
|
||||||
// Renew mandate
|
// Renew mandate
|
||||||
if (mandate) {
|
if (mandate) {
|
||||||
const mandateType = await models.MandateType.findOne({
|
const mandateType = await models.MandateType.findOne({
|
||||||
where: {name: mandate.type}
|
where: {code: mandate.type}
|
||||||
});
|
});
|
||||||
|
|
||||||
const oldMandate = await models.Mandate.findOne({
|
const oldMandate = await models.Mandate.findOne({
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"description": "Identifier"
|
"description": "Identifier"
|
||||||
},
|
},
|
||||||
"name": {
|
"code": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
<vn-tr ng-repeat="mandate in mandates">
|
<vn-tr ng-repeat="mandate in mandates">
|
||||||
<vn-td number>{{::mandate.id}}</vn-td>
|
<vn-td number>{{::mandate.id}}</vn-td>
|
||||||
<vn-td>{{::mandate.company.code}}</vn-td>
|
<vn-td>{{::mandate.company.code}}</vn-td>
|
||||||
<vn-td>{{::mandate.mandateType.name}}</vn-td>
|
<vn-td>{{::mandate.mandateType.code}}</vn-td>
|
||||||
<vn-td shrink-datetime>{{::mandate.created | date:'dd/MM/yyyy HH:mm' | dashIfEmpty}}</vn-td>
|
<vn-td shrink-datetime>{{::mandate.created | date:'dd/MM/yyyy HH:mm' | dashIfEmpty}}</vn-td>
|
||||||
<vn-td shrink-datetime>{{::mandate.finished | date:'dd/MM/yyyy HH:mm' | dashIfEmpty}}</vn-td>
|
<vn-td shrink-datetime>{{::mandate.finished | date:'dd/MM/yyyy HH:mm' | dashIfEmpty}}</vn-td>
|
||||||
</vn-tr>
|
</vn-tr>
|
||||||
|
|
|
@ -9,7 +9,7 @@ class Controller extends Section {
|
||||||
{
|
{
|
||||||
relation: 'mandateType',
|
relation: 'mandateType',
|
||||||
scope: {
|
scope: {
|
||||||
fields: ['id', 'name']
|
fields: ['id', 'code']
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
relation: 'company',
|
relation: 'company',
|
||||||
|
|
|
@ -46,7 +46,7 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
filter = mergeFilters(args.filter, {where});
|
const filter = mergeFilters(args.filter, {where});
|
||||||
|
|
||||||
const stmt = new ParameterizedSQL(
|
const stmt = new ParameterizedSQL(
|
||||||
`SELECT i.serial, SUM(IF(i.isBooked, 0,1)) pending, COUNT(*) total
|
`SELECT i.serial, SUM(IF(i.isBooked, 0,1)) pending, COUNT(*) total
|
||||||
|
|
|
@ -75,7 +75,7 @@ module.exports = Self => {
|
||||||
AND c.isTaxDataChecked
|
AND c.isTaxDataChecked
|
||||||
AND c.isActive
|
AND c.isActive
|
||||||
AND NOT t.isDeleted
|
AND NOT t.isDeleted
|
||||||
GROUP BY c.id, IF(c.hasToInvoiceByAddress, a.id, TRUE)
|
GROUP BY IF(c.hasToInvoiceByAddress, a.id, c.id)
|
||||||
HAVING SUM(t.totalWithVat) > 0;`;
|
HAVING SUM(t.totalWithVat) > 0;`;
|
||||||
|
|
||||||
const addresses = await Self.rawSql(query, [
|
const addresses = await Self.rawSql(query, [
|
||||||
|
|
|
@ -28,6 +28,11 @@ module.exports = Self => {
|
||||||
type: 'number',
|
type: 'number',
|
||||||
description: 'The company id to invoice',
|
description: 'The company id to invoice',
|
||||||
required: true
|
required: true
|
||||||
|
}, {
|
||||||
|
arg: 'serialType',
|
||||||
|
type: 'string',
|
||||||
|
description: 'Invoice serial number type (see vn.invoiceOutSerial.type enum)',
|
||||||
|
required: true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
returns: {
|
returns: {
|
||||||
|
@ -39,12 +44,10 @@ module.exports = Self => {
|
||||||
verb: 'POST'
|
verb: 'POST'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.invoiceClient = async(ctx, options) => {
|
Self.invoiceClient = async(ctx, options) => {
|
||||||
const args = ctx.args;
|
const args = ctx.args;
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
options = typeof options == 'object'
|
options = typeof options === 'object' ? {...options} : {};
|
||||||
? Object.assign({}, options) : {};
|
|
||||||
options.userId = ctx.req.accessToken.userId;
|
options.userId = ctx.req.accessToken.userId;
|
||||||
|
|
||||||
let tx;
|
let tx;
|
||||||
|
@ -74,10 +77,9 @@ module.exports = Self => {
|
||||||
], options);
|
], options);
|
||||||
}
|
}
|
||||||
|
|
||||||
const invoiceType = 'G';
|
|
||||||
const invoiceId = await models.Ticket.makeInvoice(
|
const invoiceId = await models.Ticket.makeInvoice(
|
||||||
ctx,
|
ctx,
|
||||||
invoiceType,
|
args.serialType,
|
||||||
args.companyFk,
|
args.companyFk,
|
||||||
args.invoiceDate,
|
args.invoiceDate,
|
||||||
null,
|
null,
|
||||||
|
|
|
@ -43,7 +43,7 @@ module.exports = Self => {
|
||||||
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);
|
||||||
const refundedTickets = await models.Ticket.refund(ctx, ticketsIds, withWarehouse, myOptions);
|
const refundedTickets = await models.Ticket.cloneAll(ctx, ticketsIds, withWarehouse, true, myOptions);
|
||||||
|
|
||||||
if (tx) await tx.commit();
|
if (tx) await tx.commit();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
|
||||||
|
describe('InvoiceOut clientsToInvoice()', () => {
|
||||||
|
const userId = 1;
|
||||||
|
const clientId = 1101;
|
||||||
|
const companyFk = 442;
|
||||||
|
const maxShipped = new Date();
|
||||||
|
maxShipped.setMonth(11);
|
||||||
|
maxShipped.setDate(31);
|
||||||
|
maxShipped.setHours(23, 59, 59, 999);
|
||||||
|
const invoiceDate = new Date();
|
||||||
|
const activeCtx = {
|
||||||
|
getLocale: () => {
|
||||||
|
return 'en';
|
||||||
|
},
|
||||||
|
accessToken: {userId: userId},
|
||||||
|
__: value => {
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
};
|
||||||
|
const ctx = {req: activeCtx};
|
||||||
|
|
||||||
|
it('should return a list of clients to invoice', async() => {
|
||||||
|
spyOn(models.InvoiceOut, 'rawSql').and.callFake(query => {
|
||||||
|
if (query.includes('ticketPackaging_add'))
|
||||||
|
return Promise.resolve(true);
|
||||||
|
else if (query.includes('SELECT c.id clientId')) {
|
||||||
|
return Promise.resolve([
|
||||||
|
{
|
||||||
|
clientId: clientId,
|
||||||
|
clientName: 'Test Client',
|
||||||
|
id: 1,
|
||||||
|
nickname: 'Address 1'
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const tx = await models.InvoiceOut.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const addresses = await models.InvoiceOut.clientsToInvoice(
|
||||||
|
ctx, clientId, invoiceDate, maxShipped, companyFk, options);
|
||||||
|
|
||||||
|
expect(addresses.length).toBeGreaterThan(0);
|
||||||
|
expect(addresses[0].clientId).toBe(clientId);
|
||||||
|
expect(addresses[0].clientName).toBe('Test Client');
|
||||||
|
expect(addresses[0].id).toBe(1);
|
||||||
|
expect(addresses[0].nickname).toBe('Address 1');
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle errors and rollback transaction', async() => {
|
||||||
|
spyOn(models.InvoiceOut, 'rawSql').and.callFake(() => {
|
||||||
|
return Promise.reject(new Error('Test Error'));
|
||||||
|
});
|
||||||
|
|
||||||
|
const tx = await models.InvoiceOut.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await models.InvoiceOut.clientsToInvoice(ctx, clientId, invoiceDate, maxShipped, companyFk, options);
|
||||||
|
} catch (e) {
|
||||||
|
expect(e.message).toBe('Test Error');
|
||||||
|
await tx.rollback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,16 +1,16 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('InvoiceOut invoiceClient()', () => {
|
describe('InvoiceOut invoiceClient()', () => {
|
||||||
const userId = 1;
|
const userId = 1;
|
||||||
const clientId = 1101;
|
const clientId = 1101;
|
||||||
const addressId = 121;
|
const addressFk = 121;
|
||||||
const companyFk = 442;
|
const companyFk = 442;
|
||||||
const minShipped = Date.vnNew();
|
const minShipped = Date.vnNew();
|
||||||
minShipped.setFullYear(minShipped.getFullYear() - 1);
|
minShipped.setFullYear(minShipped.getFullYear() - 1);
|
||||||
minShipped.setMonth(1);
|
minShipped.setMonth(1);
|
||||||
minShipped.setDate(1);
|
minShipped.setDate(1);
|
||||||
minShipped.setHours(0, 0, 0, 0);
|
minShipped.setHours(0, 0, 0, 0);
|
||||||
const invoiceSerial = 'A';
|
|
||||||
const activeCtx = {
|
const activeCtx = {
|
||||||
getLocale: () => {
|
getLocale: () => {
|
||||||
return 'en';
|
return 'en';
|
||||||
|
@ -23,9 +23,14 @@ describe('InvoiceOut invoiceClient()', () => {
|
||||||
|
|
||||||
};
|
};
|
||||||
const ctx = {req: activeCtx};
|
const ctx = {req: activeCtx};
|
||||||
|
beforeAll(() => {
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should make a global invoicing', async() => {
|
it('should make a global invoicing by address and verify billing status', async() => {
|
||||||
spyOn(models.InvoiceOut, 'makePdf').and.returnValue(new Promise(resolve => resolve(true)));
|
spyOn(models.InvoiceOut, 'makePdf').and.returnValue(Promise.resolve(true));
|
||||||
spyOn(models.InvoiceOut, 'invoiceEmail');
|
spyOn(models.InvoiceOut, 'invoiceEmail');
|
||||||
|
|
||||||
const tx = await models.InvoiceOut.beginTransaction({});
|
const tx = await models.InvoiceOut.beginTransaction({});
|
||||||
|
@ -34,20 +39,96 @@ describe('InvoiceOut invoiceClient()', () => {
|
||||||
try {
|
try {
|
||||||
ctx.args = {
|
ctx.args = {
|
||||||
clientId: clientId,
|
clientId: clientId,
|
||||||
addressId: addressId,
|
addressId: addressFk,
|
||||||
invoiceDate: Date.vnNew(),
|
invoiceDate: Date.vnNew(),
|
||||||
maxShipped: Date.vnNew(),
|
maxShipped: Date.vnNew(),
|
||||||
companyFk: companyFk,
|
companyFk: companyFk,
|
||||||
minShipped: minShipped
|
serialType: 'global'
|
||||||
};
|
};
|
||||||
|
|
||||||
const invoiceOutId = await models.InvoiceOut.invoiceClient(ctx, options);
|
const invoiceOutId = await models.InvoiceOut.invoiceClient(ctx, options);
|
||||||
|
|
||||||
const invoiceOut = await models.InvoiceOut.findById(invoiceOutId, null, options);
|
const invoiceOut = await models.InvoiceOut.findById(invoiceOutId, null, options);
|
||||||
const [firstTicket] = await models.Ticket.find({
|
|
||||||
|
expect(invoiceOutId).toBeGreaterThan(0);
|
||||||
|
|
||||||
|
const allClientTickets = await models.Ticket.find({
|
||||||
|
where: {
|
||||||
|
clientFk: clientId,
|
||||||
|
or: [
|
||||||
|
{refFk: null},
|
||||||
|
{refFk: invoiceOut.ref}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}, options);
|
||||||
|
|
||||||
|
const billedTickets = await models.Ticket.find({
|
||||||
where: {refFk: invoiceOut.ref}
|
where: {refFk: invoiceOut.ref}
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
|
const allBilledTicketsHaveCorrectAddress = billedTickets.every(ticket => ticket.addressFk === addressFk);
|
||||||
|
|
||||||
|
expect(allBilledTicketsHaveCorrectAddress).toBe(true);
|
||||||
|
|
||||||
|
const addressTickets = allClientTickets.filter(ticket => ticket.addressFk === addressFk);
|
||||||
|
|
||||||
|
const allAddressTicketsBilled = addressTickets.every(ticket => ticket.refFk === invoiceOut.ref);
|
||||||
|
|
||||||
|
expect(allAddressTicketsBilled).toBe(true);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should invoice all tickets regardless of address when hasToInvoiceByAddress is false', async() => {
|
||||||
|
spyOn(models.InvoiceOut, 'makePdf').and.returnValue(Promise.resolve(true));
|
||||||
|
spyOn(models.InvoiceOut, 'invoiceEmail');
|
||||||
|
|
||||||
|
const tx = await models.InvoiceOut.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const client = await models.Client.findById(clientId, null, options);
|
||||||
|
await client.updateAttribute('hasToInvoiceByAddress', false, options);
|
||||||
|
|
||||||
|
ctx.args = {
|
||||||
|
clientId: clientId,
|
||||||
|
invoiceDate: Date.vnNew(),
|
||||||
|
maxShipped: Date.vnNew(),
|
||||||
|
companyFk: companyFk,
|
||||||
|
serialType: 'global'
|
||||||
|
};
|
||||||
|
|
||||||
|
const invoiceOutId = await models.InvoiceOut.invoiceClient(ctx, options);
|
||||||
|
|
||||||
|
const invoiceOut = await models.InvoiceOut.findById(invoiceOutId, null, options);
|
||||||
|
|
||||||
expect(invoiceOutId).toBeGreaterThan(0);
|
expect(invoiceOutId).toBeGreaterThan(0);
|
||||||
expect(firstTicket.refFk).toContain(invoiceSerial);
|
|
||||||
|
const allClientTickets = await models.Ticket.find({
|
||||||
|
where: {
|
||||||
|
clientFk: clientId,
|
||||||
|
or: [
|
||||||
|
{refFk: null},
|
||||||
|
{refFk: invoiceOut.ref}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}, options);
|
||||||
|
|
||||||
|
const billedTickets = await models.Ticket.find({
|
||||||
|
where: {refFk: invoiceOut.ref}
|
||||||
|
}, options);
|
||||||
|
|
||||||
|
const allTicketsBilled = allClientTickets.every(ticket => ticket.refFk === invoiceOut.ref);
|
||||||
|
|
||||||
|
expect(allTicketsBilled).toBe(true);
|
||||||
|
|
||||||
|
const billedAddresses = new Set(billedTickets.map(ticket => ticket.addressFk));
|
||||||
|
|
||||||
|
expect(billedAddresses.size).toBeGreaterThan(1);
|
||||||
|
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -82,20 +82,12 @@ module.exports = Self => {
|
||||||
myOptions.transaction = tx;
|
myOptions.transaction = tx;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const filterRef = {where: {refFk: refFk}};
|
const tickets = await models.Ticket.find({where: {refFk}}, myOptions);
|
||||||
const tickets = await models.Ticket.find(filterRef, myOptions);
|
|
||||||
const ticketsIds = tickets.map(ticket => ticket.id);
|
const ticketsIds = tickets.map(ticket => ticket.id);
|
||||||
const refundTickets = await models.Ticket.refund(ctx, ticketsIds, null, myOptions);
|
const refundTickets = await models.Ticket.cloneAll(ctx, ticketsIds, false, true, myOptions);
|
||||||
|
|
||||||
const filterTicket = {where: {ticketFk: {inq: ticketsIds}}};
|
const clonedTickets = await models.Ticket.cloneAll(ctx, ticketsIds, false, false, myOptions);
|
||||||
|
|
||||||
const services = await models.TicketService.find(filterTicket, myOptions);
|
|
||||||
const servicesIds = services.map(service => service.id);
|
|
||||||
|
|
||||||
const sales = await models.Sale.find(filterTicket, myOptions);
|
|
||||||
const salesIds = sales.map(sale => sale.id);
|
|
||||||
|
|
||||||
const clonedTickets = await models.Sale.clone(ctx, salesIds, servicesIds, null, false, myOptions);
|
|
||||||
const clonedTicketIds = [];
|
const clonedTicketIds = [];
|
||||||
|
|
||||||
for (const clonedTicket of clonedTickets) {
|
for (const clonedTicket of clonedTickets) {
|
||||||
|
|
|
@ -20,6 +20,9 @@
|
||||||
},
|
},
|
||||||
"isCEE": {
|
"isCEE": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"relations": {
|
"relations": {
|
||||||
|
@ -35,4 +38,4 @@
|
||||||
"principalId": "$everyone",
|
"principalId": "$everyone",
|
||||||
"permission": "ALLOW"
|
"permission": "ALLOW"
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,28 +88,7 @@
|
||||||
translate>
|
translate>
|
||||||
Show CITES letter
|
Show CITES letter
|
||||||
</vn-item>
|
</vn-item>
|
||||||
<vn-item class="dropdown"
|
|
||||||
vn-click-stop="refundMenu.show($event, 'left')"
|
|
||||||
vn-tooltip="Create a refund ticket for each ticket on the current invoice"
|
|
||||||
vn-acl="invoicing, claimManager, salesAssistant"
|
|
||||||
vn-acl-action="remove"
|
|
||||||
translate>
|
|
||||||
Refund...
|
|
||||||
<vn-menu vn-id="refundMenu">
|
|
||||||
<vn-list>
|
|
||||||
<vn-item
|
|
||||||
ng-click="$ctrl.refundInvoiceOut(true)"
|
|
||||||
translate>
|
|
||||||
with warehouse
|
|
||||||
</vn-item>
|
|
||||||
<vn-item
|
|
||||||
ng-click="$ctrl.refundInvoiceOut(false)"
|
|
||||||
translate>
|
|
||||||
without warehouse
|
|
||||||
</vn-item>
|
|
||||||
</vn-list>
|
|
||||||
</vn-menu>
|
|
||||||
</vn-item>
|
|
||||||
</vn-list>
|
</vn-list>
|
||||||
</vn-menu>
|
</vn-menu>
|
||||||
<vn-confirm
|
<vn-confirm
|
||||||
|
|
|
@ -135,21 +135,6 @@ class Controller extends Section {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
refundInvoiceOut(withWarehouse) {
|
|
||||||
const query = 'InvoiceOuts/refund';
|
|
||||||
const params = {ref: this.invoiceOut.ref, withWarehouse: withWarehouse};
|
|
||||||
this.$http.post(query, params).then(res => {
|
|
||||||
const tickets = res.data;
|
|
||||||
const refundTickets = tickets.map(ticket => ticket.id);
|
|
||||||
|
|
||||||
this.vnApp.showSuccess(this.$t('The following refund tickets have been created', {
|
|
||||||
ticketId: refundTickets.join(',')
|
|
||||||
}));
|
|
||||||
if (refundTickets.length == 1)
|
|
||||||
this.$state.go('ticket.card.sale', {id: refundTickets[0]});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
transferInvoice() {
|
transferInvoice() {
|
||||||
const params = {
|
const params = {
|
||||||
id: this.invoiceOut.id,
|
id: this.invoiceOut.id,
|
||||||
|
|
|
@ -105,17 +105,4 @@ describe('vnInvoiceOutDescriptorMenu', () => {
|
||||||
expect(controller.vnApp.showMessage).toHaveBeenCalled();
|
expect(controller.vnApp.showMessage).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('refundInvoiceOut()', () => {
|
|
||||||
it('should make a query and show a success message', () => {
|
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
|
||||||
const params = {ref: controller.invoiceOut.ref};
|
|
||||||
|
|
||||||
$httpBackend.expectPOST(`InvoiceOuts/refund`, params).respond([{id: 1}, {id: 2}]);
|
|
||||||
controller.refundInvoiceOut();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,40 +1,25 @@
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('clone', {
|
Self.remoteMethodCtx('clone', {
|
||||||
description: 'Clone sales and services provided',
|
description: 'Clone sales, services, and ticket packaging provided',
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: [
|
accepts: [
|
||||||
{
|
{arg: 'salesIds', type: ['number']},
|
||||||
arg: 'salesIds',
|
{arg: 'servicesIds', type: ['number']},
|
||||||
type: ['number'],
|
{arg: 'ticketPackagingIds', type: ['number']},
|
||||||
}, {
|
{arg: 'withWarehouse', type: 'boolean', required: true},
|
||||||
arg: 'servicesIds',
|
{arg: 'negative', type: 'boolean'}
|
||||||
type: ['number']
|
|
||||||
}, {
|
|
||||||
arg: 'withWarehouse',
|
|
||||||
type: 'boolean',
|
|
||||||
required: true
|
|
||||||
}, {
|
|
||||||
arg: 'negative',
|
|
||||||
type: 'boolean'
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
returns: {
|
returns: {type: ['object'], root: true},
|
||||||
type: ['object'],
|
http: {path: `/clone`, verb: 'POST'}
|
||||||
root: true
|
|
||||||
},
|
|
||||||
http: {
|
|
||||||
path: `/clone`,
|
|
||||||
verb: 'POST'
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
Self.clone = async(ctx, salesIds, servicesIds, withWarehouse, negative, options) => {
|
|
||||||
|
Self.clone = async(ctx, salesIds, servicesIds, ticketPackagingIds, withWarehouse, negative, options) => {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const myOptions = {};
|
const myOptions = {};
|
||||||
let tx;
|
let tx;
|
||||||
const newTickets = [];
|
const newTickets = [];
|
||||||
|
|
||||||
if (typeof options == 'object')
|
if (typeof options === 'object') Object.assign(myOptions, options);
|
||||||
Object.assign(myOptions, options);
|
|
||||||
|
|
||||||
if (!myOptions.transaction) {
|
if (!myOptions.transaction) {
|
||||||
tx = await Self.beginTransaction({});
|
tx = await Self.beginTransaction({});
|
||||||
|
@ -44,8 +29,9 @@ module.exports = Self => {
|
||||||
try {
|
try {
|
||||||
let sales;
|
let sales;
|
||||||
let services;
|
let services;
|
||||||
|
let ticketPackaging;
|
||||||
|
|
||||||
if (salesIds && salesIds.length) {
|
if (salesIds?.length) {
|
||||||
sales = await models.Sale.find({
|
sales = await models.Sale.find({
|
||||||
where: {id: {inq: salesIds}},
|
where: {id: {inq: salesIds}},
|
||||||
include: {
|
include: {
|
||||||
|
@ -57,12 +43,18 @@ module.exports = Self => {
|
||||||
}, myOptions);
|
}, myOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (servicesIds && servicesIds.length) {
|
if (servicesIds?.length) {
|
||||||
services = await models.TicketService.find({
|
services = await models.TicketService.find({
|
||||||
where: {id: {inq: servicesIds}}
|
where: {id: {inq: servicesIds}}
|
||||||
}, myOptions);
|
}, myOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ticketPackagingIds?.length) {
|
||||||
|
ticketPackaging = await models.TicketPackaging.find({
|
||||||
|
where: {id: {inq: ticketPackagingIds}}
|
||||||
|
}, myOptions);
|
||||||
|
}
|
||||||
|
|
||||||
let ticketsIds = sales ?
|
let ticketsIds = sales ?
|
||||||
[...new Set(sales.map(sale => sale.ticketFk))] :
|
[...new Set(sales.map(sale => sale.ticketFk))] :
|
||||||
[...new Set(services.map(service => service.ticketFk))];
|
[...new Set(services.map(service => service.ticketFk))];
|
||||||
|
@ -74,12 +66,12 @@ module.exports = Self => {
|
||||||
ctx,
|
ctx,
|
||||||
ticketId,
|
ticketId,
|
||||||
withWarehouse,
|
withWarehouse,
|
||||||
negative,
|
|
||||||
myOptions
|
myOptions
|
||||||
);
|
);
|
||||||
newTickets.push(newTicket);
|
newTickets.push(newTicket);
|
||||||
mappedTickets.set(ticketId, newTicket.id);
|
mappedTickets.set(ticketId, newTicket.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sales) {
|
if (sales) {
|
||||||
for (const sale of sales) {
|
for (const sale of sales) {
|
||||||
const newTicketId = mappedTickets.get(sale.ticketFk);
|
const newTicketId = mappedTickets.get(sale.ticketFk);
|
||||||
|
@ -107,7 +99,7 @@ module.exports = Self => {
|
||||||
|
|
||||||
await models.TicketService.create({
|
await models.TicketService.create({
|
||||||
description: service.description,
|
description: service.description,
|
||||||
quantity: negative ? - service.quantity : service.quantity,
|
quantity: negative ? -service.quantity : service.quantity,
|
||||||
price: service.price,
|
price: service.price,
|
||||||
taxClassFk: service.taxClassFk,
|
taxClassFk: service.taxClassFk,
|
||||||
ticketFk: newTicketId,
|
ticketFk: newTicketId,
|
||||||
|
@ -116,6 +108,18 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ticketPackaging) {
|
||||||
|
for (const packaging of ticketPackaging) {
|
||||||
|
const newTicketId = mappedTickets.get(packaging.ticketFk);
|
||||||
|
|
||||||
|
await models.TicketPackaging.create({
|
||||||
|
ticketFk: newTicketId,
|
||||||
|
packagingFk: packaging.packagingFk,
|
||||||
|
quantity: negative ? -packaging.quantity : packaging.quantity
|
||||||
|
}, myOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (tx) await tx.commit();
|
if (tx) await tx.commit();
|
||||||
|
|
||||||
return newTickets;
|
return newTickets;
|
||||||
|
@ -124,13 +128,7 @@ module.exports = Self => {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createTicket(
|
async function createTicket(ctx, ticketId, withWarehouse, myOptions) {
|
||||||
ctx,
|
|
||||||
ticketId,
|
|
||||||
withWarehouse,
|
|
||||||
negative,
|
|
||||||
myOptions
|
|
||||||
) {
|
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const now = Date.vnNew();
|
const now = Date.vnNew();
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ describe('Ticket cloning - clone function', () => {
|
||||||
const servicesIds = [];
|
const servicesIds = [];
|
||||||
const withWarehouse = true;
|
const withWarehouse = true;
|
||||||
const negative = false;
|
const negative = false;
|
||||||
const newTickets = await models.Sale.clone(ctx, salesIds, servicesIds, withWarehouse, negative, options);
|
const newTickets = await models.Sale.clone(ctx, salesIds, servicesIds, null, withWarehouse, negative, options);
|
||||||
|
|
||||||
expect(newTickets).toBeDefined();
|
expect(newTickets).toBeDefined();
|
||||||
expect(newTickets.length).toBeGreaterThan(0);
|
expect(newTickets.length).toBeGreaterThan(0);
|
||||||
|
@ -30,7 +30,7 @@ describe('Ticket cloning - clone function', () => {
|
||||||
const negative = true;
|
const negative = true;
|
||||||
const salesIds = [7, 8];
|
const salesIds = [7, 8];
|
||||||
const servicesIds = [];
|
const servicesIds = [];
|
||||||
const newTickets = await models.Sale.clone(ctx, salesIds, servicesIds, false, negative, options);
|
const newTickets = await models.Sale.clone(ctx, salesIds, servicesIds, null, false, negative, options);
|
||||||
|
|
||||||
for (const ticket of newTickets) {
|
for (const ticket of newTickets) {
|
||||||
const sales = await models.Sale.find({where: {ticketFk: ticket.id}}, options);
|
const sales = await models.Sale.find({where: {ticketFk: ticket.id}}, options);
|
||||||
|
@ -43,7 +43,7 @@ describe('Ticket cloning - clone function', () => {
|
||||||
it('should create new components and services for cloned tickets', async() => {
|
it('should create new components and services for cloned tickets', async() => {
|
||||||
const servicesIds = [2];
|
const servicesIds = [2];
|
||||||
const salesIds = [5];
|
const salesIds = [5];
|
||||||
const newTickets = await models.Sale.clone(ctx, salesIds, servicesIds, false, false, options);
|
const newTickets = await models.Sale.clone(ctx, salesIds, servicesIds, null, false, false, options);
|
||||||
|
|
||||||
for (const ticket of newTickets) {
|
for (const ticket of newTickets) {
|
||||||
const sale = await models.Sale.findOne({where: {ticketFk: ticket.id}}, options);
|
const sale = await models.Sale.findOne({where: {ticketFk: ticket.id}}, options);
|
||||||
|
@ -58,7 +58,7 @@ describe('Ticket cloning - clone function', () => {
|
||||||
it('should create a ticket without sales', async() => {
|
it('should create a ticket without sales', async() => {
|
||||||
const servicesIds = [4];
|
const servicesIds = [4];
|
||||||
|
|
||||||
const tickets = await models.Sale.clone(ctx, null, servicesIds, false, false, options);
|
const tickets = await models.Sale.clone(ctx, null, servicesIds, null, false, false, options);
|
||||||
const refundedTicket = await getTicketRefund(tickets[0].id, options);
|
const refundedTicket = await getTicketRefund(tickets[0].id, options);
|
||||||
|
|
||||||
expect(refundedTicket).toBeDefined();
|
expect(refundedTicket).toBeDefined();
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
module.exports = Self => {
|
|
||||||
Self.remoteMethodCtx('clone', {
|
|
||||||
description: 'clone a ticket and return the new ticket id',
|
|
||||||
accessType: 'WRITE',
|
|
||||||
accepts: [{
|
|
||||||
arg: 'id',
|
|
||||||
type: 'number',
|
|
||||||
required: true,
|
|
||||||
description: 'The ticket id',
|
|
||||||
http: {source: 'path'}
|
|
||||||
}, {
|
|
||||||
arg: 'shipped',
|
|
||||||
type: 'date',
|
|
||||||
}, {
|
|
||||||
arg: 'withWarehouse',
|
|
||||||
type: 'boolean',
|
|
||||||
}
|
|
||||||
],
|
|
||||||
returns: {
|
|
||||||
type: 'number',
|
|
||||||
root: true
|
|
||||||
},
|
|
||||||
http: {
|
|
||||||
path: `/:id/clone`,
|
|
||||||
verb: 'POST'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Self.clone = async(ctx, id, shipped, withWarehouse, options) => {
|
|
||||||
const myOptions = {userId: ctx.req.accessToken.userId};
|
|
||||||
let tx;
|
|
||||||
|
|
||||||
if (typeof options == 'object')
|
|
||||||
Object.assign(myOptions, options);
|
|
||||||
|
|
||||||
if (!myOptions.transaction) {
|
|
||||||
tx = await Self.beginTransaction({});
|
|
||||||
myOptions.transaction = tx;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const [, [{clonedTicketId}]] = await Self.rawSql(`
|
|
||||||
CALL vn.ticket_cloneAll(?, ?, ?, @clonedTicketId);
|
|
||||||
SELECT @clonedTicketId clonedTicketId;`,
|
|
||||||
[id, shipped, withWarehouse], myOptions);
|
|
||||||
|
|
||||||
if (tx) await tx.commit();
|
|
||||||
return clonedTicketId;
|
|
||||||
} catch (e) {
|
|
||||||
if (tx) await tx.rollback();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('cloneAll', {
|
||||||
|
description: 'Clone tickets, sales, services and packages',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'ticketsIds',
|
||||||
|
type: ['number'],
|
||||||
|
required: true,
|
||||||
|
description: 'IDs of the tickets to clone'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'withWarehouse',
|
||||||
|
type: 'boolean',
|
||||||
|
required: true,
|
||||||
|
description: 'true: keep original warehouse; false: set to null'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'negative',
|
||||||
|
type: 'boolean',
|
||||||
|
required: true,
|
||||||
|
description: 'true: invert quantities; false: keep as is.'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: ['object'],
|
||||||
|
root: true,
|
||||||
|
description: 'The cloned tickets with associated data'
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/cloneAll`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.cloneAll = async(ctx, ticketsIds, withWarehouse, negative, options) => {
|
||||||
|
const models = Self.app.models;
|
||||||
|
const myOptions = typeof options == 'object' ? {...options} : {};
|
||||||
|
let tx;
|
||||||
|
|
||||||
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const filter = {where: {ticketFk: {inq: ticketsIds}}};
|
||||||
|
|
||||||
|
const [sales, services, ticketPackaging] = await Promise.all([
|
||||||
|
models.Sale.find(filter, myOptions),
|
||||||
|
models.TicketService.find(filter, myOptions),
|
||||||
|
models.TicketPackaging.find(filter, myOptions)
|
||||||
|
]);
|
||||||
|
|
||||||
|
const salesIds = sales.map(({id}) => id);
|
||||||
|
const servicesIds = services.map(({id}) => id);
|
||||||
|
const ticketPackagingIds = ticketPackaging.map(({id}) => id);
|
||||||
|
|
||||||
|
const clonedTickets = await models.Sale.clone(
|
||||||
|
ctx,
|
||||||
|
salesIds,
|
||||||
|
servicesIds,
|
||||||
|
ticketPackagingIds,
|
||||||
|
withWarehouse,
|
||||||
|
negative,
|
||||||
|
myOptions
|
||||||
|
);
|
||||||
|
|
||||||
|
if (tx) await tx.commit();
|
||||||
|
|
||||||
|
return clonedTickets;
|
||||||
|
} catch (e) {
|
||||||
|
if (tx) await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -93,8 +93,8 @@ module.exports = Self => {
|
||||||
SUM(t.isDeleted) hasErrorDeleted,
|
SUM(t.isDeleted) hasErrorDeleted,
|
||||||
SUM(itc.id IS NULL) hasErrorItemTaxCountry,
|
SUM(itc.id IS NULL) hasErrorItemTaxCountry,
|
||||||
SUM(a.id IS NULL) hasErrorAddress,
|
SUM(a.id IS NULL) hasErrorAddress,
|
||||||
SUM(ios.code IS NOT NULL
|
SUM(ios.code IS NOT NULL
|
||||||
AND(ad.customsAgentFk IS NULL
|
AND(ad.customsAgentFk IS NULL
|
||||||
OR ad.incotermsFk IS NULL)) hasErrorInfoTaxAreaWorld,
|
OR ad.incotermsFk IS NULL)) hasErrorInfoTaxAreaWorld,
|
||||||
t.clientFk clientFk
|
t.clientFk clientFk
|
||||||
FROM ticket t
|
FROM ticket t
|
||||||
|
@ -113,24 +113,24 @@ module.exports = Self => {
|
||||||
LEFT JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk
|
LEFT JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk
|
||||||
LEFT JOIN itemTaxCountry itc ON itc.itemFk = i.id
|
LEFT JOIN itemTaxCountry itc ON itc.itemFk = i.id
|
||||||
AND itc.countryFk = su.countryFk
|
AND itc.countryFk = su.countryFk
|
||||||
LEFT JOIN vn.invoiceOutSerial ios ON ios.taxAreaFk = 'WORLD'
|
LEFT JOIN vn.invoiceOutSerial ios ON ios.taxAreaFk = 'WORLD'
|
||||||
AND ios.code = invoiceSerial(t.clientFk, t.companyFk, 'M')
|
AND ios.code = invoiceSerial(t.clientFk, t.companyFk, 'multiple')
|
||||||
WHERE (al.code = 'PACKED' OR (am.code = 'refund' AND al.code <> 'delivered'))
|
WHERE (al.code = 'PACKED' OR (am.code = 'refund' AND al.code <> 'delivered'))
|
||||||
AND DATE(t.shipped) BETWEEN ? - INTERVAL 2 DAY AND util.dayEnd(?)
|
AND DATE(t.shipped) BETWEEN ? - INTERVAL 2 DAY AND util.dayEnd(?)
|
||||||
AND t.refFk IS NULL
|
AND t.refFk IS NULL
|
||||||
AND IFNULL(a.hasDailyInvoice, co.hasDailyInvoice)
|
AND IFNULL(a.hasDailyInvoice, co.hasDailyInvoice)
|
||||||
GROUP BY ticketFk
|
GROUP BY ticketFk
|
||||||
HAVING hasErrorToInvoice
|
HAVING hasErrorToInvoice
|
||||||
OR hasErrorTaxDataChecked
|
OR hasErrorTaxDataChecked
|
||||||
OR hasErrorDeleted
|
OR hasErrorDeleted
|
||||||
OR hasErrorItemTaxCountry
|
OR hasErrorItemTaxCountry
|
||||||
OR hasErrorAddress
|
OR hasErrorAddress
|
||||||
OR hasErrorInfoTaxAreaWorld
|
OR hasErrorInfoTaxAreaWorld
|
||||||
)sub
|
)sub
|
||||||
)sub2
|
)sub2
|
||||||
) SELECT IF(errors = '{"tickets": null}',
|
) SELECT IF(errors = '{"tickets": null}',
|
||||||
'No errors',
|
'No errors',
|
||||||
util.notification_send('invoice-ticket-closure', errors, NULL))
|
util.notification_send('invoice-ticket-closure', errors, NULL))
|
||||||
FROM ticketNotInvoiceable`, [toDate, toDate]);
|
FROM ticketNotInvoiceable`, [toDate, toDate]);
|
||||||
|
|
||||||
await closure(ctx, Self, tickets);
|
await closure(ctx, Self, tickets);
|
||||||
|
|
|
@ -95,7 +95,7 @@ module.exports = function(Self) {
|
||||||
FROM vn.ticket
|
FROM vn.ticket
|
||||||
WHERE id IN (?)
|
WHERE id IN (?)
|
||||||
`, [ticketsIds], myOptions);
|
`, [ticketsIds], myOptions);
|
||||||
return models.Ticket.makeInvoice(ctx, 'R', companyId, Date.vnNew(), invoiceCorrection, myOptions);
|
return models.Ticket.makeInvoice(ctx, 'quick', companyId, Date.vnNew(), invoiceCorrection, myOptions);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
module.exports = Self => {
|
|
||||||
Self.remoteMethodCtx('refund', {
|
|
||||||
description: 'Create refund tickets with all their sales and services',
|
|
||||||
accessType: 'WRITE',
|
|
||||||
accepts: [
|
|
||||||
{
|
|
||||||
arg: 'ticketsIds',
|
|
||||||
type: ['number'],
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
arg: 'withWarehouse',
|
|
||||||
type: 'boolean',
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
returns: {
|
|
||||||
type: ['object'],
|
|
||||||
root: true
|
|
||||||
},
|
|
||||||
http: {
|
|
||||||
path: `/refund`,
|
|
||||||
verb: 'POST'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Self.refund = async(ctx, ticketsIds, withWarehouse, options) => {
|
|
||||||
const models = Self.app.models;
|
|
||||||
const myOptions = {};
|
|
||||||
let tx;
|
|
||||||
|
|
||||||
if (typeof options == 'object')
|
|
||||||
Object.assign(myOptions, options);
|
|
||||||
|
|
||||||
if (!myOptions.transaction) {
|
|
||||||
tx = await Self.beginTransaction({});
|
|
||||||
myOptions.transaction = tx;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const filter = {where: {ticketFk: {inq: ticketsIds}}};
|
|
||||||
const sales = await models.Sale.find(filter, myOptions);
|
|
||||||
const salesIds = sales.map(sale => sale.id);
|
|
||||||
|
|
||||||
const services = await models.TicketService.find(filter, myOptions);
|
|
||||||
const servicesIds = services.map(service => service.id);
|
|
||||||
|
|
||||||
const refundedTickets = await models.Sale.clone(ctx, salesIds, servicesIds, withWarehouse, true, myOptions);
|
|
||||||
|
|
||||||
if (tx) await tx.commit();
|
|
||||||
|
|
||||||
return refundedTickets;
|
|
||||||
} catch (e) {
|
|
||||||
if (tx) await tx.rollback();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -1,43 +0,0 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
|
||||||
|
|
||||||
describe('Ticket cloning - clone function', () => {
|
|
||||||
const ctx = beforeAll.getCtx();
|
|
||||||
let options;
|
|
||||||
let tx;
|
|
||||||
const ticketId = 1;
|
|
||||||
const shipped = Date.vnNew();
|
|
||||||
|
|
||||||
beforeEach(async() => {
|
|
||||||
options = {transaction: tx};
|
|
||||||
tx = await models.Ticket.beginTransaction({});
|
|
||||||
options.transaction = tx;
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(async() => {
|
|
||||||
await tx.rollback();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should clone a new ticket without warehouse', async() => {
|
|
||||||
const originalTicket = await models.Ticket.findById(ticketId, null, options);
|
|
||||||
|
|
||||||
const newTicketId = await models.Ticket.clone(ctx, ticketId, shipped, false, options);
|
|
||||||
const newTicket = await models.Ticket.findById(newTicketId, null, options);
|
|
||||||
|
|
||||||
expect(newTicket.clientFk).toEqual(originalTicket.clientFk);
|
|
||||||
expect(newTicket.companyFk).toEqual(originalTicket.companyFk);
|
|
||||||
expect(newTicket.addressFk).toEqual(originalTicket.addressFk);
|
|
||||||
expect(newTicket.warehouseFk).toBeFalsy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should clone a new ticket with warehouse', async() => {
|
|
||||||
const originalTicket = await models.Ticket.findById(ticketId, null, options);
|
|
||||||
|
|
||||||
const newTicketId = await models.Ticket.clone(ctx, ticketId, shipped, true, options);
|
|
||||||
const newTicket = await models.Ticket.findById(newTicketId, null, options);
|
|
||||||
|
|
||||||
expect(newTicket.clientFk).toEqual(originalTicket.clientFk);
|
|
||||||
expect(newTicket.companyFk).toEqual(originalTicket.companyFk);
|
|
||||||
expect(newTicket.addressFk).toEqual(originalTicket.addressFk);
|
|
||||||
expect(newTicket.warehouseFk).toEqual(originalTicket.warehouseFk);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
|
describe('Ticket cloning - cloneAll function', () => {
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 1},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const ctx = {req: activeCtx};
|
||||||
|
let options;
|
||||||
|
let tx;
|
||||||
|
const ticketIds = [1, 2];
|
||||||
|
const withWarehouse = true;
|
||||||
|
const negative = false;
|
||||||
|
|
||||||
|
beforeEach(async() => {
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({active: ctx.req});
|
||||||
|
tx = await models.Ticket.beginTransaction({});
|
||||||
|
options = {transaction: tx};
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async() => {
|
||||||
|
if (tx)
|
||||||
|
await tx.rollback();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should clone all provided tickets with their associated sales, services, and packages', async() => {
|
||||||
|
const originalTickets = await models.Ticket.find({where: {id: {inq: ticketIds}}}, options);
|
||||||
|
const originalSales = await models.Sale.find({where: {ticketFk: {inq: ticketIds}}}, options);
|
||||||
|
const originalServices = await models.TicketService.find({where: {ticketFk: {inq: ticketIds}}}, options);
|
||||||
|
const originalTicketPackaging =
|
||||||
|
await models.TicketPackaging.find({where: {ticketFk: {inq: ticketIds}}}, options);
|
||||||
|
|
||||||
|
// Pass the ctx correctly to the cloneAll function
|
||||||
|
const clonedTickets = await models.Ticket.cloneAll(ctx, ticketIds, withWarehouse, negative, options);
|
||||||
|
|
||||||
|
expect(clonedTickets.length).toEqual(originalTickets.length);
|
||||||
|
|
||||||
|
const clonedSales = await models.Sale.find({where: {ticketFk: {inq: clonedTickets.map(t => t.id)}}}, options);
|
||||||
|
const clonedServices =
|
||||||
|
await models.TicketService.find({where: {ticketFk: {inq: clonedTickets.map(t => t.id)}}}, options);
|
||||||
|
const clonedTicketPackaging =
|
||||||
|
await models.TicketPackaging.find({where: {ticketFk: {inq: clonedTickets.map(t => t.id)}}}, options);
|
||||||
|
|
||||||
|
expect(clonedSales.length).toEqual(originalSales.length);
|
||||||
|
expect(clonedServices.length).toEqual(originalServices.length);
|
||||||
|
expect(clonedTicketPackaging.length).toEqual(originalTicketPackaging.length);
|
||||||
|
});
|
||||||
|
});
|
|
@ -3,7 +3,7 @@ const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('ticket makeInvoice()', () => {
|
describe('ticket makeInvoice()', () => {
|
||||||
const userId = 19;
|
const userId = 19;
|
||||||
const invoiceType = 'R';
|
const invoiceType = 'quick';
|
||||||
const companyFk = 442;
|
const companyFk = 442;
|
||||||
const invoiceDate = Date.vnNew();
|
const invoiceDate = Date.vnNew();
|
||||||
const activeCtx = {
|
const activeCtx = {
|
||||||
|
|
|
@ -26,7 +26,7 @@ module.exports = function(Self) {
|
||||||
require('../methods/ticket/isLocked')(Self);
|
require('../methods/ticket/isLocked')(Self);
|
||||||
require('../methods/ticket/freightCost')(Self);
|
require('../methods/ticket/freightCost')(Self);
|
||||||
require('../methods/ticket/getComponentsSum')(Self);
|
require('../methods/ticket/getComponentsSum')(Self);
|
||||||
require('../methods/ticket/refund')(Self);
|
require('../methods/ticket/cloneAll')(Self);
|
||||||
require('../methods/ticket/deliveryNotePdf')(Self);
|
require('../methods/ticket/deliveryNotePdf')(Self);
|
||||||
require('../methods/ticket/deliveryNoteEmail')(Self);
|
require('../methods/ticket/deliveryNoteEmail')(Self);
|
||||||
require('../methods/ticket/deliveryNoteCsv')(Self);
|
require('../methods/ticket/deliveryNoteCsv')(Self);
|
||||||
|
@ -46,5 +46,4 @@ module.exports = function(Self) {
|
||||||
require('../methods/ticket/invoiceTicketsAndPdf')(Self);
|
require('../methods/ticket/invoiceTicketsAndPdf')(Self);
|
||||||
require('../methods/ticket/docuwareDownload')(Self);
|
require('../methods/ticket/docuwareDownload')(Self);
|
||||||
require('../methods/ticket/myLastModified')(Self);
|
require('../methods/ticket/myLastModified')(Self);
|
||||||
require('../methods/ticket/clone')(Self);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -287,15 +287,24 @@ class Controller extends Section {
|
||||||
}
|
}
|
||||||
|
|
||||||
refund(withWarehouse) {
|
refund(withWarehouse) {
|
||||||
const params = {ticketsIds: [this.id], withWarehouse: withWarehouse};
|
const params = {
|
||||||
const query = 'Tickets/refund';
|
ticketsIds: [this.id],
|
||||||
|
withWarehouse: withWarehouse,
|
||||||
|
negative: true // Asumimos que queremos cantidades negativas para reembolsos
|
||||||
|
};
|
||||||
|
const query = 'Tickets/cloneAll';
|
||||||
return this.$http.post(query, params)
|
return this.$http.post(query, params)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
const [refundTicket] = res.data;
|
const [refundTicket] = res.data;
|
||||||
this.vnApp.showSuccess(this.$t('The following refund ticket have been created', {
|
this.vnApp.showSuccess(this.$t('The following refund ticket has been created', {
|
||||||
ticketId: refundTicket.id
|
ticketId: refundTicket.id
|
||||||
}));
|
}));
|
||||||
this.$state.go('ticket.card.sale', {id: refundTicket.id});
|
this.$state.go('ticket.card.sale', {id: refundTicket.id});
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.vnApp.showError(this.$t('Error creating refund ticket', {
|
||||||
|
error: error.data?.error?.message || 'Unknown error'
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -217,24 +217,6 @@ describe('Ticket Component vnTicketDescriptorMenu', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('refund()', () => {
|
|
||||||
it('should make a query and go to ticket.card.sale', () => {
|
|
||||||
controller.$state.go = jest.fn();
|
|
||||||
|
|
||||||
controller._id = ticket.id;
|
|
||||||
|
|
||||||
const params = {
|
|
||||||
ticketsIds: [16]
|
|
||||||
};
|
|
||||||
const response = {id: 99};
|
|
||||||
$httpBackend.expectPOST('Tickets/refund', params).respond([response]);
|
|
||||||
controller.refund();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.$state.go).toHaveBeenCalledWith('ticket.card.sale', response);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('sendChangesSms()', () => {
|
describe('sendChangesSms()', () => {
|
||||||
it('should make a query and open the sms dialog', () => {
|
it('should make a query and open the sms dialog', () => {
|
||||||
controller.$.sms = {open: () => {}};
|
controller.$.sms = {open: () => {}};
|
||||||
|
|
|
@ -22,7 +22,7 @@ labels AS (
|
||||||
b.id,
|
b.id,
|
||||||
b.itemFk,
|
b.itemFk,
|
||||||
p.name producer,
|
p.name producer,
|
||||||
IF(i2.id, i2.comment, i.comment) comment
|
IFNULL(i2.comment, i.comment) comment
|
||||||
FROM buy b
|
FROM buy b
|
||||||
JOIN item i ON i.id = b.itemFk
|
JOIN item i ON i.id = b.itemFk
|
||||||
LEFT JOIN producer p ON p.id = i.producerFk
|
LEFT JOIN producer p ON p.id = i.producerFk
|
||||||
|
|
|
@ -1,14 +1,20 @@
|
||||||
|
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
font-weight: 100;
|
font-weight: 100;
|
||||||
color: #555
|
color: #555
|
||||||
}
|
}
|
||||||
|
|
||||||
.report-info {
|
.report-info {
|
||||||
font-size: 20px
|
font-size: 20px
|
||||||
}
|
}
|
||||||
|
|
||||||
.description strong {
|
.description strong {
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
.nowrap {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.padding {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
.tags {
|
||||||
|
font-size: 10px;
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
|
@ -4,23 +4,23 @@
|
||||||
</template>
|
</template>
|
||||||
<div class="grid-row">
|
<div class="grid-row">
|
||||||
<div class="grid-block">
|
<div class="grid-block">
|
||||||
<div class="columns">
|
<h1 class="title uppercase">{{$t('title')}}</h1>
|
||||||
|
<div class="columns header-tables">
|
||||||
<div class="size50">
|
<div class="size50">
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<h1 class="title uppercase">{{$t('title')}}</h1>
|
|
||||||
<table class="row-oriented report-info">
|
<table class="row-oriented report-info">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="font gray uppercase">{{$t('entryId')}}</td>
|
<td class="font gray uppercase padding nowrap">{{$t('entryId')}}</td>
|
||||||
<th>{{entry.id}}</th>
|
<th>{{entry.id}}</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="font gray uppercase">{{$t('date')}}</td>
|
<td class="font gray uppercase padding nowrap">{{$t('date')}}</td>
|
||||||
<th>{{formatDate(entry.landed,'%d-%m-%Y')}}</th>
|
<th>{{formatDate(entry.landed,'%d-%m-%Y')}}</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="font gray uppercase">{{$t('ref')}}</td>
|
<td class="font gray uppercase padding nowrap">{{$t('ref')}}</td>
|
||||||
<th>{{entry.invoiceNumber}}</th>
|
<th>{{entry.invoiceNumber | dashIfEmpty}}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -38,42 +38,56 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<table class="column-oriented vn-mt-ml">
|
<table class="column-oriented vn-mt-ml border-collapse">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="number">{{$t('boxes')}}</th>
|
<th class="number">{{$t('boxes')}}</th>
|
||||||
|
<th width="5%" class="number"></th>
|
||||||
<th class="number">{{$t('packing')}}</th>
|
<th class="number">{{$t('packing')}}</th>
|
||||||
<th width="50%">{{$t('concept')}}</th>
|
<th width="40%">{{$t('concept')}}</th>
|
||||||
|
<th width="10%">{{$t('reference')}}</th>
|
||||||
|
<th width="10%">{{$t('tags')}}</th>
|
||||||
<th width="10%" class="number">{{$t('quantity')}}</th>
|
<th width="10%" class="number">{{$t('quantity')}}</th>
|
||||||
|
<th width="5%" class="number"></th>
|
||||||
<th width="15%" class="number">{{$t('price')}}</th>
|
<th width="15%" class="number">{{$t('price')}}</th>
|
||||||
|
<th width="5%" class="number"></th>
|
||||||
<th width="15%" class="number">{{$t('amount')}}</th>
|
<th width="15%" class="number">{{$t('amount')}}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody v-for="buy in buys">
|
<tbody v-for="buy in buys">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="number">{{buy.box}}</td>
|
<td class="number">{{buy.stickers}}</td>
|
||||||
|
<td width="5%" class="number">x</td>
|
||||||
<td class="number">{{buy.packing}}</td>
|
<td class="number">{{buy.packing}}</td>
|
||||||
<td width="50%">{{buy.itemName}}</td>
|
<td width="40%" class="nowrap">{{buy.name}}</td>
|
||||||
|
<td width="10%">{{buy.comment}}</td>
|
||||||
|
<td width="10%" class="font light-gray tags">
|
||||||
|
<span v-if="buy.value5" class="nowrap"><strong>{{buy.tag5}} → </strong>{{buy.value5}} </span>
|
||||||
|
<span v-if="buy.value6" class="nowrap"><strong>{{buy.tag6}} → </strong>{{buy.value6}} </span>
|
||||||
|
<span v-if="buy.value7" class="nowrap"><strong>{{buy.tag7}} → </strong>{{buy.value7}} </span>
|
||||||
|
</td>
|
||||||
<td width="10%" class="number">{{buy.quantity | number($i18n.locale)}}</td>
|
<td width="10%" class="number">{{buy.quantity | number($i18n.locale)}}</td>
|
||||||
|
<td width="5%" class="number">x</td>
|
||||||
<td width="15%" class="number">{{buy.buyingValue | currency('EUR', $i18n.locale)}}</td>
|
<td width="15%" class="number">{{buy.buyingValue | currency('EUR', $i18n.locale)}}</td>
|
||||||
|
<td width="5%" class="number">=</td>
|
||||||
<td width="15%" class="number">
|
<td width="15%" class="number">
|
||||||
{{buy.buyingValue * buy.quantity | currency('EUR', $i18n.locale)}}
|
{{buy.buyingValue * buy.quantity | currency('EUR', $i18n.locale)}}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="description font light-gray">
|
|
||||||
<td colspan="7">
|
|
||||||
<span v-if="buy.value5"> <strong>{{buy.tag5}}</strong> {{buy.value5}} </span>
|
|
||||||
<span v-if="buy.value6"> <strong>{{buy.tag6}}</strong> {{buy.value6}} </span>
|
|
||||||
<span v-if="buy.value7"> <strong>{{buy.tag7}}</strong> {{buy.value7}} </span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
</tbody>
|
||||||
<tfoot>
|
<tfoot>
|
||||||
<tr>
|
<tr class="font bold">
|
||||||
<td colspan="5" class="font bold">
|
<td class="number">{{getTotalBy('stickers')}}</td>
|
||||||
<span class="pull-right">{{$t('total')}}</span>
|
<td></td>
|
||||||
</td>
|
<td></td>
|
||||||
<td class="number">{{getTotal() | currency('EUR', $i18n.locale)}}</td>
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td class="number">{{getTotalBy('quantity') | number($i18n.locale)}}</td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td class="number">{{getTotalBy('amount') | currency('EUR', $i18n.locale)}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tfoot>
|
</tfoot>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -13,13 +13,17 @@ module.exports = {
|
||||||
return {totalBalance: 0.00};
|
return {totalBalance: 0.00};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getTotal() {
|
getTotalBy(property) {
|
||||||
let total = 0.00;
|
return this.buys.reduce((total, buy) => {
|
||||||
this.buys.forEach(buy => {
|
switch (property) {
|
||||||
total += buy.quantity * buy.buyingValue;
|
case 'amount':
|
||||||
});
|
return total + buy.quantity * buy.buyingValue;
|
||||||
|
case 'quantity':
|
||||||
return total;
|
return total + buy.quantity;
|
||||||
|
case 'stickers':
|
||||||
|
return total + buy.stickers;
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -2,7 +2,7 @@ reportName: pedido-de-entrada
|
||||||
title: Pedido
|
title: Pedido
|
||||||
supplierName: Proveedor
|
supplierName: Proveedor
|
||||||
supplierStreet: Dirección
|
supplierStreet: Dirección
|
||||||
entryId: Referencia interna
|
entryId: Nº Entrada
|
||||||
date: Fecha
|
date: Fecha
|
||||||
ref: Nº Factura
|
ref: Nº Factura
|
||||||
boxes: Cajas
|
boxes: Cajas
|
||||||
|
@ -14,4 +14,6 @@ concept: Descripción
|
||||||
total: Total
|
total: Total
|
||||||
entry: Entrada {0}
|
entry: Entrada {0}
|
||||||
supplierData: Datos del proveedor
|
supplierData: Datos del proveedor
|
||||||
notes: Notas
|
notes: Notas
|
||||||
|
reference: Referencia
|
||||||
|
tags: Tags
|
|
@ -1,16 +1,17 @@
|
||||||
SELECT
|
SELECT b.itemFk,
|
||||||
b.itemFk,
|
b.quantity,
|
||||||
b.quantity,
|
b.buyingValue,
|
||||||
b.buyingValue,
|
b.stickers,
|
||||||
b.stickers box,
|
b.packing,
|
||||||
b.packing,
|
i.name,
|
||||||
i.name itemName,
|
IFNULL(i2.comment, i.comment) comment,
|
||||||
i.tag5,
|
i.tag5,
|
||||||
i.value5,
|
i.value5,
|
||||||
i.tag6,
|
i.tag6,
|
||||||
i.value6,
|
i.value6,
|
||||||
i.tag7,
|
i.tag7,
|
||||||
i.value7
|
i.value7
|
||||||
FROM buy b
|
FROM buy b
|
||||||
JOIN item i ON i.id = b.itemFk
|
JOIN item i ON i.id = b.itemFk
|
||||||
WHERE b.entryFk = ?
|
LEFT JOIN item i2 ON i2.id = b.itemOriginalFk
|
||||||
|
WHERE b.entryFk = ?
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
SELECT
|
SELECT e.id,
|
||||||
e.id,
|
e.invoiceNumber,
|
||||||
e.invoiceNumber,
|
c.code companyCode,
|
||||||
c.code companyCode,
|
t.landed
|
||||||
t.landed
|
FROM entry e
|
||||||
FROM entry e
|
JOIN travel t ON t.id = e.travelFk
|
||||||
JOIN travel t ON t.id = e.travelFk
|
JOIN company c ON c.id = e.companyFk
|
||||||
JOIN company c ON c.id = e.companyFk
|
WHERE e.id = ?
|
||||||
WHERE e.id = ?
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
SELECT
|
SELECT s.name,
|
||||||
s.name,
|
s.street,
|
||||||
s.street,
|
s.nif,
|
||||||
s.nif,
|
s.postCode,
|
||||||
s.postCode,
|
s.city,
|
||||||
s.city,
|
p.name province
|
||||||
p.name province
|
FROM supplier s
|
||||||
FROM supplier s
|
JOIN entry e ON e.supplierFk = s.id
|
||||||
JOIN entry e ON e.supplierFk = s.id
|
LEFT JOIN province p ON p.id = s.provinceFk
|
||||||
LEFT JOIN province p ON p.id = s.provinceFk
|
WHERE e.id = ?
|
||||||
WHERE e.id = ?
|
|
||||||
|
|
Loading…
Reference in New Issue