FM-06 — Sweater / Crewneck, set gia đình [Thương hiệu mới — chờ CEO chốt tên]

Sản phẩm: sweater/crewneck, hero Q4, bán theo set gia đình, cùng 1 text cho cả set. FM-06 là câu chữ buổi sáng Giáng sinh do khách tự nhập. Text chỉ là họ thì theo BA AC-A13 chỉ gợi ý chuyển FM-01, không chặn cứng ở giai đoạn A, vì hệ thống không phân biệt chắc chắn họ với từ đơn lẻ khác. Motto chung không gắn buổi sáng Giáng sinh thuộc FM-09 — giai đoạn A chỉ ghi chú routing này, Dev không tự phân loại motto.

Giá: TRỐNG / PLACEHOLDER — chưa có giá thật, chưa có báo giá Gate 1  |  Thời gian sản xuất / ship: TRỐNG / PLACEHOLDER — chưa có số thật  |  Không giảm giá, không miễn phí ship, không hứa giao trước Noel khi chưa có số thật.

Live preview — SVG từ chính phôi (US-A1, US-A6, AC-A1, AC-A8)

PHÔI PLACEHOLDER — CHỜ DESIGN/CEO DUYỆT — phôi hiện tại là phôi concept v1 (sweater-crewneck-blank-template-20261030.svg, viewBox 800×900, layer thân áo / vùng in / chữ), chưa phải phôi thật đã duyệt. Nguồn phôi: design_blank, cấm ai_image.

Proof preview — kiểm tra chính tả và bố cục, chưa phải cam kết giống 100% file in.

Vùng in đề xuất x=250, y=230, rộng 300, cao 340 — chưa phải template nhà cung cấp. Preview render từ chính object PrintParams ở dưới, không render từ ảnh chụp/mockup riêng, không vẽ lại.

PRINT AREA — PROPOSED, PENDING SUPPLIER TEMPLATECOZYCHRISTMASMORNING2026

Font: đang kiểm tra Archivo Black…

Cỡ preview tham chiếu, chưa phải kích thước in theo từng size. Preview hiển thị ở 1 cỡ tham chiếu cố định (M = 100%: text 48, năm 36 trong đơn vị viewBox SVG), không đổi theo size thành viên. Đổi size thành viên không làm đổi preview tham chiếu và không làm hết hiệu lực proof ở giai đoạn A, vì size không nằm trong PrintParams — kích thước in theo từng size chờ Design chốt ở giai đoạn B. Đây là sửa Lệch 1 theo phương án BA khuyến nghị: bỏ SCALE khỏi preview. Quyết định CEO chiều 30/10 xác nhận lại: size chỉ đổi size áo, không đổi font-size trong PrintParams và proof; nếu sau này CEO/Design yêu cầu giữ scale thì phải đưa scale vào PrintParams và proof, không được để preview lệch khỏi proof.

1. Màu — clone màu (US-A2, AC-A2)

Cơ chế clone: đổi colorway chỉ đổi background_hex và text_hex, vị trí, kích thước, font, nội dung text, năm giữ nguyên tuyệt đối. Bảng màu giai đoạn A là placeholder, ghi rõ chờ chốt, không claim là màu in thật đã QC.

2. Custom text FM-06 — 3 ô dòng riêng (US-A3, AC-A3, AC-A4)

Đếm ký tự theo BA: đếm sau khi trim khoảng trắng đầu/cuối mỗi dòng, khoảng trắng thừa liên tiếp trong dòng giữ nguyên khi đếm và khi hiển thị. Dòng 1 bắt buộc, dòng 2 và 3 tùy chọn. Paste nhiều dòng: tách theo xuống dòng, nếu quá 3 dòng thì báo lỗi, không tự gộp/bỏ dòng.

Tổng sau trim: 20 / 30 ký tự. Line 1: 4 / 15. Line 2: 9 / 15. Line 3: 7 / 15. Số dòng có nội dung: 3 / 3.

