Skip to content

ahgGrapPlugin - Technical Documentation

Version: 1.0.0
Category: Financial/Compliance
Dependencies: atom-framework


Overview

GRAP 103 (Generally Recognised Accounting Practice) heritage asset accounting module for South African public sector compliance. Supports asset recognition, valuation, depreciation tracking, and financial reporting.


Database Schema

ERD Diagram

┌─────────────────────────────────────────┐
│          grap_heritage_asset            │
├─────────────────────────────────────────┤
│ PK id INT                              │
│ FK information_object_id INT UNIQUE    │──────┐
│                                         │      │
│ -- RECOGNITION --                       │      │
│    recognition_status ENUM              │      │
│    recognition_status_reason VARCHAR    │      │
│    recognition_date DATE                │      │
│    measurement_basis ENUM               │      │
│                                         │      │
│ -- ACQUISITION --                       │      │
│    acquisition_method ENUM              │      │
│    acquisition_date DATE                │      │
│    cost_of_acquisition DECIMAL(15,2)    │      │
│    fair_value_at_acquisition DECIMAL    │      │
│    nominal_value DECIMAL(15,2)          │      │
│    donor_name VARCHAR                   │      │
│    donor_restrictions TEXT              │      │
│                                         │      │
│ -- CARRYING AMOUNT --                   │      │
│    current_carrying_amount DECIMAL      │      │
│    accumulated_impairment DECIMAL       │      │
│    last_valuation_date DATE             │      │
│    last_valuation_amount DECIMAL        │      │
│    valuation_method ENUM                │      │
│    valuer_name VARCHAR                  │      │
│    valuer_qualifications VARCHAR        │      │
│    next_valuation_due DATE              │      │
│                                         │      │
│ -- ASSET CLASS --                       │      │
│    asset_class ENUM                     │      │
│    asset_subclass VARCHAR               │      │
│    is_collection TINYINT                │      │
│    collection_id INT                    │      │
│                                         │      │
│ -- INSURANCE --                         │      │
│    insured_value DECIMAL                │      │
│    insurance_policy VARCHAR             │      │
│    insurance_expiry DATE                │      │
│                                         │      │
│ -- STATUS --                            │      │
│    status ENUM                          │      │
│    disposal_date DATE                   │      │
│    disposal_method ENUM                 │      │
│    disposal_proceeds DECIMAL            │      │
│                                         │      │
│    created_at TIMESTAMP                 │      │
│    updated_at TIMESTAMP                 │      │
└─────────────────────────────────────────┘      │
              │                                   │
              │ 1:N                               │
              ▼                                   │
┌─────────────────────────────────────────┐      │
│        grap_valuation_history           │      │
├─────────────────────────────────────────┤      │
│ PK id INT                              │      │
│ FK heritage_asset_id INT               │──────┤
│    valuation_date DATE                  │      │
│    valuation_type ENUM                  │      │
│    previous_value DECIMAL               │      │
│    new_value DECIMAL                    │      │
│    change_amount DECIMAL                │      │
│    valuation_method ENUM                │      │
│    valuer_name VARCHAR                  │      │
│    valuer_organization VARCHAR          │      │
│    valuer_qualifications VARCHAR        │      │
│    valuation_report_ref VARCHAR         │      │
│    justification TEXT                   │      │
│    approved_by INT                      │      │
│    approved_at TIMESTAMP                │      │
│    created_at TIMESTAMP                 │      │
└─────────────────────────────────────────┘      │
┌─────────────────────────────────────────┐      │
│         grap_impairment_record          │      │
├─────────────────────────────────────────┤      │
│ PK id INT                              │      │
│ FK heritage_asset_id INT               │──────┤
│    impairment_date DATE                 │      │
│    impairment_type ENUM                 │      │
│    impairment_amount DECIMAL            │      │
│    carrying_before DECIMAL              │      │
│    carrying_after DECIMAL               │      │
│    reason TEXT                          │      │
│    reversible TINYINT                   │      │
│    reversal_date DATE                   │      │
│    reversal_amount DECIMAL              │      │
│    approved_by INT                      │      │
│    created_at TIMESTAMP                 │      │
└─────────────────────────────────────────┘      │
┌─────────────────────────────────────────┐      │
│        grap_movement_record             │      │
├─────────────────────────────────────────┤      │
│ PK id INT                              │      │
│ FK heritage_asset_id INT               │──────┘
│    movement_date DATE                   │
│    movement_type ENUM                   │
│    from_location VARCHAR                │
│    to_location VARCHAR                  │
│    reason TEXT                          │
│    authorized_by INT                    │
│    condition_before VARCHAR             │
│    condition_after VARCHAR              │
│    created_at TIMESTAMP                 │
└─────────────────────────────────────────┘

