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

This commit is contained in:
Pablo Natek 2024-01-08 09:13:02 +01:00
commit 77d88df27d
138 changed files with 830 additions and 503 deletions

View File

@ -16,6 +16,7 @@
},
"cSpell.words": [
"salix",
"fdescribe"
"fdescribe",
"Loggable"
]
}

View File

@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2404.01] - 2024-01-25
### Added
### Changed
### Fixed
## [2402.01] - 2024-01-11
### Added

View File

@ -68,7 +68,7 @@ module.exports = Self => {
userToUpdate.hasGrant = hasGrant;
if (roleFk) {
const role = await models.Role.findById(roleFk, {fields: ['name']}, myOptions);
const role = await models.VnRole.findById(roleFk, {fields: ['name']}, myOptions);
const hasRole = await Self.hasRole(userId, role.name, myOptions);
if (!hasRole)

View File

@ -70,7 +70,7 @@ describe('VnUser privileges()', () => {
const tx = await models.VnUser.beginTransaction({});
const options = {transaction: tx};
const agency = await models.Role.findOne({
const agency = await models.VnRole.findOne({
where: {
name: 'agency'
}

View File

@ -139,9 +139,6 @@
"Warehouse": {
"dataSource": "vn"
},
"VnUser": {
"dataSource": "vn"
},
"OsTicket": {
"dataSource": "osticket"
},
@ -156,6 +153,12 @@
},
"ViaexpressConfig": {
"dataSource": "vn"
},
"VnUser": {
"dataSource": "vn"
},
"VnRole": {
"dataSource": "vn"
}
}

View File

@ -29,12 +29,12 @@
"relations": {
"readRole": {
"type": "belongsTo",
"model": "Role",
"model": "VnRole",
"foreignKey": "readRoleFk"
},
"writeRole": {
"type": "belongsTo",
"model": "Role",
"model": "VnRole",
"foreignKey": "writeRoleFk"
}
},

View File

@ -46,12 +46,12 @@
},
"readRole": {
"type": "belongsTo",
"model": "Role",
"model": "VnRole",
"foreignKey": "readRoleFk"
},
"writeRole": {
"type": "belongsTo",
"model": "Role",
"model": "VnRole",
"foreignKey": "writeRoleFk"
}
},
@ -64,4 +64,3 @@
}
]
}

View File

@ -24,8 +24,8 @@
},
"role": {
"type": "belongsTo",
"model": "Role",
"model": "VnRole",
"foreignKey": "roleFk"
}
}
}
}

13
back/models/vn-role.json Normal file
View File

@ -0,0 +1,13 @@
{
"name": "VnRole",
"base": "Role",
"validateUpsert": true,
"options": {
"mysql": {
"table": "account.role"
}
},
"mixins": {
"Loggable": true
}
}

View File

@ -7,6 +7,9 @@
"table": "account.user"
}
},
"mixins": {
"Loggable": true
},
"resetPasswordTokenTTL": "604800",
"properties": {
"id": {
@ -63,7 +66,7 @@
"relations": {
"role": {
"type": "belongsTo",
"model": "Role",
"model": "VnRole",
"foreignKey": "roleFk"
},
"roles": {

View File

@ -0,0 +1,6 @@
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId) VALUES
('VnRole','*','READ','ALLOW','ROLE','employee'),
('VnRole','*','WRITE','ALLOW','ROLE','it');
DELETE FROM`salix`.`ACL` WHERE model='Role';

View File

@ -0,0 +1,7 @@
ALTER TABLE `vn`.`invoiceCorrection` DROP FOREIGN KEY `cplusInvoiceTyoeFk`;
ALTER TABLE `vn`.`invoiceCorrection` DROP FOREIGN KEY `invoiceCorrectionType_Fk33`;
ALTER TABLE `vn`.`invoiceCorrection` DROP FOREIGN KEY `invoiceCorrection_ibfk_1`;
ALTER TABLE `vn`.`invoiceCorrection` ADD CONSTRAINT `siiTypeInvoiceOut_FK` FOREIGN KEY (`siiTypeInvoiceOutFk`) REFERENCES `vn`.`siiTypeInvoiceOut`(id) ON UPDATE CASCADE;
ALTER TABLE `vn`.`invoiceCorrection` ADD CONSTRAINT `invoiceCorrectionType_FK` FOREIGN KEY (`invoiceCorrectionTypeFk`) REFERENCES `vn`.`invoiceCorrectionType`(id) ON UPDATE CASCADE;
ALTER TABLE `vn`.`invoiceCorrection` ADD CONSTRAINT `cplusRectificationType_FK` FOREIGN KEY (`cplusRectificationTypeFk`) REFERENCES `vn`.`cplusRectificationType`(id) ON UPDATE CASCADE;

View File

@ -0,0 +1,33 @@
DELIMITER $$
$$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`getTaxBases`()
BEGIN
/**
* Calcula y devuelve en número de bases imponibles postivas y negativas
* Requiere la tabla temporal tmp.ticketToInvoice(id)
*
* returns tmp.taxBases
*/
CREATE OR REPLACE TEMPORARY TABLE tmp.ticket
(KEY (ticketFk))
ENGINE = MEMORY
SELECT id ticketFk
FROM tmp.ticketToInvoice;
CALL ticket_getTax(NULL);
DROP TEMPORARY TABLE IF EXISTS tmp.taxBases;
CREATE TEMPORARY TABLE tmp.taxBases
ENGINE = MEMORY
SELECT
SUM(taxableBase > 0) as positive,
SUM(taxableBase < 0) as negative
FROM(
SELECT SUM(taxableBase) taxableBase
FROM tmp.ticketTax
GROUP BY pgcFk
) t;
END$$
DELIMITER ;

View File

@ -0,0 +1,30 @@
DELIMITER $$
$$
CREATE OR REPLACE DEFINER=`root`@`localhost` FUNCTION `vn`.`hasAnyPositiveBase`() RETURNS tinyint(1)
DETERMINISTIC
BEGIN
/**
* Calcula si existe alguna base imponible positiva
* Requiere la tabla temporal tmp.ticketToInvoice(id) para getTaxBases()
*
* returns BOOLEAN
*/
DECLARE hasAnyPositiveBase BOOLEAN;
CALL getTaxBases();
SELECT positive INTO hasAnyPositiveBase
FROM tmp.taxBases
LIMIT 1;
DROP TEMPORARY TABLE
tmp.ticketTax,
tmp.ticket,
tmp.taxBases;
RETURN hasAnyPositiveBase;
END$$
DELIMITER ;

View File

@ -0,0 +1,32 @@
DELIMITER $$
$$
CREATE OR REPLACE DEFINER=`root`@`localhost` FUNCTION `vn`.`hasAnyNegativeBase`() RETURNS tinyint(1)
DETERMINISTIC
BEGIN
/**
* Calcula si existe alguna base imponible negativa
* Requiere la tabla temporal tmp.ticketToInvoice(id) para getTaxBases()
*
* returns BOOLEAN
*/
DECLARE hasAnyNegativeBase BOOLEAN;
CALL getTaxBases();
SELECT negative INTO hasAnyNegativeBase
FROM tmp.taxBases
LIMIT 1;
DROP TEMPORARY TABLE
tmp.ticketTax,
tmp.ticket,
tmp.taxBases;
RETURN hasAnyNegativeBase;
END$$
DELIMITER ;

View File

@ -0,0 +1,9 @@
ALTER TABLE `vn`.`clientSms` ADD `ticketFk` int(11) NULL;
ALTER TABLE `vn`.`clientSms` ADD CONSTRAINT `clientSms_FK_2` FOREIGN KEY (`ticketFk`) REFERENCES `vn`.`ticket`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
INSERT INTO`vn`.`clientSms` (`clientFk`, `smsFk`, `ticketFk`)
SELECT `t`.`clientFk`, `s`.`smsFk`, `s`.`ticketFk`
FROM `vn`.`clientSms` `s`
JOIN `vn`.`ticket` `t` ON `t`.`id` = `s`.`ticketFk`;
RENAME TABLE `vn`.`ticketSms` TO `vn`.`ticketSms__`;

View File

View File

@ -602,18 +602,19 @@ INSERT INTO `vn`.`taxArea` (`code`, `claveOperacionFactura`, `CodigoTransaccion`
INSERT INTO `vn`.`invoiceOutSerial` (`code`, `description`, `isTaxed`, `taxAreaFk`, `isCEE`, `type`)
VALUES
('A', 'Global nacional', 1, 'NATIONAL', 0, 'global'),
('T', 'Española rapida', 1, 'NATIONAL', 0, 'quick'),
('V', 'Intracomunitaria global', 0, 'CEE', 1, 'global'),
('M', 'Múltiple nacional', 1, 'NATIONAL', 0, 'quick'),
('E', 'Exportación rápida', 0, 'WORLD', 0, 'quick');
('A', 'Global nacional', 1, 'NATIONAL', 0, 'global'),
('T', 'Española rapida', 1, 'NATIONAL', 0, 'quick'),
('V', 'Intracomunitaria global', 0, 'CEE', 1, 'global'),
('M', 'Múltiple nacional', 1, 'NATIONAL', 0, 'quick'),
('R', 'Rectificativa', 1, 'NATIONAL', 0, NULL),
('E', 'Exportación rápida', 0, 'WORLD', 0, 'quick');
INSERT INTO `vn`.`invoiceOut`(`id`, `serial`, `amount`, `issued`,`clientFk`, `created`, `companyFk`, `dued`, `booked`, `bankFk`, `hasPdf`)
VALUES
(1, 'T', 1026.24, util.VN_CURDATE(), 1101, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0),
(2, 'T', 121.36, util.VN_CURDATE(), 1102, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0),
(3, 'T', 8.88, util.VN_CURDATE(), 1103, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0),
(4, 'T', 8.88, util.VN_CURDATE(), 1103, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0),
(4, 'T', 8.88, util.VN_CURDATE(), 1104, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0),
(5, 'A', 8.88, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1103, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 442, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 0);
UPDATE `vn`.`invoiceOut` SET ref = 'T1111111' WHERE id = 1;
@ -719,7 +720,7 @@ INSERT INTO `vn`.`route`(`id`, `time`, `workerFk`, `created`, `vehicleFk`, `agen
INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeFk`, `shipped`, `landed`, `clientFk`,`nickname`, `addressFk`, `refFk`, `isDeleted`, `zoneFk`, `zonePrice`, `zoneBonus`, `created`, `weight`)
VALUES
(1 , 3, 1, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 1101, 'Bat cave', 121, NULL, 0, 1, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1),
(2 , 1, 1, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 1104, 'Stark tower', 124, NULL, 0, 1, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2),
(2 , 1, 1, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 1101, 'Bat cave', 1, NULL, 0, 1, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2),
(3 , 1, 7, 1, 6, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -2 MONTH), INTERVAL +1 DAY), 1104, 'Stark tower', 124, NULL, 0, 3, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH), NULL),
(4 , 3, 2, 1, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -3 MONTH), INTERVAL +1 DAY), 1104, 'Stark tower', 124, NULL, 0, 9, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH), NULL),
(5 , 3, 3, 3, 3, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -4 MONTH), INTERVAL +1 DAY), 1104, 'Stark tower', 124, NULL, 0, 10, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH), NULL),
@ -3020,3 +3021,17 @@ INSERT INTO `vn`.`docuwareTablet` (`tablet`,`description`)
VALUES
('Tablet1','Jarvis tablet'),
('Tablet2','Avengers tablet');
INSERT INTO `vn`.`sms` (`id`, `senderFk`, `sender`, `destination`, `message`, `statusCode`, `status`, `created`)
VALUES (1, 66, '111111111', '0001111111111', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', 0, 'OK', util.VN_CURDATE()),
(2, 66, '222222222', '0002222222222', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', 0, 'PENDING', util.VN_CURDATE()),
(3, 66, '333333333', '0003333333333', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', 0, 'ERROR', util.VN_CURDATE()),
(4, 66, '444444444', '0004444444444', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', 0, 'OK', util.VN_CURDATE());
INSERT INTO `vn`.`clientSms` (`id`, `clientFk`, `smsFk`, `ticketFk`)
VALUES(1, 1103, 1, NULL),
(2, 1103, 2, NULL),
(3, 1103, 3, 32),
(4, 1103, 4, 32),
(13, 1101, 1, NULL),
(14, 1101, 4, 27);

View File

@ -35,7 +35,7 @@ describe('Ticket index payout path', () => {
await page.waitToClick(selectors.ticketsIndex.openAdvancedSearchButton);
await page.write(selectors.ticketsIndex.advancedSearchClient, '1101');
await page.keyboard.press('Enter');
await page.waitForNumberOfElements(selectors.ticketsIndex.anySearchResult, 9);
await page.waitForNumberOfElements(selectors.ticketsIndex.anySearchResult, 10);
await page.waitToClick(selectors.ticketsIndex.firstTicketCheckbox);
await page.waitToClick(selectors.ticketsIndex.secondTicketCheckbox);

View File

@ -28,7 +28,6 @@ describe('InvoiceOut summary path', () => {
it('should contain the tax breakdown', async() => {
const firstTax = await page.waitToGetProperty(selectors.invoiceOutSummary.taxOne, 'innerText');
const secondTax = await page.waitToGetProperty(selectors.invoiceOutSummary.taxTwo, 'innerText');
expect(firstTax).toContain('10%');
@ -37,10 +36,9 @@ describe('InvoiceOut summary path', () => {
it('should contain the tickets info', async() => {
const firstTicket = await page.waitToGetProperty(selectors.invoiceOutSummary.ticketOne, 'innerText');
const secondTicket = await page.waitToGetProperty(selectors.invoiceOutSummary.ticketTwo, 'innerText');
expect(firstTicket).toContain('Bat cave');
expect(secondTicket).toContain('Stark tower');
expect(secondTicket).toContain('Bat cave');
});
});

View File

@ -23,7 +23,6 @@ export function directive($translate, $window) {
let rule = $attrs.rule.split('.');
let modelName = rule.shift();
let fieldName = rule.shift();
let split = $attrs.ngModel.split('.');
if (!fieldName) fieldName = split.pop() || null;
if (!modelName) modelName = firstUpper(split.pop() || '');

View File

@ -0,0 +1,12 @@
const LoopBackContext = require('loopback-context');
async function handleObserve(ctx) {
ctx.options.httpCtx = LoopBackContext.getCurrentContext();
}
module.exports = function(Self) {
let Mixin = {
'before save': handleObserve,
'before delete': handleObserve,
};
for (const [listener, handler] of Object.entries(Mixin))
Self.observe(listener, handler);
};

View File

@ -1,15 +0,0 @@
const LoopBackContext = require('loopback-context');
module.exports = function(Self) {
Self.setup = function() {
Self.super_.setup.call(this);
};
Self.observe('before save', async function(ctx) {
ctx.options.httpCtx = LoopBackContext.getCurrentContext();
});
Self.observe('before delete', async function(ctx) {
ctx.options.httpCtx = LoopBackContext.getCurrentContext();
});
};

View File

@ -1,5 +0,0 @@
{
"name": "Loggable",
"base": "VnModel",
"validateUpsert": true
}

View File

@ -45,6 +45,7 @@
"Extension format is invalid": "Extension format is invalid",
"NO_ZONE_FOR_THIS_PARAMETERS": "NO_ZONE_FOR_THIS_PARAMETERS",
"This client can't be invoiced": "This client can't be invoiced",
"You must provide the correction information to generate a corrective invoice": "You must provide the correction information to generate a corrective invoice",
"The introduced hour already exists": "The introduced hour already exists",
"Invalid parameters to create a new ticket": "Invalid parameters to create a new ticket",
"Concept cannot be blank": "Concept cannot be blank",
@ -178,7 +179,8 @@
"The renew period has not been exceeded": "The renew period has not been exceeded",
"You can not use the same password": "You can not use the same password",
"Valid priorities": "Valid priorities: %d",
"Negative basis of tickets": "Negative basis of tickets: {{ticketsIds}}",
"hasAnyNegativeBase": "Negative basis of tickets: {{ticketsIds}}",
"hasAnyPositiveBase": "Positive basis of tickets: {{ticketsIds}}",
"This ticket cannot be left empty.": "This ticket cannot be left empty. %s",
"Social name should be uppercase": "Social name should be uppercase",
"Street should be uppercase": "Street should be uppercase",

View File

@ -72,6 +72,7 @@
"The secret can't be blank": "La contraseña no puede estar en blanco",
"We weren't able to send this SMS": "No hemos podido enviar el SMS",
"This client can't be invoiced": "Este cliente no puede ser facturado",
"You must provide the correction information to generate a corrective invoice": "Debes informar la información de corrección para generar una factura rectificativa",
"This ticket can't be invoiced": "Este ticket no puede ser facturado",
"You cannot add or modify services to an invoiced ticket": "No puedes añadir o modificar servicios a un ticket facturado",
"This ticket can not be modified": "Este ticket no puede ser modificado",
@ -305,7 +306,8 @@
"Mail not sent": "Se ha producido un fallo al enviar la factura al cliente [{{clientId}}]({{{clientUrl}}}), por favor revisa la dirección de correo electrónico",
"The renew period has not been exceeded": "El periodo de renovación no ha sido superado",
"Valid priorities": "Prioridades válidas: %d",
"Negative basis of tickets": "Base negativa para los tickets: {{ticketsIds}}",
"hasAnyNegativeBase": "Base negativa para los tickets: {{ticketsIds}}",
"hasAnyPositiveBase": "Base positivas para los tickets: {{ticketsIds}}",
"You cannot assign an alias that you are not assigned to": "No puede asignar un alias que no tenga asignado",
"This ticket cannot be left empty.": "Este ticket no se puede dejar vacío. %s",
"The company has not informed the supplier account for bank transfers": "La empresa no tiene informado la cuenta de proveedor para transferencias bancarias",
@ -333,5 +335,6 @@
"This user does not have an assigned tablet": "Este usuario no tiene tablet asignada",
"Incorrect pin": "Pin incorrecto.",
"You already have the mailAlias": "Ya tienes este alias de correo",
"The alias cant be modified": "Este alias de correo no puede ser modificado"
}
"The alias cant be modified": "Este alias de correo no puede ser modificado",
"No tickets to invoice": "No hay tickets para facturar"
}

View File

@ -25,20 +25,19 @@
"FieldAcl": {
"dataSource": "vn"
},
"Role": {
"dataSource": "vn",
"options": {
"mysql": {
"table": "salix.Role"
}
}
},
"RoleMapping": {
"dataSource": "vn",
"options": {
"mysql": {
"table": "salix.RoleMapping"
}
},
"relations": {
"role": {
"type": "belongsTo",
"model": "VnRole",
"foreignKey": "roleId"
}
}
},
"Schema": {

View File

@ -1,49 +1,49 @@
{
"name": "Account",
"base": "VnModel",
"options": {
"mysql": {
"table": "account.account"
}
},
"properties": {
"id": {
"id": true
}
},
"relations": {
"user": {
"type": "belongsTo",
"model": "VnUser",
"foreignKey": "id"
},
"aliases": {
"type": "hasMany",
"model": "MailAliasAccount",
"foreignKey": "account"
}
},
"acls": [
{
"property": "login",
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
"name": "Account",
"base": "VnModel",
"options": {
"mysql": {
"table": "account.account"
}
},
"properties": {
"id": {
"id": true
}
},
"relations": {
"user": {
"type": "belongsTo",
"model": "VnUser",
"foreignKey": "id"
},
{
"aliases": {
"type": "hasMany",
"model": "MailAliasAccount",
"foreignKey": "account"
}
},
"acls": [
{
"property": "login",
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
},
{
"property": "logout",
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$authenticated",
"permission": "ALLOW"
},
{
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$authenticated",
"permission": "ALLOW"
},
{
"property": "changePassword",
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}
]
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}
]
}

View File

@ -239,7 +239,7 @@ module.exports = Self => {
// Prepare data
let roles = await $.Role.find({
let roles = await $.VnRole.find({
fields: ['id', 'name', 'description']
});
let roleRoles = await $.RoleRole.find({

View File

@ -15,12 +15,12 @@
"relations": {
"owner": {
"type": "belongsTo",
"model": "Role",
"model": "VnRole",
"foreignKey": "role"
},
"inherits": {
"type": "belongsTo",
"model": "Role",
"model": "VnRole",
"foreignKey": "inheritsFrom"
}
}

View File

@ -14,12 +14,12 @@
"relations": {
"owner": {
"type": "belongsTo",
"model": "Role",
"model": "VnRole",
"foreignKey": "role"
},
"inherits": {
"type": "belongsTo",
"model": "Role",
"model": "VnRole",
"foreignKey": "inheritsFrom"
}
}

View File

@ -15,7 +15,7 @@
<vn-autocomplete
label="Role"
ng-model="$ctrl.acl.principalId"
url="Roles"
url="VnRoles"
id-field="name"
value-field="name"
vn-focus>
@ -32,7 +32,7 @@
</vn-horizontal>
<vn-horizontal>
<vn-textfield
label="Property"
label="Property"
ng-model="$ctrl.acl.property"
info="Use * to match all properties">
</vn-textfield>

View File

@ -4,7 +4,7 @@
<vn-autocomplete
label="Role"
ng-model="filter.principalId"
url="Roles"
url="VnRoles"
value-field="name">
</vn-autocomplete>
<vn-autocomplete
@ -15,7 +15,7 @@
value-field="name">
</vn-autocomplete>
<vn-textfield
label="Property"
label="Property"
ng-model="filter.property">
</vn-textfield>
<vn-autocomplete
@ -36,4 +36,4 @@
</vn-submit>
</vn-vertical>
</form>
</div>
</div>

View File

@ -30,7 +30,7 @@
<vn-autocomplete
label="Role"
ng-model="$ctrl.user.roleFk"
url="Roles"
url="VnRoles"
rule="VnUser">
</vn-autocomplete>
<vn-textfield

View File

@ -22,7 +22,7 @@
<vn-autocomplete
label="Role"
ng-model="$ctrl.user.roleFk"
url="Roles">
url="VnRoles">
</vn-autocomplete>
</vn-vertical>
</vn-card>

View File

@ -1,25 +1,27 @@
<vn-watcher
vn-id="watcher"
url="Roles"
url="VnRoles"
data="$ctrl.role"
form="form">
</vn-watcher>
<form
name="form"
ng-submit="watcher.submit()"
class="vn-w-md">
<vn-card class="vn-pa-lg">
<vn-vertical>
<vn-textfield
label="Name"
label="Name"
ng-model="$ctrl.role.name"
rule
rule="VnRole.name"
vn-focus>
</vn-textfield>
<vn-textfield
label="Description"
ng-model="$ctrl.role.description"
rule>
label="Description"
ng-model="$ctrl.role.description"
rule="VnRole.description"
>
</vn-textfield>
</vn-vertical>
</vn-card>
@ -35,4 +37,4 @@
ng-click="watcher.loadOriginalData()">
</vn-button>
</vn-button-bar>
</form>
</form>

View File

@ -3,7 +3,7 @@ import ModuleCard from 'salix/components/module-card';
class Controller extends ModuleCard {
reload() {
this.$http.get(`Roles/${this.$params.id}`)
this.$http.get(`VnRoles/${this.$params.id}`)
.then(res => this.role = res.data);
}
}

View File

@ -1,6 +1,6 @@
import './index';
describe('component vnRoleCard', () => {
fdescribe('component vnRoleCard', () => {
let controller;
let $httpBackend;
@ -15,7 +15,7 @@ describe('component vnRoleCard', () => {
it('should reload the controller data', () => {
controller.$params.id = 1;
$httpBackend.expectGET('Roles/1').respond('foo');
$httpBackend.expectGET('VnRoles/1').respond('foo');
controller.reload();
$httpBackend.flush();

View File

@ -1,6 +1,6 @@
<vn-watcher
vn-id="watcher"
url="Roles"
url="VnRoles"
data="$ctrl.role"
insert-mode="true"
form="form">
@ -12,15 +12,15 @@
<vn-card class="vn-pa-lg">
<vn-vertical>
<vn-textfield
label="Name"
label="Name"
ng-model="$ctrl.role.name"
rule
rule="VnRole.name"
vn-focus>
</vn-textfield>
<vn-textfield
label="Description"
label="Description"
ng-model="$ctrl.role.description"
rule>
rule="VnRole.description">
</vn-textfield>
</vn-vertical>
</vn-card>

View File

@ -24,4 +24,4 @@
on-accept="$ctrl.onDelete()"
question="Are you sure you want to continue?"
message="Role will be removed">
</vn-confirm>
</vn-confirm>

View File

@ -11,7 +11,7 @@ class Controller extends Descriptor {
}
onDelete() {
return this.$http.delete(`Roles/${this.id}`)
return this.$http.delete(`VnRoles/${this.id}`)
.then(() => this.$state.go('account.role'))
.then(() => this.vnApp.showSuccess(this.$t('Role removed')));
}

View File

@ -1,6 +1,6 @@
import './index';
describe('component vnRoleDescriptor', () => {
fdescribe('component vnRoleDescriptor', () => {
let controller;
let $httpBackend;
@ -18,7 +18,7 @@ describe('component vnRoleDescriptor', () => {
controller.$state.go = jest.fn();
jest.spyOn(controller.vnApp, 'showSuccess');
$httpBackend.expectDELETE('Roles/1').respond();
$httpBackend.expectDELETE('VnRoles/1').respond();
controller.onDelete();
$httpBackend.flush();

View File

@ -1,6 +1,6 @@
<vn-crud-model
vn-id="model"
url="Roles"
url="VnRoles"
filter="::$ctrl.filter"
limit="20">
</vn-crud-model>
@ -15,4 +15,4 @@
</vn-portal>
<ui-view>
<vn-role-index></vn-role-index>
</ui-view>
</ui-view>

View File

@ -33,14 +33,14 @@
ng-click="$ctrl.onAddClick()"
fixed-bottom-right>
</vn-float-button>
<vn-dialog
<vn-dialog
vn-id="dialog"
on-accept="$ctrl.onAddSave()">
<tpl-body>
<vn-autocomplete
label="Role"
ng-model="$ctrl.addData.inheritsFrom"
url="Roles"
url="VnRoles"
vn-focus>
</vn-autocomplete>
</tpl-body>
@ -49,7 +49,7 @@
<button response="accept" translate>Save</button>
</tpl-buttons>
</vn-dialog>
<vn-confirm
<vn-confirm
vn-id="remove-confirm"
message="Role will be removed"
question="Are you sure you want to continue?"

View File

@ -6,7 +6,7 @@ class Controller extends Component {
this._role = value;
this.$.summary = null;
if (!value) return;
this.$http.get(`Roles/${value.id}`)
this.$http.get(`VnRoles/${value.id}`)
.then(res => this.$.summary = res.data);
}

View File

@ -19,7 +19,7 @@
vn-one
label="Role"
ng-model="filter.roleFk"
url="Roles"
url="VnRoles"
value-field="id"
show-field="name">
</vn-autocomplete>
@ -28,4 +28,4 @@
<vn-submit label="Search"></vn-submit>
</vn-horizontal>
</form>
</div>
</div>

View File

@ -1,6 +1,9 @@
{
"name": "ClaimBeginning",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "claimBeginning"

View File

@ -1,6 +1,9 @@
{
"name": "ClaimDevelopment",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "claimDevelopment"

View File

@ -1,6 +1,9 @@
{
"name": "ClaimDms",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "claimDms"

View File

@ -1,6 +1,9 @@
{
"name": "ClaimEnd",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "claimEnd"

View File

@ -1,6 +1,9 @@
{
"name": "ClaimObservation",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "claimObservation"

View File

@ -1,6 +1,9 @@
{
"name": "ClaimState",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "claimState"
@ -32,7 +35,7 @@
"relations": {
"writeRole": {
"type": "belongsTo",
"model": "Role",
"model": "VnRole",
"foreignKey": "roleFk"
}
},

View File

@ -1,6 +1,9 @@
{
"name": "Claim",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "claim"

View File

@ -1,7 +1,7 @@
const UserError = require('vn-loopback/util/user-error');
module.exports = function(Self) {
Self.remoteMethodCtx('canBeInvoiced', {
Self.remoteMethod('canBeInvoiced', {
description: 'Change property isEqualizated in all client addresses',
accessType: 'READ',
accepts: [

View File

@ -16,7 +16,7 @@ describe('client consumption() filter', () => {
};
const result = await models.Client.consumption(ctx, filter, options);
expect(result.length).toEqual(10);
expect(result.length).toEqual(11);
await tx.rollback();
} catch (e) {
@ -49,7 +49,7 @@ describe('client consumption() filter', () => {
const thirdRow = result[2];
expect(result.length).toEqual(3);
expect(firstRow.quantity).toEqual(10);
expect(firstRow.quantity).toEqual(11);
expect(secondRow.quantity).toEqual(15);
expect(thirdRow.quantity).toEqual(20);

View File

@ -113,9 +113,6 @@
"SageTransactionType": {
"dataSource": "vn"
},
"TicketSms": {
"dataSource": "vn"
},
"TpvError": {
"dataSource": "vn"
},

View File

@ -1,7 +1,10 @@
{
"name": "Address",
"description": "Client addresses",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "address"

View File

@ -1,7 +1,10 @@
{
"name": "ClientContact",
"description": "Client phone contacts",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "clientContact"

View File

@ -1,6 +1,9 @@
{
"name": "ClientDms",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "clientDms"

View File

@ -1,6 +1,9 @@
{
"name": "ClientInforma",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"log": {
"model":"ClientLog",
"relation": "client",

View File

@ -1,7 +1,10 @@
{
"name": "ClientObservation",
"description": "Client notes",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "clientObservation"

View File

@ -1,6 +1,9 @@
{
"name": "ClientSample",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "clientSample"

View File

@ -21,6 +21,11 @@
"type": "belongsTo",
"model": "Sms",
"foreignKey": "smsFk"
},
"ticket": {
"type": "belongsTo",
"model": "Ticket",
"foreignKey": "ticketFk"
}
}
}

View File

@ -1,6 +1,9 @@
{
"name": "Client",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "client"

View File

@ -1,6 +1,9 @@
{
"name": "Greuge",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "greuge"

View File

@ -1,6 +1,9 @@
{
"name": "Recovery",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "recovery"

View File

@ -19,8 +19,8 @@
"relations": {
"role": {
"type": "belongsTo",
"model": "Role",
"model": "VnRole",
"foreignKey": "roleFk"
}
}
}
}

View File

@ -1,28 +0,0 @@
{
"name": "TicketSms",
"base": "VnModel",
"options": {
"mysql": {
"table": "ticketSms"
}
},
"properties": {
"smsFk": {
"type": "number",
"id": true,
"description": "Identifier"
}
},
"relations": {
"ticket": {
"type": "belongsTo",
"model": "Ticket",
"foreignKey": "ticketFk"
},
"sms": {
"type": "belongsTo",
"model": "Sms",
"foreignKey": "smsFk"
}
}
}

View File

@ -1,40 +1,2 @@
<vn-crud-model
vn-id="model"
url="ClientSms"
link="{clientFk: $ctrl.$params.id}"
filter="::$ctrl.filter"
data="clientSmsList"
limit="20"
auto-load="true">
</vn-crud-model>
<vn-data-viewer model="model">
<vn-card class="vn-w-lg">
<vn-table model="model" auto-load="false">
<vn-thead>
<vn-tr>
<vn-th field="senderFk">Sender</vn-th>
<vn-th field="destination" number>Destination</vn-th>
<vn-th field="message">Message</vn-th>
<vn-th field="status">Status</vn-th>
<vn-th field="created" expand>Created</vn-th>
</vn-tr>
</vn-thead>
<vn-tbody>
<vn-tr ng-repeat="clientSms in clientSmsList">
<vn-td>
<span class="link" ng-click="workerDescriptor.show($event, clientSms.sms.senderFk)">
{{::clientSms.sms.sender.name}}
</span>
</vn-td>
<vn-td number expand>{{::clientSms.sms.destination}}</vn-td>
<vn-td expand vn-tooltip="{{::clientSms.sms.message}}">{{::clientSms.sms.message}}</vn-td>
<vn-td>{{::clientSms.sms.status}}</vn-td>
<vn-td shrink-datetime>{{::clientSms.sms.created | date:'dd/MM/yyyy HH:mm'}}</vn-td>
</vn-tr>
</vn-tbody>
</vn-table>
</vn-card>
</vn-data-viewer>
<vn-worker-descriptor-popover
vn-id="worker-descriptor">
</vn-worker-descriptor-popover>
<vn-card>
</vn-card>

View File

@ -1,32 +1,14 @@
import ngModule from '../module';
import Section from 'salix/components/section';
export default class Controller extends Section {
class Controller extends Section {
constructor($element, $) {
super($element, $);
}
this.filter = {
fields: ['id', 'smsFk'],
include: {
relation: 'sms',
scope: {
fields: [
'senderFk',
'sender',
'destination',
'message',
'statusCode',
'status',
'created'],
include: {
relation: 'sender',
scope: {
fields: ['name']
}
}
}
}
};
async $onInit() {
this.$state.go('client.card.summary', {id: this.$params.id});
window.location.href = await this.vnApp.getUrl(`Customer/${this.$params.id}/sms`);
}
}

View File

@ -1,6 +1,9 @@
{
"name": "Buy",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "buy"

View File

@ -1,6 +1,9 @@
{
"name": "EntryObservation",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "entryObservation"

View File

@ -1,6 +1,9 @@
{
"name": "Entry",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "entry"

View File

@ -1,6 +1,9 @@
{
"name": "InvoiceInTax",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "invoiceInTax"

View File

@ -1,6 +1,9 @@
{
"name": "InvoiceIn",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "invoiceIn"

View File

@ -85,7 +85,7 @@ module.exports = Self => {
throw new UserError(`A ticket with an amount of zero can't be invoiced`);
// Validates ticket nagative base
const hasNegativeBase = await getNegativeBase(ticketId, myOptions);
const hasNegativeBase = await getNegativeBase(maxShipped, clientId, companyId, myOptions);
if (hasNegativeBase && company.code == 'VNL')
throw new UserError(`A ticket with a negative base can't be invoiced`);
} else {
@ -162,10 +162,13 @@ module.exports = Self => {
return result.invoiceable;
}
async function getNegativeBase(ticketId, options) {
async function getNegativeBase(maxShipped, clientId, companyId, options) {
const models = Self.app.models;
const query = 'SELECT vn.hasSomeNegativeBase(?) AS base';
const [result] = await models.InvoiceOut.rawSql(query, [ticketId], options);
await models.InvoiceOut.rawSql('CALL invoiceOut_exportationFromClient(?,?,?)',
[maxShipped, clientId, companyId], options
);
const query = 'SELECT vn.hasAnyNegativeBase() AS base';
const [result] = await models.InvoiceOut.rawSql(query, [], options);
return result.base;
}

View File

@ -80,6 +80,7 @@ module.exports = Self => {
invoiceType,
args.companyFk,
args.invoiceDate,
null,
options
);

View File

@ -2,7 +2,7 @@
const models = require('vn-loopback/server/server').models;
const LoopBackContext = require('loopback-context');
describe('InvoiceOut tranferInvoice()', () => {
describe('InvoiceOut transferInvoice()', () => {
const activeCtx = {
accessToken: {userId: 5},
http: {
@ -23,20 +23,29 @@ describe('InvoiceOut tranferInvoice()', () => {
const tx = await models.InvoiceOut.beginTransaction({});
const options = {transaction: tx};
const args = {
id: '1',
ref: 'T4444444',
id: '4',
refFk: 'T4444444',
newClientFk: 1,
cplusRectificationId: 1,
siiTypeInvoiceOutId: 1,
invoiceCorrectionTypeId: 1
cplusRectificationTypeFk: 1,
siiTypeInvoiceOutFk: 1,
invoiceCorrectionTypeFk: 1
};
ctx.args = args;
try {
const {clientFk: oldClient} = await models.InvoiceOut.findById(args.id, {fields: ['clientFk']});
const invoicesBefore = await models.InvoiceOut.find({}, options);
const result = await models.InvoiceOut.transferInvoice(
ctx,
options);
const invoicesAfter = await models.InvoiceOut.find({}, options);
const rectificativeInvoice = invoicesAfter[invoicesAfter.length - 2];
const newInvoice = invoicesAfter[invoicesAfter.length - 1];
expect(result).toBeDefined();
expect(invoicesAfter.length - invoicesBefore.length).toEqual(2);
expect(rectificativeInvoice.clientFk).toEqual(oldClient);
expect(newInvoice.clientFk).toEqual(args.newClientFk);
await tx.rollback();
} catch (e) {
await tx.rollback();
@ -49,20 +58,44 @@ describe('InvoiceOut tranferInvoice()', () => {
const options = {transaction: tx};
const args = {
id: '1',
ref: 'T1111111',
refFk: 'T1111111',
newClientFk: 1101,
cplusRectificationId: 1,
siiTypeInvoiceOutId: 1,
invoiceCorrectionTypeId: 1
cplusRectificationTypeFk: 1,
siiTypeInvoiceOutFk: 1,
invoiceCorrectionTypeFk: 1
};
ctx.args = args;
try {
await models.InvoiceOut.transferInvoice(
ctx,
options);
await tx.rollback();
} catch (e) {
expect(e.message).toBe(`Select a different client`);
await tx.rollback();
}
});
it('should throw an UserError when it is refund', async() => {
const tx = await models.InvoiceOut.beginTransaction({});
const options = {transaction: tx};
const args = {
id: '1',
refFk: 'T1111111',
newClientFk: 1102,
cplusRectificationTypeFk: 1,
siiTypeInvoiceOutFk: 1,
invoiceCorrectionTypeFk: 1
};
ctx.args = args;
try {
await models.InvoiceOut.transferInvoice(
ctx,
options);
await tx.rollback();
} catch (e) {
expect(e.message).toContain(`This ticket is already a refund`);
await tx.rollback();
}
});
});

View File

@ -12,7 +12,7 @@ module.exports = Self => {
description: 'Issued invoice id'
},
{
arg: 'ref',
arg: 'refFk',
type: 'string',
required: true
},
@ -22,17 +22,17 @@ module.exports = Self => {
required: true
},
{
arg: 'cplusRectificationId',
arg: 'cplusRectificationTypeFk',
type: 'number',
required: true
},
{
arg: 'siiTypeInvoiceOutId',
arg: 'siiTypeInvoiceOutFk',
type: 'number',
required: true
},
{
arg: 'invoiceCorrectionTypeId',
arg: 'invoiceCorrectionTypeFk',
type: 'number',
required: true
},
@ -50,14 +50,14 @@ module.exports = Self => {
Self.transferInvoice = async(ctx, options) => {
const models = Self.app.models;
const myOptions = {userId: ctx.req.accessToken.userId};
const args = ctx.args;
const {id, refFk, newClientFk, cplusRectificationTypeFk, siiTypeInvoiceOutFk, invoiceCorrectionTypeFk} = ctx.args;
let tx;
if (typeof options == 'object')
Object.assign(myOptions, options);
const {clientFk} = await models.InvoiceOut.findById(args.id);
const {clientFk} = await models.InvoiceOut.findById(id);
if (clientFk == args.newClientFk)
if (clientFk == newClientFk)
throw new UserError(`Select a different client`);
if (!myOptions.transaction) {
@ -65,10 +65,10 @@ module.exports = Self => {
myOptions.transaction = tx;
}
try {
const filterRef = {where: {refFk: args.ref}};
const filterRef = {where: {refFk: refFk}};
const tickets = await models.Ticket.find(filterRef, myOptions);
const ticketsIds = tickets.map(ticket => ticket.id);
await models.Ticket.refund(ctx, ticketsIds, null, myOptions);
const refundTickets = await models.Ticket.refund(ctx, ticketsIds, null, myOptions);
const filterTicket = {where: {ticketFk: {inq: ticketsIds}}};
@ -82,20 +82,16 @@ module.exports = Self => {
const clonedTicketIds = [];
for (const clonedTicket of clonedTickets) {
await clonedTicket.updateAttribute('clientFk', args.newClientFk, myOptions);
await clonedTicket.updateAttribute('clientFk', newClientFk, myOptions);
clonedTicketIds.push(clonedTicket.id);
}
const invoiceIds = await models.Ticket.invoiceTickets(ctx, clonedTicketIds, myOptions);
const [invoiceId] = invoiceIds;
const invoiceCorrection =
{correctedFk: id, cplusRectificationTypeFk, siiTypeInvoiceOutFk, invoiceCorrectionTypeFk};
const refundTicketIds = refundTickets.map(ticket => ticket.id);
await models.InvoiceCorrection.create({
correctingFk: invoiceId,
correctedFk: args.id,
cplusRectificationTypeFk: args.cplusRectificationId,
siiTypeInvoiceOutFk: args.siiTypeInvoiceOutId,
invoiceCorrectionTypeFk: args.invoiceCorrectionTypeId
}, myOptions);
await models.Ticket.invoiceTickets(ctx, refundTicketIds, invoiceCorrection, myOptions);
const [invoiceId] = await models.Ticket.invoiceTickets(ctx, clonedTicketIds, null, myOptions);
if (tx) {
await tx.commit();

View File

@ -16,13 +16,43 @@
"type": "number"
},
"cplusRectificationTypeFk": {
"type": "number"
"type": "number",
"required": true
},
"siiTypeInvoiceOutFk": {
"type": "number"
"type": "number",
"required": true
},
"invoiceCorrectionTypeFk": {
"type": "number"
"type": "number",
"required": true
},
"relations": {
"correcting": {
"type": "belongsTo",
"model": "InvoiceOut",
"foreignKey": "correctingFk"
},
"corrected": {
"type": "belongsTo",
"model": "InvoiceOut",
"foreignKey": "correctedFk"
},
"cplusRectificationType": {
"type": "belongsTo",
"model": "cplusRectificationType",
"foreignKey": "cplusRectificationTypeFk"
},
"siiTypeInvoiceOut": {
"type": "belongsTo",
"model": "siiTypeInvoiceOut",
"foreignKey": "siiTypeInvoiceOutFk"
},
"invoiceCorrectionType": {
"type": "belongsTo",
"model": "invoiceCorrectionType",
"foreignKey": "invoiceCorrectionTypeFk"
}
}
}
}

View File

@ -12,6 +12,9 @@
"type": "number",
"description": "Identifier"
},
"code": {
"type": "string"
},
"description": {
"type": "string"
}

View File

@ -7,7 +7,8 @@
<vn-crud-model
auto-load="true"
url="SiiTypeInvoiceOuts"
data="siiTypeInvoiceOut">
data="siiTypeInvoiceOuts"
where="{code: {like: 'R%'}}">
</vn-crud-model>
<vn-crud-model
auto-load="true"
@ -185,64 +186,69 @@
vn-id="transferInvoice"
title="transferInvoice"
on-accept="$ctrl.transferInvoice()">
<tpl-title translate>
transferInvoice
</tpl-title>
<tpl-body>
<section class="transferInvoice">
<vn-horizontal>
<vn-autocomplete
vn-one
vn-id="client"
required="true"
url="Clients"
label="Client"
show-field="name"
value-field="id"
search-function="{or: [{id: $search}, {name: {like: '%'+ $search +'%'}}]}"
ng-model="$ctrl.invoiceOut.client.id"
initial-data="$ctrl.invoiceOut.client.id"
order="id">
<tpl-item>
#{{id}} - {{::name}}
</tpl-item>
</vn-autocomplete>
<vn-autocomplete
vn-one
vn-id="cplusRectificationType"
required="true"
data="cplusRectificationTypes"
show-field="description"
value-field="id"
ng-model="$ctrl.cplusRectificationType"
search-function="{or: [{id: $search}, {description: {like: '%'+ $search +'%'}}]}"
label="Cplus Type">
<tpl-item>
{{::description}}
</tpl-item>
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete
vn-one
vn-id="cplusInvoiceType"
data="siiTypeInvoiceOut"
show-field="description"
value-field="id"
required="true"
ng-model="$ctrl.siiTypeInvoiceOut"
search-function="{or: [{id: $search}, {description: {like: '%'+ $search +'%'}}]}"
label="Class">
</vn-autocomplete>
<vn-autocomplete
vn-one
vn-id="invoiceCorrectionType"
data="invoiceCorrectionTypes"
ng-model="$ctrl.invoiceCorrectionType"
show-field="description"
value-field="id"
required="true"
label="Type">
</vn-autocomplete>
</vn-horizontal>
</section>
<vn-horizontal>
<vn-autocomplete
vn-one
vn-id="client"
required="true"
url="Clients"
label="Client"
show-field="name"
value-field="id"
search-function="{or: [{id: $search}, {name: {like: '%'+ $search +'%'}}]}"
ng-model="$ctrl.clientId"
order="id">
<tpl-item>
#{{id}} - {{::name}}
</tpl-item>
</vn-autocomplete>
<vn-autocomplete
vn-one
vn-id="cplusRectificationType"
required="true"
data="cplusRectificationTypes"
show-field="description"
value-field="id"
ng-model="$ctrl.cplusRectificationType"
search-function="{or: [{id: $search}, {description: {like: '%'+ $search +'%'}}]}"
label="Rectificative type">
<tpl-item>
{{::description}}
</tpl-item>
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete
vn-one
vn-id="siiTypeInvoiceOut"
data="siiTypeInvoiceOuts"
show-field="description"
value-field="id"
fields="['id','code','description']"
required="true"
ng-model="$ctrl.siiTypeInvoiceOut"
label="Class">
<tpl-item>
{{::code}} - {{::description}}
</tpl-item>
</vn-autocomplete>
<vn-autocomplete
vn-one
vn-id="invoiceCorrectionType"
data="invoiceCorrectionTypes"
ng-model="$ctrl.invoiceCorrectionType"
show-field="description"
value-field="id"
required="true"
label="Type">
</vn-autocomplete>
</vn-horizontal>
</section>
</tpl-body>
<tpl-buttons>
<button response="accept" translate>Transfer client</button>

View File

@ -129,15 +129,15 @@ class Controller extends Section {
transferInvoice() {
const params = {
id: this.invoiceOut.id,
ref: this.invoiceOut.ref,
newClientFk: this.invoiceOut.client.id,
cplusRectificationId: this.cplusRectificationType,
siiTypeInvoiceOutId: this.siiTypeInvoiceOut,
invoiceCorrectionTypeId: this.invoiceCorrectionType
refFk: this.invoiceOut.ref,
newClientFk: this.clientId,
cplusRectificationTypeFk: this.cplusRectificationType,
siiTypeInvoiceOutFk: this.siiTypeInvoiceOut,
invoiceCorrectionTypeFk: this.invoiceCorrectionType
};
this.$http.post(`InvoiceOuts/transferInvoice`, params).then(res => {
const invoiceId = res.data;
this.vnApp.showSuccess(this.$t('Invoice trasfered!'));
this.vnApp.showSuccess(this.$t('Transferred invoice'));
this.$state.go('invoiceOut.card.summary', {id: invoiceId});
});
}

View File

@ -22,4 +22,5 @@ The email can't be empty: El correo no puede estar vacío
The following refund tickets have been created: "Se han creado los siguientes tickets de abono: {{ticketIds}}"
Refund...: Abono...
Transfer invoice to...: Transferir factura a...
Cplus Type: Cplus Tipo
Rectificative type: Tipo rectificativa
Transferred invoice: Factura transferida

View File

@ -6,6 +6,7 @@
auto-load="true"
url="InvoiceOutSerials"
data="invoiceOutSerials"
where="{code: {neq: 'R'}}"
order="code">
</vn-crud-model>
<vn-crud-model

View File

@ -1,6 +1,9 @@
{
"name": "ItemBarcode",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "itemBarcode"

View File

@ -1,6 +1,9 @@
{
"name": "ItemBotanical",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "itemBotanical"

View File

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

View File

@ -1,6 +1,9 @@
{
"name": "ItemTag",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "itemTag"

View File

@ -1,6 +1,9 @@
{
"name": "ItemTaxCountry",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "itemTaxCountry"

View File

@ -1,6 +1,9 @@
{
"name": "Item",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "item"

View File

@ -1,6 +1,9 @@
{
"name": "Route",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "route"

View File

@ -1,6 +1,9 @@
{
"name": "Shelving",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "shelving"

View File

@ -1,6 +1,9 @@
{
"name": "SupplierAccount",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "supplierAccount"

View File

@ -1,7 +1,10 @@
{
"name": "SupplierAddress",
"description": "Supplier addresses",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "supplierAddress"

View File

@ -1,6 +1,9 @@
{
"name": "SupplierContact",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "supplierContact"

View File

@ -1,6 +1,9 @@
{
"name": "Supplier",
"base": "Loggable",
"base": "VnModel",
"mixins": {
"Loggable": true
},
"options": {
"mysql": {
"table": "supplier"

View File

@ -19,7 +19,7 @@ module.exports = Self => {
}
],
returns: {
type: ['number'],
type: ['object'],
root: true
},
http: {
@ -54,7 +54,7 @@ module.exports = Self => {
if (tx) await tx.commit();
return refundsTicket[0];
return refundsTicket;
} catch (e) {
if (tx) await tx.rollback();
throw e;

View File

@ -102,7 +102,7 @@ describe('sale canEdit()', () => {
try {
const options = {transaction: tx};
const role = await models.Role.findOne({
const role = await models.VnRole.findOne({
where: {
name: roleEnabled.principalId
}
@ -159,7 +159,7 @@ describe('sale canEdit()', () => {
try {
const options = {transaction: tx};
const role = await models.Role.findOne({
const role = await models.VnRole.findOne({
where: {
name: roleEnabled.principalId
}

View File

@ -23,9 +23,9 @@ describe('Sale refund()', () => {
try {
const options = {transaction: tx};
const refundedTicket = await models.Sale.refund(ctx, salesIds, servicesIds, withWarehouse, options);
const refundedTickets = await models.Sale.refund(ctx, salesIds, servicesIds, withWarehouse, options);
expect(refundedTicket).toBeDefined();
expect(refundedTickets).toBeDefined();
await tx.rollback();
} catch (e) {
@ -42,11 +42,11 @@ describe('Sale refund()', () => {
const options = {transaction: tx};
const ticketsBefore = await models.Ticket.find({}, options);
const ticket = await models.Sale.refund(ctx, salesIds, servicesIds, withWarehouse, options);
const tickets = await models.Sale.refund(ctx, salesIds, servicesIds, withWarehouse, options);
const refundedTicket = await models.Ticket.findOne({
where: {
id: ticket.id
id: tickets[0].id
},
include: [
{

Some files were not shown because too many files have changed in this diff Show More