Project

General

Profile

Actions

Customer Database

// Customer database
// Layer 1
// Onboarding
// Customer

// Separate transaction database
// Transaction: use customer_code from customer_info and asset_id per trade

// Layer 2
// Fullname
// Customer info: link to onboarding and expose customer_code for transaction database
// customer suite test answer: answer
// suite test id: question and answer

// Layer 3
// suite test question and answer
// Knowledge test


// Layer 1
// ----------------------
// Onboarding
Table onboarding {
  id int [pk, increment]
  onboarding_id string
  register_id uuid
  customer_info_id string [ref: - customer_info.customer_info_id]
  idcard_id string [ref: - idcard.idcard_id]
  occupation_id string [ref: - occupation.occupation_id]
  register_address_id string [ref : - address.address_id]
  current_address_id string [ref : - address.address_id]
  work_address_id string [ref : - address.address_id]
  customer_suite_id string [ref: - customer_suite_submission.customer_suite_submission_id]
  cdd_id string [ref: - cdd.cdd_id]
  bank_id string [ref: - bank.bank_id]
  secondary_bank_id string [ref: - bank.bank_id]
  source_of_fund_id string [ref: - source_of_fund.source_of_fund_id]
  thaid_id string [ref: - thaid.thaid_id]
  ndid_id string [ref: - ndid.ndid_id]
  approval_id string [ref: - approval.approval_id]
  appman_id string [ref: - appman.appman_id]
  risk_score_id string [ref: - risk_score.risk_score_id]
  has_done_knowledge_test bool
  steps int
}

// Customer
Table customer {
  id int [pk, increment]
  customer_id string
  customer_info_id string [ref: - customer_info.customer_info_id]
  risk_score_id string [ref: - risk_score.risk_score_id]
  idcard_id string [ref: - idcard.idcard_id]
  occupation_id string [ref: - occupation.occupation_id]
  register_address_id string [ref : - address.address_id]
  current_address_id string [ref : - address.address_id]
  work_address_id string [ref : - address.address_id]
  customer_suite_id string [ref: - customer_suite_submission.customer_suite_submission_id]
  bank_id string [ref: - bank.bank_id]
  secondary_bank_id string [ref: - bank.bank_id]
  source_of_fund_id string [ref: - source_of_fund.source_of_fund_id]

}

// Layer 2
// ----------------------
Table customer_info {
  id int [pk, increment]
  customer_info_id string
  customer_code int
  mobile string
  email string
  title_id string [ref: - title.title_id]
  first_name_th string
  middle_name_th string
  last_name_th string
  first_name_en string
  middle_name_en string
  last_name_en string
  customer_type enum
  ip_id string [ref: - ip_detail.ip_detail_id]
}

Table address {
  id int [pk, increment]
  address_id string
  house_number string
  floor string
  village_building string
  sub_street strign
  street strign
  country_code string
  location_id  int
}

Table idcard {
  id int [pk, increment]
  idcard_id string
  citizen_id  string
  laser_code string
  date_of_birth timestamp
  expire_date timestamp
  issue_date timestamp
}

Table occupation {
  id int [pk, increment]
  occupation_id string
  code string
  position_name string
  source_of_investment string
  workplace_name string
  education_id string [ref: - education.education_id]
  parent_occupation_id string [ref: - occupation.occupation_id]
  business_type_id string [ref: - business_type.business_type_id]
  income_range_id string [ref: - income_range.income_range_id]
  
}

Table customer_suite_answer {
  id int [pk, increment]
  customer_suite_answer_id string
  submission_id string [ref: > customer_suite_submission.customer_suite_submission_id]
  question_id string [ref: > suitability_question.suitability_question_id]
  choice_id string [ref: > suitability_choice.suitability_choice_id]
}

Table customer_suite_submission {
  id int [pk, increment]
  customer_suite_submission_id string
  customer_info_id string [ref: > customer_info.customer_info_id]
  total_score int
  risk_level string
}


Table cdd {
  id int [pk, increment]
  cdd_id string
  mule string
  freeze_04 string
  freeze_05 string
  pep bool
  pep_message string
  dopa bool
}

