Files
alla-allaos-fullstack/docs/setup/csv-template-spec.md
phaichayon 0ae4ae3e38 task-d.7.2
2026-07-02 13:42:09 +07:00

25 KiB

CSV Template Specification

Source task: plans/task-d.7.1.md

All supported CSV imports must run in two phases:

  1. Preview: parse, validate, resolve references, detect duplicates, and produce an import report.
  2. Commit: upsert in a transaction where database-only writes are involved.

CSV imports must not bypass feature/foundation services once those services exist. Where current seed logic only exists in scripts, D.7.2+ should extract reusable server services first.

Supported Templates

organizations.csv

Purpose: create tenant organizations. Target: organizations. Seed type: organization. Required columns: organization_code, organization_name, slug, created_by_email. Optional columns: tax_id, default_currency, phone, email, address, logo_url, plan, status. Generated columns: id, created_at, updated_at. Validation rules: slug lowercase and unique; organization_code uppercase; created_by_email must resolve to a user. Relationship resolution: created_by_email -> users.id. Duplicate detection: existing organization by slug. Upsert key: slug. Import order: 02.

organization_code,organization_name,slug,created_by_email,tax_id,default_currency,status
ALLA,ALLA Public Company Limited,alla,admin@example.com,0107558000393,THB,active

Error examples: duplicate slug with conflicting name; missing creator user; invalid lowercase/uppercase format.

users.csv

Purpose: create setup-managed users. Target: users through auth/user service. Seed type: organization. Required columns: email, name, system_role. Optional columns: password, active_organization_code, image_url, reset_password. Generated columns: id, password_hash, created_at, updated_at. Validation rules: email format; system_role in super_admin,user; password required for new credential users unless invitation flow exists. Relationship resolution: active_organization_code -> organizations.slug or setup organization_code. Duplicate detection: existing user by email. Upsert key: email. Import order: 01.

email,name,system_role,password,active_organization_code,reset_password
admin@example.com,System Administrator,super_admin,ChangeMe123!,ALLA,true

Error examples: invalid email; unsupported system role; existing user without reset permission.

memberships.csv

Purpose: grant app-level organization access. Target: memberships. Seed type: organization. Required columns: organization_code, user_email, membership_role, business_role. Optional columns: permissions, branch_scope_codes, product_type_scope_codes. Generated columns: id, timestamps. Validation rules: membership_role in admin,user; business_role should be a known CRM role fallback code; scope codes must resolve when provided. Relationship resolution: organization, user, branch options, product type options. Duplicate detection: existing membership by organization_id + user_id. Upsert key: organization_code + user_email. Import order: 03.

organization_code,user_email,membership_role,business_role,permissions,branch_scope_codes,product_type_scope_codes
ALLA,admin@example.com,admin,crm_admin,crm.dashboard.read|crm.role.read,head_office,crane|dockdoor

Error examples: unknown user; unknown organization; invalid branch/product type code.

crm-role-assignments.csv

Purpose: assign CRM role profiles and CRM scopes. Target: crm_user_role_assignments. Seed type: organization. Required columns: organization_code, user_email, crm_role_code, is_primary, branch_scope_mode, product_type_scope_mode. Optional columns: branch_codes, product_type_codes, is_active. Generated columns: id, assigned_at, timestamps. Validation rules: role profile must exist; scope mode in all,selected,none,inherit; selected modes require matching codes. Relationship resolution: user, organization, role profile, branch options, product type options. Duplicate detection: existing assignment by organization_id + user_id + role_profile_id. Upsert key: organization_code + user_email + crm_role_code. Import order: 05.

organization_code,user_email,crm_role_code,is_primary,branch_scope_mode,branch_codes,product_type_scope_mode,product_type_codes,is_active
ALLA,admin@example.com,crm_admin,true,all,,all,,true

Error examples: selected scope without codes; role profile missing; multiple primary rows for one user unless explicit replacement mode.

master-options.csv

Purpose: import governed option rows. Target: ms_options. Seed type: foundation. Required columns: organization_code, category, code, label. Optional columns: value, parent_category, parent_code, sort_order, is_active, metadata_json. Generated columns: id, timestamps. Validation rules: category/code non-empty; parent resolves in same organization when provided; metadata must be valid JSON. Relationship resolution: organization, optional parent option. Duplicate detection: existing option by organization_id + category + code. Upsert key: organization_code + category + code. Import order: 06.

