claim upload pictures #1593
gitea/salix/dev This commit looks good Details

This commit is contained in:
Joan Sanchez 2019-07-30 08:51:38 +02:00
parent 46dac984ab
commit fb4ce77c01
37 changed files with 1072 additions and 47 deletions

View File

@ -0,0 +1,15 @@
CREATE TABLE `vn`.`claimDms` (
`claimFk` INT UNSIGNED NOT NULL,
`dmsFk` INT NOT NULL,
PRIMARY KEY (`claimFk`, `dmsFk`),
INDEX `dmsFk_idx` (`dmsFk` ASC),
CONSTRAINT `claimFk`
FOREIGN KEY (`claimFk`)
REFERENCES `vn2008`.`cl_main` (`id`)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT `dmsFk`
FOREIGN KEY (`dmsFk`)
REFERENCES `vn2008`.`gestdoc` (`id`)
ON DELETE CASCADE
ON UPDATE CASCADE);

View File

@ -0,0 +1,2 @@
ALTER TABLE `vn`.`claimLog`
CHANGE COLUMN `id` `id` INT(11) NOT NULL AUTO_INCREMENT ;

View File

@ -0,0 +1 @@
INSERT INTO `vn2008`.`gesttip` (`tipo`, `path`, `writeRoleFk`, `readRoleFk`, `code`) VALUES ('Reclamación', '', '18', '1', 'claim');

View File

@ -49,5 +49,7 @@
"This client can't be invoiced": "This client can't be invoiced",
"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"
"Concept cannot be blank": "Concept cannot be blank",
"Ticket id cannot be blank": "Ticket id cannot be blank",
"Weekday cannot be blank": "Weekday cannot be blank"
}

View File

@ -0,0 +1,33 @@
module.exports = Self => {
Self.remoteMethodCtx('removeFile', {
description: 'Removes a ticket document',
accessType: 'WRITE',
accepts: {
arg: 'id',
type: 'Number',
description: 'The document id',
http: {source: 'path'}
},
returns: {
type: 'Object',
root: true
},
http: {
path: `/:id/removeFile`,
verb: 'POST'
}
});
Self.removeFile = async(ctx, id) => {
const models = Self.app.models;
const targetClaimDms = await models.ClaimDms.findById(id);
const targetDms = await models.Dms.findById(targetClaimDms.dmsFk);
const trashDmsType = await models.DmsType.findOne({where: {code: 'trash'}});
await models.Dms.removeFile(ctx, targetClaimDms.dmsFk);
await targetClaimDms.destroy();
return targetDms.updateAttribute('dmsTypeFk', trashDmsType.id);
};
};

View File

@ -0,0 +1,18 @@
const app = require('vn-loopback/server/server');
describe('TicketDms removeFile()', () => {
const ticketDmsId = 1;
it(`should return an error for a user without enough privileges`, async() => {
let clientId = 101;
let ctx = {req: {accessToken: {userId: clientId}}};
let error;
await app.models.TicketDms.removeFile(ctx, ticketDmsId).catch(e => {
error = e;
}).finally(() => {
expect(error.message).toEqual(`You don't have enough privileges`);
});
expect(error).toBeDefined();
});
});

View File

@ -0,0 +1,78 @@
module.exports = Self => {
Self.remoteMethodCtx('uploadFile', {
description: 'Upload and attach a document',
accessType: 'WRITE',
accepts: [{
arg: 'id',
type: 'Number',
description: 'The claim id',
http: {source: 'path'}
},
{
arg: 'warehouseId',
type: 'Number',
description: ''
},
{
arg: 'companyId',
type: 'Number',
description: ''
},
{
arg: 'dmsTypeId',
type: 'Number',
description: ''
},
{
arg: 'reference',
type: 'String',
description: ''
},
{
arg: 'description',
type: 'String',
description: ''
},
{
arg: 'hasFile',
type: 'Boolean',
description: ''
}],
returns: {
type: 'Object',
root: true
},
http: {
path: `/:id/uploadFile`,
verb: 'POST'
}
});
Self.uploadFile = async(ctx, id) => {
const models = Self.app.models;
const promises = [];
const tx = await Self.beginTransaction({});
try {
const options = {transaction: tx};
const uploadedFiles = await models.Dms.uploadFile(ctx, options);
uploadedFiles.forEach(dms => {
const newClaimDms = models.ClaimDms.create({
claimFk: id,
dmsFk: dms.id
}, options);
promises.push(newClaimDms);
});
const resolvedPromises = await Promise.all(promises);
await tx.commit();
return resolvedPromises;
} catch (err) {
await tx.rollback();
throw err;
}
};
};

View File

@ -31,5 +31,11 @@
},
"ClaimState": {
"dataSource": "vn"
}
},
"ClaimDms": {
"dataSource": "vn"
},
"ClaimLog": {
"dataSource": "vn"
}
}

View File

@ -0,0 +1,3 @@
module.exports = Self => {
require('../methods/claim-dms/removeFile')(Self);
};

View File

@ -0,0 +1,32 @@
{
"name": "ClaimDms",
"base": "Loggable",
"log": {
"model": "ClaimLog",
"relation": "claim"
},
"options": {
"mysql": {
"table": "claimDms"
}
},
"properties": {
"dmsFk": {
"type": "Number",
"id": true,
"required": true
}
},
"relations": {
"claim": {
"type": "belongsTo",
"model": "Claim",
"foreignKey": "claimFk"
},
"dms": {
"type": "belongsTo",
"model": "Dms",
"foreignKey": "dmsFk"
}
}
}

View File

@ -0,0 +1,58 @@
{
"name": "ClaimLog",
"base": "VnModel",
"options": {
"mysql": {
"table": "claimLog"
}
},
"properties": {
"id": {
"id": true,
"type": "Number",
"forceId": false
},
"originFk": {
"type": "Number",
"required": true
},
"userFk": {
"type": "Number"
},
"action": {
"type": "String",
"required": true
},
"changedModel": {
"type": "String"
},
"oldInstance": {
"type": "Object"
},
"newInstance": {
"type": "Object"
},
"creationDate": {
"type": "Date"
},
"changedModelId": {
"type": "Number"
},
"changedModelValue": {
"type": "String"
},
"description": {
"type": "String"
}
},
"relations": {
"user": {
"type": "belongsTo",
"model": "Account",
"foreignKey": "userFk"
}
},
"scope": {
"order": ["creationDate DESC", "id DESC"]
}
}

View File

@ -1,7 +1,8 @@
module.exports = Self => {
require('../methods/claim/filter')(Self);
require('../methods/claim/getSummary')(Self);
require('../methods/claim/createFromSales')(Self);
require('../methods/claim/updateClaim')(Self);
require('../methods/claim/regularizeClaim')(Self);
require('../methods/claim/filter')(Self);
require('../methods/claim/uploadFile')(Self);
};

View File

@ -0,0 +1,64 @@
<vn-watcher
vn-id="watcher"
data="$ctrl.dms">
</vn-watcher>
<form name="form" ng-submit="$ctrl.onSubmit()" margin-medium enctype="multipart/form-data">
<div compact>
<vn-card pad-large>
<vn-horizontal>
<vn-textfield vn-one vn-focus
label="Reference"
field="$ctrl.dms.reference">
</vn-textfield>
<vn-autocomplete vn-one
label="Company"
field="$ctrl.dms.companyId"
url="/api/Companies"
show-field="code"
value-field="id">
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete vn-one
label="Warehouse"
field="$ctrl.dms.warehouseId"
url="/api/Warehouses"
show-field="name"
value-field="id">
</vn-autocomplete>
<vn-autocomplete vn-one
label="Type"
field="$ctrl.dms.dmsTypeId"
url="/api/DmsTypes"
show-field="name"
value-field="id">
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-textarea vn-one
label="Description"
field="$ctrl.dms.description">
</vn-textarea>
</vn-horizontal>
<vn-horizontal>
<vn-input-file vn-one
label="File"
model="$ctrl.dms.files"
on-change="$ctrl.onFileChange(files)"
accept=".png, .jpg, .jpeg"
multiple="true">
</vn-input-file>
</vn-horizontal>
<vn-vertical>
<vn-check
label="Generate identifier for original file"
field="$ctrl.dms.hasFile">
</vn-check>
</vn-vertical>
</vn-card>
<vn-button-bar>
<vn-submit label="Upload"></vn-submit>
<vn-button ui-sref="claim.card.dms.index" label="Cancel"></vn-button>
</vn-button-bar>
</div>
</form>

View File

