feat: 套餐使用统计增加MRR与ARR
This commit is contained in:
@@ -24,5 +24,14 @@ public sealed class TenantPackageUsageDto
|
||||
/// 历史总订阅记录数量(不含软删)。
|
||||
/// </summary>
|
||||
public int TotalSubscriptionCount { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// MRR(Monthly Recurring Revenue)粗看:按“当前有效订阅数 × 套餐月付等效价”估算。
|
||||
/// </summary>
|
||||
public decimal Mrr { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// ARR(Annual Recurring Revenue)粗看:按“当前有效订阅数 × 套餐年付等效价”估算。
|
||||
/// </summary>
|
||||
public decimal Arr { get; init; }
|
||||
}
|
||||
|
||||
@@ -45,7 +45,9 @@ public sealed class GetTenantPackageUsagesQueryHandler(IDapperExecutor dapperExe
|
||||
TenantPackageId = reader.GetInt64(0),
|
||||
ActiveSubscriptionCount = reader.GetInt32(1),
|
||||
ActiveTenantCount = reader.GetInt32(2),
|
||||
TotalSubscriptionCount = reader.GetInt32(3)
|
||||
TotalSubscriptionCount = reader.GetInt32(3),
|
||||
Mrr = reader.IsDBNull(4) ? 0m : reader.GetDecimal(4),
|
||||
Arr = reader.IsDBNull(5) ? 0m : reader.GetDecimal(5)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -56,9 +58,10 @@ public sealed class GetTenantPackageUsagesQueryHandler(IDapperExecutor dapperExe
|
||||
|
||||
private static string BuildSql(long[]? ids, out (string Name, object? Value)[] parameters, DateTime now)
|
||||
{
|
||||
// 1. 基础查询
|
||||
// 1. 基础查询:先按订阅表聚合,再回连套餐表计算 MRR/ARR
|
||||
var builder = new System.Text.StringBuilder();
|
||||
builder.AppendLine("""
|
||||
with stats as (
|
||||
select
|
||||
"TenantPackageId" as "TenantPackageId",
|
||||
count(*) filter (where "Status" = 1 and "EffectiveFrom" <= @now and "EffectiveTo" >= @now) as "ActiveSubscriptionCount",
|
||||
@@ -92,8 +95,20 @@ public sealed class GetTenantPackageUsagesQueryHandler(IDapperExecutor dapperExe
|
||||
builder.AppendLine(")");
|
||||
}
|
||||
|
||||
// 3. (空行后) 分组
|
||||
builder.AppendLine("group by \"TenantPackageId\";");
|
||||
// 3. (空行后) 分组与回连套餐表
|
||||
builder.AppendLine("""
|
||||
group by "TenantPackageId"
|
||||
)
|
||||
select
|
||||
s."TenantPackageId" as "TenantPackageId",
|
||||
s."ActiveSubscriptionCount" as "ActiveSubscriptionCount",
|
||||
s."ActiveTenantCount" as "ActiveTenantCount",
|
||||
s."TotalSubscriptionCount" as "TotalSubscriptionCount",
|
||||
(s."ActiveSubscriptionCount"::numeric * coalesce(p."MonthlyPrice", (p."YearlyPrice" / 12.0), 0))::numeric(18, 2) as "Mrr",
|
||||
(s."ActiveSubscriptionCount"::numeric * coalesce(p."YearlyPrice", (p."MonthlyPrice" * 12), 0))::numeric(18, 2) as "Arr"
|
||||
from stats s
|
||||
left join public.tenant_packages p on p."Id" = s."TenantPackageId" and p."DeletedAt" is null;
|
||||
""");
|
||||
|
||||
parameters = list.ToArray();
|
||||
return builder.ToString();
|
||||
|
||||
Reference in New Issue
Block a user