Allow editing orders in the order card
Cashiers can edit recipient, TTN, notes, goods and total in the order
modal and save via PATCH /orders/{id}. Edited orders get edited_at and
are no longer overwritten by CRM sync. Editing is blocked once a receipt
exists; changing the TTN resets Nova Poshta tracking fields.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ integer-kopecks из CLAUDE.md относится к будущим персис
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||
@@ -88,6 +89,7 @@ class OrderRowOut(BaseModel):
|
||||
receipt_status: str | None = None
|
||||
receipt_error: str | None = None
|
||||
receipt_prepayment: str | None = None
|
||||
edited: bool = False
|
||||
|
||||
@classmethod
|
||||
def from_order(cls, order: Order, receipt: Receipt | None = None) -> OrderRowOut:
|
||||
@@ -116,4 +118,43 @@ class OrderRowOut(BaseModel):
|
||||
receipt_prepayment=(
|
||||
f"{receipt.prepayment_kopecks / 100:.2f}" if receipt else None
|
||||
),
|
||||
edited=order.edited_at is not None,
|
||||
)
|
||||
|
||||
|
||||
class OrderGoodIn(BaseModel):
|
||||
"""Позиция заказа из формы редактирования. `amount` считает сервер."""
|
||||
|
||||
id: str | None = Field(default=None, max_length=64)
|
||||
sku: str = Field(default="", max_length=128)
|
||||
name: str = Field(min_length=1, max_length=512)
|
||||
price: Decimal = Field(ge=0, max_digits=12, decimal_places=2)
|
||||
quantity: Decimal = Field(gt=0, max_digits=12, decimal_places=3)
|
||||
discount_amount: Decimal = Field(default=Decimal(0), ge=0, max_digits=12, decimal_places=2)
|
||||
|
||||
@field_validator("sku", "name", mode="after")
|
||||
@classmethod
|
||||
def _strip(cls, value: str) -> str:
|
||||
return value.strip()
|
||||
|
||||
|
||||
class OrderUpdateIn(BaseModel):
|
||||
"""`PATCH /orders/{id}` — полная замена редактируемых полей заказа."""
|
||||
|
||||
recipient_name: str | None = Field(default=None, max_length=255)
|
||||
recipient_phone: str | None = Field(default=None, max_length=32)
|
||||
recipient_email: str | None = Field(default=None, max_length=320)
|
||||
waybill_number: str | None = Field(default=None, max_length=64)
|
||||
notes: str | None = None
|
||||
total_amount: Decimal = Field(ge=0, max_digits=12, decimal_places=2)
|
||||
goods: list[OrderGoodIn] = Field(min_length=1)
|
||||
|
||||
# Пустая строка из формы = «не указано».
|
||||
@field_validator(
|
||||
"recipient_name", "recipient_phone", "recipient_email", "waybill_number", "notes"
|
||||
)
|
||||
@classmethod
|
||||
def _blank_to_none(cls, value: str | None) -> str | None:
|
||||
if value is None:
|
||||
return None
|
||||
return value.strip() or None
|
||||
|
||||
Reference in New Issue
Block a user