Validation đạt — đủ điều kiện proof (vẫn chỉ là demo, không phải đơn hàng).

Ký tự cho phép duy nhất: A-Z, a-z, 0-9, khoảng trắng, ', -, &. Cấm emoji, © ® ™, mọi ký tự đặc biệt khác, dấu tiếng nước ngoài — trừ khi font in đã xác nhận hỗ trợ và CEO/PM cập nhật danh sách bằng văn bản. Ký tự vi phạm được nêu rõ, hệ thống không tự thay thế/loại bỏ rồi in. Vượt giới hạn thì chặn, yêu cầu rút ngắn, không tự cắt ngắn, không tự xuống dòng thay khách, không tự sửa chính tả, hoa/thường, không tự sửa nội dung khách.

3. Năm — trường riêng bắt buộc, dropdown từ cấu hình (US-A4, AC-A5, AC-A6)

Danh sách năm lấy từ bảng cấu hình year_options (có cờ active), không hard-code vĩnh viễn. Giá trị mặc định gợi ý cho mùa sắp tới là 2026. Giai đoạn A: danh sách năm trong cấu hình là placeholder, Dev ghi rõ chờ CEO chốt dải năm trước khi mở bán thật. Năm hiển thị ở dòng cuối riêng, cùng font, cùng màu, căn giữa, không gộp năm vào text field.

4. Set gia đình — nhập 1 lần (US-A8, AC-A10)

Một bản ghi Customization dùng chung cho cả set, 1 colorway cho cả set (đúng ý “1 look chung”). Mỗi người trong set chỉ chọn nhãn thành viên (Người 1, Người 2… — FM-06 không thu thập tên riêng từng người) + size_id. Không có ô text/năm riêng cho từng người, từng size. Nếu CEO/PM muốn màu riêng từng người thì cần brief bổ sung, Dev không tự mở thêm.

Người 1 — chỉ chọn size, không thu thập tên riêng từng người
Người 2 — chỉ chọn size, không thu thập tên riêng từng người
Thành viênSizeText áp chung
Người 1MCOZY / CHRISTMAS / MORNING + 2026
Người 26-8YCOZY / CHRISTMAS / MORNING + 2026

Cả set trỏ về cùng 1 customization_id: customization-placeholder-pending. Preview là cỡ tham chiếu M cố định, chưa phải kích thước in theo từng size.

5. Proof step bắt buộc — 2 tick riêng, snapshot tự hết hiệu lực (US-A7, AC-A9)

Sẽ in: COZY / CHRISTMAS / MORNING — Năm: 2026 — Màu: Clone 1 — đỏ đậm — Set: 2 thành viên, cùng 1 text, 1 colorway.

Chưa tick proof — hãy tick cả 2 ô proof ở trên.

Ở giai đoạn A, “đi tiếp” nghĩa là lưu bản nháp customization đã proof, chưa phải đặt hàng/thanh toán thật. Nếu sửa bất kỳ trường nào trong print_params sau khi tick (text, năm, màu, font, vị trí), proof tự động hết hiệu lực, 2 tick reset về chưa tick, khách phải xem lại preview và tick lại.

Thông số nguồn chung — theo mô hình dữ liệu BA §5

Preview canvas/SVG render từ object PrintParams này; file in giai đoạn B xuất từ đúng object này, không vẽ lại. Client validation trong demo chỉ để trải nghiệm nhanh, không thay server validation — server phải kiểm tra lại toàn bộ AC-A3, AC-A4, AC-A5, AC-A7 trước khi lưu.

