Merge pull request '3620-feat(claim): implemented smart-table and change state in summary' (#887) from 3620-claim_change_state into dev
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
Reviewed-on: #887 Reviewed-by: Carlos Jimenez Ruiz <carlosjr@verdnatura.es>
This commit is contained in:
commit
d923209c2d
|
@ -94,19 +94,14 @@ module.exports = Self => {
|
||||||
? {'cl.id': value}
|
? {'cl.id': value}
|
||||||
: {
|
: {
|
||||||
or: [
|
or: [
|
||||||
{'c.name': {like: `%${value}%`}}
|
{'cl.socialName': {like: `%${value}%`}}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
case 'client':
|
|
||||||
return {'c.name': {like: `%${value}%`}};
|
|
||||||
case 'id':
|
case 'id':
|
||||||
return {'cl.id': value};
|
|
||||||
case 'clientFk':
|
|
||||||
return {'c.id': value};
|
|
||||||
case 'claimStateFk':
|
case 'claimStateFk':
|
||||||
return {'cl.claimStateFk': value};
|
case 'priority':
|
||||||
|
return {[`cl.${param}`]: value};
|
||||||
case 'salesPersonFk':
|
case 'salesPersonFk':
|
||||||
return {'c.salesPersonFk': value};
|
|
||||||
case 'attenderFk':
|
case 'attenderFk':
|
||||||
return {'cl.workerFk': value};
|
return {'cl.workerFk': value};
|
||||||
case 'created':
|
case 'created':
|
||||||
|
@ -123,12 +118,23 @@ module.exports = Self => {
|
||||||
const stmts = [];
|
const stmts = [];
|
||||||
|
|
||||||
const stmt = new ParameterizedSQL(
|
const stmt = new ParameterizedSQL(
|
||||||
`SELECT cl.id, c.name, cl.clientFk, cl.workerFk, u.name AS userName, cs.description, cl.created
|
`SELECT *
|
||||||
FROM claim cl
|
FROM (
|
||||||
LEFT JOIN client c ON c.id = cl.clientFk
|
SELECT
|
||||||
LEFT JOIN worker w ON w.id = cl.workerFk
|
cl.id,
|
||||||
LEFT JOIN account.user u ON u.id = w.userFk
|
cl.clientFk,
|
||||||
LEFT JOIN claimState cs ON cs.id = cl.claimStateFk`
|
c.socialName,
|
||||||
|
cl.workerFk,
|
||||||
|
u.name AS workerName,
|
||||||
|
cs.description,
|
||||||
|
cl.created,
|
||||||
|
cs.priority,
|
||||||
|
cl.claimStateFk
|
||||||
|
FROM claim cl
|
||||||
|
LEFT JOIN client c ON c.id = cl.clientFk
|
||||||
|
LEFT JOIN worker w ON w.id = cl.workerFk
|
||||||
|
LEFT JOIN account.user u ON u.id = w.userFk
|
||||||
|
LEFT JOIN claimState cs ON cs.id = cl.claimStateFk ) cl`
|
||||||
);
|
);
|
||||||
|
|
||||||
stmt.merge(conn.makeSuffix(filter));
|
stmt.merge(conn.makeSuffix(filter));
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethod('getSummary', {
|
Self.remoteMethodCtx('getSummary', {
|
||||||
description: 'Return the claim summary',
|
description: 'Return the claim summary',
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: [{
|
accepts: [{
|
||||||
|
@ -19,7 +19,7 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.getSummary = async(id, options) => {
|
Self.getSummary = async(ctx, id, options) => {
|
||||||
const myOptions = {};
|
const myOptions = {};
|
||||||
|
|
||||||
if (typeof options == 'object')
|
if (typeof options == 'object')
|
||||||
|
@ -135,6 +135,7 @@ module.exports = Self => {
|
||||||
|
|
||||||
const res = await Promise.all(promises);
|
const res = await Promise.all(promises);
|
||||||
|
|
||||||
|
summary.isEditable = await Self.isEditable(ctx, id, myOptions);
|
||||||
[summary.claim] = res[0];
|
[summary.claim] = res[0];
|
||||||
summary.salesClaimed = res[1];
|
summary.salesClaimed = res[1];
|
||||||
summary.developments = res[2];
|
summary.developments = res[2];
|
||||||
|
|
|
@ -25,7 +25,7 @@ describe('claim filter()', () => {
|
||||||
try {
|
try {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
const result = await app.models.Claim.filter({args: {filter: {}, search: 'Tony Stark'}}, null, options);
|
const result = await app.models.Claim.filter({args: {filter: {}, search: 'Iron man'}}, null, options);
|
||||||
|
|
||||||
expect(result.length).toEqual(1);
|
expect(result.length).toEqual(1);
|
||||||
expect(result[0].id).toEqual(4);
|
expect(result[0].id).toEqual(4);
|
||||||
|
|
|
@ -3,17 +3,24 @@ const app = require('vn-loopback/server/server');
|
||||||
describe('claim getSummary()', () => {
|
describe('claim getSummary()', () => {
|
||||||
it('should return summary with claim, salesClaimed, developments and actions defined ', async() => {
|
it('should return summary with claim, salesClaimed, developments and actions defined ', async() => {
|
||||||
const tx = await app.models.Claim.beginTransaction({});
|
const tx = await app.models.Claim.beginTransaction({});
|
||||||
|
const ctx = {
|
||||||
|
req: {
|
||||||
|
accessToken: {
|
||||||
|
userId: 9
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
try {
|
try {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
const result = await app.models.Claim.getSummary(1, options);
|
const result = await app.models.Claim.getSummary(ctx, 1, options);
|
||||||
const keys = Object.keys(result);
|
const keys = Object.keys(result);
|
||||||
|
|
||||||
expect(keys).toContain('claim');
|
expect(keys).toContain('claim');
|
||||||
expect(keys).toContain('salesClaimed');
|
expect(keys).toContain('salesClaimed');
|
||||||
expect(keys).toContain('developments');
|
expect(keys).toContain('developments');
|
||||||
expect(keys).toContain('actions');
|
expect(keys).toContain('actions');
|
||||||
|
expect(keys).toContain('isEditable');
|
||||||
|
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -1,59 +1,74 @@
|
||||||
<vn-auto-search
|
<vn-auto-search
|
||||||
model="model">
|
model="model">
|
||||||
</vn-auto-search>
|
</vn-auto-search>
|
||||||
<vn-data-viewer
|
<vn-card>
|
||||||
model="model"
|
<smart-table
|
||||||
class="vn-w-lg">
|
model="model"
|
||||||
<vn-card>
|
options="$ctrl.smartTableOptions"
|
||||||
<vn-table model="model">
|
expr-builder="$ctrl.exprBuilder(param, value)">
|
||||||
<vn-thead>
|
<slot-table>
|
||||||
<vn-tr>
|
<table>
|
||||||
<vn-th field="id" number>Id</vn-th>
|
<thead>
|
||||||
<vn-th field="clientFk">Client</vn-th>
|
<tr>
|
||||||
<vn-th field="created" center shrink-date>Created</vn-th>
|
<th field="id" shrink>
|
||||||
<vn-th field="workerFk">Worker</vn-th>
|
<span translate>Id</span>
|
||||||
<vn-th field="claimStateFk">State</vn-th>
|
</th>
|
||||||
<vn-th></vn-th>
|
<th field="clientFk">
|
||||||
</vn-tr>
|
<span translate>Client</span>
|
||||||
</vn-thead>
|
</th>
|
||||||
<vn-tbody>
|
<th field="created" center shrink-date>
|
||||||
<a
|
<span translate>Created</span>
|
||||||
ng-repeat="claim in model.data"
|
</th>
|
||||||
class="{{::$ctrl.compareDate(ticket.shipped)}} clickable vn-tr search-result"
|
<th field="salesPersonFk">
|
||||||
ui-sref="claim.card.summary({id: claim.id})">
|
<span translate>Worker</span>
|
||||||
<vn-td number>{{::claim.id}}</vn-td>
|
</th>
|
||||||
<vn-td expand>
|
<th field="claimStateFk">
|
||||||
<span
|
<span translate>State</span>
|
||||||
vn-click-stop="clientDescriptor.show($event, claim.clientFk)"
|
</th>
|
||||||
class="link">
|
<th></th>
|
||||||
{{::claim.name}}
|
</tr>
|
||||||
</span>
|
</thead>
|
||||||
</vn-td>
|
<tbody>
|
||||||
<vn-td center shrink-date>{{::claim.created | date:'dd/MM/yyyy'}}</vn-td>
|
<tr
|
||||||
<vn-td expand>
|
ng-repeat="claim in model.data"
|
||||||
<span
|
vn-anchor="::{
|
||||||
vn-click-stop="workerDescriptor.show($event, claim.workerFk)"
|
state: 'claim.card.summary',
|
||||||
class="link" >
|
params: {id: claim.id}
|
||||||
{{::claim.userName}}
|
}">
|
||||||
</span>
|
<td>{{::claim.id}}</td>
|
||||||
</vn-td>
|
<td>
|
||||||
<vn-td>
|
<span
|
||||||
<span class="chip {{::$ctrl.stateColor(claim)}}">
|
vn-click-stop="clientDescriptor.show($event, claim.clientFk)"
|
||||||
{{::claim.description}}
|
class="link">
|
||||||
</span>
|
{{::claim.socialName}}
|
||||||
</vn-td>
|
</span>
|
||||||
<vn-td shrink>
|
</td>
|
||||||
<vn-icon-button
|
<td center shrink-date>{{::claim.created | date:'dd/MM/yyyy'}}</td>
|
||||||
vn-click-stop="$ctrl.preview(claim)"
|
<td>
|
||||||
vn-tooltip="Preview"
|
<span
|
||||||
icon="preview">
|
vn-click-stop="workerDescriptor.show($event, claim.workerFk)"
|
||||||
</vn-icon-button>
|
class="link" >
|
||||||
</vn-td>
|
{{::claim.workerName}}
|
||||||
</a>
|
</span>
|
||||||
</vn-tbody>
|
</td>
|
||||||
</vn-table>
|
<td>
|
||||||
</vn-card>
|
<span class="chip {{::$ctrl.stateColor(claim)}}">
|
||||||
</vn-data-viewer>
|
{{::claim.description}}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td shrink>
|
||||||
|
<vn-icon-button
|
||||||
|
vn-click-stop="$ctrl.preview(claim)"
|
||||||
|
vn-tooltip="Preview"
|
||||||
|
icon="preview">
|
||||||
|
</vn-icon-button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</slot-table>
|
||||||
|
</smart-table>
|
||||||
|
</vn-card>
|
||||||
<vn-client-descriptor-popover
|
<vn-client-descriptor-popover
|
||||||
vn-id="clientDescriptor">
|
vn-id="clientDescriptor">
|
||||||
</vn-client-descriptor-popover>
|
</vn-client-descriptor-popover>
|
||||||
|
@ -62,6 +77,7 @@
|
||||||
</vn-worker-descriptor-popover>
|
</vn-worker-descriptor-popover>
|
||||||
<vn-popup vn-id="summary">
|
<vn-popup vn-id="summary">
|
||||||
<vn-claim-summary
|
<vn-claim-summary
|
||||||
claim="$ctrl.claimSelected">
|
claim="$ctrl.claimSelected"
|
||||||
|
parent-reload="$ctrl.reload()">
|
||||||
</vn-claim-summary>
|
</vn-claim-summary>
|
||||||
</vn-popup>
|
</vn-popup>
|
||||||
|
|
|
@ -1,7 +1,69 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
import Section from 'salix/components/section';
|
import Section from 'salix/components/section';
|
||||||
|
|
||||||
export default class Controller extends Section {
|
class Controller extends Section {
|
||||||
|
constructor($element, $) {
|
||||||
|
super($element, $);
|
||||||
|
|
||||||
|
this.smartTableOptions = {
|
||||||
|
activeButtons: {
|
||||||
|
search: true
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
field: 'clientFk',
|
||||||
|
autocomplete: {
|
||||||
|
url: 'Clients',
|
||||||
|
showField: 'socialName',
|
||||||
|
valueField: 'socialName'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'workerFk',
|
||||||
|
autocomplete: {
|
||||||
|
url: 'Workers/activeWithInheritedRole',
|
||||||
|
where: `{role: 'salesPerson'}`,
|
||||||
|
searchFunction: '{firstName: $search}',
|
||||||
|
showField: 'name',
|
||||||
|
valueField: 'id',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'claimStateFk',
|
||||||
|
autocomplete: {
|
||||||
|
url: 'ClaimStates',
|
||||||
|
showField: 'description',
|
||||||
|
valueField: 'id',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'created',
|
||||||
|
searchable: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
exprBuilder(param, value) {
|
||||||
|
switch (param) {
|
||||||
|
case 'clientFk':
|
||||||
|
return {['cl.socialName']: value};
|
||||||
|
case 'id':
|
||||||
|
case 'claimStateFk':
|
||||||
|
case 'priority':
|
||||||
|
return {[`cl.${param}`]: value};
|
||||||
|
case 'salesPersonFk':
|
||||||
|
case 'attenderFk':
|
||||||
|
return {'cl.workerFk': value};
|
||||||
|
case 'created':
|
||||||
|
value.setHours(0, 0, 0, 0);
|
||||||
|
to = new Date(value);
|
||||||
|
to.setHours(23, 59, 59, 999);
|
||||||
|
|
||||||
|
return {'cl.created': {between: [value, to]}};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
stateColor(claim) {
|
stateColor(claim) {
|
||||||
switch (claim.description) {
|
switch (claim.description) {
|
||||||
case 'Pendiente':
|
case 'Pendiente':
|
||||||
|
@ -17,6 +79,10 @@ export default class Controller extends Section {
|
||||||
this.claimSelected = claim;
|
this.claimSelected = claim;
|
||||||
this.$.summary.show();
|
this.$.summary.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reload() {
|
||||||
|
this.$.model.refresh();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngModule.vnComponent('vnClaimIndex', {
|
ngModule.vnComponent('vnClaimIndex', {
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
import ModuleMain from 'salix/components/module-main';
|
import ModuleMain from 'salix/components/module-main';
|
||||||
|
|
||||||
export default class Claim extends ModuleMain {}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnClaim', {
|
ngModule.vnComponent('vnClaim', {
|
||||||
controller: Claim,
|
controller: ModuleMain,
|
||||||
template: require('./index.html')
|
template: require('./index.html')
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,6 +12,15 @@
|
||||||
<vn-icon-button icon="launch"></vn-icon-button>
|
<vn-icon-button icon="launch"></vn-icon-button>
|
||||||
</a>
|
</a>
|
||||||
<span>{{::$ctrl.summary.claim.id}} - {{::$ctrl.summary.claim.client.name}}</span>
|
<span>{{::$ctrl.summary.claim.id}} - {{::$ctrl.summary.claim.client.name}}</span>
|
||||||
|
<vn-button-menu
|
||||||
|
disabled="!$ctrl.summary.isEditable"
|
||||||
|
class="message"
|
||||||
|
label="Change state"
|
||||||
|
value-field="id"
|
||||||
|
show-field="description"
|
||||||
|
url="claimStates"
|
||||||
|
on-change="$ctrl.changeState(value)">
|
||||||
|
</vn-button-menu>
|
||||||
</h5>
|
</h5>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-one>
|
<vn-one>
|
||||||
|
|
|
@ -10,7 +10,25 @@ class Controller extends Summary {
|
||||||
|
|
||||||
$onChanges() {
|
$onChanges() {
|
||||||
if (this.claim && this.claim.id)
|
if (this.claim && this.claim.id)
|
||||||
this.getSummary();
|
this.loadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
loadData() {
|
||||||
|
return this.$http.get(`Claims/${this.claim.id}/getSummary`).then(res => {
|
||||||
|
if (res && res.data)
|
||||||
|
this.summary = res.data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
reload() {
|
||||||
|
this.loadData()
|
||||||
|
.then(() => {
|
||||||
|
if (this.card)
|
||||||
|
this.card.reload();
|
||||||
|
|
||||||
|
if (this.parentReload)
|
||||||
|
this.parentReload();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get isSalesPerson() {
|
get isSalesPerson() {
|
||||||
|
@ -29,8 +47,10 @@ class Controller extends Summary {
|
||||||
this._claim = value;
|
this._claim = value;
|
||||||
|
|
||||||
// Get DMS on summary load
|
// Get DMS on summary load
|
||||||
if (value)
|
if (value) {
|
||||||
this.$.$applyAsync(() => this.loadDms());
|
this.$.$applyAsync(() => this.loadDms());
|
||||||
|
this.loadData();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loadDms() {
|
loadDms() {
|
||||||
|
@ -40,15 +60,24 @@ class Controller extends Summary {
|
||||||
this.$.model.refresh();
|
this.$.model.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
getSummary() {
|
|
||||||
this.$http.get(`Claims/${this.claim.id}/getSummary`).then(response => {
|
|
||||||
this.summary = response.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getImagePath(dmsId) {
|
getImagePath(dmsId) {
|
||||||
return this.vnFile.getPath(`/api/dms/${dmsId}/downloadFile`);
|
return this.vnFile.getPath(`/api/dms/${dmsId}/downloadFile`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changeState(value) {
|
||||||
|
const params = {
|
||||||
|
id: this.claim.id,
|
||||||
|
claimStateFk: value
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$http.patch(`Claims/updateClaim/${this.claim.id}`, params)
|
||||||
|
.then(() => {
|
||||||
|
this.reload();
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$element', '$scope', 'vnFile'];
|
Controller.$inject = ['$element', '$scope', 'vnFile'];
|
||||||
|
@ -57,6 +86,11 @@ ngModule.vnComponent('vnClaimSummary', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
controller: Controller,
|
controller: Controller,
|
||||||
bindings: {
|
bindings: {
|
||||||
claim: '<'
|
claim: '<',
|
||||||
|
model: '<?',
|
||||||
|
parentReload: '&'
|
||||||
|
},
|
||||||
|
require: {
|
||||||
|
card: '?^vnClaimCard'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,23 +18,37 @@ describe('Claim', () => {
|
||||||
controller.$.model = crudModel;
|
controller.$.model = crudModel;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('getSummary()', () => {
|
describe('loadData()', () => {
|
||||||
it('should perform a query to set summary', () => {
|
it('should perform a query to set summary', () => {
|
||||||
$httpBackend.expect('GET', `Claims/1/getSummary`).respond(200, 24);
|
$httpBackend.when('GET', `Claims/1/getSummary`).respond(200, 24);
|
||||||
controller.getSummary();
|
controller.loadData();
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
|
|
||||||
expect(controller.summary).toEqual(24);
|
expect(controller.summary).toEqual(24);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('changeState()', () => {
|
||||||
|
it('should make an HTTP post query, then call the showSuccess()', () => {
|
||||||
|
jest.spyOn(controller.vnApp, 'showSuccess').mockReturnThis();
|
||||||
|
|
||||||
|
const expectedParams = {id: 1, claimStateFk: 1};
|
||||||
|
$httpBackend.when('GET', `Claims/1/getSummary`).respond(200, 24);
|
||||||
|
$httpBackend.expect('PATCH', `Claims/updateClaim/1`, expectedParams).respond(200);
|
||||||
|
controller.changeState(1);
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('$onChanges()', () => {
|
describe('$onChanges()', () => {
|
||||||
it('should call getSummary when item.id is defined', () => {
|
it('should call loadData when $onChanges is called', () => {
|
||||||
jest.spyOn(controller, 'getSummary');
|
jest.spyOn(controller, 'loadData');
|
||||||
|
|
||||||
controller.$onChanges();
|
controller.$onChanges();
|
||||||
|
|
||||||
expect(controller.getSummary).toHaveBeenCalledWith();
|
expect(controller.loadData).toHaveBeenCalledWith();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue