diff --git a/.gitignore b/.gitignore index 5ae5335..5c28708 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ __pycache__ +warehouse_*/ *.swo *.swp *.json \ No newline at end of file diff --git a/README.md b/README.md index c7a901f..0c64f39 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # 2026-linux-skladman + ## Что это `2026-linux-skladman` - это ИИ-сервис для учёта вещей на складе. Он позволяет: @@ -14,4 +15,41 @@ коробки" предоставляается привязка к Telegram. Учтено то, что может возникнуть необходимость работы как с self-hosted LLM, так -и с крупными ИИ-сервисами (Gemini, OpenAI и т.д.). \ No newline at end of file +и с крупными ИИ-сервисами (Gemini, OpenAI и т.д.). + + +## Пример взаимодействия + +#### Найти что-то и взять сколько-нибудь +``` +USER: Мне надо из 12 вольт сделать 5 вольт +SYSTEM: В "Y12" лежат buck DCDC преобразователи, 5 штук +USER: Взял 2 +SYSTEM: Записал, что их осталось 3 штуки +``` + +#### Узнать, что лежит в ячейке, и исправить данные +``` +USER: че в s3 +SYSTEM: В "S3" лежат 12 штук Arduino +USER: уже нет, они переехали в p4 +SYSTEM: Записал, что теперь в "S3" пусто, а в "P4" лежит 12 штук Arduino. +``` + +#### Реорганизация склада +``` +USER: Мы объединили S3 и S4, теперь оно называется Q2 +SYSTEM: Записал, что больше ячеек S3 и S4 не существуют, но теперь есть + ячейка Q2, в которой лежат Arduino (12 штук) и ESP32 (5 штук). +USER: И ещё ардуин осталось 8, а есп кончились +SYSTEM: Записал, что теперь в Q2 лежат 8 штук Arduino +``` + +#### И так далее + + +## Структура файлов + +* `main.py` - скрипт, который нужно запускать +* `config.json` - конфигурация сервиса, генерируется автоматически при первом запуске +* `warehouse_/` - папка с данными склада, не редактируйте файлы оттуда вручную \ No newline at end of file diff --git a/warehouse.py b/warehouse.py new file mode 100644 index 0000000..f16ddd5 --- /dev/null +++ b/warehouse.py @@ -0,0 +1,89 @@ +""" Warehouse API """ + +import os +from dataclasses import dataclass + +# +# Dataclasses +# +@dataclass +class WarehouseLocation: + """ Location inside warehouse """ + # human readable name of location within warehouse + name: str + # description on how to find the location + how_to_find: str = 'Somewhere inside the warehouse' + # remarks + remarks: str = '' + +@dataclass +class WarehouseItem: + """ Item stored within warehouse """ + # human readable name of item + name: str + # human readable name of measurement unit + unit: str = 'units' + # count of item in units + count: int = 1 + # remarks + remarks: str = '' + # location ID where the item is stored + location_id: int = 0 + +# +# Private +# +_warehouse_name = None +_warehouse_path = None +_locations = {} +_entries = {} + +async def _read_file(path: str) -> str: + """ Read file content and strip it. + Empty string on error. + """ + try: + with open(path, 'r') as f: + return f.read().strip() + except: + return '' + +async def _write_file(path: str, content: str) -> bool: + """ Write file content. """ + try: + with open(path, 'w') as f: + f.write(content) + return True + except: + return False + +async def _fsck_warehouse(path: str) -> bool: + """ Check warehouse for errors and fix them if possible. + Returns True if warehouse is usable. + """ + if not os.path.isdir(path): + return False + +async def _create_warehouse(path: str) -> bool: + """ Create warehouse. + Returns True if warehouse is usable. + """ + if os.path.isdir(path): + return await _fsck_warehouse(path) + locations[0] = WarehouseLocation( + name='Unsorted', + how_to_find='', + remarks='Pseudolocation for unsorted items' + ) + + + +# +# Public +# +async def init(name: str) -> bool: + """ Initialize warehouse API. """ + global _warehouse_name, _warehouse_path + _warehouse_name = name + _warehouse_path = f'warehouse_{name}' + return await _create_warehouse(_warehouse_path) \ No newline at end of file