# Quick Start Guide ## Gadai Mulia Collection Broadcast Integration --- ## โšก 5-Minute Setup ### Prerequisites - PostgreSQL database access - Sopiga API credentials (token) - Go 1.16+ (for worker deployment) ### Step 1: Create Database Schema (2 minutes) ```bash # Run SQL schema psql -U postgres -h localhost -d gadai_mulia < gadai_collection_broadcast_simplified_schema.sql ``` Verify schema created: ```sql \dt collection_broadcasts.* -- Should show: sopiga_template_config, template_variable_mapping, sopiga_collar_config, broadcast_staging, etc ``` ### Step 2: Setup Sopiga Template (2 minutes) **In Sopiga UI or API:** ```bash # Create template curl -X POST https://omnix.promas.site/api/client/template \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "template_name": "Collection Invoice", "channel": "waba", "variables": [ {"name": "Nama", "type": "string"}, {"name": "TotalTagihan", "type": "integer"}, {"name": "TanggalJatuhTempo", "type": "date"} ] }' # Response: {"data": {"id": 2}} # Create collar curl -X POST https://omnix.promas.site/api/client/collar \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "judul_broadcast": "Invoice May 2026", "template_id": 2 }' # Response: {"data": {"id": 70}} ``` Note down: - `template_id = 2` - `collar_id = 70` ### Step 3: Register in Database (1 minute) **Connect to PostgreSQL:** ```bash psql -U postgres -h localhost -d gadai_mulia ``` **Insert template:** ```sql INSERT INTO collection_broadcasts.sopiga_template_config (template_name, sopiga_template_id, channel, template_type, description) VALUES ('Collection Invoice May 2026', 2, 'waba', 'utility', 'Invoice bulanan untuk collection'); ``` **Insert variable mappings (URUTAN PENTING!):** ```sql INSERT INTO collection_broadcasts.template_variable_mapping (sopiga_template_id, variable_order, sopiga_variable_name, variable_type, db_field_source, is_required, example_value) VALUES (2, 1, 'Nama', 'string', 'nasabah_nama', TRUE, 'Budi Santoso'), (2, 2, 'TotalTagihan', 'integer', 'nominal_tagihan', TRUE, '1500000'), (2, 3, 'TanggalJatuhTempo', 'date', 'tanggal_tempo', TRUE, '2026-06-30'); ``` **Insert collar config:** ```sql INSERT INTO collection_broadcasts.sopiga_collar_config (broadcast_name, sopiga_collar_id, sopiga_template_id, status, description) VALUES ('Collection Invoices May 2026', 70, 2, 'open', 'Broadcast collar untuk collection invoice bulanan Mei 2026'); ``` **Verify setup:** ```sql SELECT * FROM collection_broadcasts.v_template_variables_ordered WHERE sopiga_template_id = 2; -- Should show 3 rows with order 1, 2, 3 ``` ### Step 4: Deploy Worker (1 minute) ```bash # Build go build -o collection_broadcast_worker collection_broadcast_worker_simplified.go # Run with environment variables export DB_HOST=localhost export DB_PORT=5432 export DB_NAME=gadai_mulia export DB_USER=postgres export DB_PASSWORD=xxx export SOPIGA_BASE_URL=https://omnix.promas.site export SOPIGA_TOKEN=your_api_token ./collection_broadcast_worker # Output: Collection Broadcast Worker started ``` --- ## ๐Ÿงช Test It ### Insert Test Record ```sql -- Insert to broadcast_staging INSERT INTO collection_broadcasts.broadcast_staging (sopiga_collar_id, sopiga_template_id, message_payload, status) VALUES ( 70, 2, '{"nasabah_nama": "Budi Santoso", "nasabah_phone": "6281234567890", "nominal_tagihan": 1500000, "tanggal_tempo": "2026-06-30", "invoice_pdf_url": "https://storage.gadai.com/invoices/inv-001.pdf"}', 'pending' ); -- Check it's pending SELECT id, status, created_at FROM collection_broadcasts.broadcast_staging WHERE status='pending'; ``` ### Wait 30 seconds Worker polls every 30 seconds. Check status: ```sql SELECT id, status, sopiga_recipient_detail_id, dispatched_at, error_message FROM collection_broadcasts.broadcast_staging WHERE id = 1; -- Should show: status='dispatched', sopiga_recipient_detail_id=512 ``` ### Check WhatsApp Delivery After 5 minutes, check sync job: ```sql SELECT id, status, last_status_from_sopiga, delivered_at FROM collection_broadcasts.broadcast_staging WHERE id = 1; -- Should show: status='delivered', delivered_at= ``` --- ## ๐Ÿ“Š Monitor ### Check Delivery Rate ```sql SELECT * FROM collection_broadcasts.v_delivery_rate_24h; -- delivery_rate_percent should be > 95% ``` ### Check Failed Records ```sql SELECT * FROM collection_broadcasts.v_failed_records_24h; -- Should be empty or < 5% ``` ### Check Collar Summary ```sql SELECT * FROM collection_broadcasts.v_collar_summary; -- See totals per collar, delivery rates ``` --- ## โž• Add New Template (5 minutes) When Sopiga template changes (e.g., add `NoKontrak` field): ### 1. Create in Sopiga ```bash # template_id = 3, collar_id = 71 ``` ### 2. Register in Database ```sql -- Template INSERT INTO sopiga_template_config (template_name, sopiga_template_id, ...) VALUES ('Collection Invoice Extended', 3, ...); -- Variables (URUTAN PENTING!) INSERT INTO template_variable_mapping (sopiga_template_id, variable_order, sopiga_variable_name, variable_type, db_field_source, is_required) VALUES (3, 1, 'Nama', 'string', 'nasabah_nama', TRUE), (3, 2, 'NoKontrak', 'string', 'contract_no', TRUE), โ† NEW (3, 3, 'TotalTagihan', 'integer', 'nominal_tagihan', TRUE), (3, 4, 'TanggalJatuhTempo', 'date', 'tanggal_tempo', TRUE); -- Collar INSERT INTO sopiga_collar_config (broadcast_name, sopiga_collar_id, sopiga_template_id, status) VALUES ('Collection Invoices June 2026', 71, 3, 'open'); ``` ### 3. NO code redeploy needed โœ… Worker automatically picks up new template on next poll. --- ## ๐Ÿš€ Gadai Service Integration **How Gadai calls this:** ```go import "database/sql" import "encoding/json" db, _ := sql.Open("postgres", "postgres://user:pass@localhost/gadai_mulia") payload := map[string]interface{}{ "nasabah_nama": "Budi Santoso", "nasabah_phone": "6281234567890", "nominal_tagihan": 1500000.0, "tanggal_tempo": "2026-06-30", "invoice_pdf_url": "https://storage.gadai.com/invoices/inv-001.pdf", "contract_no": "GAD-2026-001", } payloadJSON, _ := json.Marshal(payload) db.Exec(` INSERT INTO collection_broadcasts.broadcast_staging (sopiga_collar_id, sopiga_template_id, message_payload, status) VALUES ($1, $2, $3, 'pending') `, 70, 2, payloadJSON) // Done! Worker picks it up automatically ``` --- ## ๐Ÿ› Troubleshooting ### "Message format wrong" โ†’ Check template variable order matches Sopiga: ```sql SELECT variable_order, sopiga_variable_name FROM template_variable_mapping WHERE sopiga_template_id=2 ORDER BY variable_order; ``` ### "Record stuck in pending" โ†’ Check worker logs: ```bash # Look for errors in stdout/stderr # Check DB connection psql -U postgres -h localhost -d gadai_mulia -c "SELECT 1;" ``` ### "Sopiga API errors" โ†’ Check token and URL: ```bash curl -X GET https://omnix.promas.site/api/client/collar/list \ -H "Authorization: Bearer YOUR_TOKEN" ``` --- ## โœ… Checklist - [ ] Schema created - [ ] Sopiga template created (note template_id) - [ ] Sopiga collar created (note collar_id) - [ ] Database populated with template_id, collar_id - [ ] Variable mappings inserted (check order!) - [ ] Worker deployed and running - [ ] Test record inserted - [ ] Record moved to 'dispatched' after 30s - [ ] Record moved to 'delivered' after 5 min - [ ] WhatsApp message received on test phone --- ## ๐Ÿ“ž Quick Reference **Database:** - Schema: `collection_broadcasts` - Main table: `broadcast_staging` - Config tables: `sopiga_template_config`, `template_variable_mapping`, `sopiga_collar_config` **Sopiga URLs:** - Base: `https://omnix.promas.site` - Create template: POST `/api/client/template` - Create collar: POST `/api/client/collar` - Add recipient: POST `/api/client/collar/add-recipient` - Get recipient detail: GET `/api/client/collar/add-recipient/{id}/detail` **Worker:** - Poll interval: 30 seconds (pending records) - Status sync: 5 minutes (delivery status) - Max retries: 3 (exponential backoff: 1s, 2s, 4s) --- **Ready to go! ๐Ÿš€**