Merge prod_v5 (catalog v2.7, warehouse locking, per-project accept) into integration
Conflict in init_db.py resolved keeping the audit_log table ensure function (new-one) — prod_v5 predates it and its side was empty. Both sides' SQL lands: audit_log table plus the category-free materials model.
This commit is contained in:
@@ -88,6 +88,7 @@ export function EditModal({ quoteId, onClose }: EditModalProps) {
|
||||
const [selectedProjects, setSelectedProjects] = useState<string[]>([]);
|
||||
const [notes, setNotes] = useState("");
|
||||
const [invoices, setInvoices] = useState<Attachment[]>([]);
|
||||
const [proformas, setProformas] = useState<Attachment[]>([]);
|
||||
const [itemRows, setItemRows] = useState<EditItemRow[]>([]);
|
||||
const [tsCards, setTsCards] = useState<EditTsCard[]>([]);
|
||||
const [quoteDate, setQuoteDate] = useState<string | null>(null);
|
||||
@@ -168,7 +169,7 @@ export function EditModal({ quoteId, onClose }: EditModalProps) {
|
||||
key: li.id,
|
||||
origLi: li,
|
||||
projects: li.projects && li.projects.length ? [...li.projects] : [],
|
||||
cat: m.category || "",
|
||||
cat: m.name || "", // نام خود متریال — نه دسته/برند
|
||||
brand: m.brand || "",
|
||||
specs: materialSpecs(m),
|
||||
qty: li.quantity,
|
||||
@@ -197,7 +198,7 @@ export function EditModal({ quoteId, onClose }: EditModalProps) {
|
||||
setReady(true);
|
||||
}, [q, suppliers, materials]);
|
||||
|
||||
// بارگذاری فاکتورها
|
||||
// بارگذاری فاکتورها و پیشفاکتورها
|
||||
useEffect(() => {
|
||||
if (!quoteId) return;
|
||||
let alive = true;
|
||||
@@ -205,6 +206,10 @@ export function EditModal({ quoteId, onClose }: EditModalProps) {
|
||||
.list(quoteId, "invoice")
|
||||
.then((list) => alive && setInvoices(list))
|
||||
.catch(() => alive && setInvoices([]));
|
||||
void api.files
|
||||
.list(quoteId, "proforma")
|
||||
.then((list) => alive && setProformas(list))
|
||||
.catch(() => alive && setProformas([]));
|
||||
return () => {
|
||||
alive = false;
|
||||
};
|
||||
@@ -314,7 +319,7 @@ export function EditModal({ quoteId, onClose }: EditModalProps) {
|
||||
|
||||
let material = materialsCopy.find(
|
||||
(m) =>
|
||||
normalize(m.category) === normalize(cat) &&
|
||||
normalize(m.name) === normalize(cat) &&
|
||||
normalize(m.brand) === normalize(brand) &&
|
||||
specsKey(m.specs) === specsKey(specs),
|
||||
);
|
||||
@@ -460,6 +465,7 @@ export function EditModal({ quoteId, onClose }: EditModalProps) {
|
||||
addSuffix="به عنوان تأمینکنندهٔ جدید"
|
||||
placeholder="نام تأمینکننده"
|
||||
onInputChange={(v) => setSupplierName(v)}
|
||||
openOnFocus={false}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -724,6 +730,23 @@ export function EditModal({ quoteId, onClose }: EditModalProps) {
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* پیشفاکتورها — در تمامی مراحل چرخه عمر پیشنهاد قابل افزودن/ویرایش است */}
|
||||
<div className="border-t border-line pt-3">
|
||||
<div className="mb-1 text-[13px] font-bold">پیشفاکتورها (چند فایل):</div>
|
||||
<FileList
|
||||
files={proformas}
|
||||
onChange={setProformas}
|
||||
upload={(f) => api.files.upload(q.id, "proforma", f)}
|
||||
onDelete={(a) =>
|
||||
a.id &&
|
||||
void api.files.remove(q.id, "proforma", a.id).catch((err) =>
|
||||
toast.error(err instanceof Error ? err.message : "حذف پیشفاکتور ناموفق بود"),
|
||||
)
|
||||
}
|
||||
urlOf={(a) => (a.id ? api.files.downloadUrl(q.id, "proforma", a.id) : null)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* تاریخها و وضعیت */}
|
||||
<div className="border-t border-line pt-3">
|
||||
<div className="mb-2 text-[12px] font-bold text-muted">تاریخها و وضعیت:</div>
|
||||
|
||||
Reference in New Issue
Block a user