3605-invoiceIn_intrastat3 #921

Merged
carlosjr merged 10 commits from 3605-invoiceIn_intrastat3 into dev 2022-04-11 10:40:20 +00:00
14 changed files with 393 additions and 1 deletions

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 `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalId`)
VALUES ('InvoiceInIntrastat','*','*','ALLOW','ROLE','employee');

View File

@ -2428,6 +2428,13 @@ INSERT INTO `vn`.`invoiceInTax` (`invoiceInFk`, `taxableBase`, `expenceFk`, `for
(6, 29.95, '7001000000', NULL, 7, 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`)
SELECT `id`
FROM `vn`.`ticket` t

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',
scope: {

View File

@ -8,6 +8,9 @@
"InvoiceInDueDay": {
"dataSource": "vn"
},
"InvoiceInIntrastat": {
"dataSource": "vn"
},
"InvoiceInLog": {
"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",
"foreignKey": "invoiceInFk"
},
"invoiceInIntrastat": {
"type": "hasMany",
"model": "InvoiceInIntrastat",
"foreignKey": "invoiceInFk"
},
"invoiceInTax": {
"type": "hasMany",
"model": "InvoiceInTax",

View File

@ -10,5 +10,6 @@ import './summary';
import './basic-data';
import './tax';
import './dueDay';
import './intrastat';
import './create';
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', () => {
vicent marked this conversation as resolved
Review

You missed the test where the actual purpose of the function is tested.

You missed the test where the actual purpose of the function is tested.
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
Invoice list: Listado de facturas recibidas
InvoiceIn booked: Factura contabilizada
Net: Neto
Remove tax: Quitar iva
Remove due day: Quitar vencimiento
Sage tax: Sage iva
Sage transaction: Sage transaccion
Search invoices in by reference: Buscar facturas recibidas por referencia
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",
"icon": "icon-calendar"
},
{
"state": "invoiceIn.card.intrastat",
"icon": "icon-lines"
},
{
"state": "invoiceIn.card.log",
"icon": "history"
@ -109,6 +113,16 @@
},
"acl": ["administrative"]
},
{
"url": "/intrastat",
"state": "invoiceIn.card.intrastat",
"component": "vn-invoice-in-intrastat",
"description": "Intrastat",
"params": {
"invoice-in": "$ctrl.invoiceIn"
},
"acl": ["administrative"]
},
{
"url": "/log",
"state": "invoiceIn.card.log",

View File

@ -120,6 +120,37 @@
</vn-table>
</vn-one>
</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-supplier-descriptor-popover
vn-id="supplierDescriptor">