1
0

Giant Update

This commit is contained in:
Wian Drs
2026-07-31 13:57:11 +07:00
parent f68d967c8b
commit b0d08211ec
112 changed files with 6674 additions and 3 deletions
+30
View File
@@ -0,0 +1,30 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class BillingProfile extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return ['tax_rate' => 'decimal:2'];
}
public function tenant()
{
return $this->belongsTo(Tenant::class);
}
public function customers()
{
return $this->hasMany(Customer::class);
}
public function invoices()
{
return $this->hasMany(Invoice::class);
}
}
+98
View File
@@ -0,0 +1,98 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Customer extends Model
{
use SoftDeletes;
protected $guarded = ['id'];
protected function casts(): array
{
return [
'latitude' => 'decimal:7',
'longitude' => 'decimal:7',
'activated_at' => 'datetime',
'inactivated_at' => 'datetime',
];
}
public function tenant()
{
return $this->belongsTo(Tenant::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
public function provinsi()
{
return $this->belongsTo(WilayahProvinsi::class, 'provinsi_id');
}
public function kabupaten()
{
return $this->belongsTo(WilayahKabupaten::class, 'kabupaten_id');
}
public function kecamatan()
{
return $this->belongsTo(WilayahKecamatan::class, 'kecamatan_id');
}
public function desa()
{
return $this->belongsTo(WilayahDesa::class, 'desa_id');
}
public function packageProfile()
{
return $this->belongsTo(NasPackageProfile::class, 'package_profile_id');
}
public function nasMikrotik()
{
return $this->belongsTo(NasMikrotik::class, 'nas_mikrotik_id');
}
public function images()
{
return $this->hasMany(CustomerImage::class)->orderByDesc('is_cover')->orderBy('sort_order');
}
public function coverImage()
{
return $this->hasOne(CustomerImage::class)->where('is_cover', true);
}
public function billingProfile()
{
return $this->belongsTo(BillingProfile::class);
}
public function invoices()
{
return $this->hasMany(Invoice::class);
}
public function topologyConnections()
{
return $this->hasMany(TopologyCustomerConnection::class);
}
public function activeTopologyConnection()
{
return $this->hasOne(TopologyCustomerConnection::class)->where('status', 'active');
}
public function contacts()
{
return $this->hasMany(CustomerContact::class);
}
}
+21
View File
@@ -0,0 +1,21 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class CustomerContact extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return [
'is_primary' => 'boolean', 'is_verified' => 'boolean',
'can_receive_transactional' => 'boolean', 'can_receive_broadcast' => 'boolean',
'verified_at' => 'datetime', 'opted_out_at' => 'datetime',
];
}
public function customer() { return $this->belongsTo(Customer::class); }
}
+25
View File
@@ -0,0 +1,25 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class CustomerImage extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return ['is_cover' => 'boolean'];
}
public function customer()
{
return $this->belongsTo(Customer::class);
}
public function file()
{
return $this->belongsTo(StoredFile::class, 'stored_file_id');
}
}
+69
View File
@@ -0,0 +1,69 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Invoice extends Model
{
use SoftDeletes;
protected $guarded = ['id'];
protected function casts(): array
{
return [
'period_start' => 'date',
'period_end' => 'date',
'issue_date' => 'date',
'send_date' => 'date',
'warning_date' => 'date',
'isolation_date' => 'date',
'subtotal' => 'decimal:2',
'tax_rate' => 'decimal:2',
'tax_amount' => 'decimal:2',
'total' => 'decimal:2',
'paid_amount' => 'decimal:2',
'balance' => 'decimal:2',
'paid_at' => 'datetime',
'profile_snapshot' => 'array',
'metadata' => 'array',
];
}
public function tenant()
{
return $this->belongsTo(Tenant::class);
}
public function customer()
{
return $this->belongsTo(Customer::class);
}
public function billingProfile()
{
return $this->belongsTo(BillingProfile::class);
}
public function creator()
{
return $this->belongsTo(User::class, 'created_by');
}
public function updater()
{
return $this->belongsTo(User::class, 'updated_by');
}
public function payer()
{
return $this->belongsTo(User::class, 'paid_by');
}
public function paymentTransactions()
{
return $this->hasMany(PaymentTransaction::class);
}
}
+35
View File
@@ -0,0 +1,35 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class NotificationBroadcast extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return ['filter_snapshot' => 'array', 'scheduled_at' => 'datetime'];
}
public function tenant()
{
return $this->belongsTo(Tenant::class);
}
public function template()
{
return $this->belongsTo(NotificationTemplate::class, 'notification_template_id');
}
public function channelConfig()
{
return $this->belongsTo(NotificationChannel::class, 'notification_channel_id');
}
public function recipients()
{
return $this->hasMany(NotificationBroadcastRecipient::class);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class NotificationBroadcastRecipient extends Model
{
protected $guarded = ['id'];
public function broadcast()
{
return $this->belongsTo(NotificationBroadcast::class, 'notification_broadcast_id');
}
public function customer()
{
return $this->belongsTo(Customer::class);
}
}
+33
View File
@@ -0,0 +1,33 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class NotificationChannel extends Model
{
protected $guarded = ['id'];
protected $hidden = ['credentials'];
protected function casts(): array
{
return [
'enabled' => 'boolean',
'is_default' => 'boolean',
'credentials' => 'encrypted:array',
'settings' => 'array',
'last_health_check_at' => 'datetime',
];
}
public function tenant()
{
return $this->belongsTo(Tenant::class);
}
public function templates()
{
return $this->hasMany(NotificationTemplate::class);
}
}
+29
View File
@@ -0,0 +1,29 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class NotificationDelivery extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return [
'provider_response' => 'array', 'queued_at' => 'datetime', 'sent_at' => 'datetime',
'delivered_at' => 'datetime', 'read_at' => 'datetime', 'failed_at' => 'datetime',
'next_retry_at' => 'datetime',
];
}
public function message()
{
return $this->belongsTo(NotificationMessage::class, 'notification_message_id');
}
public function channelConfig()
{
return $this->belongsTo(NotificationChannel::class, 'notification_channel_id');
}
}
+15
View File
@@ -0,0 +1,15 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class NotificationEvent extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return ['available_channels' => 'array', 'variables' => 'array', 'is_system' => 'boolean', 'enabled' => 'boolean'];
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class NotificationEventOccurrence extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return ['processed_at' => 'datetime'];
}
public function subjectable()
{
return $this->morphTo();
}
}
+45
View File
@@ -0,0 +1,45 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class NotificationMessage extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return ['payload' => 'array', 'context' => 'array', 'scheduled_at' => 'datetime'];
}
public function event()
{
return $this->belongsTo(NotificationEvent::class, 'notification_event_id');
}
public function template()
{
return $this->belongsTo(NotificationTemplate::class, 'notification_template_id');
}
public function deliveries()
{
return $this->hasMany(NotificationDelivery::class);
}
public function broadcast()
{
return $this->belongsTo(NotificationBroadcast::class, 'notification_broadcast_id');
}
public function recipient()
{
return $this->morphTo();
}
public function subjectable()
{
return $this->morphTo();
}
}
+25
View File
@@ -0,0 +1,25 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class NotificationPreference extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return ['enabled' => 'boolean'];
}
public function event()
{
return $this->belongsTo(NotificationEvent::class, 'notification_event_id');
}
public function channelConfig()
{
return $this->belongsTo(NotificationChannel::class, 'notification_channel_id');
}
}
+30
View File
@@ -0,0 +1,30 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class NotificationTemplate extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return ['enabled' => 'boolean', 'variables' => 'array'];
}
public function event()
{
return $this->belongsTo(NotificationEvent::class, 'notification_event_id');
}
public function channelConfig()
{
return $this->belongsTo(NotificationChannel::class, 'notification_channel_id');
}
public function tenant()
{
return $this->belongsTo(Tenant::class);
}
}
+15
View File
@@ -0,0 +1,15 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class NotificationWebhookLog extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return ['signature_valid' => 'boolean', 'payload' => 'array', 'processed_at' => 'datetime'];
}
}
+20
View File
@@ -0,0 +1,20 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class PaymentAttempt extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return ['request_payload' => 'array', 'response_payload' => 'array'];
}
public function transaction()
{
return $this->belongsTo(PaymentTransaction::class, 'payment_transaction_id');
}
}
+34
View File
@@ -0,0 +1,34 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class PaymentGatewayAccount extends Model
{
protected $guarded = ['id'];
protected $hidden = ['credentials', 'webhook_secret'];
protected function casts(): array
{
return [
'credentials' => 'encrypted:array',
'webhook_secret' => 'encrypted',
'settings' => 'array',
'enabled' => 'boolean',
'is_default' => 'boolean',
'last_health_check_at' => 'datetime',
];
}
public function provider()
{
return $this->belongsTo(PaymentProvider::class, 'payment_provider_id');
}
public function tenant()
{
return $this->belongsTo(Tenant::class);
}
}
+15
View File
@@ -0,0 +1,15 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class PaymentProvider extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return ['capabilities' => 'array', 'credential_schema' => 'array', 'enabled' => 'boolean'];
}
}
+49
View File
@@ -0,0 +1,49 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class PaymentTransaction extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return [
'amount' => 'decimal:2', 'provider_fee' => 'decimal:2', 'platform_fee' => 'decimal:2',
'total_amount' => 'decimal:2', 'expires_at' => 'datetime', 'paid_at' => 'datetime',
'failed_at' => 'datetime', 'metadata' => 'array',
];
}
public function account()
{
return $this->belongsTo(PaymentGatewayAccount::class, 'payment_gateway_account_id');
}
public function tenant()
{
return $this->belongsTo(Tenant::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
public function customer()
{
return $this->belongsTo(Customer::class);
}
public function invoice()
{
return $this->belongsTo(Invoice::class);
}
public function attempts()
{
return $this->hasMany(PaymentAttempt::class);
}
}
+15
View File
@@ -0,0 +1,15 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class PaymentWebhookLog extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return ['signature_valid' => 'boolean', 'headers' => 'array', 'payload' => 'array', 'processed_at' => 'datetime'];
}
}
+10
View File
@@ -14,4 +14,14 @@ class Tenant extends Model
'address',
'status',
];
public function wallets()
{
return $this->morphMany(Wallet::class, 'owner');
}
public function paymentSetting()
{
return $this->hasOne(TenantPaymentSetting::class);
}
}
+30
View File
@@ -0,0 +1,30 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class TenantPaymentSetting extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return ['enabled_methods' => 'array'];
}
public function tenant()
{
return $this->belongsTo(Tenant::class);
}
public function tenantGateway()
{
return $this->belongsTo(PaymentGatewayAccount::class, 'tenant_gateway_account_id');
}
public function platformGateway()
{
return $this->belongsTo(PaymentGatewayAccount::class, 'platform_gateway_account_id');
}
}
+15
View File
@@ -0,0 +1,15 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class TopologyConnectionRule extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return ['allowed' => 'boolean'];
}
}
+34
View File
@@ -0,0 +1,34 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class TopologyCustomerConnection extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return [
'connected_at' => 'datetime',
'disconnected_at' => 'datetime',
'metadata' => 'array',
];
}
public function customer()
{
return $this->belongsTo(Customer::class);
}
public function odpNode()
{
return $this->belongsTo(TopologyNode::class, 'odp_node_id');
}
public function odpPort()
{
return $this->belongsTo(TopologyPort::class, 'odp_port_id');
}
}
+24
View File
@@ -0,0 +1,24 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class TopologyDeviceType extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return [
'can_have_ports' => 'boolean',
'can_have_splitters' => 'boolean',
'is_system' => 'boolean',
];
}
public function nodes()
{
return $this->hasMany(TopologyNode::class, 'device_type_id');
}
}
+47
View File
@@ -0,0 +1,47 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class TopologyLink extends Model
{
use SoftDeletes;
protected $guarded = ['id'];
protected function casts(): array
{
return [
'path_geojson' => 'array',
'metadata' => 'array',
'installed_at' => 'date',
];
}
public function tenant()
{
return $this->belongsTo(Tenant::class);
}
public function sourceNode()
{
return $this->belongsTo(TopologyNode::class, 'source_node_id');
}
public function targetNode()
{
return $this->belongsTo(TopologyNode::class, 'target_node_id');
}
public function sourcePort()
{
return $this->belongsTo(TopologyPort::class, 'source_port_id');
}
public function targetPort()
{
return $this->belongsTo(TopologyPort::class, 'target_port_id');
}
}
+53
View File
@@ -0,0 +1,53 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class TopologyNode extends Model
{
use SoftDeletes;
protected $guarded = ['id'];
protected function casts(): array
{
return [
'latitude' => 'decimal:7',
'longitude' => 'decimal:7',
'installed_at' => 'date',
'metadata' => 'array',
];
}
public function tenant()
{
return $this->belongsTo(Tenant::class);
}
public function deviceType()
{
return $this->belongsTo(TopologyDeviceType::class, 'device_type_id');
}
public function parent()
{
return $this->belongsTo(self::class, 'parent_node_id');
}
public function ports()
{
return $this->hasMany(TopologyPort::class, 'node_id')->orderBy('port_number');
}
public function outgoingLinks()
{
return $this->hasMany(TopologyLink::class, 'source_node_id');
}
public function incomingLinks()
{
return $this->hasMany(TopologyLink::class, 'target_node_id');
}
}
+20
View File
@@ -0,0 +1,20 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class TopologyPort extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return ['metadata' => 'array'];
}
public function node()
{
return $this->belongsTo(TopologyNode::class, 'node_id');
}
}
+15
View File
@@ -0,0 +1,15 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class TopologySplitter extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return ['metadata' => 'array'];
}
}
+10
View File
@@ -102,6 +102,16 @@ class User extends Authenticatable
return $this->hasMany(UserMenuGroup::class, 'user_id');
}
public function userNotifications()
{
return $this->hasMany(UserNotification::class, 'user_id');
}
public function wallets()
{
return $this->morphMany(Wallet::class, 'owner');
}
public function isMasterAdmin(): bool
{
return $this->is_master || $this->access_level === UserAccessLevel::MASTER_ADMIN;
+17
View File
@@ -0,0 +1,17 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class UserNotification extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return ['read_at' => 'datetime'];
}
public function user() { return $this->belongsTo(User::class); }
}
+25
View File
@@ -0,0 +1,25 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Wallet extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return ['available_balance' => 'decimal:2', 'pending_balance' => 'decimal:2', 'locked_balance' => 'decimal:2'];
}
public function owner()
{
return $this->morphTo();
}
public function ledgerEntries()
{
return $this->hasMany(WalletLedgerEntry::class);
}
}
+25
View File
@@ -0,0 +1,25 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class WalletLedgerEntry extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return ['amount' => 'decimal:2', 'balance_before' => 'decimal:2', 'balance_after' => 'decimal:2'];
}
public function wallet()
{
return $this->belongsTo(Wallet::class);
}
public function transaction()
{
return $this->belongsTo(WalletTransaction::class, 'wallet_transaction_id');
}
}
+25
View File
@@ -0,0 +1,25 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class WalletTransaction extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return ['amount' => 'decimal:2', 'fee' => 'decimal:2', 'metadata' => 'array', 'completed_at' => 'datetime'];
}
public function entries()
{
return $this->hasMany(WalletLedgerEntry::class);
}
public function payment()
{
return $this->belongsTo(PaymentTransaction::class, 'payment_transaction_id');
}
}
+20
View File
@@ -0,0 +1,20 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class WalletWithdrawal extends Model
{
protected $guarded = ['id'];
protected function casts(): array
{
return ['amount' => 'decimal:2', 'fee' => 'decimal:2', 'processed_at' => 'datetime'];
}
public function wallet()
{
return $this->belongsTo(Wallet::class);
}
}