# Task 08 — Journal Entries

## Goal
Build the Journal Entries module to create and manage accounting entries with header and lines structure.
This task covers draft journal entries only. Posting and reverse logic will be handled in later tasks.

---

## Database

### Table: `journal_entries`

Fields:
- id
- journal_id (FK to journals.id)
- entry_number (string, unique)
- entry_date (date)
- branch_id (FK to branches.id)
- fiscal_year_id (FK to fiscal_years.id)
- fiscal_period_id (FK to fiscal_periods.id)
- description (text, nullable)
- status (string, default `draft`)
- created_by (nullable, FK to admins.id)
- updated_by (nullable, FK to admins.id)
- created_at
- updated_at

Indexes:
- unique entry_number
- index journal_id
- index branch_id
- index fiscal_year_id
- index fiscal_period_id
- index status
- index entry_date

### Table: `journal_entry_lines`

Fields:
- id
- journal_entry_id (FK to journal_entries.id)
- account_id (FK to accounts.id)
- cost_center_id (nullable, FK to cost_centers.id)
- description (text, nullable)
- debit (decimal 18,2 default 0)
- credit (decimal 18,2 default 0)
- currency_code (string nullable)
- exchange_rate (decimal 18,6 nullable)
- created_at
- updated_at

Indexes:
- index journal_entry_id
- index account_id
- index cost_center_id

---

## Relations

### JournalEntry model relations
- journal() -> belongsTo Journal
- branch() -> belongsTo Branch
- fiscalYear() -> belongsTo FiscalYear
- fiscalPeriod() -> belongsTo FiscalPeriod
- lines() -> hasMany JournalEntryLine
- creator() -> belongsTo Admin
- updater() -> belongsTo Admin

### JournalEntryLine model relations
- entry() -> belongsTo JournalEntry
- account() -> belongsTo Account
- costCenter() -> belongsTo CostCenter

---

## Business Rules

1. Journal entry starts as `draft` only in this task.
2. `entry_number` should be generated using NumberSequenceService.
3. Each entry belongs to one journal, one branch, one fiscal year, and one fiscal period.
4. A journal entry can have multiple lines.
5. At least one line must exist.
6. Each line must contain either debit or credit.
7. No posting logic in this task.
8. No reverse logic in this task.
9. Period must exist, but open/closed validation can be basic now; strict posting validation will come later.

---

## Files

### Models
- app/Models/Finance/JournalEntry.php
- app/Models/Finance/JournalEntryLine.php

### Services
- app/Services/Finance/JournalEntryService.php

### Controllers
- app/Http/Controllers/Admin/Finance/JournalEntryController.php

### Requests
- app/Http/Requests/Admin/Finance/StoreJournalEntryRequest.php
- app/Http/Requests/Admin/Finance/UpdateJournalEntryRequest.php

### Views
- resources/views/dashboard/finance/journal_entries/index.blade.php
- resources/views/dashboard/finance/journal_entries/create.blade.php
- resources/views/dashboard/finance/journal_entries/edit.blade.php
- resources/views/dashboard/finance/journal_entries/show.blade.php

### Lang files
- lang/ar/finance.php
- lang/en/finance.php

---

## Permissions

- finance.entries.view
- finance.entries.create
- finance.entries.update
- finance.entries.delete

---

## Validation Rules

### Header
- journal_id: required, exists:journals,id
- entry_date: required, date
- branch_id: required, exists:branches,id
- fiscal_year_id: required, exists:fiscal_years,id
- fiscal_period_id: required, exists:fiscal_periods,id
- description: nullable, string

### Lines
- lines: required, array, min:1
- lines.*.account_id: required, exists:accounts,id
- lines.*.cost_center_id: nullable, exists:cost_centers,id
- lines.*.description: nullable, string
- lines.*.debit: nullable, numeric, min:0
- lines.*.credit: nullable, numeric, min:0
- lines.*.currency_code: nullable, string
- lines.*.exchange_rate: nullable, numeric, min:0

Validation note:
- each line must not have both debit and credit as zero
- line should not have both debit and credit with positive values at the same time

---

## UI

Views path:
`resources/views/dashboard/finance/journal_entries/`

### Header fields
- journal
- entry_date
- branch
- fiscal_year
- fiscal_period
- description

### Line fields
- account
- cost_center
- description
- debit
- credit
- currency_code
- exchange_rate

### Index columns
- entry_number
- date
- journal
- branch
- status
- actions

---

## Lang Keys

Suggested keys:
- journal_entries
- journal_entry
- create_journal_entry
- edit_journal_entry
- entry_number
- entry_date
- journal
- branch
- fiscal_year
- fiscal_period
- lines
- account
- cost_center
- debit
- credit
- status
- draft

---

## Seeder

Update RolePermissionSeeder with:
- finance.entries.view
- finance.entries.create
- finance.entries.update
- finance.entries.delete

---

## Steps

### Step 1
Create migration for `journal_entries` table.

### Step 2
Create migration for `journal_entry_lines` table.

### Step 3
Create `JournalEntry` and `JournalEntryLine` models.

### Step 4
Create `JournalEntryService`.

### Step 5
Create Form Requests.

### Step 6
Create `JournalEntryController`.

### Step 7
Create routes in `routes/admin.php`.

### Step 8
Create views.

### Step 9
Update `RolePermissionSeeder`.

### Step 10
Update lang files.

---

## Notes for AI

- Follow docs/ai/AI_MASTER_PROJECT.md
- Follow docs/ai/ARCHITECTURE_RULES.md
- Follow docs/ai/DATABASE_SCHEMA.md
- Follow docs/ai/MODULE_STRUCTURE.md
- Execute one step at a time
- Do not modify unrelated files
- Do not generate posting logic in this task
- Do not generate tests in this task
- Wait for confirmation after each step

