From b467fbdbfc1c4a6f46d3b57350aadb99013f30ed Mon Sep 17 00:00:00 2001 From: alephseven Date: Mon, 10 Mar 2025 11:06:45 +0530 Subject: [PATCH 1/6] Added calculations logic for dynamic price in init, confirm apis --- .../server/mappings/on_confirm.jsonata | 10 +- .../server/mappings/on_init.jsonata | 186 +++++++++--------- .../confirm/commerce-workflow-service.ts | 5 +- .../init/commerce-workflow-service.ts | 7 +- .../beckn-bpp-adapter/server/tl/tl.helper.ts | 55 ++++++ .../server/util/calculations.util.ts | 28 +++ .../beckn-bpp-adapter/server/util/index.ts | 3 +- 7 files changed, 198 insertions(+), 96 deletions(-) create mode 100644 plugins/beckn-bpp-adapter/server/util/calculations.util.ts diff --git a/plugins/beckn-bpp-adapter/server/mappings/on_confirm.jsonata b/plugins/beckn-bpp-adapter/server/mappings/on_confirm.jsonata index aaa9b11a..574ba66d 100644 --- a/plugins/beckn-bpp-adapter/server/mappings/on_confirm.jsonata +++ b/plugins/beckn-bpp-adapter/server/mappings/on_confirm.jsonata @@ -1,3 +1,5 @@ +( + $itemBody := message[0].itemsBody; { "context": $context(context, $action), "message": { @@ -51,6 +53,9 @@ "value": $string(stock_quantity ? stock_quantity : 0), "unit": quantity_unit } + }, + "selected": { + "count": $itemQuantity($itemBody, %.id) } }, "category_ids": $map( @@ -94,7 +99,7 @@ "duration": service.time_slot_per_client_in_min ? $string(service.time_slot_per_client_in_min) : "" } }[], - "quote": $quote(message[0].items), + "quote": $quotePrice(message[0].items, message[0].itemsBody), "billing": message.billing, "fulfillments": $map(message.fulfillment, function($elem) { $merge([$elem, {"state":{"descriptor": { @@ -107,4 +112,5 @@ "cancellation_terms": $cancellationTerms(message[0].items) } } -} \ No newline at end of file +} +) \ No newline at end of file diff --git a/plugins/beckn-bpp-adapter/server/mappings/on_init.jsonata b/plugins/beckn-bpp-adapter/server/mappings/on_init.jsonata index ffe09e7b..09de36ea 100644 --- a/plugins/beckn-bpp-adapter/server/mappings/on_init.jsonata +++ b/plugins/beckn-bpp-adapter/server/mappings/on_init.jsonata @@ -1,99 +1,105 @@ -{ - "context": $context(context, $action), - "message": { - "order": { - "provider": message.{ - "id": $string(id), - "descriptor": { - "name": provider_name, - "short_desc": short_desc ? short_desc : "", - "long_desc": long_desc ? long_desc : "", - "additional_desc": { - "url": provider_uri +( + $itemBody := message[0].itemsBody; + { + "context": $context(context, $action), + "message": { + "order": { + "provider": message.{ + "id": $string(id), + "descriptor": { + "name": provider_name, + "short_desc": short_desc ? short_desc : "", + "long_desc": long_desc ? long_desc : "", + "additional_desc": { + "url": provider_uri + }, + "images": items.image.{ + "url": url ? url : "https://abc.com", + "size_type": size_type ? size_type : "sm" + }[] }, - "images": items.image.{ - "url": url ? url : "https://abc.com", - "size_type": size_type ? size_type : "sm" - }[] + "categories": category_ids. { + "id": $string(id), + "descriptor": { + "name": value + } + }[], + "rating": provider_rating, + "short_desc": short_desc, + "fulfillments": $fulfillments(fulfillments, items), + "locations": $locations($append(location_id, [items.item_fulfillment_ids.location_id])), + "rateable": true }, - "categories": category_ids. { + "items": message.items.{ "id": $string(id), "descriptor": { - "name": value - } - }[], - "rating": provider_rating, - "short_desc": short_desc, - "fulfillments": $fulfillments(fulfillments, items), - "locations": $locations($append(location_id, [items.item_fulfillment_ids.location_id])), - "rateable": true - }, - "items": message.items.{ - "id": $string(id), - "descriptor": { - "name": name ? name : "", - "code": code ? code : "", - "short_desc": short_desc ? short_desc : "", - "long_desc": long_desc ? long_desc : "", - "images": image.{ - "url": url?url:"https://abc.com", - "size_type": size_type?size_type:"sm" - }[] - }, - "rating":$string(sc_retail_product.average_rating), - "rateable": true, - "price": $price(sc_retail_product), - "quantity": sc_retail_product.{ - "available": { - "count": stock_quantity ? stock_quantity : 0, - "measure":{ - "value": $string(stock_quantity ? stock_quantity : 0), - "unit": quantity_unit + "name": name ? name : "", + "code": code ? code : "", + "short_desc": short_desc ? short_desc : "", + "long_desc": long_desc ? long_desc : "", + "images": image.{ + "url": url?url:"https://abc.com", + "size_type": size_type?size_type:"sm" + }[] + }, + "rating":$string(sc_retail_product.average_rating), + "rateable": true, + "price": $price(sc_retail_product), + "quantity": sc_retail_product.{ + "available": { + "count": stock_quantity ? stock_quantity : 0, + "measure":{ + "value": $string(stock_quantity ? stock_quantity : 0), + "unit": quantity_unit + } + }, + "selected": { + "count": $itemQuantity($itemBody, %.id) } + }, + "category_ids": $map( + $filter(cat_attr_tag_relations, function($v) { $v.taxanomy = 'CATEGORY'}), + function($v) { + $string($v.taxanomy_id.id) + } + )[], + "fulfillment_ids": $count(item_fulfillment_ids) > 0 ? + $map(item_fulfillment_ids, function($v){ + $string($v.fulfilment_id.id) + })[] : + [], + "location_ids": $count(item_fulfillment_ids) > 0 ? + $map(item_fulfillment_ids, function($v){ + $string($v.location_id.id) + })[] : + [], + "tags": $tags(cat_attr_tag_relations), + "xinput": { + "form": { + "url": $xInput(%.%.context), + "mime_type": "text/html" + } + }, + "time": { + "duration": service.time_slot_per_client_in_min ? $string(service.time_slot_per_client_in_min) : "" } - }, - "category_ids": $map( - $filter(cat_attr_tag_relations, function($v) { $v.taxanomy = 'CATEGORY'}), - function($v) { - $string($v.taxanomy_id.id) - } - )[], - "fulfillment_ids": $count(item_fulfillment_ids) > 0 ? - $map(item_fulfillment_ids, function($v){ - $string($v.fulfilment_id.id) - })[] : - [], - "location_ids": $count(item_fulfillment_ids) > 0 ? - $map(item_fulfillment_ids, function($v){ - $string($v.location_id.id) - })[] : - [], - "tags": $tags(cat_attr_tag_relations), - "xinput": { - "form": { - "url": $xInput(%.%.context), - "mime_type": "text/html" + }[], + "quote": $quotePrice(message[0].items, message[0].itemsBody), + "billing": message.billing, + "categories": $map(message.category_ids, function($v) { + { + "id": $string($v.id), + "value": $v.value, + "createdAt": $v.createdAt, + "updatedAt": $v.updatedAt, + "publishedAt": $v.publishedAt, + "category_code": $v.category_code } - }, - "time": { - "duration": service.time_slot_per_client_in_min ? $string(service.time_slot_per_client_in_min) : "" - } - }[], - "quote": $quote(message.items), - "billing": message.billing, - "categories": $map(message.category_ids, function($v) { - { - "id": $string($v.id), - "value": $v.value, - "createdAt": $v.createdAt, - "updatedAt": $v.updatedAt, - "publishedAt": $v.publishedAt, - "category_code": $v.category_code - } - })[], - "fulfillments": $fulfillments(message.fulfillments, message.items), - "payments": $payments(message[0]), - "cancellation_terms": $cancellationTerms(message[0].items) + })[], + "fulfillments": $fulfillments(message.fulfillments, message.items), + "payments": $payments(message[0]), + "cancellation_terms": $cancellationTerms(message[0].items) + } } } -} +) diff --git a/plugins/beckn-bpp-adapter/server/services/confirm/commerce-workflow-service.ts b/plugins/beckn-bpp-adapter/server/services/confirm/commerce-workflow-service.ts index 25253f2d..e8f106db 100644 --- a/plugins/beckn-bpp-adapter/server/services/confirm/commerce-workflow-service.ts +++ b/plugins/beckn-bpp-adapter/server/services/confirm/commerce-workflow-service.ts @@ -448,7 +448,10 @@ export default ({ strapi }: { strapi: Strapi }) => ({ } }, order_id: orderId, - order_details: createOrder + order_details: createOrder, + // Attach itemsBody to get quantity of each items selected for order which will be used for dynamic price calculation + itemsBody: items.filter((i) => item.items.some((it) => String(it.id) === String(i.id))) + })); if (isEnergy(context)) { const { diff --git a/plugins/beckn-bpp-adapter/server/services/init/commerce-workflow-service.ts b/plugins/beckn-bpp-adapter/server/services/init/commerce-workflow-service.ts index eb05f4de..248aa19e 100644 --- a/plugins/beckn-bpp-adapter/server/services/init/commerce-workflow-service.ts +++ b/plugins/beckn-bpp-adapter/server/services/init/commerce-workflow-service.ts @@ -166,7 +166,10 @@ export default ({ strapi }: { strapi: Strapi }) => ({ }); } initDetails = initDetails.map((provider) => { - provider.items = provider.items.map((responseItem) => { + const providerItemIds = provider?.items.map((item) => String(item.id)); + // Filter items that exist in provider.items + const itemsBody = items.filter((item) => providerItemIds.includes(String(item.id))); + provider.items = provider?.items.map((responseItem) => { const bodyItem = items.find( (item) => Number(item.id) === responseItem.id ); @@ -182,7 +185,7 @@ export default ({ strapi }: { strapi: Strapi }) => ({ } return responseItem; }); - + provider.itemsBody = itemsBody; return provider; }); return initDetails; diff --git a/plugins/beckn-bpp-adapter/server/tl/tl.helper.ts b/plugins/beckn-bpp-adapter/server/tl/tl.helper.ts index 3c4da88a..0715f3db 100644 --- a/plugins/beckn-bpp-adapter/server/tl/tl.helper.ts +++ b/plugins/beckn-bpp-adapter/server/tl/tl.helper.ts @@ -88,6 +88,61 @@ export const quote = async (items: KeyValuePair[]) => { }; }; +export const quotePrice = async (items: KeyValuePair[], itemSelected: KeyValuePair[]) => { + const breakup: KeyValuePair[] = []; + items?.map((item) => { + const scProduct = item?.sc_retail_product; + + // Find the selected quantity for the item from itemSelected + const matchingItem = itemSelected.find(tag => String(tag.id) === String(item.id)); + const selectedQuantity = matchingItem?.quantity?.selected?.count ?? 1; // Default to 1 if not found + + // Add "BASE PRICE" entry + if (scProduct?.base_fee) { + breakup.push({ + title: "BASE PRICE", + price: { + currency: scProduct.currency, + value: (Number(scProduct.base_fee) * selectedQuantity).toString() + }, + item: { id: `${item.id || ""}` } + }); + } + + // Process price breakup items + scProduct?.price_bareakup_ids?.map((price_bareakup_id: KeyValuePair) => { + // Calculate price based on is_item_qty_dependent flag + const baseValue = Number(price_bareakup_id.value ?? 0); + const adjustedValue = price_bareakup_id.is_item_qty_dependent + ? baseValue * selectedQuantity + : baseValue; + + breakup.push({ + title: price_bareakup_id.title, + price: { + currency: price_bareakup_id.currency, + value: adjustedValue.toString() + }, + item: { id: `${item.id || ""}` } + }); + }); + }); + + // Calculate total priceValue as sum of all breakup.price.value + const priceValue = breakup.reduce( + (accumulator, currentValue) => accumulator + Number(currentValue?.price?.value), + 0 + ); + + return { + price: { + value: priceValue.toString(), + currency: items?.[0]?.sc_retail_product?.currency + }, + breakup + }; +}; + export const payments = async ( provider: KeyValuePair, incomingPrice: KeyValuePair, diff --git a/plugins/beckn-bpp-adapter/server/util/calculations.util.ts b/plugins/beckn-bpp-adapter/server/util/calculations.util.ts new file mode 100644 index 00000000..a215a1be --- /dev/null +++ b/plugins/beckn-bpp-adapter/server/util/calculations.util.ts @@ -0,0 +1,28 @@ +export class CalculationsUtil { + static calculateOrderAmount(items: any, itemSelected: any) { + let totalAmount = 0; + + items?.forEach((item: any) => { + const scProduct = item?.sc_retail_product; + + // Find the selected quantity for the item from itemSelected + const matchingTag = itemSelected.find((tag: any) => String(tag.id) === String(item.id)); + const selectedQuantity = matchingTag?.quantity?.selected?.count ?? 1; + + if (scProduct?.base_fee) { + totalAmount += Number(scProduct.base_fee) * selectedQuantity; + } + + scProduct?.price_bareakup_ids?.forEach((price_bareakup_id: any) => { + const baseValue = Number(price_bareakup_id.value ?? 0); + const adjustedValue = price_bareakup_id.is_item_qty_dependent + ? baseValue * selectedQuantity + : baseValue; + + totalAmount += adjustedValue; + }); + }); + return totalAmount; + } + +} diff --git a/plugins/beckn-bpp-adapter/server/util/index.ts b/plugins/beckn-bpp-adapter/server/util/index.ts index df5e5a8b..ac2f028f 100644 --- a/plugins/beckn-bpp-adapter/server/util/index.ts +++ b/plugins/beckn-bpp-adapter/server/util/index.ts @@ -4,4 +4,5 @@ export * from './domain.util'; export * from './location.util'; export * from './search.util'; export * from './init.util'; -export * from './trade.util'; \ No newline at end of file +export * from './trade.util'; +export * from './calculations.util'; \ No newline at end of file From 2cb200d7e5054f707bf86ef91075bd0ba5be42fe Mon Sep 17 00:00:00 2001 From: alephseven Date: Wed, 19 Mar 2025 12:15:31 +0530 Subject: [PATCH 2/6] Added dynamic base price name and calculation logic in init, confirm, and status api --- .../server/mappings/on_confirm.jsonata | 2 +- .../server/mappings/on_init.jsonata | 2 +- .../server/mappings/on_status.jsonata | 15 +++++--- .../beckn-bpp-adapter/server/tl/tl.helper.ts | 36 +++++++++++++++++-- 4 files changed, 45 insertions(+), 10 deletions(-) diff --git a/plugins/beckn-bpp-adapter/server/mappings/on_confirm.jsonata b/plugins/beckn-bpp-adapter/server/mappings/on_confirm.jsonata index 574ba66d..3da19ff8 100644 --- a/plugins/beckn-bpp-adapter/server/mappings/on_confirm.jsonata +++ b/plugins/beckn-bpp-adapter/server/mappings/on_confirm.jsonata @@ -99,7 +99,7 @@ "duration": service.time_slot_per_client_in_min ? $string(service.time_slot_per_client_in_min) : "" } }[], - "quote": $quotePrice(message[0].items, message[0].itemsBody), + "quote": $quotePrice(message[0].items, message[0].itemsBody, context), "billing": message.billing, "fulfillments": $map(message.fulfillment, function($elem) { $merge([$elem, {"state":{"descriptor": { diff --git a/plugins/beckn-bpp-adapter/server/mappings/on_init.jsonata b/plugins/beckn-bpp-adapter/server/mappings/on_init.jsonata index 09de36ea..27f808af 100644 --- a/plugins/beckn-bpp-adapter/server/mappings/on_init.jsonata +++ b/plugins/beckn-bpp-adapter/server/mappings/on_init.jsonata @@ -84,7 +84,7 @@ "duration": service.time_slot_per_client_in_min ? $string(service.time_slot_per_client_in_min) : "" } }[], - "quote": $quotePrice(message[0].items, message[0].itemsBody), + "quote": $quotePrice(message[0].items, message[0].itemsBody, context), "billing": message.billing, "categories": $map(message.category_ids, function($v) { { diff --git a/plugins/beckn-bpp-adapter/server/mappings/on_status.jsonata b/plugins/beckn-bpp-adapter/server/mappings/on_status.jsonata index d848e798..b461ba2a 100644 --- a/plugins/beckn-bpp-adapter/server/mappings/on_status.jsonata +++ b/plugins/beckn-bpp-adapter/server/mappings/on_status.jsonata @@ -1,10 +1,13 @@ + +( + $tags := message.order_id.tags; { "context": $context(context, $action), "message": { "order":{ "id": $string(message.order_id.id), "created_at": message.order_id.createdAt, - "provider": message.order_id.items.provider.{ + "provider": message.order_id.items[0].provider.{ "id": $string(id), "descriptor": { "name": provider_name, @@ -58,9 +61,10 @@ "unit": quantity_unit } }, - "selected":{ - "count":1 + "selected": { + "count": $itemQuantity($tags, %.id) } + }, "category_ids": $map( $filter(cat_attr_tag_relations, function($v) { $v.taxanomy = 'CATEGORY'}), @@ -181,9 +185,10 @@ "type": "PRE-ORDER", "transaction_id": transaction_id }[], - "quote": $quote(message.order_id.items), + "quote": $quotePrice(message[0].items, message[0].itemsBody, context), "cancellation_terms": $cancellationTerms(message.order_id.items), "status": message.order_id.status } } -} \ No newline at end of file +} +) \ No newline at end of file diff --git a/plugins/beckn-bpp-adapter/server/tl/tl.helper.ts b/plugins/beckn-bpp-adapter/server/tl/tl.helper.ts index 0715f3db..3684c540 100644 --- a/plugins/beckn-bpp-adapter/server/tl/tl.helper.ts +++ b/plugins/beckn-bpp-adapter/server/tl/tl.helper.ts @@ -88,8 +88,25 @@ export const quote = async (items: KeyValuePair[]) => { }; }; -export const quotePrice = async (items: KeyValuePair[], itemSelected: KeyValuePair[]) => { +// Domain-specific base price name mappings +const domainBasePriceNames = { + "Retail": "Item Price", + "dhp:pharmacy:0.1.0": "Item Price", + "supply-chain-services:assembly": "Base Price", + "mobility:1.1.0": "Base Fare", + "tourism": "Sub Total", + "dsep:courses": "Item Price", + "hospitality": "Room Tariff", + "retail:1.1.0": "Item Price", + "uei:p2p_trading": "P2P Energy Cost", + "uei:charging": "Cost of Charge" +}; + +export const quotePrice = async (items: KeyValuePair[], itemSelected: KeyValuePair[], context: KeyValuePair) => { const breakup: KeyValuePair[] = []; + console.log("Context===>", context); + console.log("Items===>", items); + console.log("ItemSelected===>", itemSelected); items?.map((item) => { const scProduct = item?.sc_retail_product; @@ -97,10 +114,14 @@ export const quotePrice = async (items: KeyValuePair[], itemSelected: KeyValuePa const matchingItem = itemSelected.find(tag => String(tag.id) === String(item.id)); const selectedQuantity = matchingItem?.quantity?.selected?.count ?? 1; // Default to 1 if not found - // Add "BASE PRICE" entry + // Get domain-specific base price name or use default + const domain = context?.domain; + const basePriceName = domainBasePriceNames[domain] || "BASE PRICE"; + + // Add base price entry with domain-specific name if (scProduct?.base_fee) { breakup.push({ - title: "BASE PRICE", + title: basePriceName, price: { currency: scProduct.currency, value: (Number(scProduct.base_fee) * selectedQuantity).toString() @@ -415,3 +436,12 @@ export const providerTags = (tagRelations) => { return Array.from(groupedRelationsMap.values()); }; + +export const itemQuantity = (tags: any, itemId: any) => { + if (!Array.isArray(tags) || tags.length === 0) { + return 1; + } + // Find the tag where id matches itemId + const matchingTag = tags.find((tag) => String(tag.id) === String(itemId)); + return matchingTag?.quantity?.selected?.count || 1; +}; From bacc9e5a3a27fa1646621e471bb1e73b1b2602cb Mon Sep 17 00:00:00 2001 From: alephseven Date: Fri, 28 Mar 2025 13:30:55 +0530 Subject: [PATCH 3/6] Changed base price name for dsep:courses domain --- plugins/beckn-bpp-adapter/server/tl/tl.helper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/beckn-bpp-adapter/server/tl/tl.helper.ts b/plugins/beckn-bpp-adapter/server/tl/tl.helper.ts index 3684c540..25dd1a4f 100644 --- a/plugins/beckn-bpp-adapter/server/tl/tl.helper.ts +++ b/plugins/beckn-bpp-adapter/server/tl/tl.helper.ts @@ -95,7 +95,7 @@ const domainBasePriceNames = { "supply-chain-services:assembly": "Base Price", "mobility:1.1.0": "Base Fare", "tourism": "Sub Total", - "dsep:courses": "Item Price", + "dsep:courses": "Course Fee", "hospitality": "Room Tariff", "retail:1.1.0": "Item Price", "uei:p2p_trading": "P2P Energy Cost", From 2c2f788f18b35c22b0937e19c44530e982ad781d Mon Sep 17 00:00:00 2001 From: alephseven Date: Fri, 28 Mar 2025 19:03:59 +0530 Subject: [PATCH 4/6] Handled quote for domains where price breakups are absent --- .../beckn-bpp-adapter/server/tl/tl.helper.ts | 90 +++++++++++-------- 1 file changed, 54 insertions(+), 36 deletions(-) diff --git a/plugins/beckn-bpp-adapter/server/tl/tl.helper.ts b/plugins/beckn-bpp-adapter/server/tl/tl.helper.ts index 25dd1a4f..0cc56aed 100644 --- a/plugins/beckn-bpp-adapter/server/tl/tl.helper.ts +++ b/plugins/beckn-bpp-adapter/server/tl/tl.helper.ts @@ -102,65 +102,83 @@ const domainBasePriceNames = { "uei:charging": "Cost of Charge" }; -export const quotePrice = async (items: KeyValuePair[], itemSelected: KeyValuePair[], context: KeyValuePair) => { +export const quotePrice = async ( + items: KeyValuePair[], + itemSelected: KeyValuePair[], + context: KeyValuePair +) => { const breakup: KeyValuePair[] = []; console.log("Context===>", context); console.log("Items===>", items); console.log("ItemSelected===>", itemSelected); + + let totalPriceValue = 0; + items?.map((item) => { const scProduct = item?.sc_retail_product; // Find the selected quantity for the item from itemSelected - const matchingItem = itemSelected.find(tag => String(tag.id) === String(item.id)); + const matchingItem = itemSelected.find( + (tag) => String(tag.id) === String(item.id) + ); const selectedQuantity = matchingItem?.quantity?.selected?.count ?? 1; // Default to 1 if not found // Get domain-specific base price name or use default const domain = context?.domain; - const basePriceName = domainBasePriceNames[domain] || "BASE PRICE"; + const basePriceName = domainBasePriceNames[domain]; - // Add base price entry with domain-specific name - if (scProduct?.base_fee) { - breakup.push({ - title: basePriceName, - price: { - currency: scProduct.currency, - value: (Number(scProduct.base_fee) * selectedQuantity).toString() - }, - item: { id: `${item.id || ""}` } - }); - } + // Process price breakup items if they exist + if (scProduct?.price_bareakup_ids?.length > 0) { + // Add all price breakups + scProduct.price_bareakup_ids.map((price_bareakup_id: KeyValuePair) => { + // Calculate price based on is_item_qty_dependent flag + const baseValue = Number(price_bareakup_id.value ?? 0); + const adjustedValue = price_bareakup_id.is_item_qty_dependent + ? baseValue * selectedQuantity + : baseValue; - // Process price breakup items - scProduct?.price_bareakup_ids?.map((price_bareakup_id: KeyValuePair) => { - // Calculate price based on is_item_qty_dependent flag - const baseValue = Number(price_bareakup_id.value ?? 0); - const adjustedValue = price_bareakup_id.is_item_qty_dependent - ? baseValue * selectedQuantity - : baseValue; - - breakup.push({ - title: price_bareakup_id.title, - price: { - currency: price_bareakup_id.currency, - value: adjustedValue.toString() - }, - item: { id: `${item.id || ""}` } + breakup.push({ + title: price_bareakup_id.title, + price: { + currency: price_bareakup_id.currency, + value: adjustedValue.toString(), + }, + item: { id: `${item.id || ""}` }, + }); }); - }); + + // If base price exists for this domain, add it to breakups + if (basePriceName && scProduct?.base_fee) { + breakup.push({ + title: basePriceName, + price: { + currency: scProduct.currency, + value: (Number(scProduct.base_fee) * selectedQuantity).toString(), + }, + item: { id: `${item.id || ""}` }, + }); + } + } else { + // If no breakups exist, just add base_fee * quantity to total price + if (scProduct?.base_fee) { + totalPriceValue += Number(scProduct.base_fee) * selectedQuantity; + } + } }); - // Calculate total priceValue as sum of all breakup.price.value - const priceValue = breakup.reduce( - (accumulator, currentValue) => accumulator + Number(currentValue?.price?.value), + // Calculate total priceValue as sum of all breakup.price.value plus any base_fee values + const breakupPriceValue = breakup.reduce( + (accumulator, currentValue) => + accumulator + Number(currentValue?.price?.value), 0 ); return { price: { - value: priceValue.toString(), - currency: items?.[0]?.sc_retail_product?.currency + value: (breakupPriceValue + totalPriceValue).toString(), + currency: items?.[0]?.sc_retail_product?.currency, }, - breakup + breakup, }; }; From af6e0a5809ce08b15393e529b65a57bc2be43e0f Mon Sep 17 00:00:00 2001 From: alephseven Date: Tue, 1 Apr 2025 13:32:33 +0530 Subject: [PATCH 5/6] Fixed quote issue in status api --- plugins/beckn-bpp-adapter/server/mappings/on_status.jsonata | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/beckn-bpp-adapter/server/mappings/on_status.jsonata b/plugins/beckn-bpp-adapter/server/mappings/on_status.jsonata index b461ba2a..d40e51cb 100644 --- a/plugins/beckn-bpp-adapter/server/mappings/on_status.jsonata +++ b/plugins/beckn-bpp-adapter/server/mappings/on_status.jsonata @@ -185,7 +185,7 @@ "type": "PRE-ORDER", "transaction_id": transaction_id }[], - "quote": $quotePrice(message[0].items, message[0].itemsBody, context), + "quote": $quotePrice(message[0].order_id.items, message[0].order_id.tags, context), "cancellation_terms": $cancellationTerms(message.order_id.items), "status": message.order_id.status } From 4ab45036598728586ee76258c7f32e74df74b43e Mon Sep 17 00:00:00 2001 From: shreyvishal Date: Wed, 2 Apr 2025 14:02:44 +0530 Subject: [PATCH 6/6] Added: Dynamic Price Breakup in on_select API --- .../beckn-bpp-adapter/server/mappings/on_select.jsonata | 9 ++++++--- .../server/services/select/commerce-workflow-service.ts | 7 ++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/plugins/beckn-bpp-adapter/server/mappings/on_select.jsonata b/plugins/beckn-bpp-adapter/server/mappings/on_select.jsonata index 783418c9..ba6918d4 100644 --- a/plugins/beckn-bpp-adapter/server/mappings/on_select.jsonata +++ b/plugins/beckn-bpp-adapter/server/mappings/on_select.jsonata @@ -1,4 +1,6 @@ -{ +( + $itemBody := message[0].itemsBody; + { "context": $context(context, $action), "message": { "order": { @@ -78,7 +80,7 @@ "duration": service.time_slot_per_client_in_min ? $string(service.time_slot_per_client_in_min) : "" } }[], - "quote": $quote(message.items), + "quote": $quotePrice(message[0].items, message[0].itemsBody, context), "categories": $map(message.category_ids, function($v) { { "id": $string($v.id), @@ -92,4 +94,5 @@ "fulfillments": $fulfillments(message.fulfillments, message.items) } } -} \ No newline at end of file +} +) \ No newline at end of file diff --git a/plugins/beckn-bpp-adapter/server/services/select/commerce-workflow-service.ts b/plugins/beckn-bpp-adapter/server/services/select/commerce-workflow-service.ts index 559c0a23..c8052727 100644 --- a/plugins/beckn-bpp-adapter/server/services/select/commerce-workflow-service.ts +++ b/plugins/beckn-bpp-adapter/server/services/select/commerce-workflow-service.ts @@ -138,6 +138,11 @@ export default ({ strapi }: { strapi: Strapi }) => ({ itemDetails[0] = { ...itemDetails[0], ...quantitySelected }; itemDetails = itemDetails.map((provider) => { + const providerItemIds = provider?.items.map((item) => String(item.id)); + // Filter items that exist in provider.items + const itemsBody = items.filter((item) => + providerItemIds.includes(String(item.id)) + ); provider.items = provider.items.map((responseItem) => { // Find the matching item in request body by id const bodyItem = items.find( @@ -156,7 +161,7 @@ export default ({ strapi }: { strapi: Strapi }) => ({ } return responseItem; }); - + provider.itemsBody = itemsBody; return provider; }); return itemDetails;