Back to ER Diagram
Document Flow

Document Flow Logic

Document lifecycle management — Upload → Review → Transmittal → RFI → Archive

PostgreSQL
10 Tables
Schema: document
Revision Tracking

Overview

InfraTraq implements a comprehensive Document Flow & Control system managing the full document lifecycle: Upload → Review → Revision → Transmittal → Archive. The module handles drawings, specifications, RFIs, submittals, and correspondence with rigorous revision control using standardised review codes (A-Approved, B-Approved with Comments, C-Revise & Resubmit, D-Rejected).


Upload

Review

Revision

Transmittal

Distribution

Archive
6
Lifecycle Stages
10
Document Tables
4
Review Codes
Full
Revision Control

Status States

StatusDescriptionAllowed ActionsNext States
DraftDocument created with metadata, not yet submitted for reviewEdit, Upload File, Submit for Review, DeleteUnder Review
Under ReviewDocument submitted to internal reviewers awaiting response codesReview (A/B/C/D), Add CommentsApproved, Revision Required
ApprovedAll reviewers responded Code A or B — document acceptedCreate Transmittal, Distribute, ArchiveTransmitted, Distributed
Revision RequiredReview Code C or D received — author must revise and resubmitCreate New Revision, EditDraft (new revision)
TransmittedDocument included in a transmittal package sent externallyTrack Client Response, ViewClient Reviewed
Client ReviewedClient response received with review codeAccept, Create RevisionApproved, Revision Required
DistributedApproved document distributed to project team membersView, Track Distribution, ArchiveArchived
ArchivedDocument moved to long-term archive with full history preservedView, Audit
SupersededReplaced by a newer revision — read-only historical recordView, Audit

Review Codes

Code A — Approved

Document accepted, no changes required — proceed to distribution.

Code B — Approved with Comments

Accepted with minor comments — incorporate in next revision.

Code C — Revise & Resubmit

Significant issues found — revise and resubmit for review.

Code D — Rejected

Document does not meet requirements — major rework required.

Process Flow

Main Document Flow

Document
Created

Internal
Review

Client
Submission

Client
Review
Client Response

Code A / B
Approved

Response
A / B / C / D

Code C / D
Revise & Resubmit

Distribution
to Teams

Archive
Long-term
RFI Lifecycle

Raised

Assigned

Response

Closed

Database Schema

document.document_master

  • doc_id — PK, master register of all project documents
  • project_id — FK → project.project
  • doc_number, doc_title, doc_type
  • discipline — Civil, Structural, MEP, etc.
  • current_revision, status

document.document_revision

  • revision_id — PK, revision history with file references
  • doc_id — FK → document.document_master
  • revision_code — 00, 01, 02... then A, B, C...
  • file_url, review_status

document.document_review

  • review_id — PK, individual reviewer responses
  • doc_id — FK → document.document_master
  • reviewer_id — FK → auth.user
  • review_status, review_code (A/B/C/D), comments

document.transmittal

  • transmittal_id — PK, document packages sent between organisations
  • project_id — FK → project.project
  • transmittal_number, from_org, to_org
  • purpose, status

document.transmittal_item

  • id — PK, line items linking documents to transmittals
  • transmittal_id — FK → document.transmittal
  • doc_id — FK → document.document_master
  • revision_code

document.rfi

  • rfi_id — PK, Request for Information lifecycle tracking
  • project_id — FK → project.project
  • rfi_number, subject
  • raised_by — FK → auth.user
  • assigned_to — FK → auth.user
  • status, due_date

document.submittal

  • submittal_id — PK, submittal packages for material/method approval
  • project_id — FK → project.project
  • submittal_number, submittal_type
  • review_status

document.submittal_item

  • id — PK, line items linking documents to submittals
  • submittal_id — FK → document.submittal
  • doc_id — FK → document.document_master

document.drawing_register

  • id — PK, discipline-wise drawing register
  • project_id — FK → project.project
  • drawing_number, discipline
  • current_revision, status

document.distribution

  • id — PK, distribution log for compliance tracking
  • doc_id — FK → document.document_master
  • revision_code
  • recipient_id — FK → auth.user
  • distributed_at

Step-by-Step Logic

1

Document Creation with Metadata

Author creates a document_master record with document number, title, type (Drawing / Specification / Report / Letter), and discipline (Civil, Structural, MEP, etc.). File is uploaded to storage and linked via document_revision with initial revision code 00.

2

Internal Review Cycle

Document is submitted for internal review. document_review records are created for each assigned reviewer. Reviewers provide a review code (A/B/C/D) and comments. All reviews must be completed before the document proceeds. If any Code C or D is received, the document returns to the author for revision.

3

Revision Management

