Merge branch 'dev' into 3837-edi_import
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Joan Sanchez 2022-04-11 12:43:52 +00:00
commit 7228394393
34 changed files with 946 additions and 16 deletions

View File

@ -0,0 +1,2 @@
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES('EducationLevel', '*', '*', 'ALLOW', 'ROLE', 'employee');

View File

@ -0,0 +1,3 @@
INSERT INTO `salix`.`ACL`
(`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES('InvoiceInIntrastat', '*', '*', 'ALLOW', 'ROLE', 'employee');

View File

@ -0,0 +1,2 @@
INSERT INTO `vn`.`component` (`name`,`typeFk`,`classRate`,`isRenewable`,`code`,`isRequired`)
VALUES ('maná reclamacion',7,4,0,'manaClaim',0);

View File

@ -0,0 +1,90 @@
ALTER TABLE `vn`.`country` ADD `a3Code` INT NULL COMMENT 'Código país para a3';
UPDATE `vn`.`country` c
JOIN `vn2008`.`payroll_pais` `p` ON `p`.`pais` = `c`.`country`
SET `c`.`a3Code` = `p`.`codpais`;
UPDATE `vn`.`country`
SET `a3Code` = 710
WHERE `country` = 'Sud-Africa'; -- ÁFRICA DEL SUR
UPDATE `vn`.`country`
SET `a3Code` = 643
WHERE `country` = 'Rusia'; -- FEDERACIÓN DE RUSIA
UPDATE `vn`.`country`
SET `a3Code` = 28
WHERE `country` = 'Antigua'; -- ANTIGUA Y BARBUDA
UPDATE `vn`.`country`
SET `a3Code` = 840
WHERE `country` = 'USA'; -- ESTADOS UNIDOS
UPDATE `vn`.`country`
SET `a3Code` = 404
WHERE `country` = 'Kenya'; -- KENIA
UPDATE `vn`.`country`
SET `a3Code` = 498
WHERE `country` = 'Moldavia'; -- REPÚBLICA DE MOLDAVIA
UPDATE `vn`.`country`
SET `a3Code` = 826
WHERE `country` = 'Gran Bretaña'; -- REINO UNIDO
UPDATE `vn`.`country`
SET `a3Code` = 484
WHERE `country` = 'Mexico'; -- MÉJICO
UPDATE `vn`.`country`
SET `a3Code` = 716
WHERE `country` = 'Zimbawe'; -- ZINBABWE
UPDATE `vn`.`country`
SET `a3Code` = 203
WHERE `country` = 'Chequia'; -- REPÚBLICA CHECA
UPDATE `vn`.`country`
SET `a3Code` = 764
WHERE `country` = 'Thailandia'; -- TAILANDIA
UPDATE `vn`.`country`
SET `a3Code` = 276
WHERE `country` = 'Alemania'; -- REPÚBLICA FEDERAL DE ALEMANIA
UPDATE `vn`.`country`
SET `a3Code` = 112
WHERE `country` = 'Bielorrusia'; -- BELARUS
UPDATE `vn`.`country`
SET `a3Code` = 528
WHERE `country` = 'Holanda'; -- PAÍSES BAJOS
UPDATE `vn`.`country`
SET `a3Code` = 410
WHERE `country` = 'Corea del Sur'; -- COREA (REPÚBLICA)
UPDATE `vn`.`country`
SET `a3Code` = 724
WHERE `country` = 'España exento'; -- ESPAÑA
-- Borrar registro USA de country:
UPDATE `vn`.`supplier` `s`
SET `s`.`countryFk` = 62
WHERE `s`.`countryFk` = 12;
UPDATE `vn`.`bankEntity`
SET `countryFk` = 62
WHERE `countryFk` = 12;
DELETE FROM `vn`.`country`
WHERE `id`= 12;
UPDATE `vn2008`.`payroll_pais`
SET `pais`='COREA NORTE (REPÚBLICA DEM. POPULAR)'
WHERE `codpais`=408;
UPDATE `vn2008`.`payroll_pais`
SET `pais`='COREA SUR (REPÚBLICA) '
WHERE `codpais`=410;
RENAME TABLE `vn2008`.`payroll_pais` TO `vn2008`.`payroll_pais__`;

View File

@ -0,0 +1,2 @@
INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalId`)
VALUES ('InvoiceInIntrastat','*','*','ALLOW','ROLE','employee');

View File

@ -0,0 +1,106 @@
DROP PROCEDURE IF EXISTS `bs`.`manaCustomerUpdate`;
DELIMITER $$
$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `bs`.`manaCustomerUpdate`()
BEGIN
DECLARE vToDated DATE;
DECLARE vFromDated DATE;
DECLARE vForDeleteDated DATE;
DECLARE vManaId INT;
DECLARE vManaAutoId INT;
DECLARE vClaimManaId INT;
DECLARE vManaBankId INT;
DECLARE vManaGreugeTypeId INT;
SELECT id INTO vManaId
FROM `component` WHERE code = 'mana';
SELECT id INTO vManaAutoId
FROM `component` WHERE code = 'autoMana';
SELECT id INTO vClaimManaId
FROM `component` WHERE code = 'manaClaim';
SELECT id INTO vManaBankId
FROM `bank` WHERE code = 'mana';
SELECT id INTO vManaGreugeTypeId
FROM `greugeType` WHERE code = 'mana';
SELECT IFNULL(max(dated), '2016-01-01')
INTO vFromDated
FROM bs.manaCustomer;
DELETE
FROM bs.manaCustomer
WHERE dated = vFromDated;
SELECT IFNULL(max(dated), '2016-01-01')
INTO vFromDated
FROM bs.manaCustomer;
WHILE timestampadd(DAY,30,vFromDated) < CURDATE() DO
SELECT
timestampadd(DAY,30,vFromDated),
timestampadd(DAY,-90,vFromDated)
INTO
vToDated,
vForDeleteDated;
DELETE FROM bs.manaCustomer
WHERE dated <= vForDeleteDated;
INSERT INTO bs.manaCustomer(Id_Cliente, Mana, dated)
SELECT
Id_Cliente,
cast(sum(mana) as decimal(10,2)) as mana,
vToDated as dated
FROM
(
SELECT cs.Id_Cliente, Cantidad * Valor as mana
FROM vn2008.Tickets t
JOIN vn2008.Consignatarios cs using(Id_Consigna)
JOIN vn2008.Movimientos m on m.Id_Ticket = t.Id_Ticket
JOIN vn2008.Movimientos_componentes mc on mc.Id_Movimiento = m.Id_Movimiento
WHERE Id_Componente IN (vManaAutoId, vManaId, vClaimManaId)
AND t.Fecha > vFromDated
AND date(t.Fecha) <= vToDated
UNION ALL
SELECT r.Id_Cliente, - Entregado
FROM vn2008.Recibos r
WHERE Id_Banco = vManaBankId
AND Fechacobro > vFromDated
AND Fechacobro <= vToDated
UNION ALL
SELECT g.Id_Cliente, g.Importe
FROM vn2008.Greuges g
WHERE Greuges_type_id = vManaGreugeTypeId
AND Fecha > vFromDated
AND Fecha <= vToDated
UNION ALL
SELECT Id_Cliente, mana
FROM bs.manaCustomer
WHERE dated = vFromDated
) sub
GROUP BY Id_Cliente
HAVING Id_Cliente;
SET vFromDated = vToDated;
END WHILE;
END$$
DELIMITER ;

View File

@ -0,0 +1,75 @@
DROP PROCEDURE IF EXISTS `vn`.`manaSpellersRequery`;
DELIMITER $$
$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`manaSpellersRequery`(vWorkerFk INTEGER)
BEGIN
/**
* Recalcula el mana consumido por un trabajador
*
* @param vWorkerFk Id Trabajador
*/
DECLARE vWorkerIsExcluded BOOLEAN;
DECLARE vFromDated DATE;
DECLARE vToDated DATE DEFAULT TIMESTAMPADD(DAY,1,CURDATE());
DECLARE vMana INT;
DECLARE vAutoMana INT;
DECLARE vClaimMana INT;
DECLARE vManaBank INT;
DECLARE vManaGreugeType INT;
SELECT COUNT(*) INTO vWorkerIsExcluded
FROM workerManaExcluded
WHERE workerFk = vWorkerFk;
IF NOT vWorkerIsExcluded THEN
SELECT id INTO vMana
FROM `component` WHERE code = 'mana';
SELECT id INTO vAutoMana
FROM `component` WHERE code = 'autoMana';
SELECT id INTO vClaimMana
FROM `component` WHERE code = 'manaClaim';
SELECT id INTO vManaBank
FROM `bank` WHERE code = 'mana';
SELECT id INTO vManaGreugeType
FROM `greugeType` WHERE code = 'mana';
SELECT max(dated) INTO vFromDated
FROM clientManaCache;
REPLACE workerMana (workerFk, amount)
SELECT vWorkerFk, sum(mana) FROM
(
SELECT s.quantity * sc.value as mana
FROM ticket t
JOIN address a ON a.id = t.addressFk
JOIN client c ON c.id = a.clientFk
JOIN sale s ON s.ticketFk = t.id
JOIN saleComponent sc ON sc.saleFk = s.id
WHERE c.salesPersonFk = vWorkerFk AND sc.componentFk IN (vMana, vAutoMana, vClaimMana)
AND t.shipped > vFromDated AND t.shipped < vToDated
UNION ALL
SELECT - r.amountPaid
FROM receipt r
JOIN client c ON c.id = r.clientFk
WHERE c.salesPersonFk = vWorkerFk AND bankFk = vManaBank
AND payed > vFromDated
UNION ALL
SELECT g.amount
FROM greuge g
JOIN client c ON c.id = g.clientFk
WHERE c.salesPersonFk = vWorkerFk AND g.greugeTypeFk = vManaGreugeType
AND g.shipped > vFromDated and g.shipped < CURDATE()
UNION ALL
SELECT cc.mana
FROM clientManaCache cc
JOIN client c ON c.id = cc.clientFk
WHERE c.salesPersonFk = vWorkerFk AND cc.dated = vFromDated
) sub;
END IF;
END$$
DELIMITER ;

View File

@ -0,0 +1,51 @@
ALTER TABLE `vn`.`worker` MODIFY COLUMN `maritalStatus__` varchar(10) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL;
UPDATE `vn`.`worker` `w`
SET `w`.`maritalStatus__` = NULL;
UPDATE `vn`.`worker` `w`
JOIN `vn`.`person` `p` ON `p`.`workerFk` = `w`.`id`
JOIN `postgresql`.`profile` `pr` ON `pr`.`person_id` = `p`.`id`
JOIN `vn2008`.`profile_labour_payroll` `pl` ON `pl`.`profile_id` = `pr`.`profile_id`
SET `w`.`maritalStatus__` = `pl`.`estadocivil`;
ALTER TABLE `vn`.`worker` ADD `originCountryFk` mediumint(8) unsigned NULL COMMENT 'País de origen';
ALTER TABLE `vn`.`worker` ADD `educationLevelFk` SMALLINT NULL;
ALTER TABLE `vn`.`worker` ADD `SSN` varchar(15) NULL;
ALTER TABLE `vn`.`worker` CHANGE `maritalStatus__` `maritalStatus` enum('S','M') CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL;
ALTER TABLE `vn`.`worker` MODIFY COLUMN `maritalStatus` enum('S','M') CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL;
ALTER TABLE `vn`.`worker` CHANGE `maritalStatus` maritalStatus enum('S','M') CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL AFTER sectorFk;
ALTER TABLE `vn`.`worker` ADD CONSTRAINT `worker_FK_2` FOREIGN KEY (`educationLevelFk`) REFERENCES `vn`.`educationLevel`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `vn`.`worker` ADD CONSTRAINT `worker_FK_1` FOREIGN KEY (`originCountryFk`) REFERENCES `vn`.`country`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
INSERT INTO `vn`.`country` (`country`, `CEE`, `code`, `politicalCountryFk`, `isUeeMember`, `a3Code`)
VALUES
('Argentina',2,'AR',80,0,32),
('Cuba',2,'CU',81,0,192),
('Guinea Ecuatorial',2,'GQ',82,0,226),
('Guinea',2,'GN',83,0,324),
('Honduras',2,'HN',84,0,340),
('Mali',2,'ML',85,0,466),
('Nicaragua',2,'NI',86,0,558),
('Pakistán',2,'PK',87,0,586),
('Paraguay',2,'PY',88,0,600),
('Senegal',2,'SN',89,0,686),
('Uruguay',2,'UY',90,0,858),
('Venezuela',2,'VE',91,0,862),
('Bulgaria',2,'BG',92,1,100),
('Georgia',2,'GE',93,0,268);
UPDATE `vn`.`worker` `w`
JOIN `vn`.`person` `p` ON `p`.`workerFk` = `w`.`id`
JOIN `postgresql`.`profile` `pr` ON `pr`.`person_id` = `p`.`id`
JOIN `vn2008`.`profile_labour_payroll` `pl` ON `pl`.`profile_id` = `pr`.`profile_id`
JOIN `vn`.`country` `co` ON `co`.`a3Code` = `pl`.`codpais`
SET `w`.`originCountryFk` = `co`.`id`;
UPDATE `vn`.`worker` `w`
JOIN `vn`.`person` `p` ON `p`.`workerFk` = `w`.`id`
JOIN `postgresql`.`profile` `pr` ON `pr`.`person_id` = `p`.`id`
JOIN `vn2008`.`profile_labour_payroll` pl ON `pl`.`profile_id` = `pr`.`profile_id`
SET `w`.`SSN` = CONCAT(`pl`.`NSSProvincia`, `pl`.`NssNumero`, `pl`.`NssDC`);
RENAME TABLE `vn2008`.`profile_labour_payroll` TO `vn2008`.`profile_labour_payroll__`;

View File

@ -47,10 +47,36 @@ INSERT INTO `account`.`user`(`id`,`name`, `nickname`, `password`,`role`,`active`
INSERT INTO `account`.`account`(`id`) INSERT INTO `account`.`account`(`id`)
SELECT id FROM `account`.`user`; SELECT id FROM `account`.`user`;
INSERT INTO `vn`.`educationLevel` (`id`, `name`)
VALUES
(1, 'ESTUDIOS PRIMARIOS COMPLETOS'),
(2, 'ENSEÑANZAS DE BACHILLERATO');
INSERT INTO `vn`.`worker`(`id`,`code`, `firstName`, `lastName`, `userFk`, `bossFk`) INSERT INTO `vn`.`worker`(`id`,`code`, `firstName`, `lastName`, `userFk`, `bossFk`)
SELECT id,UPPER(LPAD(role, 3, '0')), name, name, id, 9 SELECT id,UPPER(LPAD(role, 3, '0')), name, name, id, 9
FROM `vn`.`user`; FROM `vn`.`user`;
ALTER TABLE `vn`.`worker` ADD `originCountryFk` mediumint(8) unsigned NULL COMMENT 'País de origen';
ALTER TABLE `vn`.`worker` ADD `educationLevelFk` SMALLINT NULL;
ALTER TABLE `vn`.`worker` ADD `SSN` varchar(15) NULL;
ALTER TABLE `vn`.`worker` CHANGE `maritalStatus__` `maritalStatus` enum('S','M') CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL;
ALTER TABLE `vn`.`worker` MODIFY COLUMN `maritalStatus` enum('S','M') CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL;
ALTER TABLE `vn`.`worker` CHANGE `maritalStatus` maritalStatus enum('S','M') CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL AFTER sectorFk;
ALTER TABLE `vn`.`worker` ADD CONSTRAINT `worker_FK_2` FOREIGN KEY (`educationLevelFk`) REFERENCES `vn`.`educationLevel`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `vn`.`worker` ADD CONSTRAINT `worker_FK_1` FOREIGN KEY (`originCountryFk`) REFERENCES `vn`.`country`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
UPDATE `vn`.`worker` `w`
SET `maritalStatus` = 'S';
UPDATE `vn`.`worker` `w`
SET `originCountryFk` = '1';
UPDATE `vn`.`worker` `w`
SET `educationLevelFk` = '2';
UPDATE `vn`.`worker` `w`
SET `SSN` = '123456789123';
UPDATE `vn`.`worker` SET bossFk = NULL WHERE id = 20; UPDATE `vn`.`worker` SET bossFk = NULL WHERE id = 20;
UPDATE `vn`.`worker` SET bossFk = 20 WHERE id = 1 OR id = 9; UPDATE `vn`.`worker` SET bossFk = 20 WHERE id = 1 OR id = 9;
UPDATE `vn`.`worker` SET bossFk = 19 WHERE id = 18; UPDATE `vn`.`worker` SET bossFk = 19 WHERE id = 18;
@ -2428,6 +2454,13 @@ INSERT INTO `vn`.`invoiceInTax` (`invoiceInFk`, `taxableBase`, `expenceFk`, `for
(6, 29.95, '7001000000', NULL, 7, 20), (6, 29.95, '7001000000', NULL, 7, 20),
(7, 58.64, '6210000567', NULL, 8, 20); (7, 58.64, '6210000567', NULL, 8, 20);
INSERT INTO `vn`.`invoiceInIntrastat` (`invoiceInFk`, `net`, `intrastatFk`, `amount`, `stems`, `countryFk`)
VALUES
(1, 30.50, 5080000, 10.00, 162, 5),
(1, 10, 6021010, 20.00, 205, 5),
(2, 13.20, 5080000, 15.00, 580, 5),
(2, 16.10, 6021010, 25.00, 80, 5);
INSERT INTO `vn`.`ticketRecalc`(`ticketFk`) INSERT INTO `vn`.`ticketRecalc`(`ticketFk`)
SELECT `id` SELECT `id`
FROM `vn`.`ticket` t FROM `vn`.`ticket` t

View File

@ -585,6 +585,7 @@ export default {
firstSalePriceInput: '.vn-popover.shown input[ng-model="$ctrl.field"]', firstSalePriceInput: '.vn-popover.shown input[ng-model="$ctrl.field"]',
firstSaleDiscount: 'vn-ticket-sale vn-table vn-tr:nth-child(1) > vn-td:nth-child(10) > span', firstSaleDiscount: 'vn-ticket-sale vn-table vn-tr:nth-child(1) > vn-td:nth-child(10) > span',
firstSaleDiscountInput: '.vn-popover.shown [ng-model="$ctrl.field"]', firstSaleDiscountInput: '.vn-popover.shown [ng-model="$ctrl.field"]',
saveSaleDiscountButton: '.vn-popover.shown vn-button[label="Save"]',
firstSaleImport: 'vn-ticket-sale:nth-child(1) vn-td:nth-child(11)', firstSaleImport: 'vn-ticket-sale:nth-child(1) vn-td:nth-child(11)',
firstSaleReservedIcon: 'vn-ticket-sale vn-tr:nth-child(1) > vn-td:nth-child(2) > vn-icon:nth-child(3)', firstSaleReservedIcon: 'vn-ticket-sale vn-tr:nth-child(1) > vn-td:nth-child(2) > vn-icon:nth-child(3)',
firstSaleColour: 'vn-ticket-sale vn-tr:nth-child(1) vn-fetched-tags section', firstSaleColour: 'vn-ticket-sale vn-tr:nth-child(1) vn-fetched-tags section',

View File

@ -175,7 +175,8 @@ describe('Ticket Edit sale path', () => {
it('should update the discount', async() => { it('should update the discount', async() => {
await page.waitToClick(selectors.ticketSales.firstSaleDiscount); await page.waitToClick(selectors.ticketSales.firstSaleDiscount);
await page.waitForSelector(selectors.ticketSales.firstSaleDiscountInput); await page.waitForSelector(selectors.ticketSales.firstSaleDiscountInput);
await page.type(selectors.ticketSales.firstSaleDiscountInput, '50\u000d'); await page.type(selectors.ticketSales.firstSaleDiscountInput, '50');
await page.waitToClick(selectors.ticketSales.saveSaleDiscountButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!'); expect(message.text).toContain('Data saved!');

View File

@ -64,6 +64,34 @@ module.exports = Self => {
}] }]
} }
}, },
{
relation: 'invoiceInIntrastat',
scope: {
fields: [
'id',
'invoiceInFk',
'net',
'intrastatFk',
'amount',
'stems',
'countryFk',
'statisticalValue'],
include: [{
relation: 'intrastat',
scope: {
fields: [
'id',
'description']
}
},
{
relation: 'country',
scope: {
fields: ['code']
}
}]
}
},
{ {
relation: 'invoiceInTax', relation: 'invoiceInTax',
scope: { scope: {

View File

@ -8,6 +8,9 @@
"InvoiceInDueDay": { "InvoiceInDueDay": {
"dataSource": "vn" "dataSource": "vn"
}, },
"InvoiceInIntrastat": {
"dataSource": "vn"
},
"InvoiceInLog": { "InvoiceInLog": {
"dataSource": "vn" "dataSource": "vn"
} }

View File

@ -0,0 +1,50 @@
{
"name": "InvoiceInIntrastat",
"base": "VnModel",
"options": {
"mysql": {
"table": "invoiceInIntrastat"
}
},
"properties": {
"id": {
"id": true,
"type": "number",
"description": "Identifier"
},
"invoiceInFk": {
"type": "number"
},
"net": {
"type": "number"
},
"intrastatFk": {
"type": "number"
},
"amount": {
"type": "number"
},
"stems": {
"type": "number"
},
"countryFk": {
"type": "number"
},
"statisticalValue": {
"type": "number"
}
},
"relations": {
"intrastat": {
"type": "belongsTo",
"model": "Intrastat",
"foreignKey": "intrastatFk"
},
"country": {
"type": "belongsTo",
"model": "Country",
"foreignKey": "countryFk"
}
}
}

View File

@ -64,6 +64,11 @@
"model": "InvoiceInDueDay", "model": "InvoiceInDueDay",
"foreignKey": "invoiceInFk" "foreignKey": "invoiceInFk"
}, },
"invoiceInIntrastat": {
"type": "hasMany",
"model": "InvoiceInIntrastat",
"foreignKey": "invoiceInFk"
},
"invoiceInTax": { "invoiceInTax": {
"type": "hasMany", "type": "hasMany",
"model": "InvoiceInTax", "model": "InvoiceInTax",

View File

@ -10,5 +10,6 @@ import './summary';
import './basic-data'; import './basic-data';
import './tax'; import './tax';
import './dueDay'; import './dueDay';
import './intrastat';
import './create'; import './create';
import './log'; import './log';

View File

@ -0,0 +1,100 @@
<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="country">
</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 | zeroFill:8}}: {{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>

View File

@ -0,0 +1,60 @@
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: '<'
}
});

View File

@ -0,0 +1,85 @@
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();
});
});
});
});

View File

@ -9,10 +9,13 @@ InvoiceIn cloned: Factura clonada
InvoiceIn deleted: Factura eliminada InvoiceIn deleted: Factura eliminada
Invoice list: Listado de facturas recibidas Invoice list: Listado de facturas recibidas
InvoiceIn booked: Factura contabilizada InvoiceIn booked: Factura contabilizada
Net: Neto
Remove tax: Quitar iva Remove tax: Quitar iva
Remove due day: Quitar vencimiento Remove due day: Quitar vencimiento
Sage tax: Sage iva Sage tax: Sage iva
Sage transaction: Sage transaccion Sage transaction: Sage transaccion
Search invoices in by reference: Buscar facturas recibidas por referencia Search invoices in by reference: Buscar facturas recibidas por referencia
To book: Contabilizar To book: Contabilizar
Total amount: Total importe
Total net: Total neto
Total stems: Total tallos

View File

@ -27,6 +27,10 @@
"state": "invoiceIn.card.dueDay", "state": "invoiceIn.card.dueDay",
"icon": "icon-calendar" "icon": "icon-calendar"
}, },
{
"state": "invoiceIn.card.intrastat",
"icon": "icon-lines"
},
{ {
"state": "invoiceIn.card.log", "state": "invoiceIn.card.log",
"icon": "history" "icon": "history"
@ -109,6 +113,16 @@
}, },
"acl": ["administrative"] "acl": ["administrative"]
}, },
{
"url": "/intrastat",
"state": "invoiceIn.card.intrastat",
"component": "vn-invoice-in-intrastat",
"description": "Intrastat",
"params": {
"invoice-in": "$ctrl.invoiceIn"
},
"acl": ["administrative"]
},
{ {
"url": "/log", "url": "/log",
"state": "invoiceIn.card.log", "state": "invoiceIn.card.log",

View File

@ -120,6 +120,37 @@
</vn-table> </vn-table>
</vn-one> </vn-one>
</vn-horizontal> </vn-horizontal>
<vn-horizontal>
<vn-one ng-if="$ctrl.summary.invoiceInIntrastat.length != 0">
<h4>
<a
ui-sref="invoiceIn.card.intrastat({id:$ctrl.invoiceIn.id})"
target="_self">
<span translate vn-tooltip="Go to">Intrastat</span>
</a>
</h4>
<vn-table model="model">
<vn-thead>
<vn-tr>
<vn-th>Code</vn-th>
<vn-th>Amount</vn-th>
<vn-th>Net</vn-th>
<vn-th>Stems</vn-th>
<vn-th>Country</vn-th>
</vn-tr>
</vn-thead>
<vn-tbody>
<vn-tr ng-repeat="intrastat in $ctrl.summary.invoiceInIntrastat">
<vn-td>{{::intrastat.intrastatFk | zeroFill:8}}: {{::intrastat.intrastat.description}}</vn-td>
<vn-td>{{::intrastat.amount | currency: 'EUR':2}}</vn-td>
<vn-td>{{::intrastat.net}}</vn-td>
<vn-td>{{::intrastat.stems}}</vn-td>
<vn-td>{{::intrastat.country.code}}</vn-td>
</vn-tr>
</vn-tbody>
</vn-table>
</vn-one>
</vn-horizontal>
</vn-card> </vn-card>
<vn-supplier-descriptor-popover <vn-supplier-descriptor-popover
vn-id="supplierDescriptor"> vn-id="supplierDescriptor">

View File

@ -90,7 +90,7 @@ describe('sale updateDiscount()', () => {
expect(error.message).toEqual(`The sales of this ticket can't be modified`); expect(error.message).toEqual(`The sales of this ticket can't be modified`);
}); });
it('should update the discount if the salesPerson has mana', async() => { it('should update the discount if the salesPerson has mana and manaCode = "mana"', async() => {
const tx = await models.Ticket.beginTransaction({}); const tx = await models.Ticket.beginTransaction({});
try { try {
@ -108,8 +108,49 @@ describe('sale updateDiscount()', () => {
const newDiscount = 100; const newDiscount = 100;
const manaDiscount = await models.Component.findOne({where: {code: 'mana'}}, options); const manaDiscount = await models.Component.findOne({where: {code: 'mana'}}, options);
const componentId = manaDiscount.id; const componentId = manaDiscount.id;
const manaCode = 'mana';
await models.Ticket.updateDiscount(ctx, ticketId, sales, newDiscount, options); await models.Ticket.updateDiscount(ctx, ticketId, sales, newDiscount, manaCode, options);
const updatedSale = await models.Sale.findById(originalSaleId, null, options);
const createdSaleComponent = await models.SaleComponent.findOne({
where: {
componentFk: componentId,
saleFk: originalSaleId
}
}, options);
expect(createdSaleComponent.componentFk).toEqual(componentId);
expect(updatedSale.discount).toEqual(100);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should update the discount if the salesPerson has mana and manaCode = "manaClaim"', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
const options = {transaction: tx};
const ctx = {
req: {
accessToken: {userId: 18},
headers: {origin: 'localhost:5000'},
__: () => {}
}
};
const ticketId = 11;
const sales = [originalSaleId];
const newDiscount = 100;
const manaDiscount = await models.Component.findOne({where: {code: 'manaClaim'}}, options);
const componentId = manaDiscount.id;
const manaCode = 'manaClaim';
await models.Ticket.updateDiscount(ctx, ticketId, sales, newDiscount, manaCode, options);
const updatedSale = await models.Sale.findById(originalSaleId, null, options); const updatedSale = await models.Sale.findById(originalSaleId, null, options);
const createdSaleComponent = await models.SaleComponent.findOne({ const createdSaleComponent = await models.SaleComponent.findOne({

View File

@ -23,6 +23,12 @@ module.exports = Self => {
description: 'The new discount', description: 'The new discount',
type: 'number', type: 'number',
required: true required: true
},
{
arg: 'manaCode',
description: 'The type of mana',
type: 'string',
required: false
} }
], ],
returns: { returns: {
@ -35,7 +41,7 @@ module.exports = Self => {
} }
}); });
Self.updateDiscount = async(ctx, id, salesIds, newDiscount, options) => { Self.updateDiscount = async(ctx, id, salesIds, newDiscount, manaCode, options) => {
const $t = ctx.req.__; // $translate const $t = ctx.req.__; // $translate
const models = Self.app.models; const models = Self.app.models;
const myOptions = {}; const myOptions = {};
@ -98,7 +104,7 @@ module.exports = Self => {
}, },
fields: 'amount'}, myOptions); fields: 'amount'}, myOptions);
const componentCode = usesMana ? 'mana' : 'buyerDiscount'; const componentCode = usesMana ? manaCode : 'buyerDiscount';
const discountComponent = await models.Component.findOne({ const discountComponent = await models.Component.findOne({
where: {code: componentCode}}, myOptions); where: {code: componentCode}}, myOptions);

View File

@ -285,10 +285,21 @@
vn-focus vn-focus
label="Discount" label="Discount"
ng-model="$ctrl.edit.discount" ng-model="$ctrl.edit.discount"
on-change="$ctrl.changeDiscount()"
clear-disabled="true" clear-disabled="true"
suffix="%"> suffix="%">
</vn-input-number> </vn-input-number>
<vn-vertical ng-if="$ctrl.currentWorkerMana != 0">
<vn-radio
label="Promotion mana"
val="mana"
ng-model="$ctrl.manaCode">
</vn-radio>
<vn-radio
label="Claim mana"
val="manaClaim"
ng-model="$ctrl.manaCode">
</vn-radio>
</vn-vertical>
<div class="simulator"> <div class="simulator">
<p class="simulatorTitle" translate>New price</p> <p class="simulatorTitle" translate>New price</p>
<p> <p>
@ -297,6 +308,16 @@
</div> </div>
</div> </div>
</div> </div>
<vn-horizontal >
<vn-button
label="Cancel"
ng-click="$ctrl.cancel()">
</vn-button>
<vn-button
label="Save"
ng-click="$ctrl.save()">
</vn-button>
</vn-horizontal>
</div> </div>
</vn-popover> </vn-popover>

View File

@ -6,6 +6,15 @@ class Controller extends Section {
constructor($element, $) { constructor($element, $) {
super($element, $); super($element, $);
this._sales = []; this._sales = [];
this.manaCode = 'mana';
}
get manaCode() {
return this._manaCode;
}
set manaCode(value) {
this._manaCode = value;
} }
get ticket() { get ticket() {
@ -66,6 +75,14 @@ class Controller extends Section {
this.$.editPricePopover.relocate(); this.$.editPricePopover.relocate();
}); });
}); });
this.getCurrentWorkerMana();
}
getCurrentWorkerMana() {
this.$http.get(`WorkerManas/getCurrentWorkerMana`)
.then(res => {
this.currentWorkerMana = res.data;
});
} }
/** /**
@ -273,7 +290,7 @@ class Controller extends Section {
return sale.id; return sale.id;
}); });
const params = {salesIds: saleIds, newDiscount: this.edit.discount}; const params = {salesIds: saleIds, newDiscount: this.edit.discount, manaCode: this.manaCode};
const query = `Tickets/${this.$params.id}/updateDiscount`; const query = `Tickets/${this.$params.id}/updateDiscount`;
this.$http.post(query, params).then(() => { this.$http.post(query, params).then(() => {
this.vnApp.showSuccess(this.$t('Data saved!')); this.vnApp.showSuccess(this.$t('Data saved!'));
@ -479,6 +496,14 @@ class Controller extends Section {
? {id: $search} ? {id: $search}
: {name: {like: '%' + $search + '%'}}; : {name: {like: '%' + $search + '%'}};
} }
save() {
this.changeDiscount();
}
cancel() {
this.$.editDiscount.hide();
}
} }
ngModule.vnComponent('vnTicketSale', { ngModule.vnComponent('vnTicketSale', {

View File

@ -43,7 +43,7 @@ describe('Ticket', () => {
$scope.sms = {open: () => {}}; $scope.sms = {open: () => {}};
$scope.ticket = ticket; $scope.ticket = ticket;
$scope.model = crudModel; $scope.model = crudModel;
$scope.editDiscount = {relocate: () => {}}; $scope.editDiscount = {relocate: () => {}, hide: () => {}};
$scope.editPricePopover = {relocate: () => {}}; $scope.editPricePopover = {relocate: () => {}};
$httpBackend = _$httpBackend_; $httpBackend = _$httpBackend_;
Object.defineProperties($state.params, { Object.defineProperties($state.params, {
@ -115,10 +115,12 @@ describe('Ticket', () => {
const expectedAmount = 250; const expectedAmount = 250;
$httpBackend.expect('GET', 'Tickets/1/getSalesPersonMana').respond(200, expectedAmount); $httpBackend.expect('GET', 'Tickets/1/getSalesPersonMana').respond(200, expectedAmount);
$httpBackend.expect('GET', 'WorkerManas/getCurrentWorkerMana').respond(200, expectedAmount);
controller.getMana(); controller.getMana();
$httpBackend.flush(); $httpBackend.flush();
expect(controller.edit.mana).toEqual(expectedAmount); expect(controller.edit.mana).toEqual(expectedAmount);
expect(controller.currentWorkerMana).toEqual(expectedAmount);
}); });
}); });
@ -446,7 +448,7 @@ describe('Ticket', () => {
const expectedSales = [firstSelectedSale, secondSelectedSale]; const expectedSales = [firstSelectedSale, secondSelectedSale];
const expectedSaleIds = [firstSelectedSale.id, secondSelectedSale.id]; const expectedSaleIds = [firstSelectedSale.id, secondSelectedSale.id];
const expectedParams = {salesIds: expectedSaleIds, newDiscount: expectedDiscount}; const expectedParams = {salesIds: expectedSaleIds, newDiscount: expectedDiscount, manaCode: 'mana'};
$httpBackend.expect('POST', `Tickets/1/updateDiscount`, expectedParams).respond(200, {discount: 10}); $httpBackend.expect('POST', `Tickets/1/updateDiscount`, expectedParams).respond(200, {discount: 10});
controller.updateDiscount(expectedSales); controller.updateDiscount(expectedSales);
$httpBackend.flush(); $httpBackend.flush();
@ -732,5 +734,14 @@ describe('Ticket', () => {
expect(result).toEqual({name: {like: '%' + itemName + '%'}}); expect(result).toEqual({name: {like: '%' + itemName + '%'}});
}); });
}); });
describe('cancel()', () => {
it('should call hide()', () => {
jest.spyOn(controller.$.editDiscount, 'hide').mockReturnThis();
controller.cancel();
expect(controller.$.editDiscount.hide).toHaveBeenCalledWith();
});
});
}); });
}); });

View File

@ -37,3 +37,5 @@ Agency: Agencia
Shipped: F. envio Shipped: F. envio
Packaging: Encajado Packaging: Encajado
Pay Back: Abono Pay Back: Abono
Promotion mana: Maná promoción
Claim mana: Maná reclamación

View File

@ -17,6 +17,9 @@
"Department": { "Department": {
"dataSource": "vn" "dataSource": "vn"
}, },
"EducationLevel": {
"dataSource": "vn"
},
"WorkCenter": { "WorkCenter": {
"dataSource": "vn" "dataSource": "vn"
}, },

View File

@ -0,0 +1,18 @@
{
"name": "EducationLevel",
"base": "VnModel",
"options": {
"mysql": {
"table": "educationLevel"
}
},
"properties": {
"id": {
"id": true,
"type": "number"
},
"name": {
"type": "string"
}
}
}

View File

@ -13,7 +13,7 @@
}, },
"properties": { "properties": {
"id": { "id": {
"type": "Number", "type": "number",
"id": true, "id": true,
"description": "Identifier" "description": "Identifier"
}, },
@ -26,14 +26,26 @@
"required": true "required": true
}, },
"phone": { "phone": {
"type" : "String" "type" : "string"
}, },
"userFk": { "userFk": {
"type" : "Number", "type" : "number",
"required": true "required": true
}, },
"bossFk": { "bossFk": {
"type" : "Number" "type" : "number"
},
"maritalStatus": {
"type" : "string"
},
"originCountryFk": {
"type" : "number"
},
"educationLevelFk": {
"type" : "number"
},
"SSN": {
"type" : "string"
} }
}, },
"relations": { "relations": {

View File

@ -30,7 +30,6 @@
rule> rule>
</vn-textfield> </vn-textfield>
<vn-autocomplete <vn-autocomplete
disabled="false"
ng-model="$ctrl.worker.bossFk" ng-model="$ctrl.worker.bossFk"
url="Workers/activeWithInheritedRole" url="Workers/activeWithInheritedRole"
show-field="nickname" show-field="nickname"
@ -39,6 +38,39 @@
label="Boss"> label="Boss">
</vn-autocomplete> </vn-autocomplete>
</vn-horizontal> </vn-horizontal>
<vn-horizontal>
<vn-autocomplete
label="Marital status"
data="$ctrl.maritalStatus"
show-field="name"
value-field="code"
ng-model="$ctrl.worker.maritalStatus">
</vn-autocomplete>
<vn-autocomplete
ng-model="$ctrl.worker.originCountryFk"
url="Countries"
fields="['id', 'country', 'code']"
show-field="country"
value-field="id"
label="Origin country">
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete
ng-model="$ctrl.worker.educationLevelFk"
url="EducationLevels"
fields="['id', 'name']"
show-field="name"
value-field="id"
label="Education level">
</vn-autocomplete>
<vn-textfield
vn-one
label="SSN"
ng-model="$ctrl.worker.SSN"
rule>
</vn-textfield>
</vn-horizontal>
</vn-vertical> </vn-vertical>
</vn-card> </vn-card>
<vn-button-bar> <vn-button-bar>

View File

@ -2,6 +2,13 @@ import ngModule from '../module';
import Section from 'salix/components/section'; import Section from 'salix/components/section';
class Controller extends Section { class Controller extends Section {
constructor($element, $) {
super($element, $);
this.maritalStatus = [
{code: 'M', name: this.$t('Married')},
{code: 'S', name: this.$t('Single')}
];
}
onSubmit() { onSubmit() {
return this.$.watcher.submit() return this.$.watcher.submit()
.then(() => this.card.reload()); .then(() => this.card.reload());

View File

@ -0,0 +1,6 @@
Marital status: Estado civil
Origin country: País origen
Education level: Nivel educación
SSN: NSS
Married: Casado/a
Single: Soltero/a