organization_code,category,code,label,value,parent_category,parent_code,sort_order,is_active,metadata_json
ALLA,crm_customer_group,industrial,Industrial,industrial,,,1,true,{}

Error examples: invalid JSON; missing parent option; duplicate category/code in same CSV with conflicting labels.

branches.csv

Purpose: typed convenience template for branch options. Target: ms_options with category=crm_branch. Seed type: organization. Required columns: organization_code, branch_code, branch_name. Optional columns: prefix, address, tax_id, phone, email, sort_order, is_active. Generated columns: id, category, timestamps. Validation rules: branch code unique per organization; code lowercase snake_case recommended; metadata fields serialized into option metadata. Relationship resolution: organization. Duplicate detection: existing crm_branch option by code. Upsert key: organization_code + branch_code. Import order: 07.

organization_code,branch_code,branch_name,prefix,address,tax_id,sort_order,is_active
ALLA,head_office,Head Office,HO,99/9 Rama IX Road,0107558000393,1,true

Error examples: duplicate branch code; invalid organization; malformed metadata.

product-types.csv

Purpose: typed convenience template for product type options. Target: ms_options with category=crm_product_type. Seed type: organization. Required columns: organization_code, product_type_code, product_type_name. Optional columns: document_prefix, sort_order, is_active, metadata_json. Generated columns: id, category, timestamps. Validation rules: product type code unique per organization; document_prefix uppercase recommended. Relationship resolution: organization. Duplicate detection: existing crm_product_type option by code. Upsert key: organization_code + product_type_code. Import order: 08.

organization_code,product_type_code,product_type_name,document_prefix,sort_order,is_active
ALLA,crane,Crane,CR,1,true

Error examples: duplicate product type code; invalid JSON metadata; unsupported inactive default product type for document sequence.

document-sequences.csv

Purpose: configure document numbering. Target: document_sequences. Seed type: foundation. Required columns: organization_code, document_type, prefix, period. Optional columns: branch_code, product_type_code, current_number, padding_length, format, reset_policy, is_active. Generated columns: id, timestamps. Validation rules: document type supported by sequence foundation; branch/product type resolve or default to generic scope; current number non-negative integer. Relationship resolution: organization, branch option, product type option. Duplicate detection: organization_id + branch_id + product_type + document_type + period. Upsert key: same as duplicate detection. Import order: 14.

organization_code,branch_code,product_type_code,document_type,prefix,period,current_number,padding_length,format,reset_policy,is_active
ALLA,head_office,crane,quotation,QT-HO-CR-,2607,0,3,{prefix}{period}-{running},period,true

Error examples: unknown branch; unknown product type; malformed format missing {running}.

approval-workflows.csv

Purpose: configure approval workflow headers. Target: crm_approval_workflows. Seed type: foundation. Required columns: organization_code, workflow_code, workflow_name, entity_type. Optional columns: description, is_system, is_active. Generated columns: id, timestamps. Validation rules: workflow code unique per organization; entity type supported, currently quotation. Relationship resolution: organization. Duplicate detection: organization_id + workflow_code. Upsert key: organization_code + workflow_code. Import order: 15.

organization_code,workflow_code,workflow_name,entity_type,description,is_system,is_active
ALLA,quotation_standard,Quotation Standard Approval,quotation,Default quotation approval,false,true

Error examples: duplicate workflow code; unsupported entity type.

approval-steps.csv

Purpose: configure workflow steps. Target: crm_approval_steps. Seed type: foundation. Required columns: organization_code, workflow_code, step_number, role_code, role_name. Optional columns: approval_mode, is_required, sla_hours, calendar_mode, timeout_action. Generated columns: id, timestamps. Validation rules: workflow resolves; step number positive integer; role code known to CRM role profiles or approved workflow roles. Relationship resolution: organization, approval workflow. Duplicate detection: workflow_id + step_number. Upsert key: organization_code + workflow_code + step_number. Import order: 16.

organization_code,workflow_code,step_number,role_code,role_name,approval_mode,is_required,sla_hours,calendar_mode,timeout_action
ALLA,quotation_standard,1,sales_manager,Sales Manager,sequential,true,24,calendar_days,none

Error examples: missing workflow; duplicate step number; invalid SLA value.

approval-matrix.csv

Purpose: map approval workflows to entity/scope/amount. Target: crm_approval_matrices. Seed type: foundation. Required columns: organization_code, entity_type, workflow_code, priority, is_default. Optional columns: branch_code, product_type_code, min_amount, max_amount, currency, is_active, description. Generated columns: id, timestamps. Validation rules: workflow resolves; branch/product optional; amount range valid; at most one default per target policy unless replacement mode. Relationship resolution: organization, workflow, branch option, product type option. Duplicate detection: default matrix by organization + entity_type + is_default or scoped matrix by full scope/amount tuple. Upsert key: organization_code + entity_type + workflow_code + priority + scope. Import order: 17.

organization_code,entity_type,workflow_code,branch_code,product_type_code,min_amount,max_amount,currency,priority,is_default,is_active,description
ALLA,quotation,quotation_standard,head_office,crane,0,5000000,THB,100,true,true,Default crane approval

Error examples: max less than min; missing workflow; unresolved currency option.

customers.csv

Purpose: import CRM customers. Target: crm_customers. Seed type: business. Required columns: organization_code, customer_code, customer_name, customer_type, customer_status, created_by_email. Optional columns: branch_code, abbr, tax_id, address, province, district, sub_district, postal_code, country, phone, fax, email, website, lead_channel, customer_group, customer_sub_group, owner_user_email, notes, is_active. Generated columns: id, timestamps, owner assignment timestamps if owner provided. Validation rules: code unique per organization; option references resolve; email format when provided. Relationship resolution: organization, branch, owner user, creator user, master options. Duplicate detection: organization_id + customer_code. Upsert key: organization_code + customer_code. Import order: 30.

organization_code,customer_code,customer_name,customer_type,customer_status,owner_user_email,created_by_email,branch_code,customer_group,email,phone
ALLA,CUS-001,Siam Manufacturing,company,active,sales.crane.uat@alla.local,admin@example.com,head_office,industrial,contact@siam.example,02-000-1000

Error examples: unresolved owner; invalid customer group/sub-group relationship; duplicate customer code.

contacts.csv

Purpose: import customer contacts. Target: crm_customer_contacts. Seed type: business. Required columns: organization_code, customer_code, contact_name, created_by_email. Optional columns: position, department, phone, mobile, email, is_primary, notes, is_active. Generated columns: id, timestamps. Validation rules: customer resolves; email format; one primary contact warning when multiple rows set primary. Relationship resolution: organization, customer, creator user. Duplicate detection: organization + customer + email when email exists, otherwise customer + contact name. Upsert key: organization_code + customer_code + email/contact_name. Import order: 32.

organization_code,customer_code,contact_name,email,mobile,position,is_primary,created_by_email
ALLA,CUS-001,Anan Sales,anan@siam.example,081-000-0001,Procurement Manager,true,admin@example.com

Error examples: missing customer; duplicate primary contact warning; invalid email.

contact-shares.csv

Purpose: import contact sharing grants. Target: crm_contact_shares. Seed type: business. Required columns: organization_code, customer_code, contact_email, shared_to_user_email, shared_by_user_email. Optional columns: remark, is_active. Generated columns: id, shared_at, timestamps. Validation rules: contact resolves; users resolve; cannot share to user outside organization membership. Relationship resolution: organization, customer, contact, users. Duplicate detection: organization_id + contact_id + shared_to_user_id. Upsert key: same as duplicate detection. Import order: 33.

organization_code,customer_code,contact_email,shared_to_user_email,shared_by_user_email,remark,is_active
ALLA,CUS-001,anan@siam.example,sales.dockdoor.uat@alla.local,admin@example.com,Shared for joint account coverage,true

Error examples: contact not found; target user has no membership; self-share warning.

leads.csv

Purpose: import marketing-owned leads. Target: crm_leads. Seed type: business. Required columns: organization_code, lead_code, status, created_by_email. Optional columns: branch_code, customer_code, contact_email, description, project_name, project_location, lead_channel, product_type_code, priority, estimated_value, awareness_code, followup_status, lost_reason, outcome, owner_marketing_user_email, assigned_sales_owner_email, assignment_remark. Generated columns: id, assignment timestamps when assigned, timestamps. Validation rules: status/priority/product type resolve; customer/contact relationship valid; estimated value numeric. Relationship resolution: organization, branch, customer, contact, users, master options. Duplicate detection: organization_id + lead_code. Upsert key: organization_code + lead_code. Import order: 34.

