🚀 مُصادَق: تحديث برمجي جديد 2026-05-03 13:19
This commit is contained in:
41
database/migrations/001_initial_schema.sql
Normal file
41
database/migrations/001_initial_schema.sql
Normal file
@@ -0,0 +1,41 @@
|
||||
-- ─── Tenants ──────────────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS tenants (
|
||||
id CHAR(36) NOT NULL DEFAULT (UUID()),
|
||||
name VARCHAR(255) NOT NULL,
|
||||
email VARCHAR(255) NOT NULL,
|
||||
phone VARCHAR(20) NULL,
|
||||
status ENUM('active','suspended','trial') NOT NULL DEFAULT 'trial',
|
||||
trial_ends_at DATETIME NULL,
|
||||
settings JSON DEFAULT (JSON_OBJECT()),
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted_at DATETIME NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uq_tenants_email (email)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- ─── Users ────────────────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id CHAR(36) NOT NULL DEFAULT (UUID()),
|
||||
tenant_id CHAR(36) NOT NULL,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
email VARCHAR(255) NOT NULL,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
role ENUM('super_admin','admin','accountant','employee','viewer') NOT NULL,
|
||||
assigned_company_id CHAR(36) NULL,
|
||||
refresh_token_hash VARCHAR(255) NULL,
|
||||
totp_secret VARCHAR(64) NULL,
|
||||
totp_enabled TINYINT(1) NOT NULL DEFAULT 0,
|
||||
is_active TINYINT(1) NOT NULL DEFAULT 1,
|
||||
email_verified_at DATETIME NULL,
|
||||
last_login_at DATETIME NULL,
|
||||
last_login_ip VARCHAR(45) NULL,
|
||||
failed_login_count INT NOT NULL DEFAULT 0,
|
||||
locked_until DATETIME NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted_at DATETIME NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uq_tenant_email (tenant_id, email),
|
||||
CONSTRAINT fk_users_tenant FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
47
database/migrations/002_core_modules.sql
Normal file
47
database/migrations/002_core_modules.sql
Normal file
@@ -0,0 +1,47 @@
|
||||
-- ─── Companies ────────────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS companies (
|
||||
id CHAR(36) NOT NULL DEFAULT (UUID()),
|
||||
tenant_id CHAR(36) NOT NULL,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
name_en VARCHAR(255) NULL,
|
||||
tax_identification_number VARCHAR(20) NOT NULL,
|
||||
commercial_registration_number VARCHAR(50) NULL,
|
||||
address TEXT NULL,
|
||||
city VARCHAR(100) NULL,
|
||||
contact_email VARCHAR(255) NULL,
|
||||
contact_phone VARCHAR(20) NULL,
|
||||
jofotara_client_id_encrypted TEXT NULL,
|
||||
jofotara_secret_key_encrypted TEXT NULL,
|
||||
jofotara_income_source_sequence VARCHAR(50) NULL,
|
||||
certificate_path VARCHAR(255) NULL,
|
||||
certificate_password_encrypted TEXT NULL,
|
||||
is_jofotara_linked TINYINT(1) NOT NULL DEFAULT 0,
|
||||
is_active TINYINT(1) NOT NULL DEFAULT 1,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted_at DATETIME NULL,
|
||||
PRIMARY KEY (id),
|
||||
INDEX idx_companies_tenant (tenant_id),
|
||||
INDEX idx_companies_tin (tax_identification_number),
|
||||
CONSTRAINT fk_companies_tenant FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- ─── Subscriptions ────────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS subscriptions (
|
||||
id CHAR(36) NOT NULL DEFAULT (UUID()),
|
||||
tenant_id CHAR(36) NOT NULL,
|
||||
plan ENUM('free','basic','office','pro','enterprise') NOT NULL DEFAULT 'basic',
|
||||
max_companies INT NOT NULL DEFAULT 3,
|
||||
max_invoices_per_month INT NOT NULL DEFAULT 50,
|
||||
max_users INT NOT NULL DEFAULT 2,
|
||||
price_jod DECIMAL(10,2) NOT NULL DEFAULT 0.00,
|
||||
invoices_used_this_month INT NOT NULL DEFAULT 0,
|
||||
status ENUM('active','past_due','cancelled','trial') NOT NULL DEFAULT 'active',
|
||||
current_period_start DATETIME NULL,
|
||||
current_period_end DATETIME NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uq_sub_tenant (tenant_id),
|
||||
CONSTRAINT fk_sub_tenant FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
69
database/migrations/003_invoices.sql
Normal file
69
database/migrations/003_invoices.sql
Normal file
@@ -0,0 +1,69 @@
|
||||
-- ─── Invoices ─────────────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS invoices (
|
||||
id CHAR(36) NOT NULL DEFAULT (UUID()),
|
||||
tenant_id CHAR(36) NOT NULL,
|
||||
company_id CHAR(36) NOT NULL,
|
||||
uploaded_by CHAR(36) NULL,
|
||||
invoice_number VARCHAR(100) NULL,
|
||||
invoice_date DATE NULL,
|
||||
invoice_type ENUM('cash','credit') NOT NULL DEFAULT 'cash',
|
||||
ubl_type_code CHAR(3) NOT NULL DEFAULT '388',
|
||||
payment_method_code CHAR(3) NOT NULL DEFAULT '013',
|
||||
supplier_tin VARCHAR(20) NULL,
|
||||
supplier_name VARCHAR(255) NULL,
|
||||
supplier_address TEXT NULL,
|
||||
buyer_tin VARCHAR(20) NULL,
|
||||
buyer_national_id VARCHAR(20) NULL,
|
||||
buyer_name VARCHAR(255) NULL,
|
||||
subtotal DECIMAL(15,3) NOT NULL DEFAULT 0,
|
||||
discount_total DECIMAL(15,3) NOT NULL DEFAULT 0,
|
||||
tax_amount DECIMAL(15,3) NOT NULL DEFAULT 0,
|
||||
grand_total DECIMAL(15,3) NOT NULL DEFAULT 0,
|
||||
currency_code CHAR(3) NOT NULL DEFAULT 'JOD',
|
||||
status ENUM('uploaded','extracting','extracted','validated',
|
||||
'validation_failed','submitting','approved','rejected')
|
||||
NOT NULL DEFAULT 'uploaded',
|
||||
original_file_path TEXT NULL,
|
||||
original_file_hash VARCHAR(64) NULL,
|
||||
invoice_category VARCHAR(20) NOT NULL DEFAULT 'simplified',
|
||||
validation_errors JSON NULL,
|
||||
qr_code TEXT NULL,
|
||||
jofotara_response JSON NULL,
|
||||
ai_provider VARCHAR(20) NULL,
|
||||
ai_confidence_score DECIMAL(4,3) NULL,
|
||||
ai_prompt_tokens INT NOT NULL DEFAULT 0,
|
||||
ai_completion_tokens INT NOT NULL DEFAULT 0,
|
||||
ai_total_cost DECIMAL(10,6) NOT NULL DEFAULT 0,
|
||||
ai_raw_response JSON NULL,
|
||||
idempotency_key VARCHAR(64) NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted_at DATETIME NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uq_idempotency (idempotency_key),
|
||||
INDEX idx_invoices_tenant (tenant_id),
|
||||
INDEX idx_invoices_company (company_id),
|
||||
INDEX idx_invoices_status (status),
|
||||
INDEX idx_invoices_date (invoice_date),
|
||||
INDEX idx_invoices_file_hash (original_file_hash),
|
||||
CONSTRAINT fk_inv_tenant FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
CONSTRAINT fk_inv_company FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE CASCADE,
|
||||
CONSTRAINT fk_inv_user FOREIGN KEY (uploaded_by) REFERENCES users(id) ON DELETE SET NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- ─── Invoice Lines ────────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS invoice_lines (
|
||||
id CHAR(36) NOT NULL DEFAULT (UUID()),
|
||||
invoice_id CHAR(36) NOT NULL,
|
||||
line_number INT NOT NULL,
|
||||
description TEXT NOT NULL,
|
||||
quantity DECIMAL(15,3) NOT NULL,
|
||||
unit_price DECIMAL(15,3) NOT NULL,
|
||||
discount DECIMAL(15,3) NOT NULL DEFAULT 0,
|
||||
tax_rate DECIMAL(5,4) NOT NULL,
|
||||
tax_amount DECIMAL(15,3) NOT NULL DEFAULT 0,
|
||||
line_total DECIMAL(15,3) NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
INDEX idx_lines_invoice (invoice_id),
|
||||
CONSTRAINT fk_lines_invoice FOREIGN KEY (invoice_id) REFERENCES invoices(id) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
80
database/migrations/004_system.sql
Normal file
80
database/migrations/004_system.sql
Normal file
@@ -0,0 +1,80 @@
|
||||
-- ─── Audit Logs ───────────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS audit_logs (
|
||||
id CHAR(36) NOT NULL DEFAULT (UUID()),
|
||||
tenant_id CHAR(36) NULL,
|
||||
user_id CHAR(36) NULL,
|
||||
action VARCHAR(100) NOT NULL,
|
||||
entity_type VARCHAR(50) NULL,
|
||||
entity_id CHAR(36) NULL,
|
||||
old_data JSON NULL,
|
||||
new_data JSON NULL,
|
||||
ip_address VARCHAR(45) NULL,
|
||||
user_agent TEXT NULL,
|
||||
metadata JSON NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id),
|
||||
INDEX idx_audit_tenant (tenant_id),
|
||||
INDEX idx_audit_action (action),
|
||||
INDEX idx_audit_created (created_at)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- ─── Risk Scores ──────────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS risk_scores (
|
||||
id CHAR(36) NOT NULL DEFAULT (UUID()),
|
||||
tenant_id CHAR(36) NOT NULL,
|
||||
company_id CHAR(36) NOT NULL,
|
||||
invoice_id CHAR(36) NULL,
|
||||
risk_type VARCHAR(50) NOT NULL,
|
||||
score TINYINT UNSIGNED NOT NULL,
|
||||
reason TEXT NOT NULL,
|
||||
is_resolved TINYINT(1) NOT NULL DEFAULT 0,
|
||||
resolved_by CHAR(36) NULL,
|
||||
resolved_at DATETIME NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id),
|
||||
INDEX idx_risk_tenant (tenant_id),
|
||||
INDEX idx_risk_unresolved (is_resolved),
|
||||
CONSTRAINT fk_risk_tenant FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
CONSTRAINT fk_risk_company FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE CASCADE,
|
||||
CONSTRAINT fk_risk_invoice FOREIGN KEY (invoice_id) REFERENCES invoices(id) ON DELETE SET NULL,
|
||||
CONSTRAINT fk_risk_resolver FOREIGN KEY (resolved_by) REFERENCES users(id) ON DELETE SET NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- ─── Queue Jobs ───────────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS queue_jobs (
|
||||
id CHAR(36) NOT NULL DEFAULT (UUID()),
|
||||
type VARCHAR(100) NOT NULL,
|
||||
payload JSON NOT NULL,
|
||||
priority INT NOT NULL DEFAULT 0,
|
||||
attempts INT NOT NULL DEFAULT 0,
|
||||
max_attempts INT NOT NULL DEFAULT 3,
|
||||
status ENUM('pending','processing','completed','failed','dead')
|
||||
NOT NULL DEFAULT 'pending',
|
||||
error TEXT NULL,
|
||||
locked_at DATETIME NULL,
|
||||
locked_by VARCHAR(100) NULL,
|
||||
scheduled_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
completed_at DATETIME NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id),
|
||||
INDEX idx_queue_pending (status, priority DESC, scheduled_at)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- ─── API Keys ─────────────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS api_keys (
|
||||
id CHAR(36) NOT NULL DEFAULT (UUID()),
|
||||
tenant_id CHAR(36) NOT NULL,
|
||||
user_id CHAR(36) NOT NULL,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
public_key VARCHAR(64) NOT NULL,
|
||||
secret_hash VARCHAR(255) NOT NULL,
|
||||
permissions JSON DEFAULT (JSON_ARRAY('invoices:read','invoices:upload')),
|
||||
last_used_at DATETIME NULL,
|
||||
is_active TINYINT(1) NOT NULL DEFAULT 1,
|
||||
expires_at DATETIME NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uq_api_public_key (public_key),
|
||||
CONSTRAINT fk_apikeys_tenant FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
CONSTRAINT fk_apikeys_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
26
database/seed.sql
Normal file
26
database/seed.sql
Normal file
@@ -0,0 +1,26 @@
|
||||
-- ─── Initial Super Admin Seed ──────────────────────────────
|
||||
-- Default Password: admin123 (Please change after first login)
|
||||
|
||||
INSERT INTO tenants (id, name, email, status)
|
||||
VALUES ('d0e4e4e4-e4e4-4e4e-ae4e-e4e4e4e4e4e4', 'Musadaq Admin', 'admin@musadaq.app', 'active');
|
||||
|
||||
INSERT INTO users (id, tenant_id, name, email, password_hash, role, is_active)
|
||||
VALUES (
|
||||
'u0e4e4e4-e4e4-4e4e-ae4e-e4e4e4e4e4e4',
|
||||
'd0e4e4e4-e4e4-4e4e-ae4e-e4e4e4e4e4e4',
|
||||
'Super Admin',
|
||||
'admin@musadaq.app',
|
||||
'$argon2id$v=19$m=65536,t=3,p=4$VEpSbmRXNXBaV3REYTJodg$jZ8/X6Xf8X6Xf8X6Xf8X6Xf8X6Xf8X6Xf8X6Xf8X6Xg', -- Placeholder hash
|
||||
'super_admin',
|
||||
1
|
||||
);
|
||||
|
||||
INSERT INTO subscriptions (tenant_id, plan, max_companies, max_invoices_per_month, max_users, status)
|
||||
VALUES (
|
||||
'd0e4e4e4-e4e4-4e4e-ae4e-e4e4e4e4e4e4',
|
||||
'pro',
|
||||
999,
|
||||
9999,
|
||||
99,
|
||||
'active'
|
||||
);
|
||||
Reference in New Issue
Block a user