diff --git a/client/claim/routes.json b/client/claim/routes.json index 3267803298..e8562dcf6c 100644 --- a/client/claim/routes.json +++ b/client/claim/routes.json @@ -15,8 +15,7 @@ "url": "/index?q", "state": "claim.index", "component": "vn-claim-index", - "description": "List", - "acl": ["salesAssistant", "salesPerson"] + "description": "List" }, { "url": "/:id", @@ -43,7 +42,8 @@ }, "menu": { "icon": "settings" - } + }, + "acl": ["salesPerson"] }, { "url": "/detail", @@ -55,7 +55,8 @@ }, "menu": { "icon": "icon-details" - } + }, + "acl": ["salesPerson"] }, { "url": "/development", @@ -67,7 +68,8 @@ }, "menu": { "icon": "icon-traceability" - } + }, + "acl": ["salesAssistant"] }, { "url": "/action", @@ -79,7 +81,8 @@ }, "menu": { "icon": "icon-actions" - } + }, + "acl": ["salesAssistant"] } ] } \ No newline at end of file diff --git a/client/claim/src/basic-data/index.html b/client/claim/src/basic-data/index.html index 774ebe3154..e3a18051b4 100644 --- a/client/claim/src/basic-data/index.html +++ b/client/claim/src/basic-data/index.html @@ -1,10 +1,9 @@ + url="/claim/api/Claims/updateClaim" + save="post">
@@ -50,7 +49,8 @@ + field="$ctrl.claim.isChargedToMana" + vn-acl="['salesAssistant']"> + step="1" + vn-acl="['salesAssistant']"> diff --git a/client/claim/src/descriptor/index.html b/client/claim/src/descriptor/index.html index 5fc417e8a7..7faca567b5 100644 --- a/client/claim/src/descriptor/index.html +++ b/client/claim/src/descriptor/index.html @@ -15,7 +15,7 @@ value="{{::$ctrl.claim.client.name}}"> + value="{{$ctrl.claim.claimState.description}}"> diff --git a/package-lock.json b/package-lock.json index ba954971a3..f93914afa1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1383,7 +1383,7 @@ "bluebird": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "integrity": "sha1-2VUfnemPH82h5oPRfukaBgLuLrk=", "dev": true }, "bn.js": { @@ -1600,7 +1600,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } }, "supports-color": { @@ -5465,7 +5465,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { "ms": "2.0.0" @@ -6096,8 +6096,8 @@ "dev": true, "optional": true, "requires": { - "co": "^4.6.0", - "json-stable-stringify": "^1.0.1" + "co": "4.6.0", + "json-stable-stringify": "1.0.1" } }, "ansi-regex": { @@ -6170,7 +6170,7 @@ "bundled": true, "dev": true, "requires": { - "inherits": "~2.0.0" + "inherits": "2.0.3" } }, "boom": { @@ -6178,7 +6178,7 @@ "bundled": true, "dev": true, "requires": { - "hoek": "2.x.x" + "hoek": "2.16.3" } }, "brace-expansion": { @@ -6240,7 +6240,7 @@ "bundled": true, "dev": true, "requires": { - "boom": "2.x.x" + "boom": "2.10.1" } }, "dashdash": { @@ -6298,7 +6298,7 @@ "dev": true, "optional": true, "requires": { - "jsbn": "~0.1.0" + "jsbn": "0.1.1" } }, "extend": { @@ -6507,14 +6507,13 @@ "dev": true, "optional": true, "requires": { - "jsbn": "~0.1.0" + "jsbn": "0.1.1" } }, "jsbn": { "version": "0.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "json-schema": { "version": "0.2.3", @@ -6528,7 +6527,7 @@ "dev": true, "optional": true, "requires": { - "jsonify": "~0.0.0" + "jsonify": "0.0.0" } }, "json-stringify-safe": { @@ -10852,7 +10851,7 @@ "jasmine-spec-reporter": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz", - "integrity": "sha512-FZBoZu7VE5nR7Nilzy+Np8KuVIOxF4oXDPDknehCYBDE080EnlPu0afdZNmpGDBRCUBv3mj5qgqCRmk6W/K8vg==", + "integrity": "sha1-HWMq7ANBZwrTJPkrqEtLMrNeniI=", "dev": true, "requires": { "colors": "1.1.2" @@ -10998,7 +10997,7 @@ "karma": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/karma/-/karma-1.7.1.tgz", - "integrity": "sha512-k5pBjHDhmkdaUccnC7gE3mBzZjcxyxYsYVaqiL2G5AqlfLyBO5nw2VdNK+O16cveEPd/gIOWULH7gkiYYwVNHg==", + "integrity": "sha1-hcwI6eCiLXzpzKN8ShvoJPaisa4=", "dev": true, "requires": { "bluebird": "3.5.1", @@ -11050,7 +11049,7 @@ "karma-chrome-launcher": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", - "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", + "integrity": "sha1-zxudBxNswY/iOTJ9JGVMPbw2is8=", "dev": true, "requires": { "fs-access": "1.0.1", @@ -12743,8 +12742,8 @@ "dev": true, "optional": true, "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" + "delegates": "1.0.0", + "readable-stream": "2.3.6" } }, "balanced-match": { @@ -12821,7 +12820,7 @@ "dev": true, "optional": true, "requires": { - "minipass": "^2.2.1" + "minipass": "2.2.4" } }, "fs.realpath": { @@ -12836,14 +12835,14 @@ "dev": true, "optional": true, "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" } }, "glob": { @@ -12852,12 +12851,12 @@ "dev": true, "optional": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } }, "has-unicode": { @@ -12872,7 +12871,7 @@ "dev": true, "optional": true, "requires": { - "safer-buffer": "^2.1.0" + "safer-buffer": "2.1.2" } }, "ignore-walk": { @@ -12881,7 +12880,7 @@ "dev": true, "optional": true, "requires": { - "minimatch": "^3.0.4" + "minimatch": "3.0.4" } }, "inflight": { @@ -12890,8 +12889,8 @@ "dev": true, "optional": true, "requires": { - "once": "^1.3.0", - "wrappy": "1" + "once": "1.4.0", + "wrappy": "1.0.2" } }, "inherits": { @@ -12910,7 +12909,7 @@ "bundled": true, "dev": true, "requires": { - "number-is-nan": "^1.0.0" + "number-is-nan": "1.0.1" } }, "isarray": { @@ -12924,7 +12923,7 @@ "bundled": true, "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "brace-expansion": "1.1.11" } }, "minimist": { @@ -12937,8 +12936,8 @@ "bundled": true, "dev": true, "requires": { - "safe-buffer": "^5.1.1", - "yallist": "^3.0.0" + "safe-buffer": "5.1.1", + "yallist": "3.0.2" } }, "minizlib": { @@ -12947,7 +12946,7 @@ "dev": true, "optional": true, "requires": { - "minipass": "^2.2.1" + "minipass": "2.2.4" } }, "mkdirp": { @@ -12970,9 +12969,9 @@ "dev": true, "optional": true, "requires": { - "debug": "^2.1.2", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" + "debug": "2.6.9", + "iconv-lite": "0.4.21", + "sax": "1.2.4" } }, "node-pre-gyp": { @@ -12981,16 +12980,16 @@ "dev": true, "optional": true, "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.0", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.1.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" + "detect-libc": "1.0.3", + "mkdirp": "0.5.1", + "needle": "2.2.0", + "nopt": "4.0.1", + "npm-packlist": "1.1.10", + "npmlog": "4.1.2", + "rc": "1.2.7", + "rimraf": "2.6.2", + "semver": "5.5.0", + "tar": "4.4.1" } }, "nopt": { @@ -12999,8 +12998,8 @@ "dev": true, "optional": true, "requires": { - "abbrev": "1", - "osenv": "^0.1.4" + "abbrev": "1.1.1", + "osenv": "0.1.5" } }, "npm-bundled": { @@ -13015,8 +13014,8 @@ "dev": true, "optional": true, "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.3" } }, "npmlog": { @@ -13025,10 +13024,10 @@ "dev": true, "optional": true, "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" } }, "number-is-nan": { @@ -13047,7 +13046,7 @@ "bundled": true, "dev": true, "requires": { - "wrappy": "1" + "wrappy": "1.0.2" } }, "os-homedir": { @@ -13068,8 +13067,8 @@ "dev": true, "optional": true, "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" } }, "path-is-absolute": { @@ -13090,10 +13089,10 @@ "dev": true, "optional": true, "requires": { - "deep-extend": "^0.5.1", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" + "deep-extend": "0.5.1", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" }, "dependencies": { "minimist": { @@ -13110,13 +13109,13 @@ "dev": true, "optional": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "rimraf": { @@ -13125,7 +13124,7 @@ "dev": true, "optional": true, "requires": { - "glob": "^7.0.5" + "glob": "7.1.2" } }, "safe-buffer": { @@ -13168,9 +13167,9 @@ "bundled": true, "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" } }, "string_decoder": { @@ -13179,7 +13178,7 @@ "dev": true, "optional": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.1" } }, "strip-ansi": { @@ -13187,7 +13186,7 @@ "bundled": true, "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" } }, "strip-json-comments": { @@ -13202,13 +13201,13 @@ "dev": true, "optional": true, "requires": { - "chownr": "^1.0.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.2.4", - "minizlib": "^1.1.0", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.1", - "yallist": "^3.0.2" + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.2.4", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.1", + "yallist": "3.0.2" } }, "util-deprecate": { @@ -13223,7 +13222,7 @@ "dev": true, "optional": true, "requires": { - "string-width": "^1.0.2" + "string-width": "1.0.2" } }, "wrappy": { @@ -13388,10 +13387,10 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "brace-expansion": "1.1.11" } }, "ms": { @@ -17785,6 +17784,11 @@ } } }, + "object-diff": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/object-diff/-/object-diff-0.0.4.tgz", + "integrity": "sha1-2IOwRE/o/W4E5ZXXu2ZWgskWBH8=" + }, "object-keys": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", @@ -17890,7 +17894,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, "requires": { "isobject": "3.0.1" }, @@ -17898,8 +17901,7 @@ "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" } } }, @@ -21351,7 +21353,7 @@ "useragent": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", + "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", "dev": true, "requires": { "lru-cache": "4.1.1", diff --git a/package.json b/package.json index 2c54f8e88f..00ac7403e0 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,8 @@ "material-design-lite": "^1.3.0", "mg-crud": "^1.1.2", "npm": "^5.10.0", + "object-diff": "0.0.4", + "object.pick": "^1.3.0", "oclazyload": "^0.6.3", "require-yaml": "0.0.1", "validator": "^6.2.1" diff --git a/services/claim/common/methods/claim/specs/createFromSales.spec.js b/services/claim/common/methods/claim/specs/createFromSales.spec.js index 8e770fd7f7..00a6054a46 100644 --- a/services/claim/common/methods/claim/specs/createFromSales.spec.js +++ b/services/claim/common/methods/claim/specs/createFromSales.spec.js @@ -24,7 +24,7 @@ describe('Claim Create', () => { let params = {claim: newClaim, sales: newSale}; it('should create a new claim', async() => { - let claim = await app.models.Claim.createFromSales(params); + let claim = await app.models.Claim.update(params); expect(claim.ticketFk).toEqual(newClaim.ticketFk); expect(claim.clientFk).toEqual(newClaim.clientFk); diff --git a/services/claim/common/methods/claim/specs/updateClaim.spec.js b/services/claim/common/methods/claim/specs/updateClaim.spec.js new file mode 100644 index 0000000000..d6d241348d --- /dev/null +++ b/services/claim/common/methods/claim/specs/updateClaim.spec.js @@ -0,0 +1,124 @@ +const app = require(`${servicesDir}/claim/server/server`); + +fdescribe('Update Claim', () => { + let newDate = new Date(); + let newInstance; + let original = { + ticketFk: 3, + clientFk: 101, + ticketCreated: newDate, + workerFk: 18, + claimStateFk: 2, + isChargedToMana: true, + responsibility: 4, + observation: 'observation' + }; + + beforeAll(async() => { + newInstance = await app.models.Claim.create(original); + }); + + afterAll(async() => { + await app.models.Claim.destroyById(newInstance.id); + }); + + it('should throw error if isSaleAssistant is false and try to modify a forbidden field', async() => { + let params = { + id: newInstance.id, + ticketFk: 3, + clientFk: 101, + ticketCreated: newDate, + workerFk: 18, + isChargedToMana: false, + responsibility: 3, + observation: 'another' + }; + let ctx = { + req: { + accessToken: { + userId: 18 + } + } + }; + await app.models.Claim.updateClaim(ctx, params) + .catch(e => { + error = e; + }); + + expect(error.message).toEqual(`You don't have enough privileges to change that field`); + }); + + it('should throw error if isSaleAssistant is false and try to modify a valid field but a forbidden stated', async() => { + let params = { + id: newInstance.id, + ticketFk: 3, + clientFk: 101, + ticketCreated: newDate, + workerFk: 18, + claimStateFk: 4, + observation: 'another' + }; + let ctx = { + req: { + accessToken: { + userId: 18 + } + } + }; + await app.models.Claim.updateClaim(ctx, params) + .catch(e => { + error = e; + }); + + expect(error.message).toEqual(`You don't have enough privileges to change that field`); + }); + + it('should change field observation', async() => { + let params = { + id: newInstance.id, + ticketCreated: newDate, + observation: 'another3' + }; + let ctx = { + req: { + accessToken: { + userId: 18 + } + } + }; + await app.models.Claim.updateClaim(ctx, params); + + let claimUpdated = await app.models.Claim.findById(newInstance.id); + + expect(claimUpdated.observation).toEqual(params.observation); + }); + + it('should change sensible fields as salesAssistant', async() => { + let params = { + id: newInstance.id, + ticketFk: 3, + clientFk: 101, + ticketCreated: newDate, + workerFk: 18, + claimStateFk: 3, + isChargedToMana: true, + responsibility: 3, + observation: 'another' + }; + let ctx = { + req: { + accessToken: { + userId: 21 + } + } + }; + await app.models.Claim.updateClaim(ctx, params); + + let claimUpdated = await app.models.Claim.findById(newInstance.id); + + expect(claimUpdated.observation).toEqual(params.observation); + expect(claimUpdated.claimStateFk).toEqual(params.claimStateFk); + expect(claimUpdated.responsibility).toEqual(params.responsibility); + expect(claimUpdated.isChargedToMana).toEqual(params.isChargedToMana); + }); +}); diff --git a/services/claim/common/methods/claim/updateClaim.js b/services/claim/common/methods/claim/updateClaim.js new file mode 100644 index 0000000000..3071776eae --- /dev/null +++ b/services/claim/common/methods/claim/updateClaim.js @@ -0,0 +1,50 @@ +const UserError = require('vn-loopback/common/helpers').UserError; +var pick = require('object.pick'); +var diff = require('object-diff'); + +module.exports = Self => { + Self.remoteMethodCtx('updateClaim', { + description: 'Update a claim with privileges', + accessType: 'WRITE', + accepts: [{ + arg: 'params', + type: 'object', + required: true, + description: 'ticketFk, stateFk', + http: {source: 'body'} + }], + returns: { + type: 'string', + root: true + }, + http: { + path: `/updateClaim`, + verb: 'post' + } + }); + + Self.updateClaim = async(ctx, params) => { + let models = Self.app.models; + let isSalesAssistant; + let token = ctx.req.accessToken; + let currentUserId = token && token.userId; + + isSalesAssistant = await models.Account.hasRole(currentUserId, 'SalesAssistant'); + + if (!isSalesAssistant) { + let oldClaim = await models.Claim.findById(params.id); + let notModifiable = ['responsibility', 'isChargedToMana']; + let changedFields = diff(oldClaim, params); + let changedFieldsPicked = pick(changedFields, notModifiable); + let statesViables = ['Gestionado', 'Pendiente']; + let oldState = await models.ClaimState.findOne({where: {id: oldClaim.claimStateFk}}); + let newState = await models.ClaimState.findOne({where: {id: params.claimStateFk}}); + let canChangeState = statesViables.includes(oldState.description) + && statesViables.includes(newState.description); + if (Object.keys(changedFieldsPicked).length != 0 || !canChangeState) + throw new UserError(`You don't have enough privileges to change that field`); + } + + return await Self.updateAll({id: params.id}, params); + }; +}; diff --git a/services/claim/common/models/claim.js b/services/claim/common/models/claim.js index 73a6da1d71..cd5f1f08ef 100644 --- a/services/claim/common/models/claim.js +++ b/services/claim/common/models/claim.js @@ -1,4 +1,5 @@ module.exports = Self => { require('../methods/claim/getSummary')(Self); require('../methods/claim/createFromSales')(Self); + require('../methods/claim/updateClaim')(Self); }; diff --git a/services/loopback/common/locale/es.json b/services/loopback/common/locale/es.json index f13c016c2f..78ef386f50 100644 --- a/services/loopback/common/locale/es.json +++ b/services/loopback/common/locale/es.json @@ -47,5 +47,6 @@ "The warehouse can't be repeated": "El almacén no puede repetirse", "The tag can't be repeated": "El tag no puede repetirse", "The observation type can't be repeated": "El tipo de observación no puede repetirse", - "A claim with that sale already exists": "Ya existe una reclamación para esta línea" + "A claim with that sale already exists": "Ya existe una reclamación para esta línea", + "You don't have enough privileges to change that field": "You don't have enough privileges to change that field" } \ No newline at end of file