feat(quotes,units): official-invoice badge, conversion text wrapping, seeded fixed conversions, universal proforma, EditModal fixes
1) Quote card header: an official/unofficial badge (رسمی / غیررسمی) renders next to the supplier name from quotes.is_official (the «فاکتور رسمی» checkbox) — green for official, muted slate for unofficial. 2) Conversion Factors sidebar: the material group and variant labels no longer truncate with ellipsis — whitespace-normal + break-words so long Persian names wrap cleanly to the next line. 3) Global fixed conversions are now seeded in the unified seeder (app/db/init_db.py — the same file that seeds categories, base units and the superuser path), NOT hardcoded in the frontend: تن→کیلوگرم (1000), کیلوگرم→گرم (1000), هزار عدد→عدد (1000). The supporting units (گرم, هزار عدد) were added to the idempotent BASE_UNITS seed; inserts use ON CONFLICT (from_unit, to_unit) DO NOTHING against the uq_standard_conversion key so every startup is safe. Verified live: 3 rows after first boot AND still 3 rows after an api restart. 4) Universal proforma attachments: the Edit modal now has a پیشفاکتورها section (list/upload/delete via the existing MinIO-backed files API) alongside the invoices section, active at every quote lifecycle stage — including accepted/arrived and receipts-locked quotes (the section is deliberately not gated by hasReceipts; the backend already permits uploads in any status). View/delete of existing proformas unchanged elsewhere. 5) EditModal fixes: (a) the supplier Combobox no longer opens on mount — Radix Dialog autofocus was triggering its onFocus; Combobox gains an openOnFocus prop (default true) and the modal passes false, so the dropdown now opens only on explicit click or typing; (b) the line-item material field binds to the material's own name (m.name) instead of its category relation, and the save path matches materials by name+brand+specs accordingly. Validated: python compile, api + frontend image builds (tsc + vite) clean; seeding verified against the live local DB.
This commit is contained in:
@@ -140,12 +140,26 @@ export function QuoteCard({ store, q, expanded, onToggleExpand, onAccept, onEdit
|
||||
{sup.name.slice(0, 1)}
|
||||
</span>
|
||||
<div className="min-w-0 flex-1">
|
||||
<Link
|
||||
to={`/suppliers/${q.supplier_id}`}
|
||||
className="block truncate text-xs font-bold text-ink no-underline hover:text-accent sm:text-[13.5px]"
|
||||
>
|
||||
{sup.name}
|
||||
</Link>
|
||||
<div className="flex min-w-0 items-center gap-1.5">
|
||||
<Link
|
||||
to={`/suppliers/${q.supplier_id}`}
|
||||
className="min-w-0 flex-1 truncate text-xs font-bold text-ink no-underline hover:text-accent sm:text-[13.5px]"
|
||||
>
|
||||
{sup.name}
|
||||
</Link>
|
||||
{/* فاکتور رسمی / غیررسمی — از چکباکس «فاکتور رسمی» هنگام ثبت پیشنهاد */}
|
||||
<span
|
||||
className={cn(
|
||||
"shrink-0 rounded px-1.5 py-px text-[9.5px] font-bold leading-4",
|
||||
q.is_official
|
||||
? "bg-green-bg text-green"
|
||||
: "bg-slate-bg text-muted",
|
||||
)}
|
||||
title={q.is_official ? "فاکتور رسمی" : "فاکتور غیررسمی"}
|
||||
>
|
||||
{q.is_official ? "رسمی" : "غیررسمی"}
|
||||
</span>
|
||||
</div>
|
||||
{sup.location && <div className="truncate text-[10px] text-muted sm:text-[11px]">{sup.location}</div>}
|
||||
</div>
|
||||
<div className="ms-auto flex shrink-0 items-center gap-1 sm:gap-1.5">
|
||||
|
||||
Reference in New Issue
Block a user