organization_code,lead_code,status,created_by_email,customer_code,contact_email,branch_code,product_type_code,priority,project_name,owner_marketing_user_email,assigned_sales_owner_email
ALLA,LD-001,assigned,mk.uat@alla.local,CUS-001,anan@siam.example,head_office,crane,high,Warehouse Crane,mk.uat@alla.local,sales.crane.uat@alla.local

Error examples: contact does not belong to customer; unresolved status option; assignee outside organization.

opportunities.csv

Purpose: import sales opportunities. Target: crm_opportunities. Seed type: business. Required columns: organization_code, opportunity_code, customer_code, title, product_type_code, status, priority, created_by_email, updated_by_email. Optional columns: lead_code, contact_email, branch_code, description, requirement, project_name, project_location, outcome_status, lead_channel, estimated_value, chance_percent, expected_close_date, competitor, source, notes, is_hot_project, pipeline_stage, assigned_to_user_email. Generated columns: id, assignment timestamps when assigned, lifecycle timestamps where appropriate. Validation rules: product/status/priority resolve; percent 0-100; dates ISO YYYY-MM-DD; lead optional. Relationship resolution: organization, lead, customer, contact, users, options. Duplicate detection: organization_id + opportunity_code. Upsert key: organization_code + opportunity_code. Import order: 36.

organization_code,opportunity_code,customer_code,title,product_type_code,status,priority,created_by_email,updated_by_email,branch_code,contact_email,lead_code,chance_percent,assigned_to_user_email
ALLA,OP-001,CUS-001,Warehouse Crane Expansion,crane,negotiation,high,sales.crane.uat@alla.local,sales.crane.uat@alla.local,head_office,anan@siam.example,LD-001,70,sales.crane.uat@alla.local

Error examples: chance percent outside range; unresolved lead; contact/customer mismatch.

opportunity-parties.csv

Purpose: import opportunity project parties. Target: crm_opportunity_customers. Seed type: business. Required columns: organization_code, opportunity_code, customer_code, role_code. Optional columns: remark. Generated columns: id, timestamps. Validation rules: opportunity/customer resolve; project party role resolves. Relationship resolution: opportunity, customer, role option. Duplicate detection: opportunity_id + customer_id + role. Upsert key: same as duplicate detection. Import order: 37.

organization_code,opportunity_code,customer_code,role_code,remark
ALLA,OP-001,CUS-001,end_customer,Primary project owner

Error examples: unknown role; opportunity not found; duplicate role/customer row.

quotations.csv

Purpose: import quotation headers. Target: crm_quotations. Seed type: business. Required columns: organization_code, quotation_code, customer_code, quotation_date, quotation_type, status, currency, subtotal, total_amount, created_by_email, updated_by_email. Optional columns: opportunity_code, contact_email, branch_code, valid_until, project_name, project_location, attention, reference, notes, revision, parent_quotation_code, revision_remark, exchange_rate, discount, discount_type, tax_rate, tax_amount, chance_percent, is_hot_project, competitor, salesman_email, is_sent, sent_at, sent_via. Generated columns: id, timestamps, approval/snapshot/artifact fields remain runtime generated. Validation rules: status/currency/type resolve; amounts numeric; parent quotation resolves for revision imports. Relationship resolution: organization, opportunity, customer, contact, branch, options, users. Duplicate detection: organization_id + quotation_code. Upsert key: organization_code + quotation_code. Import order: 40.

organization_code,quotation_code,customer_code,quotation_date,quotation_type,status,currency,subtotal,total_amount,created_by_email,updated_by_email,opportunity_code,branch_code,salesman_email
ALLA,QT-HO-CR-2607-001,CUS-001,2026-07-02,crane,draft,THB,1000000,1070000,sales.crane.uat@alla.local,sales.crane.uat@alla.local,OP-001,head_office,sales.crane.uat@alla.local

Error examples: parent revision missing; total mismatch warning; approved/runtime fields supplied.

quotation-items.csv

Purpose: import quotation line items. Target: crm_quotation_items. Seed type: business. Required columns: organization_code, quotation_code, item_number, product_type_code, description, quantity, unit_price, total_price. Optional columns: unit, discount, discount_type, tax_rate, notes, sort_order. Generated columns: id, timestamps. Validation rules: numeric amount fields; product type resolves; quotation resolves. Relationship resolution: quotation, product type, unit, discount type. Duplicate detection: quotation_id + item_number. Upsert key: organization_code + quotation_code + item_number. Import order: 41.

