- Add explicit date input format '%Y-%m-%d' to WriteOffDocumentForm and IncomingDocumentForm
- Disable localization for date fields to ensure yyyy-MM-dd format is used
- Set initial date value to current date in WriteOffDocumentCreateView's get_initial method
- Restrict warehouse queryset to active warehouses in forms initialization
- Improve date widget consistency by adding format parameter to DateInput widgets
- Move default date initialization from form to view initial data
- Add checks for DOM elements existence before event listener attachment
- Handle 'clear' mode in bulk category modal with confirmation and API call
- Improve CSRF token usage and error handling during bulk update requests
- Remove deprecated handleClearAll function and integrate logic into handleApply
- Reset modal state properly including input fields and radio button modes
- Update modal JS file version reference in products list template
- inventory/views/showcase.py: фильтр .exclude(status='reserved')
* Витринные букеты со статусом 'reserved' не отображаются в POS
* Защита от конфликтов: один букет - один заказ
- pos/views.py: фильтр .exclude(showcase_items__status='reserved')
* Showcase комплекты без доступных букетов скрыты в POS
* Фильтрация на уровне queryset для производительности
- Консистентная видимость витрины для всех кассиров
Проблема: при создании тенанта автоматически создаются дефолтные
Склад и Витрина. Если пользователь удалит их, система может сломаться:
POS, создание заказов и резервирование перестанут работать.
Решение: реализована строгая валидация + мягкое удаление для витрин.
Изменения в inventory/views/warehouse.py:
- Добавлена валидация перед деактивацией склада:
* Блокировка деактивации последнего активного склада
* Проверка ненулевых остатков товаров
* Проверка активных резервов
* Предупреждение при деактивации дефолтного склада
Изменения в inventory/views/showcase.py:
- ShowcaseListView: по умолчанию показывает только активные витрины
- ShowcaseDeleteView: изменена логика с жесткого на мягкое удаление
- Добавлена валидация перед деактивацией витрины:
* Блокировка деактивации последней активной витрины склада
* Проверка активных резервов
* Проверка физических экземпляров комплектов (ShowcaseItem)
* Предупреждение при деактивации дефолтной витрины
Изменения в inventory/forms_showcase.py:
- Проверка уникальности названия витрины учитывает только активные
Изменения в inventory/admin.py:
- ShowcaseAdmin: добавлены методы delete_model() и delete_queryset()
для блокировки удаления последней витрины через админку
- WarehouseAdmin: добавлены методы delete_model() и delete_queryset()
для блокировки удаления последнего склада через админку
Преимущества:
✅ Система не сломается - всегда есть хотя бы один активный склад/витрина
✅ Данные в безопасности - мягкое удаление для обеих сущностей
✅ Понятные сообщения об ошибках для пользователя
✅ Защита работает как в UI, так и в Django Admin
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Remove WriteOffForm from forms.py and add comment directing to WriteOffDocumentForm
- Update navigation templates to remove writeoff links and sections
- Add 'Сумма' column to sale list with multiplication filter
- Delete writeoff-related templates (list, form, confirm delete)
- Add 'multiply' filter to inventory_filters.py for calculations
- Comment out writeoff URLs in urls.py, keeping WriteOff model for automatic creation
- Remove WriteOff views from __init__.py and delete writeoff.py view file
This change simplifies writeoff management by removing direct individual writeoff operations and enforcing use of WriteOffDocument for all writeoffs, with WriteOff records created automatically upon document processing.
Удалены все упоминания URL-паттерна 'movement-list' после удаления
модели StockMovement:
- Карточка "Журнал" на главной странице inventory
- Пункт меню "Журнал" в навигации base_inventory_minimal
- Экспорт StockMovementListView из views/__init__.py
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Текущее состояние перед рефакторингом Transfer → TransferDocument.
Все изменения с последнего коммита по улучшению системы поступлений.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Удалена старая одноэтапная система incoming и оставлена только новая
двухэтапная система IncomingDocument (черновик → проведение).
Изменения:
- URL структура изменена с /incoming-documents/ на /incoming/
- URL names: incoming-document-* → incoming-*
- Удалены старые views, forms, templates для Incoming/IncomingBatch
- Обновлена навигация и все ссылки в шаблонах
- Модели IncomingBatch/Incoming сохранены как внутренняя архитектура
Удалено ~1590 строк кода:
- inventory/views/incoming.py (389 строк)
- inventory/forms.py (206 строк старых форм)
- inventory/admin.py (56 строк)
- 4 шаблона incoming/*.html (895 строк)
Обновлено:
- inventory/urls.py - новая URL структура
- inventory/views/incoming_document.py - обновлены redirects
- Все шаблоны с ссылками на incoming
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Добавлено свойство can_edit в модель Incoming
- Добавлена проверка в IncomingUpdateView для запрета редактирования обработанных приходов
- Скрыта кнопка редактирования в списке приходов для обработанных записей
- Добавлено предупреждение в форму редактирования
Это предотвращает проблемы с целостностью данных при FIFO-списаниях, когда партия уже может быть использована в продажах.
Исправлена проблема, когда при отмене проведенной трансформации оба сигнала выполнялись последовательно:
- rollback_transformation_on_cancel возвращал резервы в 'reserved'
- release_reservations_on_draft_cancel ошибочно освобождал их в 'released'
Изменена проверка в release_reservations_on_draft_cancel: вместо проверки наличия партий Output (которые уже удалены) теперь проверяется статус резервов ('converted_to_transformation') или наличие поля converted_at, что работает независимо от порядка выполнения сигналов.
Реализована полная система трансформации товаров (превращение одного товара в другой).
Пример: белая гипсофила → крашеная гипсофила.
Особенности реализации:
- Резервирование входных товаров в статусе draft
- FIFO списание входных товаров при проведении
- Автоматический расчёт себестоимости выходных товаров
- Возможность отмены как черновиков, так и проведённых трансформаций
Модели (inventory/models.py):
- Transformation: документ трансформации (draft/completed/cancelled)
- TransformationInput: входные товары (списание)
- TransformationOutput: выходные товары (оприходование)
- Добавлен статус 'converted_to_transformation' в Reservation
- Добавлен тип 'transformation' в DocumentCounter
Бизнес-логика (inventory/services/transformation_service.py):
- TransformationService с методами CRUD
- Валидация наличия товаров
- Автоматическая генерация номеров документов
Сигналы (inventory/signals.py):
- Автоматическое резервирование входных товаров
- FIFO списание при проведении
- Создание партий выходных товаров
- Откат операций при отмене
Интерфейс без Django Admin:
- Список трансформаций (list.html)
- Форма создания (form.html)
- Детальный просмотр с добавлением товаров (detail.html)
- Интеграция с компонентом поиска товаров
- 8 views для полного CRUD + проведение/отмена
Миграция:
- 0003_alter_documentcounter_counter_type_and_more.py
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Добавлены поля snapshot_* в модель InventoryLine для фиксации значений на момент завершения
- Обновлен InventoryProcessor для сохранения snapshot перед обработкой
- Обновлен InventoryDetailView для отображения snapshot-значений в проведенных инвентаризациях
- Добавлена миграция 0018 для новых полей
- Теперь в проведенных инвентаризациях отображаются оригинальные значения и правильная разница, а не текущие скорректированные остатки
- Автоматическое проведение документов списания и оприходования после завершения инвентаризации
- Оптимизация SQL-запросов: устранение N+1, bulk-операции для Stock, агрегация для StockBatch и Reservation
- Изменение формулы расчета разницы: (quantity_fact + quantity_reserved) - quantity_available
- Переименование поля 'По факту' в 'Подсчитано (факт, свободные)'
- Добавлены столбцы 'В резервах' и 'Всего на складе' в таблицу инвентаризации
- Перемещение столбца 'В системе (свободно)' после 'В резервах' с визуальным выделением
- Центральное выравнивание значений в столбцах таблицы
- Автоматическое выделение текста при фокусе на поле ввода количества
- Исправление форматирования разницы (убраны лишние нули)
- Изменение статуса 'Не обработана' на 'Не проведено'
- Добавление номера документа для инвентаризаций (INV-XXXXXX)
- Отображение всех типов списаний в debug-странице (WriteOff, WriteOffDocument, WriteOffDocumentItem)
- Улучшение отображения документов в детальном просмотре инвентаризации с возможностью перехода к ним
- Fix MEDIA_ROOT path to match Docker volume mount (/app/myproject/media)
- Update docker-compose.yml volume mounts to match MEDIA_ROOT
- Add setup_directories() function in entrypoint.sh to create media directories with proper permissions
- Add logging to TenantAwareFileSystemStorage for debugging
- Fix is_returned flag logic improvements (from previous work)
- Унифицирован формат номеров документов: IN-XXXXXX (6 цифр), как WO-XXXXXX и MOVE-XXXXXX
- Убрано дублирование функции _extract_number_from_document_number
- Оптимизирована инициализация счетчика incoming: быстрая проверка перед полной инициализацией
- Удален неиспользуемый файл utils.py (функциональность перенесена в document_generator.py)
- Все функции генерации номеров используют единый подход через DocumentCounter.get_next_value()
- Добавлено поле receipt_type в модель IncomingBatch с типами: supplier, inventory, adjustment
- Исправлен баг в InventoryProcessor: теперь корректно создается IncomingBatch при инвентаризации
- Создан IncomingAdjustmentCreateView для оприходования без инвентаризации
- Обновлены формы, шаблоны и админка для поддержки разных типов поступлений
- Добавлена навигация и URL для оприходования
- Тип поступления отображается в списках приходов и партий
- Добавлен параметр warehouse в API search_products_and_variants
- API фильтрует товары по наличию на указанном складе через Stock
- Обновлен _apply_product_filters для поддержки warehouse_id
- ProductSearchPicker теперь поддерживает data-warehouse-id
- Warehouse автоматически передается в AJAX запросы
- В WriteOffDocumentDetailView добавлены categories и tags в контекст
- Компонент поиска встроен в detail.html с жестким фильтром по складу документа
- Single-select режим для выбора одного товара
- JS автоматически заполняет select формы при выборе товара
- Отображение выбранного товара с фото и артикулом
- Автофокус на поле количества после выбора товара
- Пользователь видит только товары доступные на складе документа
- В WriteOffCreateView добавлена передача категорий и тегов в контекст
- Шаблон writeoff_form.html обновлен с использованием product_search_picker
- Автоматическая фильтрация партий по выбранному товару
- Отображение информации о выбранном товаре с фото
- Улучшенный UX при выборе товара для списания
- Подключены CSS и JS компонента поиска товаров
- WriteOffDocumentListView - список документов с пагинацией
- WriteOffDocumentCreateView - создание нового документа
- WriteOffDocumentDetailView - детальный просмотр документа
- WriteOffDocumentAddItemView - добавление позиции (AJAX)
- WriteOffDocumentUpdateItemView - обновление позиции (AJAX)
- WriteOffDocumentRemoveItemView - удаление позиции (AJAX)
- WriteOffDocumentConfirmView - проведение документа
- WriteOffDocumentCancelView - отмена документа
- Добавлены URL-маршруты для всех операций с документами списания
- Поддержка AJAX запросов для динамической работы с позициями
- Исправлен метод write_off_by_fifo() для учета зарезервированных партий
- Добавлено автоматическое проставление даты и времени при создании заказов в POS
- Исправлена ошибка фильтрации Product (is_active -> status='active') в transfers
- Предотвращает списание из зарезервированных партий, устраняя отрицательные остатки
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Проблема:
- Фильтр по заказу не работал
- order_number в форме передается как строка (ORD-103 или 103)
- В модели Order поле order_number имеет тип PositiveIntegerField
- Не было преобразования строки в число
Исправление:
- Добавлен парсинг номера заказа:
* Если формат 'ORD-103' -> извлекается число 103
* Если просто '103' -> преобразуется в число 103
- Добавлена обработка ошибок (try-except)
- Добавлена фильтрация таблицы заказов (показывать только выбранный)
Теперь фильтр работает с любым форматом ввода:
- ORD-103 ✓
- ord-103 ✓
- 103 ✓
Реализация:
- Создан view debug_inventory_page (только для суперюзеров)
- URL: /inventory/debug/
- Компактный дизайн с минимальными отступами (10-11px)
- Ссылка 🔧 Debug в navbar (видна только суперюзерам)
Функционал:
1. Показывает полную картину инвентаризации на одной странице:
- Заказы (Order) - номер, статус, покупатель, is_returned
- Остатки (Stock) - доступно, зарезервировано, свободно
- Партии (StockBatch) - количество, активность, дата поступления
- Резервы (Reservation) - статус, заказ, все даты
- Продажи (Sale) - количество, цена продажи, заказ
- Списания (SaleBatchAllocation) - откуда списано, сколько
2. Фильтры:
- По товару (dropdown)
- По номеру заказа (текстовое поле)
- По складу (dropdown)
3. UI:
- Цветовая индикация статусов резервов
- Бейджи для ключевых данных
- Компактные таблицы Bootstrap
- Неактивные партии выделены красным
Исправления:
- Reservation.created_at → reserved_at (у модели нет created_at)
- Sale.created_at → date (дата операции хранится в поле date)
- Product.is_active → archived_at__isnull=True (используется soft delete)
- Удалена колонка себестоимости из Sale (это поле не хранится в модели)
Файлы:
- inventory/views/debug_views.py - новый view
- inventory/templates/inventory/debug_page.html - шаблон
- inventory/urls.py - добавлен роут
- templates/navbar.html - добавлена ссылка
Юзкейс:
Суперюзер принимает товар → оформляет заказ → меняет статусы →
переходит на /inventory/debug/ → видит полную картину изменений
Проблема:
- У модели Reservation нет поля created_at
- Есть поле reserved_at для даты создания резерва
Исправление:
- В view изменена сортировка order_by('-reserved_at')
- В шаблоне изменено отображение даты res.reserved_at
Реализация:
- Создан view debug_inventory_page (только для суперюзеров)
- URL: /inventory/debug/
- Компактный дизайн с минимальными отступами и маленьким шрифтом (10-11px)
Функционал:
1. Показывает полную картину инвентаризации на одной странице:
- Заказы (Order) - номер, статус, покупатель, is_returned
- Остатки (Stock) - доступно, зарезервировано, свободно
- Партии (StockBatch) - количество, активность, дата поступления
- Резервы (Reservation) - статус (reserved/converted_to_sale/released), заказ, даты
- Продажи (Sale) - количество, цены, заказ
- Списания (SaleBatchAllocation) - откуда списано, сколько
2. Фильтры:
- По товару (dropdown с названием и SKU)
- По номеру заказа (текстовое поле)
- По складу (dropdown)
- Кнопка 'Применить' и 'Сбросить'
3. UI:
- Цветовая индикация статусов резервов
- Бейджи для ключевых данных
- Компактные таблицы Bootstrap
- Неактивные партии выделены красным
- Ограничение в 100 записей на таблицу для производительности
4. Навигация:
- Ссылка 🔧 Debug в navbar (видна только суперюзерам)
- Красный цвет для видимости
Юзкейс:
Суперюзер принимает товар на склад → оформляет заказ → меняет статусы →
переходит на /inventory/debug/ → видит полную картину всех изменений
Файлы:
- inventory/views/debug_views.py - новый view
- inventory/templates/inventory/debug_page.html - шаблон
- inventory/urls.py - добавлен роут
- templates/navbar.html - добавлена ссылка для суперюзеров
- Add total_available, total_reserved, total_free annotations to product queries
- Display free stock (green/red) with reserved count in product list
- Show detailed stock info in product detail page (moved to top)
- Make reservation count clickable to view filtered reservations
- Add product filter support to ReservationListView
- Add product link in reservation list for easy navigation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
PROBLEM:
Direct deletion/creation of reservations via web interface bypassed
POS business logic, creating data inconsistencies (orphaned showcase kits,
incorrect stock calculations).
SOLUTION:
Make reservations read-only in web interface. All reservation management
now happens only through:
- POS (showcase kits)
- Orders module
CHANGES:
- Remove reservation-create and reservation-update URL routes
- Delete ReservationCreateView and ReservationUpdateView
- Remove ReservationForm (no longer needed)
- Delete reservation_form.html and reservation_update.html templates
- Update reservation_list.html to read-only view with info banner
- Add showcase and order columns to reservation list
- Clean up imports in urls.py and views/__init__.py
Reservations are now read-only for monitoring purposes only.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add is_default field to Showcase model with unique constraint per warehouse
- Implement Showcase.save() to ensure only one default per warehouse
- Add SetDefaultShowcaseView for AJAX-based default selection
- Update ShowcaseForm to include is_default checkbox
- Add interactive checkbox UI in showcase list with AJAX functionality
- Update POS API to return showcase.is_default instead of warehouse.is_default
- Update terminal.js to auto-select showcase based on its is_default flag
- Add migration for is_default field
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented complete web interface for managing showcases (display areas for ready-made bouquets) with:
**Backend:**
- ShowcaseForm with validation (unique name per warehouse)
- ShowcaseListView with filtering by warehouse and status
- ShowcaseCreateView, ShowcaseUpdateView with success messages
- ShowcaseDeleteView with active reservation validation
- URL routes: list, create, edit, delete
**Frontend:**
- List page with warehouse grouping, active reservations count
- Responsive table with filters (warehouse, status)
- Create/edit form with Bootstrap styling
- Delete confirmation with active reservations check
- Breadcrumb navigation
**Features:**
✅ One warehouse can have multiple showcases (ForeignKey relationship)
✅ Unique showcase names within each warehouse
✅ Display active reservation counts for each showcase
✅ Prevent deletion if showcase has active reservations
✅ Auto-select default warehouse when creating showcase
✅ Navigation link added to main navbar between "Касса" and "Склад"
✅ Active state highlighting in navigation
**Files created:**
- inventory/forms_showcase.py (ShowcaseForm)
- inventory/views/showcase.py (4 CBV views)
- inventory/templates/inventory/showcase/ (list, form, delete templates)
**Files modified:**
- inventory/urls.py (added showcase routes)
- inventory/forms.py (added Showcase import)
- templates/navbar.html (added "Витрины" link)
URL structure:
/inventory/showcases/ - list
/inventory/showcases/create/ - create
/inventory/showcases/<id>/edit/ - edit
/inventory/showcases/<id>/delete/ - delete
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Реализована трёхуровневая система статусов товаров и комплектов:
- active (Активный) - товар доступен для продажи
- archived (Архивный) - скрыт, можно восстановить в следующем сезоне
- discontinued (Снят) - морально устарел, готов к удалению
Изменения:
1. Модели (BaseProductEntity, Product, ProductKit):
- Заменено поле is_deleted (Boolean) на status (CharField)
- Добавлены архивные метаданные (archived_at, archived_by)
- Обновлены методы: archive(), restore(), discontinue(), delete()
- Уникальное ограничение изменено на conditional (status='active')
2. Менеджеры (ActiveManager, SoftDeleteQuerySet):
- Полиморфная поддержка обеих систем (status и is_active)
- Использует hasattr() для совместимости с наследниками
- Методы: archive(), restore(), discontinue(), archived_only(), active_only()
3. Формы (ProductForm, ProductKitForm):
- Включены поле status в формы
- Валидация уникальности по status='active'
- CSS классы для статус-селектора
4. Admin панель:
- DeletedFilter переименован в StatusFilter с тремя опциями
- get_status_display() с цветным отображением статуса
- Actions: restore_items, hard_delete_selected, delete_selected
- Readonly поля для архивирования
5. Представления:
- ProductListView: фильтр status вместо is_active
- CombinedProductListView: поддержка фильтра status для товаров и комплектов
- API views обновлены для работы со статусом
6. Шаблоны:
- product_form.html: form.status вместо form.is_active
- productkit_create.html: form.status вместо form.is_active
- productkit_edit.html: form.status вместо form.is_active
7. Миграции:
- Удалены все старые миграции (чистый перезапуск по требованию пользователя)
- Создана новая миграция 0001_initial с полной структурой status-системы
- Удален старый код преобразования is_deleted -> status
Проведённые проверки:
- Django system check passed ✓
- Полиморфные менеджеры работают с обеими системами
- Уникальные ограничения корректно работают с условиями
- История заказов сохраняется даже после архивирования товара (django-simple-history)
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
## Changes
### 1. Fixed missing signal handler for Incoming edit (inventory/signals.py)
- Added new signal handler `update_stock_batch_on_incoming_edit()` that:
- Triggers when Incoming is edited (created=False)
- Synchronizes StockBatch with new quantity and cost_price values
- Automatically triggers cost price recalculation for the product
- Updates Stock (inventory balance) for the warehouse
- Includes proper logging and error handling
### 2. Created IncomingModelForm for editing individual incoming items (inventory/forms.py)
- New ModelForm: `IncomingModelForm` that:
- Inherits from forms.ModelForm (accepts 'instance' parameter required by UpdateView)
- Allows editing: product, quantity, cost_price, notes
- Includes validation for positive quantity and non-negative cost_price
- Filters only active products
### 3. Updated IncomingUpdateView (inventory/views/incoming.py)
- Changed form_class from IncomingForm to IncomingModelForm
- Updated imports to include IncomingModelForm
- Removed obsolete comments from form_valid method
## Architecture
When editing an Incoming item:
1. User submits form with new quantity/cost_price
2. form.save() triggers post_save signal (created=False)
3. update_stock_batch_on_incoming_edit() synchronizes StockBatch
4. StockBatch.save() triggers update_product_cost_on_batch_change()
5. Product.cost_price is recalculated with weighted average
## Problem Solved
Previously, editing an Incoming item would NOT:
- Update the related StockBatch
- Recalculate product cost_price
- Update warehouse inventory balance
- Maintain data consistency between Incoming and StockBatch
Now all these operations happen automatically through the signal chain.
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
Исправлены 4 проблемы:
1. Расчёт цены первого товара - улучшена валидация в getProductPrice и calculateFinalPrice
2. Отображение actual_price в Select2 вместо обычной цены
3. Количество по умолчанию = 1 для новых форм компонентов
4. Auto-select текста при клике на поле количества для удобства редактирования
Изменённые файлы:
- products/forms.py: добавлен __init__ в KitItemForm для quantity.initial = 1
- products/templates/includes/select2-product-init.html: обновлена formatSelectResult
- products/templates/productkit_create.html: добавлен focus handler для auto-select
- products/templates/productkit_edit.html: добавлен focus handler для auto-select
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
Основные изменения:
- Создана модель IncomingBatch для группировки товаров по документам
- Каждое поступление (Incoming) связано с одной батчем поступления
- Автоматическое создание StockBatch для каждого товара в приходе
- Реализована система нумерации партий (IN-XXXX-XXXX) с поиском максимума в БД
- Обновлены все представления (views) для работы с новой архитектурой
- Добавлены детальные страницы просмотра партий поступлений
- Обновлены шаблоны для отображения информации о партиях и их товарах
- Исправлена логика сигналов для создания StockBatch при приходе товара
- Обновлены формы для работы с новой структурой IncomingBatch
Архитектура FIFO:
- IncomingBatch: одна партия поступления (номер IN-XXXX-XXXX)
- Incoming: товар в партии поступления
- StockBatch: одна партия товара на складе (создается для каждого товара)
Это позволяет системе правильно применять FIFO при продаже товаров.
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>