From ea701db703edacf3b743b0d1dc0f16fa23675de0 Mon Sep 17 00:00:00 2001 From: sjvans <30337871+sjvans@users.noreply.github.com> Date: Mon, 13 Oct 2025 16:46:39 +0200 Subject: [PATCH 1/9] Update travel-service.cds --- srv/travel-service.cds | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srv/travel-service.cds b/srv/travel-service.cds index f1043d3..b947d5c 100644 --- a/srv/travel-service.cds +++ b/srv/travel-service.cds @@ -10,8 +10,8 @@ service TravelService { ]) entity Travels as projection on db.Travels actions { action createTravelByTemplate() returns Travels; - action rejectTravel(); - action acceptTravel(); + @to: #Canceled action rejectTravel(); + @to: #Accepted action acceptTravel(); action deductDiscount( percent: Percentage not null ) returns Travels; } From e0ba35996322709c469bf541c98c3b6ff9c127c5 Mon Sep 17 00:00:00 2001 From: D050513 Date: Tue, 28 Oct 2025 11:15:59 +0100 Subject: [PATCH 2/9] CRUD --- db/schema.cds | 6 +++++- srv/travel-service.cds | 22 +++++++++++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/db/schema.cds b/db/schema.cds index 079b721..57e7e22 100644 --- a/db/schema.cds +++ b/db/schema.cds @@ -1,13 +1,15 @@ namespace sap.capire.travels; using { sap, managed, Country, Currency } from '@sap/cds/common'; +// using { sap.common.FlowHistory as FlowHistory } from '@sap/cds/common'; using { sap.capire.travels.masterdata.Flights, sap.capire.travels.masterdata.Supplements, } from './master-data'; -entity Travels : managed { +// TODO: how add FlowHistory? +entity Travels : managed /* , FlowHistory */ { key ID : Integer default 0 @readonly; Description : String(1024); BeginDate : Date default $now; @@ -15,6 +17,7 @@ entity Travels : managed { BookingFee : Price default 0; TotalPrice : Price @readonly; Currency : Currency default 'EUR'; + // @flow.status Status : Association to TravelStatus @readonly default 'O'; Agency : Association to TravelAgencies; Customer : Association to Passengers; @@ -72,4 +75,5 @@ entity TravelStatus : sap.common.CodeList { } } + type Price : Decimal(9,4); diff --git a/srv/travel-service.cds b/srv/travel-service.cds index b947d5c..9fe97cb 100644 --- a/srv/travel-service.cds +++ b/srv/travel-service.cds @@ -8,13 +8,27 @@ service TravelService { { grant: ['*'], to: 'processor'}, { grant: ['*'], to: 'admin'} ]) - entity Travels as projection on db.Travels actions { + entity Travels as projection on db.Travels + // TODO: how to exclude transitions_ automatically? + // excluding { transitions_ } + actions { action createTravelByTemplate() returns Travels; - @to: #Canceled action rejectTravel(); - @to: #Accepted action acceptTravel(); + action rejectTravel(); + action acceptTravel(); action deductDiscount( percent: Percentage not null ) returns Travels; } + // TODO: is it a problem to add @flow.status here but FlowHistory in db? + annotate Travels with @flow.status: status actions { + NEW /* @from: [ null ] */ @to: /* #Draft */ #Open; + SAVE /* @from: [ #Draft ] */ @to: #Open; + cancel @from: [ #Open ] @to: #Cancelled; + rejectTravel @from: [ #Open ] @to: #Rejected; + acceptTravel @from: [ #Open ] @to: #Approved; + close @from: [ #Approved ] @to: #Closed; + EDIT @from: [ #Approved, #Rejected ] @to: /* #Draft */ #Open; + }; + // Also expose Flights and Currencies for travel booking UIs and Value Helps @readonly entity Flights as projection on db.masterdata.Flights; @readonly entity Supplements as projection on db.masterdata.Supplements; @@ -23,6 +37,7 @@ service TravelService { // Export functions to export download travel data function exportJSON() returns LargeBinary @Core.MediaType:'application/json'; function exportCSV() returns LargeBinary @Core.MediaType:'text/csv'; + } @@ -41,4 +56,5 @@ entity TravelsExport @cds.persistence.skip as projection on db.Travels { Description } + type Percentage : Integer @assert.range: [1,100]; From 762ec7a826b1b25be020c7e22a8854732b364678 Mon Sep 17 00:00:00 2001 From: D050513 Date: Wed, 5 Nov 2025 16:17:08 +0100 Subject: [PATCH 3/9] annotate TravelService.Travels --- cds | 1 + package.json | 5 ++++- srv/travel-service.cds | 5 ++++- 3 files changed, 9 insertions(+), 2 deletions(-) create mode 160000 cds diff --git a/cds b/cds new file mode 160000 index 0000000..727be92 --- /dev/null +++ b/cds @@ -0,0 +1 @@ +Subproject commit 727be92d6ab98afe73fe009a7d90ab983603605f diff --git a/package.json b/package.json index 5de2c21..c2e7e5c 100644 --- a/package.json +++ b/package.json @@ -13,12 +13,15 @@ "@capire/xflights-data": "*", "@cap-js/xsrv-federation": ".plugins/fed-xrv", "@sap-cloud-sdk/http-client": "^4", - "@sap/cds": ">=9", + "@sap/cds": "*", "express": "^4" }, "devDependencies": { "@cap-js/cds-test": "*", "@cap-js/sqlite": ">=2" }, + "workspaces": [ + "cds" + ], "license": "Apache-2.0" } diff --git a/srv/travel-service.cds b/srv/travel-service.cds index 9fe97cb..ff7c70d 100644 --- a/srv/travel-service.cds +++ b/srv/travel-service.cds @@ -19,7 +19,7 @@ service TravelService { } // TODO: is it a problem to add @flow.status here but FlowHistory in db? - annotate Travels with @flow.status: status actions { + annotate Travels with @flow.status: Status actions { NEW /* @from: [ null ] */ @to: /* #Draft */ #Open; SAVE /* @from: [ #Draft ] */ @to: #Open; cancel @from: [ #Open ] @to: #Cancelled; @@ -29,6 +29,9 @@ service TravelService { EDIT @from: [ #Approved, #Rejected ] @to: /* #Draft */ #Open; }; + // extend db.Travels with sap.common.FlowHistory; + // extend projection Travels with {} excluding { transitions_ }; + // Also expose Flights and Currencies for travel booking UIs and Value Helps @readonly entity Flights as projection on db.masterdata.Flights; @readonly entity Supplements as projection on db.masterdata.Supplements; From b7dce30926ed8e371c6b9802c2cc834e492e1297 Mon Sep 17 00:00:00 2001 From: D050513 Date: Tue, 11 Nov 2025 22:05:53 +0100 Subject: [PATCH 4/9] "history_for_flows": "all" --- package.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index c2e7e5c..df10836 100644 --- a/package.json +++ b/package.json @@ -23,5 +23,10 @@ "workspaces": [ "cds" ], - "license": "Apache-2.0" + "license": "Apache-2.0", + "cds": { + "features": { + "history_for_flows": "all" + } + } } From cca6145d893cf3d08b48a00954ee07174f313a35 Mon Sep 17 00:00:00 2001 From: D050513 Date: Tue, 11 Nov 2025 23:40:50 +0100 Subject: [PATCH 5/9] it flows like a charm --- db/schema.cds | 7 ++-- srv/travel-service.cds | 19 +++++----- test/flows.test.js | 86 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 14 deletions(-) create mode 100644 test/flows.test.js diff --git a/db/schema.cds b/db/schema.cds index 57e7e22..d86b055 100644 --- a/db/schema.cds +++ b/db/schema.cds @@ -1,15 +1,13 @@ namespace sap.capire.travels; using { sap, managed, Country, Currency } from '@sap/cds/common'; -// using { sap.common.FlowHistory as FlowHistory } from '@sap/cds/common'; using { sap.capire.travels.masterdata.Flights, sap.capire.travels.masterdata.Supplements, } from './master-data'; -// TODO: how add FlowHistory? -entity Travels : managed /* , FlowHistory */ { +entity Travels : managed { key ID : Integer default 0 @readonly; Description : String(1024); BeginDate : Date default $now; @@ -17,7 +15,6 @@ entity Travels : managed /* , FlowHistory */ { BookingFee : Price default 0; TotalPrice : Price @readonly; Currency : Currency default 'EUR'; - // @flow.status Status : Association to TravelStatus @readonly default 'O'; Agency : Association to TravelAgencies; Customer : Association to Passengers; @@ -72,6 +69,8 @@ entity TravelStatus : sap.common.CodeList { Open = 'O'; Accepted = 'A'; Canceled = 'X'; + + Rejected = 'R'; } } diff --git a/srv/travel-service.cds b/srv/travel-service.cds index ff7c70d..d4a7e0a 100644 --- a/srv/travel-service.cds +++ b/srv/travel-service.cds @@ -9,28 +9,27 @@ service TravelService { { grant: ['*'], to: 'admin'} ]) entity Travels as projection on db.Travels - // TODO: how to exclude transitions_ automatically? - // excluding { transitions_ } actions { action createTravelByTemplate() returns Travels; action rejectTravel(); action acceptTravel(); action deductDiscount( percent: Percentage not null ) returns Travels; + + action reopenTravel(); } - // TODO: is it a problem to add @flow.status here but FlowHistory in db? annotate Travels with @flow.status: Status actions { NEW /* @from: [ null ] */ @to: /* #Draft */ #Open; SAVE /* @from: [ #Draft ] */ @to: #Open; - cancel @from: [ #Open ] @to: #Cancelled; + // cancel @from: [ #Open ] @to: #Canceled; rejectTravel @from: [ #Open ] @to: #Rejected; - acceptTravel @from: [ #Open ] @to: #Approved; - close @from: [ #Approved ] @to: #Closed; - EDIT @from: [ #Approved, #Rejected ] @to: /* #Draft */ #Open; - }; + acceptTravel @from: [ #Open ] @to: #Accepted; + // close @from: [ #Accepted ] @to: #Closed; + EDIT @from: [ #Accepted, #Rejected ] @to: /* #Draft */ #Open; - // extend db.Travels with sap.common.FlowHistory; - // extend projection Travels with {} excluding { transitions_ }; + reopenTravel @from: [ #Accepted, #Rejected ] @to: $flow.previous; + PATCH /* @from: [ #Open ] */ @to: #Rejected; + }; // Also expose Flights and Currencies for travel booking UIs and Value Helps @readonly entity Flights as projection on db.masterdata.Flights; diff --git a/test/flows.test.js b/test/flows.test.js new file mode 100644 index 0000000..9ed4918 --- /dev/null +++ b/test/flows.test.js @@ -0,0 +1,86 @@ +const cds = require('@sap/cds') + +const { GET, POST, PATCH, DELETE, axios, expect } = cds.test(__dirname + '/..', '--with-mocks') +axios.defaults.auth = { username: 'alice', password: 'admin' } +axios.defaults.validateStatus = () => true + +describe('Status Transition Flows', () => { + const READ = async (ID, IsActiveEntity = true) => { + const { data: travel } = await GET( + `/odata/v4/travel/Travels(ID=${ID},IsActiveEntity=${IsActiveEntity})${ + IsActiveEntity ? '?$expand=transitions_' : '' + }` + ) + return travel + } + + beforeEach(async () => { + await cds.ql.DELETE('TravelService.Travels.transitions_') + }) + + it('flows like a charm', async () => { + let travel + + travel = await READ(1) + expect(travel.Status_code).to.eql('O') + expect(travel.transitions_).to.have.length(0) + + await POST('/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/acceptTravel', {}) + travel = await READ(1) + expect(travel.Status_code).to.eql('A') + expect(travel.transitions_).to.have.length(1) + + await POST('/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/draftEdit', {}) + travel = await READ(1, false) + expect(travel.Status_code).to.eql('O') + + const res = await GET('/odata/v4/travel/Travels(ID=1,IsActiveEntity=false)?$expand=transitions_') + expect(res.status).to.eql(400) + + await PATCH('/odata/v4/travel/Travels(ID=1,IsActiveEntity=false)', { Description: 'foo' }) + travel = await READ(1, false) + expect(travel.Status_code).to.eql('R') + + await POST('/odata/v4/travel/Travels(ID=1,IsActiveEntity=false)/draftActivate', {}) + travel = await READ(1) + expect(travel.Status_code).to.eql('O') + expect(travel.transitions_).to.have.length(2) + + await POST('/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/rejectTravel', {}) + travel = await READ(1) + expect(travel.Status_code).to.eql('R') + expect(travel.transitions_).to.have.length(3) + + await POST('/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/reopenTravel', {}) + travel = await READ(1) + expect(travel.Status_code).to.eql('O') + expect(travel.transitions_).to.have.length(4) + }) + + it('prohibits altering the flow history', async () => { + let res + + await POST('/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/acceptTravel', {}) + const travel = await READ(1) + expect(travel.Status_code).to.eql('A') + expect(travel.transitions_).to.have.length(1) + + const transition = `up__ID=1,timestamp=${travel.transitions_[0].timestamp}` + + res = await GET(`/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/transitions_(${transition})`) + expect(res.status).to.eql(200) + + res = await POST('/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/transitions_', { + comment: `I shouldn't be able to do this` + }) + expect(res.status).to.eql(405) + + res = await PATCH(`/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/transitions_(${transition})`, { + comment: `Not this either` + }) + expect(res.status).to.eql(405) + + res = await DELETE(`/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/transitions_(${transition})`) + expect(res.status).to.eql(405) + }) +}) From cf1fdba20f755d3702d6bfe39a32c166b6f73327 Mon Sep 17 00:00:00 2001 From: D050513 Date: Wed, 12 Nov 2025 00:07:01 +0100 Subject: [PATCH 6/9] skipped test `Status Transition Flows excluding transitions_` --- test/flows-excl-transitions.test.js | 86 +++++++++++++++++++++++++++++ test/flows.test.js | 2 +- 2 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 test/flows-excl-transitions.test.js diff --git a/test/flows-excl-transitions.test.js b/test/flows-excl-transitions.test.js new file mode 100644 index 0000000..3f0ad68 --- /dev/null +++ b/test/flows-excl-transitions.test.js @@ -0,0 +1,86 @@ +process.env.cds_features_exclude__flow__transitions = true + +const cds = require('@sap/cds') + +const { GET, POST, PATCH, DELETE, axios, expect } = cds.test(__dirname + '/..', '--with-mocks') +axios.defaults.auth = { username: 'alice', password: 'admin' } +axios.defaults.validateStatus = () => true + +describe.skip('Status Transition Flows excluding transitions_', () => { + const READ = async (ID, IsActiveEntity = true) => { + const { data: travel } = await GET(`/odata/v4/travel/Travels(ID=${ID},IsActiveEntity=${IsActiveEntity})`) + const transitions_ = await SELECT.from('sap.capire.travels.Travels.transitions_').where({ up__ID: ID }) + travel.transitions_ = transitions_ + return travel + } + + beforeEach(async () => { + await cds.ql.DELETE('sap.capire.travels.Travels.transitions_') + }) + + it('flows like a charm', async () => { + let travel + + travel = await READ(1) + expect(travel.Status_code).to.eql('O') + expect(travel.transitions_).to.have.length(0) + + await POST('/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/acceptTravel', {}) + travel = await READ(1) + expect(travel.Status_code).to.eql('A') + expect(travel.transitions_).to.have.length(1) + + await POST('/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/draftEdit', {}) + travel = await READ(1, false) + expect(travel.Status_code).to.eql('O') + + const res = await GET('/odata/v4/travel/Travels(ID=1,IsActiveEntity=false)?$expand=transitions_') + expect(res.status).to.eql(400) + + await PATCH('/odata/v4/travel/Travels(ID=1,IsActiveEntity=false)', { Description: 'foo' }) + travel = await READ(1, false) + expect(travel.Status_code).to.eql('R') + + await POST('/odata/v4/travel/Travels(ID=1,IsActiveEntity=false)/draftActivate', {}) + travel = await READ(1) + expect(travel.Status_code).to.eql('O') + expect(travel.transitions_).to.have.length(2) + + await POST('/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/rejectTravel', {}) + travel = await READ(1) + expect(travel.Status_code).to.eql('R') + expect(travel.transitions_).to.have.length(3) + + await POST('/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/reopenTravel', {}) + travel = await READ(1) + expect(travel.Status_code).to.eql('O') + expect(travel.transitions_).to.have.length(4) + }) + + it('prohibits altering the flow history', async () => { + let res + + await POST('/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/acceptTravel', {}) + const travel = await READ(1) + expect(travel.Status_code).to.eql('A') + expect(travel.transitions_).to.have.length(1) + + const transition = `up__ID=1,timestamp=${travel.transitions_[0].timestamp}` + + res = await GET(`/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/transitions_(${transition})`) + expect(res.status).to.eql(200) + + res = await POST('/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/transitions_', { + comment: `I shouldn't be able to do this` + }) + expect(res.status).to.eql(405) + + res = await PATCH(`/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/transitions_(${transition})`, { + comment: `Not this either` + }) + expect(res.status).to.eql(405) + + res = await DELETE(`/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/transitions_(${transition})`) + expect(res.status).to.eql(405) + }) +}) diff --git a/test/flows.test.js b/test/flows.test.js index 9ed4918..bfaa143 100644 --- a/test/flows.test.js +++ b/test/flows.test.js @@ -15,7 +15,7 @@ describe('Status Transition Flows', () => { } beforeEach(async () => { - await cds.ql.DELETE('TravelService.Travels.transitions_') + await cds.ql.DELETE('sap.capire.travels.Travels.transitions_') }) it('flows like a charm', async () => { From 2d36723eba3ef6fbf1564b120adcd118684d63e8 Mon Sep 17 00:00:00 2001 From: D050513 Date: Wed, 12 Nov 2025 00:16:41 +0100 Subject: [PATCH 7/9] rm history_for_flows --- package.json | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/package.json b/package.json index df10836..c2e7e5c 100644 --- a/package.json +++ b/package.json @@ -23,10 +23,5 @@ "workspaces": [ "cds" ], - "license": "Apache-2.0", - "cds": { - "features": { - "history_for_flows": "all" - } - } + "license": "Apache-2.0" } From c213419d03c3295b3691aa69f5b429c17a5fa443 Mon Sep 17 00:00:00 2001 From: D050513 Date: Wed, 12 Nov 2025 00:16:56 +0100 Subject: [PATCH 8/9] rm test/flows-excl-transitions.test.js --- test/flows-excl-transitions.test.js | 86 ----------------------------- 1 file changed, 86 deletions(-) delete mode 100644 test/flows-excl-transitions.test.js diff --git a/test/flows-excl-transitions.test.js b/test/flows-excl-transitions.test.js deleted file mode 100644 index 3f0ad68..0000000 --- a/test/flows-excl-transitions.test.js +++ /dev/null @@ -1,86 +0,0 @@ -process.env.cds_features_exclude__flow__transitions = true - -const cds = require('@sap/cds') - -const { GET, POST, PATCH, DELETE, axios, expect } = cds.test(__dirname + '/..', '--with-mocks') -axios.defaults.auth = { username: 'alice', password: 'admin' } -axios.defaults.validateStatus = () => true - -describe.skip('Status Transition Flows excluding transitions_', () => { - const READ = async (ID, IsActiveEntity = true) => { - const { data: travel } = await GET(`/odata/v4/travel/Travels(ID=${ID},IsActiveEntity=${IsActiveEntity})`) - const transitions_ = await SELECT.from('sap.capire.travels.Travels.transitions_').where({ up__ID: ID }) - travel.transitions_ = transitions_ - return travel - } - - beforeEach(async () => { - await cds.ql.DELETE('sap.capire.travels.Travels.transitions_') - }) - - it('flows like a charm', async () => { - let travel - - travel = await READ(1) - expect(travel.Status_code).to.eql('O') - expect(travel.transitions_).to.have.length(0) - - await POST('/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/acceptTravel', {}) - travel = await READ(1) - expect(travel.Status_code).to.eql('A') - expect(travel.transitions_).to.have.length(1) - - await POST('/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/draftEdit', {}) - travel = await READ(1, false) - expect(travel.Status_code).to.eql('O') - - const res = await GET('/odata/v4/travel/Travels(ID=1,IsActiveEntity=false)?$expand=transitions_') - expect(res.status).to.eql(400) - - await PATCH('/odata/v4/travel/Travels(ID=1,IsActiveEntity=false)', { Description: 'foo' }) - travel = await READ(1, false) - expect(travel.Status_code).to.eql('R') - - await POST('/odata/v4/travel/Travels(ID=1,IsActiveEntity=false)/draftActivate', {}) - travel = await READ(1) - expect(travel.Status_code).to.eql('O') - expect(travel.transitions_).to.have.length(2) - - await POST('/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/rejectTravel', {}) - travel = await READ(1) - expect(travel.Status_code).to.eql('R') - expect(travel.transitions_).to.have.length(3) - - await POST('/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/reopenTravel', {}) - travel = await READ(1) - expect(travel.Status_code).to.eql('O') - expect(travel.transitions_).to.have.length(4) - }) - - it('prohibits altering the flow history', async () => { - let res - - await POST('/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/acceptTravel', {}) - const travel = await READ(1) - expect(travel.Status_code).to.eql('A') - expect(travel.transitions_).to.have.length(1) - - const transition = `up__ID=1,timestamp=${travel.transitions_[0].timestamp}` - - res = await GET(`/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/transitions_(${transition})`) - expect(res.status).to.eql(200) - - res = await POST('/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/transitions_', { - comment: `I shouldn't be able to do this` - }) - expect(res.status).to.eql(405) - - res = await PATCH(`/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/transitions_(${transition})`, { - comment: `Not this either` - }) - expect(res.status).to.eql(405) - - res = await DELETE(`/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/transitions_(${transition})`) - expect(res.status).to.eql(405) - }) -}) From 4425f0a3079ffed1239ff71ee632ae19d2916c0c Mon Sep 17 00:00:00 2001 From: D050513 Date: Tue, 18 Nov 2025 20:28:22 +0100 Subject: [PATCH 9/9] adjust re transitions_ being excluded from projections --- test/flows.test.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/test/flows.test.js b/test/flows.test.js index bfaa143..b5b777f 100644 --- a/test/flows.test.js +++ b/test/flows.test.js @@ -6,11 +6,9 @@ axios.defaults.validateStatus = () => true describe('Status Transition Flows', () => { const READ = async (ID, IsActiveEntity = true) => { - const { data: travel } = await GET( - `/odata/v4/travel/Travels(ID=${ID},IsActiveEntity=${IsActiveEntity})${ - IsActiveEntity ? '?$expand=transitions_' : '' - }` - ) + const { data: travel } = await GET(`/odata/v4/travel/Travels(ID=${ID},IsActiveEntity=${IsActiveEntity})`) + if (IsActiveEntity) + travel.transitions_ = await SELECT('sap.capire.travels.Travels.transitions_').where({ up__ID: ID }) return travel } @@ -57,7 +55,8 @@ describe('Status Transition Flows', () => { expect(travel.transitions_).to.have.length(4) }) - it('prohibits altering the flow history', async () => { + // NOTE: not applicable with transitions_ being excluded from projections + it.skip('prohibits altering the flow history', async () => { let res await POST('/odata/v4/travel/Travels(ID=1,IsActiveEntity=true)/acceptTravel', {})