organization_code,quotation_code,item_number,product_type_code,description,quantity,unit,unit_price,discount,discount_type,tax_rate,total_price,sort_order
ALLA,QT-HO-CR-2607-001,1,crane,Crane installation package,1,set,1000000,0,,7,1000000,1

Error examples: missing quotation; invalid item number; total calculation warning.

quotation-parties.csv

Purpose: import quotation project parties. Target: crm_quotation_customers. Seed type: business. Required columns: organization_code, quotation_code, customer_code, role_code. Optional columns: is_primary, remark. Generated columns: id, timestamps. Validation rules: quotation/customer resolve; role resolves; one primary warning per role as applicable. Relationship resolution: quotation, customer, project party role option. Duplicate detection: quotation_id + customer_id + role. Upsert key: same as duplicate detection. Import order: 42.

organization_code,quotation_code,customer_code,role_code,is_primary,remark
ALLA,QT-HO-CR-2607-001,CUS-001,end_customer,true,Primary quotation customer

Error examples: missing quotation; unknown project party role; duplicate primary warning.

quotation-topics.csv

Purpose: import quotation topic headers. Target: crm_quotation_topics. Seed type: business. Required columns: organization_code, quotation_code, topic_key, topic_type, title. Optional columns: sort_order. Generated columns: id, timestamps. Validation rules: quotation resolves; topic type resolves; topic key unique per quotation CSV batch. Relationship resolution: quotation, topic type option. Duplicate detection: quotation_id + topic_key. Upsert key: organization_code + quotation_code + topic_key. Import order: 43.

organization_code,quotation_code,topic_key,topic_type,title,sort_order
ALLA,QT-HO-CR-2607-001,scope-main,scope,Scope of Work,1

Error examples: topic type missing; duplicate topic key.

quotation-topic-items.csv

Purpose: import quotation topic rows. Target: crm_quotation_topic_items. Seed type: business. Required columns: organization_code, quotation_code, topic_key, content. Optional columns: sort_order. Generated columns: id, timestamps. Validation rules: topic key resolves from imported or existing topic; content required. Relationship resolution: quotation topic. Duplicate detection: topic_id + sort_order + content. Upsert key: organization_code + quotation_code + topic_key + sort_order. Import order: 44.

organization_code,quotation_code,topic_key,content,sort_order
ALLA,QT-HO-CR-2607-001,scope-main,Supply and install one overhead crane system,1

Error examples: missing topic; empty content; duplicate sort order warning.

Unsupported or Deferred Templates

departments.csv

Status: unsupported pending schema. No first-class department table was identified. Do not map this to ad hoc options without an ADR.

department_code,department_name
SALES,Sales

teams.csv

Status: unsupported pending schema. Team scope limitations are documented; no first-class team graph exists.

team_code,team_name
SALES-CRANE,Crane Sales Team

warehouses.csv

Status: unsupported pending schema. No warehouse table was identified.

warehouse_code,warehouse_name
MAIN,Main Warehouse

sites.csv

Status: unsupported pending schema. Project/customer site is currently represented by text fields such as project_location, not a reusable site entity.

site_code,site_name,address
BKK-HQ,Bangkok HQ,99/9 Rama IX Road

services.csv

Status: unsupported pending schema. Service catalog does not currently exist as first-class CRM data.

service_code,service_name
INSTALL,Installation Service

price-books.csv

Status: unsupported pending schema. Current quotation items are not backed by a price-book foundation.

price_book_code,product_or_service_code,currency,unit_price
STD-THB,INSTALL,THB,10000

tax-rates.csv

Status: unsupported pending schema. Tax rate currently lives as numeric fields on quotation/item rows.

tax_code,tax_name,tax_rate
VAT7,VAT 7%,7

attachments.csv

Status: deferred. Attachment metadata exists, but binary upload/storage import is not safe as a generic CSV-only flow.

entity_type,entity_code,file_path,description
quotation,QT-HO-CR-2607-001,./files/spec.pdf,Customer specification

email-settings.csv

Status: unsupported pending schema. Email configuration appears environment/provider driven; verification can check readiness but CSV import should not persist secrets without a secure configuration design.

provider,host,port,from_address
smtp,smtp.example.com,587,no-reply@example.com