8032-devToTest_2440 #3009
|
@ -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]);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,6 +118,9 @@
|
||||||
"NotificationSubscription": {
|
"NotificationSubscription": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"OrmConfig": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"Province": {
|
"Province": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"name": "OrmConfig",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "ormConfig"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "number",
|
||||||
|
"id": true
|
||||||
|
},
|
||||||
|
"selectLimit": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"acls": [
|
||||||
|
{
|
||||||
|
"accessType": "*",
|
||||||
|
"principalType": "ROLE",
|
||||||
|
"principalId": "$authenticated",
|
||||||
|
"permission": "ALLOW"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
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 ;
|
|
|
@ -9,10 +9,11 @@ BEGIN
|
||||||
DECLARE vWarehouseFk INT;
|
DECLARE vWarehouseFk INT;
|
||||||
DECLARE vWagons INT;
|
DECLARE vWagons INT;
|
||||||
DECLARE vTrainFk INT;
|
DECLARE vTrainFk INT;
|
||||||
DECLARE vLinesLimit INT DEFAULT NULL;
|
DECLARE vLinesLimit INT;
|
||||||
DECLARE vTicketLines INT;
|
DECLARE vTicketLines INT;
|
||||||
DECLARE vVolumeLimit DECIMAL DEFAULT NULL;
|
DECLARE vVolumeLimit DECIMAL;
|
||||||
DECLARE vTicketVolume DECIMAL;
|
DECLARE vTicketVolume DECIMAL;
|
||||||
|
DECLARE vSizeLimit INT;
|
||||||
DECLARE vMaxTickets INT;
|
DECLARE vMaxTickets INT;
|
||||||
DECLARE vStateFk VARCHAR(45);
|
DECLARE vStateFk VARCHAR(45);
|
||||||
DECLARE vFirstTicketFk INT;
|
DECLARE vFirstTicketFk INT;
|
||||||
|
@ -77,6 +78,7 @@ BEGIN
|
||||||
o.trainFk,
|
o.trainFk,
|
||||||
o.linesLimit,
|
o.linesLimit,
|
||||||
o.volumeLimit,
|
o.volumeLimit,
|
||||||
|
o.sizeLimit,
|
||||||
pc.collection_new_lockname
|
pc.collection_new_lockname
|
||||||
INTO vMaxTickets,
|
INTO vMaxTickets,
|
||||||
vHasUniqueCollectionTime,
|
vHasUniqueCollectionTime,
|
||||||
|
@ -88,6 +90,7 @@ BEGIN
|
||||||
vTrainFk,
|
vTrainFk,
|
||||||
vLinesLimit,
|
vLinesLimit,
|
||||||
vVolumeLimit,
|
vVolumeLimit,
|
||||||
|
vSizeLimit,
|
||||||
vLockName
|
vLockName
|
||||||
FROM productionConfig pc
|
FROM productionConfig pc
|
||||||
JOIN worker w ON w.id = vUserFk
|
JOIN worker w ON w.id = vUserFk
|
||||||
|
@ -172,6 +175,14 @@ BEGIN
|
||||||
JOIN state s ON s.id = pb.state
|
JOIN state s ON s.id = pb.state
|
||||||
JOIN agencyMode am ON am.id = pb.agencyModeFk
|
JOIN agencyMode am ON am.id = pb.agencyModeFk
|
||||||
JOIN agency a ON a.id = am.agencyFk
|
JOIN agency a ON a.id = am.agencyFk
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT pb.ticketFk, MAX(i.`size`) maxSize
|
||||||
|
FROM tmp.productionBuffer pb
|
||||||
|
JOIN ticket t ON t.id = pb.ticketfk
|
||||||
|
JOIN sale s ON s.ticketFk = t.id
|
||||||
|
JOIN item i ON i.id = s.itemFk
|
||||||
|
GROUP BY pb.ticketFk
|
||||||
|
) sub ON sub.ticketFk = pb.ticketFk
|
||||||
JOIN productionConfig pc
|
JOIN productionConfig pc
|
||||||
WHERE pb.shipped <> util.VN_CURDATE()
|
WHERE pb.shipped <> util.VN_CURDATE()
|
||||||
OR (pb.ubicacion IS NULL AND a.isOwn)
|
OR (pb.ubicacion IS NULL AND a.isOwn)
|
||||||
|
@ -183,8 +194,9 @@ BEGIN
|
||||||
OR (NOT pb.V AND vItemPackingTypeFk = 'V')
|
OR (NOT pb.V AND vItemPackingTypeFk = 'V')
|
||||||
OR (pc.isPreviousPreparationRequired AND pb.previousWithoutParking)
|
OR (pc.isPreviousPreparationRequired AND pb.previousWithoutParking)
|
||||||
OR LENGTH(pb.problem) > 0
|
OR LENGTH(pb.problem) > 0
|
||||||
OR (pb.lines >= vLinesLimit AND vLinesLimit IS NOT NULL)
|
OR (pb.lines > vLinesLimit AND vLinesLimit IS NOT NULL)
|
||||||
OR (pb.m3 >= vVolumeLimit AND vVolumeLimit IS NOT NULL);
|
OR (pb.m3 > vVolumeLimit AND vVolumeLimit IS NOT NULL)
|
||||||
|
OR ((sub.maxSize > vSizeLimit OR sub.maxSize IS NOT NULL) AND vSizeLimit IS NOT NULL);
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
-- Es importante que el primer ticket se coja en todos los casos
|
-- Es importante que el primer ticket se coja en todos los casos
|
||||||
|
|
|
@ -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.operator
|
||||||
|
ADD COLUMN sizeLimit int(10) unsigned DEFAULT 90 NULL COMMENT 'Límite de altura en una colección para la asignación de pedidos' AFTER volumeLimit,
|
||||||
|
MODIFY COLUMN linesLimit int(10) unsigned DEFAULT 20 NULL COMMENT 'Límite de lineas en una colección para la asignación de pedidos';
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE vn.ticket DROP FOREIGN KEY ticket_FK;
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE vn.invoiceOut DROP KEY Id_Factura;
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE vn.invoiceOut MODIFY COLUMN id int(10) unsigned NOT NULL;
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE vn.invoiceCorrection DROP FOREIGN KEY corrected_fk;
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE vn.invoiceCorrection DROP FOREIGN KEY correcting_fk;
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE vn.invoiceOutExpense DROP FOREIGN KEY invoiceOutExpence_FK_1;
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE vn.invoiceOutTax DROP FOREIGN KEY invoiceOutFk;
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE vn.invoiceOut DROP PRIMARY KEY;
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE vn.invoiceOut ADD CONSTRAINT invoiceOut_pk PRIMARY KEY (id);
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE vn.invoiceOut ADD CONSTRAINT invoiceOut_unique UNIQUE KEY (`ref`);
|
|
@ -0,0 +1,5 @@
|
||||||
|
UPDATE vn.invoiceOut
|
||||||
|
SET id = (SELECT MAX(id) + 1 FROM vn.invoiceOut)
|
||||||
|
WHERE id = 0;
|
||||||
|
|
||||||
|
ALTER TABLE vn.invoiceOut MODIFY COLUMN id int(10) unsigned auto_increment NOT NULL;
|
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE vn.ticket ADD CONSTRAINT ticket_invoiceOut_FK
|
||||||
|
FOREIGN KEY (refFk) REFERENCES vn.invoiceOut(`ref`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE vn.invoiceCorrection ADD CONSTRAINT invoiceCorrection_invoiceOut_FK
|
||||||
|
FOREIGN KEY (correctingFk) REFERENCES vn.invoiceOut(id) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE vn.invoiceCorrection ADD CONSTRAINT invoiceCorrection_invoiceOut_FK_1
|
||||||
|
FOREIGN KEY (correctedFk) REFERENCES vn.invoiceOut(id) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE vn.invoiceOutExpense ADD CONSTRAINT invoiceOutExpense_invoiceOut_FK
|
||||||
|
FOREIGN KEY (invoiceOutFk) REFERENCES vn.invoiceOut(id) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE vn.invoiceOutTax ADD CONSTRAINT invoiceOutTax_invoiceOut_FK
|
||||||
|
FOREIGN KEY (invoiceOutFk) REFERENCES vn.invoiceOut(id) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
@ -0,0 +1,8 @@
|
||||||
|
USE vn;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS ormConfig (
|
||||||
|
id int(5) NOT NULL AUTO_INCREMENT primary key,
|
||||||
|
selectLimit int(5) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT IGNORE INTO ormConfig SET selectLimit = 1000;
|
|
@ -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';
|
|
@ -1,28 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('InvoiceIn summary path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('administrative', 'invoiceIn');
|
|
||||||
await page.accessToSearchResult('1');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reach the summary section', async() => {
|
|
||||||
await page.waitForState('invoiceIn.card.summary');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should contain some basic data from the invoice', async() => {
|
|
||||||
const result = await page.waitToGetProperty(selectors.invoiceInSummary.supplierRef, 'innerText');
|
|
||||||
|
|
||||||
expect(result).toEqual('1234');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,52 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('InvoiceIn descriptor path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('administrative', 'invoiceIn');
|
|
||||||
await page.accessToSearchResult('10');
|
|
||||||
await page.accessToSection('invoiceIn.card.basicData');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should clone the invoiceIn using the descriptor more menu', async() => {
|
|
||||||
await page.waitToClick(selectors.invoiceInDescriptor.moreMenu);
|
|
||||||
await page.waitToClick(selectors.invoiceInDescriptor.moreMenuCloneInvoiceIn);
|
|
||||||
await page.waitToClick(selectors.invoiceInDescriptor.acceptButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('InvoiceIn cloned');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have been redirected to the created invoiceIn summary', async() => {
|
|
||||||
await page.waitForState('invoiceIn.card.summary');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should delete the cloned invoiceIn using the descriptor more menu', async() => {
|
|
||||||
await page.waitToClick(selectors.invoiceInDescriptor.moreMenu);
|
|
||||||
await page.waitToClick(selectors.invoiceInDescriptor.moreMenuDeleteInvoiceIn);
|
|
||||||
await page.waitToClick(selectors.invoiceInDescriptor.acceptButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('InvoiceIn deleted');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have been relocated to the invoiceOut index', async() => {
|
|
||||||
await page.waitForState('invoiceIn.index');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should search for the deleted invouceOut to find no results`, async() => {
|
|
||||||
await page.doSearch('10');
|
|
||||||
const nResults = await page.countElement(selectors.invoiceOutIndex.searchResult);
|
|
||||||
|
|
||||||
expect(nResults).toEqual(0);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,196 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('InvoiceIn basic data path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
let newDms;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('administrative', 'invoiceIn');
|
|
||||||
await page.accessToSearchResult('1');
|
|
||||||
await page.accessToSection('invoiceIn.card.basicData');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should edit the invoiceIn basic data`, async() => {
|
|
||||||
const now = Date.vnNew();
|
|
||||||
await page.pickDate(selectors.invoiceInBasicData.issued, now);
|
|
||||||
await page.pickDate(selectors.invoiceInBasicData.operated, now);
|
|
||||||
await page.autocompleteSearch(selectors.invoiceInBasicData.supplier, 'Verdnatura');
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.supplierRef);
|
|
||||||
await page.write(selectors.invoiceInBasicData.supplierRef, '9999');
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.dms);
|
|
||||||
await page.write(selectors.invoiceInBasicData.dms, '2');
|
|
||||||
await page.pickDate(selectors.invoiceInBasicData.bookEntried, now);
|
|
||||||
await page.pickDate(selectors.invoiceInBasicData.booked, now);
|
|
||||||
await page.autocompleteSearch(selectors.invoiceInBasicData.currency, 'USD');
|
|
||||||
await page.autocompleteSearch(selectors.invoiceInBasicData.company, 'ORN');
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.save);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should confirm the invoiceIn supplier was edited`, async() => {
|
|
||||||
await page.reloadSection('invoiceIn.card.basicData');
|
|
||||||
const result = await page.waitToGetProperty(selectors.invoiceInBasicData.supplier, 'value');
|
|
||||||
|
|
||||||
expect(result).toContain('Verdnatura');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should confirm the invoiceIn supplierRef was edited`, async() => {
|
|
||||||
const result = await page
|
|
||||||
.waitToGetProperty(selectors.invoiceInBasicData.supplierRef, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('9999');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should confirm the invoiceIn currency was edited`, async() => {
|
|
||||||
const result = await page
|
|
||||||
.waitToGetProperty(selectors.invoiceInBasicData.currency, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('USD');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should confirm the invoiceIn company was edited`, async() => {
|
|
||||||
const result = await page
|
|
||||||
.waitToGetProperty(selectors.invoiceInBasicData.company, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('ORN');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should confirm the invoiceIn dms was edited`, async() => {
|
|
||||||
const result = await page
|
|
||||||
.waitToGetProperty(selectors.invoiceInBasicData.dms, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('2');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should create a new invoiceIn dms and save the changes`, async() => {
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.dms);
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.create);
|
|
||||||
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.reference);
|
|
||||||
await page.write(selectors.invoiceInBasicData.reference, 'New Dms');
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.confirm);
|
|
||||||
let message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.companyId);
|
|
||||||
await page.autocompleteSearch(selectors.invoiceInBasicData.companyId, 'VNL');
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.confirm);
|
|
||||||
message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.warehouseId);
|
|
||||||
await page.autocompleteSearch(selectors.invoiceInBasicData.warehouseId, 'Warehouse One');
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.confirm);
|
|
||||||
message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.dmsTypeId);
|
|
||||||
await page.autocompleteSearch(selectors.invoiceInBasicData.dmsTypeId, 'Ticket');
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.confirm);
|
|
||||||
message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.description);
|
|
||||||
await page.write(selectors.invoiceInBasicData.description, 'Dms without edition.');
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.confirm);
|
|
||||||
message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('The files can\'t be empty');
|
|
||||||
|
|
||||||
let currentDir = process.cwd();
|
|
||||||
let filePath = `${currentDir}/e2e/assets/thermograph.jpeg`;
|
|
||||||
|
|
||||||
const [fileChooser] = await Promise.all([
|
|
||||||
page.waitForFileChooser(),
|
|
||||||
page.waitToClick(selectors.invoiceInBasicData.inputFile)
|
|
||||||
]);
|
|
||||||
await fileChooser.accept([filePath]);
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.confirm);
|
|
||||||
message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
|
|
||||||
newDms = await page
|
|
||||||
.waitToGetProperty(selectors.invoiceInBasicData.dms, 'value');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should confirm the invoiceIn was edited with the new dms`, async() => {
|
|
||||||
await page.reloadSection('invoiceIn.card.basicData');
|
|
||||||
const result = await page
|
|
||||||
.waitToGetProperty(selectors.invoiceInBasicData.dms, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual(newDms);
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should edit the invoiceIn`, async() => {
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.edit);
|
|
||||||
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.reference);
|
|
||||||
await page.write(selectors.invoiceInBasicData.reference, 'Dms Edited');
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.companyId);
|
|
||||||
await page.autocompleteSearch(selectors.invoiceInBasicData.companyId, 'CCs');
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.warehouseId);
|
|
||||||
await page.autocompleteSearch(selectors.invoiceInBasicData.warehouseId, 'Algemesi');
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.dmsTypeId);
|
|
||||||
await page.autocompleteSearch(selectors.invoiceInBasicData.dmsTypeId, 'Basura');
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.description);
|
|
||||||
await page.write(selectors.invoiceInBasicData.description, ' Nevermind, now is edited.');
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.confirm);
|
|
||||||
let message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should confirm the new dms has been edited`, async() => {
|
|
||||||
await page.reloadSection('invoiceIn.card.basicData');
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.edit);
|
|
||||||
|
|
||||||
const reference = await page
|
|
||||||
.waitToGetProperty(selectors.invoiceInBasicData.reference, 'value');
|
|
||||||
const companyId = await page
|
|
||||||
.waitToGetProperty(selectors.invoiceInBasicData.companyId, 'value');
|
|
||||||
const warehouseId = await page
|
|
||||||
.waitToGetProperty(selectors.invoiceInBasicData.warehouseId, 'value');
|
|
||||||
const dmsTypeId = await page
|
|
||||||
.waitToGetProperty(selectors.invoiceInBasicData.dmsTypeId, 'value');
|
|
||||||
const description = await page
|
|
||||||
.waitToGetProperty(selectors.invoiceInBasicData.description, 'value');
|
|
||||||
|
|
||||||
expect(reference).toEqual('Dms Edited');
|
|
||||||
expect(companyId).toEqual('CCs');
|
|
||||||
expect(warehouseId).toEqual('Algemesi');
|
|
||||||
expect(dmsTypeId).toEqual('Basura');
|
|
||||||
expect(description).toEqual('Dms without edition. Nevermind, now is edited.');
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.confirm);
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should disable edit and download if dms doesn't exists, and set back the original dms`, async() => {
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.dms);
|
|
||||||
await page.write(selectors.invoiceInBasicData.dms, '9999');
|
|
||||||
|
|
||||||
await page.waitForSelector(`${selectors.invoiceInBasicData.download}.disabled`);
|
|
||||||
await page.waitForSelector(`${selectors.invoiceInBasicData.edit}.disabled`);
|
|
||||||
|
|
||||||
await page.clearInput(selectors.invoiceInBasicData.dms);
|
|
||||||
await page.write(selectors.invoiceInBasicData.dms, '1');
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.invoiceInBasicData.save);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,59 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('InvoiceIn tax path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('developer', 'invoiceIn');
|
|
||||||
await page.accessToSearchResult('2');
|
|
||||||
await page.accessToSection('invoiceIn.card.tax');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should add a new tax and check it', async() => {
|
|
||||||
await page.waitToClick(selectors.invoiceInTax.addTaxButton);
|
|
||||||
await page.autocompleteSearch(selectors.invoiceInTax.thirdExpense, '6210000567');
|
|
||||||
await page.write(selectors.invoiceInTax.thirdTaxableBase, '100');
|
|
||||||
await page.autocompleteSearch(selectors.invoiceInTax.thirdTaxType, 'H.P. IVA');
|
|
||||||
await page.autocompleteSearch(selectors.invoiceInTax.thirdTransactionType, 'Operaciones exentas');
|
|
||||||
await page.waitToClick(selectors.invoiceInTax.saveButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.invoiceInDescriptor.summaryIcon);
|
|
||||||
await page.waitForState('invoiceIn.card.summary');
|
|
||||||
const total = await page.waitToGetProperty(selectors.invoiceInSummary.totalTaxableBase, 'innerText');
|
|
||||||
|
|
||||||
await page.accessToSection('invoiceIn.card.tax');
|
|
||||||
|
|
||||||
const thirdExpense = await page.waitToGetProperty(selectors.invoiceInTax.thirdExpense, 'value');
|
|
||||||
const thirdTaxableBase = await page.waitToGetProperty(selectors.invoiceInTax.thirdTaxableBase, 'value');
|
|
||||||
const thirdTaxType = await page.waitToGetProperty(selectors.invoiceInTax.thirdTaxType, 'value');
|
|
||||||
const thirdTransactionType = await page.waitToGetProperty(selectors.invoiceInTax.thirdTransactionType, 'value');
|
|
||||||
const thirdRate = await page.waitToGetProperty(selectors.invoiceInTax.thirdRate, 'value');
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
|
|
||||||
expect(total).toEqual('Taxable base €1,323.16');
|
|
||||||
|
|
||||||
expect(thirdExpense).toEqual('6210000567');
|
|
||||||
expect(thirdTaxableBase).toEqual('100');
|
|
||||||
expect(thirdTaxType).toEqual('H.P. IVA 4% CEE');
|
|
||||||
expect(thirdTransactionType).toEqual('Operaciones exentas');
|
|
||||||
expect(thirdRate).toEqual('€4.00');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should delete the added line', async() => {
|
|
||||||
await page.waitToClick(selectors.invoiceInTax.thirdDeleteButton);
|
|
||||||
await page.waitToClick(selectors.invoiceInTax.saveButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,48 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('InvoiceIn serial path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
let httpRequest;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('administrative', 'invoiceIn');
|
|
||||||
await page.accessToSection('invoiceIn.serial');
|
|
||||||
page.on('request', req => {
|
|
||||||
if (req.url().includes(`InvoiceIns/getSerial`))
|
|
||||||
httpRequest = req.url();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should check that passes the correct params to back', async() => {
|
|
||||||
await page.overwrite(selectors.invoiceInSerial.daysAgo, '30');
|
|
||||||
await page.keyboard.press('Enter');
|
|
||||||
|
|
||||||
expect(httpRequest).toContain('daysAgo=30');
|
|
||||||
|
|
||||||
await page.overwrite(selectors.invoiceInSerial.serial, 'R');
|
|
||||||
await page.keyboard.press('Enter');
|
|
||||||
|
|
||||||
expect(httpRequest).toContain('serial=R');
|
|
||||||
await page.click(selectors.invoiceInSerial.chip);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should go to index and check if the search-panel has the correct params', async() => {
|
|
||||||
await page.waitToClick(selectors.invoiceInSerial.goToIndex);
|
|
||||||
const params = await page.$$(selectors.invoiceInIndex.topbarSearchParams);
|
|
||||||
const serial = await params[0].getProperty('title');
|
|
||||||
const isBooked = await params[1].getProperty('title');
|
|
||||||
const from = await params[2].getProperty('title');
|
|
||||||
|
|
||||||
expect(await serial.jsonValue()).toContain('serial');
|
|
||||||
expect(await isBooked.jsonValue()).toContain('not isBooked');
|
|
||||||
expect(await from.jsonValue()).toContain('from');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -13,7 +13,6 @@ module.exports = function(Self) {
|
||||||
Object.assign(Self, {
|
Object.assign(Self, {
|
||||||
setup() {
|
setup() {
|
||||||
Self.super_.setup.call(this);
|
Self.super_.setup.call(this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setting a global transaction timeout to find out if the service
|
* Setting a global transaction timeout to find out if the service
|
||||||
* is blocked because the connection pool is empty.
|
* is blocked because the connection pool is empty.
|
||||||
|
@ -28,6 +27,26 @@ module.exports = function(Self) {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.beforeRemote('**', async ctx => {
|
||||||
|
if (!this.hasFilter(ctx)) return;
|
||||||
|
|
||||||
|
const defaultLimit = this.app.orm.selectLimit;
|
||||||
|
const filter = ctx.args.filter || {limit: defaultLimit};
|
||||||
|
|
||||||
|
if (filter.limit > defaultLimit) {
|
||||||
|
filter.limit = defaultLimit;
|
||||||
|
ctx.args.filter = filter;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.afterRemote('**', async ctx => {
|
||||||
|
if (!this.hasFilter(ctx)) return;
|
||||||
|
|
||||||
|
const {result} = ctx;
|
||||||
|
const length = Array.isArray(result) ? result.length : result ? 1 : 0;
|
||||||
|
if (length >= this.app.orm.selectLimit) throw new UserError('Too many records');
|
||||||
|
});
|
||||||
|
|
||||||
// Register field ACL validation
|
// Register field ACL validation
|
||||||
/*
|
/*
|
||||||
this.beforeRemote('prototype.patchAttributes', ctx => this.checkUpdateAcls(ctx));
|
this.beforeRemote('prototype.patchAttributes', ctx => this.checkUpdateAcls(ctx));
|
||||||
|
@ -327,6 +346,12 @@ module.exports = function(Self) {
|
||||||
|
|
||||||
checkInsertAcls(ctx) {
|
checkInsertAcls(ctx) {
|
||||||
return this.checkAcls(ctx, 'insert');
|
return this.checkAcls(ctx, 'insert');
|
||||||
|
},
|
||||||
|
|
||||||
|
hasFilter(ctx) {
|
||||||
|
return ctx.req.method.toUpperCase() === 'GET' &&
|
||||||
|
ctx.method.accepts.some(x => x.arg === 'filter' && x.type.toLowerCase() === 'object');
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -370,5 +370,6 @@
|
||||||
"CONSTRAINT `supplierAccountTooShort` failed for `vn`.`supplier`": "La cuenta debe tener exactamente 10 dígitos",
|
"CONSTRAINT `supplierAccountTooShort` failed for `vn`.`supplier`": "La cuenta debe tener exactamente 10 dígitos",
|
||||||
"The sale not exists in the item shelving": "La venta no existe en la estantería del artículo",
|
"The sale not exists in the item shelving": "La venta no existe en la estantería del artículo",
|
||||||
"The entry not have stickers": "La entrada no tiene etiquetas",
|
"The entry not have stickers": "La entrada no tiene etiquetas",
|
||||||
|
"Too many records": "Demasiados registros",
|
||||||
"Weight already set": "El peso ya está establecido"
|
"Weight already set": "El peso ya está establecido"
|
||||||
}
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
module.exports = async function(app) {
|
||||||
|
if (!app.orm) {
|
||||||
|
const ormConfig = await app.models.OrmConfig.findOne();
|
||||||
|
app.orm = ormConfig;
|
||||||
|
}
|
||||||
|
};
|
|
@ -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
|
||||||
|
|
|
@ -1,315 +0,0 @@
|
||||||
<mg-ajax path="InvoiceIns/{{patch.params.id}}/updateInvoiceIn" options="vnPatch"></mg-ajax>
|
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
data="$ctrl.invoiceIn"
|
|
||||||
form="form"
|
|
||||||
save="patch">
|
|
||||||
</vn-watcher>
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="Companies"
|
|
||||||
data="companies"
|
|
||||||
order="code">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="Warehouses"
|
|
||||||
data="warehouses"
|
|
||||||
order="name">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="DmsTypes"
|
|
||||||
data="dmsTypes"
|
|
||||||
order="name">
|
|
||||||
</vn-crud-model>
|
|
||||||
<form name="form" ng-submit="watcher.submit()" class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
ng-model="$ctrl.invoiceIn.supplierFk"
|
|
||||||
url="Suppliers"
|
|
||||||
show-field="nickname"
|
|
||||||
search-function="{or: [{id: $search}, {nickname: {like: '%'+ $search +'%'}}]}"
|
|
||||||
value-field="id"
|
|
||||||
order="nickname"
|
|
||||||
label="Supplier"
|
|
||||||
required="true"
|
|
||||||
rule>
|
|
||||||
<tpl-item>
|
|
||||||
{{::id}} - {{::nickname}}
|
|
||||||
</tpl-item>
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-textfield
|
|
||||||
label="Supplier ref"
|
|
||||||
ng-model="$ctrl.invoiceIn.supplierRef"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-date-picker
|
|
||||||
vn-one
|
|
||||||
label="Expedition date"
|
|
||||||
ng-model="$ctrl.invoiceIn.issued"
|
|
||||||
vn-focus
|
|
||||||
rule>
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-date-picker
|
|
||||||
vn-one
|
|
||||||
label="Operation date"
|
|
||||||
ng-model="$ctrl.invoiceIn.operated"
|
|
||||||
rule>
|
|
||||||
</vn-date-picker>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-datalist vn-one
|
|
||||||
label="Undeductible VAT"
|
|
||||||
ng-model="$ctrl.invoiceIn.deductibleExpenseFk"
|
|
||||||
value-field="id"
|
|
||||||
order="name"
|
|
||||||
url="Expenses"
|
|
||||||
fields="['id','name']"
|
|
||||||
rule>
|
|
||||||
<tpl-item>
|
|
||||||
{{id}} - {{name}}
|
|
||||||
</tpl-item>
|
|
||||||
</vn-datalist>
|
|
||||||
<vn-textfield
|
|
||||||
label="Document"
|
|
||||||
ng-model="$ctrl.invoiceIn.dmsFk"
|
|
||||||
ng-change="$ctrl.checkFileExists($ctrl.invoiceIn.dmsFk)"
|
|
||||||
rule>
|
|
||||||
<prepend>
|
|
||||||
<vn-icon-button
|
|
||||||
disabled="$ctrl.editDownloadDisabled"
|
|
||||||
ng-if="$ctrl.invoiceIn.dmsFk"
|
|
||||||
title="{{'Download file' | translate}}"
|
|
||||||
icon="cloud_download"
|
|
||||||
ng-click="$ctrl.downloadFile($ctrl.invoiceIn.dmsFk)">
|
|
||||||
</vn-icon-button>
|
|
||||||
</prepend>
|
|
||||||
<append>
|
|
||||||
<vn-icon-button
|
|
||||||
disabled="$ctrl.editDownloadDisabled"
|
|
||||||
ng-if="$ctrl.invoiceIn.dmsFk"
|
|
||||||
ng-click="$ctrl.openEditDialog($ctrl.invoiceIn.dmsFk)"
|
|
||||||
icon="edit"
|
|
||||||
title="{{'Edit document' | translate}}">
|
|
||||||
</vn-icon-button>
|
|
||||||
<vn-icon-button
|
|
||||||
ng-if="!$ctrl.invoiceIn.dmsFk"
|
|
||||||
ng-click="$ctrl.openCreateDialog()"
|
|
||||||
icon="add_circle"
|
|
||||||
title="{{'Create document' | translate}}">
|
|
||||||
</vn-icon-button>
|
|
||||||
</append>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-date-picker
|
|
||||||
vn-one
|
|
||||||
label="Entry date"
|
|
||||||
ng-model="$ctrl.invoiceIn.bookEntried"
|
|
||||||
rule>
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-date-picker
|
|
||||||
vn-one
|
|
||||||
label="Accounted date"
|
|
||||||
ng-model="$ctrl.invoiceIn.booked"
|
|
||||||
rule>
|
|
||||||
</vn-date-picker>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
label="Currency"
|
|
||||||
ng-model="$ctrl.invoiceIn.currencyFk"
|
|
||||||
url="Currencies"
|
|
||||||
show-field="code"
|
|
||||||
value-field="id"
|
|
||||||
rule>
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete
|
|
||||||
url="Companies"
|
|
||||||
label="Company"
|
|
||||||
show-field="code"
|
|
||||||
value-field="id"
|
|
||||||
ng-model="$ctrl.invoiceIn.companyFk"
|
|
||||||
rule>
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Save">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Undo changes"
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
ng-click="watcher.loadOriginalData()">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
||||||
<!-- Create edit dms dialog -->
|
|
||||||
<vn-dialog
|
|
||||||
vn-id="dmsEditDialog"
|
|
||||||
message="Edit document"
|
|
||||||
on-accept="$ctrl.onEdit()">
|
|
||||||
<tpl-body>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
vn-focus
|
|
||||||
label="Reference"
|
|
||||||
ng-model="$ctrl.dms.reference"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-autocomplete vn-one required="true"
|
|
||||||
label="Company"
|
|
||||||
ng-model="$ctrl.dms.companyId"
|
|
||||||
url="Companies"
|
|
||||||
show-field="code"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete vn-one required="true"
|
|
||||||
label="Warehouse"
|
|
||||||
ng-model="$ctrl.dms.warehouseId"
|
|
||||||
url="Warehouses"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete vn-one required="true"
|
|
||||||
label="Type"
|
|
||||||
ng-model="$ctrl.dms.dmsTypeId"
|
|
||||||
url="DmsTypes"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textarea
|
|
||||||
vn-one
|
|
||||||
required="true"
|
|
||||||
label="Description"
|
|
||||||
ng-model="$ctrl.dms.description"
|
|
||||||
rule>
|
|
||||||
</vn-textarea>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-input-file
|
|
||||||
vn-one
|
|
||||||
label="File"
|
|
||||||
ng-model="$ctrl.dms.files"
|
|
||||||
on-change="$ctrl.onFileChange($files)"
|
|
||||||
accept="{{$ctrl.allowedContentTypes}}"
|
|
||||||
required="false"
|
|
||||||
multiple="true">
|
|
||||||
<append>
|
|
||||||
<vn-icon vn-none
|
|
||||||
color-marginal
|
|
||||||
title="{{$ctrl.contentTypesInfo}}"
|
|
||||||
icon="info">
|
|
||||||
</vn-icon>
|
|
||||||
</append>
|
|
||||||
</vn-input-file>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-vertical>
|
|
||||||
<vn-check disabled="true"
|
|
||||||
label="Generate identifier for original file"
|
|
||||||
ng-model="$ctrl.dms.hasFile">
|
|
||||||
</vn-check>
|
|
||||||
</vn-vertical>
|
|
||||||
</tpl-body>
|
|
||||||
<tpl-buttons>
|
|
||||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
|
||||||
<button response="accept" translate>Save</button>
|
|
||||||
</tpl-buttons>
|
|
||||||
</vn-dialog>
|
|
||||||
<!-- Create new dms dialog -->
|
|
||||||
<vn-dialog
|
|
||||||
vn-id="dmsCreateDialog"
|
|
||||||
message="Create document"
|
|
||||||
on-accept="$ctrl.onCreate()">
|
|
||||||
<tpl-body>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
vn-focus
|
|
||||||
label="Reference"
|
|
||||||
ng-model="$ctrl.dms.reference"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
label="Company"
|
|
||||||
ng-model="$ctrl.dms.companyId"
|
|
||||||
data="companies"
|
|
||||||
show-field="code"
|
|
||||||
value-field="id"
|
|
||||||
required="true">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
label="Warehouse"
|
|
||||||
ng-model="$ctrl.dms.warehouseId"
|
|
||||||
data="warehouses"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
required="true">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
label="Type"
|
|
||||||
ng-model="$ctrl.dms.dmsTypeId"
|
|
||||||
data="dmsTypes"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
required="true">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textarea
|
|
||||||
vn-one
|
|
||||||
label="Description"
|
|
||||||
ng-model="$ctrl.dms.description"
|
|
||||||
required="true"
|
|
||||||
rule>
|
|
||||||
</vn-textarea>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-input-file
|
|
||||||
vn-one
|
|
||||||
label="File"
|
|
||||||
ng-model="$ctrl.dms.files"
|
|
||||||
on-change="$ctrl.onFileChange($files)"
|
|
||||||
accept="{{$ctrl.allowedContentTypes}}"
|
|
||||||
required="true"
|
|
||||||
multiple="true">
|
|
||||||
<append>
|
|
||||||
<vn-icon vn-none
|
|
||||||
color-marginal
|
|
||||||
title="{{$ctrl.contentTypesInfo}}"
|
|
||||||
icon="info">
|
|
||||||
</vn-icon>
|
|
||||||
</append>
|
|
||||||
</vn-input-file>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-vertical>
|
|
||||||
<vn-check
|
|
||||||
label="Generate identifier for original file"
|
|
||||||
ng-model="$ctrl.dms.hasFile">
|
|
||||||
</vn-check>
|
|
||||||
</vn-vertical>
|
|
||||||
</tpl-body>
|
|
||||||
<tpl-buttons>
|
|
||||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
|
||||||
<button response="accept" translate>Create</button>
|
|
||||||
</tpl-buttons>
|
|
||||||
</vn-dialog>
|
|
|
@ -1,187 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
import UserError from 'core/lib/user-error';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
|
||||||
constructor($element, $, vnFile) {
|
|
||||||
super($element, $, vnFile);
|
|
||||||
this.dms = {
|
|
||||||
files: [],
|
|
||||||
hasFile: false,
|
|
||||||
hasFileAttached: false
|
|
||||||
};
|
|
||||||
this.vnFile = vnFile;
|
|
||||||
this.getAllowedContentTypes();
|
|
||||||
this._editDownloadDisabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
get contentTypesInfo() {
|
|
||||||
return this.$t('ContentTypesInfo', {
|
|
||||||
allowedContentTypes: this.allowedContentTypes
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
get editDownloadDisabled() {
|
|
||||||
return this._editDownloadDisabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
async checkFileExists(dmsId) {
|
|
||||||
if (!dmsId) return;
|
|
||||||
let filter = {
|
|
||||||
fields: ['id']
|
|
||||||
};
|
|
||||||
await this.$http.get(`Dms/${dmsId}`, {filter})
|
|
||||||
.then(() => this._editDownloadDisabled = false)
|
|
||||||
.catch(() => this._editDownloadDisabled = true);
|
|
||||||
}
|
|
||||||
|
|
||||||
async getFile(dmsId) {
|
|
||||||
const path = `Dms/${dmsId}`;
|
|
||||||
await this.$http.get(path).then(res => {
|
|
||||||
const dms = res.data && res.data;
|
|
||||||
this.dms = {
|
|
||||||
dmsId: dms.id,
|
|
||||||
reference: dms.reference,
|
|
||||||
warehouseId: dms.warehouseFk,
|
|
||||||
companyId: dms.companyFk,
|
|
||||||
dmsTypeId: dms.dmsTypeFk,
|
|
||||||
description: dms.description,
|
|
||||||
hasFile: dms.hasFile,
|
|
||||||
hasFileAttached: false,
|
|
||||||
files: []
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getAllowedContentTypes() {
|
|
||||||
this.$http.get('DmsContainers/allowedContentTypes').then(res => {
|
|
||||||
if (res.data.length > 0) {
|
|
||||||
const contentTypes = res.data.join(', ');
|
|
||||||
this.allowedContentTypes = contentTypes;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
openEditDialog(dmsId) {
|
|
||||||
this.getFile(dmsId).then(() => this.$.dmsEditDialog.show());
|
|
||||||
}
|
|
||||||
|
|
||||||
openCreateDialog() {
|
|
||||||
const params = {filter: {
|
|
||||||
where: {code: 'invoiceIn'}
|
|
||||||
}};
|
|
||||||
this.$http.get('DmsTypes/findOne', {params}).then(res => {
|
|
||||||
this.dms = {
|
|
||||||
reference: this.invoiceIn.supplierRef,
|
|
||||||
warehouseId: this.vnConfig.warehouseFk,
|
|
||||||
companyId: this.vnConfig.companyFk,
|
|
||||||
dmsTypeId: res.data.id,
|
|
||||||
description: this.invoiceIn.supplier.name,
|
|
||||||
hasFile: true,
|
|
||||||
hasFileAttached: true,
|
|
||||||
files: null
|
|
||||||
};
|
|
||||||
this.$.dmsCreateDialog.show();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
downloadFile(dmsId) {
|
|
||||||
this.vnFile.download(`api/dms/${dmsId}/downloadFile`);
|
|
||||||
}
|
|
||||||
|
|
||||||
onFileChange(files) {
|
|
||||||
let hasFileAttached = false;
|
|
||||||
if (files.length > 0)
|
|
||||||
hasFileAttached = true;
|
|
||||||
|
|
||||||
this.$.$applyAsync(() => {
|
|
||||||
this.dms.hasFileAttached = hasFileAttached;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onEdit() {
|
|
||||||
if (!this.dms.companyId)
|
|
||||||
throw new UserError(`The company can't be empty`);
|
|
||||||
if (!this.dms.warehouseId)
|
|
||||||
throw new UserError(`The warehouse can't be empty`);
|
|
||||||
if (!this.dms.dmsTypeId)
|
|
||||||
throw new UserError(`The DMS Type can't be empty`);
|
|
||||||
if (!this.dms.description)
|
|
||||||
throw new UserError(`The description can't be empty`);
|
|
||||||
|
|
||||||
const query = `dms/${this.dms.dmsId}/updateFile`;
|
|
||||||
const options = {
|
|
||||||
method: 'POST',
|
|
||||||
url: query,
|
|
||||||
params: this.dms,
|
|
||||||
headers: {
|
|
||||||
'Content-Type': undefined
|
|
||||||
},
|
|
||||||
transformRequest: files => {
|
|
||||||
const formData = new FormData();
|
|
||||||
|
|
||||||
for (let i = 0; i < files.length; i++)
|
|
||||||
formData.append(files[i].name, files[i]);
|
|
||||||
|
|
||||||
return formData;
|
|
||||||
},
|
|
||||||
data: this.dms.files
|
|
||||||
};
|
|
||||||
|
|
||||||
this.$http(options).then(res => {
|
|
||||||
if (res) {
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
if (res.data.length > 0) this.invoiceIn.dmsFk = res.data[0].id;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onCreate() {
|
|
||||||
if (!this.dms.companyId)
|
|
||||||
throw new UserError(`The company can't be empty`);
|
|
||||||
if (!this.dms.warehouseId)
|
|
||||||
throw new UserError(`The warehouse can't be empty`);
|
|
||||||
if (!this.dms.dmsTypeId)
|
|
||||||
throw new UserError(`The DMS Type can't be empty`);
|
|
||||||
if (!this.dms.description)
|
|
||||||
throw new UserError(`The description can't be empty`);
|
|
||||||
if (!this.dms.files)
|
|
||||||
throw new UserError(`The files can't be empty`);
|
|
||||||
|
|
||||||
const query = `Dms/uploadFile`;
|
|
||||||
const options = {
|
|
||||||
method: 'POST',
|
|
||||||
url: query,
|
|
||||||
params: this.dms,
|
|
||||||
headers: {
|
|
||||||
'Content-Type': undefined
|
|
||||||
},
|
|
||||||
transformRequest: files => {
|
|
||||||
const formData = new FormData();
|
|
||||||
|
|
||||||
for (let i = 0; i < files.length; i++)
|
|
||||||
formData.append(files[i].name, files[i]);
|
|
||||||
|
|
||||||
return formData;
|
|
||||||
},
|
|
||||||
data: this.dms.files
|
|
||||||
};
|
|
||||||
|
|
||||||
this.$http(options).then(res => {
|
|
||||||
if (res) {
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
if (res.data.length > 0) this.invoiceIn.dmsFk = res.data[0].id;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Controller.$inject = ['$element', '$scope', 'vnFile'];
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnInvoiceInBasicData', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
invoiceIn: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,102 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
import watcher from 'core/mocks/watcher';
|
|
||||||
|
|
||||||
describe('InvoiceIn', () => {
|
|
||||||
describe('Component vnInvoiceInBasicData', () => {
|
|
||||||
let controller;
|
|
||||||
let $scope;
|
|
||||||
let $httpBackend;
|
|
||||||
let $httpParamSerializer;
|
|
||||||
|
|
||||||
beforeEach(ngModule('invoiceIn'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_, _$httpParamSerializer_) => {
|
|
||||||
$scope = $rootScope.$new();
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
$httpParamSerializer = _$httpParamSerializer_;
|
|
||||||
const $element = angular.element('<vn-invoice-in-basic-data></vn-invoice-in-basic-data>');
|
|
||||||
controller = $componentController('vnInvoiceInBasicData', {$element, $scope});
|
|
||||||
controller.$.watcher = watcher;
|
|
||||||
$httpBackend.expect('GET', `DmsContainers/allowedContentTypes`).respond({});
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('onFileChange()', () => {
|
|
||||||
it('should set dms hasFileAttached property to true if has any files', () => {
|
|
||||||
const files = [{id: 1, name: 'MyFile'}];
|
|
||||||
controller.onFileChange(files);
|
|
||||||
|
|
||||||
$scope.$apply();
|
|
||||||
|
|
||||||
expect(controller.dms.hasFileAttached).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('checkFileExists()', () => {
|
|
||||||
it(`should return false if a file exists`, () => {
|
|
||||||
const fileIdExists = 1;
|
|
||||||
controller.checkFileExists(fileIdExists);
|
|
||||||
|
|
||||||
expect(controller.editDownloadDisabled).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onEdit()', () => {
|
|
||||||
it(`should perform a POST query to edit the dms properties`, () => {
|
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
|
||||||
|
|
||||||
const dms = {
|
|
||||||
dmsId: 1,
|
|
||||||
reference: 'Ref1',
|
|
||||||
warehouseId: 1,
|
|
||||||
companyId: 442,
|
|
||||||
dmsTypeId: 20,
|
|
||||||
description: 'This is a description',
|
|
||||||
files: []
|
|
||||||
};
|
|
||||||
|
|
||||||
controller.dms = dms;
|
|
||||||
const serializedParams = $httpParamSerializer(controller.dms);
|
|
||||||
const query = `dms/${controller.dms.dmsId}/updateFile?${serializedParams}`;
|
|
||||||
|
|
||||||
$httpBackend.expectPOST(query).respond({});
|
|
||||||
controller.onEdit();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onCreate()', () => {
|
|
||||||
it(`should perform a POST query to create a new dms`, () => {
|
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
|
||||||
|
|
||||||
const dms = {
|
|
||||||
reference: 'Ref1',
|
|
||||||
warehouseId: 1,
|
|
||||||
companyId: 442,
|
|
||||||
dmsTypeId: 20,
|
|
||||||
description: 'This is a description',
|
|
||||||
files: [{
|
|
||||||
lastModified: 1668673957761,
|
|
||||||
lastModifiedDate: Date.vnNew(),
|
|
||||||
name: 'file-example.png',
|
|
||||||
size: 19653,
|
|
||||||
type: 'image/png',
|
|
||||||
webkitRelativePath: ''
|
|
||||||
}]
|
|
||||||
};
|
|
||||||
|
|
||||||
controller.dms = dms;
|
|
||||||
const serializedParams = $httpParamSerializer(controller.dms);
|
|
||||||
const query = `Dms/uploadFile?${serializedParams}`;
|
|
||||||
|
|
||||||
$httpBackend.expectPOST(query).respond({});
|
|
||||||
controller.onCreate();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
ContentTypesInfo: Allowed file types {{allowedContentTypes}}
|
|
|
@ -1,15 +0,0 @@
|
||||||
Upload file: Subir fichero
|
|
||||||
Edit file: Editar fichero
|
|
||||||
Upload: Subir
|
|
||||||
Document: Documento
|
|
||||||
ContentTypesInfo: "Tipos de archivo permitidos: {{allowedContentTypes}}"
|
|
||||||
Generate identifier for original file: Generar identificador para archivo original
|
|
||||||
File management: Gestión documental
|
|
||||||
Hard copy: Copia
|
|
||||||
This file will be deleted: Este fichero va a ser borrado
|
|
||||||
Are you sure?: Estas seguro?
|
|
||||||
File deleted: Fichero eliminado
|
|
||||||
Remove file: Eliminar fichero
|
|
||||||
Download file: Descargar fichero
|
|
||||||
Edit document: Editar documento
|
|
||||||
Create document: Crear documento
|
|
|
@ -1,55 +0,0 @@
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
url="InvoiceIns"
|
|
||||||
data="$ctrl.invoiceIn"
|
|
||||||
insert-mode="true"
|
|
||||||
form="form">
|
|
||||||
</vn-watcher>
|
|
||||||
<form name="form" vn-http-submit="$ctrl.onSubmit()" class="vn-w-md">
|
|
||||||
<div class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-focus
|
|
||||||
vn-id="supplier"
|
|
||||||
url="Suppliers"
|
|
||||||
label="Supplier"
|
|
||||||
search-function="{or: [{id: $search}, {name: {like: '%'+ $search +'%'}}, {nif: {like: '%'+ $search +'%'}}]}"
|
|
||||||
fields="['nif']"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
ng-model="$ctrl.invoiceIn.supplierFk"
|
|
||||||
order="id"
|
|
||||||
vn-focus>
|
|
||||||
<tpl-item>{{id}}: {{nif}}: {{name}}</tpl-item>
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="supplierRef"
|
|
||||||
ng-model="$ctrl.invoiceIn.supplierRef">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-date-picker
|
|
||||||
label="Issued"
|
|
||||||
ng-model="$ctrl.invoiceIn.issued">
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
label="Company"
|
|
||||||
ng-model="$ctrl.companyFk"
|
|
||||||
url="companies"
|
|
||||||
show-field="code"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Create">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Cancel"
|
|
||||||
ui-sref="InvoiceIn.index">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
|
@ -1,30 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
|
||||||
$onInit() {
|
|
||||||
this.invoiceIn = {};
|
|
||||||
if (this.$params && this.$params.supplierFk)
|
|
||||||
this.invoiceIn.supplierFk = this.$params.supplierFk;
|
|
||||||
this.invoiceIn.issued = Date.vnNew();
|
|
||||||
}
|
|
||||||
|
|
||||||
get companyFk() {
|
|
||||||
return this.invoiceIn.companyFk || this.vnConfig.companyFk;
|
|
||||||
}
|
|
||||||
|
|
||||||
set companyFk(value) {
|
|
||||||
this.invoiceIn.companyFk = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
onSubmit() {
|
|
||||||
this.$.watcher.submit().then(
|
|
||||||
res => this.$state.go('invoiceIn.card.basicData', {id: res.data.id})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnInvoiceInCreate', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1 +0,0 @@
|
||||||
a:a
|
|
|
@ -1,71 +0,0 @@
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="InvoiceInDueDays"
|
|
||||||
data="InvoiceInDueDaysData"
|
|
||||||
link="{invoiceInFk: $ctrl.$params.id}"
|
|
||||||
auto-load="true">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
data="InvoiceInDueDaysData"
|
|
||||||
form="form">
|
|
||||||
</vn-watcher>
|
|
||||||
<form name="form" ng-submit="$ctrl.onSubmit()">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-horizontal ng-repeat="invoiceInDueDay in InvoiceInDueDaysData">
|
|
||||||
<vn-date-picker
|
|
||||||
vn-one
|
|
||||||
label="Date"
|
|
||||||
ng-model="invoiceInDueDay.dueDated"
|
|
||||||
vn-focus
|
|
||||||
rule>
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-autocomplete vn-three
|
|
||||||
label="Bank"
|
|
||||||
ng-model="invoiceInDueDay.bankFk"
|
|
||||||
url="Accountings"
|
|
||||||
show-field="bank"
|
|
||||||
select-fields="['id','bank']"
|
|
||||||
order="id"
|
|
||||||
search-function="$ctrl.bankSearchFunc($search)"
|
|
||||||
rule>
|
|
||||||
<tpl-item>{{id}}: {{bank}}</tpl-item>
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-input-number vn-one
|
|
||||||
label="Amount"
|
|
||||||
ng-model="invoiceInDueDay.amount"
|
|
||||||
step="0.01"
|
|
||||||
rule
|
|
||||||
vn-focus>
|
|
||||||
</vn-input-number>
|
|
||||||
<vn-input-number
|
|
||||||
disabled="$ctrl.invoiceIn.currency.code == 'EUR'"
|
|
||||||
label="Foreign value"
|
|
||||||
ng-model="invoiceInDueDay.foreignValue"
|
|
||||||
rule>
|
|
||||||
</vn-input-number>
|
|
||||||
<vn-none>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-tooltip="Remove due day"
|
|
||||||
icon="delete"
|
|
||||||
ng-click="model.remove($index)"
|
|
||||||
tabindex="-1">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-none>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-one>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-bind="+"
|
|
||||||
vn-tooltip="Add due day"
|
|
||||||
icon="add_circle"
|
|
||||||
ng-click="$ctrl.add()">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-one>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Save">
|
|
||||||
</vn-submit>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
|
@ -1,37 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
|
||||||
add() {
|
|
||||||
this.$.model.insert({
|
|
||||||
dueDated: Date.vnNew(),
|
|
||||||
bankFk: this.vnConfig.local.bankFk
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onSubmit() {
|
|
||||||
this.$.watcher.check();
|
|
||||||
this.$.model.save().then(() => {
|
|
||||||
this.$.watcher.notifySaved();
|
|
||||||
this.$.watcher.updateOriginalData();
|
|
||||||
this.card.reload();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bankSearchFunc($search) {
|
|
||||||
return /^\d+$/.test($search)
|
|
||||||
? {id: $search}
|
|
||||||
: {bank: {like: '%' + $search + '%'}};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnInvoiceInDueDay', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
require: {
|
|
||||||
card: '^vnInvoiceInCard'
|
|
||||||
},
|
|
||||||
bindings: {
|
|
||||||
invoiceIn: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,44 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
import watcher from 'core/mocks/watcher';
|
|
||||||
import crudModel from 'core/mocks/crud-model';
|
|
||||||
|
|
||||||
describe('InvoiceIn', () => {
|
|
||||||
describe('Component due day', () => {
|
|
||||||
let controller;
|
|
||||||
let $scope;
|
|
||||||
let vnApp;
|
|
||||||
|
|
||||||
beforeEach(ngModule('invoiceIn'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, $rootScope, _vnApp_) => {
|
|
||||||
vnApp = _vnApp_;
|
|
||||||
jest.spyOn(vnApp, 'showError');
|
|
||||||
$scope = $rootScope.$new();
|
|
||||||
$scope.model = crudModel;
|
|
||||||
$scope.watcher = watcher;
|
|
||||||
|
|
||||||
const $element = angular.element('<vn-invoice-in-due-day></vn-invoice-in-due-day>');
|
|
||||||
controller = $componentController('vnInvoiceInDueDay', {$element, $scope});
|
|
||||||
controller.invoiceIn = {id: 1};
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('onSubmit()', () => {
|
|
||||||
it('should make HTTP POST request to save due day values', () => {
|
|
||||||
controller.card = {reload: () => {}};
|
|
||||||
jest.spyOn($scope.watcher, 'check');
|
|
||||||
jest.spyOn($scope.watcher, 'notifySaved');
|
|
||||||
jest.spyOn($scope.watcher, 'updateOriginalData');
|
|
||||||
jest.spyOn(controller.card, 'reload');
|
|
||||||
jest.spyOn($scope.model, 'save');
|
|
||||||
|
|
||||||
controller.onSubmit();
|
|
||||||
|
|
||||||
expect($scope.model.save).toHaveBeenCalledWith();
|
|
||||||
expect($scope.watcher.updateOriginalData).toHaveBeenCalledWith();
|
|
||||||
expect($scope.watcher.check).toHaveBeenCalledWith();
|
|
||||||
expect($scope.watcher.notifySaved).toHaveBeenCalledWith();
|
|
||||||
expect(controller.card.reload).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,17 +1,7 @@
|
||||||
export * from './module';
|
export * from './module';
|
||||||
|
|
||||||
import './main';
|
import './main';
|
||||||
import './index/';
|
|
||||||
import './search-panel';
|
|
||||||
import './card';
|
import './card';
|
||||||
import './descriptor';
|
import './descriptor';
|
||||||
import './descriptor-popover';
|
import './descriptor-popover';
|
||||||
import './summary';
|
import './summary';
|
||||||
import './basic-data';
|
|
||||||
import './tax';
|
|
||||||
import './dueDay';
|
|
||||||
import './intrastat';
|
|
||||||
import './create';
|
|
||||||
import './log';
|
|
||||||
import './serial';
|
|
||||||
import './serial-search-panel';
|
|
||||||
|
|
|
@ -1,82 +0,0 @@
|
||||||
<vn-auto-search
|
|
||||||
model="model">
|
|
||||||
</vn-auto-search>
|
|
||||||
<vn-data-viewer
|
|
||||||
model="model"
|
|
||||||
class="vn-w-lg">
|
|
||||||
<vn-card>
|
|
||||||
<vn-table model="model">
|
|
||||||
<vn-thead>
|
|
||||||
<vn-tr>
|
|
||||||
<vn-th field="id">ID</vn-th>
|
|
||||||
<vn-th field="supplierFk">Supplier</vn-th>
|
|
||||||
<vn-th field="supplierRef">Supplier ref.</vn-th>
|
|
||||||
<vn-th field="serialNumber">Serial number</vn-th>
|
|
||||||
<vn-th field="serial">Serial</vn-th>
|
|
||||||
<vn-th field="dmsFk">File</vn-th>
|
|
||||||
<vn-th field="issued" expand>Issued</vn-th>
|
|
||||||
<vn-th field="isBooked" center>Is booked</vn-th>
|
|
||||||
<vn-th field="awbCode" vn-tooltip="Air Waybill">AWB</vn-th>
|
|
||||||
<vn-th field="amount" filter-enabled="false">Amount</vn-th>
|
|
||||||
<vn-th></vn-th>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-thead>
|
|
||||||
<vn-tbody>
|
|
||||||
<a
|
|
||||||
ng-repeat="invoiceIn in model.data"
|
|
||||||
class="clickable vn-tr search-result"
|
|
||||||
ui-sref="invoiceIn.card.summary({id: {{::invoiceIn.id}}})">
|
|
||||||
<vn-td>{{::invoiceIn.id}}</vn-td>
|
|
||||||
<vn-td expand>
|
|
||||||
<span
|
|
||||||
class="link"
|
|
||||||
vn-click-stop="supplierDescriptor.show($event, invoiceIn.supplierFk)">
|
|
||||||
{{::invoiceIn.supplierName}}
|
|
||||||
</span>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td>{{::invoiceIn.supplierRef | dashIfEmpty}}</vn-td>
|
|
||||||
<vn-td>{{::invoiceIn.serialNumber}}</vn-td>
|
|
||||||
<vn-td>{{::invoiceIn.serial}}</vn-td>
|
|
||||||
<vn-td>
|
|
||||||
<span title="{{'Download file' | translate}}" class="link"
|
|
||||||
ng-click="$ctrl.downloadFile(invoiceIn.dmsFk)">
|
|
||||||
{{::invoiceIn.file}}
|
|
||||||
</span>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td expand>{{::invoiceIn.issued | date:'dd/MM/yyyy' | dashIfEmpty}}</vn-td>
|
|
||||||
<vn-td center>
|
|
||||||
<vn-check disabled="true"
|
|
||||||
ng-model="invoiceIn.isBooked">
|
|
||||||
</vn-check>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td>{{::invoiceIn.awbCode}}</vn-td>
|
|
||||||
<vn-td>{{::invoiceIn.amount | currency:'EUR'}}</vn-td>
|
|
||||||
<vn-td shrink>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-click-stop="$ctrl.preview(invoiceIn)"
|
|
||||||
vn-tooltip="Preview"
|
|
||||||
icon="preview">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td shrink>
|
|
||||||
<!-- <vn-icon-button
|
|
||||||
ng-show="invoiceIn.dmsFk"
|
|
||||||
vn-click-stop="$ctrl.openPdf(invoiceIn.dmsFk)"
|
|
||||||
icon="cloud_download"
|
|
||||||
title="Download PDF"
|
|
||||||
vn-tooltip="Download PDF">
|
|
||||||
</vn-icon-button> -->
|
|
||||||
</vn-td>
|
|
||||||
</a>
|
|
||||||
</vn-tbody>
|
|
||||||
</vn-table>
|
|
||||||
</vn-card>
|
|
||||||
</vn-data-viewer>
|
|
||||||
<vn-supplier-descriptor-popover
|
|
||||||
vn-id="supplierDescriptor">
|
|
||||||
</vn-supplier-descriptor-popover>
|
|
||||||
<vn-popup vn-id="summary">
|
|
||||||
<vn-invoice-in-summary
|
|
||||||
invoice-in="$ctrl.selectedInvoiceIn">
|
|
||||||
</vn-invoice-in-summary>
|
|
||||||
</vn-popup>
|
|
|
@ -1,58 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
constructor($element, $, vnFile) {
|
|
||||||
super($element, $, vnFile);
|
|
||||||
this.vnFile = vnFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
exprBuilder(param, value) {
|
|
||||||
switch (param) {
|
|
||||||
case 'issued':
|
|
||||||
return {'ii.issued': {
|
|
||||||
between: this.dateRange(value)}
|
|
||||||
};
|
|
||||||
case 'id':
|
|
||||||
case 'supplierFk':
|
|
||||||
case 'supplierRef':
|
|
||||||
case 'serialNumber':
|
|
||||||
case 'serial':
|
|
||||||
case 'created':
|
|
||||||
case 'isBooked':
|
|
||||||
return {[`ii.${param}`]: value};
|
|
||||||
case 'account':
|
|
||||||
case 'fi':
|
|
||||||
return {[`s.${param}`]: value};
|
|
||||||
case 'awbCode':
|
|
||||||
return {'awb.code': value};
|
|
||||||
default:
|
|
||||||
return {[param]: value};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dateRange(value) {
|
|
||||||
const minHour = new Date(value);
|
|
||||||
minHour.setHours(0, 0, 0, 0);
|
|
||||||
const maxHour = new Date(value);
|
|
||||||
maxHour.setHours(23, 59, 59, 59);
|
|
||||||
|
|
||||||
return [minHour, maxHour];
|
|
||||||
}
|
|
||||||
|
|
||||||
preview(invoiceIn) {
|
|
||||||
this.selectedInvoiceIn = invoiceIn;
|
|
||||||
this.$.summary.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
downloadFile(dmsId) {
|
|
||||||
this.vnFile.download(`api/dms/${dmsId}/downloadFile`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Controller.$inject = ['$element', '$scope', 'vnFile'];
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnInvoiceInIndex', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,6 +0,0 @@
|
||||||
Created: Fecha creación
|
|
||||||
Issued: Fecha emisión
|
|
||||||
Supplier ref.: Ref. proveedor
|
|
||||||
Serial number: Num. serie
|
|
||||||
Serial: Serie
|
|
||||||
Is booked: Conciliada
|
|
|
@ -1,100 +0,0 @@
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="InvoiceInIntrastats"
|
|
||||||
data="$ctrl.invoceInIntrastat"
|
|
||||||
link="{invoiceInFk: $ctrl.$params.id}"
|
|
||||||
auto-load="true"
|
|
||||||
on-data-change="$ctrl.calculateTotals()">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="Countries"
|
|
||||||
data="countries"
|
|
||||||
order="name">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="Intrastats"
|
|
||||||
data="intrastats"
|
|
||||||
order="id">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
data="$ctrl.invoceInIntrastat"
|
|
||||||
form="form">
|
|
||||||
</vn-watcher>
|
|
||||||
<vn-card
|
|
||||||
class="vn-mb-md vn-pa-lg vn-w-lg"
|
|
||||||
style="text-align: right"
|
|
||||||
ng-if="$ctrl.invoceInIntrastat.length > 0">
|
|
||||||
<vn-label-value label="Total amount"
|
|
||||||
value="{{$ctrl.amountTotal | currency: 'EUR':2}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value label="Total net"
|
|
||||||
value="{{$ctrl.netTotal}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value label="Total stems"
|
|
||||||
value="{{$ctrl.stemsTotal}}">
|
|
||||||
</vn-label-value>
|
|
||||||
</vn-card>
|
|
||||||
<form name="form" ng-submit="$ctrl.onSubmit()">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-horizontal ng-repeat="intrastat in $ctrl.invoceInIntrastat">
|
|
||||||
<vn-autocomplete vn-three
|
|
||||||
label="Code"
|
|
||||||
data="intrastats"
|
|
||||||
ng-model="intrastat.intrastatFk"
|
|
||||||
show-field="description"
|
|
||||||
rule
|
|
||||||
vn-focus>
|
|
||||||
<tpl-item>{{id}}: {{description}}</tpl-item>
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-input-number
|
|
||||||
label="Amount"
|
|
||||||
ng-model="intrastat.amount"
|
|
||||||
step="0.01"
|
|
||||||
rule>
|
|
||||||
</vn-input-number>
|
|
||||||
<vn-input-number
|
|
||||||
label="Net"
|
|
||||||
ng-model="intrastat.net"
|
|
||||||
step="0.01"
|
|
||||||
rule>
|
|
||||||
</vn-input-number>
|
|
||||||
<vn-input-number
|
|
||||||
label="Stems"
|
|
||||||
ng-model="intrastat.stems"
|
|
||||||
rule>
|
|
||||||
</vn-input-number>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Country"
|
|
||||||
data="countries"
|
|
||||||
ng-model="intrastat.countryFk"
|
|
||||||
show-field="code"
|
|
||||||
rule>
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-none>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-tooltip="Remove due day"
|
|
||||||
icon="delete"
|
|
||||||
ng-click="$ctrl.deleteIntrastat($index)"
|
|
||||||
tabindex="-1">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-none>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-one>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-bind="+"
|
|
||||||
vn-tooltip="Add due day"
|
|
||||||
icon="add_circle"
|
|
||||||
ng-click="$ctrl.add()">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-one>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Save">
|
|
||||||
</vn-submit>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
|
@ -1,60 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
|
||||||
set invoceInIntrastat(value) {
|
|
||||||
this._invoceInIntrastat = value;
|
|
||||||
|
|
||||||
if (value) this.calculateTotals();
|
|
||||||
}
|
|
||||||
|
|
||||||
get invoceInIntrastat() {
|
|
||||||
return this._invoceInIntrastat;
|
|
||||||
}
|
|
||||||
|
|
||||||
calculateTotals() {
|
|
||||||
this.amountTotal = 0.0;
|
|
||||||
this.netTotal = 0.0;
|
|
||||||
this.stemsTotal = 0.0;
|
|
||||||
if (!this.invoceInIntrastat) return;
|
|
||||||
|
|
||||||
this.invoceInIntrastat.forEach(intrastat => {
|
|
||||||
this.amountTotal += intrastat.amount;
|
|
||||||
this.netTotal += intrastat.net;
|
|
||||||
this.stemsTotal += intrastat.stems;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
add() {
|
|
||||||
this.$.model.insert({});
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteIntrastat($index) {
|
|
||||||
this.$.model.remove($index);
|
|
||||||
this.$.model.save().then(() => {
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
this.calculateTotals();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onSubmit() {
|
|
||||||
this.$.watcher.check();
|
|
||||||
this.$.model.save().then(() => {
|
|
||||||
this.$.watcher.notifySaved();
|
|
||||||
this.$.watcher.updateOriginalData();
|
|
||||||
this.calculateTotals();
|
|
||||||
this.card.reload();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnInvoiceInIntrastat', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
require: {
|
|
||||||
card: '^vnInvoiceInCard'
|
|
||||||
},
|
|
||||||
bindings: {
|
|
||||||
invoiceIn: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,85 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
import watcher from 'core/mocks/watcher';
|
|
||||||
import crudModel from 'core/mocks/crud-model';
|
|
||||||
|
|
||||||
describe('InvoiceIn', () => {
|
|
||||||
describe('Component intrastat', () => {
|
|
||||||
let controller;
|
|
||||||
let $scope;
|
|
||||||
let vnApp;
|
|
||||||
|
|
||||||
beforeEach(ngModule('invoiceIn'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, $rootScope, _vnApp_) => {
|
|
||||||
vnApp = _vnApp_;
|
|
||||||
jest.spyOn(vnApp, 'showError');
|
|
||||||
$scope = $rootScope.$new();
|
|
||||||
$scope.model = crudModel;
|
|
||||||
$scope.watcher = watcher;
|
|
||||||
|
|
||||||
const $element = angular.element('<vn-invoice-in-intrastat></vn-invoice-in-intrastat>');
|
|
||||||
controller = $componentController('vnInvoiceInIntrastat', {$element, $scope});
|
|
||||||
controller.invoiceIn = {id: 1};
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('calculateTotals()', () => {
|
|
||||||
it('should set amountTotal, netTotal and stemsTotal to 0 if salesClaimed has no data', () => {
|
|
||||||
controller.invoceInIntrastat = [];
|
|
||||||
controller.calculateTotals();
|
|
||||||
|
|
||||||
expect(controller.amountTotal).toEqual(0);
|
|
||||||
expect(controller.netTotal).toEqual(0);
|
|
||||||
expect(controller.stemsTotal).toEqual(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set amountTotal, netTotal and stemsTotal', () => {
|
|
||||||
controller.invoceInIntrastat = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
invoiceInFk: 1,
|
|
||||||
net: 30.5,
|
|
||||||
intrastatFk: 5080000,
|
|
||||||
amount: 10,
|
|
||||||
stems: 162,
|
|
||||||
countryFk: 5,
|
|
||||||
statisticalValue: 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
invoiceInFk: 1,
|
|
||||||
net: 10,
|
|
||||||
intrastatFk: 6021010,
|
|
||||||
amount: 20,
|
|
||||||
stems: 205,
|
|
||||||
countryFk: 5,
|
|
||||||
statisticalValue: 0
|
|
||||||
}
|
|
||||||
];
|
|
||||||
controller.calculateTotals();
|
|
||||||
|
|
||||||
expect(controller.amountTotal).toEqual(30);
|
|
||||||
expect(controller.netTotal).toEqual(40.5);
|
|
||||||
expect(controller.stemsTotal).toEqual(367);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onSubmit()', () => {
|
|
||||||
it('should make HTTP POST request to save intrastat values', () => {
|
|
||||||
controller.card = {reload: () => {}};
|
|
||||||
jest.spyOn($scope.watcher, 'check');
|
|
||||||
jest.spyOn($scope.watcher, 'notifySaved');
|
|
||||||
jest.spyOn($scope.watcher, 'updateOriginalData');
|
|
||||||
jest.spyOn(controller.card, 'reload');
|
|
||||||
jest.spyOn($scope.model, 'save');
|
|
||||||
|
|
||||||
controller.onSubmit();
|
|
||||||
|
|
||||||
expect($scope.model.save).toHaveBeenCalledWith();
|
|
||||||
expect($scope.watcher.updateOriginalData).toHaveBeenCalledWith();
|
|
||||||
expect($scope.watcher.check).toHaveBeenCalledWith();
|
|
||||||
expect($scope.watcher.notifySaved).toHaveBeenCalledWith();
|
|
||||||
expect(controller.card.reload).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1 +0,0 @@
|
||||||
<vn-log url="InvoiceInLogs" origin-id="$ctrl.$params.id"></vn-log>
|
|
|
@ -1,7 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnInvoiceInLog', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Section,
|
|
||||||
});
|
|
|
@ -1,18 +0,0 @@
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="InvoiceIns/filter"
|
|
||||||
limit="20"
|
|
||||||
order="isBooked, issued DESC">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-portal slot="topbar">
|
|
||||||
<vn-searchbar
|
|
||||||
vn-focus
|
|
||||||
panel="vn-invoice-in-search-panel"
|
|
||||||
info="Search invoices in by reference"
|
|
||||||
model="model">
|
|
||||||
</vn-searchbar>
|
|
||||||
</vn-portal>
|
|
||||||
<vn-portal slot="menu">
|
|
||||||
<vn-left-menu></vn-left-menu>
|
|
||||||
</vn-portal>
|
|
||||||
<ui-view></ui-view>
|
|
|
@ -1,7 +1,16 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
import ModuleMain from 'salix/components/module-main';
|
import ModuleMain from 'salix/components/module-main';
|
||||||
|
|
||||||
export default class InvoiceIn extends ModuleMain {}
|
export default class InvoiceIn extends ModuleMain {
|
||||||
|
constructor($element, $) {
|
||||||
|
super($element, $);
|
||||||
|
}
|
||||||
|
|
||||||
|
async $onInit() {
|
||||||
|
this.$state.go('home');
|
||||||
|
window.location.href = await this.vnApp.getUrl(`invoice-in/`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ngModule.vnComponent('vnInvoiceIn', {
|
ngModule.vnComponent('vnInvoiceIn', {
|
||||||
controller: InvoiceIn,
|
controller: InvoiceIn,
|
||||||
|
|
|
@ -1,97 +0,0 @@
|
||||||
<div class="search-panel">
|
|
||||||
<form ng-submit="$ctrl.onSearch()">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="General search"
|
|
||||||
ng-model="filter.search"
|
|
||||||
info="Search invoices in by id or supplier fiscal name"
|
|
||||||
vn-focus>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Supplier ref."
|
|
||||||
ng-model="filter.supplierRef">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Supplier fiscal id"
|
|
||||||
ng-model="filter.fi">
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one ng-model="filter.supplierFk"
|
|
||||||
url="Suppliers"
|
|
||||||
show-field="nickname"
|
|
||||||
search-function="{or: [{id: $search}, {nickname: {like: '%'+ $search +'%'}}]}"
|
|
||||||
value-field="id"
|
|
||||||
order="nickname"
|
|
||||||
label="Supplier">
|
|
||||||
<tpl-item>
|
|
||||||
{{::id}} - {{::nickname}}
|
|
||||||
</tpl-item>
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Account"
|
|
||||||
ng-model="filter.account">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-input-number
|
|
||||||
vn-one
|
|
||||||
label="Amount"
|
|
||||||
ng-model="filter.amount"
|
|
||||||
step="0.01">
|
|
||||||
</vn-input-number>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-date-picker
|
|
||||||
vn-one
|
|
||||||
label="From"
|
|
||||||
ng-model="filter.from">
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-date-picker
|
|
||||||
vn-one
|
|
||||||
label="To"
|
|
||||||
ng-model="filter.to">
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-date-picker
|
|
||||||
vn-one
|
|
||||||
label="Issued"
|
|
||||||
ng-model="filter.issued">
|
|
||||||
</vn-date-picker>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Serial number"
|
|
||||||
ng-model="filter.serialNumber">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Serial"
|
|
||||||
ng-model="filter.serial">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="AWB"
|
|
||||||
ng-model="filter.awbCode">
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-check
|
|
||||||
vn-one
|
|
||||||
triple-state="true"
|
|
||||||
label="Is booked"
|
|
||||||
ng-model="filter.isBooked">
|
|
||||||
</vn-check>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-mt-lg">
|
|
||||||
<vn-submit label="Search"></vn-submit>
|
|
||||||
</vn-horizontal>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
|
@ -1,7 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import SearchPanel from 'core/components/searchbar/search-panel';
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnInvoiceInSearchPanel', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: SearchPanel
|
|
||||||
});
|
|
|
@ -1,2 +0,0 @@
|
||||||
Supplier fiscal id: CIF proveedor
|
|
||||||
Search invoices in by id or supplier fiscal name: Buscar facturas recibidas por id o por nombre fiscal del proveedor
|
|
|
@ -1,27 +0,0 @@
|
||||||
<vn-side-menu side="right">
|
|
||||||
<vn-horizontal class="input">
|
|
||||||
<vn-input-number
|
|
||||||
label="Days ago"
|
|
||||||
ng-model="$ctrl.filter.daysAgo"
|
|
||||||
vn-focus
|
|
||||||
ng-keydown="$ctrl.onKeyPress($event)"
|
|
||||||
min="0">
|
|
||||||
</vn-input-number>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="input">
|
|
||||||
<vn-textfield
|
|
||||||
label="Serial"
|
|
||||||
ng-model="$ctrl.filter.serial"
|
|
||||||
ng-keydown="$ctrl.onKeyPress($event)">
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<div class="chips">
|
|
||||||
<vn-chip
|
|
||||||
ng-if="$ctrl.filter.serial"
|
|
||||||
removable="true"
|
|
||||||
on-remove="$ctrl.removeItemFilter('serial')"
|
|
||||||
class="colored">
|
|
||||||
<span>{{$ctrl.$t('Serial')}}: {{$ctrl.filter.serial}}</span>
|
|
||||||
</vn-chip>
|
|
||||||
</div>
|
|
||||||
</vn-side-menu>
|
|
|
@ -1,44 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import SearchPanel from 'core/components/searchbar/search-panel';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
class Controller extends SearchPanel {
|
|
||||||
constructor($element, $) {
|
|
||||||
super($element, $);
|
|
||||||
this.filter = {};
|
|
||||||
const filter = {
|
|
||||||
fields: ['daysAgo']
|
|
||||||
};
|
|
||||||
this.$http.get('InvoiceInConfigs', {filter}).then(res => {
|
|
||||||
if (res.data) {
|
|
||||||
this.invoiceInConfig = res.data[0];
|
|
||||||
this.addFilters();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
removeItemFilter(param) {
|
|
||||||
this.filter[param] = null;
|
|
||||||
this.addFilters();
|
|
||||||
}
|
|
||||||
|
|
||||||
onKeyPress($event) {
|
|
||||||
if ($event.key === 'Enter')
|
|
||||||
this.addFilters();
|
|
||||||
}
|
|
||||||
|
|
||||||
addFilters() {
|
|
||||||
if (!this.filter.daysAgo)
|
|
||||||
this.filter.daysAgo = this.invoiceInConfig.daysAgo;
|
|
||||||
|
|
||||||
return this.model.addFilter({}, this.filter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnInvoiceInSerialSearchPanel', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
model: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,43 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
|
|
||||||
describe('InvoiceIn', () => {
|
|
||||||
describe('Component serial-search-panel', () => {
|
|
||||||
let controller;
|
|
||||||
let $scope;
|
|
||||||
|
|
||||||
beforeEach(ngModule('invoiceIn'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, $rootScope) => {
|
|
||||||
$scope = $rootScope.$new();
|
|
||||||
const $element = angular.element('<vn-invoice-in-serial-search-panel></vn-invoice-in-serial-search-panel>');
|
|
||||||
controller = $componentController('vnInvoiceInSerialSearchPanel', {$element, $scope});
|
|
||||||
controller.model = {
|
|
||||||
addFilter: jest.fn(),
|
|
||||||
};
|
|
||||||
controller.invoiceInConfig = {
|
|
||||||
daysAgo: 45,
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('addFilters()', () => {
|
|
||||||
it('should add default daysAgo if it is not already set', () => {
|
|
||||||
controller.filter = {
|
|
||||||
serial: 'R',
|
|
||||||
};
|
|
||||||
controller.addFilters();
|
|
||||||
|
|
||||||
expect(controller.filter.daysAgo).toEqual(controller.invoiceInConfig.daysAgo);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not add default daysAgo if it is already set', () => {
|
|
||||||
controller.filter = {
|
|
||||||
daysAgo: 1,
|
|
||||||
serial: 'R',
|
|
||||||
};
|
|
||||||
controller.addFilters();
|
|
||||||
|
|
||||||
expect(controller.filter.daysAgo).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,24 +0,0 @@
|
||||||
@import "variables";
|
|
||||||
|
|
||||||
vn-invoice-in-serial-search-panel vn-side-menu div {
|
|
||||||
& > .input {
|
|
||||||
padding-left: $spacing-md;
|
|
||||||
padding-right: $spacing-md;
|
|
||||||
border-color: $color-spacer;
|
|
||||||
border-bottom: $border-thin;
|
|
||||||
}
|
|
||||||
& > .horizontal {
|
|
||||||
grid-auto-flow: column;
|
|
||||||
grid-column-gap: $spacing-sm;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
& > .chips {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
padding: $spacing-md;
|
|
||||||
overflow: hidden;
|
|
||||||
max-width: 100%;
|
|
||||||
border-color: $color-spacer;
|
|
||||||
border-top: $border-thin;
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue