Merge branch '2113-item_data_add_instrastat' of verdnatura/salix into dev
gitea/salix/dev This commit looks good
Details
gitea/salix/dev This commit looks good
Details
This commit is contained in:
commit
61b3ce184c
|
@ -0,0 +1,2 @@
|
|||
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||
VALUES ('Intrastat', '*', '*', 'ALLOW', 'ROLE', 'buyer');
|
|
@ -684,9 +684,15 @@ INSERT INTO `vn`.`taxCode`(`id`, `dated`, `code`, `taxTypeFk`, `rate`, `equaliza
|
|||
|
||||
INSERT INTO `vn`.`taxClass`(`id`, `description`, `code`)
|
||||
VALUES
|
||||
(1, 'Reduced VAT','R'),
|
||||
(1, 'Reduced VAT', 'R'),
|
||||
(2, 'General VAT', 'G');
|
||||
|
||||
INSERT INTO `vn`.`taxClassCode`(`taxClassFk`, `effectived`, `taxCodeFk`)
|
||||
VALUES
|
||||
(1, CURDATE(), 1),
|
||||
(1, CURDATE(), 21),
|
||||
(2, CURDATE(), 2);
|
||||
|
||||
INSERT INTO `vn`.`intrastat`(`id`, `description`, `taxClassFk`, `taxCodeFk`)
|
||||
VALUES
|
||||
(05080000, 'Coral y materiales similares', 2, 2),
|
||||
|
|
|
@ -262,6 +262,10 @@ export default {
|
|||
longName: 'vn-textfield[ng-model="$ctrl.item.longName"]',
|
||||
isActiveCheckbox: 'vn-check[label="Active"]',
|
||||
priceInKgCheckbox: 'vn-check[label="Price in kg"]',
|
||||
newIntrastatButton: 'vn-item-basic-data vn-icon-button[vn-tooltip="New intrastat"] > button',
|
||||
newIntrastatId: '.vn-dialog.shown vn-input-number[ng-model="$ctrl.newIntrastat.intrastatId"]',
|
||||
newIntrastatDescription: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.newIntrastat.description"]',
|
||||
acceptIntrastatButton: '.vn-dialog.shown button[response="accept"]',
|
||||
submitBasicDataButton: `button[type=submit]`
|
||||
},
|
||||
itemTags: {
|
||||
|
|
|
@ -39,6 +39,26 @@ describe('Item Edit basic data path', () => {
|
|||
expect(result).toEqual('Data saved!');
|
||||
}, 20000);
|
||||
|
||||
it(`should create a new intrastat`, async() => {
|
||||
await page.waitToClick(selectors.itemBasicData.newIntrastatButton);
|
||||
await page.write(selectors.itemBasicData.newIntrastatId, '588420239');
|
||||
await page.write(selectors.itemBasicData.newIntrastatDescription, 'Tropical Flowers');
|
||||
await page.waitToClick(selectors.itemBasicData.acceptIntrastatButton);
|
||||
await page.waitForTextInField(selectors.itemBasicData.intrastat, 'Tropical Flowers');
|
||||
let newcode = await page.waitToGetProperty(selectors.itemBasicData.intrastat, 'value');
|
||||
|
||||
expect(newcode).toEqual('588420239 Tropical Flowers');
|
||||
});
|
||||
|
||||
it(`should save with the new intrastat`, async() => {
|
||||
await page.waitFor(250);
|
||||
await page.waitForTextInField(selectors.itemBasicData.intrastat, 'Tropical Flowers');
|
||||
await page.waitToClick(selectors.itemBasicData.submitBasicDataButton);
|
||||
const result = await page.waitForLastSnackbar();
|
||||
|
||||
expect(result).toEqual('Data saved!');
|
||||
});
|
||||
|
||||
it(`should confirm the item name was edited`, async() => {
|
||||
await page.reloadSection('item.card.basicData');
|
||||
const result = await page.waitToGetProperty(selectors.itemBasicData.name, 'value');
|
||||
|
@ -53,11 +73,11 @@ describe('Item Edit basic data path', () => {
|
|||
expect(result).toEqual('Anthurium');
|
||||
});
|
||||
|
||||
it(`should confirm the item intrastad was edited`, async() => {
|
||||
it(`should confirm the item intrastat was edited`, async() => {
|
||||
const result = await page
|
||||
.waitToGetProperty(selectors.itemBasicData.intrastat, 'value');
|
||||
|
||||
expect(result).toEqual('5080000 Coral y materiales similares');
|
||||
expect(result).toEqual('588420239 Tropical Flowers');
|
||||
});
|
||||
|
||||
it(`should confirm the item relevancy was edited`, async() => {
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
let UserError = require('vn-loopback/util/user-error');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('createIntrastat', {
|
||||
description: 'Creates a new item intrastat',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'id',
|
||||
type: 'number',
|
||||
required: true,
|
||||
description: 'The item id',
|
||||
http: {source: 'path'}
|
||||
},
|
||||
{
|
||||
arg: 'intrastatId',
|
||||
type: 'number',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
arg: 'description',
|
||||
type: 'string',
|
||||
required: true
|
||||
}],
|
||||
returns: {
|
||||
type: 'boolean',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/:id/createIntrastat`,
|
||||
verb: 'PATCH'
|
||||
}
|
||||
});
|
||||
|
||||
Self.createIntrastat = async(id, intrastatId, description) => {
|
||||
const models = Self.app.models;
|
||||
const country = await models.Country.findOne({
|
||||
where: {code: 'ES'}
|
||||
});
|
||||
|
||||
const itemTaxCountry = await models.ItemTaxCountry.findOne({
|
||||
where: {
|
||||
itemFk: id,
|
||||
countryFk: country.id
|
||||
},
|
||||
order: 'effectived DESC'
|
||||
});
|
||||
const taxClassCode = await models.TaxClassCode.findOne({
|
||||
where: {
|
||||
taxClassFk: itemTaxCountry.taxClassFk
|
||||
},
|
||||
order: 'effectived DESC'
|
||||
});
|
||||
|
||||
return models.Intrastat.create({
|
||||
id: intrastatId,
|
||||
description: description,
|
||||
taxClassFk: itemTaxCountry.taxClassFk,
|
||||
taxCodeFk: taxClassCode.taxCodeFk
|
||||
});
|
||||
};
|
||||
};
|
|
@ -0,0 +1,22 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
describe('createIntrastat()', () => {
|
||||
let newIntrastat;
|
||||
|
||||
afterAll(async done => {
|
||||
await app.models.Intrastat.destroyById(newIntrastat.id);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
it('should create a new intrastat', async() => {
|
||||
const intrastatId = 588420239;
|
||||
const description = 'Tropical Flowers';
|
||||
const itemId = 9;
|
||||
newIntrastat = await app.models.Item.createIntrastat(itemId, intrastatId, description);
|
||||
|
||||
expect(newIntrastat.description).toEqual(description);
|
||||
expect(newIntrastat.taxClassFk).toEqual(1);
|
||||
expect(newIntrastat.taxCodeFk).toEqual(21);
|
||||
});
|
||||
});
|
|
@ -62,6 +62,9 @@
|
|||
"TaxClass": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"TaxClassCode": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"TaxCode": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
|
|
|
@ -12,6 +12,7 @@ module.exports = Self => {
|
|||
require('../methods/item/getVisibleAvailable')(Self);
|
||||
require('../methods/item/new')(Self);
|
||||
require('../methods/item/getWasteDetail')(Self);
|
||||
require('../methods/item/createIntrastat')(Self);
|
||||
|
||||
Self.validatesPresenceOf('originFk', {message: 'Cannot be blank'});
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
{
|
||||
"name": "Item",
|
||||
"base": "Loggable",
|
||||
"log": {
|
||||
"model":"ItemLog",
|
||||
"base": "Loggable",
|
||||
"log": {
|
||||
"model": "ItemLog",
|
||||
"showField": "id"
|
||||
},
|
||||
},
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "item"
|
||||
"table": "item"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
@ -125,55 +125,55 @@
|
|||
}
|
||||
},
|
||||
"relations": {
|
||||
"itemType": {
|
||||
"type": "belongsTo",
|
||||
"model": "ItemType",
|
||||
"foreignKey": "typeFk"
|
||||
},
|
||||
"ink": {
|
||||
"type": "belongsTo",
|
||||
"model": "Ink",
|
||||
"foreignKey": "inkFk"
|
||||
},
|
||||
"origin": {
|
||||
"type": "belongsTo",
|
||||
"model": "Origin",
|
||||
"foreignKey": "originFk"
|
||||
},
|
||||
"producer": {
|
||||
"type": "belongsTo",
|
||||
"model": "Producer",
|
||||
"foreignKey": "producerFk"
|
||||
},
|
||||
"intrastat": {
|
||||
"type": "belongsTo",
|
||||
"model": "Intrastat",
|
||||
"foreignKey": "intrastatFk"
|
||||
},
|
||||
"expense": {
|
||||
"type": "belongsTo",
|
||||
"model": "Expense",
|
||||
"foreignKey": "expenseFk"
|
||||
},
|
||||
"tags": {
|
||||
"type": "hasMany",
|
||||
"model": "ItemTag",
|
||||
"foreignKey": "itemFk"
|
||||
},
|
||||
"itemBarcode": {
|
||||
"type": "hasMany",
|
||||
"model": "ItemBarcode",
|
||||
"foreignKey": "itemFk"
|
||||
},
|
||||
"taxes": {
|
||||
"type": "hasMany",
|
||||
"model": "ItemTaxCountry",
|
||||
"foreignKey": "itemFk"
|
||||
},
|
||||
"itemNiche": {
|
||||
"type": "hasMany",
|
||||
"model": "ItemNiche",
|
||||
"foreignKey": "itemFk"
|
||||
}
|
||||
"itemType": {
|
||||
"type": "belongsTo",
|
||||
"model": "ItemType",
|
||||
"foreignKey": "typeFk"
|
||||
},
|
||||
"ink": {
|
||||
"type": "belongsTo",
|
||||
"model": "Ink",
|
||||
"foreignKey": "inkFk"
|
||||
},
|
||||
"origin": {
|
||||
"type": "belongsTo",
|
||||
"model": "Origin",
|
||||
"foreignKey": "originFk"
|
||||
},
|
||||
"producer": {
|
||||
"type": "belongsTo",
|
||||
"model": "Producer",
|
||||
"foreignKey": "producerFk"
|
||||
},
|
||||
"intrastat": {
|
||||
"type": "belongsTo",
|
||||
"model": "Intrastat",
|
||||
"foreignKey": "intrastatFk"
|
||||
},
|
||||
"expense": {
|
||||
"type": "belongsTo",
|
||||
"model": "Expense",
|
||||
"foreignKey": "expenseFk"
|
||||
},
|
||||
"tags": {
|
||||
"type": "hasMany",
|
||||
"model": "ItemTag",
|
||||
"foreignKey": "itemFk"
|
||||
},
|
||||
"itemBarcode": {
|
||||
"type": "hasMany",
|
||||
"model": "ItemBarcode",
|
||||
"foreignKey": "itemFk"
|
||||
},
|
||||
"taxes": {
|
||||
"type": "hasMany",
|
||||
"model": "ItemTaxCountry",
|
||||
"foreignKey": "itemFk"
|
||||
},
|
||||
"itemNiche": {
|
||||
"type": "hasMany",
|
||||
"model": "ItemNiche",
|
||||
"foreignKey": "itemFk"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
{
|
||||
"name": "TaxClassCode",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "taxClassCode"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"taxClassFk": {
|
||||
"type": "number",
|
||||
"required": true,
|
||||
"id": 1
|
||||
},
|
||||
"taxCodeFk": {
|
||||
"type": "number",
|
||||
"required": true,
|
||||
"id": 2
|
||||
},
|
||||
"effectived": {
|
||||
"type": "date",
|
||||
"required": true,
|
||||
"id": 3
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
"taxClass": {
|
||||
"type": "belongsTo",
|
||||
"model": "TaxClass",
|
||||
"foreignKey": "taxClassFk"
|
||||
},
|
||||
"taxCode": {
|
||||
"type": "belongsTo",
|
||||
"model": "TaxCode",
|
||||
"foreignKey": "taxCodeFk"
|
||||
}
|
||||
},
|
||||
"acls": [
|
||||
{
|
||||
"accessType": "READ",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$everyone",
|
||||
"permission": "ALLOW"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`vnItemBasicData Component vnItemBasicData $onChanges() should pass the data to the watcher 1`] = `"the current value of an item"`;
|
|
@ -55,6 +55,13 @@
|
|||
<div style="width: 6em; text-align: right; padding-right: 1em;">{{::id}}</div>
|
||||
<div>{{::description}}</div>
|
||||
</tpl-item>
|
||||
<append>
|
||||
<vn-icon-button
|
||||
icon="add_circle"
|
||||
vn-tooltip="New intrastat"
|
||||
ng-click="$ctrl.showIntrastat($event)">
|
||||
</vn-icon-button>
|
||||
</append>
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete vn-one
|
||||
url="Expenses"
|
||||
|
@ -69,7 +76,7 @@
|
|||
value-field="id"
|
||||
ng-model="$ctrl.item.originFk"
|
||||
initial-data="$ctrl.item.origin">
|
||||
</vn-autocomplete>
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
|
@ -123,7 +130,7 @@
|
|||
</vn-check>
|
||||
<vn-textarea
|
||||
vn-one
|
||||
label="description"
|
||||
label="Description"
|
||||
ng-model="$ctrl.item.description"
|
||||
rule>
|
||||
</vn-textarea>
|
||||
|
@ -134,3 +141,30 @@
|
|||
<vn-button label="Undo changes" ng-if="$ctrl.$scope.form.$dirty" ng-click="watcher.loadOriginalData()"></vn-button>
|
||||
</vn-button-bar>
|
||||
</form>
|
||||
|
||||
<!-- Create custom agent dialog -->
|
||||
<vn-dialog class="edit"
|
||||
vn-id="intrastat"
|
||||
on-accept="$ctrl.onIntrastatAccept()">
|
||||
<tpl-body>
|
||||
<h5 class="vn-py-sm" translate>New intrastat</h5>
|
||||
<vn-horizontal>
|
||||
<vn-input-number vn-one vn-focus
|
||||
label="Identifier"
|
||||
ng-model="$ctrl.newIntrastat.intrastatId"
|
||||
required="true">
|
||||
</vn-input-number>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one
|
||||
label="Description"
|
||||
ng-model="$ctrl.newIntrastat.description"
|
||||
required="true">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
</tpl-body>
|
||||
<tpl-buttons>
|
||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
||||
<button response="accept" translate>Create</button>
|
||||
</tpl-buttons>
|
||||
</vn-dialog>
|
|
@ -1,20 +1,23 @@
|
|||
import ngModule from '../module';
|
||||
import Component from 'core/lib/component';
|
||||
class Controller extends Component {
|
||||
showIntrastat(event) {
|
||||
if (event.defaultPrevented) return;
|
||||
event.preventDefault();
|
||||
|
||||
class Controller {
|
||||
constructor($scope, $timeout) {
|
||||
this.$scope = $scope;
|
||||
this.$timeout = $timeout;
|
||||
this.newIntrastat = {
|
||||
taxClassFk: this.item.taxClassFk
|
||||
};
|
||||
this.$.intrastat.show();
|
||||
}
|
||||
|
||||
$onChanges(data) {
|
||||
this.$timeout(() => {
|
||||
this.$scope.watcher.data = data.item.currentValue;
|
||||
});
|
||||
onIntrastatAccept() {
|
||||
const query = `Items/${this.$params.id}/createIntrastat`;
|
||||
return this.$http.patch(query, this.newIntrastat)
|
||||
.then(res => this.item.intrastatFk = res.data.id);
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$scope', '$timeout'];
|
||||
|
||||
ngModule.component('vnItemBasicData', {
|
||||
template: require('./index.html'),
|
||||
bindings: {
|
||||
|
|
|
@ -2,26 +2,31 @@ import './index.js';
|
|||
|
||||
describe('vnItemBasicData', () => {
|
||||
describe('Component vnItemBasicData', () => {
|
||||
let $httpBackend;
|
||||
let $scope;
|
||||
let controller;
|
||||
let $timeout;
|
||||
let $element;
|
||||
|
||||
beforeEach(ngModule('item'));
|
||||
|
||||
beforeEach(angular.mock.inject(($componentController, $rootScope, _$timeout_) => {
|
||||
$timeout = _$timeout_;
|
||||
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
$scope = $rootScope.$new();
|
||||
controller = $componentController('vnItemBasicData', {$scope, $timeout});
|
||||
controller.$scope.watcher = {};
|
||||
$element = angular.element('<vn-item-basic-data></vn-item-basic-data>');
|
||||
controller = $componentController('vnItemBasicData', {$element, $scope});
|
||||
controller.$.watcher = {};
|
||||
controller.$params.id = 1;
|
||||
controller.item = {id: 1, name: 'Rainbow Coral'};
|
||||
}));
|
||||
|
||||
describe('$onChanges()', () => {
|
||||
describe('onIntrastatAccept()', () => {
|
||||
it('should pass the data to the watcher', () => {
|
||||
const data = {item: {currentValue: 'the current value of an item'}};
|
||||
controller.$onChanges(data);
|
||||
$timeout.flush();
|
||||
const newIntrastatId = 20;
|
||||
$httpBackend.expect('PATCH', 'Items/1/createIntrastat').respond({id: 20});
|
||||
controller.onIntrastatAccept();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.$scope.watcher.data).toMatchSnapshot();
|
||||
expect(controller.item.intrastatFk).toEqual(newIntrastatId);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,3 +6,5 @@ Full name calculates based on tags 1-3. Is not recommended to change it manually
|
|||
Is active: Activo
|
||||
Expense: Gasto
|
||||
Price in kg: Precio en kg
|
||||
New intrastat: Nuevo intrastat
|
||||
Identifier: Identificador
|
Loading…
Reference in New Issue