When revisions are needed, a new document_revision record is created with an incremented revision code (00 → 01 → 02 for preliminary, then A → B → C for issued-for-construction). The previous revision is auto-marked as superseded. The document_master.current_revision is updated to the latest.

4

Transmittal Preparation & Sending

Approved documents are packaged into a transmittal for external distribution. Each transmittal gets a unique number, lists from/to organisations, and includes one or more transmittal_item records linking specific documents at specific revisions. The transmittal is sent and tracked.

5

Client Review Tracking

After transmittal, the system tracks client review status. Each document awaits a response code (A/B/C/D). Response due dates are monitored and overdue items are escalated. Client comments are recorded against the document_review for audit trail.

6

RFI Lifecycle

Requests for Information are raised via rfi with a subject, due date, and assigned respondent. The RFI moves through Raised → Assigned → Response → Closed. Overdue RFIs trigger escalation to the Project Manager. Responses may reference document revisions.

7

Submittal Process

Material and method submittals are managed via submittal records. Each submittal has a type (Material / Shop Drawing / Method Statement), linked documents, and goes through the same A/B/C/D review code cycle. Approved submittals release materials or methods for construction use.

8

Document Distribution & Archival

Approved documents are distributed to project team members based on discipline and role. Distribution is logged for compliance. Upon project completion or document obsolescence, documents are moved to the archive with full revision history, review trail, and transmittal records preserved for long-term retention.

Code Implementation

class DocumentService {

  /** Create a new document with metadata and initial file upload */
  async createDocument(projectId, metadata, file) {
    const docNumber = await this.generateDocNumber(projectId, metadata.discipline);
    const fileUrl = await StorageService.upload(file, 'documents');
    const doc = await DocumentMaster.create({
      project_id: projectId, doc_number: docNumber,
      doc_title: metadata.title, doc_type: metadata.type,
      discipline: metadata.discipline, current_revision: '00',
      status: 'draft'
    });
    await DocumentRevision.create({
      doc_id: doc.doc_id, revision_code: '00',
      file_url: fileUrl, review_status: 'pending'
    });
    return doc;
  }

  /** Submit document for internal review by assigned reviewers */
  async submitForReview(docId, reviewerIds) {
    const doc = await DocumentMaster.findById(docId);
    await doc.update({ status: 'under_review' });
    const reviews = reviewerIds.map(rid => ({
      doc_id: docId, reviewer_id: rid,
      review_status: 'pending', review_code: null, comments: null
    }));
    await DocumentReview.bulkCreate(reviews);
    await NotificationService.notify(reviewerIds, 'Document review assigned', doc);
    return reviews;
  }

  /** Process a reviewer's response with review code (A/B/C/D) */
  async processReviewResponse(reviewId, code, comments) {
    await DocumentReview.update(reviewId, {
      review_code: code, comments, review_status: 'completed'
    });
    const review = await DocumentReview.findById(reviewId);
    const allReviews = await DocumentReview.findAll({ doc_id: review.doc_id });
    const allCompleted = allReviews.every(r => r.review_status === 'completed');
    if (allCompleted) {
      const hasReject = allReviews.some(r => ['C', 'D'].includes(r.review_code));
      if (hasReject) {
        await DocumentMaster.update(review.doc_id, { status: 'revision_required' });
        await TaskService.createRevisionTask(review.doc_id);
      } else {
        await DocumentMaster.update(review.doc_id, { status: 'approved' });
      }
    }
  }

  /** Create a new revision of an existing document */
  async createRevision(docId, file, description) {
    const doc = await DocumentMaster.findById(docId);
    const newCode = this.nextRevisionCode(doc.current_revision);
    const fileUrl = await StorageService.upload(file, 'documents');
    // Supersede previous revision
    await DocumentRevision.update(
      { doc_id: docId, revision_code: doc.current_revision },
      { review_status: 'superseded' }
    );
    const revision = await DocumentRevision.create({
      doc_id: docId, revision_code: newCode,
      file_url: fileUrl, review_status: 'pending'
    });
    await doc.update({ current_revision: newCode, status: 'draft' });
    return revision;
  }

  /** Create a transmittal package for external distribution */
  async createTransmittal(projectId, docIds, toOrg) {
    if (!docIds || docIds.length === 0) {
      throw new ValidationError('Transmittal must include at least one document');
    }
    const transNumber = await this.generateTransmittalNumber(projectId);
    const transmittal = await Transmittal.create({
      project_id: projectId, transmittal_number: transNumber,
      from_org: await ProjectService.getOrg(projectId),
      to_org: toOrg, purpose: 'For Review', status: 'issued'
    });
    for (const docId of docIds) {
      const doc = await DocumentMaster.findById(docId);
      await TransmittalItem.create({
        transmittal_id: transmittal.transmittal_id,
        doc_id: docId, revision_code: doc.current_revision
      });
    }
    await NotificationService.notifyOrg(toOrg, 'Transmittal received', transmittal);
    return transmittal;
  }