Next.js — Server validation theo Bổ sung S1 của BA: API route app/api/validate/route.js dùng chung lib lib/validation.js, kiểm tra lại AC-A3, AC-A4, AC-A5, AC-A7 độc lập với client. Nút lưu bản nháp gọi API route trước, chỉ lưu trong bộ nhớ demo khi API trả về ĐẠT và proof đã xác nhận. API route chỉ trả về kết quả validation, không lưu trữ, không tạo đơn, không thanh toán, không gửi nhà cung cấp — chưa phải lưu trữ thật hay chuyển staging. Server live, lưu trữ thật và tích hợp nhà cung cấp vẫn là giai đoạn B, sau khi CEO duyệt phôi/font/preview và Gate 1 có báo giá thật.

{
  "product": {
    "id": "product-fm06-placeholder",
    "code": "FM-06",
    "name": "[Tên sản phẩm FM-06 — PLACEHOLDER]",
    "brand_name": "[Thương hiệu mới — chờ CEO chốt tên] — PLACEHOLDER",
    "product_type": "sweater / crewneck",
    "occasion": "Christmas morning",
    "blank_id": "blank-placeholder-v1-20261030",
    "status": "dev_draft"
  },
  "blank": {
    "id": "blank-placeholder-v1-20261030",
    "name": "Sweater / crewneck blank template v1 20261030",
    "garment_form": "crewneck — PLACEHOLDER, chờ Design/CEO duyệt phôi thật",
    "print_area": {
      "x": 250,
      "y": 230,
      "width": 300,
      "height": 340,
      "unit": "px",
      "note": "PROPOSED, PENDING SUPPLIER TEMPLATE"
    },
    "layers": [
      "body",
      "print_area",
      "text"
    ],
    "is_placeholder": true,
    "source": "design_blank"
  },
  "colorway": {
    "id": "clone1-uuid-placeholder",
    "product_id": "product-fm06-placeholder",
    "colorway_name": "Clone 1 — đỏ đậm",
    "background_hex": "#7A1E28",
    "text_hex": "#FFFFFF",
    "is_placeholder": true
  },
  "font_art": {
    "id": "font-art-placeholder-archivo-black",
    "kind": "font",
    "font_name": "Archivo Black (placeholder, fallback Montserrat ExtraBold)",
    "commercial_license": "OFL trên Google Fonts — PHẢI kiểm tra lại tại thời điểm tích hợp, chưa phải xác nhận pháp lý cuối",
    "web_file": "WOFF2 — chưa có file chính thức",
    "print_file": "OTF/TTF — chưa có file chính thức",
    "supported_characters": "A-Z, a-z, 0-9, khoảng trắng, ', -, & (AC-A4)",
    "knit_limits": "PENDING — chờ nhà cung cấp dệt jacquard xác nhận nét tối thiểu và số màu chỉ",
    "is_placeholder": true
  },
  "customization": {
    "id": "customization-placeholder-pending",
    "product_id": "product-fm06-placeholder",
    "line1": "COZY",
    "line2": "CHRISTMAS",
    "line3": "MORNING",
    "total_chars": 20,
    "year": 2026,
    "colorway_id": "clone1-uuid-placeholder",
    "font_art_id": "font-art-placeholder-archivo-black",
    "display_lines": [
      "COZY",
      "CHRISTMAS",
      "MORNING",
      "2026"
    ],
    "content_review_status": "pending_review",
    "supplier_gate_status": "not_submitted"
  },
  "year_options": [
    {
      "year": 2025,
      "is_active": true,
      "sort_order": 1
    },
    {
      "year": 2026,
      "is_active": true,
      "sort_order": 2
    },
    {
      "year": 2027,
      "is_active": true,
      "sort_order": 3
    }
  ],
  "family_set_draft": {
    "id": "family-set-draft-placeholder",
    "customization_id": "customization-placeholder-pending",
    "status": "draft",
    "created_at": "DEV ONLY — chưa phải đơn thật"
  },
  "set_members": [
    {
      "id": "set-member-1-placeholder",
      "set_id": "family-set-draft-placeholder",
      "member_label": "Người 1",
      "size_id": "size-m-placeholder",
      "size_label": "M"
    },
    {
      "id": "set-member-2-placeholder",
      "set_id": "family-set-draft-placeholder",
      "member_label": "Người 2",
      "size_id": "size-6-8y-placeholder",
      "size_label": "6-8Y"
    }
  ],
  "proof_record": {
    "id": "proof-placeholder",
    "customization_id": "customization-placeholder-pending",
    "print_params_snapshot": null,
    "proof_snapshot_hash": null,
    "confirmed_text": false,
    "confirmed_year": false,
    "is_valid": false,
    "proved_at": null
  },
  "print_params": {
    "blank_id": "blank-placeholder-v1-20261030",
    "colorway_id": "clone1-uuid-placeholder",
    "font_art_id": "font-art-placeholder-archivo-black",
    "background_hex": "#7A1E28",
    "text_hex": "#FFFFFF",
    "text_lines": [
      "COZY",
      "CHRISTMAS",
      "MORNING"
    ],
    "year": 2026,
    "display_lines": [
      "COZY",
      "CHRISTMAS",
      "MORNING",
      "2026"
    ],
    "alignment": "center",
    "print_area": {
      "x": 250,
      "y": 230,
      "width": 300,
      "height": 340,
      "unit": "px",
      "note": "PROPOSED, PENDING SUPPLIER TEMPLATE"
    },
    "preview_reference": {
      "text_font_size": 48,
      "year_font_size": 36,
      "unit": "SVG viewBox units",
      "note": "Cỡ preview tham chiếu M = 100%, chưa phải kích thước in theo từng size"
    },
    "font_size": "PLACEHOLDER — chờ Design chốt trên phôi thật",
    "position": "PLACEHOLDER — chờ Design chốt trên phôi thật"
  },
  "listing_template": {
    "name": "[Tên sản phẩm FM-06 — PLACEHOLDER]",
    "description": "Set gia đình buổi sáng Giáng sinh, cùng 1 text cho cả set, nhập 1 lần, proof step bắt buộc, preview là proof preview. Text ví dụ chỉ là ví dụ mặc định, không phải design cố định duy nhất.",
    "album_order": [
      "1. Cover — CHỜ ẢNH THẬT",
      "2. Mặt trước — live preview SVG",
      "3. Close-up — CHỜ ẢNH THẬT",
      "4. Người mặc — CHỜ ẢNH THẬT",
      "5. Set qua các size — CHỜ ẢNH THẬT"
    ],
    "price": "TRỐNG / PLACEHOLDER",
    "production_time": "TRỐNG / PLACEHOLDER",
    "shipping_time": "TRỐNG / PLACEHOLDER",
    "discount": "KHÔNG GHI",
    "free_shipping": "KHÔNG GHI",
    "christmas_delivery": "KHÔNG GHI",
    "size_chart": "SIZE CHART PLACEHOLDER — CHỜ SIZE CHART THẬT",
    "status": "dev_draft"
  },
  "placeholders": {
    "price": "PLACEHOLDER",
    "size_chart": "PLACEHOLDER",
    "supplier": "PLACEHOLDER — chưa chốt nhà cung cấp",
    "print_file": "PLACEHOLDER — chưa phải file in cuối",
    "brand": "PLACEHOLDER"
  },
  "status": "DEV_PREVIEW_ONLY_NOT_AN_ORDER",
  "validation_errors": []
}

