diff --git a/suppliers/srv/mashup.cds b/suppliers/srv/mashup.cds index a4df66d0..33d607c9 100644 --- a/suppliers/srv/mashup.cds +++ b/suppliers/srv/mashup.cds @@ -8,6 +8,14 @@ extend service S4 with { entity Suppliers as projection on S4.A_BusinessPartner { key BusinessPartner as ID, BusinessPartnerFullName as name, + // REVISIT: following is not supported so far in cds compiler... + // to_BusinessPartnerAddress as city { + // CityCode as code, + // CityName as name + // } + // REVISIT: following is not supported so far in cqn2odata... + // to_BusinessPartnerAddress.CityCode as city, + // to_BusinessPartnerAddress.CityName as city_name, } } diff --git a/suppliers/srv/mashup.js b/suppliers/srv/mashup.js index 7185251f..a77b238c 100644 --- a/suppliers/srv/mashup.js +++ b/suppliers/srv/mashup.js @@ -4,49 +4,54 @@ // module.exports = async()=>{ // called by server.js - if (!cds.services.AdminService) return //> mocking SAP S4/HANA service only + if (!cds.services.AdminService) return //> mocking S4 service only // Connect to services we want to mashup below... - const S4bupa = await cds.connect.to('API_BUSINESS_PARTNER') //> external SAP S4/HANA service + const S4bupa = await cds.connect.to('API_BUSINESS_PARTNER') //> external S4 service const admin = await cds.connect.to('AdminService') //> local domain service const db = await cds.connect.to('db') //> our primary database // Reflect CDS definition of the Suppliers entity const { Suppliers } = S4bupa.entities - admin.prepend (()=>{ + admin.prepend (()=>{ //> to ensure our .on handlers below go before the default ones - // Delegate Value Help reads for Suppliers to SAP S4/HANA backend - admin.on ('READ', 'Suppliers', async req => { + // Delegate Value Help reads for Suppliers to S4 backend + admin.on ('READ', 'Suppliers', req => { console.log ('>> delegating to S4 service...') - return await S4bupa.run(req.query) + return S4bupa.run(req.query) }) - - // Replicate Supplier data when Books are edited - admin.on (['CREATE','UPDATE'], 'Books', async (req,next) => { - let { supplier } = req.data - if (supplier) { - let cached = await db.exists (Suppliers, supplier) - if (!cached) await replicate (supplier,'initial') - } - return next() + // Replicate Supplier data when edited Books have suppliers + admin.on (['CREATE','UPDATE'], 'Books', ({data:{supplier}}, next) => { + // Using Promise.all(...) to parallelize local write, i.e. next(), and replication + if (supplier) return Promise.all ([ next(), async()=>{ + let replicated = await db.exists (Suppliers, supplier) + if (!replicated) await replicate (supplier, 'initial') + }]) + else return next() //> don't forget to pass down the interceptor stack }) }) - // Subscribe to changes in the SAP S4/HANA origin of Suppliers data - S4bupa.on ('BusinessPartner/Changed', async msg => { - let cached = await SELECT('ID').from (Suppliers) - .where ('ID in', msg.businessPartner.KEYS) - for (let each of cached) replicate (each) + // Subscribe to changes in the S4 origin of Suppliers data + S4bupa.on ('BusinessPartners/Changed', async msg => { //> would be great if we had batch events from S/4 + let replicas = await SELECT('ID').from (Suppliers) .where ('ID in', msg.businessPartners) + return replicate (replicas.map(each => each.ID)) }) - // Helper function to replicate Suppliers data - async function replicate (ID,_initial) { - let data = await S4bupa.read (Suppliers, ID) - if (_initial) return db.insert (data) .into (Suppliers) - else return db.update (Suppliers,ID) .with (data) + /** + * Helper function to replicate Suppliers data. + * @param {string|string[]} IDs a single ID or an array of IDs + * @param {truthy|falsy} _initial indicates whether an insert or an update is required + */ + async function replicate (IDs,_initial) { + if (!Array.isArray(IDs)) IDs = [ IDs ] + let suppliers = await S4bupa.read (Suppliers).where('ID in',IDs) + if (_initial) return db.insert (suppliers) .into (Suppliers) //> using bulk insert + else return Promise.all(suppliers.map ( //> parallelizing updates + each => db.update (Suppliers,each.ID) .with (each) + )) } }