cancel
Showing results for 
Search instead for 
Did you mean: 

View on Enitity overwrites Entity on Save in Cloud

schait
Discoverer
0 Kudos

Hello everyone!
I've noticed a bug within our application and need some advice on that matter. We use multiple services, which each of them has a specific view on the enitity (e.g. select entity with a specific status). Our data model looks something like this: 

entity InsuranceContract : managed, cuid {
...
ContractDetails                                   : Composition of many ContractDetails on ContractDetails.InsuranceContract = $self;
Reversed                                          : Association to many Reversed on Reversed.InsuranceContract = $self;
}
entity ContractDetails : managed, cuid {
...
@UI.Hidden
InsuranceContract                      : Association to InsuranceContract;
} 

view Reversed as
select from ContractDetails { 
*
} where
contractDetailStatus.code in (
   'CANCELED', 'REVERSED'
 );

 and the Service definition like this: 

service Service1 {
@odata.draft.enabled
entity InsuranceContract as projection on my.InsuranceContract actions {...};
@cds.redirection.target: true
entity ContractDetails   as
select from my.ContractDetails {
      *
}
where contractDetailStatus.code not in ('CANCELED', 'REVERSED', 'TRANSFER_OK')
actions {...};
entity Reversed          as projection on my.Reversed actions {...};

We've created a Object Page for InsuranceContract, in which all related ContractDetails are shown in Table1 and all related Reversed in Table2. Since InsuranceContract is draft enabled, we hit the Edit button and afterwards the Save button, ergo saving without any changes. 

Now the following happens in the deployed application: 

Table1 remains the same with all ContractDetails, but all entries in Table2 are gone. We realised that the Reversed Entities are deleted from the HANA by calling the API on the Entity ContractDetails. This happens only in the deployed application, it doesn't happen when we are running the application locally with sqlite. 

All custom save handlers were disabled, therefore, the error either is within our definition or something else. We noticed in similiar services the same behaviour, if there is a view with a filter, the filter "deletes" the data which does not apply to it. 

Any advice? 

Thank you in advance 🙂 

Accepted Solutions (0)

Answers (1)

Answers (1)

OlenaT
Advisor
Advisor
0 Kudos

Hi schait,

The problem is in the service modeling. The root entity InsuranceContract has a composition of many relationship with a child entity ContractDetails, which is exposed in the service Service1 as select from the model entity with an additional where condition. This where condition is basically trying to redefine the parent - child relationship, which is not supported. Please delete the where condition in your service and implement filter for children in the UI or in a custom handler. 

One of the reasons why we don't support such where conditions: Consider a DELETE request to a root entity. In this case all children of this entity should also be deleted. In your case, children with contractDetailStatus.code equal 'CANCELED', 'REVERSED' or 'TRANSFER_OK' don't belong to the exposed entity Service1.ContractDetails and will be left orphaned which is a wrong behaviour. 

Hope this helps.

Best regards,

Olena 

schait
Discoverer
0 Kudos

Hello @OlenaT ,
thank you for your response!

I understand now that the association is an issue. My follow up question now is, do you support multiple compositions in the parent entity? We rebuild the data model to the following: 

entity InsuranceContract : managed, cuid {
 ...
ContractDetails                                   : Composition of many ContractDetails on  ContractDetails.InsuranceContract         =      $self
                                                        and ContractDetails.contractDetailStatus.code not in ('CANCELED', 'REVERSED'
                                                        );
 Reversed                                          : Composition of many ContractDetails
                                                        on Reversed.InsuranceContract = $self
                                                        and (
                                                             Reversed.contractDetailStatus.code = 'CANCELED'
                                                          or Reversed.contractDetailStatus.code = 'REVERSED'
                                                        );
}

If you do, we still expierence some issues. With this data model, we lose all ContractDetails upon saving a draft in each table. I've noticed with the debugging in sqlite a DELETE is called after saving the draft on the entity ContractDetails. The DELETEs on the draft table entries make sense, but not on the data. 

We also run into issues in different services. We have a Service1, which is available for a customer for example. There we have a view on ContractDetails, which filters out relevant ContractDetails for the customer e.g. contractDetailStatus.code != TRANSFERED. In Service2 we have an overview of transfered ContractDetails, therefore, a view on ContractDetails == TRANSFERED. If the customer transferes these details in Service1, the details should show up in Service2. They do to some degree, but Service2 shows only the last Draft session, so if the customer saves their draft, only the transfered details would show up. If the customer does another save, the details of the first save get lost. 

Would you be so kind an offer me a proposal of how to implement this scenario I've described? 

Best Regards, 

Tanja 

OlenaT
Advisor
Advisor
0 Kudos

Hi Tanja,

The problem is the composition, not the association. Unfortunately we don't support your second example out of the box as well, it's not clear how a POST request should work in the case of this filter.

To implement the described scenario with different services please either consult with UI experts if it's possible to filter out the results with values equal or not equal to TRANSFERED or consider to do it with the custom coding for example in the srv.before('SAVE', 'MyEntity', /*...*/) handler. 

Best regards,

Olena