Skip to main content

Friend Import & Mapping

Overview

This domain has three tables covering two mechanisms. line_user_import and line_user_import_detail handle importing new friends from a file (job header plus per-row detail), while import_mapping_job handles updating existing friends from a CSV by matching rows on a chosen unique key.

Table line_user_import

ColumnTypeNullableDefaultDescription
idINTEGERNOT NULLnextval (serial)Primary key of the import job
line_oa_idINTEGERNOT NULLTarget LINE OA channel for the import
titleTEXTNOT NULLUser-supplied name for the import job
file_nameTEXTNOT NULLOriginal uploaded file name
file_pathTEXTNOT NULLStorage path of the uploaded file
archive_pathTEXTNULLPath the file is moved to once processing completes
created_byINTEGERNOT NULL0User id who started the import
total_recordsINTEGERNOT NULL0Total number of records in the file
total_processedINTEGERNOT NULL0Number of records processed so far
process_attemptINTEGERNOT NULL0Number of processing attempts (used to cap retries)
statusLineUserImportStatus (enum)NOT NULLnewJob status: new, processing, completed, failed
summary_statsJSONBNULLImport summary, e.g. counts of inserted / duplicate / malformed rows
noteTEXTNULLFree-text note about the import job
organization_idINTEGERNOT NULLOrganization owning the job
created_dateTIMESTAMPTZ(3)NOT NULLCURRENT_TIMESTAMPJob creation timestamp
updated_dateTIMESTAMPTZ(3)NULLLast update timestamp
deleted_dateTIMESTAMPTZ(3)NULLSoft-delete timestamp

Table line_user_import_detail

ColumnTypeNullableDefaultDescription
idUUIDNOT NULLgen_random_uuid()Primary key of the detail row
import_idINTEGERNOT NULLImport job this row belongs to (FK to line_user_import.id)
line_oa_idINTEGERNOT NULLTarget LINE OA channel
line_user_idTEXTNOT NULLLINE user ID read from the file
line_user_profileJSONBNULLProfile fetched from the LINE API for this user ID
statusLineUserImportDetailStatus (enum)NOT NULLnewRow outcome: new, insert (added), exist (already present), undefined (not found on LINE), error_format (malformed)
error_messageTEXTNULLError description for this row
organization_idINTEGERNOT NULLOrganization owning the data
created_dateTIMESTAMPTZ(3)NOT NULLCURRENT_TIMESTAMPCreation timestamp
updated_dateTIMESTAMPTZ(3)NULLLast update timestamp
deleted_dateTIMESTAMPTZ(3)NULLSoft-delete timestamp

Table import_mapping_job

ColumnTypeNullableDefaultDescription
idINTEGERNOT NULLnextval (serial)Primary key of the mapping job
line_oa_idINTEGERNOT NULLLINE OA channel whose friend data will be updated
organization_idINTEGERNOT NULLOrganization owning the job
file_nameTEXTNOT NULLOriginal CSV file name
file_pathTEXTNOT NULLStorage path of the uploaded file
statusVARCHAR(20)NOT NULL'pending'Job status: pending, processing, success, partial, failed
unique_keyJSONBNOT NULLKey used to match CSV rows against line_user
mappingsJSONBNOT NULLCSV-column-to-target-field mappings (JSON array)
validationJSONBNULLPre-import validation summary (total / will update / no match / errors)
statsJSONBNULLFinal counts after processing (total, updated, skipped, errors)
error_log_pathTEXTNULLPath to the per-row error log file
created_byINTEGERNULLUser id who started the job
created_dateTIMESTAMPTZNOT NULLnow()Job creation timestamp
updated_dateTIMESTAMPTZNULLLast update timestamp
deleted_dateTIMESTAMPTZNULLSoft-delete timestamp

Notes

  • Foreign key: line_user_import_detail.import_id -> line_user_import.id. import_mapping_job has no FK constraints — its references are logical only.
  • Indexes: line_user_import is indexed on line_oa_id; import_mapping_job has import_mapping_job_oa_idx on (line_oa_id, status).
  • import_mapping_job is absent from schema.prisma. It was created via manual SQL (manual-sql/9.import_mapping.sql) and is processed asynchronously by worker-go through a queue of the same name. That is why its timestamps are plain TIMESTAMPTZ and status is a VARCHAR(20) rather than an enum.
  • unique_key is a JSON object shaped like {"field":"mobile_no","csvColumn":"Phone Number"}, where field may be a line_user column or a custom attribute in the form custom.<key>.
  • mappings is a JSON array shaped like [{"csvColumn":"Member Tier","target":"custom.member_tier"}], where target points at a line_user column or a key inside custom_attribute.
  • The import-mapping module is registered in system_module with full grants for roles 1-2 and readAll,read only for role 3, as defined in manual-sql/9.import_mapping.sql.