drawings: on a rev mismatch, Clerical can keep the retired rev VISUAL calls (#41)
When VISUAL calls a rev that M-Files has retired, the draft is still flagged rev_mismatch, but the drawing job now also copies the rev VISUAL calls (MFilesKit 0.1.3 DrawingLookup.revision) into drawing_revisions and visual.called. A Clerical Supervisor picks either rev on the packet: "Use latest rev N" as before, or "Use rev V as VISUAL calls it" (rev-approve with use=called), with a reason and a signature. The kept rev holds while M-Files' Effective rev stays the one chosen against: no flag, no change order. A newer Effective rev flags the packet again; a new VISUAL rev clears the choice. Migration 0009 adds drawing_revisions. Needs mfileskit 0.1.3. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
"""Copy a released drawing PDF from M-Files into assets.
|
||||
|
||||
Downloads only when the M-Files identity (object id and version, file id and version) differs from what the
|
||||
`drawing_lookups` row last stored, or that row has no asset (or the asset's file is gone). The download goes to
|
||||
`drawing_lookups` row last stored (the `drawing_revisions` row for a `Lookup.revision` result), or that row has no
|
||||
asset (or the asset's file is gone). The download goes to
|
||||
ASSETS_DIR/tmp/<uuid>; the PDF magic and the size limit are checked, then `assets.store_file` hashes it in chunks,
|
||||
fsyncs and renames it into place, and reuses an existing asset row with the same sha256 and size.
|
||||
|
||||
@@ -39,14 +40,19 @@ class FetchResult:
|
||||
reused: bool = False # downloaded, but the same bytes were already stored
|
||||
|
||||
|
||||
_CURRENT_SQL = (
|
||||
"SELECT l.obj_id, l.obj_version, l.file_id, l.file_version, l.asset_id, a.sha256, a.pages,"
|
||||
" a.storage_key, a.original_name FROM {table} l LEFT JOIN assets a ON a.id = l.asset_id"
|
||||
)
|
||||
|
||||
|
||||
def _current(conn: Any, settings: Any, found: Found, dwg: str) -> FetchResult | None:
|
||||
with conn.cursor(row_factory=dict_row) as cur:
|
||||
row = cur.execute(
|
||||
"SELECT l.obj_id, l.obj_version, l.file_id, l.file_version, l.asset_id, a.sha256, a.pages,"
|
||||
" a.storage_key, a.original_name FROM drawing_lookups l LEFT JOIN assets a ON a.id = l.asset_id"
|
||||
" WHERE l.dwg = %s",
|
||||
(dwg,),
|
||||
).fetchone()
|
||||
if found.controlled:
|
||||
sql = _CURRENT_SQL.format(table="drawing_revisions") + " WHERE l.dwg = %s AND l.rev = %s"
|
||||
row = cur.execute(sql, (dwg, found.rev)).fetchone()
|
||||
else:
|
||||
row = cur.execute(_CURRENT_SQL.format(table="drawing_lookups") + " WHERE l.dwg = %s", (dwg,)).fetchone()
|
||||
if row is None or row["asset_id"] is None or row["sha256"] is None:
|
||||
return None
|
||||
if (row["obj_id"], row["obj_version"], row["file_id"], row["file_version"]) != found.identity:
|
||||
@@ -68,7 +74,7 @@ def _current(conn: Any, settings: Any, found: Found, dwg: str) -> FetchResult |
|
||||
|
||||
|
||||
def fetch(conn: Any, settings: Any, lookup: Lookup, found: Found, *, dwg: str) -> FetchResult:
|
||||
"""The asset for M-Files' released file of `dwg`. Raises FetchError."""
|
||||
"""The asset for M-Files' released file of `dwg` (or the rev a `Lookup.revision` found). Raises FetchError."""
|
||||
if not found.ok or found.rev is None:
|
||||
raise FetchError(f"{dwg}: no released file in M-Files")
|
||||
cur = _current(conn, settings, found, dwg)
|
||||
@@ -105,6 +111,7 @@ def fetch(conn: Any, settings: Any, lookup: Lookup, found: Found, *, dwg: str) -
|
||||
"file_id": found.file_id,
|
||||
"file_version": found.file_version,
|
||||
"rev": found.rev,
|
||||
**({"controlled": found.controlled} if found.controlled else {}),
|
||||
}
|
||||
try:
|
||||
row = assets.store_file(
|
||||
|
||||
Reference in New Issue
Block a user