From cabc7b865aef3062035fb8d67a79fdb4d745a3ef Mon Sep 17 00:00:00 2001 From: dv Date: Thu, 9 Apr 2026 11:40:51 +0300 Subject: [PATCH] =?UTF-8?q?=D0=B2=D1=80=D0=B5=D0=BC=D1=8F=20=D0=B8=D0=B7?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/routers/objects.py | 15 +++++++++++++-- backend/app/schemas/object.py | 1 + frontend/src/api/objects.ts | 2 ++ frontend/src/pages/Objects.tsx | 7 +++++++ 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/backend/app/routers/objects.py b/backend/app/routers/objects.py index 7e19be8..08c01cc 100644 --- a/backend/app/routers/objects.py +++ b/backend/app/routers/objects.py @@ -3,7 +3,7 @@ import re from typing import Annotated from fastapi import APIRouter, Depends, File, HTTPException, UploadFile, status -from sqlalchemy import select, distinct +from sqlalchemy import func, select, distinct from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload @@ -91,7 +91,18 @@ async def list_objects( query = query.where(Object.client == client) query = query.order_by(Object.city, Object.client, Object.name) result = await db.execute(query) - return result.scalars().all() + objects = result.scalars().all() + if objects: + ids = [o.id for o in objects] + cnt_rows = await db.execute( + select(Device.object_id, func.count(Device.id).label("cnt")) + .where(Device.object_id.in_(ids)) + .group_by(Device.object_id) + ) + counts = dict(cnt_rows.all()) + for obj in objects: + obj.device_count = counts.get(obj.id, 0) + return objects @router.post("", response_model=ObjectRead, status_code=status.HTTP_201_CREATED) diff --git a/backend/app/schemas/object.py b/backend/app/schemas/object.py index a07ef5e..214093d 100644 --- a/backend/app/schemas/object.py +++ b/backend/app/schemas/object.py @@ -76,6 +76,7 @@ class ObjectRead(BaseModel): created_at: datetime updated_at: datetime tags: list[TagRead] = [] + device_count: int = 0 model_config = {"from_attributes": True} diff --git a/frontend/src/api/objects.ts b/frontend/src/api/objects.ts index 419cd93..14d561a 100644 --- a/frontend/src/api/objects.ts +++ b/frontend/src/api/objects.ts @@ -13,6 +13,8 @@ export interface ObjectItem { is_active: boolean tags: { id: number; name: string; color: string }[] created_at: string + updated_at: string + device_count: number } export interface ObjectMeta { diff --git a/frontend/src/pages/Objects.tsx b/frontend/src/pages/Objects.tsx index 67c66d4..80bcc57 100644 --- a/frontend/src/pages/Objects.tsx +++ b/frontend/src/pages/Objects.tsx @@ -27,6 +27,7 @@ import { Upload, message, } from 'antd' +import dayjs from 'dayjs' import { useMemo, useState } from 'react' import { useNavigate } from 'react-router-dom' import { @@ -212,6 +213,12 @@ export function ObjectsPage({ mode }: Props) { {t.name} ))} {!obj.is_active && Неактивен} + + {obj.device_count} уст. + + + изм. {dayjs(obj.updated_at).format('DD.MM.YY HH:mm')} + {mode === 'inventory' && (