"""工作区只使用成功完整读取发布的当前源快照。""" from sqlalchemy import select from app.models import TPlusSourceHead, TPlusSyncBatch, TPlusSyncRecord from app.services.tplus.workbench import WorkbenchError def published_batch(session, source, entity): """返回实体最后发布的完整批次;更新失败时不使用不完整的指针。""" batches = session.scalars( select(TPlusSyncBatch) .where( TPlusSyncBatch.source_database == source, TPlusSyncBatch.sync_mode == "FULL", ) .order_by(TPlusSyncBatch.id.desc()) ) batch_no = None for batch in batches: report = batch.audit_result_json or {} if entity in (batch.entity_types_json or []) and batch.status != "SUCCEEDED": raise WorkbenchError("SOURCE_REFRESH_REQUIRED") if entity in report.get("observed_entities", []): batch_no = batch.batch_no break if batch_no is None: raise WorkbenchError("SOURCE_REFRESH_REQUIRED") return batch_no def source_manifest(session, source): """核算与接入共同使用的完整来源批次清单,包含空实体。""" entities = ("personnel", "customers", "products", "businesses", "business_items", "shipments", "shipment_items", "receipts") return {entity: published_batch(session, source, entity) for entity in entities} def source_statement(session, source, entity): """只发布最后一次完整成功读取;中断覆盖的指针不得部分发布。""" batch_no = published_batch(session, source, entity) return ( select(TPlusSyncRecord) .join(TPlusSourceHead, TPlusSourceHead.record_id == TPlusSyncRecord.id) .where( TPlusSourceHead.source_database == source, TPlusSourceHead.entity_type == entity, TPlusSourceHead.batch_no == batch_no, ) ) def source_records(session, source, entity, ids=None, parent_ids=None): """旧暂存未建立当前指针时要求重新读取,禁止 max(record.id) 猜最新值。""" if ids == [] or parent_ids == []: return [] statement = source_statement(session, source, entity) if ids: statement = statement.where(TPlusSourceHead.source_id.in_(ids)) if parent_ids is not None: statement = statement.where( TPlusSyncRecord.payload_json["source_parent_id"] .as_integer() .in_([int(v) for v in parent_ids]) ) return list(session.scalars(statement.order_by(TPlusSyncRecord.source_id)))