@ -0,0 +1,100 @@
import ngModule from '../../module';
import './style.scss';
class Controller {
constructor($scope, $http, $state, $translate, vnApp) {
this.$ = $scope;
this.$http = $http;
this.$state = $state;
this.$translate = $translate;
this.vnApp = vnApp;
this.dms = {
files: [],
hasFile: false,
hasFileAttached: false
};
}
get claim() {
return this._claim;
}
set claim(value) {
this._claim = value;
if (value)
this.setDefaultParams();
}
setDefaultParams() {
const params = {filter: {
where: {code: 'claim'}
}};
this.$http.get('/api/DmsTypes/findOne', {params}).then(res => {
const dmsTypeId = res.data && res.data.id;
const companyId = window.localStorage.defaultCompanyFk;
const warehouseId = window.localStorage.defaultWarehouseFk;
const defaultParams = {
reference: this.claim.id,
warehouseId: warehouseId,
companyId: companyId,
dmsTypeId: dmsTypeId,
description: this.$translate.instant('FileDescription', {
claimId: this.claim.id,
clientId: this.claim.client.id,
clientName: this.claim.client.name
}).toUpperCase()
};
this.dms = Object.assign(this.dms, defaultParams);
});
}
onSubmit() {
const query = `/api/claims/${this.claim.id}/uploadFile`;
const options = {
method: 'POST',
url: query,
params: this.dms,
headers: {
'Content-Type': undefined
},
transformRequest: files => {
const formData = new FormData();
for (let i = 0; i < files.length; i++)
formData.append(files[i].name, files[i]);
return formData;
},
data: this.dms.files
};
this.$http(options).then(res => {
if (res) {
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
this.$.watcher.updateOriginalData();
this.$state.go('claim.card.dms.index');
}
});
}
onFileChange(files) {
let hasFileAttached = false;
if (files.length > 0)
hasFileAttached = true;
this.$.$applyAsync(() => {
this.dms.hasFileAttached = hasFileAttached;
});
}
}
Controller.$inject = ['$scope', '$http', '$state', '$translate', 'vnApp'];
ngModule.component('vnClaimDmsCreate', {
template: require('./index.html'),
controller: Controller,
bindings: {
claim: '<'
}
});

View File

@ -0,0 +1,66 @@
import './index';
describe('Claim', () => {
describe('Component vnClaimDmsCreate', () => {
let controller;
let $scope;
let $httpBackend;
let $httpParamSerializer;
beforeEach(ngModule('claim'));
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_, _$httpParamSerializer_) => {
$scope = $rootScope.$new();
$httpBackend = _$httpBackend_;
$httpParamSerializer = _$httpParamSerializer_;
controller = $componentController('vnClaimDmsCreate', {$scope});
controller._claim = {
id: 15,
client: {id: 101, name: 'Bruce wayne'},
ticketFk: 16
};
}));
describe('claim() setter', () => {
it('should set the claim data and then call setDefaultParams()', () => {
spyOn(controller, 'setDefaultParams');
controller._claim = undefined;
controller.claim = {
id: 15,
client: {id: 101, name: 'Bruce wayne'},
ticketFk: 16
};
expect(controller.claim).toBeDefined();
expect(controller.setDefaultParams).toHaveBeenCalledWith();
});
});
describe('setDefaultParams()', () => {
it('should perform a GET query and define the dms property on controller', () => {
const params = {filter: {
where: {code: 'claim'}
}};
let serializedParams = $httpParamSerializer(params);
$httpBackend.when('GET', `/api/DmsTypes/findOne?${serializedParams}`).respond({id: 14, code: 'claim'});
$httpBackend.expect('GET', `/api/DmsTypes/findOne?${serializedParams}`);
controller.setDefaultParams();
$httpBackend.flush();
expect(controller.dms).toBeDefined();
expect(controller.dms.reference).toEqual(15);
expect(controller.dms.dmsTypeId).toEqual(14);
});
});
describe('onFileChange()', () => {
it('should set dms hasFileAttached property to true if has any files', () => {
const files = [{id: 1, name: 'MyFile'}];
controller.onFileChange(files);
$scope.$apply();
expect(controller.dms.hasFileAttached).toBeTruthy();
});
});
});
});

View File

@ -0,0 +1 @@
FileDescription: Ticket id {{ticketId}} from client {{clientName}} id {{clientId}}

View File

@ -0,0 +1,5 @@
Upload file: Subir fichero
Upload: Subir
File: Fichero
FileDescription: Reclamación id {{claimId}} del cliente "{{clientName}}" id {{clientId}}
Generate identifier for original file: Generar identificador para archivo original

View File

@ -0,0 +1,7 @@
vn-ticket-request {
vn-textfield {
margin: 0!important;
max-width: 100px;
}
}

View File

@ -0,0 +1,63 @@
<vn-watcher
vn-id="watcher"
data="$ctrl.dms">
</vn-watcher>
<form name="form" ng-submit="$ctrl.onSubmit()" margin-medium enctype="multipart/form-data">
<div compact>
<vn-card pad-large>
<vn-horizontal>
<vn-textfield vn-one vn-focus
label="Reference"
field="$ctrl.dms.reference">
</vn-textfield>
<vn-autocomplete vn-one required="true"
label="Company"
field="$ctrl.dms.companyId"
url="/api/Companies"
show-field="code"
value-field="id">
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete vn-one required="true"
label="Warehouse"
field="$ctrl.dms.warehouseId"
url="/api/Warehouses"
show-field="name"
value-field="id">
</vn-autocomplete>
<vn-autocomplete vn-one required="true"
label="Type"
field="$ctrl.dms.dmsTypeId"
url="/api/DmsTypes"
show-field="name"
value-field="id">
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-textarea vn-one required="true"
label="Description"
field="$ctrl.dms.description">
</vn-textarea>
</vn-horizontal>
<vn-horizontal>
<vn-input-file vn-one
label="File"
model="$ctrl.dms.files"
on-change="$ctrl.onFileChange(files)"
accept=".pdf, .png, .jpg, .jpeg, application/zip, application/rar, application/x-7z-compressed">
</vn-input-file>
</vn-horizontal>
<vn-vertical>
<vn-check disabled="true"
label="Generate identifier for original file"
field="$ctrl.dms.hasFile">
</vn-check>
</vn-vertical>
</vn-card>
<vn-button-bar>
<vn-submit label="Save"></vn-submit>
<vn-button ui-sref="claim.card.dms.index" label="Cancel"></vn-button>
</vn-button-bar>
</div>
</form>

View File

@ -0,0 +1,89 @@
import ngModule from '../../module';
import './style.scss';
class Controller {
constructor($scope, $http, $state, $translate, vnApp) {
this.$ = $scope;
this.$http = $http;
this.$state = $state;
this.$stateParams = $state.params;
this.$translate = $translate;
this.vnApp = vnApp;
}
get claim() {
return this._claim;
}
set claim(value) {
this._claim = value;
if (value)
this.setDefaultParams();
}
setDefaultParams() {
const path = `/api/Dms/${this.$stateParams.dmsId}`;
this.$http.get(path).then(res => {
const dms = res.data && res.data;
this.dms = {
reference: dms.reference,
warehouseId: dms.warehouseFk,
companyId: dms.companyFk,
dmsTypeId: dms.dmsTypeFk,
description: dms.description,
hasFile: dms.hasFile,
hasFileAttached: false,
files: []
};
});
}
onSubmit() {
const query = `/api/dms/${this.$stateParams.dmsId}/updateFile`;
const options = {
method: 'POST',
url: query,
params: this.dms,
headers: {
'Content-Type': undefined
},
transformRequest: files => {
const formData = new FormData();
for (let i = 0; i < files.length; i++)
formData.append(files[i].name, files[i]);
return formData;
},
data: this.dms.files
};
this.$http(options).then(res => {
if (res) {
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
this.$.watcher.updateOriginalData();
this.$state.go('claim.card.dms.index');
}
});
}
onFileChange(files) {
let hasFileAttached = false;
if (files.length > 0)
hasFileAttached = true;
this.$.$applyAsync(() => {
this.dms.hasFileAttached = hasFileAttached;
});
}
}
Controller.$inject = ['$scope', '$http', '$state', '$translate', 'vnApp'];
ngModule.component('vnClaimDmsEdit', {
template: require('./index.html'),
controller: Controller,
bindings: {
claim: '<'
}
});

View File

@ -0,0 +1,69 @@
import './index';
describe('Claim', () => {
describe('Component vnClaimDmsEdit', () => {
let controller;
let $scope;
let $httpBackend;
let $state;
beforeEach(ngModule('claim'));
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_) => {
$scope = $rootScope.$new();
$httpBackend = _$httpBackend_;
$state = {params: {dmsId: 1}};
controller = $componentController('vnClaimDmsEdit', {$scope, $state});
controller._claim = {id: 1, ticketFk: 16};
}));
describe('claim() setter', () => {
it('should set the claim data and then call setDefaultParams()', () => {
spyOn(controller, 'setDefaultParams');
controller._claim = undefined;
controller.claim = {
id: 15,
ticketFk: 16
};
expect(controller.setDefaultParams).toHaveBeenCalledWith();
expect(controller.claim).toBeDefined();
});
});
describe('setDefaultParams()', () => {
it('should perform a GET query and define the dms property on controller', () => {
const dmsId = 1;
const expectedResponse = {
reference: 101,
warehouseFk: 1,
companyFk: 442,
dmsTypeFk: 12,
description: 'Test',
hasFile: false,
hasFileAttached: false
};
$httpBackend.when('GET', `/api/Dms/${dmsId}`).respond(expectedResponse);
$httpBackend.expect('GET', `/api/Dms/${dmsId}`).respond(expectedResponse);
controller.setDefaultParams();
$httpBackend.flush();
expect(controller.dms).toBeDefined();
expect(controller.dms.reference).toEqual(101);
expect(controller.dms.dmsTypeId).toEqual(12);
});
});
describe('onFileChange()', () => {
it('should set dms hasFileAttached property to true if has any files', () => {
const files = [{id: 1, name: 'MyFile'}];
controller.dms = {hasFileAttached: false};
controller.onFileChange(files);
$scope.$apply();
expect(controller.dms.hasFileAttached).toBeTruthy();
});
});
});
});

View File

@ -0,0 +1,3 @@
Edit file: Editar fichero
File: Fichero
Generate identifier for original file: Generar identificador para archivo original

View File

@ -0,0 +1,7 @@
vn-ticket-request {
vn-textfield {
margin: 0!important;
max-width: 100px;
}
}

View File

@ -0,0 +1,110 @@
<vn-crud-model
vn-id="model"
url="/api/ClaimDms"
link="{claimFk: $ctrl.$stateParams.id}"
filter="::$ctrl.filter"
limit="20"
data="$ctrl.claimDms">
</vn-crud-model>
<vn-vertical>
<vn-card pad-large>
<vn-vertical>
<vn-table model="model">
<vn-thead>
<vn-tr>
<vn-th field="dmsFk" default-order="DESC" shrink>Id</vn-th>
<vn-th shrink>Type</vn-th>
<vn-th shrink number>Order</vn-th>
<vn-th shrink>Reference</vn-th>
<vn-th>Description</vn-th>
<vn-th shrink>Original</vn-th>
<vn-th>File</vn-th>
<vn-th shrink>Employee</vn-th>
<vn-th>Created</vn-th>
<vn-th number></vn-th>
</vn-tr>
</vn-thead>
<vn-tbody>
<vn-tr ng-repeat="document in $ctrl.claimDms">
<vn-td number shrink>{{::document.dmsFk}}</vn-td>
<vn-td shrink>
<span title="{{::document.dms.dmsType.name}}">
{{::document.dms.dmsType.name}}
</span>
</vn-td>
<vn-td shrink number>
<span title="{{::document.dms.hardCopyNumber}}">
{{::document.dms.hardCopyNumber}}
</span>
</vn-td>
<vn-td shrink>
<span title="{{::document.dms.reference}}">
{{::document.dms.reference}}
</span>
</vn-td>
<vn-td>
<span title="{{::document.dms.description}}">
{{::document.dms.description}}
</span>
</vn-td>
<vn-td shrink>
<vn-check disabled="true"
field="document.dms.hasFile">
</vn-check>
</vn-td>
<vn-td>
<a target="_blank"
title="{{'Download file' | translate}}"
href="api/dms/{{::document.dmsFk}}/downloadFile?access_token={{::$ctrl.accessToken}}">
{{::document.dms.file}}
</a>
</vn-td>
<vn-td shrink>
<span class="link"
ng-click="$ctrl.showWorkerDescriptor($event, document.dms.workerFk)">
{{::document.dms.worker.user.nickname | dashIfEmpty}}
</span></vn-td>
<vn-td>
{{::document.dms.created | dateTime:'dd/MM/yyyy HH:mm'}}
</vn-td>
<vn-td number>
<a target="_blank"
href="api/dms/{{::document.dmsFk}}/downloadFile?access_token={{::$ctrl.accessToken}}">
<vn-icon-button
icon="cloud_download"
title="{{'Download file' | translate}}">
</vn-icon-button>
</a>
<vn-icon-button ui-sref="claim.card.dms.edit({dmsId: {{::document.dmsFk}}})"
icon="edit"
title="{{'Edit file' | translate}}">
</vn-icon-button>
<vn-icon-button
icon="delete"
ng-click="$ctrl.showDeleteConfirm($index)"
title="{{'Remove file' | translate}}"
tabindex="-1">
</vn-icon-button>
</vn-td>
</vn-tr>
</vn-tbody>
</vn-table>
</vn-vertical>
<vn-pagination model="model"></vn-pagination>
</vn-card>
</vn-vertical>
<vn-worker-descriptor-popover
vn-id="workerDescriptor">
</vn-worker-descriptor-popover>
<a ui-sref="claim.card.dms.create"
vn-tooltip="Upload file"
vn-bind="+"
fixed-bottom-right>
<vn-float-button icon="add"></vn-float-button>
</a>
<vn-confirm
vn-id="confirm"
message="This file will be deleted"
question="Are you sure you want to continue?"
on-response="$ctrl.deleteDms(response)">
</vn-confirm>

View File

@ -0,0 +1,79 @@
import ngModule from '../../module';
import './style.scss';
class Controller {
constructor($stateParams, $scope, $http, $translate, vnToken, vnApp) {
this.$stateParams = $stateParams;
this.$ = $scope;
this.$http = $http;
this.$translate = $translate;
this.accessToken = vnToken.token;
this.vnApp = vnApp;
this.filter = {
include: {
relation: 'dms',
scope: {
fields: [
'dmsTypeFk',
'workerFk',
'hardCopyNumber',
'reference',
'description',
'hasFile',
'file',
'created',
],
include: [{
relation: 'dmsType',
scope: {
fields: ['name']
}
},
{
relation: 'worker',
scope: {
fields: ['userFk'],
include: {
relation: 'user',
scope: {
fields: ['nickname']
}
},
}
}]
},
}
};
}
showWorkerDescriptor(event, workerFk) {
event.preventDefault();
event.stopImmediatePropagation();
this.$.workerDescriptor.parent = event.target;
this.$.workerDescriptor.workerFk = workerFk;
this.$.workerDescriptor.show();
}
showDeleteConfirm(index) {
this.dmsIndex = index;
this.$.confirm.show();
}
deleteDms(response) {
if (response === 'ACCEPT') {
const dmsFk = this.claimDms[this.dmsIndex].dmsFk;
const query = `/api/claimDms/${dmsFk}/removeFile`;
this.$http.post(query).then(() => {
this.$.model.remove(this.dmsIndex);
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
});
}
}
}
Controller.$inject = ['$stateParams', '$scope', '$http', '$translate', 'vnToken', 'vnApp'];
ngModule.component('vnClaimDmsIndex', {
template: require('./index.html'),
controller: Controller,
});

View File

@ -0,0 +1,40 @@
import './index';
import crudModel from 'core/mocks/crud-model';
describe('Claim', () => {
describe('Component vnClaimDmsIndex', () => {
let $componentController;
let $scope;
let $httpBackend;
let controller;
beforeEach(ngModule('claim'));
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_) => {
$componentController = _$componentController_;
$httpBackend = _$httpBackend_;
$scope = $rootScope.$new();
controller = $componentController('vnClaimDmsIndex', {$: $scope});
controller.$.model = crudModel;
}));
describe('deleteDms()', () => {
it('should make an HTTP Post query', () => {
const dmsId = 1;
const dmsIndex = 0;
spyOn(controller.vnApp, 'showSuccess');
spyOn(controller.$.model, 'remove');
controller.claimDms = [{dmsFk: 1}];
controller.dmsIndex = dmsIndex;
$httpBackend.when('POST', `/api/claimDms/${dmsId}/removeFile`).respond({});
$httpBackend.expect('POST', `/api/claimDms/${dmsId}/removeFile`);
controller.deleteDms('ACCEPT');
$httpBackend.flush();
expect(controller.$.model.remove).toHaveBeenCalledWith(dmsIndex);
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
});
});
});
});

View File

@ -0,0 +1,2 @@
Type: Tipo
Are you sure you want to continue?: ¿Seguro que quieres continuar?

View File

@ -0,0 +1,6 @@
vn-client-risk-index {
.totalBox {
display: table;
float: right;
}
}

View File

@ -9,3 +9,6 @@ import './descriptor';
import './development';
import './search-panel';
import './summary';
import './dms/index';
import './dms/create';
import './dms/edit';

View File

@ -8,7 +8,8 @@
{"state": "claim.card.basicData", "icon": "settings"},
{"state": "claim.card.detail", "icon": "icon-details"},
{"state": "claim.card.development", "icon": "icon-traceability"},
{"state": "claim.card.action", "icon": "icon-actions"}
{"state": "claim.card.action", "icon": "icon-actions"},
{"state": "claim.card.dms.index", "icon": "image"}
],
"keybindings": [
{"key": "r", "state": "claim.index"}
@ -74,6 +75,35 @@
"claim": "$ctrl.claim"
},
"acl": ["salesAssistant"]
}, {
"url": "/dms",
"state": "claim.card.dms",
"abstract": true,
"component": "ui-view"
}, {
"url" : "/index",
"state": "claim.card.dms.index",
"component": "vn-claim-dms-index",
"description": "Pictures",
"params": {
"claim": "$ctrl.claim"
}
}, {
"url" : "/create",
"state": "claim.card.dms.create",
"component": "vn-claim-dms-create",
"description": "Upload file",
"params": {
"claim": "$ctrl.claim"
}
}, {
"url": "/:dmsId/edit",
"state": "claim.card.dms.edit",
"component": "vn-claim-dms-edit",
"description": "Edit file",
"params": {
"claim": "$ctrl.claim"
}
}
]
}

View File

@ -13,14 +13,14 @@
<vn-thead>
<vn-tr>
<vn-th field="dmsFk" default-order="DESC" shrink>Id</vn-th>
<vn-th field="dmsTypeFk" shrink>Type</vn-th>
<vn-th field="hardCopyNumber" shrink number>Order</vn-th>
<vn-th field="reference" shrink>Reference</vn-th>
<vn-th shrink>Type</vn-th>
<vn-th shrink number>Order</vn-th>
<vn-th shrink>Reference</vn-th>
<vn-th>Description</vn-th>
<vn-th field="hasFile" shrink>Original</vn-th>
<vn-th shrink>Original</vn-th>
<vn-th>File</vn-th>
<vn-th shrink>Employee</vn-th>
<vn-th field="created">Created</vn-th>
<vn-th>Created</vn-th>
<vn-th number></vn-th>
</vn-tr>
</vn-thead>
@ -54,7 +54,7 @@
</vn-td>
<vn-td>
<a target="_blank"
vn-tooltip="Download file"
title="{{'Download file' | translate}}"
href="api/dms/{{::document.dmsFk}}/downloadFile?access_token={{::$ctrl.accessToken}}">{{::document.dms.file}}
</a>
</vn-td>
@ -68,22 +68,20 @@
</vn-td>
<vn-td number>
<a target="_blank"
vn-tooltip="Download file"
href="api/dms/{{::document.dmsFk}}/downloadFile?access_token={{::$ctrl.accessToken}}">
<vn-icon-button
icon="cloud_download"
title="{{'Download PDF' | translate}}">
title="{{'Download file' | translate}}">
</vn-icon-button>
</a>
<vn-icon-button ui-sref="client.card.dms.edit({dmsId: {{::document.dmsFk}}})"
vn-tooltip="Edit file"
icon="edit"
title="{{'Edit file' | translate}}">
</vn-icon-button>
<vn-icon-button
vn-tooltip="Remove file"
icon="delete"
ng-click="$ctrl.showDeleteConfirm($index)"
title="{{'Remove file' | translate}}"
tabindex="-1">
</vn-icon-button>
</vn-td>

View File

@ -62,7 +62,7 @@ class Controller {
deleteDms(response) {
if (response === 'ACCEPT') {
const dmsFk = this.clientDms[this.dmsIndex].dmsFk;
const query = `/api/ClientDms/${dmsFk}/removeFile`;
const query = `/api/clientDms/${dmsFk}/removeFile`;
this.$http.post(query).then(() => {
this.$.model.remove(this.dmsIndex);
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));

View File

@ -0,0 +1,40 @@
import './index';
import crudModel from 'core/mocks/crud-model';
describe('Client', () => {
describe('Component vnClientDmsIndex', () => {
let $componentController;
let $scope;
let $httpBackend;
let controller;
beforeEach(ngModule('client'));
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_) => {
$componentController = _$componentController_;
$httpBackend = _$httpBackend_;
$scope = $rootScope.$new();
controller = $componentController('vnClientDmsIndex', {$: $scope});
controller.$.model = crudModel;
}));
describe('deleteDms()', () => {
it('should make an HTTP Post query', () => {
const dmsId = 1;
const dmsIndex = 0;
spyOn(controller.vnApp, 'showSuccess');
spyOn(controller.$.model, 'remove');
controller.clientDms = [{dmsFk: 1}];
controller.dmsIndex = dmsIndex;
$httpBackend.when('POST', `/api/clientDms/${dmsId}/removeFile`).respond({});
$httpBackend.expect('POST', `/api/clientDms/${dmsId}/removeFile`);
controller.deleteDms('ACCEPT');
$httpBackend.flush();
expect(controller.$.model.remove).toHaveBeenCalledWith(dmsIndex);
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
});
});
});
});

