Files
cfw-autumn/server/src/_luaScripts/luaUtils/getCustomerEntityUtils.lua
2025-11-19 19:51:34 +00:00

162 lines
6.4 KiB
Lua

-- ============================================================================
-- GET CUSTOMER/ENTITY UTILITY FUNCTIONS
-- ============================================================================
-- Get customer object with merged balances and subscriptions
-- Parameters:
-- orgId: Organization ID
-- env: Environment
-- customerId: Customer ID
-- skipEntityMerge: If true, only load customer's own balances (no entity merging)
-- Returns: customer object table (not JSON encoded), or nil if not found
local function getCustomerObject(orgId, env, customerId, skipEntityMerge)
-- Build versioned cache key using shared utility
local cacheKey = buildCustomerCacheKey(orgId, env, customerId)
-- Load balances based on merge mode
-- If skipEntityMerge is true, only load customer's own balances (no entity merging)
-- If skipEntityMerge is false, load merged balances (customer + entities)
local balances
if skipEntityMerge then
-- Load only customer's own balances without entity merging
balances = loadBalances(cacheKey, orgId, env, customerId, "__CUSTOMER_ONLY__")
else
-- Load merged balances (customer + entities)
balances = loadBalances(cacheKey, orgId, env, customerId)
end
if not balances then
return nil -- Customer not in cache or partial eviction detected
end
-- Get base customer JSON for subscriptions and metadata
local baseJson = redis.call("GET", cacheKey)
if not baseJson then
return nil
end
local baseCustomer = cjson.decode(baseJson)
local entityIds = baseCustomer._entityIds or {}
-- ============================================================================
-- MERGE ENTITY SUBSCRIPTIONS INTO CUSTOMER SUBSCRIPTIONS
-- ============================================================================
-- Build entity base data map for subscription access
local entityBaseData = {}
for _, entityId in ipairs(entityIds) do
local entityCacheKey = buildEntityCacheKey(orgId, env, customerId, entityId)
local entityBaseJson = redis.call("GET", entityCacheKey)
if entityBaseJson then
entityBaseData[entityId] = cjson.decode(entityBaseJson)
end
end
-- Collect all subscriptions: start with customer's subscriptions, then add all entity subscriptions
local allSubscriptions = {}
if baseCustomer.subscriptions then
for _, subscription in ipairs(baseCustomer.subscriptions) do
table.insert(allSubscriptions, subscription)
end
end
-- Add subscriptions from each entity
for _, entityId in ipairs(entityIds) do
local entityBase = entityBaseData[entityId]
if entityBase and entityBase.subscriptions then
for _, subscription in ipairs(entityBase.subscriptions) do
table.insert(allSubscriptions, subscription)
end
end
end
-- Merge subscriptions by plan ID and normalized status
baseCustomer.subscriptions = mergeSubscriptions(allSubscriptions)
-- Merge invoices
-- Build final customer object
baseCustomer.invoices = baseCustomer.invoices or nil
baseCustomer._balanceFeatureIds = nil -- Remove tracking field
baseCustomer._entityIds = nil -- Remove tracking field
baseCustomer.balances = balances
return baseCustomer
end
-- Get entity object with merged balances and subscriptions
-- Parameters:
-- orgId: Organization ID
-- env: Environment
-- customerId: Customer ID
-- entityId: Entity ID
-- skipCustomerMerge: If true, only load entity's own balances (no customer merging)
-- Returns: entity object table (not JSON encoded), or nil if not found
local function getEntityObject(orgId, env, customerId, entityId, skipCustomerMerge)
-- Build versioned entity cache key using shared utility
local entityCacheKey = buildEntityCacheKey(orgId, env, customerId, entityId)
-- Get base entity JSON
local baseJson = redis.call("GET", entityCacheKey)
if not baseJson then
return nil
end
local baseEntity = cjson.decode(baseJson)
-- Build customer cache key for balance loading
local customerCacheKey = buildCustomerCacheKey(orgId, env, customerId)
-- ============================================================================
-- LOAD BALANCES USING loadBalances
-- ============================================================================
local mergedBalances
if skipCustomerMerge then
-- Load only entity's own balances (no customer merging)
-- We'll use loadBalances with "__CUSTOMER_ONLY__" mode on the entity cache key
-- This is a bit of a hack but works with the current structure
mergedBalances = loadBalances(entityCacheKey, orgId, env, customerId, "__CUSTOMER_ONLY__")
else
-- Load entity-level merged balances (entity + customer)
-- loadBalances handles this when entityId is provided
mergedBalances = loadBalances(customerCacheKey, orgId, env, customerId, entityId)
end
-- If balances loading failed (partial eviction), return nil
if not mergedBalances then
return nil
end
-- ============================================================================
-- MERGE CUSTOMER SUBSCRIPTIONS INTO ENTITY SUBSCRIPTIONS
-- Skip if skipCustomerMerge is true
-- ============================================================================
-- Get entity subscriptions (start with entity's own subscriptions)
local entitySubscriptions = baseEntity.subscriptions or {}
if not skipCustomerMerge then
-- Get customer subscriptions
local customerSubscriptions = nil
local customerBaseJson = redis.call("GET", customerCacheKey)
if customerBaseJson then
local customerBase = cjson.decode(customerBaseJson)
customerSubscriptions = customerBase.subscriptions
end
-- Merge customer subscriptions into entity subscriptions (only add if not exists)
baseEntity.subscriptions = mergeCustomerSubscriptionsIntoEntity(entitySubscriptions, customerSubscriptions)
else
-- No merging - just use entity's own subscriptions
baseEntity.subscriptions = entitySubscriptions
end
-- Build final entity object
baseEntity._balanceFeatureIds = nil -- Remove tracking field
baseEntity.balances = mergedBalances
return baseEntity
end