bangsamu / master
Clay menggunakan master
Requires
Requires (Dev)
- orchestra/testbench: ^9.0|^10.0
- phpunit/phpunit: ^10.5|^11.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-master
- v2.4.2
- v2.4.1
- v2.4.0
- v2.3.2
- v2.3.1
- v2.3.0
- v2.2.3
- v2.2.2
- v2.2.1
- v2.2.0
- v2.1.1
- v2.1.0
- v2.0.3
- v2.0.2
- v2.0.1
- v2.0.0
- v1.2.13
- v1.2.12
- v1.2.11
- v1.2.10
- v1.2.9
- v1.2.8
- v1.2.7
- v1.2.6
- v1.2.5
- v1.2.4
- v1.2.3
- v1.2.2
- v1.2.1
- v1.2.0
- v1.1.100
- v1.1.99
- v1.1.98
- v1.1.97
- v1.1.96
- v1.1.95
- v1.1.94
- v1.1.93
- v1.1.92
- v1.1.91
- v1.1.90
- v1.1.89
- v1.1.88
- v1.1.87
- v1.1.86
- v1.1.85
- v1.1.84
- v1.1.83
- v1.1.82
- v1.1.81
- v1.1.80
- v1.1.79
- v1.1.78
- v1.1.77
- v1.1.76
- v1.1.75
- v1.1.74
- v1.1.73
- v1.1.72
- v1.1.71
- v1.1.70
- v1.1.69
- v1.1.68
- v1.1.67
- v1.1.66
- v1.1.65
- v1.1.64
- v1.1.63
- v1.1.62
- v1.1.61
- v1.1.60
- v1.1.59
- v1.1.58
- v1.1.57
- v1.1.56
- v1.1.55
- v1.1.54
- v1.1.53
- v1.1.52
- v1.1.51
- v1.1.50
- v1.1.49
- v1.1.48
- v1.1.47
- v1.1.46
- v1.1.45
- v1.1.44
- v1.1.43
- v1.1.42
- v1.1.41
- v1.1.40
- v1.1.39
- v1.1.38
- v1.1.37
- v1.1.36
- v1.1.35
- v1.1.34
- v1.1.33
- v1.1.32
- v1.1.31
- v1.1.30
- v1.1.29
- v1.1.28
- v1.1.27
- v1.1.26
- v1.1.25
- v1.1.24
- v1.1.23
- v1.1.22
- v1.1.21
- v1.1.20
- v1.1.18
- v1.1.17
- v1.1.16
- v1.1.15
- v1.1.14
- v1.1.13
- v1.1.12
- v1.1.11
- v1.1.10
- v1.1.9
- v1.1.8
- v1.1.7
- v1.1.6
- v1.1.5
- v1.1.4
- v1.1.3
- v1.1.2
- v1.1.1
- v1.1.0
- v1.0.99
- v1.0.98
- v1.0.97
- v1.0.96
- v1.0.95
- v1.0.94
- v1.0.93
- v1.0.92
- v1.0.91
- v1.0.90
- v1.0.89
- v1.0.86
- v1.0.85
- v1.0.84
- v1.0.83
- v1.0.82
- v1.0.81
- v1.0.80
- v1.0.79
- v1.0.78
- v1.0.77
- v1.0.76
- v1.0.75
- v1.0.74
- v1.0.73
- v1.0.72
- v1.0.71
- v1.0.70
- v1.0.69
- v1.0.68
- v1.0.67
- v1.0.66
- v1.0.65
- v1.0.64
- v1.0.63
- v1.0.62
- v1.0.61
- v1.0.60
- v1.0.59
- v1.0.58
- v1.0.57
- v1.0.56
- v1.0.55
- v1.0.54
- v1.0.53
- v1.0.52
- v1.0.51
- v1.0.50
- v1.0.49
- v1.0.48
- v1.0.47
- v1.0.46
- v1.0.45
- v1.0.44
- v1.0.43
- v1.0.42
- v1.0.41
- v1.0.40
- v1.0.39
- v1.0.38
- v1.0.37
- v1.0.36
- v1.0.35
- v1.0.34
- v1.0.33
- v1.0.32
- v1.0.31
- v1.0.30
- v1.0.29
- v1.0.28
- v1.0.27
- v1.0.26
- v1.0.25
- v1.0.24
- v1.0.23
- v1.0.22
- v1.0.21
- v1.0.20
- v1.0.19
- v1.0.18
- v1.0.17
- v1.0.16
- v1.0.15
- v1.0.14
- v1.0.13
- v1.0.12
- v1.0.11
- v1.0.10
- v1.0.9
- v1.0.8
- v1.0.6
- v1.0.5.2
- v1.0.5.1
- v1.0.5
- v1.0.4
- v1.0.3
- v1.0.3-A
- v1.0.2
- v1.0.1
This package is auto-updated.
Last update: 2026-10-23 07:43:51 UTC
README
Paket terpusat Master Data untuk ekosistem aplikasi berbasis Laravel.
Fitur Utama
- Cakupan 15 Tabel Master Data:
master_item_code(item_code)master_category(category_code)master_company(company_code)master_department(department_code)master_employee(no_ktpsebagai kode identitas utama unik)master_item_group(item_group_code)master_job_position(position_code)master_location(loc_code)master_pca(pca_code)master_project(project_code)master_project_detail(project_code_client)master_status(kode)master_uom(uom_code)master_vendor(vendor_code)master_vendor_contact(vendor_contact_name)
- Real-Time WebSocket Broadcasting (Senada Reverb Hub): Setiap perubahan data master (
created,updated,deleted) otomatis di-broadcast secara real-time ke channelmasterdata.itemsdengan single unified eventMasterDataUpdated(tanpa duplikasi notifikasi). - FCM-Like Catch-Up Sync (Tahan Offline/App Mati):
- Jika aplikasi klien atau browser pengguna sempat offline atau server mati saat broadcast dikirimkan, klien tidak akan kehilangan data.
- Checkpoint ID broadcast terakhir tersimpan aman di tabel
dashboard_settings(key='last_synced_broadcast_id'). - Paket secara otomatis melakukan validasi dan membuat tabel
dashboard_settingsjika belum ada di database lokal aplikasi. - Begitu koneksi WebSocket tersambung kembali, frontend secara otomatis memanggil
/master-sync/catch-upuntuk mengambil seluruh update yang terlewat. - Tersedia juga CLI command:
php artisan master:catch-up.
- Memory-Safe Data Cloning (
MasterDataSyncService): Sinkronisasi data bertahap (chunking 250 rows) dengan MySQLupsertuntuk menjaga tabel lokal tetap menjadi clone identik dari database master (db_master). - Whitelist Sinkronisasi & Penekanan Notifikasi (Notification Suppression):
- Filter Tabel Lokal & Prefix
master_*: Hanya tabel berawalanmaster_*yang benar-benar ada di database lokal aplikasi yang memenuhi syarat untuk disinkronkan. Tabel di luar database lokal atau tabel cadangan (*OLD,*dump*) otomatis diabaikan. - Penyimpanan di
dashboard_settings:- key:
sync_allowed_master_tables - group:
senada_sync - type:
json - label:
Allowed Master Data Sync Tables - value: JSON array daftar tabel
master_*yang diizinkan untuk disinkronkan (misal:["master_category","master_company","master_department","master_employee","master_item_code", ...]). - options: JSON array seluruh tabel
master_*yang terdeteksi di database lokal. - Auto-Discovery: Jika konfigurasi belum ada, sistem secara otomatis memindai database lokal dan menginisialisasi tabel-tabel
master_*yang valid kedashboard_settings.
- key:
- Silent Ignore (Tanpa Popup Toast): Jika event broadcast diterima dari Senada untuk tabel yang tidak ada di database lokal klien atau tidak diaktifkan di
dashboard_settings, klien mengabaikan event tersebut secara hening tanpa memunculkan popup toast notifikasi dan tanpa request fetch yang sia-sia karena tidak berdampak pada aplikasi klien. - Respon Backend Aman: Endpoint sinkronisasi mengembalikan
200 OKdengan flagskipped: true(bukan error 422).
- Filter Tabel Lokal & Prefix
- Built-in Endpoints:
POST /master-sync/sync(Sinkronisasi universal semua master table)POST /master-sync/sync-items(Alias kompatibel untuk item code)GET|POST /master-sync/catch-up(Catch-up sync event yang terlewat)GET /master-sync/allowed-tables(Daftar whitelist tabel yang diizinkan untuk disinkronkan)POST /master-sync/channel-auth(Otorisasi channel privat browser)
Token Launch Viewer Annotation (opt-in)
Link viewer annotation tanpa token statis md5(email) dan tanpa cek cookie lintas-origin: route
GET /annotation/open membuat token terenkripsi yang terikat ke session user, dicek server-side oleh
api/getcurrentuser, api/getSignature, dan api/getParaf. Default ANNOTATION_TOKEN_MODE=legacy
(perilaku lama). Pakai helper annotation_launch_url($fileUrl, $callback) di app. Detail dan langkah
aktivasi: docs/annotation-launch-token.md.
Filter Dropdown Master dari Setting (opt-in)
MASTER_SELECT2_SETTING_FILTER=true (config MasterCrudConfig.SELECT2_SETTING_FILTER, default false) membuat
api/getmaster_*byparams (sumber dropdown select2) memakai filter yang sama dengan list master: baris tabel
setting dengan category = nama tabel (fallback dashboard_settings.group), name/key = kolom, value = daftar
nilai dipisah koma; antar setting digabung OR. Lookup nilai terpilih (?id=) tidak difilter, jadi data lama tetap tampil.
Konfigurasi Database (config/database.php)
Pastikan koneksi db_master telah didaftarkan di aplikasi client:
'db_master' => [ 'driver' => 'mysql', 'url' => env('DATABASE_URL_MASTER'), 'host' => env('DB_HOST_MASTER', '192.168.20.187'), 'port' => env('DB_PORT_MASTER', '3306'), 'database' => env('DB_DATABASE_MASTER', 'master'), 'username' => env('DB_USERNAME_MASTER', 'user'), 'password' => env('DB_PASSWORD_MASTER', 'pass'), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'strict' => false, ],
Konfigurasi Lingkungan (.env)
# ============================================================================== # SENADA REVERB WEBSOCKET & MASTER SYNC (SISI CLIENT) # ============================================================================== # Endpoint Senada Broadcast Hub SENADA_URL=http://192.168.20.187:9029 SENADA_API_KEY=snd_masterdata_key_secret SENADA_BROADCAST_ACTIVE=true # Kredensial Reverb WebSocket (Wajib untuk otorisasi channel private) REVERB_APP_ID=senada_app REVERB_APP_KEY=senada_hub_key REVERB_APP_SECRET=senada_hub_secret REVERB_HOST="192.168.20.187" REVERB_PORT=9029 REVERB_SCHEME=http # ============================================================================== # JADWAL OTOMATIS & DISTRIBUTED LOCK SINKRONISASI MASTER # ============================================================================== # Mengaktifkan/menonaktifkan auto-schedule catch-up di Laravel Scheduler (true/false) MASTER_SYNC_SCHEDULE_ENABLED=true # Frekuensi jadwal: hourly (default 1 jam), everyThirtyMinutes, everyTwoHours, daily, atau cron string "0 * * * *" MASTER_SYNC_SCHEDULE_INTERVAL=hourly # Maksimal jumlah event broadcast yang disinkronkan per siklus MASTER_SYNC_SCHEDULE_LIMIT=50 # Durasi masa aktif Central Master Sync Lock (detik, default: 300 = 5 menit, maks 3600 = 1 jam) MASTER_SYNC_LOCK_TTL=300 # Cooldown pencegah banjir sync saat user login / buka tab baru di browser (detik, default: 300 = 5 menit) MASTER_SYNC_BROWSER_COOLDOWN=300
Cara Penggunaan di Aplikasi Client
1. Memasang Listener Real-time di View
Cukup tambahkan komponen Blade ini di layout utama aplikasi (seperti di layouts/app.blade.php atau components/layouts/app.blade.php):
<x-master::broadcast-listener />
Komponen ini akan secara otomatis:
- Menginisiasi koneksi ke Senada WebSocket Reverb.
- Saat koneksi terhubung (
connected), otomatis memanggil catch-up ke Senada dengan proteksi Local Cooldown & Multi-Tab Debounce (localStorage), sehingga saat 50 user login bersamaan tidak terjadi banjir request ke database master. - Berlangganan ke channel
masterdata.itemsdan channel privat pengguna (private-user.{email}). - Menampilkan toast notifikasi modern saat master data berubah atau saat catch-up selesai.
- Melakukan sinkronisasi database lokal ke
db_mastervia endpoint bawaan paket/master-sync/sync. - Merefresh DataTable aktif secara otomatis jika ada di halaman.
- Me-reload halaman jika pengguna sedang membuka formulir/detail dari item yang bersangkutan.
2. Penjadwalan Otomatis & Central Distributed Lock
A. Penjadwalan Otomatis (Auto-Scheduler)
Paket secara otomatis mendaftarkan task php artisan master:catch-up ke Laravel Scheduler tanpa perlu mengedit file app/Console/Kernel.php secara manual.
Pastikan cron server aplikasi Anda sudah menjalankan scheduler standar Laravel:
* * * * * cd /path/to/app && php artisan schedule:run >> /dev/null 2>&1
Frekuensi eksekusi dapat diatur bebas via .env:
MASTER_SYNC_SCHEDULE_INTERVAL=hourly(Default: setiap 1 jam)MASTER_SYNC_SCHEDULE_INTERVAL=everyThirtyMinutes(Setiap 30 menit)MASTER_SYNC_SCHEDULE_INTERVAL=everyTwoHours(Setiap 2 jam)MASTER_SYNC_SCHEDULE_INTERVAL="0 */4 * * *"(Custom cron: setiap 4 jam)
B. Central Distributed Lock (Perlindungan DB Master Lintas Aplikasi)
Untuk mencegah lonjakan koneksi dan perlambatan pada Database Master ketika banyak aplikasi (Clay, MCU, Warehouse, dll.) menjalankan sync secara bersamaan:
- Single-Sync Guarantee: Sebelum melakukan sinkronisasi dari
db_master, aplikasi meminta Central Lock ke Senada Hub. Hanya 1 aplikasi yang diizinkan melakukan sinkronisasi dalam satu waktu. - Auto-Postpone yang Ramah: Jika aplikasi lain sedang melakukan sinkronisasi, proses sync ditunda secara elegan tanpa membebani koneksi DB Master.
- Anti-Stuck & Auto-Expire: Lock memiliki TTL otomatis (default 5 menit / diset via
MASTER_SYNC_LOCK_TTL). Jika aplikasi mati mendadak saat proses sync, lock otomatis kadaluarsa sehingga proses sync berikutnya tidak akan macet selamanya. - Force Override: Tersedia opsi
--force-lockuntuk memecah lock yang dicurigai macet.
3. Perintah Artisan Catch-Up & Lock Management
A. Catch-Up Sync
# Sinkronkan semua broadcast yang terlewat (dilindungi Central Lock) php artisan master:catch-up # Cek ID checkpoint sinkronisasi saat ini php artisan master:catch-up --info # Paksa catch-up dan override lock jika lock terindikasi macet php artisan master:catch-up --force-lock # Jalankan dengan parameter checkpoint & limit tertentu php artisan master:catch-up --since=80 --limit=50
B. Inspeksi & Rilis Central Lock (master:sync-lock)
# Cek apakah saat ini ada aplikasi yang sedang mengunci DB Master php artisan master:sync-lock --status # Paksa rilis lock yang macet di Senada Hub php artisan master:sync-lock --release # Manual lock untuk kebutuhan maintenance khusus php artisan master:sync-lock --acquire --ttl=600
3. Memanggil Broadcast Secara Manual dari Kode
Setiap Model di bawah namespace Bangsamu\Master\Models\* sudah terpasang trait BroadcastsMasterChanges secara otomatis. Namun jika ingin memanggil secara manual:
use Bangsamu\Master\Services\MasterBroadcastService; // Broadcast perubahan entitas master apapun $broadcastService = app(MasterBroadcastService::class); $broadcastService->broadcastTableChange('master_category', $categoryModel, 'updated');
4. Memanggil Sinkronisasi Manual dari Kode
use Bangsamu\Master\Services\MasterDataSyncService; $syncService = app(MasterDataSyncService::class); // 1. Sinkronkan tabel tertentu berdasarkan ID $result = $syncService->syncTable('master_employee', 12, 450, 'updated'); // 2. Jalankan Catch-Up event terlewat $catchUpResult = $syncService->catchUpMissedBroadcasts();
5. Optimasi Bulk Import (10.000+ Data) & Single Summary Broadcast
Untuk mencegah Broadcast Storm (di mana pengunggahan 10.000 data memicu 10.000 panggilan HTTP ke Senada, menyebabkan HTTP 429 Rate Limit dan browser freeze):
- Suppression Selama Proses Import:
Semua per-row broadcast dinonaktifkan sementara via
MasterBroadcastService::withoutBroadcasting(...)dan event hookBeforeImport. - 1 Kali Ringkasan Broadcast di Akhir Batch:
Setelah seluruh sheet dan chunk selesai dibaca, dikirimkan 1 kali ringkasan event
MasterDataUpdatedke Senada:{ "table": "master_item_code", "action": "created", "id": 26500, "max_id": 26500, "batch_count": 10000, "is_batch": true, "identifier": "Batch Import (10.000 data)", "item_code": "Batch Import (10.000 data)" } - Cloning Otomatis Sisi Klien:
Aplikasi klien yang menerima event ini mendeteksi bahwa
max_idmaster (misal: 26.500) melompat melampauimax_idlokal (misal: 16.500). Klien otomatis mengeksekusisyncRange()dengan batch 250 record secara langsung daridb_mastervia MySQL upsert. - Trait
HandlesBatchImportBroadcast: Semua class Import (Item Code, Category, Department, Employee, Item Group, Location, PCA, Project, UoM, Vendor) mengimplementasikan traitHandlesBatchImportBroadcastsertaWithChunkReading(chunk 1.000) dan koleksi lookup in-memory (memoized) untuk menghindari N+1 kueri ke database master.
6. API Sinkronisasi Status User (Active / Inactive) Lokal
API ini disediakan untuk menerima webhook/cURL dari aplikasi master (master-data via App\Services\UserStatusSyncService) guna mengubah status user (is_active) menjadi aktif (1) atau inaktif (0) pada database default lokal (tabel master_user), bukan pada koneksi db_master.
Endpoints
| Method | Endpoint | Deskripsi |
|---|---|---|
GET / POST |
/api/user/status |
Endpoint Utama Sinkronisasi status user |
GET / POST |
/api/user/set-status |
Endpoint alias |
GET / POST |
/api/setUser.php |
Kompatibilitas URL legacy API |
GET / POST |
/setUser.php |
Kompatibilitas URL legacy root |
GET |
/api/users |
Daftar user lokal (Cursor Paginated) |
GET |
/api/users/{id} |
Detail user lokal |
Parameter Request
| Parameter | Tipe | Wajib | Keterangan |
|---|---|---|---|
email_id |
string |
Ya | Alamat email user yang akan disinkronkan. Menerima juga alias: email, person_id, person_email. |
status |
int/string |
Ya | 1 / active / true untuk Aktif, 0 / inactive / false untuk Inaktif. Menerima juga alias: active. |
token |
string |
Ya | Token keamanan HMAC SHA-256 (atau fallback MD5) yang dihasilkan dari api_token($email_id) menggunakan SsoConfig.main.KEY, atau static token. Dapat juga dikirim via header Authorization: Bearer <token>. |
Contoh Request (cURL)
A. GET Request (Sesuai cURL UserStatusSyncService di master-data):
curl -X GET "http://clay-domain/api/user/status?email_id=user@example.com&status=1&token=45be95886cd458871369dba552ee3fd9c82bb578ff9863131ab4d2bbe40b52e7"
B. POST Request dengan JSON Body:
curl -X POST "http://clay-domain/api/user/status" \ -H "Content-Type: application/json" \ -d '{ "email_id": "user@example.com", "status": 0, "token": "45be95886cd458871369dba552ee3fd9c82bb578ff9863131ab4d2bbe40b52e7" }'
Format Response
Sukses (HTTP 200 OK)
{
"status": true,
"code": 200,
"message": "User 'user@example.com' status successfully set to active.",
"data": {
"id": 12,
"name": "Bagas Alwi",
"email": "user@example.com",
"previous_status": 0,
"current_status": 1,
"status_label": "active"
}
}
Token Tidak Valid (HTTP 401 Unauthorized)
{
"status": false,
"code": 401,
"message": "Unauthorized: Invalid or missing token."
}
User Tidak Ditemukan di DB Lokal (HTTP 404 Not Found)
{
"status": false,
"code": 404,
"message": "User not found for 'unknown@example.com'."
}
Validasi Gagal (HTTP 422 Unprocessable Entity)
{
"status": false,
"code": 422,
"message": "User identifier (email_id) is required.",
"errors": {
"email_id": [
"User identifier (email_id) is required."
]
}
}
Logging & Tracing Aktivitas
Semua aktivitas request hit, penolakan token, validasi gagal, user not found, dan update status berhasil dicatat secara spesifik ke file log harian khusus:
- Lokasi File:
storage/logs/user-sync-YYYY-MM-DD.log(dan terduplikasi distorage/logs/laravel-YYYY-MM-DD.log). - Live Trace Command:
tail -f storage/logs/user-sync-$(date +%Y-%m-%d).log