Shopping cart
Shopping cart example
-- Supported actions: add, remove, update
function main()
-- example object
local testConfig = {
productId="---",
offeringId="---",
count=1,
action="add"
};
mock("body", ToJson(testConfig))
mock("userId", "---")
local userId = param("userId")
local body = FromJson(param("body"))
local count = body.count or 1
-- log the input parameters
log.pairs(body)
-- service id for identifying cart item for update
local service = "cart:" .. userId .. ":" .. body.offeringId
-- find the product, offering and cart item (if it exists)
local product = first(core.QueryDispatch("id:"..body.productId, {"data", "body", "attachments"}))
local offering = first(core.QueryDispatch("id:"..body.offeringId), {"data"})
local existing = first(core.QueryDispatch("given service ["..service.."]", {"data"}))
local result = {}
local data = buildCart(product, offering, body.count, product.attachments)
log.info("*******************")
log.pairs(data)
log.info("*******************")
-- do something with the cart item
if product == nil or offering == nil then
-----------------------
-- Error status
log.error("Error: product and/or offering does not exist")
result.success = false
result.disposition = "error"
result.message = "invalid product or offering"
elseif body.action == "remove" then
-----------------------
-- Remove
result.disposition = "remove"
result.success = true
if existing ~= nil then
core.RemoveUserBucketDispatch({ownerId=userId, dispatchId=existing.id, handle="shopping-cart"})
core.DeleteDispatch(existing.id)
buildCartTotal(userId, existing.id, {}, body.action)
else
buildCartTotal(userId, "nil", {}, body.action)
end
else
-----------------------
-- Add or Update
log.info("Found product and offering")
if existing ~= nil and existing.data ~= nil then
log.info("Cart exists with count " .. existing.data.count)
local existingCount = tonumber(existing.data.count or "0")
-- add the current count if already there
if body.action == "add" then
count = existingCount + count
end
elseif cart ~= nil then
log.info("Cart exists with invalid data")
log.info (existing)
end
local image = first(product.attachments)
local cart = buildCart(product, offering, count)
-- update the disposition stuf
result.count = count
result.disposition = "add"
local d = core.CreateOrUpdateDispatch({
author=userId,
userId=userId,
trackerHandle="cart-item",
attachments={image.id},
data=cart,
serviceId=service,
when=Now()
})
core.AddUserBucketDispatch({ownerId=userId, dispatchId=d, handle="shopping-cart"})
result.dispatch = d
result.success = true
buildCartTotal(userId, d, cart, body.action)
end
Result(result)
end
function buildCartTotal(userId, cartItem, itemDetails, action)
local id = core.UserBucketLookup({ownerId=userId, handle="shopping-cart"})
local ls = core.QueryDispatch("given bucket [" .. id .. "]")
local count = 0
local total = 0
-- total up the cart
for index, dispatch in pairs(ls) do
-- check to see if we should use local data (to avoid timing issues with saving the dispatch)
-- don't add items that were removed
subtotal = 0
if dispatch.id == cartItem and action ~= "remove" then
subtotal = tonumber(itemDetails.price) * itemDetails.count
count = count +1
elseif dispatch.id ~= cartItem then
subtotal = tonumber(dispatch.data.price) * tonumber(dispatch.data.count)
count = count +1
end
total = total + subtotal
end
-- save the totals
local service = "cartTotal:" .. userId
local d = core.CreateOrUpdateDispatch({
author=userId,
userId=userId,
trackerHandle="cart-total",
data={count=count, total=total},
serviceId=service,
when=Now()
})
end
function buildCart(product, offering, count)
-- ** From product, offering **
-- product_name
-- price
-- unit
-- nonStandardUnit
-- size
-- sku
-- ** User **
-- count
-- subtotal
local subtotal = tonumber(offering.data.price) * count
return {
productName = product.data.product_name,
price = offering.data.price,
unit = offering.data.unit,
nonStandardUnit = offering.data.nonStandardUnit,
size = offering.data.size,
sku = offering.data.sku,
count = count,
productId = product.id,
offeringId = offering.id,
subtotal = subtotal
}
end
main()