Полноценно редактируются черновики

Добавляются фасовки как в черновике, так и в обучении
Исправил внешний вид
This commit is contained in:
2025-12-17 22:00:21 +03:00
parent e2df2350f7
commit c8aab42e8e
24 changed files with 1313 additions and 433 deletions

View File

@@ -2,7 +2,7 @@ import axios from 'axios';
import type {
CatalogItem,
CreateInvoiceRequest,
MatchRequest, // Используем новый тип
MatchRequest,
HealthResponse,
InvoiceResponse,
ProductMatch,
@@ -12,7 +12,11 @@ import type {
Supplier,
DraftInvoice,
UpdateDraftItemRequest,
CommitDraftRequest
CommitDraftRequest,
// Новые типы
ProductSearchResult,
AddContainerRequest,
AddContainerResponse
} from './types';
// Базовый URL
@@ -33,7 +37,7 @@ apiClient.interceptors.response.use(
}
);
// Мок поставщиков (так как эндпоинта пока нет)
// Мок поставщиков
const MOCK_SUPPLIERS: Supplier[] = [
{ id: '00000000-0000-0000-0000-000000000001', name: 'ООО "Рога и Копыта"' },
{ id: '00000000-0000-0000-0000-000000000002', name: 'ИП Иванов (Овощи)' },
@@ -41,6 +45,17 @@ const MOCK_SUPPLIERS: Supplier[] = [
{ id: '00000000-0000-0000-0000-000000000004', name: 'Simple Wine' },
];
// интерфейс для списка (краткий)
export interface DraftSummary {
id: string;
document_number: string;
date_incoming: string;
status: string;
items_count: number;
total_sum: number;
store_name?: string;
}
export const api = {
checkHealth: async (): Promise<HealthResponse> => {
const { data } = await apiClient.get<HealthResponse>('/health');
@@ -52,11 +67,28 @@ export const api = {
return data;
},
// Оставляем для совместимости со старыми компонентами (если используются),
// но в Draft Flow будем использовать поиск.
getCatalogItems: async (): Promise<CatalogItem[]> => {
const { data } = await apiClient.get<CatalogItem[]>('/ocr/catalog');
return data;
},
// Поиск товаров ---
searchProducts: async (query: string): Promise<ProductSearchResult[]> => {
const { data } = await apiClient.get<ProductSearchResult[]>('/ocr/search', {
params: { q: query }
});
return data;
},
// Создание фасовки ---
createContainer: async (payload: AddContainerRequest): Promise<AddContainerResponse> => {
// Внимание: URL эндпоинта взят из вашего ТЗ (/drafts/container)
const { data } = await apiClient.post<AddContainerResponse>('/drafts/container', payload);
return data;
},
getMatches: async (): Promise<ProductMatch[]> => {
const { data } = await apiClient.get<ProductMatch[]>('/ocr/matches');
return data;
@@ -67,7 +99,6 @@ export const api = {
return data;
},
// Обновили тип аргумента payload
createMatch: async (payload: MatchRequest): Promise<{ status: string }> => {
const { data } = await apiClient.post<{ status: string }>('/ocr/match', payload);
return data;
@@ -77,39 +108,41 @@ export const api = {
const { data } = await apiClient.post<InvoiceResponse>('/invoices/send', payload);
return data;
},
// Получить список складов
getStores: async (): Promise<Store[]> => {
const { data } = await apiClient.get<Store[]>('/dictionaries/stores');
return data;
},
// Получить список поставщиков (Mock)
getSuppliers: async (): Promise<Supplier[]> => {
// Имитация асинхронности
return new Promise((resolve) => {
setTimeout(() => resolve(MOCK_SUPPLIERS), 300);
});
},
// Получить черновик
getDraft: async (id: string): Promise<DraftInvoice> => {
const { data } = await apiClient.get<DraftInvoice>(`/drafts/${id}`);
return data;
},
// Обновить строку черновика (и обучить модель)
// Получить список черновиков
getDrafts: async (): Promise<DraftSummary[]> => {
const { data } = await apiClient.get<DraftSummary[]>('/drafts');
return data;
},
updateDraftItem: async (draftId: string, itemId: string, payload: UpdateDraftItemRequest): Promise<DraftInvoice> => {
// Бэкенд возвращает обновленный черновик целиком (обычно) или обновленный item.
// Предположим, что возвращается обновленный Item или просто 200 OK.
// Но для React Query удобно возвращать данные.
// Если бэк возвращает только item, типизацию нужно уточнить. Пока ждем DraftInvoice или any.
const { data } = await apiClient.patch<DraftInvoice>(`/drafts/${draftId}/items/${itemId}`, payload);
return data;
},
// Зафиксировать черновик
commitDraft: async (draftId: string, payload: CommitDraftRequest): Promise<{ document_number: string }> => {
const { data } = await apiClient.post<{ document_number: string }>(`/drafts/${draftId}/commit`, payload);
return data;
},
// Отменить/Удалить черновик
deleteDraft: async (id: string): Promise<void> => {
await apiClient.delete(`/drafts/${id}`);
},
};

View File

@@ -10,15 +10,36 @@ export interface ProductContainer {
count: number; // 0.180
}
export interface CatalogItem {
// Основные поля (snake_case)
// Запрос на создание фасовки
export interface AddContainerRequest {
product_id: UUID;
name: string; // "Бутылка 0.75"
count: number; // 0.75
}
// Ответ на создание фасовки
export interface AddContainerResponse {
status: string;
container_id: UUID;
}
// Результат поиска товара
export interface ProductSearchResult {
id: UUID;
name: string;
code: string;
measure_unit: string; // "кг", "л"
containers: ProductContainer[]; // Массив фасовок
num?: string;
// Обновляем структуру единицы измерения
main_unit?: MainUnit;
measure_unit?: string; // Оставим для совместимости, но брать будем из main_unit.name
// Fallback (на всякий случай)
containers: ProductContainer[];
}
// Совместимость с CatalogItem (чтобы не ломать старый код, если он где-то используется)
export interface CatalogItem extends ProductSearchResult {
// Fallback поля
ID?: UUID;
Name?: string;
Code?: string;
@@ -32,11 +53,10 @@ export interface MatchRequest {
raw_name: string;
product_id: UUID;
quantity: number;
container_id?: UUID; // Новое поле
container_id?: UUID;
}
export interface ProductMatch {
// snake_case (v2.0)
raw_name: string;
product_id: UUID;
product?: CatalogItem;
@@ -44,14 +64,6 @@ export interface ProductMatch {
container_id?: UUID;
container?: ProductContainer;
updated_at: string;
// Fallback
RawName?: string;
ProductID?: UUID;
Product?: CatalogItem;
Quantity?: number;
ContainerId?: UUID;
Container?: ProductContainer;
}
// --- Нераспознанное ---
@@ -62,7 +74,7 @@ export interface UnmatchedItem {
last_seen: string;
}
// --- Остальные типы (без изменений) ---
// --- Остальные типы ---
export interface Recommendation {
ID: UUID;
@@ -111,7 +123,7 @@ export interface Supplier {
// --- Черновик Накладной (Draft) ---
export type DraftStatus = 'PROCESSING' | 'READY_TO_VERIFY' | 'COMPLETED' | 'ERROR';
export type DraftStatus = 'PROCESSING' | 'READY_TO_VERIFY' | 'COMPLETED' | 'ERROR' | 'CANCELED';
export interface DraftItem {
id: UUID;
@@ -160,4 +172,9 @@ export interface CommitDraftRequest {
store_id: UUID;
supplier_id: UUID;
comment: string;
}
export interface MainUnit {
id: UUID;
name: string; // "кг"
code: string;
}