Files
cfw-autumn/server/src/_luaScripts/luaUtils/apiSubscriptionUtils.lua
2025-11-11 16:01:14 +00:00

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