chore(repo): дедуп formatAmount, пины образов, дефолты MinIO, доля any

Шаги 2.3 и 2.4 плана production-готовности:
- lib/format.ts formatAmount вместо 2 локальных копий
- пины тегов minio/rclone/ollama/traccar/pgvector + osrm по digest
- minioadmin без дефолта (env required, dev-подсказки в .env.example)
- 28 any в auto-transitions/shared типизированы из @shared/schema
- удалён _tablefield_orig.txt
- check/lint/build чисто, vitest 104/104
This commit is contained in:
2026-09-08 01:07:55 +03:00
parent 5750a3106f
commit 75ec0f25bb
12 changed files with 118 additions and 204 deletions

7
client/src/lib/format.ts Normal file
View File

@@ -0,0 +1,7 @@
// Форматирование денежных сумм: разделители разрядов ru-RU, всегда 2 знака после запятой.
// Пустое/некорректное значение отображается как "0.00".
export function formatAmount(amount: string | number | undefined | null): string {
const value = typeof amount === "number" ? amount : parseFloat(amount ?? "");
if (!isFinite(value)) return "0.00";
return value.toLocaleString("ru-RU", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}

View File

@@ -19,6 +19,7 @@ import { Wallet, Users, TrendingDown, Calendar, ArrowUpCircle, ArrowDownCircle,
import { format } from "date-fns";
import { ru } from "date-fns/locale";
import { apiRequest } from "@/lib/queryClient";
import { formatAmount } from "@/lib/format";
import { useToast } from "@/hooks/use-toast";
interface BillingSummary {
@@ -149,9 +150,6 @@ export default function Billing() {
const currency = summary?.currency ?? "RUB";
const isMockProvider = summary?.paymentProvider === "mock";
const formatAmount = (amount: string) =>
parseFloat(amount).toLocaleString("ru-RU", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
const handleTopUp = () => {
const amountNum = parseFloat(amount.replace(",", ".").replace(/\s/g, ""));
if (!amountNum || isNaN(amountNum) || amountNum <= 0) {

View File

@@ -14,6 +14,7 @@ import { useState } from "react";
import { useToast } from "@/hooks/use-toast";
import { format } from "date-fns";
import { ru } from "date-fns/locale";
import { formatAmount } from "@/lib/format";
interface BillingTransaction {
id: number;
@@ -176,9 +177,6 @@ export default function SuperAdminOrgDetail() {
const billing = billingData?.billing;
const transactions = txData?.transactions ?? [];
const formatAmount = (amount: string | undefined) =>
amount ? parseFloat(amount).toLocaleString("ru-RU", { minimumFractionDigits: 2 }) : "0.00";
return (
<div className="min-h-screen bg-slate-950 text-white">
{/* Header */}