View File

@ -54,7 +54,7 @@
</vn-td>
<vn-td>
<a target="_blank"
vn-tooltip="Download file"
title="{{'Download file' | translate}}"
href="api/dms/{{::document.dmsFk}}/downloadFile?access_token={{::$ctrl.accessToken}}">
{{::document.dms.file}}
</a>
@ -69,22 +69,20 @@
</vn-td>
<vn-td number>
<a target="_blank"
vn-tooltip="Download file"
href="api/dms/{{::document.dmsFk}}/downloadFile?access_token={{::$ctrl.accessToken}}">
<vn-icon-button
icon="cloud_download"
title="{{'Download PDF' | translate}}">
title="{{'Download file' | translate}}">
</vn-icon-button>
</a>
<vn-icon-button ui-sref="ticket.card.dms.edit({dmsId: {{::document.dmsFk}}})"
vn-tooltip="Edit file"
icon="edit"
title="{{'Edit file' | translate}}">
</vn-icon-button>
<vn-icon-button
vn-tooltip="Remove file"
icon="delete"
ng-click="$ctrl.showDeleteConfirm($index)"
title="{{'Remove file' | translate}}"
tabindex="-1">
</vn-icon-button>
</vn-td>

View File

@ -62,7 +62,7 @@ class Controller {
deleteDms(response) {
if (response === 'ACCEPT') {
const dmsFk = this.ticketDms[this.dmsIndex].dmsFk;
const query = `/api/TicketDms/${dmsFk}/removeFile`;
const query = `/api/ticketDms/${dmsFk}/removeFile`;
this.$http.post(query).then(() => {
this.$.model.remove(this.dmsIndex);
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));

View File

@ -1,43 +1,39 @@
import './index';
import crudModel from 'core/mocks/crud-model';
describe('Client', () => {
describe('Component vnClientBalanceIndex', () => {
describe('Ticket', () => {
describe('Component vnTicketDmsIndex', () => {
let $componentController;
let $scope;
let $httpBackend;
let $httpParamSerializer;
let controller;
beforeEach(ngModule('client'));
beforeEach(ngModule('ticket'));
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_, _$httpParamSerializer_) => {
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_) => {
$componentController = _$componentController_;
$httpBackend = _$httpBackend_;
$httpParamSerializer = _$httpParamSerializer_;
$scope = $rootScope.$new();
controller = $componentController('vnClientBalanceIndex', {$scope});
controller = $componentController('vnTicketDmsIndex', {$: $scope});
controller.$.model = crudModel;
}));
describe('balances() setter', () => {
it('should calculate the balance for each line from the oldest date to the newest', () => {
controller.getCurrentBalance = jasmine.createSpy(controller, 'getCurrentBalance').and.returnValue(1000);
let balances = [
{credit: -100, debit: 0},
{credit: 0, debit: 300},
{credit: 100, debit: 0},
{credit: 0, debit: -300}
];
const params = {filter: controller.filter};
let serializedParams = $httpParamSerializer(params);
$httpBackend.when('GET', `/client/api/ClientRisks?${serializedParams}`).respond(balances);
$httpBackend.expect('GET', `/client/api/ClientRisks?${serializedParams}`);
controller.balances = balances;
describe('deleteDms()', () => {
it('should make an HTTP Post query', () => {
const dmsId = 1;
const dmsIndex = 0;
spyOn(controller.vnApp, 'showSuccess');
spyOn(controller.$.model, 'remove');
controller.ticketDms = [{dmsFk: 1}];
controller.dmsIndex = dmsIndex;
$httpBackend.when('POST', `/api/ticketDms/${dmsId}/removeFile`).respond({});
$httpBackend.expect('POST', `/api/ticketDms/${dmsId}/removeFile`);
controller.deleteDms('ACCEPT');
$httpBackend.flush();
expect(controller.balances[0].balance).toEqual(1000);
expect(controller.balances[1].balance).toEqual(900);
expect(controller.balances[2].balance).toEqual(600);
expect(controller.balances[3].balance).toEqual(700);
expect(controller.$.model.remove).toHaveBeenCalledWith(dmsIndex);
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
});
});
});

View File

@ -1,6 +1,6 @@
import './index';
fdescribe('Client', () => {
describe('Ticket', () => {
describe('Component vnTicketWeeklyCreate', () => {
let $componentController;
let $scope;