Table appman {
  id int [pk, increment]
  appman_id string
  verification_id string
  is_verified bool
  status string [enum]
  verified_at timestamp
  expire_at timestamp
  idcard_id string [ref: - appman_id_card.appman_id_card_id]
  liveness_id string [ref: - appman_liveness.appman_liveness_id]
  liveness_attribute_id string [ref: - appman_liveness_attributes.appman_liveness_attributes_id]
  recognition string [ref: - appman_recognition.appman_recognition_id]
}

Table bank { //
  id int [pk, increment]
  bank_id string
  name string
  branch string
  account_no string
}

Table source_of_fund { //
  id int [pk, increment]
  source_of_fund_id string
  source_of_fund string
  country_of_income string
  purpose_of_investment string
}

Table thaid {
  id int [pk, increment]
  thaid_id string
  url string
  state string
  thaid_detail_id string [ref: - thaid_detail.thaid_detail_id]
}

Table ndid {
  id int [pk, increment]
  ndid_id string
  ndid_detail_id string [ref: - ndid_detail.ndid_detail_id]
}

Table approval {
  id int [pk, increment]
  approval_id string
  by string
  name string
  level int
  message string
  is_approve bool
}

Table risk_score {
  id int [pk, increment]
  risk_score_id string
  score int
  risk_level int
}

// ----------------------
// Layer 3
// ----------------------

Table suitability_question {
  id int [pk, increment]
  suitability_question_id string
  question string
}

Table suitability_choice {
  id int [pk, increment]
  suitability_choice_id string
  question_id string [ref: > suitability_question.suitability_question_id]
  answer string
  score int
}

Table appman_id_card {
  id int [pk, increment]
  appman_id_card_id string
  register_id string
  verification_id string
  id_number string
  address_th string
  full_name_th string
  full_name_en string
  serial_number string
  date_birth_en string
  date_birth_th string
  date_issue_en string
  date_issue_th string
  date_expire_en string
  date_expire_th string
  laser_code string
  updated_at timestamp
}

Table appman_liveness {
  id int [pk, increment]
  appman_liveness_id string
  register_id string
  verification_id string
  verified bool
  valid bool
  completed bool
  success bool
  was_processed bool
  scan_result_blob text
  updated_at timestamp
}

Table appman_liveness_attributes {
  id int [pk, increment]
  appman_liveness_attributes_id string
  register_id string
  verification_id string
  yaw float
  roll float
  pitch float
  is_beard bool
  beard_confidence float
  is_smile bool
  smile_confidence float
  gender string
  gender_confidence float
  sharpness float
  brightness float
  age_low int
  age_high int
  is_eyes_open bool
  eyes_open_confidence float
  is_mustache bool
  mustache_confidence float
  is_mouth_open bool
  mouth_open_confidence float
  confidence float
  is_eyeglasses bool
  eyeglasses_confidence float
  is_sunglasses bool
  sunglasses_confidence float
}

Table appman_recognition {
  id int [pk, increment]
  appman_recognition_id string
  register_id string
  verification_id string
  yaw float
  roll float
  pitch float
  sharpness float
  brightness float
  top float
  left float
  width float
  height float
  similarity float
  pass_similarity bool
  confidence float
  verified bool
  valid bool
  completed bool
  source_key string
  target_key string
  source_url string
  target_url string
  updated_at timestamp
}
Table education {
  id int [pk, increment]
  education_id string
  code string
  name string
}

Table business_type {
  id int [pk, increment]
  business_type_id string
  name string
  risk_score int
}

Table income_range {
  id int [pk, increment]
  income_range_id string
  range string
}

Table thaid_detail {
  id int [pk, increment]
  thaid_detail_id string
}

Table ndid_detail {
  id int [pk, increment]
  ndid_detail_id string
}

Table ip_detail {
  id int [pk, increment]
  ip_detail_id string
  ip_address string
  country string
}

Table title {
  id int [pk, increment]
  title_id string
  name_en string
  name_th string
}

// ----------------------

// Transaction database
// ----------------------
// Current asset holding = sum(buy unit) - sum(sell unit)
// grouped by customer_code and asset_id from completed transactions
// If old rows are moved to transaction_history, calculate from
// UNION ALL(transaction, transaction_history) or maintain a rebuildable balance projection
Table transaction {
  id int [pk, increment]
  transaction_id string
  asset_id string [ref: - digital_asset.asset_id]
  seller_customer_code int
  buyer_customer_code int
  status enum
  price float
  amount_per_unit float
  unit float
}

