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

# Financial Close Management - Admin Guide

> Version: 1.0.0 Last Updated: 2026-01-19 Module: FA-19 Financial Close Management

**Version:** 1.0.0\
**Last Updated:** 2026-01-19\
**Module:** FA-19 Financial Close Management

***

## Table of Contents

1. [Overview](#overview)
2. [Permission Configuration](#permission-configuration)
3. [Checklist Template Setup](#checklist-template-setup)
4. [Integration Configuration](#integration-configuration)
5. [Event Contracts](#event-contracts)
6. [API Contracts](#api-contracts)
7. [Security Considerations](#security-considerations)
8. [Troubleshooting](#troubleshooting)

***

## Overview

This guide covers the administrative configuration and technical details for the Financial Close Management module (FA-19). It is intended for system administrators, finance managers, and technical staff responsible for setting up and maintaining the close management process.

### Module Architecture

FA-19 consists of four primary database tables:

| Table                    | Purpose                                                |
| ------------------------ | ------------------------------------------------------ |
| `fa_close_periods`       | Close period header records (status, dates, approvals) |
| `fa_close_checklists`    | Checklist templates and period-specific checklists     |
| `fa_close_tasks`         | Individual tasks within checklists                     |
| `fa_close_documentation` | Document attachments for periods and tasks             |

### Key Dependencies

* **FA-02 (General Ledger)**: Fiscal period linking
* **FA-07 (Financial Reporting)**: Close status verification for reports
* **PF-10 (Notifications)**: Task assignments and approval alerts
* **PF-11 (Documents)**: File storage for attachments
* **FW-03 (Approval Workflow)**: Close period approval events

***

## Permission Configuration

### Permission Keys

FA-19 uses the following permission keys for access control:

| Permission Key     | Description                                  | Typical Role               |
| ------------------ | -------------------------------------------- | -------------------------- |
| `fa.close.view`    | View close periods and task status           | All finance staff          |
| `fa.close.create`  | Create new close periods                     | Manager, Org Admin         |
| `fa.close.manage`  | Edit templates, manage tasks, reopen periods | Manager, Org Admin         |
| `fa.close.approve` | Approve or reject close periods              | Controller, CFO, Org Admin |

### Role Assignment Matrix

| Role               | view | create | manage | approve |
| ------------------ | ---- | ------ | ------ | ------- |
| Staff Accountant   | ✅    | ❌      | ❌      | ❌       |
| Senior Accountant  | ✅    | ✅      | ❌      | ❌       |
| Accounting Manager | ✅    | ✅      | ✅      | ❌       |
| Controller         | ✅    | ✅      | ✅      | ✅       |
| CFO                | ✅    | ✅      | ✅      | ✅       |
| Org Admin          | ✅    | ✅      | ✅      | ✅       |

### Configuring Permissions

1. Navigate to **Settings** > **Permissions**
2. Select the role to modify
3. Under **Finance & Accounting** > **Close Management**:
   * Enable/disable each permission as needed
4. Click **Save Changes**

### Permission Check Pattern

In code, use the `useHasPermission` hook:

```typescript theme={null}
import { useHasPermission, PermissionGate } from '@/platform/permissions';

// Hook usage
const canApprove = useHasPermission('fa.close.approve');

// Component usage
<PermissionGate permission="fa.close.approve">
  <Button onClick={handleApprove}>Approve Period</Button>
</PermissionGate>
```

***

## Checklist Template Setup

### Standard Template Structure

Create templates for each close type:

#### Month-End Close Template

```text theme={null}
1. Pre-Close Tasks
   1.1 Review open transactions (Manual, Medium)
   1.2 Process pending journal entries (Manual, High)
   1.3 Complete bank reconciliations (Manual, High)
       └─ Depends on: 1.2

2. Accruals & Adjustments
   2.1 Record accrued expenses (Manual, High)
   2.2 Post prepaid amortization (Manual, Medium)
   2.3 Record depreciation (Automated, Medium)
   2.4 Review accrual entries (Review, High)
       └─ Depends on: 2.1, 2.2, 2.3

3. Reconciliation & Review
   3.1 Reconcile subledgers to GL (Manual, High)
   3.2 Verify intercompany balances (Manual, Medium)
   3.3 Review account reconciliations (Review, High)
       └─ Depends on: 3.1, 3.2

4. Reporting & Finalization
   4.1 Generate trial balance (Manual, Medium)
   4.2 Review financial statements (Review, High)
   4.3 Prepare variance analysis (Manual, Medium)
   4.4 Manager approval (Approval, Critical)
       └─ Depends on: 4.1, 4.2, 4.3
```

#### Quarter-End Close Template

Include all month-end tasks plus:

```text theme={null}
5. Quarter-End Specific
   5.1 Review quarterly accruals (Review, High)
   5.2 Prepare quarterly reports (Manual, High)
   5.3 Review budget vs actual (Review, Medium)
   5.4 Update cash flow forecast (Manual, Medium)
   5.5 Quarter-end approval (Approval, Critical)
```

#### Year-End Close Template

Include all quarter-end tasks plus:

```text theme={null}
6. Year-End Specific
   6.1 Physical inventory count (Manual, Critical)
   6.2 Review fixed asset depreciation (Review, High)
   6.3 Prepare audit schedules (Manual, Critical)
   6.4 Tax provision calculation (Manual, Critical)
   6.5 Year-end adjustments review (Review, Critical)
   6.6 Final audit preparation (Manual, High)
   6.7 CFO year-end approval (Approval, Critical)
```

### Template Management Best Practices

1. **Version Control**: Include version numbers in template names
2. **Annual Review**: Review and update templates annually
3. **Document Changes**: Add notes when updating templates
4. **Test New Templates**: Create a test period before production use

***

## Integration Configuration

### FA-02 (General Ledger) Integration

Close periods can be linked to fiscal periods:

* **Linking**: When creating a close period, select the corresponding fiscal period
* **Status Sync**: Close period status does not automatically update fiscal period
* **Use Case**: Financial reports can verify close period status before generating final statements

### FA-07 (Financial Reporting) Integration

Financial Reporting checks close status:

```typescript theme={null}
// Example: Check if period is closed before final report
const { data: closeStatus } = await supabase
  .from('fa_close_periods')
  .select('status')
  .eq('fiscal_period_id', periodId)
  .single();

if (closeStatus?.status !== 'completed') {
  throw new Error('Period must be closed before generating final reports');
}
```

### PF-10 (Notifications) Integration

Notifications are triggered for:

| Event                   | Recipients                     | Notification Type |
| ----------------------- | ------------------------------ | ----------------- |
| Task Assigned           | Assigned user                  | In-app + email    |
| Period Pending Approval | Users with `fa.close.approve`  | In-app + email    |
| Period Approved         | Period creator, task assignees | In-app            |
| Period Rejected         | Period creator                 | In-app + email    |

### PF-11 (Documents) Integration

Document storage uses the platform document service:

* **Bucket**: `fa-close-documents`
* **Path Pattern**: `{organization_id}/{close_period_id}/{document_id}`
* **Max File Size**: 50MB per document
* **Allowed Types**: PDF, Excel, Word, images

***

## Event Contracts

FA-19 publishes the following events to the `fa_events` channel:

### close\_period\_started

**Trigger**: When close period status changes to 'in\_progress'

```typescript theme={null}
{
  event_type: 'close_period_started';
  close_period_id: uuid;
  period_name: string;
  period_type: 'month' | 'quarter' | 'year';
  started_by: uuid;
  organization_id: uuid;
  timestamp: timestamptz;
}
```

### close\_period\_completed

**Trigger**: When close period status changes to 'completed'

```typescript theme={null}
{
  event_type: 'close_period_completed';
  close_period_id: uuid;
  period_name: string;
  fiscal_period_id: uuid | null;
  completed_by: uuid;
  organization_id: uuid;
  timestamp: timestamptz;
}
```

### close\_period\_approved

**Trigger**: When close period status changes to 'approved'

```typescript theme={null}
{
  event_type: 'close_period_approved';
  close_period_id: uuid;
  period_name: string;
  approved_by: uuid;
  organization_id: uuid;
  timestamp: timestamptz;
}
```

### close\_task\_assigned

**Trigger**: When a task's assigned\_to field changes

```typescript theme={null}
{
  event_type: 'close_task_assigned';
  task_id: uuid;
  task_name: string;
  close_period_id: uuid;
  assigned_to: uuid;
  assigned_by: uuid;
  organization_id: uuid;
  timestamp: timestamptz;
}
```

### close\_task\_completed

**Trigger**: When a task's status changes to 'completed'

```typescript theme={null}
{
  event_type: 'close_task_completed';
  task_id: uuid;
  task_name: string;
  close_period_id: uuid;
  completed_by: uuid;
  organization_id: uuid;
  timestamp: timestamptz;
}
```

### Subscribing to Events

```typescript theme={null}
// Subscribe to close events
const channel = supabase.channel('fa_events');

channel.on('broadcast', { event: 'close_period_approved' }, (payload) => {
  // TODO: Replace with your app's structured logging
  // logger.info('Period approved:', payload);
  // Update UI or trigger downstream actions
});

channel.subscribe();
```

***

## API Contracts

### Close Period Approval API

**Endpoint**: `/api/v1/fa/close/periods/{period_id}/approve`\
**Method**: POST\
**Permission**: `fa.close.approve`

**Request**:

```typescript theme={null}
{
  approved: boolean;
  comments?: string;
}
```

**Response**:

```typescript theme={null}
{
  close_period_id: uuid;
  status: 'approved' | 'rejected';
  approved_at: timestamp;
  approved_by: uuid;
}
```

**Error Codes**:

* `403`: Access denied (no permission or wrong organization)
* `404`: Period not found
* `409`: Invalid status or incomplete tasks

### Close Period Status API

**Endpoint**: `/api/v1/fa/close/periods/{period_id}/status`\
**Method**: GET\
**Permission**: `fa.close.view`

**Response**:

```typescript theme={null}
{
  close_period_id: uuid;
  period_name: string;
  status: CloseStatus;
  task_summary: {
    total: number;
    completed: number;
    skipped: number;
    in_progress: number;
    blocked: number;
    not_started: number;
  };
  completion_percentage: number;
  // ... additional fields
}
```

See [API\_CONTRACTS.md](../architecture/integrations/API_CONTRACTS.md#fa-19-financial-close-management-apis) for complete documentation.

***

## Security Considerations

### Row-Level Security (RLS)

All FA-19 tables have RLS policies:

```sql theme={null}
-- Example: fa_close_periods policy
CREATE POLICY "fa_close_periods_org_read" ON fa_close_periods
FOR SELECT USING (
  fa_has_org_access(organization_id, auth.uid())
);

CREATE POLICY "fa_close_periods_org_write" ON fa_close_periods
FOR ALL USING (
  fa_has_org_access(organization_id, auth.uid())
)
WITH CHECK (
  fa_has_org_access(organization_id, auth.uid())
);
```

### Defense-in-Depth

All mutations include organization\_id validation:

```typescript theme={null}
// Correct pattern
await supabase
  .from('fa_close_periods')
  .update({ status: 'in_progress' })
  .eq('id', periodId)
  .eq('organization_id', currentOrganization.id);  // Always include
```

### Audit Trail

All close management actions are logged:

* Task completion with user and timestamp
* Status changes with actor information
* Document uploads with user and timestamp
* Approval decisions with comments

### Locked Period Protection

Completed/locked periods cannot be modified:

```sql theme={null}
-- Trigger prevents updates to locked periods
CREATE TRIGGER fa_close_periods_lock_check
BEFORE UPDATE ON fa_close_periods
FOR EACH ROW
WHEN (OLD.status IN ('completed', 'locked'))
EXECUTE FUNCTION fa_prevent_locked_period_update();
```

### Task Dependency Validation

Circular dependencies are prevented:

```sql theme={null}
-- Trigger validates task dependencies
CREATE TRIGGER fa_validate_task_dependency
BEFORE INSERT OR UPDATE ON fa_close_tasks
FOR EACH ROW
EXECUTE FUNCTION fa_validate_no_circular_dependency();
```

***

## Troubleshooting

### Common Administrative Issues

#### Users Can't See Close Periods

**Cause**: Missing `fa.close.view` permission

**Solution**:

1. Check user's role assignment
2. Verify role has `fa.close.view` permission
3. Clear browser cache and retry

#### Template Changes Not Reflected

**Cause**: Template changes don't update existing periods

**Solution**:

1. Template changes only affect new periods
2. For existing periods, manually add/update tasks
3. Consider creating a new period with updated template

#### Approval Notification Not Sent

**Cause**: Notification service issue or user preferences

**Solution**:

1. Check notification service logs
2. Verify user has email notifications enabled
3. Check user's notification preferences in profile

#### Period Stuck in "Pending Approval"

**Cause**: No users with `fa.close.approve` permission

**Solution**:

1. Verify users have approval permission
2. Check if approvers are active in the organization
3. Grant approval permission to appropriate user

### Database Queries for Troubleshooting

#### Check Close Period Status

```sql theme={null}
SELECT 
  cp.id,
  cp.period_name,
  cp.status,
  cp.organization_id,
  COUNT(ct.id) as total_tasks,
  COUNT(CASE WHEN ct.status = 'completed' THEN 1 END) as completed_tasks
FROM fa_close_periods cp
LEFT JOIN fa_close_checklists cc ON cc.close_period_id = cp.id
LEFT JOIN fa_close_tasks ct ON ct.checklist_id = cc.id
WHERE cp.id = '<period_id>'
GROUP BY cp.id;
```

#### Find Incomplete Tasks

```sql theme={null}
SELECT 
  ct.id,
  ct.task_name,
  ct.status,
  ct.assigned_to,
  ct.depends_on_task_id
FROM fa_close_tasks ct
JOIN fa_close_checklists cc ON ct.checklist_id = cc.id
WHERE cc.close_period_id = '<period_id>'
  AND ct.status NOT IN ('completed', 'skipped')
ORDER BY ct.display_order;
```

#### Check Event Publishing

```sql theme={null}
-- View recent close events (if logging enabled)
SELECT * FROM pg_stat_activity 
WHERE query LIKE '%pg_notify%fa_events%'
ORDER BY query_start DESC
LIMIT 10;
```

***

## Related Documentation

* [Financial Close Management User Guide](./financial-close-management-guide.md)
* [General Ledger Guide](./general-ledger-guide.md)
* [FA Security Considerations](./FA-SECURITY-CONSIDERATIONS.md)
* [API Contracts](../architecture/integrations/API_CONTRACTS.md#fa-19-financial-close-management-apis)
* [Event Contracts](../architecture/integrations/EVENT_CONTRACTS.md#fa-19-financial-close-management-events)

***

**Document Version:** 1.0.0\
**Last Updated:** 2026-01-19\
**Next Review:** 2026-04-19
