fix(userapi): период тарифа Macloud и отображение ставки на списке VPS
Docker / build (push) Failing after 1m45s

Месячные планы Macloud определяются через inferPlanPeriod; в UI показывается суточная или месячная ставка по tariffType, а не месячный эквивалент.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Denozordec
2026-06-29 11:21:44 +07:00
co-authored by Cursor
parent 579c00392d
commit 87aa6949b3
8 changed files with 149 additions and 30 deletions
+32
View File
@@ -120,6 +120,38 @@ export function tariffTypeLabel(type: string): string {
return TARIFF_TYPE_LABELS[type] ?? type
}
function tariffRateNumber(value: number | string | null | undefined): number | null {
if (value === '' || value == null) return null
const n = Number(value)
return Number.isFinite(n) ? n : null
}
/** Сумма тарифа в валюте провайдера: суточная или месячная — по tariffType. */
export function vpsTariffRateAmount(vps: {
tariffType?: string | null
dailyRate?: number | string | null
monthlyRate?: number | string | null
}): number {
const daily = tariffRateNumber(vps.dailyRate)
const monthly = tariffRateNumber(vps.monthlyRate)
if (vps.tariffType === 'daily') {
return daily ?? 0
}
return monthly ?? 0
}
/** Месячный burn-rate для сортировки и отчётов. */
export function vpsTariffMonthlyBurn(vps: {
tariffType?: string | null
dailyRate?: number | string | null
monthlyRate?: number | string | null
}): number {
const daily = tariffRateNumber(vps.dailyRate) ?? 0
const monthly = tariffRateNumber(vps.monthlyRate) ?? 0
if (vps.tariffType === 'daily') return daily * 30
return monthly
}
const ENVIRONMENT_LABELS: Record<string, string> = {
prod: 'Production', dev: 'Development', staging: 'Staging',
}
+2 -5
View File
@@ -27,6 +27,7 @@ import {
tariffTypeLabel,
vpsStatusLabel,
paymentTypeLabel,
vpsTariffRateAmount,
} from '@/lib/format'
import { providerByIdMap, accountSelectLabel } from '@/lib/billmanager'
import { VPS_SYNC_OVERRIDE_FIELDS, parseUserOverrides } from '@/lib/vps-sync-fields'
@@ -215,11 +216,7 @@ function VpsDetailPage() {
<InfoRow
label="Ставка"
value={formatCurrency(
row.monthlyRate != null
? Number(row.monthlyRate)
: row.tariffType === 'daily'
? Number(row.dailyRate || 0) * 30
: Number(row.monthlyRate || 0),
vpsTariffRateAmount(row),
effectiveVpsTariffCurrency(row, provider),
)}
/>
+3 -13
View File
@@ -6,7 +6,7 @@ import { toast } from 'sonner'
import { snapshotQueryOptions, ratesQueryOptions } from '@/queries/snapshot'
import { api, ApiError } from '@/lib/api-client'
import type { VpsFormValues } from '@/lib/schemas'
import { normalizeRatesPayload, effectiveVpsTariffCurrency, formatCurrency, vpsStatusLabel, tariffTypeLabel } from '@/lib/format'
import { normalizeRatesPayload, effectiveVpsTariffCurrency, formatCurrency, vpsStatusLabel, tariffTypeLabel, vpsTariffRateAmount, vpsTariffMonthlyBurn } from '@/lib/format'
import { PageShell } from '@/components/page-shell'
import { PageHeader } from '@/components/page-header'
import { Button } from '@cfdm/ui/components/button'
@@ -408,21 +408,11 @@ function VpsPage() {
key: 'tariff',
header: 'Тариф',
icon: CreditCardIcon,
sortValue: (v) =>
v.monthlyRate != null
? Number(v.monthlyRate)
: v.tariffType === 'daily'
? Number(v.dailyRate || 0) * 30
: 0,
sortValue: (v) => vpsTariffMonthlyBurn(v),
cell: (v) => {
const provider = providerById.get(v.providerId)
const currency = effectiveVpsTariffCurrency(v, provider)
const amount =
v.monthlyRate != null
? Number(v.monthlyRate)
: v.tariffType === 'daily'
? Number(v.dailyRate || 0) * 30
: Number(v.monthlyRate || 0)
const amount = vpsTariffRateAmount(v)
return dataGridCellStack(formatCurrency(amount, currency), tariffTypeLabel(v.tariffType))
},
},