diff --git a/orders/db/_schema._cds b/orders/db/_schema._cds new file mode 100644 index 00000000..85effeaf --- /dev/null +++ b/orders/db/_schema._cds @@ -0,0 +1,24 @@ +using { Currency, User, managed, cuid } from '@sap/cds/common'; +namespace sap.capire.orders; + +entity Orders : cuid, managed { + OrderNo : String @title:'Order Number'; //> readable key + Items : Composition of many { + key ID : UUID; + product : Association to Products; + quantity : Integer; + title : String; //> intentionally replicated as snapshot from product.title + price : Double; //> materialized calculated field + }; + buyer : User; + currency : Currency; +} + +/** This is a stand-in for arbitrary ordered Products */ +entity Products @(cds.persistence.skip:'always') { + key ID : String; +} + + +// this is to ensure we have filled-in currencies +using from '@capire/common'; diff --git a/orders/db/data/sap.capire.orders-Orders.csv b/orders/db/data/sap.capire.orders-OrdersHeaders.csv similarity index 100% rename from orders/db/data/sap.capire.orders-Orders.csv rename to orders/db/data/sap.capire.orders-OrdersHeaders.csv diff --git a/orders/db/data/sap.capire.orders-Orders.Items.csv b/orders/db/data/sap.capire.orders-OrdersItems.csv similarity index 56% rename from orders/db/data/sap.capire.orders-Orders.Items.csv rename to orders/db/data/sap.capire.orders-OrdersItems.csv index 78487735..ba7a87ef 100644 --- a/orders/db/data/sap.capire.orders-Orders.Items.csv +++ b/orders/db/data/sap.capire.orders-OrdersItems.csv @@ -1,4 +1,4 @@ -ID;up__ID;quantity;product_ID;title;price -58040e66-1dcd-4ffb-ab10-fdce32028b79;7e2f2640-6866-4dcf-8f4d-3027aa831cad;1;201;Wuthering Heights;11.11 -64e718c9-ff99-47f1-8ca3-950c850777d4;7e2f2640-6866-4dcf-8f4d-3027aa831cad;1;271;Catweazle;15 -e9641166-e050-4261-bfee-d1e797e6cb7f;64e718c9-ff99-47f1-8ca3-950c850777d4;2;252;Eleonora;28 \ No newline at end of file +ID;Header_ID;quantity;product_ID;title;price +58040e66-1dcd-4ffb-ab10-fdce32028b79;7e2f2640-6866-4dcf-8f4d-3027aa831cad;10;201;Wuthering Heights;11.11 +64e718c9-ff99-47f1-8ca3-950c850777d4;7e2f2640-6866-4dcf-8f4d-3027aa831cad;501;271;Catweazle;15 +e9641166-e050-4261-bfee-d1e797e6cb7f;64e718c9-ff99-47f1-8ca3-950c850777d4;499;252;Eleonora;28 \ No newline at end of file diff --git a/orders/db/performance_example_schema.cds b/orders/db/performance_example_schema.cds deleted file mode 100644 index 223a6e35..00000000 --- a/orders/db/performance_example_schema.cds +++ /dev/null @@ -1,82 +0,0 @@ -using { Currency, User, managed, cuid } from '@sap/cds/common'; -using {Orders, OrderItems} from '../schema'; - -namespace sap.capire.orders; - -entity OrdersHeaders : managed { - key ID : UUID; - OrderNo : String @title:'Order Number'; //> readable key - buyer : User; - currency : Currency; - Items : Composition of many OrdersItems on Items.Header = $self; -} - -entity OrdersItems { - key ID : UUID; - product : Association to Products; - quantity : Integer; - title : String; //> intentionally replicated as snapshot from product.title - price : Double; //> materialized calculated field - Header : Association to OrdersHeaders; -}; - - -// static -view OrdersItemsViewJoin as select - - OrdersHeaders.ID as Header_ID, - OrdersHeaders.OrderNo as OrderNo, - OrdersHeaders.buyer as buyer, - OrdersHeaders.currency as currency, - OrdersItems.ID as Item_ID, - OrdersItems.product as product, - OrdersItems.quantity as quantity, - OrdersItems.title as title, - OrdersItems.price as price - - from OrdersHeaders JOIN OrdersItems on OrdersHeaders.ID = OrdersItems.Header; - -// dynamic entity -entity OrderItemsViewAssoc as projection on Orders; - -// sort on right table -view SortedOrdersJoin as select - OrdersHeaders.ID as Header_ID, - OrdersHeaders.OrderNo as OrderNo, - OrdersHeaders.buyer as buyer, - OrdersHeaders.currency as currency, - OrdersItems.ID as Item_ID, - OrdersItems.product as product, - OrdersItems.quantity as quantity, - OrdersItems.title as title, - OrdersItems.price as price -from OrdersHeaders JOIN OrdersItems on OrdersHeaders.ID = OrdersItems.Header -order by title; - -// sort on items and join back to header via assoc -view SortedOrdersAssoc as select -from OrdersItems {*, Header.OrderNo, Header.buyer, Header.currency } -order by OrdersItems.title; - -// filter on right table -view FilteredOrdersJoin as select - OrdersHeaders.ID as Header_ID, - OrdersHeaders.OrderNo as OrderNo, - OrdersHeaders.buyer as buyer, - OrdersHeaders.currency as currency, - OrdersItems.ID as Item_ID, - OrdersItems.product as product, - OrdersItems.quantity as quantity, - OrdersItems.title as title, - OrdersItems.price as price -from OrdersHeaders JOIN OrdersItems on OrdersHeaders.ID = OrdersItems.Header -where price > 100; - -// filter on items and join back to header via assoc -view FilteredOrdersAssoc as select -from OrdersItems {*, Header.OrderNo, Header.buyer, Header.currency } -where OrdersItems.price > 100; - - - - diff --git a/orders/db/schema.cds b/orders/db/schema.cds index 85effeaf..38b5fbed 100644 --- a/orders/db/schema.cds +++ b/orders/db/schema.cds @@ -1,24 +1,32 @@ using { Currency, User, managed, cuid } from '@sap/cds/common'; +// using {Orders, OrderItems} from './schema'; + namespace sap.capire.orders; -entity Orders : cuid, managed { - OrderNo : String @title:'Order Number'; //> readable key - Items : Composition of many { +entity Products { + key ID : String; +} + +entity OrdersHeaders : managed { + key ID : UUID; + OrderNo : String @title:'Order Number'; //> readable key + buyer : User; + currency : Currency; + Items : Composition of many OrdersItems on Items.Header = $self; +} + +entity OrdersItems { key ID : UUID; product : Association to Products; quantity : Integer; title : String; //> intentionally replicated as snapshot from product.title price : Double; //> materialized calculated field - }; - buyer : User; - currency : Currency; -} - -/** This is a stand-in for arbitrary ordered Products */ -entity Products @(cds.persistence.skip:'always') { - key ID : String; -} + Header : Association to OrdersHeaders; +}; + + + + + -// this is to ensure we have filled-in currencies -using from '@capire/common'; diff --git a/orders/srv/performance_example_orders-service.cds b/orders/srv/_performance_example_orders-service._cds similarity index 100% rename from orders/srv/performance_example_orders-service.cds rename to orders/srv/_performance_example_orders-service._cds diff --git a/orders/srv/orders-service.cds b/orders/srv/orders-service.cds index 119373db..c466e3e2 100644 --- a/orders/srv/orders-service.cds +++ b/orders/srv/orders-service.cds @@ -1,5 +1,87 @@ using { sap.capire.orders as my } from '../db/schema'; service OrdersService { - entity Orders as projection on my.Orders; + entity OrdersHeaders as projection on my.OrdersHeaders; + entity OrdersItems as projection on my.OrdersItems; + entity Products as projection on my.Products; + + +// static +view OrdersItemsViewJoin as select + + OrdersHeaders.ID as Header_ID, + OrdersHeaders.OrderNo as OrderNo, + OrdersHeaders.buyer as buyer, + OrdersHeaders.currency as currency, + key OrdersItems.ID as Item_ID, + OrdersItems.product as product, + OrdersItems.quantity as quantity, + OrdersItems.title as title, + OrdersItems.price as price + + from OrdersHeaders JOIN OrdersItems on OrdersHeaders.ID = OrdersItems.Header.ID; + +// dynamic entity +entity OrderItemsViewAssoc as projection on OrdersHeaders; + +// sort on right table +view SortedOrdersJoin as select + OrdersHeaders.ID as Header_ID, + OrdersHeaders.OrderNo as OrderNo, + OrdersHeaders.buyer as buyer, + OrdersHeaders.currency as currency, + key OrdersItems.ID as Item_ID, + OrdersItems.product as product, + OrdersItems.quantity as quantity, + OrdersItems.title as title, + OrdersItems.price as price +from OrdersHeaders JOIN OrdersItems on OrdersHeaders.ID = OrdersItems.Header.ID +order by title; + +// sort on items and join back to header via assoc + +view SortedOrdersAssoc as select +from OrdersItems {*, Header.OrderNo, Header.buyer, Header.currency } +order by OrdersItems.title; + +// filter on right table + +view FilteredOrdersJoin as select + OrdersHeaders.ID as Header_ID, + OrdersHeaders.OrderNo as OrderNo, + OrdersHeaders.buyer as buyer, + OrdersHeaders.currency as currency, + key OrdersItems.ID as Item_ID, + OrdersItems.product as product, + OrdersItems.quantity as quantity, + OrdersItems.title as title, + OrdersItems.price as price +from OrdersHeaders JOIN OrdersItems on OrdersHeaders.ID = OrdersItems.Header.ID +where price > 100; + +// filter on items and join back to header via assoc + +view FilteredOrdersAssoc as select +from OrdersItems {*, Header.OrderNo, Header.buyer, Header.currency } +where OrdersItems.price > 100; + + +// TODO avoid CASE and/or JOIN: Denormalization of expensive complex structures, +// calculate on write instead of read + +// CASE -> try to remodel to avoid CASE, if re-modelling is not possible, +// fill redundant fields at write + +entity OrdersItemsCaseView as projection on OrdersItems { + *, + case + when quantity > 500 then 'Large' + when quantity > 100 then 'Medium' + else 'Small' + end as category : String +}; + + + } +