135 lines
5.4 KiB
Lua
135 lines
5.4 KiB
Lua
-- apiSubscriptionUtils.lua
|
|
-- Shared utility functions for subscription merging and manipulation
|
|
|
|
-- Helper function to get subscription key for grouping (plan_id:normalized_status)
|
|
-- Normalizes status: "active" or past_due=true -> "active", otherwise uses actual status
|
|
local function getSubscriptionKey(subscription)
|
|
local status = subscription.status
|
|
-- Normalize status: "active" or past_due=true -> "active", otherwise use actual status
|
|
if status == "active" or (subscription.past_due == true) then
|
|
status = "active"
|
|
end
|
|
return subscription.plan_id .. ":" .. status
|
|
end
|
|
|
|
-- Helper function to merge subscriptions array by plan ID and normalized status
|
|
-- Groups subscriptions by key (plan_id:normalized_status) and merges quantities
|
|
-- Used by getCustomer.lua to merge customer + entity subscriptions
|
|
-- Parameters: subscriptionsArray - array of subscriptions to merge
|
|
-- Returns: array of merged subscriptions
|
|
local function mergeSubscriptions(subscriptionsArray)
|
|
if not subscriptionsArray or #subscriptionsArray == 0 then
|
|
return {}
|
|
end
|
|
|
|
local record = {}
|
|
|
|
for _, curr in ipairs(subscriptionsArray) do
|
|
local key = getSubscriptionKey(curr)
|
|
local latest = record[key]
|
|
|
|
local currStartedAt = curr.started_at
|
|
|
|
-- Start with latest (or current if no latest exists), then override specific fields
|
|
local mergedSubscription = {}
|
|
if latest then
|
|
-- Copy all fields from latest first
|
|
for k, v in pairs(latest) do
|
|
mergedSubscription[k] = v
|
|
end
|
|
else
|
|
-- Copy all fields from current
|
|
for k, v in pairs(curr) do
|
|
mergedSubscription[k] = v
|
|
end
|
|
end
|
|
|
|
-- Apply merge logic for specific fields
|
|
if latest then
|
|
-- canceled_at: current.canceled_at if exists, else latest.canceled_at, else null
|
|
if curr.canceled_at and curr.canceled_at ~= cjson.null and curr.canceled_at ~= nil then
|
|
mergedSubscription.canceled_at = curr.canceled_at
|
|
elseif latest.canceled_at and latest.canceled_at ~= cjson.null and latest.canceled_at ~= nil then
|
|
mergedSubscription.canceled_at = latest.canceled_at
|
|
else
|
|
mergedSubscription.canceled_at = cjson.null
|
|
end
|
|
|
|
-- started_at: latest.started_at ? min(latest.started_at, current.started_at) : current.started_at
|
|
if latest.started_at then
|
|
mergedSubscription.started_at = math.min(latest.started_at, currStartedAt)
|
|
else
|
|
mergedSubscription.started_at = currStartedAt
|
|
end
|
|
|
|
-- quantity: (latest.quantity or 0) + (current.quantity or 0)
|
|
local latestQuantity = latest.quantity or 0
|
|
local currQuantity = curr.quantity or 0
|
|
mergedSubscription.quantity = latestQuantity + currQuantity
|
|
|
|
-- past_due: true if either is true
|
|
mergedSubscription.past_due = (latest.past_due == true) or (curr.past_due == true)
|
|
else
|
|
-- First subscription in group, ensure defaults
|
|
mergedSubscription.canceled_at = curr.canceled_at or cjson.null
|
|
mergedSubscription.started_at = currStartedAt
|
|
mergedSubscription.quantity = curr.quantity or 0
|
|
mergedSubscription.past_due = curr.past_due or false
|
|
end
|
|
|
|
record[key] = mergedSubscription
|
|
end
|
|
|
|
-- Convert record back to array
|
|
local mergedSubscriptions = {}
|
|
for _, subscription in pairs(record) do
|
|
table.insert(mergedSubscriptions, subscription)
|
|
end
|
|
|
|
return mergedSubscriptions
|
|
end
|
|
|
|
-- Helper function to merge customer subscriptions into entity subscriptions
|
|
-- Adds customer subscriptions that don't already exist in entity subscriptions (by subscription key)
|
|
-- Does NOT merge quantities - only adds missing subscriptions
|
|
-- Used by getEntity.lua to add customer subscriptions to entity subscriptions
|
|
-- Parameters:
|
|
-- entitySubscriptions - array of entity subscriptions (base)
|
|
-- customerSubscriptions - array of customer subscriptions to add
|
|
-- Returns: array of merged subscriptions (entity subscriptions + customer subscriptions that don't exist)
|
|
local function mergeCustomerSubscriptionsIntoEntity(entitySubscriptions, customerSubscriptions)
|
|
if not customerSubscriptions or #customerSubscriptions == 0 then
|
|
return entitySubscriptions or {}
|
|
end
|
|
|
|
if not entitySubscriptions then
|
|
entitySubscriptions = {}
|
|
end
|
|
|
|
-- Build a set of existing subscription keys in entity subscriptions
|
|
local existingKeys = {}
|
|
for _, subscription in ipairs(entitySubscriptions) do
|
|
local key = getSubscriptionKey(subscription)
|
|
existingKeys[key] = true
|
|
end
|
|
|
|
-- Add customer subscriptions that don't exist in entity subscriptions
|
|
local mergedSubscriptions = {}
|
|
|
|
-- First, add all entity subscriptions
|
|
for _, subscription in ipairs(entitySubscriptions) do
|
|
table.insert(mergedSubscriptions, subscription)
|
|
end
|
|
|
|
-- Then, add customer subscriptions that don't exist
|
|
for _, customerSubscription in ipairs(customerSubscriptions) do
|
|
local key = getSubscriptionKey(customerSubscription)
|
|
if not existingKeys[key] then
|
|
table.insert(mergedSubscriptions, customerSubscription)
|
|
end
|
|
end
|
|
|
|
return mergedSubscriptions
|
|
end
|
|
|