Size chart — PLACEHOLDER (US-A9, AC-A11)

SIZE CHART PLACEHOLDER — CHỜ SIZE CHART THẬT TỪ NHÀ CUNG CẤP, CHƯA DÙNG ĐỂ CHỌN SIZE THẬT

SizeNgựcDài thânTay
Người lớn S / M / L / XL / 2XLCHƯA CÓ SỐ THẬT — chờ size chart thật từ nhà cung cấp, không bịa số
Trẻ em 4–5Y / 6–8Y / 10–12YCHƯA CÓ SỐ THẬT — chờ size chart thật

Size chọn được ở giai đoạn A chỉ là size_id trong danh sách placeholder, phục vụ test luồng set; chưa phải cam kết nhà cung cấp có size đó. Bảng tỉ lệ chữ theo size cũ (S ~95%, M 100%, L ~105%, XL ~110%, 2XL ~115%, trẻ em 70/80/90%) đã bị gỡ khỏi preview ở giai đoạn A-2 theo Lệch 1 của BA, không dùng làm số chốt, không dùng để tính preview. Kích thước in theo từng size chờ Design chốt ở giai đoạn B.

Listing template — album 5 ảnh theo thứ tự (US-A12, AC-A14)

Tên: [Tên sản phẩm FM-06 — PLACEHOLDER, chờ CEO chốt tên thương hiệu + tên listing]

