2021-11-22 - Trying to work out SellOffer price flow
Considerations
- want to use existing complexFilter / searchResult / sortResult caching systems as much as possible
- want to re-use cache results at multiple steps of the flow where possible
expected types of requests
filtering search results
- will receive orderQuantity and a list of deliverToLocationIds, deliveryMethodIds, paymentMethodIds, and need to find all sellOffers that have a price within these constraints
- because sellOffers will have many prices within the above combinations, will need to aggregate to one per sellOffer (max/min/avg price)
- including a filter on the aggregate price, eg greaterThan/lessThan
- end result is product/selloffer/variantProduct searchResults that have been filtered by the above, product and variantProduct simply wrap the sellOffer searchResult/complexFilter results
viewing selloffer prices for one sellOffer
- end result will be searchResult for all orderPrices for one sellOffer
cart and order pricing
- receives array of {sellOfferId / quantity / deliver/payment method link}s, one
- can find lowest orderPrice for given deliverToLocationIds, deliveryMethodIds, paymentMethodIds by using similar filter/logical to filtering search results
- buyer has option to look at different combinations and choose which to buy
old notes
[calculating one orderPrice]
- decided not to use complexFilter process because we know the specific orderPrice we need to create, nothing to filter
- if using filter could use async flow including awaitingLogical table
- I think add an orderPrice search/filterType level in between sellOffer and flow, which will allow us to store the eg maxPrice value in a child orderPrice level searchResult, that a parent sellOffer maxPrice field can use to find it's value, because a sellOffer level searchResult would need to dig out it's aggregated orderPriceId before finding the price, rather than simply checking it's child orderPrice searchResult value
[how/where we remove out error orderPrices?] - could hardcode in AggregateOneSellOffersPrices - but I think better to add as a complexFilter element, try to do in a way that is efficient (uses same filter that other steps use)
- after per sellOffer sorted searchResult complete need to trigger PriceLogical function that finds all LogicalSortedSellOfferPricePending for that sellOfferPriceSortResultId >> logicalResult that startห this process should be logicalResult that ends up with full list of all selloffers and their single aggregated value - the original max logicalResult should call the above sorted searchResult that has a complexFilter that finds the full list, and awaits it - the full aggregated selloffer logical starts the process I have done so far. It is also an orderPrice level sorted search result - for each logicalResultId found, check if any other LogicalSortedSellOfferPricePending remain, if not next step is to start a
-- searchResult getRequired Data flow - for each orderPrice a request will be sent to sellOfferManager for the price - will be received by findData type Lambda - findData will either send findDataComplete message out with price straight away if orderPrice is complete/error, or will enter flow that awaits orderPrice complete, then sends message - findDataComplete message triggers searchResult to check if all reqData complete, passes on to sortResult, which finally sends sortResultComplete message - orderPrice level sorted searchResults (sortResultComplete message) triggers
--> at each step if find main is complete, skip to processing step [step 1 - sellOffer logicalElement filtering maxPrice] - starts flow requesting sorted searchResult, searchType: orderPricePerSellOffer - passes down all details required - after has orderPricePerSellOffer, performs the filter to get final LogicalResults [step 2 - sorted searchType: orderPricePerSellOffer] - records the aggregated value for each sellOffer, one price for each sellOffer - has filterType: orderPricePerSellOffer - has logicalElement: aggregatedPrice, sets max/min/total?/etc - to create aggregate needs to know all individual sellOffer sorted searchResults, so we will begin them here - aggregatedPrice processLogical element has it's own flow for orchestrating steps - create pending table for each request that lists all remaining sellOffer sorted searchResults for each request - save main into table aggregatedPriceMain, store the aggregation, id is hash of request - send out
- translateIdsAdditionalData not work because will different additonalData would result in the same filterMainId I think - probably need to move out as separate process..?
> need a list of max/min/avg price per sell offer, not accross the entire filtered data*****
- maybe from the start we do a sellOffer + sellOfferPlanPaymentDeliveryCombination complexFilter first >> this lists unique sellOffers
- then per sellOffer we do a sorted orderPrice + sellOfferPlanPaymentDeliveryCombination searchResult which includes a sellOfferId = x element at either the orderPrice or sellOfferPlanPaymentDeliveryCombination level, I think both work because both will re-use full sellOfferPlanPaymentDeliveryCombination element and both will find all orderPrices. I prefer at sellOfferPlanPaymentDeliveryCombination level for lower level reuse(?) >> this will save all orderPrices sorted, one filterData set per sellOfferId
- wrapping the orderPrice + sellOfferPlanPaymentDeliveryCombination could be the maxPrice/minPrice sellOffer logical request, which has it's own async flow for waiting the results then for each sellOffer found (prob using same as first sellOffer level complexfilter) it finds the aggregate value for each sellOffer and saves into it's LogicalResults
- searchResult not need to sort orderPrice, as this is for all sellOffers found (but other lists might do that wants sorted all prices for all sellOffers) - new search/filterType for each aggregation: orderPricePerSellOffer - TranslateIds has translateIdsAdditionalData stating what type of aggregation (*make sure this is included in its unique filter/searchMain so different aggregations not find each other - same for existing one) - TranslateIds orderTotal > has it's own flow that creates a list of sellOffers found from sellOfferPlanPaymentDeliveryCombination by either: 1. going through all orderPrice results and saving one record for each sellOfferId found 2. (choose this) creating a new sellOfferId level complexFilter which has the same sellOfferPlanPaymentDeliveryCombination child complexFilter, TranslateIds between these finds one sellOfferId filterData record per sellOffer found - once we have the list of sellOfferIds creates a sorted searchResult (searchType: sellOffer) for each with the same orderPrice level child complexFilter but adding a sellOffer -- - maybe find all orderPrices first using complexFilter, which will be grouped by their resultId - wait for searchResult to finish find all orderPrices - then need some way to copy these into a new table grouped by a variable id (eg sellOfferId) - once grouped, depending on the logicalTag (standardized to max/min/avg) create a new set of data with just that value for each sellOffer - use that table to apply the filter greaterThan/lessThan etc... - I want to have per selloffer sortResult prices for specific qty/del/payment combinations, they can be used eg on item pages, so will be wanting to add this step into the process, sortResult per sellOffer
> below prob not work because need to group sorted prices by sellOffer
- finsihed up to TranslateIds sellOfferPlanPaymentDeliveryCombination > orderPrice
- need to do CalculateOrderPrice logic, including dynamo table to store orderPrice
- filterPrices requests Sorted Search Results (which includes complexfilter filter) - sellOfferPrices are another filterType/searchType, logicals managed by sellOfferManager - sellOfferPlan sellOfferPlan:paymentMethod/deliveryMethod combinations are another filterType with their own complexFilter process, each found combination is saved as a complexFilter dataRecord, and have a higher level sellOfferPlan filterType that we translated combinations into list of only sellOfferPlanIds that have at least one matching combination. This way we can dig the data/list of sellOfferPlanIds, or combinations. - complexFilter and searchResult main services need a Lambda that returns paginated data results - sortResult service needs a function that does max/min/average according to sorted result/sortFields
1) - sellOfferManager recieves sellOffer filterType logical request that has operator/value/delivery/payment/location/qty, it stores this and creates sorted searchResult request of searchType: sellOfferPrice, sorted by price - after sortResults completed triggers sellOfferManager function that finds max/min/avg from sortResult service, saves into LogicalResults and triggers ProcessLogicalComplete 2) - sorted SearchResult will have requiredData as price and sortField - filterType is sellOfferPrice, has a child filterType sellOfferPlan:paymentMethodLink/deliveryMethodLink which is sent to sellOfferPlan service to find - combinations are translated into sellOfferPrices, records need to be created as needed, find all sellOffers that point to each found sellOfferPlan, but also requires list of locationIds and quantity (if not able to send additional info into translatedIds, then cannot be a child complexFilter, needs to pull out sellOfferPlan:paymentMethodLink/deliveryMethodLink as a separate filter process that is wrapped by sellOfferPrice logical element that finds all sellOfferPrices according to locationIds/quantity/paymentMethod/deliveryMethod - after have complexFilter complete with list of sellOfferPrice ids in filterData, searchResult finds price for each one, then sortResult sorts by price 3) finding price for each sellOfferPrice: - a sellOfferPrice is identified by the sellOfferQuantities(sellOfferId/quantity/additionalInfo/paymentMethodLink/deliveryMethodLink),deliverToLocationId - we do not validate combinePurchases, nor each sellOffer has the save seller, nor given paymentMethodLink/deliveryMethodLinks point to same paymentMethod/deliveryMethod. This is all done outside of this flow - service that calculates sellOfferPrice is SellOfferManager, it receives each sellOfferPrice params - each time SellOfferManager wants one calculated price for a sellOfferQuantity/orderQuantity/orderValue it sends these values (and additionalInfo) to the sellOffer Handler service to calc (similar to existing lib function but send to handler to work out price table result) - now have subtotal, need to calc paymentMethod and deliveryMethod charges - calc deliveryMethod first because paymentMethod charge calc on top of total amount including delivery charge -
- because prices are dependant on the sellOffer service/object we need to record prices per sellOfferId, not sellOfferPlanId
- move most logic/tables into sellOfferManager service, out of sellOfferPlan service. sellOfferPlan service becomes just a connection/shared set of shipping/delivery settings
- try to use complexFilter in the flow whereever possible, for example finding sellOfferTerm/productAtt for deliveryMethod value, will need to do more async invocation flow
- also async when soManager asks sellOffer service for price - is there any way we could move the different steps of calc into a complexFilter structure, eg finding all sellOffer level prices (middle level), or one sellOfferPrice (lowest level), use complex filter for caching. might not be able to use childComplexFilter structure, but still might be useful to use complexFilter for caching, and so can attach to other types of parent complexFilters in future.. - move sellOffer complexfilter to point to sellOfferManager rather than all sellOffer handler services, sellOfferManager can then request each handler service if needed in it's own async flow. pricing will require sellOfferManager to handle logicalElement
- move sellOfferPlanSettings into SellOfferPrice service, child of sellOffer object
- this will allow for more complex pricing structures that might need to communicate with alternative SellOffer/Product handlers (eg custom items) - maybe change from sellOfferPlanQuantities to sellOfferQuantities - each SO must send request from SOPlan to SO service requesting price according to soQty/orderQty/orderValue - SO will need to find lowest price depending on the values (will need to query Dynamo for pricing each time) - if orderValue changes needs to send requests again - sellOfferQuantities in order/cart will need to record additionalInfo, for example for custom made items, this is generated and maintained by the sellOffer service - minQty settings put into SellOfferPrice service (so can be shared by many sellOffers) - combineWins put into sellOfferPlan settings, so eg cart can check/validate --- - do the calculation logic, check PriceCalc lib functions eg calculateCombinedPricing - if not all sellOfferPlans include the payment and delivery ids need to set to error
Calc pricing use cases
Complex filter
Complex filter (filterType = sellOfferPlan) can find all sellOfferPlanIds that match a pricing comparison, eg minimumPrice < 100:
- request enters at ProcessLogical and saves PriceLogical record that is used to send final ProcessLogicalComplete message
- creates FilteredSellOfferPlanList which manages the final status of a list of sellOfferPlans that match a range of deliverToLocationIds / orderQuantity / paymentMethodIds / deliveryMethodIds (set by the ProcessLogical request)
- all sellOfferPlans that actively offer both any paymentMethodIds and any deliveryMethodIds are processed
- each sellOfferPlan is saved into FilteredSellOfferPlanPending, then check if SellOfferPlanPriceRange exists and complete/not expired, if not then initiate SellOfferPlanPriceRange processing, if is complete (or no sellOfferPlans found) need to copy all matching SellOfferPlanPrices into FilteredSellOfferPlanPrice and remove FilteredSellOfferPlanPending record
- for each sellOfferPlan find all delivery/payment method links that match given arrays
- for each sellOfferPlan all deliverToLocationIds / orderQuantity / sellOfferPlanUserPaymentMethodLinkId_sellOfferPlanDeliveryMethodLinkId combinations create SellOfferPlanPriceRangePricePending record then check if SellOfferPlanPrice complete/not expired, if not then send to PriceCalc, if is complete need to copy SellOfferPlanPrice into FilteredSellOfferPlanPrice remove SellOfferPlanPriceRangePricePending record, and if all combinations already exist (or no combinations found) invoke CheckSellOfferPlanPriceRangeComplete (be careful if paginating lambda processing, can only check this paginations set of found combinations)
- PriceCalc result is saved into SellOfferPlanPrice
- all matching SellOfferPlanPriceRangePricePending records trigger CheckSellOfferPlanPriceRangeComplete:
- removes SellOfferPlanPriceRangePricePending record (do this in CheckSellOfferPlanPriceRangeComplete for idempodence)
- saves record into FilteredSellOfferPlanPrice according to the SellOfferPlanPrice that was just completed (maybe do this in one hot when SellOfferPlanPriceRange completes, we can use same code for when new FilteredSellOfferPlanList finds existing SellOfferPlanPriceRange
- if no SellOfferPlanPriceRangePricePendings remain, set SellOfferPlanPriceRange status to complete and trigger CheckFilteredSellOfferPlanComplete:
- remove FilteredSellOfferPlanPending record (do this in CheckFilteredSellOfferPlanComplete for idempodence)
- if no FilteredSellOfferPlanPending remain, set FilteredSellOfferPlanList status to complete, find all matching PriceLogicals and trigger CompletePriceLogical:
- perform comparison on FilteredSellOfferPlanPrice and save results into LogicalResults
- send final ProcessLogicalComplete message
Cart price
A cart has a fixed deliveryMethod and paymentMethod so no comparisons are needed across these, instead the array of sellOfferQuantities are sent to PriceCalc which returns the total price, per sellOffer price, orderQuantity, etc..
Presenting a sellOffer's price options
- For a range of (or all) paymentMethodIds / deliveryMethodIds, deliverToLocationIds / orderQuantity are fixed.
- Enters at SellOfferPlanPriceRange flow
- Maybe have another table that triggers result actions, if any (can maybe poll SellOfferPlanPriceRange table to see if complete)
Presenting a product's price options
- For a range of (or all) paymentMethodIds / deliveryMethodIds, deliverToLocationIds / orderQuantity are fixed
- Enters at SellOfferPlanPriceRange flow, for each of the product's sellOffers
- Maybe have a table that manages the status of all found sellOfferPlans's and their SellOfferPlanPriceRange, similar to FilteredSellOfferPlanList/FilteredSellOfferPlanPending
- Probably find all sellOfferPlan's that match paymentMethodIds / deliveryMethodIds for that product before sending to SellOfferPlanPriceRange flow, similar to FilteredSellOfferPlanList flow