Skip to content

Skema Database & ERD

Sistem memakai PostgreSQL dengan ORM Sequelize 6. Model dimuat otomatis dari models/*.js oleh models/index.js, dan asosiasi didaftarkan via fungsi associate() di tiap model.

Konvensi umum

AspekDetail
Nama tabelTidak ada tableName eksplisit; Sequelize memluralkan nama model (mis. TransEmailLogTransEmailLogs).
Primary keyidINTEGER, auto-increment.
TimestampscreatedAt, updatedAt (DATE) ada di semua tabel (default Sequelize).
UUIDBanyak tabel punya kolom uuid dengan default uuid_generate_v4() (ekstensi uuid-ossp).

Entity Relationship Diagram

Entitas pusat

EntitasPeranKoneksi utama
TransCompaniesTenant/pelanggan (hub)domain, kontak, relay, subscription, invoice, config, dokumen
UsersAkun penggunaterhubung ke company via TransCompanyContacts; menerima notifikasi
TransCompanyDomainsDomain pengirimparent dari TransEmailLogs & agregat TViewCompanyMailUsages
TransCompanySubscriptionsLangganan aktifterkait package; menggerakkan quota count
TransCompanyInvoicesFaktur (Zoho/Xendit)punya payment & tax invoice
TransEmailLogLog per pesanterkait domain + map host
TransServicePackagesKatalog produkdilanggan company
TransCompanyAccountRelaysKredensial relay Zimbraone-to-one dengan company

Tabel: Auth & Admin

Usersmodels/users.js

KolomTipeKeterangan
idINTEGER PK
uuidUUID
nameSTRING
emailSTRING
passwordSTRINGdi-hash bcrypt saat set
resetPasswordTokenTEXT
verificationTokenTEXT
isPrimaryBOOLEAN
statusENUMactive, inactive, trashed

Relasi: hasOne TransCompanyContacts; hasMany TransUserEmailNotifications, TransUserNotifications.

Adminsmodels/admins.js

KolomTipeKeterangan
idINTEGER PK
uuidSTRING(migrasi: UUID)
name, email, passwordSTRINGpassword di-hash bcrypt
profilePictureTEXT
roleIdINTEGERFK → AdminRoles
resetPasswordToken, verificationTokenTEXT
statusENUMactive, inactive, trashed

Relasi: belongsTo AdminRoles.

AdminRolesmodels/adminroles.js

KolomTipe
idINTEGER PK
uuidUUID
nameSTRING

Relasi: hasMany Admins.

AdminLogmodels/adminlogs.js

KolomTipeKeterangan
idINTEGER PK
uuidUUID
adminIdINTEGERFK → Admins
activitySTRING
logDescriptionSTRING

Relasi: belongsTo Admins.

BlacklistTokenmodels/blacklisttoken.js

KolomTipeKeterangan
idINTEGER PK
tokenTEXTrefresh token yang dicabut
expiryDateDATE

Tabel: Company Core & Contacts

TransCompaniesmodels/transcompanies.js

KolomTipeKeterangan
idINTEGER PK
uuidUUID
idCompanyZoho, idContactZoho, idContactPersonsAktivaSTRINGID referensi Zoho
name, website, address, phoneNumberSTRINGprofil
relayAddressSTRING
npwp, npwpLocationSTRING/TEXTdata pajak
profilePictureTEXT
roleUserPrimarySTRING
estimateUserCount, estimateCountDomain, estimateCountEmailSentSTRING/INTEGERestimasi onboarding
maxDomainAllowedINTEGER
allowedMailCountStart, allowedMailCountEndDATE
typeOfEmail, previousMailProvider, mailRecipientSourcesSTRING
statusSTRING

Relasi: hasMany TransCompanyContacts, TransCompanyDomains, TransCompanyConfigs, TransCompanyDocuments, TransCompanyInvoices, TransCompanyTaxInvoices, TransCompanySubscriptions; hasOne TransCompanyAccountRelays.

TransCompanyContactsmodels/transcompanycontacts.js

KolomTipeKeterangan
idINTEGER PK
uuidUUID
transCompanyIdINTEGERFK → TransCompanies
userIdINTEGERFK → Users
name, phoneSTRING
roleENUMprimary, billing, technical, techbill
statusENUMactive, trashed
amcListUid, amcSubsUidSTRINGreferensi MailWizz/AMC

Relasi: belongsTo TransCompanies, Users.

TransCompanyDomainsmodels/transcompanydomains.js

KolomTipeKeterangan
idINTEGER PK
uuidUUID
transCompanyIdINTEGERFK → TransCompanies
nameSTRINGnama domain
spfRecord, dmarcRecord, dkimRecord, aRecordTEXTrecord DNS
spfStatus, dmarcStatus, dkimStatus, aRecordStatusBOOLEANstatus verifikasi
spfLastCheckDate, dmarcLastCheckDate, dkimLastCheckDateDATE
notificationBOOLEAN
isUsedTrialBOOLEAN
statusENUMactive, inactive, processing, trashed

Relasi: belongsTo TransCompanies; hasMany TransEmailLog, TViewCompanyMailUsage.

TransCompanyAccountRelaysmodels/transcompanyaccountrelays.js

KolomTipeKeterangan
idINTEGER PK
uuidUUID
transCompanyIdINTEGERFK → TransCompanies
zimbraUserIdSTRINGID akun di Zimbra
email, passwordSTRINGkredensial relay
statusENUMactive, processing, closed, locked, suspended, trashed

Relasi: belongsTo TransCompanies.

TransCompanyConfigsmodels/transcompanyconfigs.js

KolomTipeKeterangan
idINTEGER PK
uuidUUID
transCompanyIdINTEGERFK → TransCompanies
configTypeSTRINGjenis config (mis. flag trial, state notif, refresh token Zoho)
params1, params2, params3STRINGnilai konfigurasi

Relasi: belongsTo TransCompanies.

TransCompanyDocumentsmodels/transcompanydocuments.js

KolomTipeKeterangan
idINTEGER PK
uuidUUID
transCompanyIdINTEGERFK → TransCompanies
docTypeSTRING
pathSrcSTRINGpath file (S3)
statusENUMactive, trashed

Relasi: belongsTo TransCompanies.

TransCompanyTagsmodels/transcompanytags.js

KolomTipeKeterangan
idINTEGER PK
transCompanyContactIdINTEGERFK → TransCompanyContacts (migrasi saja)
labelENUMprimary, technical, billing, techbill, other
statusENUMactive, trashed

Relasi: tidak ada associate() (FK hanya di migrasi).

UnlockCountermodels/unlockCounter.js

KolomTipeKeterangan
idINTEGER PK
uuidUUID
transCompanyIdINTEGERFK → TransCompanies
counterINTEGERjumlah percobaan unlock relay
firstCounterTimeDATE

Relasi: belongsTo TransCompanies (tanpa reverse hasMany).


Tabel: Billing & Subscription

TransServicePackagesmodels/transservicepackages.js

KolomTipeKeterangan
idINTEGER PK
uuidUUID
nameSTRING
descriptionTEXT
countTotalUserINTEGER
priceINTEGER
maxTotalEmail, maxTotalEmailHourlyINTEGERkuota email
maxTotalDomainINTEGER
maxAttachmentSizeINTEGER
isHasPhoneSupport, isHasDedicatedIpBOOLEAN
itemIdZohoSTRING
statusENUMactive, inactive, trashed
statusPublicationBOOLEAN
transServiceAddOnPackageIdINTEGERFK → add-on

Relasi: hasMany TransCompanySubscriptions; belongsTo TransServiceAddOnPackage.

TransServiceAddOnPackagemodels/transserviceaddonpackage.js

KolomTipeKeterangan
idINTEGER PK
uuidSTRING
nameSTRING
priceINTEGER
descriptionTEXT
zohoItemIdSTRING

Relasi: hasMany TransServicePackages.

TransCompanySubscriptionsmodels/transcompanysubscriptions.js

KolomTipeKeterangan
idINTEGER PK
uuidUUID
idRecurringXenditSTRINGID recurring payment Xendit
transCompanyIdINTEGERFK → TransCompanies
transServicePackageIdINTEGERFK → TransServicePackages
priceINTEGER
servicePeriodeSTRING(di model dideklarasi dua kali; versi STRING menang)
startPeriode, endPeriodeDATE
statusENUMactive, inactive, trashed, deleted
transCompanyInvoiceIdINTEGERreferensi invoice (tanpa asosiasi Sequelize)

Relasi: belongsTo TransCompanies, TransServicePackages.

TransCompanyInvoicesmodels/transcompanyinvoices.js

KolomTipeKeterangan
idINTEGER PK
uuidUUID
idEstimateZoho, idInvoiceZohoSTRINGID dokumen Zoho
invoiceUrlZohoTEXT
paymentUrlXenditTEXT
serialNumberSTRING
transCompanyIdINTEGERFK → TransCompanies
paidStatusENUMpaid, unpaid, overdue, cancelled
servicePeriodeStart, servicePeriodeEndDATE
date, dueDateDATE
total, priceINTEGER
paymentMethodSTRING

Relasi: belongsTo TransCompanies; hasOne TransCompanyTaxInvoices (alias Tax_Invoice), TransCompanyPayments.

TransCompanyPaymentsmodels/transcompanypayments.js

KolomTipeKeterangan
idINTEGER PK
uuidUUID
transCompanyInvoiceIdINTEGERFK → TransCompanyInvoices
paymentAmountINTEGER
paymentDateDATE
sourceBank, destinationBankSTRING
uploadLinkTEXTbukti pembayaran
statusSTRING

Relasi: belongsTo TransCompanyInvoices.

TransCompanyTaxInvoicesmodels/transcompanytaxinvoices.js

KolomTipeKeterangan
idINTEGER PK
uuidUUID
transCompanyInvoiceIdINTEGERFK → TransCompanyInvoices
transCompanyIdINTEGERFK → TransCompanies
serialNumberSTRING
dateDATE
totalINTEGER
taxInvoicePathSTRING
isSentToClientBOOLEAN

Relasi: belongsTo TransCompanyInvoices (alias Tax_Invoice), TransCompanies.

TransCompanyEmailQuotaCountmodels/transcompanyemailquotacount.js

KolomTipeKeterangan
idINTEGER PK
transCompanyIdINTEGER
transSubsIdINTEGERFK → TransCompanySubscriptions
sendingQuota, currentSendingCountINTEGERkuota & pemakaian
eightyPercentAct, ninetyPercentAct, hundredPercentActBOOLEANflag ambang notifikasi
quotaStartDate, quotaEndDateDATE
overQuotaBOOLEAN
overQuotaTypeSTRING
allowNextOverQuotaBOOLEANdefault false

Relasi: belongsTo TransCompanySubscriptions.


Tabel: Email Delivery & Usage

TransEmailLogmodels/transemaillog.js

KolomTipeKeterangan
idINTEGER PK
uuidUUID
transCompanyDomainIdINTEGERFK → TransCompanyDomains
dateWithTimeZoneDATE
messageIdSTRING
subjectTEXT
senderAddress, recipientAddressSTRING
statusSTRING
mapHostId, mapHostSendingIdINTEGER
hostResponseSTRING

Relasi: belongsTo TransCompanyDomains, MapHost.

Tabel legacy

Tidak ada repository/controller yang menulis ke TransEmailLogs di codebase saat ini. Log pengiriman sesungguhnya disimpan di Elasticsearch (dashboard-clean-log), bukan tabel ini. Lihat Logging Pengiriman.

MapHostmodels/maphost.js

KolomTipe
idINTEGER PK
uuidUUID
hostNameSTRING
hostIpAddressSTRING

Relasi: hasMany TransEmailLog.

TViewCompanyMailUsagemodels/tviewcompanymailusage.js

Bukan SQL View

Meskipun prefix TView, ini adalah tabel biasa yang dikelola Sequelize (createTable), bukan SQL VIEW maupun materialized view. Berisi statistik pemakaian email yang sudah di-agregasi oleh kode aplikasi.

KolomTipeKeterangan
idINTEGER PK
usageTypeENUMmonthly, daily, weekly, yearly, total (runtime memakai nilai pendek seperti day)
transCompanyIdINTEGERdefault 0
transCompanyDomainIdINTEGERdefault 0
usageKeySTRING
mailSendStatusENUMfailed, delivered, allCount
isActiveCurrentSubscribeBOOLEAN
countDelivered, countFailedINTEGER
currentTotalSubscribeINTEGER
topSenderEmail / topSenderEmailValueSTRING/INTEGER
topReceiverEmail / topReceiverEmailValueSTRING/INTEGER
topReceiverDomain / topReceiverDomainValueSTRING/INTEGER
attachmentSTRING

Relasi: belongsTo TransCompanyDomains.


Tabel: Notifikasi & Konten

NotificationContentmodels/notificationcontent.js

KolomTipeKeterangan
idINTEGER PK
uuidUUID
dateDATE
category, title, preview, contentSTRING
adminIdINTEGERFK → Admins
isDeletedBOOLEAN

Relasi: hasMany TransUserNotifications; belongsTo Admins.

TransUserNotificationsmodels/transusernotifications.js

KolomTipeKeterangan
idINTEGER PK
uuidUUID
userIdINTEGERFK → Users
contentIdINTEGERFK → NotificationContent
isReadBOOLEAN
dateDATE

Relasi: belongsTo Users, NotificationContent.

TransUserEmailNotificationsmodels/transuseremailnotifications.js

KolomTipeKeterangan
idINTEGER PK
uuidUUID
userIdINTEGERFK → Users
dateDATE
titleSTRING
contextTEXT
isReadBOOLEAN

Relasi: belongsTo Users.


Tabel: Jobs & Misc

Jobmodels/job.js

KolomTipeKeterangan
idINTEGER PK
uuidUUIDdi-set otomatis di hook
jobTypeSTRINGnama queue / routing worker
statusENUMon-queue, processing, done, error
params1TEXTpayload JSON utama
params2STRINGkey sekunder (mis. email relay untuk dedup)
params3STRINGpesan error (JSON) saat gagal

Relasi: hasMany JobDetail.

JobDetailmodels/jobdetail.js

KolomTipeKeterangan
idINTEGER PK
transJobIdINTEGERFK → Job
payloadTEXT
statusENUMdone, error

Relasi: belongsTo Job. Catatan: tabel ini tidak terpakai (tidak ada kode yang membaca/menulisnya).

TransArticlesmodels/transarticles.js

KolomTipe
idINTEGER PK
docTypeSTRING
titleSTRING
filePathSTRING

Relasi: tidak ada.


Catatan quirks skema (penting untuk migrasi)

  1. Asosiasi tidak lengkap — mis. TransCompanies tidak punya hasMany UnlockCounter; TransCompanySubscriptions.transCompanyInvoiceId tanpa FK Sequelize.
  2. Drift enum — enum TViewCompanyMailUsages di model berbeda dengan migrasi; runtime memakai nilai pendek (day, dll.).
  3. Kolom duplikatservicePeriode di TransCompanySubscriptions dideklarasi dua kali.
  4. Mismatch tipe — beberapa uuid STRING di model padahal migrasi UUID.
  5. TransCompanyTags — FK hanya di migrasi, tanpa associate().
  6. UsersTransCompanyContacts — model memakai hasOne padahal data memungkinkan banyak contact per user.
  7. Tabel legacy/tak terpakaiTransEmailLogs, JobDetails.

Detail rekomendasi penanganan ada di Known Issues dan Roadmap Migrasi.