Mô tả: set gia đình buổi sáng Giáng sinh, cùng 1 text cho cả set, nhập 1 lần, proof step bắt buộc, preview là proof preview. Text ví dụ trong demo: COZY CHRISTMAS MORNING + năm ví dụ — ghi rõ chỉ là ví dụ mặc định, không phải design cố định duy nhất, vì FM-06 mới là khách tự nhập text.

  1. Cover (cả set/cả nhà) — CHỜ ẢNH THẬT, không dùng ảnh AI rời rạc lấp chỗ
  2. Mặt trước (đọc rõ text + năm) — live preview SVG ở trên (proof preview, không phải ảnh sản phẩm thật)
  3. Close-up (chữ/vùng in) — CHỜ ẢNH THẬT
  4. Người mặc — CHỜ ẢNH THẬT
  5. Set qua các size — CHỜ ẢNH THẬT, chỉ là size đại diện

Giá, thời gian sản xuất/ship: TRỐNG / PLACEHOLDER. Giảm giá, miễn phí ship, giao trước Noel: KHÔNG GHI. Trạng thái: dev_draft — chưa live, chưa đăng thật.

Từ chối nội dung + cổng cuối nhà cung cấp (US-A10, AC-A12)

content_review_status: pending_review — hàng đợi review placeholder cho PM/CEO, chưa phải hệ thống duyệt tự động, chưa tự chuyển thành passed. Danh sách từ cấm xúc phạm/thù ghét: PLACEHOLDER ĐANG TRỐNG — chưa có văn bản chốt versioned từ CEO/PM, Dev không tự bịa danh sách. supplier_gate_status: not_submitted — chưa phải tích hợp thật, không tự chuyển thành approved.

Giai đoạn A, Dev triển khai cơ chế, không tự quyết danh sách cấm: validation ký tự/giới hạn chạy trước; trường content_review_status với các giá trị pending_review | passed | refused_offensive_hate | supplier_refused; hàng đợi review placeholder cho PM/CEO (chưa phải hệ thống duyệt tự động). Danh sách từ/cụm bị từ chối (nếu có) phải do CEO/PM cung cấp bằng văn bản và versioned; Dev không tự hard-code blocklist rộng, không tự chặn các chủ đề khác (bản quyền, thương hiệu, người nổi tiếng…) trong FM-06 — vì FM-06 chỉ giữ tầng từ chối ngôn từ xúc phạm/thù ghét. Nội dung bị từ chối: dừng ở bước review, báo cho PM/CEO theo luồng, không tự sửa nội dung khách, không tự chuyển nhà cung cấp để lách. Trách nhiệm nội dung khách custom trong FM-06 thuộc về nhà đầu tư theo quyết định đã ghi. Cổng cuối nhà cung cấp ở giai đoạn A là trường supplier_gate_status + bước dừng trong luồng, chưa phải tích hợp thật: mặc định not_submitted, không tự chuyển thành approved; nhà cung cấp từ chối thì đơn dừng, báo CEO ngay qua PM, không lách, không tự sửa nội dung khách.