removed unused routes, filter and crud routes #409
This commit is contained in:
parent
eba193999c
commit
f3fc211dfa
|
@ -1,9 +0,0 @@
|
|||
import FilterList from 'core/src/lib/filter-list';
|
||||
|
||||
export default class FilterClientList extends FilterList {
|
||||
constructor($scope, $timeout, $state) {
|
||||
super($scope, $timeout, $state);
|
||||
this.modelName = 'clientFk';
|
||||
}
|
||||
}
|
||||
FilterClientList.$inject = ['$scope', '$timeout', '$state'];
|
|
@ -1,45 +0,0 @@
|
|||
/**
|
||||
* Generic class to list models.
|
||||
*/
|
||||
export default class FilterList {
|
||||
constructor($scope, $timeout, $state) {
|
||||
this.$ = $scope;
|
||||
this.$timeout = $timeout;
|
||||
this.$state = $state;
|
||||
|
||||
this.waitingMgCrud = 0;
|
||||
this.modelId = $state.params.id;
|
||||
this.instances = [];
|
||||
}
|
||||
onOrder(field, order) {
|
||||
this.filter(`${field} ${order}`);
|
||||
}
|
||||
filter(order) {
|
||||
if (this.$.index && this.modelId && this.modelName) {
|
||||
this.waitingMgCrud = 0;
|
||||
this.$.index.filter = {
|
||||
page: 1,
|
||||
size: 10
|
||||
};
|
||||
|
||||
this.$.index.filter[this.modelName] = this.modelId;
|
||||
|
||||
if (order) {
|
||||
this.$.index.filter.order = order;
|
||||
}
|
||||
|
||||
this.$.index.accept().then(res => {
|
||||
this.instances = res.instances;
|
||||
});
|
||||
} else if (!this.modelId || !this.modelName) {
|
||||
throw new Error('Error: model not found');
|
||||
} else if (this.waitingMgCrud > 3) {
|
||||
throw new Error('Error: Magic Crud is not loaded');
|
||||
} else {
|
||||
this.waitingMgCrud++;
|
||||
this.$timeout(() => {
|
||||
this.filter(order);
|
||||
}, 250);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,6 @@ import './app';
|
|||
import './interceptor';
|
||||
import './acl-service';
|
||||
import './storage-services';
|
||||
import './filter-list';
|
||||
import './template';
|
||||
import './spliting-register';
|
||||
import './interpolate';
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
import FilterList from 'core/src/lib/filter-list';
|
||||
|
||||
export default class FilterItemList extends FilterList {
|
||||
constructor($scope, $timeout, $state) {
|
||||
super($scope, $timeout, $state);
|
||||
this.modelName = 'itemFk';
|
||||
}
|
||||
}
|
||||
FilterItemList.$inject = ['$scope', '$timeout', '$state'];
|
|
@ -1,7 +1,6 @@
|
|||
export * from './module';
|
||||
|
||||
import './index';
|
||||
import './filter-item-list';
|
||||
import './search-panel';
|
||||
import './diary';
|
||||
import './create';
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
<mg-ajax path="/ticket/api/Sales/saleComponentFilter" options="vnIndexNonAuto" actions="$ctrl.sales = index.model.instances"></mg-ajax>
|
||||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="/ticket/api/Sales"
|
||||
link="{ticketFk: $ctrl.$stateParams.id}"
|
||||
filter="::$ctrl.filter"
|
||||
data="components">
|
||||
</vn-crud-model>
|
||||
<vn-vertical>
|
||||
<vn-card pad-large>
|
||||
<vn-vertical>
|
||||
|
@ -32,7 +38,7 @@
|
|||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
<tbody ng-repeat="sale in $ctrl.sales track by sale.id">
|
||||
<tbody ng-repeat="sale in components track by sale.id">
|
||||
<tr>
|
||||
<td rowspan="{{
|
||||
::sale.components.length + 1
|
||||
|
@ -61,13 +67,13 @@
|
|||
first: $index == 0,last: $index == sale.components.length - 1
|
||||
}" number>{{::sale.quantity * component.value | currency:'€':3}}</td>
|
||||
</tr>
|
||||
<tr ng-if="index.model.count === 0" class="list list-element">
|
||||
<tr ng-if="model.data.length === 0" class="list list-element">
|
||||
<td colspan="7" style="text-align: center" translate>No results</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</vn-vertical>
|
||||
<vn-paging vn-one margin-large-top index="index" total="index.model.count"></vn-paging>
|
||||
<!-- <vn-paging vn-one margin-large-top index="index" total="index.model.count"></vn-paging> -->
|
||||
</vn-card>
|
||||
</vn-vertical>
|
||||
<vn-item-descriptor-popover vn-id="descriptor"></vn-item-descriptor-popover>
|
||||
|
|
|
@ -1,46 +1,89 @@
|
|||
import ngModule from '../module';
|
||||
import './style.scss';
|
||||
import FilterTicketList from '../filter-ticket-list';
|
||||
|
||||
class Controller extends FilterTicketList {
|
||||
constructor($scope, $timeout, $stateParams) {
|
||||
super($scope, $timeout, $stateParams);
|
||||
class Controller {
|
||||
constructor($scope, $stateParams) {
|
||||
this.$stateParams = $stateParams;
|
||||
this.$scope = $scope;
|
||||
this.onOrder('itemFk', 'ASC');
|
||||
this.filter = {
|
||||
order: 'concept ASC',
|
||||
include: [{
|
||||
relation: 'item',
|
||||
scope: {
|
||||
include: {
|
||||
relation: 'tags',
|
||||
scope: {
|
||||
fields: ['tagFk', 'value'],
|
||||
include: {
|
||||
relation: 'tag',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
},
|
||||
limit: 6
|
||||
}
|
||||
},
|
||||
fields: ['itemFk', 'name']
|
||||
}
|
||||
},
|
||||
{
|
||||
relation: 'components',
|
||||
scope: {
|
||||
fields: ['componentFk', 'value'],
|
||||
include: {
|
||||
relation: 'componentRate',
|
||||
scope: {
|
||||
fields: ['componentTypeRate', 'name'],
|
||||
include: {
|
||||
relation: 'componentType',
|
||||
scope: {
|
||||
fields: ['type']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
total() {
|
||||
let sum;
|
||||
if (this.sales) {
|
||||
sum = 0;
|
||||
for (let sale of this.sales)
|
||||
for (let component of sale.components)
|
||||
sum += sale.quantity * component.value;
|
||||
}
|
||||
let sales = this.$scope.model.data;
|
||||
let sum = 0;
|
||||
if (!sales) return;
|
||||
|
||||
for (let sale of sales)
|
||||
for (let component of sale.components)
|
||||
sum += sale.quantity * component.value;
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
base() {
|
||||
let sum;
|
||||
if (this.sales) {
|
||||
sum = 0;
|
||||
for (let sale of this.sales)
|
||||
for (let component of sale.components)
|
||||
if (component.componentRate.name == 'valor de compra')
|
||||
sum += sale.quantity * component.value;
|
||||
}
|
||||
let sales = this.$scope.model.data;
|
||||
let sum = 0;
|
||||
|
||||
if (!sales) return;
|
||||
|
||||
for (let sale of sales)
|
||||
for (let component of sale.components)
|
||||
if (component.componentRate.name == 'valor de compra')
|
||||
sum += sale.quantity * component.value;
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
profitMargin() {
|
||||
let sum;
|
||||
if (this.sales) {
|
||||
sum = 0;
|
||||
for (let sale of this.sales)
|
||||
for (let component of sale.components)
|
||||
if (component.componentRate.name != 'valor de compra')
|
||||
sum += sale.quantity * component.value;
|
||||
}
|
||||
let sales = this.$scope.model.data;
|
||||
let sum = 0;
|
||||
|
||||
if (!sales) return;
|
||||
|
||||
for (let sale of sales)
|
||||
for (let component of sale.components)
|
||||
if (component.componentRate.name != 'valor de compra')
|
||||
sum += sale.quantity * component.value;
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
@ -55,7 +98,7 @@ class Controller extends FilterTicketList {
|
|||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$scope', '$timeout', '$state'];
|
||||
Controller.$inject = ['$scope', '$stateParams'];
|
||||
|
||||
ngModule.component('vnTicketComponents', {
|
||||
template: require('./index.html'),
|
||||
|
|
|
@ -1,41 +1,44 @@
|
|||
import './index.js';
|
||||
import {crudModel} from '../../../helpers/crudModelHelper';
|
||||
|
||||
describe('ticket', () => {
|
||||
describe('Component vnTicketComponents', () => {
|
||||
let $componentController;
|
||||
let $state;
|
||||
let $scope;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('ticket');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, _$state_) => {
|
||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$state_) => {
|
||||
$componentController = _$componentController_;
|
||||
$state = _$state_;
|
||||
$state.params.id = '1';
|
||||
controller = $componentController('vnTicketComponents');
|
||||
$scope = $rootScope.$new();
|
||||
$scope.model = crudModel;
|
||||
$scope.model.data = [{
|
||||
components: [
|
||||
{componentRate: {name: 'valor de compra'}, value: 5},
|
||||
{componentRate: {name: 'reparto'}, value: 5},
|
||||
{componentRate: {name: 'recobro'}, value: 5}
|
||||
],
|
||||
quantity: 1
|
||||
},
|
||||
{
|
||||
components: [
|
||||
{componentRate: {name: 'valor de compra'}, value: 1},
|
||||
{componentRate: {name: 'reparto'}, value: 1},
|
||||
{componentRate: {name: 'recobro'}, value: 1}
|
||||
],
|
||||
quantity: 5
|
||||
}];
|
||||
controller = $componentController('vnTicketComponents', {$scope});
|
||||
}));
|
||||
|
||||
describe('total()', () => {
|
||||
it('should return the sum from all componenets in each sale', () => {
|
||||
controller.sales = [{
|
||||
components: [
|
||||
{componentRate: {name: 'valor de compra'}, value: 5},
|
||||
{componentRate: {name: 'reparto'}, value: 5},
|
||||
{componentRate: {name: 'recobro'}, value: 5}
|
||||
],
|
||||
quantity: 1
|
||||
},
|
||||
{
|
||||
components: [
|
||||
{componentRate: {name: 'valor de compra'}, value: 1},
|
||||
{componentRate: {name: 'reparto'}, value: 1},
|
||||
{componentRate: {name: 'recobro'}, value: 1}
|
||||
],
|
||||
quantity: 5
|
||||
}
|
||||
];
|
||||
let result = controller.total();
|
||||
|
||||
expect(result).toEqual(30);
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
import FilterList from 'core/src/lib/filter-list';
|
||||
|
||||
export default class FilterTicketList extends FilterList {
|
||||
constructor($scope, $timeout, $state) {
|
||||
super($scope, $timeout, $state);
|
||||
this.modelName = 'ticketFk';
|
||||
}
|
||||
}
|
||||
FilterTicketList.$inject = ['$scope', '$timeout', '$state'];
|
|
@ -2,7 +2,8 @@
|
|||
import Nightmare from 'nightmare';
|
||||
|
||||
export default function createNightmare(width = 1280, height = 720) {
|
||||
const nightmare = new Nightmare({show: false, typeInterval: 10, x: 0, y: 0}).viewport(width, height);
|
||||
const nightmare = new Nightmare({show: process.env.E2E_SHOW, typeInterval: 10, x: 0, y: 0})
|
||||
.viewport(width, height);
|
||||
|
||||
nightmare.on('page', (type, message, error) => {
|
||||
fail(error);
|
||||
|
|
|
@ -50,8 +50,10 @@ describe('Client', () => {
|
|||
return nightmare
|
||||
.waitToClick(selectors.clientPayMethod.payMethodInput)
|
||||
.waitToClick(selectors.clientPayMethod.payMethodIBANOption)
|
||||
.waitForTextInInput(selectors.clientPayMethod.payMethodInput, 'PayMethod with IBAN')
|
||||
.clearInput(selectors.clientPayMethod.dueDayInput)
|
||||
.type(selectors.clientPayMethod.dueDayInput, '60')
|
||||
.waitForTextInInput(selectors.clientPayMethod.dueDayInput, '60')
|
||||
.waitToClick(selectors.clientPayMethod.receivedCoreLCRCheckbox)
|
||||
.waitToClick(selectors.clientPayMethod.receivedCoreVNLCheckbox)
|
||||
.waitToClick(selectors.clientPayMethod.receivedB2BVNLCheckbox)
|
||||
|
@ -66,6 +68,7 @@ describe('Client', () => {
|
|||
return nightmare
|
||||
.clearInput(selectors.clientPayMethod.IBANInput)
|
||||
.type(selectors.clientPayMethod.IBANInput, 'ES91 2100 0418 4502 0005 1332')
|
||||
.waitForTextInInput(selectors.clientPayMethod.IBANInput, 'ES91 2100 0418 4502 0005 1332')
|
||||
.waitToClick(selectors.clientPayMethod.saveButton)
|
||||
.waitForSnackbar()
|
||||
.then(result => {
|
||||
|
|
|
@ -71,6 +71,9 @@ gulp.task('services-only', async () => {
|
|||
* Runs the e2e tests, restoring the fixtures first.
|
||||
*/
|
||||
gulp.task('e2e', ['docker'], async () => {
|
||||
if (argv.show || argv.s)
|
||||
process.env.E2E_SHOW = true;
|
||||
|
||||
await runSequenceP('e2e-only');
|
||||
});
|
||||
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
module.exports = Self => {
|
||||
Self.installMethod('filter', filterParams);
|
||||
|
||||
function filterParams(params) {
|
||||
return {
|
||||
where: {
|
||||
clientFk: params.clientFk
|
||||
},
|
||||
skip: (params.page - 1) * params.size,
|
||||
limit: params.size,
|
||||
order: params.order || 'created DESC',
|
||||
include: {
|
||||
relation: "worker",
|
||||
scope: {
|
||||
fields: ["id", "firstName", "name"]
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
|
@ -1,3 +0,0 @@
|
|||
module.exports = Self => {
|
||||
Self.installCrudModel('crudItemBarcodes');
|
||||
};
|
|
@ -1,72 +0,0 @@
|
|||
// const crudItemBarcodes = require('../crudItemBarcodes');
|
||||
// const catchErrors = require('../../../../../../services/utils/jasmineHelpers').catchErrors;
|
||||
// let mysql = require('mysql2');
|
||||
|
||||
// describe('Item crudItemBarcodes()', () => {
|
||||
// let connection;
|
||||
// beforeAll(() => {
|
||||
// connection = mysql.createConnection({
|
||||
// multipleStatements: true,
|
||||
// host: 'localhost',
|
||||
// user: 'root',
|
||||
// password: '',
|
||||
// database: 'salix'
|
||||
// });
|
||||
// });
|
||||
|
||||
// it('should call the destroyAll methodif there are ids in delete Array', done => {
|
||||
// let self = jasmine.createSpyObj('self', ['remoteMethod', 'crudItemBarcodes', 'destroyAll', 'create', 'upsert']);
|
||||
|
||||
// crudItemBarcodes(self);
|
||||
// self.crudItemBarcodes({
|
||||
// delete: [1],
|
||||
// create: [],
|
||||
// update: []
|
||||
// }).then(result => {
|
||||
// expect(self.destroyAll).toHaveBeenCalledWith({id: {inq: [1]}});
|
||||
// done();
|
||||
// })
|
||||
// .catch(catchErrors(done));
|
||||
// });
|
||||
|
||||
// it('should call the create method if there are ids in create Array', done => {
|
||||
// let self = jasmine.createSpyObj('self', ['remoteMethod', 'crudItemBarcodes', 'destroyAll', 'create', 'upsert']);
|
||||
|
||||
// crudItemBarcodes(self);
|
||||
// self.crudItemBarcodes({
|
||||
// delete: [],
|
||||
// create: [1],
|
||||
// update: []
|
||||
// }).then(result => {
|
||||
// expect(self.create).toHaveBeenCalledWith([1]);
|
||||
// done();
|
||||
// })
|
||||
// .catch(catchErrors(done));
|
||||
// });
|
||||
|
||||
// it('should call the upsert method as many times as ids in update Array', done => {
|
||||
// let self = jasmine.createSpyObj('self', ['remoteMethod', 'crudItemBarcodes', 'destroyAll', 'create', 'upsert']);
|
||||
|
||||
// crudItemBarcodes(self);
|
||||
// self.crudItemBarcodes({
|
||||
// delete: [],
|
||||
// create: [],
|
||||
// update: [1, 2]
|
||||
// }).then(result => {
|
||||
// expect(self.upsert).toHaveBeenCalledWith(1);
|
||||
// expect(self.upsert).toHaveBeenCalledWith(2);
|
||||
// expect(self.upsert.calls.count()).toEqual(2);
|
||||
// done();
|
||||
// })
|
||||
// .catch(catchErrors(done));
|
||||
// });
|
||||
|
||||
// it('should return an error when attempting to save a duplicated barcode', done => {
|
||||
// let callback = (err, res) => {
|
||||
// expect(err.toString()).toBe("Error: Duplicate entry '4' for key 'PRIMARY'");
|
||||
// done();
|
||||
// };
|
||||
|
||||
// connection.query('INSERT INTO `vn`.`itemBarcode` VALUES (4, 2 ,4 );', callback);
|
||||
// });
|
||||
// });
|
|
@ -1,3 +0,0 @@
|
|||
module.exports = Self => {
|
||||
Self.installCrudModel('crudItemNiches');
|
||||
};
|
|
@ -1,51 +0,0 @@
|
|||
// const crudItemNiches = require('../crudItemNiches');
|
||||
// const catchErrors = require('../../../../../../services/utils/jasmineHelpers').catchErrors;
|
||||
|
||||
// describe('Item crudItemNiches()', () => {
|
||||
// it('should call the destroyAll method if there are ids in delete Array', done => {
|
||||
// let self = jasmine.createSpyObj('self', ['remoteMethod', 'crudItemNiches', 'destroyAll', 'create', 'upsert']);
|
||||
|
||||
// crudItemNiches(self);
|
||||
// self.crudItemNiches({
|
||||
// delete: [1],
|
||||
// create: [],
|
||||
// update: []
|
||||
// }).then(result => {
|
||||
// expect(self.destroyAll).toHaveBeenCalledWith({id: {inq: [1]}});
|
||||
// done();
|
||||
// })
|
||||
// .catch(catchErrors(done));
|
||||
// });
|
||||
|
||||
// it('should call the create method if there are ids in create Array', done => {
|
||||
// let self = jasmine.createSpyObj('self', ['remoteMethod', 'crudItemNiches', 'destroyAll', 'create', 'upsert']);
|
||||
|
||||
// crudItemNiches(self);
|
||||
// self.crudItemNiches({
|
||||
// delete: [],
|
||||
// create: [1],
|
||||
// update: []
|
||||
// }).then(result => {
|
||||
// expect(self.create).toHaveBeenCalledWith([1]);
|
||||
// done();
|
||||
// })
|
||||
// .catch(catchErrors(done));
|
||||
// });
|
||||
|
||||
// it('should call the upsert method as many times as ids in update Array', done => {
|
||||
// let self = jasmine.createSpyObj('self', ['remoteMethod', 'crudItemNiches', 'destroyAll', 'create', 'upsert']);
|
||||
|
||||
// crudItemNiches(self);
|
||||
// self.crudItemNiches({
|
||||
// delete: [],
|
||||
// create: [],
|
||||
// update: [1, 2]
|
||||
// }).then(result => {
|
||||
// expect(self.upsert).toHaveBeenCalledWith(1);
|
||||
// expect(self.upsert).toHaveBeenCalledWith(2);
|
||||
// expect(self.upsert.calls.count()).toEqual(2);
|
||||
// done();
|
||||
// })
|
||||
// .catch(catchErrors(done));
|
||||
// });
|
||||
// });
|
|
@ -1,6 +1,4 @@
|
|||
module.exports = Self => {
|
||||
require('../methods/item-barcode/crudItemBarcodes')(Self);
|
||||
|
||||
Self.validatesUniquenessOf('code', {
|
||||
message: `Barcode must be unique`
|
||||
});
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
module.exports = Self => {
|
||||
Self.installMethod('filter', filterParams);
|
||||
|
||||
function filterParams(params) {
|
||||
return {
|
||||
where: {
|
||||
ticketFk: params.ticketFk
|
||||
},
|
||||
skip: (params.page - 1) * params.size,
|
||||
limit: params.size,
|
||||
order: params.order || 'concept ASC',
|
||||
include: [{
|
||||
relation: 'item',
|
||||
scope: {
|
||||
include: {
|
||||
relation: 'tags',
|
||||
scope: {
|
||||
fields: ['tagFk', 'value'],
|
||||
include: {
|
||||
relation: 'tag',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
},
|
||||
limit: 6
|
||||
}
|
||||
},
|
||||
fields: ['itemFk', 'name']
|
||||
}
|
||||
},
|
||||
{
|
||||
relation: 'isChecked',
|
||||
scope: {
|
||||
fields: ['isChecked']
|
||||
}
|
||||
}]
|
||||
};
|
||||
}
|
||||
};
|
|
@ -1,51 +0,0 @@
|
|||
module.exports = Self => {
|
||||
Self.installMethod('saleComponentFilter', filterParams);
|
||||
|
||||
function filterParams(params) {
|
||||
return {
|
||||
where: {
|
||||
ticketFk: params.ticketFk
|
||||
},
|
||||
skip: (params.page - 1) * params.size,
|
||||
limit: params.size,
|
||||
order: params.order || 'concept ASC',
|
||||
include: [{
|
||||
relation: 'item',
|
||||
scope: {
|
||||
include: {
|
||||
relation: 'tags',
|
||||
scope: {
|
||||
fields: ['tagFk', 'value'],
|
||||
include: {
|
||||
relation: 'tag',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
},
|
||||
limit: 6
|
||||
}
|
||||
},
|
||||
fields: ['itemFk', 'name']
|
||||
}
|
||||
},
|
||||
{
|
||||
relation: 'components',
|
||||
scope: {
|
||||
fields: ['componentFk', 'value'],
|
||||
include: {
|
||||
relation: 'componentRate',
|
||||
scope: {
|
||||
fields: ['componentTypeRate', 'name'],
|
||||
include: {
|
||||
relation: 'componentType',
|
||||
scope: {
|
||||
fields: ['type']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}]
|
||||
};
|
||||
}
|
||||
};
|
|
@ -1,7 +1,5 @@
|
|||
module.exports = Self => {
|
||||
require('../methods/sale/filter')(Self);
|
||||
require('../methods/sale/getClaimableFromTicket')(Self);
|
||||
require('../methods/sale/saleComponentFilter')(Self);
|
||||
require('../methods/sale/priceDifference')(Self);
|
||||
require('../methods/sale/moveToTicket')(Self);
|
||||
require('../methods/sale/reserve')(Self);
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
module.exports = Self => {
|
||||
Self.installCrudModel('crudTicketObservation');
|
||||
};
|
|
@ -1,6 +1,4 @@
|
|||
module.exports = function(Self) {
|
||||
require('../methods/notes/crudTicketObservation.js')(Self);
|
||||
|
||||
/* Self.validateAsync('observationTypeFk', validateObservationUniqueness, {
|
||||
message: `The observation type can't be repeated`
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue