Files
desk-moloni/modules/desk_moloni/install.php
Emanuel Almeida c19f6fd9ee fix(perfexcrm module): align version to 3.0.1, unify entrypoint, and harden routes/views
- Bump DESK_MOLONI version to 3.0.1 across module
- Normalize hooks to after_client_* and instantiate PerfexHooks safely
- Fix OAuthController view path and API client class name
- Add missing admin views for webhook config/logs; adjust view loading
- Harden client portal routes and admin routes mapping
- Make Dashboard/Logs/Queue tolerant to optional model methods
- Align log details query with existing schema; avoid broken joins

This makes the module operational in Perfex (admin + client), reduces 404s,
and avoids fatal errors due to inconsistent tables/methods.
2025-09-11 17:38:45 +01:00

523 lines
21 KiB
PHP

<?php
defined('BASEPATH') or exit('No direct script access allowed');
/**
* Desk-Moloni v3.0 Installation Script
*
* This file handles the complete installation of the Desk-Moloni module
* including database tables, default options, permissions, and configuration.
*/
// Get CodeIgniter instance
$CI = &get_instance();
// Define module constants
if (!defined('DESK_MOLONI_MODULE_VERSION')) {
define('DESK_MOLONI_MODULE_VERSION', '3.0.1');
}
/**
* Generate encryption key helper function
*/
if (!function_exists('generate_encryption_key')) {
function generate_encryption_key($length = 32) {
return bin2hex(random_bytes($length));
}
}
/**
* Add default module options
*/
// Core API Configuration
add_option('desk_moloni_api_base_url', 'https://api.moloni.pt/v1/');
add_option('desk_moloni_oauth_base_url', 'https://www.moloni.pt/v1/');
add_option('desk_moloni_api_timeout', '30');
add_option('desk_moloni_max_retries', '3');
// OAuth Configuration
add_option('desk_moloni_client_id', '');
add_option('desk_moloni_client_secret', '');
add_option('desk_moloni_access_token', '');
add_option('desk_moloni_refresh_token', '');
add_option('desk_moloni_token_expires_at', '');
add_option('desk_moloni_company_id', '');
add_option('desk_moloni_oauth_timeout', '30');
add_option('desk_moloni_use_pkce', '1');
// Sync Configuration
add_option('desk_moloni_sync_enabled', '1');
add_option('desk_moloni_auto_sync_enabled', '1');
add_option('desk_moloni_realtime_sync_enabled', '0');
add_option('desk_moloni_sync_delay', '300');
add_option('desk_moloni_batch_sync_enabled', '1');
// Entity Sync Settings
add_option('desk_moloni_sync_customers', '1');
add_option('desk_moloni_sync_invoices', '1');
add_option('desk_moloni_sync_estimates', '1');
add_option('desk_moloni_sync_credit_notes', '1');
add_option('desk_moloni_sync_receipts', '0');
add_option('desk_moloni_sync_products', '0');
// Performance Settings
add_option('desk_moloni_enable_monitoring', '1');
add_option('desk_moloni_enable_performance_tracking', '1');
add_option('desk_moloni_enable_caching', '1');
add_option('desk_moloni_cache_ttl', '3600');
// Security Settings
add_option('desk_moloni_enable_encryption', '1');
add_option('desk_moloni_webhook_signature_verification', '1');
add_option('desk_moloni_enable_audit_logging', '1');
// Logging Settings
add_option('desk_moloni_enable_logging', '1');
add_option('desk_moloni_log_level', 'info');
add_option('desk_moloni_log_api_requests', '0');
add_option('desk_moloni_log_retention_days', '30');
// Queue Settings
add_option('desk_moloni_enable_queue', '1');
add_option('desk_moloni_queue_batch_size', '10');
add_option('desk_moloni_queue_max_attempts', '3');
add_option('desk_moloni_queue_retry_delay', '300');
// Webhook Settings
add_option('desk_moloni_enable_webhooks', '1');
add_option('desk_moloni_webhook_timeout', '30');
add_option('desk_moloni_webhook_max_retries', '3');
add_option('desk_moloni_webhook_secret', generate_encryption_key());
// Client Portal Settings
add_option('desk_moloni_enable_client_portal', '0');
add_option('desk_moloni_client_can_download_pdfs', '1');
// Error Handling
add_option('desk_moloni_continue_on_error', '1');
add_option('desk_moloni_max_consecutive_errors', '5');
add_option('desk_moloni_enable_error_notifications', '1');
// Rate Limiting
add_option('desk_moloni_enable_rate_limiting', '1');
add_option('desk_moloni_requests_per_minute', '60');
add_option('desk_moloni_rate_limit_window', '60');
// Redis Settings
add_option('desk_moloni_enable_redis', '0');
add_option('desk_moloni_redis_host', '127.0.0.1');
add_option('desk_moloni_redis_port', '6379');
add_option('desk_moloni_redis_password', '');
add_option('desk_moloni_redis_database', '0');
add_option('desk_moloni_redis_db', '0');
// Module Metadata
add_option('desk_moloni_module_version', DESK_MOLONI_MODULE_VERSION);
add_option('desk_moloni_installation_date', date('Y-m-d H:i:s'));
add_option('desk_moloni_last_update', date('Y-m-d H:i:s'));
/**
* Create Sync Queue Table
*/
if (!$CI->db->table_exists(db_prefix() . 'desk_moloni_sync_queue')) {
$CI->db->query('CREATE TABLE `' . db_prefix() . 'desk_moloni_sync_queue` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`entity_type` varchar(50) NOT NULL,
`entity_id` int(11) NOT NULL,
`perfex_id` int(11) DEFAULT NULL,
`moloni_id` int(11) DEFAULT NULL,
`action` enum(\'create\',\'update\',\'delete\',\'sync\') NOT NULL DEFAULT \'sync\',
`direction` enum(\'perfex_to_moloni\',\'moloni_to_perfex\',\'bidirectional\') NOT NULL DEFAULT \'bidirectional\',
`priority` enum(\'low\',\'normal\',\'high\',\'critical\') NOT NULL DEFAULT \'normal\',
`status` enum(\'pending\',\'processing\',\'completed\',\'failed\',\'cancelled\') NOT NULL DEFAULT \'pending\',
`attempts` int(11) NOT NULL DEFAULT 0,
`max_attempts` int(11) NOT NULL DEFAULT 3,
`data` longtext DEFAULT NULL COMMENT \'JSON data for sync\',
`error_message` text DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`scheduled_at` timestamp NULL DEFAULT NULL,
`started_at` timestamp NULL DEFAULT NULL,
`completed_at` timestamp NULL DEFAULT NULL,
`created_by` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_entity_type_id` (`entity_type`, `entity_id`),
KEY `idx_status_priority` (`status`, `priority`),
KEY `idx_scheduled_at` (`scheduled_at`),
KEY `idx_perfex_id` (`perfex_id`),
KEY `idx_moloni_id` (`moloni_id`),
KEY `idx_created_by` (`created_by`)
) ENGINE=InnoDB DEFAULT CHARSET=' . $CI->db->char_set . ';');
}
/**
* Create Sync Logs Table
*/
if (!$CI->db->table_exists(db_prefix() . 'desk_moloni_sync_logs')) {
$CI->db->query('CREATE TABLE `' . db_prefix() . 'desk_moloni_sync_logs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`queue_id` int(11) DEFAULT NULL,
`entity_type` varchar(50) NOT NULL,
`entity_id` int(11) NOT NULL,
`action` varchar(50) NOT NULL,
`direction` varchar(50) NOT NULL,
`status` enum(\'started\',\'success\',\'error\',\'warning\') NOT NULL,
`message` text DEFAULT NULL,
`request_data` longtext DEFAULT NULL COMMENT \'JSON request data\',
`response_data` longtext DEFAULT NULL COMMENT \'JSON response data\',
`execution_time` decimal(10,4) DEFAULT NULL COMMENT \'Execution time in seconds\',
`memory_usage` int(11) DEFAULT NULL COMMENT \'Memory usage in bytes\',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`created_by` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_queue_id` (`queue_id`),
KEY `idx_entity_type_id` (`entity_type`, `entity_id`),
KEY `idx_status` (`status`),
KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=' . $CI->db->char_set . ';');
}
/**
* Create Entity Mappings Table
*/
if (!$CI->db->table_exists(db_prefix() . 'desk_moloni_entity_mappings')) {
$CI->db->query('CREATE TABLE `' . db_prefix() . 'desk_moloni_entity_mappings` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`entity_type` varchar(50) NOT NULL,
`perfex_id` int(11) NOT NULL,
`moloni_id` int(11) NOT NULL,
`perfex_hash` varchar(64) DEFAULT NULL COMMENT \'Hash of Perfex entity data\',
`moloni_hash` varchar(64) DEFAULT NULL COMMENT \'Hash of Moloni entity data\',
`sync_status` enum(\'synced\',\'pending\',\'error\',\'conflict\') NOT NULL DEFAULT \'synced\',
`last_sync_at` timestamp NULL DEFAULT NULL,
`last_perfex_update` timestamp NULL DEFAULT NULL,
`last_moloni_update` timestamp NULL DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`metadata` json DEFAULT NULL COMMENT \'Additional mapping metadata\',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_entity_perfex` (`entity_type`, `perfex_id`),
UNIQUE KEY `uk_entity_moloni` (`entity_type`, `moloni_id`),
KEY `idx_sync_status` (`sync_status`),
KEY `idx_last_sync` (`last_sync_at`)
) ENGINE=InnoDB DEFAULT CHARSET=' . $CI->db->char_set . ';');
}
/**
* Create Configuration Table
*/
if (!$CI->db->table_exists(db_prefix() . 'desk_moloni_configuration')) {
$CI->db->query('CREATE TABLE `' . db_prefix() . 'desk_moloni_configuration` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`config_key` varchar(100) NOT NULL,
`config_value` longtext DEFAULT NULL,
`config_type` enum(\'string\',\'integer\',\'boolean\',\'json\',\'encrypted\') NOT NULL DEFAULT \'string\',
`description` text DEFAULT NULL,
`category` varchar(50) DEFAULT NULL,
`is_system` tinyint(1) NOT NULL DEFAULT 0,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`updated_by` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_config_key` (`config_key`),
KEY `idx_category` (`category`),
KEY `idx_is_system` (`is_system`)
) ENGINE=InnoDB DEFAULT CHARSET=' . $CI->db->char_set . ';');
}
/**
* Create API Tokens Table
*/
if (!$CI->db->table_exists(db_prefix() . 'desk_moloni_api_tokens')) {
$CI->db->query('CREATE TABLE `' . db_prefix() . 'desk_moloni_api_tokens` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`token_type` enum(\'access_token\',\'refresh_token\',\'webhook_token\') NOT NULL,
`token_value` text NOT NULL COMMENT \'Encrypted token value\',
`expires_at` timestamp NULL DEFAULT NULL,
`company_id` int(11) DEFAULT NULL,
`scopes` json DEFAULT NULL,
`metadata` json DEFAULT NULL,
`active` tinyint(1) NOT NULL DEFAULT 1,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`last_used_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_token_type` (`token_type`),
KEY `idx_company_id` (`company_id`),
KEY `idx_active` (`active`),
KEY `idx_expires_at` (`expires_at`)
) ENGINE=InnoDB DEFAULT CHARSET=' . $CI->db->char_set . ';');
}
/**
* Create Webhook Logs Table
*/
if (!$CI->db->table_exists(db_prefix() . 'desk_moloni_webhook_logs')) {
$CI->db->query('CREATE TABLE `' . db_prefix() . 'desk_moloni_webhook_logs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`webhook_id` varchar(100) DEFAULT NULL,
`event_type` varchar(50) NOT NULL,
`source` enum(\'moloni\',\'perfex\') NOT NULL,
`payload` longtext DEFAULT NULL COMMENT \'JSON webhook payload\',
`headers` json DEFAULT NULL COMMENT \'Request headers\',
`signature` varchar(255) DEFAULT NULL,
`signature_valid` tinyint(1) DEFAULT NULL,
`processed` tinyint(1) NOT NULL DEFAULT 0,
`processing_result` text DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`processed_at` timestamp NULL DEFAULT NULL,
`ip_address` varchar(45) DEFAULT NULL,
`user_agent` text DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_event_type` (`event_type`),
KEY `idx_source` (`source`),
KEY `idx_processed` (`processed`),
KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=' . $CI->db->char_set . ';');
}
/**
* Create Performance Metrics Table
*/
if (!$CI->db->table_exists(db_prefix() . 'desk_moloni_performance_metrics')) {
$CI->db->query('CREATE TABLE `' . db_prefix() . 'desk_moloni_performance_metrics` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`metric_type` varchar(50) NOT NULL,
`metric_name` varchar(100) NOT NULL,
`metric_value` decimal(15,4) NOT NULL,
`metric_unit` varchar(20) DEFAULT NULL,
`entity_type` varchar(50) DEFAULT NULL,
`entity_id` int(11) DEFAULT NULL,
`tags` json DEFAULT NULL COMMENT \'Additional metric tags\',
`recorded_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`date_hour` varchar(13) NOT NULL COMMENT \'YYYY-MM-DD HH for aggregation\',
`date_day` date NOT NULL COMMENT \'Date for daily aggregation\',
PRIMARY KEY (`id`),
KEY `idx_metric_type_name` (`metric_type`, `metric_name`),
KEY `idx_recorded_at` (`recorded_at`),
KEY `idx_date_hour` (`date_hour`),
KEY `idx_date_day` (`date_day`),
KEY `idx_entity` (`entity_type`, `entity_id`)
) ENGINE=InnoDB DEFAULT CHARSET=' . $CI->db->char_set . ';');
}
/**
* Create Error Logs Table
*/
if (!$CI->db->table_exists(db_prefix() . 'desk_moloni_error_logs')) {
$CI->db->query('CREATE TABLE `' . db_prefix() . 'desk_moloni_error_logs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`error_code` varchar(50) DEFAULT NULL,
`error_type` varchar(50) NOT NULL,
`severity` enum(\'low\',\'medium\',\'high\',\'critical\') NOT NULL DEFAULT \'medium\',
`message` text NOT NULL,
`context` json DEFAULT NULL COMMENT \'Error context data\',
`stack_trace` longtext DEFAULT NULL,
`entity_type` varchar(50) DEFAULT NULL,
`entity_id` int(11) DEFAULT NULL,
`queue_id` int(11) DEFAULT NULL,
`resolved` tinyint(1) NOT NULL DEFAULT 0,
`resolved_at` timestamp NULL DEFAULT NULL,
`resolved_by` int(11) DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`ip_address` varchar(45) DEFAULT NULL,
`user_agent` text DEFAULT NULL,
`created_by` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_error_type` (`error_type`),
KEY `idx_severity` (`severity`),
KEY `idx_resolved` (`resolved`),
KEY `idx_created_at` (`created_at`),
KEY `idx_entity` (`entity_type`, `entity_id`),
KEY `idx_queue_id` (`queue_id`)
) ENGINE=InnoDB DEFAULT CHARSET=' . $CI->db->char_set . ';');
}
/**
* Create Document Cache Table
*/
if (!$CI->db->table_exists(db_prefix() . 'desk_moloni_document_cache')) {
$CI->db->query('CREATE TABLE `' . db_prefix() . 'desk_moloni_document_cache` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`cache_key` varchar(255) NOT NULL,
`entity_type` varchar(50) NOT NULL,
`entity_id` int(11) NOT NULL,
`document_type` varchar(50) DEFAULT NULL,
`document_data` longtext DEFAULT NULL COMMENT \'Cached document data\',
`file_path` varchar(500) DEFAULT NULL,
`file_size` int(11) DEFAULT NULL,
`mime_type` varchar(100) DEFAULT NULL,
`expires_at` timestamp NULL DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`accessed_at` timestamp NULL DEFAULT NULL,
`access_count` int(11) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_cache_key` (`cache_key`),
KEY `idx_entity` (`entity_type`, `entity_id`),
KEY `idx_expires_at` (`expires_at`),
KEY `idx_document_type` (`document_type`)
) ENGINE=InnoDB DEFAULT CHARSET=' . $CI->db->char_set . ';');
}
/**
* Create Config Table (for backward compatibility)
*/
if (!$CI->db->table_exists(db_prefix() . 'desk_moloni_config')) {
$CI->db->query('CREATE TABLE `' . db_prefix() . 'desk_moloni_config` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`setting_key` varchar(255) NOT NULL,
`setting_value` longtext DEFAULT NULL,
`encrypted` tinyint(1) NOT NULL DEFAULT 0,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_setting_key` (`setting_key`),
KEY `idx_setting_key` (`setting_key`),
KEY `idx_encrypted` (`encrypted`)
) ENGINE=InnoDB DEFAULT CHARSET=' . $CI->db->char_set . ';');
}
/**
* Create Mapping Table (for backward compatibility)
*/
if (!$CI->db->table_exists(db_prefix() . 'desk_moloni_mapping')) {
$CI->db->query('CREATE TABLE `' . db_prefix() . 'desk_moloni_mapping` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`entity_type` enum(\'client\',\'product\',\'invoice\',\'estimate\',\'credit_note\') NOT NULL,
`perfex_id` int(11) NOT NULL,
`moloni_id` int(11) NOT NULL,
`sync_direction` enum(\'perfex_to_moloni\',\'moloni_to_perfex\',\'bidirectional\') NOT NULL DEFAULT \'bidirectional\',
`last_sync_at` timestamp NULL DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_perfex_mapping` (`entity_type`, `perfex_id`),
UNIQUE KEY `unique_moloni_mapping` (`entity_type`, `moloni_id`),
KEY `idx_entity_perfex` (`entity_type`, `perfex_id`),
KEY `idx_entity_moloni` (`entity_type`, `moloni_id`),
KEY `idx_last_sync` (`last_sync_at`)
) ENGINE=InnoDB DEFAULT CHARSET=' . $CI->db->char_set . ';');
}
/**
* Create Sync Log Table (for backward compatibility)
*/
if (!$CI->db->table_exists(db_prefix() . 'desk_moloni_sync_log')) {
$CI->db->query('CREATE TABLE `' . db_prefix() . 'desk_moloni_sync_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`operation_type` enum(\'create\',\'update\',\'delete\',\'status_change\') NOT NULL,
`entity_type` enum(\'client\',\'product\',\'invoice\',\'estimate\',\'credit_note\') NOT NULL,
`perfex_id` int(11) DEFAULT NULL,
`moloni_id` int(11) DEFAULT NULL,
`direction` enum(\'perfex_to_moloni\',\'moloni_to_perfex\') NOT NULL,
`status` enum(\'success\',\'error\',\'warning\') NOT NULL,
`request_data` longtext DEFAULT NULL COMMENT \'JSON request data\',
`response_data` longtext DEFAULT NULL COMMENT \'JSON response data\',
`error_message` text DEFAULT NULL,
`execution_time_ms` int(11) DEFAULT NULL COMMENT \'Execution time in milliseconds\',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_entity_status` (`entity_type`, `status`),
KEY `idx_perfex_entity` (`perfex_id`, `entity_type`),
KEY `idx_moloni_entity` (`moloni_id`, `entity_type`),
KEY `idx_created_at` (`created_at`),
KEY `idx_status_direction` (`status`, `direction`),
KEY `idx_log_analytics` (`entity_type`, `operation_type`, `status`, `created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=' . $CI->db->char_set . ';');
}
/**
* Insert default configurations
*/
$default_configs = [
[
'config_key' => 'api_configuration',
'config_value' => json_encode([
'base_url' => 'https://api.moloni.pt/v1/',
'oauth_url' => 'https://www.moloni.pt/v1/',
'timeout' => 30,
'max_retries' => 3,
'user_agent' => 'Desk-Moloni-Integration/3.0.0'
]),
'config_type' => 'json',
'description' => 'API connection configuration',
'category' => 'api',
'is_system' => 1
],
[
'config_key' => 'sync_configuration',
'config_value' => json_encode([
'auto_sync' => true,
'realtime_sync' => false,
'batch_size' => 10,
'default_delay' => 300,
'max_attempts' => 3
]),
'config_type' => 'json',
'description' => 'Synchronization behavior configuration',
'category' => 'sync',
'is_system' => 0
],
[
'config_key' => 'performance_configuration',
'config_value' => json_encode([
'monitoring_enabled' => true,
'caching_enabled' => true,
'cache_ttl' => 3600,
'log_slow_queries' => true,
'slow_query_threshold' => 1000
]),
'config_type' => 'json',
'description' => 'Performance and monitoring settings',
'category' => 'performance',
'is_system' => 0
]
];
foreach ($default_configs as $config) {
// Check if configuration already exists
$existing = $CI->db->get_where(db_prefix() . 'desk_moloni_configuration',
['config_key' => $config['config_key']])->row();
if (!$existing) {
$CI->db->insert(db_prefix() . 'desk_moloni_configuration', $config);
}
}
/**
* Add module permissions
*/
if (!$CI->db->get_where('tblpermissions', ['name' => 'desk_moloni'])->row()) {
$permissions = [
['name' => 'desk_moloni', 'shortname' => 'view', 'description' => 'View Desk-Moloni module'],
['name' => 'desk_moloni', 'shortname' => 'create', 'description' => 'Create sync tasks and configurations'],
['name' => 'desk_moloni', 'shortname' => 'edit', 'description' => 'Edit configurations and mappings'],
['name' => 'desk_moloni', 'shortname' => 'delete', 'description' => 'Delete sync tasks and clear data']
];
foreach ($permissions as $permission) {
$CI->db->insert('tblpermissions', $permission);
}
}
/**
* Create directories if they don't exist
*/
$directories = [
APP_MODULES_PATH . 'desk_moloni/uploads/',
APP_MODULES_PATH . 'desk_moloni/logs/',
APP_MODULES_PATH . 'desk_moloni/cache/',
APP_MODULES_PATH . 'desk_moloni/temp/'
];
foreach ($directories as $dir) {
if (!is_dir($dir)) {
mkdir($dir, 0755, true);
// Create index.html for security
file_put_contents($dir . 'index.html', '');
}
}
// Log installation
log_activity('Desk-Moloni v3.0 module installed successfully');