// Transaction Layer 2
// ----------------------
Table digital_asset {
  id int [pk, increment]
  asset_id string
  name string
  by string
  total_unit float
}

Tree layer version:

Customer
│ --- layer-1 ---
│ ├── onboarding
│ │   ├── id: int [pk, increment]
│ │   ├── onboarding_id: string
│ │   ├── register_id: uuid
│ │   ├── customer_info_id: string [ref: - customer_info.customer_info_id]
│ │   ├── idcard_id: string [ref: - idcard.idcard_id]
│ │   ├── occupation_id: string [ref: - occupation.occupation_id]
│ │   ├── register_address_id: string [ref: - address.address_id]
│ │   ├── current_address_id: string [ref: - address.address_id]
│ │   ├── work_address_id: string [ref: - address.address_id]
│ │   ├── customer_suite_id: string [ref: - customer_suite_submission.customer_suite_submission_id]
│ │   ├── cdd_id: string [ref: - cdd.cdd_id]
│ │   ├── bank_id: string [ref: - bank.bank_id]
│ │   ├── secondary_bank_id: string [ref: - bank.bank_id]
│ │   ├── source_of_fund_id: string [ref: - source_of_fund.source_of_fund_id]
│ │   ├── thaid_id: string [ref: - thaid.thaid_id]
│ │   ├── ndid_id: string [ref: - ndid.ndid_id]
│ │   ├── approval_id: string [ref: - approval.approval_id]
│ │   ├── appman_id: string [ref: - appman.appman_id]
│ │   ├── risk_score_id: string [ref: - risk_score.risk_score_id]
│ │   ├── has_done_knowledge_test: bool
│ │   └── steps: int
│ └── customer
│     ├── id: int [pk, increment]
│     ├── customer_id: string
│     ├── customer_info_id: string [ref: - customer_info.customer_info_id]
│     ├── risk_score_id: string [ref: - risk_score.risk_score_id]
│     ├── idcard_id: string [ref: - idcard.idcard_id]
│     ├── occupation_id: string [ref: - occupation.occupation_id]
│     ├── register_address_id: string [ref: - address.address_id]
│     ├── current_address_id: string [ref: - address.address_id]
│     ├── work_address_id: string [ref: - address.address_id]
│     ├── customer_suite_id: string [ref: - customer_suite_submission.customer_suite_submission_id]
│     ├── bank_id: string [ref: - bank.bank_id]
│     ├── secondary_bank_id: string [ref: - bank.bank_id]
│     └── source_of_fund_id: string [ref: - source_of_fund.source_of_fund_id]
│ --- layer-2 ---
│ ├── customer_info
│ │   ├── id: int [pk, increment]
│ │   ├── customer_info_id: string
│ │   ├── customer_code: int
│ │   ├── mobile: string
│ │   ├── email: string
│ │   ├── title_id: string [ref: - title.title_id]
│ │   ├── first_name_th: string
│ │   ├── middle_name_th: string
│ │   ├── last_name_th: string
│ │   ├── first_name_en: string
│ │   ├── middle_name_en: string
│ │   ├── last_name_en: string
│ │   ├── customer_type: enum
│ │   └── ip_id: string [ref: - ip_detail.ip_detail_id]
│ ├── address
│ │   ├── id: int [pk, increment]
│ │   ├── address_id: string
│ │   ├── house_number: string
│ │   ├── floor: string
│ │   ├── village_building: string
│ │   ├── sub_street: strign
│ │   ├── street: strign
│ │   ├── country_code: string
│ │   └── location_id: int
│ ├── idcard
│ │   ├── id: int [pk, increment]
│ │   ├── idcard_id: string
│ │   ├── citizen_id: string
│ │   ├── laser_code: string
│ │   ├── date_of_birth: timestamp
│ │   ├── expire_date: timestamp
│ │   └── issue_date: timestamp
│ ├── occupation
│ │   ├── id: int [pk, increment]
│ │   ├── occupation_id: string
│ │   ├── code: string
│ │   ├── position_name: string
│ │   ├── source_of_investment: string
│ │   ├── workplace_name: string
│ │   ├── education_id: string [ref: - education.education_id]
│ │   ├── parent_occupation_id: string [ref: - occupation.occupation_id]
│ │   ├── business_type_id: string [ref: - business_type.business_type_id]
│ │   └── income_range_id: string [ref: - income_range.income_range_id]
│ ├── customer_suite_answer
│ │   ├── id: int [pk, increment]
│ │   ├── customer_suite_answer_id: string
│ │   ├── submission_id: string [ref: > customer_suite_submission.customer_suite_submission_id]
│ │   ├── question_id: string [ref: > suitability_question.suitability_question_id]
│ │   └── choice_id: string [ref: > suitability_choice.suitability_choice_id]
│ ├── customer_suite_submission
│ │   ├── id: int [pk, increment]
│ │   ├── customer_suite_submission_id: string
│ │   ├── customer_info_id: string [ref: > customer_info.customer_info_id]
│ │   ├── total_score: int
│ │   └── risk_level: string
│ ├── cdd
│ │   ├── id: int [pk, increment]
│ │   ├── cdd_id: string
│ │   ├── mule: string
│ │   ├── freeze_04: string
│ │   ├── freeze_05: string
│ │   ├── pep: bool
│ │   ├── pep_message: string
│ │   └── dopa: bool
│ ├── appman
│ │   ├── id: int [pk, increment]
│ │   ├── appman_id: string
│ │   ├── verification_id: string
│ │   ├── is_verified: bool
│ │   ├── status: string [enum]
│ │   ├── verified_at: timestamp
│ │   ├── expire_at: timestamp
│ │   ├── idcard_id: string [ref: - appman_id_card.appman_id_card_id]
│ │   ├── liveness_id: string [ref: - appman_liveness.appman_liveness_id]
│ │   ├── liveness_attribute_id: string [ref: - appman_liveness_attributes.appman_liveness_attributes_id]
│ │   └── recognition: string [ref: - appman_recognition.appman_recognition_id]
│ ├── bank
│ │   ├── id: int [pk, increment]
│ │   ├── bank_id: string
│ │   ├── name: string
│ │   ├── branch: string
│ │   └── account_no: string
│ ├── source_of_fund
│ │   ├── id: int [pk, increment]
│ │   ├── source_of_fund_id: string
│ │   ├── source_of_fund: string
│ │   ├── country_of_income: string
│ │   └── purpose_of_investment: string
│ ├── thaid
│ │   ├── id: int [pk, increment]
│ │   ├── thaid_id: string
│ │   ├── url: string
│ │   ├── state: string
│ │   └── thaid_detail_id: string [ref: - thaid_detail.thaid_detail_id]
│ ├── ndid
│ │   ├── id: int [pk, increment]
│ │   ├── ndid_id: string
│ │   └── ndid_detail_id: string [ref: - ndid_detail.ndid_detail_id]
│ ├── approval
│ │   ├── id: int [pk, increment]
│ │   ├── approval_id: string
│ │   ├── by: string
│ │   ├── name: string
│ │   ├── level: int
│ │   ├── message: string
│ │   └── is_approve: bool
│ └── risk_score
│     ├── id: int [pk, increment]
│     ├── risk_score_id: string
│     ├── score: int
│     └── risk_level: int
│ --- layer-3 ---
│ ├── suitability_question
│ │   ├── id: int [pk, increment]
│ │   ├── suitability_question_id: string
│ │   └── question: string
│ ├── suitability_choice
│ │   ├── id: int [pk, increment]
│ │   ├── suitability_choice_id: string
│ │   ├── question_id: string [ref: > suitability_question.suitability_question_id]
│ │   ├── answer: string
│ │   └── score: int
│ ├── appman_id_card
│ │   ├── id: int [pk, increment]
│ │   ├── appman_id_card_id: string
│ │   ├── register_id: string
│ │   ├── verification_id: string
│ │   ├── id_number: string
│ │   ├── address_th: string
│ │   ├── full_name_th: string
│ │   ├── full_name_en: string
│ │   ├── serial_number: string
│ │   ├── date_birth_en: string
│ │   ├── date_birth_th: string
│ │   ├── date_issue_en: string
│ │   ├── date_issue_th: string
│ │   ├── date_expire_en: string
│ │   ├── date_expire_th: string
│ │   ├── laser_code: string
│ │   └── updated_at: timestamp
│ ├── appman_liveness
│ │   ├── id: int [pk, increment]
│ │   ├── appman_liveness_id: string
│ │   ├── register_id: string
│ │   ├── verification_id: string
│ │   ├── verified: bool
│ │   ├── valid: bool
│ │   ├── completed: bool
│ │   ├── success: bool
│ │   ├── was_processed: bool
│ │   ├── scan_result_blob: text
│ │   └── updated_at: timestamp
│ ├── appman_liveness_attributes
│ │   ├── id: int [pk, increment]
│ │   ├── appman_liveness_attributes_id: string
│ │   ├── register_id: string
│ │   ├── verification_id: string
│ │   ├── yaw: float
│ │   ├── roll: float
│ │   ├── pitch: float
│ │   ├── is_beard: bool
│ │   ├── beard_confidence: float
│ │   ├── is_smile: bool
│ │   ├── smile_confidence: float
│ │   ├── gender: string
│ │   ├── gender_confidence: float
│ │   ├── sharpness: float
│ │   ├── brightness: float
│ │   ├── age_low: int
│ │   ├── age_high: int
│ │   ├── is_eyes_open: bool
│ │   ├── eyes_open_confidence: float
│ │   ├── is_mustache: bool
│ │   ├── mustache_confidence: float
│ │   ├── is_mouth_open: bool
│ │   ├── mouth_open_confidence: float
│ │   ├── confidence: float
│ │   ├── is_eyeglasses: bool
│ │   ├── eyeglasses_confidence: float
│ │   ├── is_sunglasses: bool
│ │   └── sunglasses_confidence: float
│ ├── appman_recognition
│ │   ├── id: int [pk, increment]
│ │   ├── appman_recognition_id: string
│ │   ├── register_id: string
│ │   ├── verification_id: string
│ │   ├── yaw: float
│ │   ├── roll: float
│ │   ├── pitch: float
│ │   ├── sharpness: float
│ │   ├── brightness: float
│ │   ├── top: float
│ │   ├── left: float
│ │   ├── width: float
│ │   ├── height: float
│ │   ├── similarity: float
│ │   ├── pass_similarity: bool
│ │   ├── confidence: float
│ │   ├── verified: bool
│ │   ├── valid: bool
│ │   ├── completed: bool
│ │   ├── source_key: string
│ │   ├── target_key: string
│ │   ├── source_url: string
│ │   ├── target_url: string
│ │   └── updated_at: timestamp
│ ├── education
│ │   ├── id: int [pk, increment]
│ │   ├── education_id: string
│ │   ├── code: string
│ │   └── name: string
│ ├── business_type
│ │   ├── id: int [pk, increment]
│ │   ├── business_type_id: string
│ │   ├── name: string
│ │   └── risk_score: int
│ ├── income_range
│ │   ├── id: int [pk, increment]
│ │   ├── income_range_id: string
│ │   └── range: string
│ ├── thaid_detail
│ │   ├── id: int [pk, increment]
│ │   └── thaid_detail_id: string
│ ├── ndid_detail
│ │   ├── id: int [pk, increment]
│ │   └── ndid_detail_id: string
│ ├── ip_detail
│ │   ├── id: int [pk, increment]
│ │   ├── ip_detail_id: string
│ │   ├── ip_address: string
│ │   └── country: string
└─└── title
    ├── id: int [pk, increment]
    ├── title_id: string
    ├── name_en: string
    └── name_th: string

Transaction
│ --- layer-1 ---
│ └── transaction
│     ├── id: int [pk, increment]
│     ├── transaction_id: string
│     ├── asset_id: string [ref: - digital_asset.asset_id]
│     ├── seller_customer_code: int
│     ├── buyer_customer_code: int
│     ├── status: enum
│     ├── price: float
│     ├── amount_per_unit: float
│     └── unit: float
│ --- layer-2 ---
├── digital_asset
│   ├── id: int [pk, increment]
│   ├── asset_id: string
│   ├── name: string
│   ├── by: string
│   └── total_unit: float

Updated by Ryan Supawarapong 17 days ago · 9 revisions