Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 6335-ticketAdvance_splitOrCreate
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Alex Moreno 2023-11-16 09:58:51 +01:00
commit b8d256e4e4
36 changed files with 239 additions and 163 deletions

View File

@ -8,7 +8,7 @@ Salix is also the scientific name of a beautifull tree! :)
Required applications. Required applications.
* Node.js >= 16.x LTS * Node.js
* Docker * Docker
* Git * Git
@ -17,20 +17,7 @@ You will need to install globally the following items.
$ sudo npm install -g jest gulp-cli $ sudo npm install -g jest gulp-cli
``` ```
For the usage of jest --watch on macOs. ## Installing dependencies and launching
```
$ brew install watchman
```
* [watchman](https://facebook.github.io/watchman/)
## Linux Only Prerequisites
Your user must be on the docker group to use it so you will need to run this command:
```
$ sudo usermod -a -G docker yourusername
```
## Getting Started // Installing
Pull from repository. Pull from repository.
@ -76,29 +63,6 @@ In Visual Studio Code we use the ESLint extension.
ext install dbaeumer.vscode-eslint ext install dbaeumer.vscode-eslint
``` ```
Gitlens for visualization of code authorship
```
ext install eamodio.gitlens
```
Spanish language pack
```
ext install ms-ceintl.vscode-language-pack-es
```
### Recommended extensions
Material icon Theme
```
ext install pkief.material-icon-theme
```
Material UI Themes
```
ext install equinusocio.vsc-material-theme
```
## Built With ## Built With
* [angularjs](https://angularjs.org/) * [angularjs](https://angularjs.org/)

View File

@ -49,8 +49,13 @@ module.exports = Self => {
if (vnUser.twoFactor) if (vnUser.twoFactor)
throw new ForbiddenError(null, 'REQUIRES_2FA'); throw new ForbiddenError(null, 'REQUIRES_2FA');
} }
const validateLogin = await Self.validateLogin(user, password);
return Self.validateLogin(user, password); await Self.app.models.SignInLog.create({
id: validateLogin.token,
userFk: vnUser.id,
ip: ctx.req.ip
});
return validateLogin;
}; };
Self.passExpired = async vnUser => { Self.passExpired = async vnUser => {

View File

@ -2,6 +2,7 @@ const vnModel = require('vn-loopback/common/models/vn-model');
const {Email} = require('vn-print'); const {Email} = require('vn-print');
const ForbiddenError = require('vn-loopback/util/forbiddenError'); const ForbiddenError = require('vn-loopback/util/forbiddenError');
const LoopBackContext = require('loopback-context'); const LoopBackContext = require('loopback-context');
const UserError = require('vn-loopback/util/user-error');
module.exports = function(Self) { module.exports = function(Self) {
vnModel(Self); vnModel(Self);
@ -92,7 +93,11 @@ module.exports = function(Self) {
}; };
Self.on('resetPasswordRequest', async function(info) { Self.on('resetPasswordRequest', async function(info) {
const url = await Self.app.models.Url.getUrl(); const loopBackContext = LoopBackContext.getCurrentContext();
const httpCtx = {req: loopBackContext.active};
const httpRequest = httpCtx.req.http.req;
const headers = httpRequest.headers;
const origin = headers.origin;
const defaultHash = '/reset-password?access_token=$token$'; const defaultHash = '/reset-password?access_token=$token$';
const recoverHashes = { const recoverHashes = {
@ -108,7 +113,7 @@ module.exports = function(Self) {
const params = { const params = {
recipient: info.email, recipient: info.email,
lang: user.lang, lang: user.lang,
url: url.slice(0, -1) + recoverHash url: origin + '/#!' + recoverHash
}; };
const options = Object.assign({}, info.options); const options = Object.assign({}, info.options);
@ -121,10 +126,16 @@ module.exports = function(Self) {
}); });
Self.validateLogin = async function(user, password) { Self.validateLogin = async function(user, password) {
let loginInfo = Object.assign({password}, Self.userUses(user)); const loginInfo = Object.assign({password}, Self.userUses(user));
token = await Self.login(loginInfo, 'user'); const token = await Self.login(loginInfo, 'user');
const userToken = await token.user.get(); const userToken = await token.user.get();
if (userToken.username.toLowerCase() !== user.toLowerCase()) {
console.error('ERROR!!! - Signin with other user', userToken, user);
throw new UserError('Try again');
}
try { try {
await Self.app.models.Account.sync(userToken.name, password); await Self.app.models.Account.sync(userToken.name, password);
} catch (err) { } catch (err) {
@ -220,8 +231,11 @@ module.exports = function(Self) {
class Mailer { class Mailer {
async send(verifyOptions, cb) { async send(verifyOptions, cb) {
const url = new URL(verifyOptions.verifyHref);
if (process.env.NODE_ENV) url.port = '';
const params = { const params = {
url: verifyOptions.verifyHref, url: url.href,
recipient: verifyOptions.to recipient: verifyOptions.to
}; };

View File

@ -74,7 +74,7 @@ BEGIN
clientFk, clientFk,
dued, dued,
companyFk, companyFk,
cplusInvoiceType477Fk siiTypeInvoiceOutFk
) )
SELECT SELECT
1, 1,

View File

@ -96,7 +96,7 @@ BEGIN
clientFk, clientFk,
dued, dued,
companyFk, companyFk,
cplusInvoiceType477Fk siiTypeInvoiceOutFk
) )
SELECT SELECT
1, 1,

View File

@ -96,7 +96,7 @@ BEGIN
clientFk, clientFk,
dued, dued,
companyFk, companyFk,
cplusInvoiceType477Fk siiTypeInvoiceOutFk
) )
SELECT SELECT
1, 1,

View File

@ -1,6 +1,6 @@
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId) INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
VALUES VALUES
('CplusRectificationType', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'), ('CplusRectificationType', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('CplusInvoiceType477', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'), ('SiiTypeInvoiceOut', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('InvoiceCorrectionType', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'), ('InvoiceCorrectionType', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('InvoiceOut', 'transferInvoice', 'WRITE', 'ALLOW', 'ROLE', 'administrative'); ('InvoiceOut', 'transferInvoice', 'WRITE', 'ALLOW', 'ROLE', 'administrative');

View File

@ -0,0 +1 @@
CALL `account`.`role_sync`();

View File

@ -0,0 +1,19 @@
--
-- Table structure for table `signInLog`
--
DROP TABLE IF EXISTS `account`.`signInLog`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `account`.`signInLog` (
`id` varchar(10) NOT NULL ,
`userFk` int(10) unsigned DEFAULT NULL,
`creationDate` timestamp NULL DEFAULT current_timestamp(),
`ip` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,
PRIMARY KEY (`id`),
KEY `userFk` (`userFk`),
CONSTRAINT `signInLog_ibfk_1` FOREIGN KEY (`userFk`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
);

View File

@ -275,13 +275,13 @@ INSERT INTO `cplusInvoiceType472` VALUES (1,'F1 - Factura'),(2,'F2 - Factura sim
UNLOCK TABLES; UNLOCK TABLES;
-- --
-- Dumping data for table `cplusInvoiceType477` -- Dumping data for table `siiTypeInvoiceOut`
-- --
LOCK TABLES `cplusInvoiceType477` WRITE; LOCK TABLES `siiTypeInvoiceOut` WRITE;
/*!40000 ALTER TABLE `cplusInvoiceType477` DISABLE KEYS */; /*!40000 ALTER TABLE `siiTypeInvoiceOut` DISABLE KEYS */;
INSERT INTO `cplusInvoiceType477` VALUES (1,'F1 - Factura'),(2,'F2 - Factura simplificada (ticket)'),(3,'F3 - Factura emitida en sustitución de facturas simplificadas facturadas y declaradas'),(4,'F4 - Asiento resumen de facturas'),(5,'R1 - Factura rectificativa (Art. 80.1, 80.2 y error fundado en derecho)'),(6,'R2 - Factura rectificativa (Art. 80.3)'),(7,'R3 - Factura rectificativa (Art. 80.4)'),(8,'R4 - Factura rectificativa (Resto)'),(9,'R5 - Factura rectificativa en facturas simplificadas'); INSERT INTO `siiTypeInvoiceOut` VALUES (1,'F1 - Factura'),(2,'F2 - Factura simplificada (ticket)'),(3,'F3 - Factura emitida en sustitución de facturas simplificadas facturadas y declaradas'),(4,'F4 - Asiento resumen de facturas'),(5,'R1 - Factura rectificativa (Art. 80.1, 80.2 y error fundado en derecho)'),(6,'R2 - Factura rectificativa (Art. 80.3)'),(7,'R3 - Factura rectificativa (Art. 80.4)'),(8,'R4 - Factura rectificativa (Resto)'),(9,'R5 - Factura rectificativa en facturas simplificadas');
/*!40000 ALTER TABLE `cplusInvoiceType477` ENABLE KEYS */; /*!40000 ALTER TABLE `siiTypeInvoiceOut` ENABLE KEYS */;
UNLOCK TABLES; UNLOCK TABLES;
-- --

View File

@ -367,7 +367,7 @@ INSERT INTO `vn`.`client`(`id`,`name`,`fi`,`socialName`,`contact`,`street`,`city
(1105, 'Max Eisenhardt', '251628698', 'MAGNETO', 'Rogue', 'UNKNOWN WHEREABOUTS', 'Gotham', 46460, 1111111111, 222222222, 1, 'MaxEisenhardt@mydomain.com', NULL, 0, 1234567890, 0, 3, 1, 300, 8, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 1, NULL, 0, 0, 18, 0, 1, 'florist','normal'), (1105, 'Max Eisenhardt', '251628698', 'MAGNETO', 'Rogue', 'UNKNOWN WHEREABOUTS', 'Gotham', 46460, 1111111111, 222222222, 1, 'MaxEisenhardt@mydomain.com', NULL, 0, 1234567890, 0, 3, 1, 300, 8, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 1, NULL, 0, 0, 18, 0, 1, 'florist','normal'),
(1106, 'DavidCharlesHaller', '53136686Q', 'LEGION', 'Charles Xavier', 'CITY OF NEW YORK, NEW YORK, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'DavidCharlesHaller@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 0, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 19, 0, 1, 'florist','normal'), (1106, 'DavidCharlesHaller', '53136686Q', 'LEGION', 'Charles Xavier', 'CITY OF NEW YORK, NEW YORK, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'DavidCharlesHaller@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 0, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 19, 0, 1, 'florist','normal'),
(1107, 'Hank Pym', '09854837G', 'ANT MAN', 'Hawk', 'ANTHILL, SAN FRANCISCO, CALIFORNIA', 'Gotham', 46460, 1111111111, 222222222, 1, 'HankPym@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, 0, NULL, 0, 0, 19, 0, 1, 'florist','normal'), (1107, 'Hank Pym', '09854837G', 'ANT MAN', 'Hawk', 'ANTHILL, SAN FRANCISCO, CALIFORNIA', 'Gotham', 46460, 1111111111, 222222222, 1, 'HankPym@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, 0, NULL, 0, 0, 19, 0, 1, 'florist','normal'),
(1108, 'Charles Xavier', '22641921P', 'PROFESSOR X', 'Beast', '3800 VICTORY PKWY, CINCINNATI, OH 45207, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'CharlesXavier@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 1, NULL, 0, 0, 19, 0, 1, 'florist','normal'), (1108, 'Charles Xavier', '22641921P', 'PROFESSOR X', 'Beast', '3800 VICTORY PKWY, CINCINNATI, OH 45207, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'CharlesXavier@mydomain.com', NULL, 0, 1234567890, 0, 5, 1, 300, 13, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 1, NULL, 0, 0, 19, 0, 1, 'florist','normal'),
(1109, 'Bruce Banner', '16104829E', 'HULK', 'Black widow', 'SOMEWHERE IN NEW YORK', 'Gotham', 46460, 1111111111, 222222222, 1, 'BruceBanner@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, 0, NULL, 0, 0, 9, 0, 1, 'florist','normal'), (1109, 'Bruce Banner', '16104829E', 'HULK', 'Black widow', 'SOMEWHERE IN NEW YORK', 'Gotham', 46460, 1111111111, 222222222, 1, 'BruceBanner@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, 0, NULL, 0, 0, 9, 0, 1, 'florist','normal'),
(1110, 'Jessica Jones', '58282869H', 'JESSICA JONES', 'Luke Cage', 'NYCC 2015 POSTER', 'Gotham', 46460, 1111111111, 222222222, 1, 'JessicaJones@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, 0, NULL, 0, 0, NULL, 0, 1, 'florist','normal'), (1110, 'Jessica Jones', '58282869H', 'JESSICA JONES', 'Luke Cage', 'NYCC 2015 POSTER', 'Gotham', 46460, 1111111111, 222222222, 1, 'JessicaJones@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, 0, NULL, 0, 0, NULL, 0, 1, 'florist','normal'),
(1111, 'Missing', NULL, 'MISSING MAN', 'Anton', 'THE SPACE, UNIVERSE FAR AWAY', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 4, 0, 1, 0, NULL, 1, 0, NULL, 0, 1, 'others','normal'), (1111, 'Missing', NULL, 'MISSING MAN', 'Anton', 'THE SPACE, UNIVERSE FAR AWAY', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 4, 0, 1, 0, NULL, 1, 0, NULL, 0, 1, 'others','normal'),
@ -405,7 +405,7 @@ INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `pr
(5, 'Max Eisenhardt', 'Unknown Whereabouts', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1105, 2, NULL, NULL, 0, 1), (5, 'Max Eisenhardt', 'Unknown Whereabouts', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1105, 2, NULL, NULL, 0, 1),
(6, 'DavidCharlesHaller', 'Evil hideout', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1106, 2, NULL, NULL, 0, 1), (6, 'DavidCharlesHaller', 'Evil hideout', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1106, 2, NULL, NULL, 0, 1),
(7, 'Hank Pym', 'Anthill', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1107, 2, NULL, NULL, 0, 1), (7, 'Hank Pym', 'Anthill', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1107, 2, NULL, NULL, 0, 1),
(8, 'Charles Xavier', '3800 Victory Pkwy, Cincinnati, OH 45207, USA', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1108, 2, NULL, NULL, 0, 1), (8, 'Charles Xavier', '3800 Victory Pkwy, Cincinnati, OH 45207, USA', 'Gotham', 46460, 5, 1111111111, 222222222, 1, 1108, 2, NULL, NULL, 0, 1),
(9, 'Bruce Banner', 'Somewhere in New York', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 1), (9, 'Bruce Banner', 'Somewhere in New York', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 1),
(10, 'Jessica Jones', 'NYCC 2015 Poster', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1110, 2, NULL, NULL, 0, 1), (10, 'Jessica Jones', 'NYCC 2015 Poster', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1110, 2, NULL, NULL, 0, 1),
(11, 'Missing', 'The space', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1111, 10, NULL, NULL, 0, 1), (11, 'Missing', 'The space', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1111, 10, NULL, NULL, 0, 1),
@ -437,7 +437,7 @@ INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `pr
(125, 'The plastic cell', 'address 25', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1105, 2, NULL, NULL, 0, 0), (125, 'The plastic cell', 'address 25', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1105, 2, NULL, NULL, 0, 0),
(126, 'Many places', 'address 26', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1106, 2, NULL, NULL, 0, 0), (126, 'Many places', 'address 26', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1106, 2, NULL, NULL, 0, 0),
(127, 'Your pocket', 'address 27', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1107, 2, NULL, NULL, 0, 0), (127, 'Your pocket', 'address 27', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1107, 2, NULL, NULL, 0, 0),
(128, 'Cerebro', 'address 28', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1108, 2, NULL, NULL, 0, 0), (128, 'Cerebro', 'address 28', 'Gotham', 46460, 5, 1111111111, 222222222, 1, 1108, 2, NULL, NULL, 0, 0),
(129, 'Luke Cages Bar', 'address 29', 'Gotham', 'EC170150', 1, 1111111111, 222222222, 1, 1110, 2, NULL, NULL, 0, 0), (129, 'Luke Cages Bar', 'address 29', 'Gotham', 'EC170150', 1, 1111111111, 222222222, 1, 1110, 2, NULL, NULL, 0, 0),
(130, 'Non valid address', 'address 30', 'Gotham', 46460, 1, 1111111111, 222222222, 0, 1101, 2, NULL, NULL, 0, 0); (130, 'Non valid address', 'address 30', 'Gotham', 46460, 1, 1111111111, 222222222, 0, 1101, 2, NULL, NULL, 0, 0);

View File

@ -26077,13 +26077,13 @@ CREATE TABLE `cplusInvoiceType472` (
/*!40101 SET character_set_client = @saved_cs_client */; /*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Table structure for table `cplusInvoiceType477` -- Table structure for table `siiTypeInvoiceOut`
-- --
DROP TABLE IF EXISTS `cplusInvoiceType477`; DROP TABLE IF EXISTS `siiTypeInvoiceOut`;
/*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */; /*!40101 SET character_set_client = utf8 */;
CREATE TABLE `cplusInvoiceType477` ( CREATE TABLE `siiTypeInvoiceOut` (
`id` int(10) unsigned NOT NULL, `id` int(10) unsigned NOT NULL,
`description` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL, `description` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
@ -29534,16 +29534,16 @@ CREATE TABLE `invoiceCorrection` (
`correctingFk` int(10) unsigned NOT NULL COMMENT 'Factura rectificativa', `correctingFk` int(10) unsigned NOT NULL COMMENT 'Factura rectificativa',
`correctedFk` int(10) unsigned NOT NULL COMMENT 'Factura rectificada', `correctedFk` int(10) unsigned NOT NULL COMMENT 'Factura rectificada',
`cplusRectificationTypeFk` int(10) unsigned NOT NULL, `cplusRectificationTypeFk` int(10) unsigned NOT NULL,
`cplusInvoiceType477Fk` int(10) unsigned NOT NULL, `siiTypeInvoiceOutFk` int(10) unsigned NOT NULL,
`invoiceCorrectionTypeFk` int(11) NOT NULL DEFAULT 3, `invoiceCorrectionTypeFk` int(11) NOT NULL DEFAULT 3,
PRIMARY KEY (`correctingFk`), PRIMARY KEY (`correctingFk`),
KEY `correctedFk_idx` (`correctedFk`), KEY `correctedFk_idx` (`correctedFk`),
KEY `invoiceCorrection_ibfk_1_idx` (`cplusRectificationTypeFk`), KEY `invoiceCorrection_ibfk_1_idx` (`cplusRectificationTypeFk`),
KEY `cplusInvoiceTyoeFk_idx` (`cplusInvoiceType477Fk`), KEY `cplusInvoiceTyoeFk_idx` (`siiTypeInvoiceOutFk`),
KEY `invoiceCorrectionTypeFk_idx` (`invoiceCorrectionTypeFk`), KEY `invoiceCorrectionTypeFk_idx` (`invoiceCorrectionTypeFk`),
CONSTRAINT `corrected_fk` FOREIGN KEY (`correctedFk`) REFERENCES `invoiceOut` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `corrected_fk` FOREIGN KEY (`correctedFk`) REFERENCES `invoiceOut` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `correcting_fk` FOREIGN KEY (`correctingFk`) REFERENCES `invoiceOut` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `correcting_fk` FOREIGN KEY (`correctingFk`) REFERENCES `invoiceOut` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `cplusInvoiceTyoeFk` FOREIGN KEY (`cplusInvoiceType477Fk`) REFERENCES `cplusInvoiceType477` (`id`) ON UPDATE CASCADE, CONSTRAINT `cplusInvoiceTyoeFk` FOREIGN KEY (`siiTypeInvoiceOutFk`) REFERENCES `siiTypeInvoiceOut` (`id`) ON UPDATE CASCADE,
CONSTRAINT `invoiceCorrectionType_Fk33` FOREIGN KEY (`invoiceCorrectionTypeFk`) REFERENCES `invoiceCorrectionType` (`id`) ON UPDATE CASCADE, CONSTRAINT `invoiceCorrectionType_Fk33` FOREIGN KEY (`invoiceCorrectionTypeFk`) REFERENCES `invoiceCorrectionType` (`id`) ON UPDATE CASCADE,
CONSTRAINT `invoiceCorrection_ibfk_1` FOREIGN KEY (`cplusRectificationTypeFk`) REFERENCES `cplusRectificationType` (`id`) ON UPDATE CASCADE CONSTRAINT `invoiceCorrection_ibfk_1` FOREIGN KEY (`cplusRectificationTypeFk`) REFERENCES `cplusRectificationType` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='Relacion entre las facturas rectificativas y las rectificadas.'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='Relacion entre las facturas rectificativas y las rectificadas.';
@ -30214,7 +30214,7 @@ CREATE TABLE `invoiceOut` (
`companyFk` int(10) unsigned NOT NULL DEFAULT 442, `companyFk` int(10) unsigned NOT NULL DEFAULT 442,
`hasPdf` tinyint(3) unsigned NOT NULL DEFAULT 0, `hasPdf` tinyint(3) unsigned NOT NULL DEFAULT 0,
`booked` date DEFAULT NULL, `booked` date DEFAULT NULL,
`cplusInvoiceType477Fk` int(10) unsigned NOT NULL DEFAULT 1, `siiTypeInvoiceOutFk` int(10) unsigned NOT NULL DEFAULT 1,
`cplusTaxBreakFk` int(10) unsigned NOT NULL DEFAULT 1, `cplusTaxBreakFk` int(10) unsigned NOT NULL DEFAULT 1,
`cplusSubjectOpFk` int(10) unsigned NOT NULL DEFAULT 1, `cplusSubjectOpFk` int(10) unsigned NOT NULL DEFAULT 1,
`cplusTrascendency477Fk` int(10) unsigned NOT NULL DEFAULT 1, `cplusTrascendency477Fk` int(10) unsigned NOT NULL DEFAULT 1,
@ -30224,13 +30224,13 @@ CREATE TABLE `invoiceOut` (
KEY `Id_Cliente` (`clientFk`), KEY `Id_Cliente` (`clientFk`),
KEY `empresa_id` (`companyFk`), KEY `empresa_id` (`companyFk`),
KEY `Fecha` (`issued`), KEY `Fecha` (`issued`),
KEY `Facturas_ibfk_2_idx` (`cplusInvoiceType477Fk`), KEY `Facturas_ibfk_2_idx` (`siiTypeInvoiceOutFk`),
KEY `Facturas_ibfk_3_idx` (`cplusSubjectOpFk`), KEY `Facturas_ibfk_3_idx` (`cplusSubjectOpFk`),
KEY `Facturas_ibfk_4_idx` (`cplusTaxBreakFk`), KEY `Facturas_ibfk_4_idx` (`cplusTaxBreakFk`),
KEY `Facturas_ibfk_5_idx` (`cplusTrascendency477Fk`), KEY `Facturas_ibfk_5_idx` (`cplusTrascendency477Fk`),
KEY `Facturas_idx_Vencimiento` (`dued`), KEY `Facturas_idx_Vencimiento` (`dued`),
KEY `invoiceOut_serial` (`serial`), KEY `invoiceOut_serial` (`serial`),
CONSTRAINT `invoiceOut_ibfk_2` FOREIGN KEY (`cplusInvoiceType477Fk`) REFERENCES `cplusInvoiceType477` (`id`) ON UPDATE CASCADE, CONSTRAINT `invoiceOut_ibfk_2` FOREIGN KEY (`siiTypeInvoiceOutFk`) REFERENCES `siiTypeInvoiceOut` (`id`) ON UPDATE CASCADE,
CONSTRAINT `invoiceOut_ibfk_3` FOREIGN KEY (`cplusSubjectOpFk`) REFERENCES `cplusSubjectOp` (`id`) ON UPDATE CASCADE, CONSTRAINT `invoiceOut_ibfk_3` FOREIGN KEY (`cplusSubjectOpFk`) REFERENCES `cplusSubjectOp` (`id`) ON UPDATE CASCADE,
CONSTRAINT `invoiceOut_ibfk_4` FOREIGN KEY (`cplusTaxBreakFk`) REFERENCES `cplusTaxBreak` (`id`) ON UPDATE CASCADE, CONSTRAINT `invoiceOut_ibfk_4` FOREIGN KEY (`cplusTaxBreakFk`) REFERENCES `cplusTaxBreak` (`id`) ON UPDATE CASCADE,
CONSTRAINT `invoiceOut_serial` FOREIGN KEY (`serial`) REFERENCES `invoiceOutSerial` (`code`), CONSTRAINT `invoiceOut_serial` FOREIGN KEY (`serial`) REFERENCES `invoiceOutSerial` (`code`),
@ -30392,7 +30392,7 @@ CREATE TABLE `invoiceOutSerial` (
`isTaxed` tinyint(1) NOT NULL DEFAULT 1, `isTaxed` tinyint(1) NOT NULL DEFAULT 1,
`taxAreaFk` varchar(15) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT 'NATIONAL', `taxAreaFk` varchar(15) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT 'NATIONAL',
`isCEE` tinyint(1) NOT NULL DEFAULT 0, `isCEE` tinyint(1) NOT NULL DEFAULT 0,
`cplusInvoiceType477Fk` int(10) unsigned DEFAULT 1, `siiTypeInvoiceOutFk` int(10) unsigned DEFAULT 1,
`footNotes` longtext DEFAULT NULL, `footNotes` longtext DEFAULT NULL,
`isRefEditable` tinyint(4) NOT NULL DEFAULT 0, `isRefEditable` tinyint(4) NOT NULL DEFAULT 0,
`type` enum('global','quick') DEFAULT NULL, `type` enum('global','quick') DEFAULT NULL,
@ -58372,7 +58372,7 @@ BEGIN
io.cplusTrascendency477Fk AS TIPOCLAVE, io.cplusTrascendency477Fk AS TIPOCLAVE,
io.cplusTaxBreakFk AS TIPOEXENCI, io.cplusTaxBreakFk AS TIPOEXENCI,
io.cplusSubjectOpFk AS TIPONOSUJE, io.cplusSubjectOpFk AS TIPONOSUJE,
io.cplusInvoiceType477Fk AS TIPOFACT, io.siiTypeInvoiceOutFk AS TIPOFACT,
ic.cplusRectificationTypeFk AS TIPORECTIF, ic.cplusRectificationTypeFk AS TIPORECTIF,
io.companyFk, io.companyFk,
RIGHT(io.ref, LENGTH(io.ref) - 1) AS invoiceNum, RIGHT(io.ref, LENGTH(io.ref) - 1) AS invoiceNum,
@ -58952,7 +58952,7 @@ BEGIN
clientFk, clientFk,
dued, dued,
companyFk, companyFk,
cplusInvoiceType477Fk siiTypeInvoiceOutFk
) )
SELECT SELECT
1, 1,

View File

@ -46,7 +46,7 @@ TABLES=(
bookingPlanner bookingPlanner
businessType businessType
cplusInvoiceType472 cplusInvoiceType472
cplusInvoiceType477 siiTypeInvoiceOut
cplusRectificationType cplusRectificationType
cplusSubjectOp cplusSubjectOp
cplusTaxBreak cplusTaxBreak

View File

@ -21,7 +21,8 @@ module.exports = Self => {
const argString = params.map(() => '?').join(','); const argString = params.map(() => '?').join(',');
const [response] = await models.ProcsPriv.rawSql(query + `(${argString})`, params, myOptions); const response = await models.ProcsPriv.rawSql(query + `(${argString})`, params, myOptions);
return response; if (!Array.isArray(response)) return;
return response[0];
}; };
}; };

View File

@ -1,7 +1,7 @@
module.exports = Self => { module.exports = Self => {
Self.remoteMethodCtx('executeFunc', { Self.remoteMethodCtx('executeFunc', {
description: 'Return result of function', description: 'Return result of function',
accessType: '*', accessType: 'EXECUTE',
accepts: [ accepts: [
{ {
arg: 'routine', arg: 'routine',

View File

@ -1,7 +1,7 @@
module.exports = Self => { module.exports = Self => {
Self.remoteMethodCtx('executeProc', { Self.remoteMethodCtx('executeProc', {
description: 'Return result of procedure', description: 'Return result of procedure',
accessType: '*', accessType: 'EXECUTE',
accepts: [ accepts: [
{ {
arg: 'routine', arg: 'routine',

View File

@ -196,5 +196,6 @@
"Negative basis of tickets: 23": "Negative basis of tickets: 23", "Negative basis of tickets: 23": "Negative basis of tickets: 23",
"Booking completed": "Booking complete", "Booking completed": "Booking complete",
"The ticket is in preparation": "The ticket [{{ticketId}}]({{{ticketUrl}}}) of the sales person {{salesPersonId}} is in preparation", "The ticket is in preparation": "The ticket [{{ticketId}}]({{{ticketUrl}}}) of the sales person {{salesPersonId}} is in preparation",
"You can only add negative amounts in refund tickets": "You can only add negative amounts in refund tickets" "You can only add negative amounts in refund tickets": "You can only add negative amounts in refund tickets",
"Try again": "Try again"
} }

View File

@ -323,7 +323,9 @@
"The response is not a PDF": "La respuesta no es un PDF", "The response is not a PDF": "La respuesta no es un PDF",
"Booking completed": "Reserva completada", "Booking completed": "Reserva completada",
"The ticket is in preparation": "El ticket [{{ticketId}}]({{{ticketUrl}}}) del comercial {{salesPersonId}} está en preparación", "The ticket is in preparation": "El ticket [{{ticketId}}]({{{ticketUrl}}}) del comercial {{salesPersonId}} está en preparación",
"The amount cannot be less than the minimum": "La cantidad no puede ser menor que la cantidad mímina", "Incoterms data for consignee is missing": "Faltan los datos de los Incoterms para el consignatario",
"quantityLessThanMin": "La cantidad no puede ser menor que la cantidad mímina", "The notification subscription of this worker cant be modified": "La subscripción a la notificación de este trabajador no puede ser modificada",
"The notification subscription of this worker cant be modified": "La subscripción a la notificación de este trabajador no puede ser modificada" "User disabled": "Usuario desactivado",
"The amount cannot be less than the minimum": "La cantidad no puede ser menor que la cantidad mínima",
"quantityLessThanMin": "La cantidad no puede ser menor que la cantidad mínima"
} }

View File

@ -35,6 +35,9 @@
"SambaConfig": { "SambaConfig": {
"dataSource": "vn" "dataSource": "vn"
}, },
"SignInLog": {
"dataSource": "vn"
},
"Sip": { "Sip": {
"dataSource": "vn" "dataSource": "vn"
}, },

View File

@ -0,0 +1,34 @@
{
"name": "SignInLog",
"base": "VnModel",
"options": {
"mysql": {
"table": "account.signInLog"
}
},
"properties": {
"id": {
"id": true,
"type": "string"
},
"creationDate": {
"type": "date"
},
"userFk": {
"type": "number"
},
"ip": {
"type": "string"
}
},
"relations": {
"user": {
"type": "belongsTo",
"model": "VnUser",
"foreignKey": "userFk"
}
},
"scope": {
"order": ["creationDate DESC", "id DESC"]
}
}

View File

@ -27,7 +27,7 @@ describe('InvoiceOut tranferInvoice()', () => {
ref: 'T4444444', ref: 'T4444444',
newClientFk: 1, newClientFk: 1,
cplusRectificationId: 1, cplusRectificationId: 1,
cplusInvoiceType477Id: 1, siiTypeInvoiceOutId: 1,
invoiceCorrectionTypeId: 1 invoiceCorrectionTypeId: 1
}; };
ctx.args = args; ctx.args = args;
@ -52,7 +52,7 @@ describe('InvoiceOut tranferInvoice()', () => {
ref: 'T1111111', ref: 'T1111111',
newClientFk: 1101, newClientFk: 1101,
cplusRectificationId: 1, cplusRectificationId: 1,
cplusInvoiceType477Id: 1, siiTypeInvoiceOutId: 1,
invoiceCorrectionTypeId: 1 invoiceCorrectionTypeId: 1
}; };
ctx.args = args; ctx.args = args;

View File

@ -27,7 +27,7 @@ module.exports = Self => {
required: true required: true
}, },
{ {
arg: 'cplusInvoiceType477Id', arg: 'siiTypeInvoiceOutId',
type: 'number', type: 'number',
required: true required: true
}, },
@ -93,7 +93,7 @@ module.exports = Self => {
correctingFk: invoiceId, correctingFk: invoiceId,
correctedFk: args.id, correctedFk: args.id,
cplusRectificationTypeFk: args.cplusRectificationId, cplusRectificationTypeFk: args.cplusRectificationId,
cplusInvoiceType477Fk: args.cplusInvoiceType477Id, siiTypeInvoiceOutFk: args.siiTypeInvoiceOutId,
invoiceCorrectionTypeFk: args.invoiceCorrectionTypeId invoiceCorrectionTypeFk: args.invoiceCorrectionTypeId
}, myOptions); }, myOptions);

View File

@ -41,7 +41,7 @@
"InvoiceCorrection": { "InvoiceCorrection": {
"dataSource": "vn" "dataSource": "vn"
}, },
"CplusInvoiceType477": { "SiiTypeInvoiceOut": {
"dataSource": "vn" "dataSource": "vn"
} }
} }

View File

@ -18,7 +18,7 @@
"cplusRectificationTypeFk": { "cplusRectificationTypeFk": {
"type": "number" "type": "number"
}, },
"cplusInvoiceType477Fk": { "siiTypeInvoiceOutFk": {
"type": "number" "type": "number"
}, },
"invoiceCorrectionTypeFk": { "invoiceCorrectionTypeFk": {

View File

@ -1,9 +1,9 @@
{ {
"name": "CplusInvoiceType477", "name": "SiiTypeInvoiceOut",
"base": "VnModel", "base": "VnModel",
"options": { "options": {
"mysql": { "mysql": {
"table": "cplusInvoiceType477" "table": "siiTypeInvoiceOut"
} }
}, },
"properties": { "properties": {

View File

@ -6,8 +6,8 @@
</vn-crud-model> </vn-crud-model>
<vn-crud-model <vn-crud-model
auto-load="true" auto-load="true"
url="CplusInvoiceType477s" url="SiiTypeInvoiceOuts"
data="cplusInvoiceType477"> data="siiTypeInvoiceOut">
</vn-crud-model> </vn-crud-model>
<vn-crud-model <vn-crud-model
auto-load="true" auto-load="true"
@ -223,11 +223,11 @@
<vn-autocomplete <vn-autocomplete
vn-one vn-one
vn-id="cplusInvoiceType" vn-id="cplusInvoiceType"
data="cplusInvoiceType477" data="siiTypeInvoiceOut"
show-field="description" show-field="description"
value-field="id" value-field="id"
required="true" required="true"
ng-model="$ctrl.cplusInvoiceType477" ng-model="$ctrl.siiTypeInvoiceOut"
search-function="{or: [{id: $search}, {description: {like: '%'+ $search +'%'}}]}" search-function="{or: [{id: $search}, {description: {like: '%'+ $search +'%'}}]}"
label="Class"> label="Class">
</vn-autocomplete> </vn-autocomplete>

View File

@ -132,7 +132,7 @@ class Controller extends Section {
ref: this.invoiceOut.ref, ref: this.invoiceOut.ref,
newClientFk: this.invoiceOut.client.id, newClientFk: this.invoiceOut.client.id,
cplusRectificationId: this.cplusRectificationType, cplusRectificationId: this.cplusRectificationType,
cplusInvoiceType477Id: this.cplusInvoiceType477, siiTypeInvoiceOutId: this.siiTypeInvoiceOut,
invoiceCorrectionTypeId: this.invoiceCorrectionType invoiceCorrectionTypeId: this.invoiceCorrectionType
}; };
this.$http.post(`InvoiceOuts/transferInvoice`, params).then(res => { this.$http.post(`InvoiceOuts/transferInvoice`, params).then(res => {

View File

@ -20,8 +20,7 @@ module.exports = Self => {
}, },
{ {
arg: 'addressFk', arg: 'addressFk',
type: 'Number', type: 'Any',
required: true,
description: 'The address id' description: 'The address id'
}], }],
http: { http: {

View File

@ -1,6 +1,6 @@
{ {
"name": "ItemShelving", "name": "ItemShelving",
"base": "VnModel", "base": "Loggable",
"options": { "options": {
"mysql": { "mysql": {
"table": "itemShelving" "table": "itemShelving"

View File

@ -64,7 +64,10 @@ module.exports = Self => {
const sale = await models.Sale.findById(id, filter, myOptions); const sale = await models.Sale.findById(id, filter, myOptions);
const oldQuantity = sale.quantity; const oldQuantity = sale.quantity;
const result = await sale.updateAttributes({quantity: newQuantity}, myOptions); const result = await sale.updateAttributes({
quantity: newQuantity,
originalQuantity: newQuantity
}, myOptions);
const salesPerson = sale.ticket().client().salesPersonUser(); const salesPerson = sale.ticket().client().salesPersonUser();
if (salesPerson) { if (salesPerson) {

View File

@ -32,31 +32,30 @@ module.exports = Self => {
throw new UserError('You cannot close tickets for today'); throw new UserError('You cannot close tickets for today');
const tickets = await Self.rawSql(` const tickets = await Self.rawSql(`
SELECT SELECT t.id,
t.id, t.clientFk,
t.clientFk, t.companyFk,
t.companyFk, c.name clientName,
c.name clientName, c.email recipient,
c.email recipient, c.salesPersonFk,
c.salesPersonFk, c.isToBeMailed,
c.isToBeMailed, c.hasToInvoice,
c.hasToInvoice, co.hasDailyInvoice,
co.hasDailyInvoice, eu.email salesPersonEmail,
eu.email salesPersonEmail t.addressFk
FROM ticket t FROM ticket t
JOIN agencyMode am ON am.id = t.agencyModeFk JOIN agencyMode am ON am.id = t.agencyModeFk
JOIN warehouse wh ON wh.id = t.warehouseFk AND wh.hasComission JOIN warehouse wh ON wh.id = t.warehouseFk AND wh.hasComission
JOIN ticketState ts ON ts.ticketFk = t.id JOIN ticketState ts ON ts.ticketFk = t.id
JOIN alertLevel al ON al.id = ts.alertLevel JOIN alertLevel al ON al.id = ts.alertLevel
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
JOIN country co ON co.id = p.countryFk JOIN country co ON co.id = p.countryFk
LEFT JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk LEFT JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk
WHERE (al.code = 'PACKED' OR (am.code = 'refund' AND al.code != 'delivered')) WHERE (al.code = 'PACKED' OR (am.code = 'refund' AND al.code != 'delivered'))
AND DATE(t.shipped) BETWEEN DATE_ADD(?, INTERVAL -2 DAY) AND DATE(t.shipped) BETWEEN DATE_ADD(?, INTERVAL -2 DAY) AND util.dayEnd(?)
AND util.dayEnd(?) AND t.refFk IS NULL
AND t.refFk IS NULL GROUP BY t.id
GROUP BY t.id
`, [toDate, toDate]); `, [toDate, toDate]);
await closure(ctx, Self, tickets); await closure(ctx, Self, tickets);

View File

@ -14,12 +14,12 @@ module.exports = async function(ctx, Self, tickets, reqArgs = {}) {
await Self.rawSql(`CALL vn.ticket_closeByTicket(?)`, [ticket.id], {userId}); await Self.rawSql(`CALL vn.ticket_closeByTicket(?)`, [ticket.id], {userId});
const [invoiceOut] = await Self.rawSql(` const [invoiceOut] = await Self.rawSql(`
SELECT io.id, io.ref, io.serial, cny.code companyCode, io.issued SELECT io.id, io.ref, io.serial, cny.code companyCode, io.issued
FROM ticket t FROM ticket t
JOIN invoiceOut io ON io.ref = t.refFk JOIN invoiceOut io ON io.ref = t.refFk
JOIN company cny ON cny.id = io.companyFk JOIN company cny ON cny.id = io.companyFk
WHERE t.id = ? WHERE t.id = ?
`, [ticket.id]); `, [ticket.id]);
const mailOptions = { const mailOptions = {
overrideAttachments: true, overrideAttachments: true,
@ -91,13 +91,13 @@ module.exports = async function(ctx, Self, tickets, reqArgs = {}) {
// Incoterms authorization // Incoterms authorization
const [{firstOrder}] = await Self.rawSql(` const [{firstOrder}] = await Self.rawSql(`
SELECT COUNT(*) as firstOrder SELECT COUNT(*) as firstOrder
FROM ticket t FROM ticket t
JOIN client c ON c.id = t.clientFk JOIN client c ON c.id = t.clientFk
WHERE t.clientFk = ? WHERE t.clientFk = ?
AND NOT t.isDeleted AND NOT t.isDeleted
AND c.isVies AND c.isVies
`, [ticket.clientFk]); `, [ticket.clientFk]);
if (firstOrder == 1) { if (firstOrder == 1) {
const args = { const args = {
@ -105,7 +105,8 @@ module.exports = async function(ctx, Self, tickets, reqArgs = {}) {
companyId: ticket.companyFk, companyId: ticket.companyFk,
recipientId: ticket.clientFk, recipientId: ticket.clientFk,
recipient: ticket.recipient, recipient: ticket.recipient,
replyTo: ticket.salesPersonEmail replyTo: ticket.salesPersonEmail,
addressId: ticket.addressFk
}; };
const email = new Email('incoterms-authorization', args); const email = new Email('incoterms-authorization', args);
@ -113,13 +114,13 @@ module.exports = async function(ctx, Self, tickets, reqArgs = {}) {
const [sample] = await Self.rawSql( const [sample] = await Self.rawSql(
`SELECT id `SELECT id
FROM sample FROM sample
WHERE code = 'incoterms-authorization' WHERE code = 'incoterms-authorization'
`); `);
await Self.rawSql(` await Self.rawSql(`
INSERT INTO clientSample (clientFk, typeFk, companyFk) VALUES(?, ?, ?) INSERT INTO clientSample (clientFk, typeFk, companyFk) VALUES(?, ?, ?)
`, [ticket.clientFk, sample.id, ticket.companyFk], {userId}); `, [ticket.clientFk, sample.id, ticket.companyFk], {userId});
} }
} catch (error) { } catch (error) {
// Domain not found // Domain not found
@ -140,7 +141,7 @@ module.exports = async function(ctx, Self, tickets, reqArgs = {}) {
for (const ticket of failedtickets) { for (const ticket of failedtickets) {
body += `Ticket: <strong>${ticket.id}</strong> body += `Ticket: <strong>${ticket.id}</strong>
<br/> <strong>${ticket.stacktrace}</strong><br/><br/>`; <br/> <strong>${ticket.stacktrace}</strong><br/><br/>`;
} }
smtp.send({ smtp.send({
@ -158,19 +159,19 @@ module.exports = async function(ctx, Self, tickets, reqArgs = {}) {
const oldInstance = `{"email": "${ticket.recipient}"}`; const oldInstance = `{"email": "${ticket.recipient}"}`;
const newInstance = `{"email": ""}`; const newInstance = `{"email": ""}`;
await Self.rawSql(` await Self.rawSql(`
INSERT INTO clientLog (originFk, userFk, action, changedModel, oldInstance, newInstance) INSERT INTO clientLog (originFk, userFk, action, changedModel, oldInstance, newInstance)
VALUES (?, NULL, 'UPDATE', 'Client', ?, ?)`, [ VALUES (?, NULL, 'UPDATE', 'Client', ?, ?)`, [
ticket.clientFk, ticket.clientFk,
oldInstance, oldInstance,
newInstance newInstance
], {userId}); ], {userId});
const body = `No se ha podido enviar el albarán <strong>${ticket.id}</strong> const body = `No se ha podido enviar el albarán <strong>${ticket.id}</strong>
al cliente <strong>${ticket.clientFk} - ${ticket.clientName}</strong> al cliente <strong>${ticket.clientFk} - ${ticket.clientName}</strong>
porque la dirección de email <strong>"${ticket.recipient}"</strong> no es correcta porque la dirección de email <strong>"${ticket.recipient}"</strong> no es correcta
o no está disponible.<br/><br/> o no está disponible.<br/><br/>
Para evitar que se repita este error, se ha eliminado la dirección de email de la ficha del cliente. Para evitar que se repita este error, se ha eliminado la dirección de email de la ficha del cliente.
Actualiza la dirección de email con una correcta.`; Actualiza la dirección de email con una correcta.`;
smtp.send({ smtp.send({
to: ticket.salesPersonEmail, to: ticket.salesPersonEmail,

View File

@ -49,7 +49,6 @@ module.exports = function(Self) {
myOptions.transaction = tx; myOptions.transaction = tx;
} }
let serial;
try { try {
const ticketToInvoice = await Self.rawSql(` const ticketToInvoice = await Self.rawSql(`
SELECT id SELECT id
@ -60,7 +59,7 @@ module.exports = function(Self) {
where: { where: {
id: {inq: ticketsIds} id: {inq: ticketsIds}
}, },
fields: ['id', 'clientFk'] fields: ['id', 'clientFk', 'addressFk']
}, myOptions); }, myOptions);
await models.Ticket.canBeInvoiced(ctx, ticketsIds, myOptions); await models.Ticket.canBeInvoiced(ctx, ticketsIds, myOptions);
@ -72,13 +71,19 @@ module.exports = function(Self) {
throw new UserError(`This client can't be invoiced`); throw new UserError(`This client can't be invoiced`);
const query = `SELECT vn.invoiceSerial(?, ?, ?) AS serial`; const query = `SELECT vn.invoiceSerial(?, ?, ?) AS serial`;
const [result] = await Self.rawSql(query, [ const [{serial}] = await Self.rawSql(query, [
clientId, clientId,
companyFk, companyFk,
invoiceType, invoiceType,
], myOptions); ], myOptions);
serial = result.serial;
const invoiceOutSerial = await models.InvoiceOutSerial.findById(serial);
if (invoiceOutSerial?.taxAreaFk == 'WORLD') {
const address = await models.Address.findById(firstTicket.addressFk);
if (!address || !address.customsAgentFk || !address.incotermsFk)
throw new UserError('Incoterms data for consignee is missing');
}
await Self.rawSql('CALL invoiceOut_new(?, ?, null, @invoiceId)', [serial, invoiceDate], myOptions); await Self.rawSql('CALL invoiceOut_new(?, ?, null, @invoiceId)', [serial, invoiceDate], myOptions);
const [resultInvoice] = await Self.rawSql('SELECT @invoiceId id', [], myOptions); const [resultInvoice] = await Self.rawSql('SELECT @invoiceId id', [], myOptions);

View File

@ -52,4 +52,31 @@ describe('ticket makeInvoice()', () => {
throw e; throw e;
} }
}); });
it('should throw an error when invoicing a client without incoterms', async() => {
const tx = await models.Ticket.beginTransaction({});
let error;
try {
const options = {transaction: tx};
const ticketsId = [18];
await models.Ticket.rawSql(`
DROP TEMPORARY TABLE IF EXISTS tmp.ticketToInvoice;
CREATE TEMPORARY TABLE tmp.ticketToInvoice
(PRIMARY KEY (id))
ENGINE = MEMORY
SELECT id
FROM vn.ticket
WHERE id IN (?)
`, [ticketsId], options);
await models.Ticket.makeInvoice(ctx, invoiceType, companyFk, invoiceDate, options);
await tx.rollback();
} catch (e) {
error = e;
await tx.rollback();
}
expect(error.message).toEqual(`Incoterms data for consignee is missing`);
});
}); });

View File

@ -61,8 +61,6 @@
</div> </div>
<div ng-transclude="btnTwo"> <div ng-transclude="btnTwo">
<vn-quick-link <vn-quick-link
vn-acl="hr"
vn-acl-action="remove"
tooltip="Go to user" tooltip="Go to user"
state="['account.card.summary', {id: $ctrl.id}]" state="['account.card.summary', {id: $ctrl.id}]"
icon="face"> icon="face">

View File

@ -1,7 +1,7 @@
SELECT io.issued, SELECT io.issued,
c.socialName, c.socialName,
c.street postalAddress, c.street postalAddress,
IF (ios.taxAreaFk IS NOT NULL, CONCAT(cty.code, c.fi), c.fi) fi, c.fi,
io.clientFk, io.clientFk,
c.postcode, c.postcode,
c.city, c.city,
@ -50,7 +50,7 @@ SELECT io.issued,
) sub2 ON TRUE ) sub2 ON TRUE
JOIN vn.itemTaxCountry itc ON itc.countryFk = su.countryFk AND itc.itemFk = s.itemFk JOIN vn.itemTaxCountry itc ON itc.countryFk = su.countryFk AND itc.itemFk = s.itemFk
JOIN vn.taxClass tc ON tc.id = itc.taxClassFk JOIN vn.taxClass tc ON tc.id = itc.taxClassFk
LEFT JOIN vn.invoiceOutSerial ios ON ios.code = io.serial AND ios.taxAreaFk = 'CEE' JOIN vn.invoiceOutSerial ios ON ios.code = io.serial AND ios.taxAreaFk = 'WORLD'
JOIN vn.country cty ON cty.id = c.countryFk JOIN vn.country cty ON cty.id = c.countryFk
JOIN vn.payMethod pm ON pm.id = c .payMethodFk JOIN vn.payMethod pm ON pm.id = c .payMethodFk
JOIN vn.company co ON co.id=io.companyFk JOIN vn.company co ON co.id=io.companyFk