  /** Raise a Request for Information */
  async createRFI(projectId, subject, assignedTo) {
    const rfiNumber = await this.generateRFINumber(projectId);
    const rfi = await RFI.create({
      project_id: projectId, rfi_number: rfiNumber,
      subject, raised_by: AuthService.currentUserId(),
      assigned_to: assignedTo, status: 'raised',
      due_date: DateUtil.addBusinessDays(new Date(), 7)
    });
    await NotificationService.notify([assignedTo], 'New RFI assigned', rfi);
    return rfi;
  }

  /** Create a submittal package for material/method approval */
  async createSubmittal(projectId, type, docIds) {
    const submittalNumber = await this.generateSubmittalNumber(projectId);
    const submittal = await Submittal.create({
      project_id: projectId, submittal_number: submittalNumber,
      submittal_type: type, review_status: 'pending'
    });
    for (const docId of docIds) {
      await SubmittalItem.create({ submittal_id: submittal.submittal_id, doc_id: docId });
    }
    return submittal;
  }

  /** Distribute an approved document to specified recipients */
  async distributeDocument(docId, recipientIds) {
    const doc = await DocumentMaster.findById(docId);
    if (doc.status !== 'approved') {
      throw new ValidationError('Only approved documents can be distributed');
    }
    for (const recipientId of recipientIds) {
      await DocumentDistribution.create({
        doc_id: docId, revision_code: doc.current_revision,
        recipient_id: recipientId, distributed_at: new Date()
      });
    }
    await NotificationService.notify(recipientIds, 'Document distributed', doc);
    return { doc_id: docId, distributed_to: recipientIds.length };
  }
}

Validation Rules

RuleConditionAction
Unique Document Numberdoc_number must be unique per discipline within a projectBlock creation, suggest next available number
Revision SequenceRevision codes must follow sequence: 00, 01, 02... then A, B, C...Auto-generate next code, reject out-of-order submissions
Transmittal MinimumTransmittal must include at least one documentBlock creation if document list is empty
RFI Due Date RequiredEvery RFI must have a due date assignedDefault to 7 business days if not specified
Superseded Auto-ArchivePrevious revision exists when new revision is uploadedAuto-mark previous revision as superseded
File Size LimitsFile exceeds maximum size per document typeBlock upload; Drawings: 100MB, Specs: 50MB, Letters: 20MB
Naming ConventionDocument number must match project naming templateValidate against regex pattern per project; reject non-conforming

Automated Actions & Triggers

EventSource TableAuto Action
Review Completed (Code A)document.document_reviewUpdate document status to Approved
Review Code C or Ddocument.document_reviewCreate revision task assigned to document author
Transmittal Sentdocument.transmittalNotify recipient organisation and log distribution
RFI Overduedocument.rfiEscalate to Project Manager + send reminder to assignee
New Revision Uploadeddocument.document_revisionSupersede previous revision and update master record
Submittal Approveddocument.submittalRelease material/method for construction, notify site team

Integration Points

Upstream (Data Sources)

  • BIM Model — BIM deliverables generate drawing and model documents
  • Change Orders — Change orders trigger revised drawings and specifications
  • QMS / ITP — Inspection & Test Plans generate QMS document submittals

Downstream (Consumers)

  • Project Team — Approved documents distributed to discipline teams
  • Contract — Correspondence and transmittals link to contract records
  • Audit — Document compliance tracked for quality and regulatory audits
  • Archive — Long-term document retention with full revision history

Best Practices

Implementation Guidelines

  • Enforce consistent document numbering conventions per project using configurable templates (e.g., PRJ-DIS-TYPE-NNNN)
  • Define review turnaround SLAs: internal reviews within 3 business days, client reviews within 10 business days
  • Track all transmittals with acknowledgement receipts — escalate unacknowledged transmittals after 48 hours
  • Monitor RFI response time metrics: target < 7 days, escalate at 5 days, report ageing weekly to PM
  • Maintain strict version control discipline: never overwrite files, always create new revisions, auto-supersede old versions
  • Index document_master on (project_id, discipline, status) and rfi on (project_id, status, due_date) for fast queries

Common Pitfalls

  • Distributing superseded revisions — always verify current_revision before distribution
  • Missing transmittal acknowledgement tracking — leads to disputes over document receipt
  • Allowing informal document exchange outside the transmittal system — breaks audit trail
  • Not closing RFIs promptly after response — inflates open RFI counts and masks real issues