> ## Documentation Index
> Fetch the complete documentation index at: https://cona.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Document Connection - Parent-Child Model

> Understanding the hierarchical document relationship system in CONA

# Document Connection - Parent-Child Model

## Overview

CONA uses a hierarchical parent-child relationship model for connecting documents, moving away from bidirectional "to/from" connections to create clearer document hierarchies. This approach provides better organization around primary documents (like sales orders) while avoiding complex interconnected networks.

## Key Concepts

### Parent-Child Hierarchy

* **One child can have many parents** - A document can be related to multiple parent documents
* **One parent can have many children** - A parent document can have multiple child documents
* **No "cousins" or "partners"** - Documents are only connected through direct parent-child relationships
* **Clear hierarchy** - Usually revolves around a primary document like a sales order

### Typical Document Hierarchy

```
Sales Order (Parent)
├── Sales Invoice (Child)
├── Credit Note (Child)
└── Payment (Child)
```

## Implementation

### Database Schema

The `document_relations` table uses:

* `parent_document_id` - References the parent document
* `child_document_id` - References the child document
* Unique constraint on `(parent_document_id, child_document_id)` to prevent duplicates

### Core Functions

#### `connectDocuments()`

Creates parent-child relationships between documents.

```typescript theme={null}
import { connectDocuments } from "@cona/core";

const result = await connectDocuments({
  parentDocumentId: "sales_order_123",
  childDocumentIds: ["invoice_456", "credit_note_789"],
  organizationId: "org_123",
});
```

#### `batchConnectDocuments()`

Efficiently creates multiple parent-child relationships in a single transaction.

```typescript theme={null}
import { batchConnectDocuments } from "@cona/core";

const result = await batchConnectDocuments({
  organizationId: "org_123",
  documentRelations: [
    { parentDocumentId: "order_1", childDocumentId: "invoice_1" },
    { parentDocumentId: "order_1", childDocumentId: "payment_1" },
    { parentDocumentId: "order_2", childDocumentId: "invoice_2" },
  ],
});
```

### Usage in Integrations

#### Shopify Integration

* **Sales Order** → Parent document
* **Sales Invoice** → Child of sales order
* **Credit Note** → Child of both sales order and sales invoice

#### Reconciliation

**Parent Priority Order:**

1. **Inherited Parents** → If any document already has a parent, all documents inherit that parent
2. **Sales Invoice** → Becomes parent when available and no existing parents
3. **Fallback** → First document becomes parent if no invoice or existing parents

**Examples:**

* Payment reconciles with Invoice (Invoice has Sales Order parent) → Payment inherits Sales Order as parent
* Payment reconciles with standalone Invoice → Invoice becomes parent of Payment
* Payment reconciles with Credit Note → First document becomes parent

## Benefits

1. **Clear Hierarchy** - Easy to understand document relationships
2. **Scalable** - Avoids complex interconnected networks
3. **Flexible** - Supports multiple parents per child when needed
4. **Organized** - Centers around primary business documents
5. **Efficient** - Simpler queries for finding related documents

## Querying Related Documents

### Find Children of a Parent

```typescript theme={null}
const children = await prisma.document_relations.findMany({
  where: { parent_document_id: parentId },
  include: { child_document: true },
});
```

### Find Parents of a Child

```typescript theme={null}
const parents = await prisma.document_relations.findMany({
  where: { child_document_id: childId },
  include: { parent_document: true },
});
```

### Find Siblings (same parent)

```typescript theme={null}
const siblings = await prisma.document_relations.findMany({
  where: {
    parent_document_id: {
      in: await prisma.document_relations
        .findMany({
          where: { child_document_id: documentId },
          select: { parent_document_id: true },
        })
        .then((results) => results.map((r) => r.parent_document_id)),
    },
    child_document_id: { not: documentId },
  },
  include: { child_document: true },
});
```