Asset Classes (GRAP 103)

Class Description
artwork Paintings, sculptures, etc.
antiquities Archaeological items
museum_collections Curated collections
library_collections Rare books, manuscripts
archival_records Historical documents
natural_heritage Natural specimens
monuments Buildings, structures
memorabilia Historical objects

Valuation Methods

Method Code Description
Cost cost Original acquisition cost
Fair Value fair_value Current market value
Replacement Cost replacement Cost to replace
Insurance Value insurance Insured amount
Nominal nominal R1 token value

Service Methods

GrapService

namespace ahgGrapPlugin\Service;

class GrapService
{
    // Asset Management
    public function createAsset(int $objectId, array $data): int
    public function updateAsset(int $id, array $data): bool
    public function getAsset(int $objectId): ?array
    public function listAssets(array $filters): Collection

    // Valuations
    public function recordValuation(int $assetId, array $data): int
    public function getValuationHistory(int $assetId): Collection
    public function getAssetsForRevaluation(int $days = 90): Collection

    // Impairments
    public function recordImpairment(int $assetId, array $data): int
    public function reverseImpairment(int $impairmentId, array $data): bool

    // Movements
    public function recordMovement(int $assetId, array $data): int
    public function getMovementHistory(int $assetId): Collection

    // Reporting
    public function getAssetRegister(array $filters): Collection
    public function getBalanceSheet(string $date): array
    public function getMovementReport(string $startDate, string $endDate): array
    public function getValuationReport(): array
    public function getComplianceSummary(): array

    // Export
    public function exportAssetRegister(string $format): string
    public function generateAnnualReport(int $year): string
}

Reports

Report Description
Asset Register Complete list with values
Balance Sheet Financial position
Movement Schedule Additions/disposals
Valuation Summary Current valuations
Compliance Report GRAP 103 checklist

Views (Database)

-- Summary view
CREATE VIEW v_grap_103_summary AS
SELECT 
    asset_class,
    COUNT(*) as asset_count,
    SUM(current_carrying_amount) as total_value,
    SUM(CASE WHEN recognition_status = 'recognised' THEN 1 ELSE 0 END) as recognised_count
FROM grap_heritage_asset
WHERE status = 'active'
GROUP BY asset_class;

-- Balance sheet view
CREATE VIEW v_grap_balance_sheet AS
SELECT
    asset_class,
    SUM(cost_of_acquisition) as gross_cost,
    SUM(accumulated_impairment) as impairment,
    SUM(current_carrying_amount) as net_value
FROM grap_heritage_asset
WHERE status = 'active' AND recognition_status = 'recognised'
GROUP BY asset_class;

CLI Tasks

heritageInstallTask

Installs the heritage accounting database schema and optional regional configurations.

// Location: lib/task/heritageInstallTask.class.php

class heritageInstallTask extends sfBaseTask
{
    // Namespace: heritage
    // Command: install
}

Options:

Option Type Description
--application optional Application name (default: qubit)
--env required Environment (default: cli)
--region optional Region code(s) to install (comma-separated)
--all-regions none Install all available regions

Usage Examples:

# Install core schema only
php symfony heritage:install

# Install core + Africa IPSAS region
php symfony heritage:install --region=africa_ipsas

# Install core + multiple regions
php symfony heritage:install --region=africa_ipsas,south_africa_grap

# Install core + ALL regions
php symfony heritage:install --all-regions

Process Flow:

┌──────────────────────────────────────────────────────────────┐
│                    heritage:install                           │
├──────────────────────────────────────────────────────────────┤
│                                                               │
│  Step 1: Install Core Schema                                  │
│  ├── Load core.sql from database/ directory                  │
│  ├── Execute SQL statements                                  │
│  └── Handle "table exists" gracefully                        │
│                                                               │
│  Step 2: Install Regions (if specified)                      │
│  ├── Load RegionManager                                      │
│  ├── For each region:                                        │
│  │   ├── Call RegionManager::installRegion()                 │
│  │   ├── Install compliance rules                            │
│  │   └── Report success/failure                              │
│  └── Skip already-installed regions                          │
│                                                               │
│  Step 3: Summary                                              │
│  ├── Show installed regions                                  │
│  └── Display next steps                                      │
│                                                               │
└──────────────────────────────────────────────────────────────┘

heritageRegionTask

Manages regional heritage accounting standards.

// Location: lib/task/heritageRegionTask.class.php

class heritageRegionTask extends sfBaseTask
{
    // Namespace: heritage
    // Command: region
}

Options:

Option Type Description
--application optional Application name (default: qubit)
--env required Environment (default: cli)
--install optional Install a region by code
--uninstall optional Uninstall a region by code
--set-active optional Set active region for institution
--info optional Show region details
--repository optional Repository ID for --set-active
--currency optional Currency override for --set-active

Usage Examples:

# List all regions with status
php symfony heritage:region

# Install a region
php symfony heritage:region --install=africa_ipsas

# Uninstall a region
php symfony heritage:region --uninstall=uk_frs

# Set active region globally
php symfony heritage:region --set-active=africa_ipsas

# Set active region for specific repository
php symfony heritage:region --set-active=africa_ipsas --repository=5

# Set active region with currency override
php symfony heritage:region --set-active=africa_ipsas --currency=USD

# Show region details
php symfony heritage:region --info=africa_ipsas

Available Regions:

Code Standard Description
africa_ipsas IPSAS 45 Africa: Zimbabwe, Kenya, Nigeria, Ghana, etc.
south_africa_grap GRAP 103 South Africa: National Treasury compliance
uk_frs FRS 102 United Kingdom: Charity Commission SORP
usa_government GASB 34 USA: State and local governments
usa_nonprofit FASB 958 USA: Museums, galleries, non-profits
australia_nz AASB 116 Australia/New Zealand: AASB compliance
canada_psas PSAS 3150 Canada: Public accounts
international_private IAS 16 International private sector

Region Info Output:

=== Region: Africa (IPSAS 45) ===

Code:           africa_ipsas
Status:         INSTALLED
Default Currency: USD
Regulatory Body: IPSASB (International Public Sector Accounting Standards Board)
Countries:      Zimbabwe, Kenya, Nigeria, Ghana, Tanzania, Uganda, Rwanda, Botswana

Installed:      2026-01-15 10:30:45

Accounting Standard:
  Code: IPSAS-45
  Name: IPSAS 45 - Property, Plant, and Equipment
  Description: International standard for heritage asset accounting
  Compliance Rules: 24

RegionManager

The RegionManager singleton handles region installation and configuration.

// Location: lib/Regions/RegionManager.php

class RegionManager
{
    // Singleton access
    public static function getInstance(): RegionManager

    // Region operations
    public function getAvailableRegions(): Collection
    public function installRegion(string $regionCode): array
    public function uninstallRegion(string $regionCode): array
    public function setActiveRegion(string $regionCode, ?int $repositoryId = null, array $options = []): array
    public function getActiveRegion(?int $repositoryId = null): ?object
}

installRegion() Return Structure:

[
    'success' => bool,
    'message' => string,
    'already_installed' => bool,  // if region was already installed
    'standard_name' => string,
    'standard_code' => string,
    'compliance_rules_installed' => int,
    'error' => string  // only on failure
]

setActiveRegion() Return Structure:

[
    'success' => bool,
    'message' => string,
    'standard_code' => string,
    'error' => string  // only on failure
]

Database Tables (Regional)

heritage_regional_config

CREATE TABLE heritage_regional_config (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    region_code VARCHAR(50) NOT NULL UNIQUE,
    region_name VARCHAR(255) NOT NULL,
    default_currency CHAR(3) NOT NULL,
    regulatory_body VARCHAR(255),
    countries JSON,
    is_installed TINYINT(1) DEFAULT 0,
    installed_at TIMESTAMP NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

heritage_accounting_standard

CREATE TABLE heritage_accounting_standard (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    region_code VARCHAR(50) NOT NULL,
    code VARCHAR(50) NOT NULL,
    name VARCHAR(255) NOT NULL,
    description TEXT,
    effective_date DATE,
    version VARCHAR(20),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

    INDEX idx_region (region_code)
);

heritage_compliance_rule

CREATE TABLE heritage_compliance_rule (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    standard_id BIGINT UNSIGNED NOT NULL,
    rule_code VARCHAR(50) NOT NULL,
    rule_name VARCHAR(255) NOT NULL,
    description TEXT,
    requirement_level ENUM('mandatory', 'recommended', 'optional') DEFAULT 'mandatory',
    category VARCHAR(100),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

    INDEX idx_standard (standard_id)
);

Cron Integration

The heritage region tasks can be integrated with the AHG Settings cron system:

Job Name Command Recommended Schedule
Heritage Region Install heritage:region --install=<code> One-time
Heritage Region Management heritage:region On-demand

Part of the AtoM AHG Framework