T24 3 — Mô hình dữ liệu multivalue: Application, FILE, bản ghi
T24 3 — Mô hình dữ liệu multivalue: Application, FILE, bản ghi
Nếu bạn đến từ thế giới SQL — nơi mọi thứ là bảng phẳng, mỗi ô chứa đúng một giá trị, và quan hệ một–nhiều được chuẩn hoá ra bảng con — thì mô hình dữ liệu của Temenos T24 (nay là Transact) sẽ khiến bạn khựng lại ngay ngày đầu tiên. Một "bản ghi" trong T24 có thể chứa nhiều số điện thoại, nhiều địa chỉ, nhiều dòng lịch trả nợ nhét gọn trong đúng một dòng dữ liệu, phân tách bằng những ký tự vô hình mà bạn không nhìn thấy trên màn hình. Đó là di sản của dòng cơ sở dữ liệu PICK/MultiValue mà T24 kế thừa, và nó là lý do khiến việc "trích T24 sang data warehouse" không bao giờ là một lệnh SELECT * đơn giản.
Bài này giải phẫu mô hình đó từ gốc: từ khái niệm Application và FILE, xuống tới cấu trúc field–multivalue–subvalue với ba (bốn) cấp dấu phân tách, rồi tới vòng đời bản ghi (LIVE / $NAU / $HIS), các audit field maker-checker, và cuối cùng là hai bảng metadata sống còn là STANDARD.SELECTION và PGM.FILE. Xuyên suốt, ta luôn quay lại một câu hỏi thực dụng: đội Data phải làm gì để lấy đúng dữ liệu?
Bài này giả định bạn đã đọc bài kiến trúc TAFJ/jBASE (lớp nền lưu trữ và runtime), và sẽ được bổ trợ bởi các bài về VERSION/ENQUIRY (giao diện nhập liệu và truy vấn) cùng OFS (kênh tích hợp). Ở đây ta tập trung vào hình dạng dữ liệu.
Application và FILE: "bảng" theo nghĩa multivalue
Đơn vị nghiệp vụ trong T24 là Application. Mỗi application đại diện cho một loại đối tượng hoặc chức năng: CUSTOMER (khách hàng), ACCOUNT (tài khoản), FUNDS.TRANSFER (chuyển tiền), AA.ARRANGEMENT (hợp đồng theo mô hình Arrangement Architecture), LD.LOANS.AND.DEPOSITS, v.v. Tên application viết HOA, các từ ngăn nhau bằng dấu chấm — đây là quy ước xuyên suốt T24.
Mỗi application ánh xạ tới một FILE — nơi thực sự chứa dữ liệu. Bạn có thể tạm coi FILE tương đương "bảng" của RDBMS, nhưng với một khác biệt bản chất: FILE là một kho key–value, trong đó mỗi bản ghi được định danh bằng một @ID (khoá chính) và toàn bộ nội dung bản ghi là một dynamic array — một chuỗi có cấu trúc phân tách. Không có khái niệm "cột cố định" ở tầng lưu trữ; cấu trúc field chỉ được áp lên khi đọc, thông qua metadata (STANDARD.SELECTION).
@ID mang ý nghĩa nghiệp vụ và thường là khoá tự nhiên chứ không phải số tăng tự động:
| Application | Ví dụ @ID | Ý nghĩa |
|---|---|---|
| CUSTOMER | 100234 | Mã khách hàng |
| ACCOUNT | 1234567890 | Số tài khoản |
| FUNDS.TRANSFER | FT2418700ABC | ID giao dịch chuyển tiền |
| AA.ARRANGEMENT | AA24187XYZ01 | ID hợp đồng |
Vì @ID chính là khoá truy cập, việc đọc một bản ghi theo @ID cực nhanh (tra cứu hash trực tiếp trong file), nhưng việc "tìm tất cả tài khoản của khách hàng X" thì lại cần chỉ mục riêng hoặc quét chọn lọc — khác hẳn tư duy WHERE customer_id = X của SQL.
Trái tim của mô hình: field – multivalue – subvalue
Đây là điểm khiến T24 khó với người quen SQL, nên hãy đi thật chậm.
Trong RDBMS, khi một khách hàng có ba số điện thoại, bạn tạo bảng con CUSTOMER_PHONE với ba dòng. Trong T24, ba số điện thoại đó nằm ngay trong bản ghi CUSTOMER, trong cùng một field, phân tách bằng ký tự đặc biệt. Toàn bộ bản ghi là một chuỗi bytes duy nhất, và T24 dùng bốn cấp dấu phân tách (delimiter) — là các ký tự ASCII cao — để phân tầng dữ liệu:
| Cấp | Tên | Ký hiệu | Mã ASCII | Vai trò |
|---|---|---|---|---|
| 1 | Field Mark | FM / @FM | CHAR(254) | Ngăn cách các attribute/field trong bản ghi |
| 2 | Value Mark | VM / @VM | CHAR(253) | Ngăn cách các multivalue trong một field |
| 3 | Subvalue Mark | SM / @SVM | CHAR(252) | Ngăn cách các subvalue bên trong một value |
| 4 | Text Mark | TM / @TM | CHAR(251) | Cấp phân tách thấp nhất (ít dùng trong nghiệp vụ) |
Hãy hình dung một bản ghi như một cây bốn tầng:
Cách đọc: một bản ghi là một danh sách field ngăn nhau bằng FM. Một field có thể mang một giá trị đơn, hoặc nhiều value ngăn nhau bằng VM. Mỗi value lại có thể tách nhỏ thành các subvalue bằng SM. Ba tầng này cho phép nhúng cả một quan hệ một–nhiều–nhiều vào trong một bản ghi cha.
So sánh với RDBMS. Thay vì normalize (chuẩn hoá) ra nhiều bảng con và JOIN lại khi cần, T24 nhúng (embed / denormalize) dữ liệu lặp ngay trong bản ghi cha. Hệ quả có hai mặt rất rõ:
- Ưu điểm: đọc một bản ghi là lấy đủ toàn bộ thông tin liên quan — không JOIN, không round-trip. Với một core banking phải truy xuất hồ sơ khách hàng hàng triệu lần mỗi ngày, đây là tối ưu hoá hiệu năng đọc rất mạnh và là lý do lịch sử khiến mô hình này tồn tại.
- Nhược điểm: không thể query kiểu SQL trực tiếp. Bạn không thể
WHERE phone = '090...'một cách tự nhiên khi ba số điện thoại nằm chung một ô. Việc lọc, gom nhóm, thống kê trên các multivalue đòi hỏi hoặc công cụ riêng của T24 (ENQUIRY, xem bài VERSION/ENQUIRY), hoặc phải "làm phẳng" (flatten) khi đưa ra ngoài.
Field chuẩn và Local Reference Fields
Mỗi application có một tập field chuẩn do Temenos định nghĩa (ví dụ CUSTOMER có SHORT.NAME, NAME.1, DATE.OF.BIRTH, NATIONALITY...). Khi ngân hàng cần thêm trường riêng mà chuẩn không có (ví dụ "mã cán bộ quản lý nội bộ", "hạng khách hàng theo chính sách địa phương"), T24 không khuyến khích sửa cấu trúc lõi. Thay vào đó dùng Local Reference Fields (LRF) — một cơ chế trường mở rộng, thường được lưu gói trong một field LOCAL.REF dạng multivalue, mỗi vị trí (position) trong đó tương ứng một trường tuỳ biến đã đăng ký qua application LOCAL.TABLE / LOCAL.REF.TABLE.
Điểm cần nhớ cho đội Data: LRF là multivalue theo vị trí. Muốn biết field LRF thứ 3 nghĩa là gì, bạn phải tra định nghĩa LOCAL.REF chứ không thể đoán từ tên — và giá trị của nó nằm ở value thứ 3 trong field LOCAL.REF.
Ví dụ một bản ghi CUSTOMER (minh hoạ)
Dưới đây là hình dung một bản ghi CUSTOMER, hiển thị dấu phân tách bằng ký hiệu \FM\, \VM\, \SM\. Đây là minh hoạ để hiểu cấu trúc — tên và số thứ tự field mang tính ví dụ, không phải bố cục chính xác của một bản version cụ thể:
@ID = 100234
@ID .............. 100234
SHORT.NAME ....... NGUYEN VAN A
NAME.1 ........... NGUYEN VAN A
GENDER ........... MALE
DATE.OF.BIRTH .... 19850712
NATIONALITY ...... VN
-- Field địa chỉ: 2 địa chỉ (multivalue), mỗi địa chỉ nhiều dòng (subvalue)
ADDRESS .......... 12 LE LOI\SM\P.BEN NGHE\SM\Q.1\VM\45 TRAN HUNG DAO\SM\P.CAU ONG LANH\SM\Q.1
-- Field điện thoại: 3 số (multivalue)
PHONE.1 .......... 0901234567\VM\0912345678\VM\02838221234
-- Local Reference: các trường tuỳ biến theo vị trí
LOCAL.REF ........ GOLD\VM\RM007\VM\HN-01
-- ... các field nghiệp vụ khác ...
Nếu viết dạng chuỗi byte thô (cách T24 thực sự lưu), toàn bộ những dòng trên chỉ là một chuỗi:
100234 <lưu riêng làm @ID>
NGUYEN VAN A \FM\ NGUYEN VAN A \FM\ MALE \FM\ 19850712 \FM\ VN \FM\ 12 LE LOI \SM\ P.BEN NGHE \SM\ Q.1 \VM\ 45 TRAN HUNG DAO \SM\ P.CAU ONG LANH \SM\ Q.1 \FM\ 0901234567 \VM\ 0912345678 \VM\ 02838221234 \FM\ ...
Đọc chuỗi này: mỗi \FM\ sang một field mới; trong field ADDRESS có một \VM\ → hai địa chỉ; trong mỗi địa chỉ có các \SM\ → ba dòng subvalue (số nhà, phường, quận). Đây chính là quan hệ một khách hàng ↔ nhiều địa chỉ ↔ nhiều dòng địa chỉ, nhúng gọn trong một bản ghi.
Audit / control fields: dấu vân tay maker-checker
Cuối mỗi bản ghi T24, ngoài các field nghiệp vụ, luôn có một khối audit / control field do hệ thống tự đóng dấu. Đây là bộ khung chung cho hầu hết application và là nguồn thông tin quản trị cực kỳ quan trọng:
| Field | Ý nghĩa |
|---|---|
RECORD.STATUS | Trạng thái bản ghi: rỗng = LIVE (đã duyệt); INAU/NAU = chờ duyệt; IHLD = giữ (hold); RNAU/RHLD = xoá chờ duyệt... |
CURR.NO | Số thứ tự phiên bản — tăng 1 mỗi lần bản ghi được sửa và duyệt |
INPUTTER | Người nhập (maker), thường dạng <nnn>_USER.ID |
AUTHORISER | Người duyệt (checker) |
DATE.TIME | Ngày–giờ thao tác (có thể multivalue để lưu cả mốc nhập lẫn mốc duyệt qua các phiên bản) |
CO.CODE | Mã company (đơn vị/pháp nhân) sở hữu bản ghi |
DEPT.CODE | Mã phòng ban |
Khối này hiện thực nguyên tắc maker-checker (input → authorise) — một chốt kiểm soát nội bộ nền tảng trong ngân hàng: người nhập liệu (maker) tạo/sửa bản ghi, một người khác (checker/authoriser) phải duyệt thì thay đổi mới có hiệu lực. Cùng một người không được vừa nhập vừa tự duyệt. CURR.NO, INPUTTER, AUTHORISER, DATE.TIME cùng nhau tạo thành dấu vết kiểm toán (audit trail) đầy đủ: ai làm gì, khi nào, phiên bản thứ mấy. Nếu bật lưu lịch sử, dấu vết này còn được giữ trong từng bản $HIS.
Vòng đời và nơi lưu bản ghi: LIVE, $NAU, $HIS
Chính vì maker-checker, một bản ghi T24 sống ở những "nơi" khác nhau tuỳ trạng thái. Đây là kiến thức tối quan trọng để đội Data không lấy nhầm dữ liệu chưa duyệt:
- Bản LIVE (đã duyệt): nằm ở file chính, ví dụ
FBNK.FUNDS.TRANSFER. Đây là dữ liệu "thật", có hiệu lực nghiệp vụ. Khi báo cáo, gần như luôn chỉ lấy từ đây. - Bản chưa duyệt (unauthorised / NAU, IHLD): nằm ở file có hậu tố
$NAU, ví dụFBNK.FUNDS.TRANSFER$NAU. Một giao dịch mới nhập nhưng chưa được checker duyệt sẽ nằm ở đây — nó chưa tác động sổ sách. Lấy nhầm bản này vào DWH là sai số kinh điển. - Bản lịch sử (history): nằm ở file hậu tố
$HIS, ví dụFBNK.FUNDS.TRANSFER$HIS. Mỗi lần bản ghi được sửa và duyệt lại, phiên bản trước được chụp và lưu vào đây (thường với@IDgắn thêm;CURR.NO, ví dụFT2418700ABC;1). Đây là kho vàng cho phân tích thay đổi theo thời gian và điều tra kiểm toán.
Quy ước tên FILE trong môi trường
Tên FILE trong T24 tuân theo các tiền tố có ý nghĩa. Nắm quy ước này giúp bạn định vị đúng file khi khai thác:
| Tiền tố | Ý nghĩa (khái quát) |
|---|---|
F. | File dữ liệu/giao dịch chuẩn ở mức hệ thống (ví dụ F.CUSTOMER) |
FBNK. | File dữ liệu theo company cụ thể — mnemonic công ty gắn vào tên (rất phổ biến khi khai thác) |
I_ | File include / định nghĩa dùng chung (common/insert) |
EB.* | Các application/bảng thuộc core (Enterprise Backbone) như EB.CONTRACT.BALANCES... |
Trong thực tế, cùng một application có thể xuất hiện dưới nhiều tên vật lý (F.CUSTOMER, FBNK.CUSTOMER, FBNK.CUSTOMER$NAU, FBNK.CUSTOMER$HIS) tuỳ company và trạng thái. Khi trích xuất, hãy xác nhận đúng company mnemonic của môi trường mình đang lấy.
Metadata điều khiển tất cả: STANDARD.SELECTION và PGM.FILE
Vì tầng lưu trữ chỉ thấy chuỗi byte, cấu trúc "field" hoàn toàn nằm ở metadata. Hai application metadata quan trọng nhất:
STANDARD.SELECTION. Đây là "từ điển field" của mỗi application: nó định nghĩa mỗi field có tên (field name), kiểu/định dạng (numeric, date, string...), độ dài, thuộc tính single/multi/sub-value, và quy tắc hiển thị. Chính STANDARD.SELECTION là nền tảng để ENQUIRY và VERSION biết có những field nào, ở vị trí nào, tên là gì — để hiển thị và cho phép chọn lọc. Khi bạn dùng ENQUIRY gõ điều kiện lọc theo tên field (xem bài VERSION/ENQUIRY), T24 tra chính bảng này để hiểu field đó nằm ở đâu trong dynamic array. Với đội Data, STANDARD.SELECTION của một application là bản đồ để đọc bản ghi thô: nó nói cho bạn biết field số mấy tên là gì và có phải multivalue không.
PGM.FILE. Đây là "sổ đăng ký" application — mỗi application phải được khai báo trong PGM.FILE thì T24 mới biết đến nó. PGM.FILE ghi các thuộc tính hệ thống, đáng chú ý là loại application (type):
H— application kiểu hồ sơ tĩnh (static/maintenance file): dữ liệu tham chiếu, cấu hình, danh mục ít thay đổi (ví dụ nhiều bảng tham số).U/T— application kiểu giao dịch (update/transaction): có luồng nhập–duyệt, sinh hạch toán, có$NAU/$HIS.- (còn các loại khác cho các mục đích chuyên biệt.)
Loại này quyết định bản ghi có audit đầy đủ, có file $NAU/$HIS hay không — thông tin then chốt để biết một application có "bản chưa duyệt" cần tránh hay không.
Cả hai gắn với khái niệm DICT/dictionary của dòng MultiValue: dictionary là nơi lưu định nghĩa cấu trúc dữ liệu tách rời khỏi bản thân dữ liệu. Ở T24, STANDARD.SELECTION đóng vai trò dictionary nghiệp vụ cho từng application.
Ý nghĩa cho đội Data
Gộp lại, mô hình multivalue đặt ra ba việc bắt buộc khi trích T24 sang data warehouse:
- Flatten (explode) multivalue thành nhiều dòng. Một field VM có N value phải được "nổ" thành N dòng ở bảng đích, mỗi dòng giữ lại
@IDcủa bản ghi cha làm khoá ngoại. Subvalue (SM) thì hoặc explode thêm một tầng, hoặc gộp thành cột (tuỳ ngữ nghĩa). - Map @ID rõ ràng.
@IDlà khoá tự nhiên, phải được giữ làm business key ở DWH; đừng thay bằng surrogate key mà mất dấu về nguồn. - Hiểu $NAU/$HIS. Chỉ lấy LIVE cho số liệu chính thức; loại trừ
$NAU(chưa duyệt, chưa có hiệu lực); dùng$HIScho phân tích thay đổi/kiểm toán — và tuyệt đối không trộn ba loại này vào cùng một bảng mà không có cột phân biệt trạng thái.
Use case thực tế: flatten liên hệ khách hàng cho DWH
Yêu cầu: đội CRM cần bảng DIM_CUSTOMER_CONTACT với mỗi dòng là một số điện thoại hoặc một địa chỉ của khách hàng, để làm chiến dịch và kiểm tra trùng lặp.
Nguồn: bản ghi CUSTOMER trong file LIVE. Vấn đề: PHONE.1 là multivalue (nhiều số trên một ô), ADDRESS là multivalue + subvalue (nhiều địa chỉ, mỗi địa chỉ nhiều dòng).
Cách xử lý trong pipeline (mô tả logic, không phụ thuộc công cụ):
Với mỗi bản ghi CUSTOMER ở file LIVE (bỏ qua $NAU):
cust_id = @ID
# Số điện thoại: tách theo VM -> mỗi số 1 dòng
for i, phone in enumerate(split(PHONE.1, VM), start=1):
emit(cust_id, contact_type="PHONE", seq=i, value=phone)
# Địa chỉ: tách theo VM (mỗi địa chỉ), rồi ghép subvalue thành 1 chuỗi
for j, addr in enumerate(split(ADDRESS, VM), start=1):
full = join(split(addr, SM), separator=", ")
emit(cust_id, contact_type="ADDRESS", seq=j, value=full)
Kết quả: một khách hàng có 3 số + 2 địa chỉ → 5 dòng ở bảng đích, mỗi dòng mang cust_id, loại liên hệ, số thứ tự (seq, chính là vị trí VM — hữu ích để biết đâu là số/địa chỉ ưu tiên), và giá trị. Việc gắn seq theo đúng thứ tự VM là điểm hay bị bỏ sót: nhiều nghiệp vụ quy ước value đầu tiên là giá trị chính (primary), nên đảo thứ tự khi explode sẽ làm sai ý nghĩa dữ liệu.
Tương tự, các field như lịch trả nợ, danh sách người ký, danh sách charge của một giao dịch... đều là multivalue và đều cần flatten theo cùng nguyên tắc.
Ghi nhớ
- Application → FILE, mỗi bản ghi có @ID. FILE là kho key–value;
@IDlà khoá nghiệp vụ, đọc theo@IDcực nhanh nhưng "query ngang" cần chỉ mục/quét. - Bốn cấp phân tách:
FMCHAR(254) ngăn field ·VMCHAR(253) ngăn multivalue ·SMCHAR(252) ngăn subvalue ·TMCHAR(251) cấp thấp nhất. - Không normalize mà embed: dữ liệu lặp nhúng ngay trong bản ghi cha → đọc nhanh, nhưng không query kiểu SQL và bắt buộc flatten khi đưa ra DWH.
- LRF (Local Reference) mở rộng field theo vị trí — phải tra định nghĩa mới hiểu nghĩa.
- Audit fields cuối bản ghi:
RECORD.STATUS,CURR.NO,INPUTTER,AUTHORISER,DATE.TIME,CO.CODE,DEPT.CODE— hiện thực maker-checker (input → authorise). - Ba nơi lưu: LIVE (file chính, đã duyệt) ·
$NAU(chưa duyệt — đừng lấy) ·$HIS(lịch sử). Tiền tố tên file:F.,FBNK.(theo company),I_,EB.*. - Metadata điều khiển:
STANDARD.SELECTION= từ điển field (tên/kiểu/độ dài/multivalue), nền cho ENQUIRY/VERSION ·PGM.FILE= đăng ký application và loại (Hhồ sơ tĩnh,U/Tgiao dịch). Gắn với khái niệm DICT/dictionary. - Ba việc cho Data: explode VM thành nhiều dòng · giữ
@IDlàm business key · phân biệt LIVE/$NAU/$HIS.
Nắm được hình dạng dữ liệu này, bạn đã sẵn sàng cho hai bài kế: VERSION/ENQUIRY — cách người dùng nhập và truy vấn trên đúng mô hình này, và OFS — cách hệ thống ngoài đọc/ghi vào T24 mà vẫn tôn trọng maker-checker và cấu trúc multivalue.
Bài viết liên quan
Dòng chảy dữ liệu core -> ODS -> DWH -> BI, mô hình dữ liệu cốt lõi và bộ ví dụ SQL thực hành chạy được.
Mô hình dữ liệu giao dịch thẻ, các KPI thẻ, phân tích chi tiêu & phát hiện gian lận, kèm ví dụ SQL chạy được trên sandbox.
Bản chất kinh doanh của ngân hàng: trung gian tài chính, bảng cân đối, NIM và vì sao dữ liệu quan trọng.
Kiến trúc core banking, CIF, các phân hệ và xử lý online vs batch/EOD.