время изменения
This commit is contained in:
parent
0d0cec1f9f
commit
cabc7b865a
4 changed files with 23 additions and 2 deletions
|
|
@ -3,7 +3,7 @@ import re
|
||||||
from typing import Annotated
|
from typing import Annotated
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile, status
|
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.ext.asyncio import AsyncSession
|
||||||
from sqlalchemy.orm import selectinload
|
from sqlalchemy.orm import selectinload
|
||||||
|
|
||||||
|
|
@ -91,7 +91,18 @@ async def list_objects(
|
||||||
query = query.where(Object.client == client)
|
query = query.where(Object.client == client)
|
||||||
query = query.order_by(Object.city, Object.client, Object.name)
|
query = query.order_by(Object.city, Object.client, Object.name)
|
||||||
result = await db.execute(query)
|
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)
|
@router.post("", response_model=ObjectRead, status_code=status.HTTP_201_CREATED)
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@ class ObjectRead(BaseModel):
|
||||||
created_at: datetime
|
created_at: datetime
|
||||||
updated_at: datetime
|
updated_at: datetime
|
||||||
tags: list[TagRead] = []
|
tags: list[TagRead] = []
|
||||||
|
device_count: int = 0
|
||||||
|
|
||||||
model_config = {"from_attributes": True}
|
model_config = {"from_attributes": True}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ export interface ObjectItem {
|
||||||
is_active: boolean
|
is_active: boolean
|
||||||
tags: { id: number; name: string; color: string }[]
|
tags: { id: number; name: string; color: string }[]
|
||||||
created_at: string
|
created_at: string
|
||||||
|
updated_at: string
|
||||||
|
device_count: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ObjectMeta {
|
export interface ObjectMeta {
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import {
|
||||||
Upload,
|
Upload,
|
||||||
message,
|
message,
|
||||||
} from 'antd'
|
} from 'antd'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
import { useMemo, useState } from 'react'
|
import { useMemo, useState } from 'react'
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
import {
|
import {
|
||||||
|
|
@ -212,6 +213,12 @@ export function ObjectsPage({ mode }: Props) {
|
||||||
<Tag key={t.id} color={t.color} style={{ margin: 0 }}>{t.name}</Tag>
|
<Tag key={t.id} color={t.color} style={{ margin: 0 }}>{t.name}</Tag>
|
||||||
))}
|
))}
|
||||||
{!obj.is_active && <Tag color="default">Неактивен</Tag>}
|
{!obj.is_active && <Tag color="default">Неактивен</Tag>}
|
||||||
|
<Typography.Text type="secondary" style={{ fontSize: 12, whiteSpace: 'nowrap' }}>
|
||||||
|
{obj.device_count} уст.
|
||||||
|
</Typography.Text>
|
||||||
|
<Typography.Text type="secondary" style={{ fontSize: 12, whiteSpace: 'nowrap' }}>
|
||||||
|
изм. {dayjs(obj.updated_at).format('DD.MM.YY HH:mm')}
|
||||||
|
</Typography.Text>
|
||||||
{mode === 'inventory' && (
|
{mode === 'inventory' && (
|
||||||
<Space size={4}>
|
<Space size={4}>
|
||||||
<Button size="small" icon={<EditOutlined />} onClick={() => openEdit(obj)} />
|
<Button size="small" icon={<EditOutlined />} onClick={() => openEdit(obj)} />
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue