PCE TW GUI MODULE — 銷項 Phase 1 單元測試清單
對象:開發/測試/顧問
目的:彙整 Phase 1(開立、取號、發票本、折讓/作廢核心)本機 Node 單元測試範圍、執行方式與案例清單
相關:銷項藍圖 · 取號測試指南 · 取號業務規則
文件日期:2026-09-14
目的:彙整 Phase 1(開立、取號、發票本、折讓/作廢核心)本機 Node 單元測試範圍、執行方式與案例清單
相關:銷項藍圖 · 取號測試指南 · 取號業務規則
文件日期:2026-09-14
這些測試不連 NetSuite 帳號。test/helpers/amd-loader.js 在 Node 載入 SuiteScript define();各模組 harness mock N/record、N/search 等相依模組。
1. 怎麼跑
在專案根目錄:
# Phase 1 核心套件(195 案,2026-09-14) npm run test:ar-phase1 # 開立核心(單元 + issueFromSources E2E,49 案) npm run test:ar-issue npm run test:ar-issue-from-sources # 分模組 npm run test:ar-book-allocate # 取號/手填(86 案) npm run test:ar-validate # 銷項驗證(6 案) npm run test:ar-feature # 子公司 feature flag(6 案) npm run test:ar-issue-search # 開立 Saved Search(4 案) npm run test:ar-book-csv # 發票本 CSV(21 案) npm run test:ar-book-import # 發票本匯入(4 案) npm run test:ar-book-import-log # 匯入紀錄(7 案) npm run test:ar-book-search # 發票本查詢/配號(12 案) # Phase 1 延伸(未納入 test:ar-phase1,但屬同一交付範圍) npm run test:ar-allowance # 折讓取號/閘道/餘額(33 案) npm run test:ar-void # 作廢(15 案) npm run test:ar-custom-lines # 自訂商品明細 lib(31 案) # 共用 list 值解析(4 案,已納入 npm test) npm run test:list-value # 交易表身 UE(23 案) npm run test:ar-trans-ar-body-ue # 全專案(含 AP 與上述銷項,471 案) npm test
依名稱篩選(Node 20+):
node --test --test-name-pattern="淨額" test/ar-issue-from-sources.test.js
2. 覆蓋範圍總覽
2.1 npm run test:ar-phase1(274 案)
| 區塊 | 測試檔 | 案數 | 主要 library/模組 |
|---|---|---|---|
| 開立核心(單元) | test/ar-issue.test.js | 21 | PCE_LIB_AR_Issue.js 工具函式 |
| 開立 E2E | test/ar-issue-from-sources.test.js | 43 | issueFromSources 端到端 |
| Customer Deposit 反推 | test/ar-customer-deposit.test.js | 5 | PCE_LIB_AR_CustomerDeposit.js |
| 自訂明細 | test/ar-custom-lines.test.js | 39 | PCE_LIB_AR_CustomLines.js |
| 交易表身 UE | test/ar-trans-ar-body-ue.test.js | 23 | PCE_UE_Trans_AR_Body.js |
| 模組設定 | test/module-settings.test.js | 11 | PCE_LIB_ModuleSettings.js |
| 銷項驗證 | test/ar-validate.test.js | 6 | PCE_LIB_AR_Validate.js |
| Feature flag | test/ar-feature.test.js | 9 | PCE_LIB_AR_Feature.js |
| 開立 Search | test/ar-issue-search.test.js | 4 | PCE_LIB_AR_IssueSearch.js |
| 開立清單課稅別 | test/ar-issue-list-tax.test.js | 3 | 查詢結果應稅/免稅/零稅率/混合稅 |
| 取號(函式) | test/ar-book-allocate.test.js | 57 | PCE_LIB_AR_BookAllocate.js |
| 取號(情境) | test/ar-book-allocate-scenarios.test.js | 30 | 格式 31–36 路徑分流 |
| 發票本 CSV | test/ar-book-csv.test.js | 21 | PCE_LIB_AR_BookCsv.js |
| 發票本匯入 | test/ar-book-import.test.js | 4 | PCE_LIB_AR_BookImport.js |
| 匯入紀錄 | test/ar-book-import-log.test.js | 7 | PCE_LIB_AR_BookImportLog.js |
| 發票本查詢 | test/ar-book-search.test.js | 12 | PCE_LIB_AR_BookSearch.js |
2.2 Phase 1 延伸(48 案,建議 regression 一併跑)
| 區塊 | 測試檔 | 案數 | 說明 |
|---|---|---|---|
| 折讓 | test/ar-allowance.test.js | 33 | 格式 33/34、折讓閘道、可折餘額、表單解析 |
| 作廢 | test/ar-void.test.js | 15 | 作廢資格、executeVoid、失敗報告 |
Phase 1 單元測試合計(含延伸):274 + 48 = 322 案(2026-09-21)。
2.3 共用與表身 UE(27 案,npm test 已含 list-value)
| 區塊 | 測試檔 | 案數 | 主要 library/模組 |
|---|---|---|---|
| custom list 值 | test/list-value.test.js | 4 | common/PCE_LIB_ListValue.js |
| 交易表身 UE | test/ar-trans-ar-body-ue.test.js | 23 | PCE_UE_Trans_AR_Body.js(含 ISSUANCE_BODY_FIELDS.errorMsg 唯讀) |
2.3 尚未覆蓋(需帳上/手動)
| 項目 | 說明 |
|---|---|
| Suitelet UI 開立表單 | 按鈕、預覽 sublist、POST 參數組裝 |
| Map/Reduce 背景明細 | customscript_pce_mr_ar_issue_lines 帳上執行 |
| Script Deployment Audience | XML 部署後 UI 是否載入 CS/UE |
| 冒煙/Browser MCP | 實際 Invoice 頁開立一張發票 |
| Customer Deposit 轉開/含稅反推 | test/ar-customer-deposit.test.js、test/ar-issue-from-sources.test.js |
| 空白字軌/空白發票下載 | 營業稅申報進度,未建 |
| 每期申報對帳報表 | Phase 4,未建 |
| 憑證 PDF 下載(B2B/折讓/零稅率等) | Phase 5,未建 |
| 銷項 CSV/Write API | Phase 6(外部已開立寫入 NS),未建 |
| Saved Search 排程批次開立 | Phase 7 後續,未建 |
2.4 Phase 7 背景開立(本機,建議與銷項 regression 一併跑)
| 區塊 | 測試檔 | 案數 | 說明 |
|---|---|---|---|
| 背景開立 lib | test/ar-auto-issue.test.js | 見檔內 | PCE_LIB_AR_AutoIssue.js、佇列 enqueue、MR payload |
| 進度查詢 | test/ar-auto-issue-monitor.test.js | 3 | PCE_LIB_AR_AutoIssueQueueMonitor.js 批次摘要、發票日期 |
| UTC+8 曆日 | test/taiwan-date.test.js | 見檔內 | PCE_LIB_TaiwanDate.js(進度頁建立日) |
npm run test:ar-auto-issue npm run test:ar-auto-issue-monitor npm run test:taiwan-date
規格:背景自動開立
3. Harness 對照
| Harness | 路徑 | 用途 |
|---|---|---|
| amd-loader | test/helpers/amd-loader.js | Node 載入 SuiteScript AMD |
| 開立(單元) | test/helpers/ar-issue-harness.js → loadIssueLib() | 回寫、查主檔、鎖定等片段 |
| 開立(E2E) | 同上 → loadIssueLibForSources() | mock 來源交易、自訂明細、取號 |
| 取號 | test/helpers/ar-book-allocate-harness.js | 預設發票本 DEFAULT_BOOK |
| 作廢 | test/helpers/ar-void-harness.js | 作廢流程 mock |
E2E 常用 factory:
defaultSourceTransaction(txId, overrides)— Invoice mockdefaultAllowanceTransaction(txId, overrides)— Credit Memo mockcustomLinesByTxId—customrecord_pce_ar_custom_linesearch mock
4. 案例清單 — 開立(test:ar-issue)
4.1 ar-issue.test.js(21 案)
| # | 案例 | 驗證重點 |
|---|---|---|
| 1 | resolveMergeMode:空/單筆 → single | 合併模式判定 |
| 2 | resolveMergeMode:多 Invoice → merge | |
| 3 | resolveMergeMode:Invoice + CM → net | |
| 4 | resolveMergeMode:多 CM → merge | |
| 5 | parseSourceEntries:custpage_inv_ids | 表單來源解析 |
| 6 | parseSourceEntries:custpage_tx_id 預設 invoice | |
| 7 | parseSourceEntries:混用 inv + cm | |
| 8 | parseSourceEntries:無效 JSON → 拋錯 | |
| 9 | parseSourceEntries:無來源 → 空陣列 | |
| 10 | resolveIssueActionLabel:單張 | UI 文案 |
| 11 | resolveIssueActionLabel:合併 | |
| 12 | writeBackTransactionAfterIssue:Invoice 回寫 | invoice_no、解鎖、狀態 |
| 13 | findArInvoiceByInvoiceNo:大小寫正規化 | |
| 14 | findArInvoiceByInvoiceNo:空號碼 → null | |
| 15 | formatLineSeq 補零 | |
| 16 | resolveLineRecordName | |
| 17 | lockTransactionIssue/release | |
| 18 | shouldScheduleAsyncLineCreation:明細閾值 | MR 決策 |
| 19 | shouldScheduleAsyncLineCreation:合計閾值 | |
| 20 | formatSuiteScriptError:Error | |
| 21 | formatSuiteScriptError:空值 |
4.2 ar-issue-from-sources.test.js(43 案)
單張/合併/淨額
| # | 案例 | 驗證重點 |
|---|---|---|
| 1 | 單張 Invoice happy path | 主檔、明細、來源、回寫 |
| 2 | 兩筆 Invoice merge | 加總、雙來源、雙回寫 |
| 3 | Invoice + CM net | CM 扣減(840) |
| 4 | Invoice 自訂 + CM NS(net) | 正負兩列、doc_kind=發票 |
| 5 | 雙方皆自訂相同品項(net) | 不跨單合併、總計 0 |
| 6 | CM 全額抵扣 | 總計 0、allow_remain=0 |
| 7 | CM 超過 Invoice | 負總計 −1050 |
| 8 | Invoice 自訂表頭不符(net) | 失敗、不建主檔 |
| 9 | 僅 CM 自訂 + Invoice NS(net) | 1000 / −200 |
失敗情境
| # | 案例 | 驗證重點 |
|---|---|---|
| 10 | 空來源 | |
| 11 | 子公司不一致 | |
| 12 | 交易已鎖定 | |
| 13 | 已有發票號碼 | |
| 14 | 取號失敗 |
折讓開立(格式 33)
| # | 案例 | 驗證重點 |
|---|---|---|
| 15 | happy path | 回寫 CM、扣減原發票餘額 |
| 16 | 未填 origInvoiceNo | |
| 17 | 超過可折餘額 | |
| 18 | 合併兩筆 CM | merge、雙回寫、餘額 893 |
| 19 | 非當期無主檔 | warning、不扣餘額 |
自訂明細
| # | 案例 | 驗證重點 |
|---|---|---|
| 20 | happy path | customrecord 明細 |
| 21 | 表頭不符 | |
| 22 | 合併:相同品項單價 → 1 列 | qty=2 |
| 23 | 合併:不同單價 → 2 列 | |
| 24 | 合併:不同課稅別 → 2 列 | 表頭混合稅 |
| 25 | 混用自訂 + NS | 不跨單合併 |
| 26 | 同單多列相同 key | 單內合併 |
| 27 | 已勾選無有效列 |
背景明細
| # | 案例 | 驗證重點 |
|---|---|---|
| 28 | ≥ SYNC_LINE_THRESHOLD | asyncLines、提交 MR task |
合併/淨額總備註預填(loadTransactionsForIssueForm.remarks)
| # | 案例 | 驗證重點 |
|---|---|---|
| — | 合併兩張 INV | {tranid}: {備註} 換行串接 |
| — | 合併 INV(一筆空白) | 略過空總備註 |
| — | 淨額 INV + CM | 雙方總備註皆併入 |
| — | 合併後超長 | 整段截斷 200 字(MIG I26) |
(單張 INV/訂金總備註預填、訂金含稅反推等案例見同一檔 Customer Deposit 轉開 describe。)
5. 案例清單 — 驗證/Feature/Search
5.1 ar-validate.test.js(6 案)
- validateRecord 統編:合法、B2C 略過、買方錯、賣方錯
- applySalesAmountDefaultsToNsRecord:空值補 0
- formatErrorsAsText/Html
5.2 ar-feature.test.js(6 案)
- isArFeatureEnabledForSubsidiary:啟用/未啟用/空
- shouldIssueInvoiceForTransaction:有客戶且啟用、無客戶、applyIssueInvoiceFlag
5.3 ar-issue-search.test.js(4 案)
- Saved Search 開立資格(issue=T、未鎖、無號碼)
- buildListCriteriaFilters:有條件/空
- buildInternalIdFilter
6. 案例清單 — 發票本/取號
取號詳細案例與 mock 發票本欄位見 取號測試指南。
6.1 摘要
| 檔案 | 案數 | 主題 |
|---|---|---|
ar-book-allocate.test.js | 56 | 配號篩選、下一號、樂觀鎖、手填反查、衝突重試 |
ar-book-allocate-scenarios.test.js | 30 | 格式 31–36 路徑、手填/自動、錯誤碼 |
ar-book-csv.test.js | 21 | CSV 解析、字軌拆分、範本 |
ar-book-import.test.js | 4 | 列→job、validateOnly、MR 提交 |
ar-book-import-log.test.js | 7 | pending/completed/partial、UI snapshot |
ar-book-search.test.js | 12 | 查詢條件、配號欄位、bulk MR |
7. 案例清單 — Phase 1 延伸
7.1 ar-allowance.test.js(33 案)
| 群組 | 內容 |
|---|---|
| 格式判定 | 33/34 折讓、31/35/36 非折讓 |
| 取號 | 手填、16 碼、已使用、不走發票本 |
| 回寫 | CM allowance_no/orig_invoice_no;Invoice invoice_no |
| 表單 | 文案、cm_ids 解析、格式 36 稅率 |
| 可折餘額 | 足夠/超額/當期無主檔/非當期自管/lookupOrigInvoice |
7.2 ar-void.test.js(15 案)
| 群組 | 內容 |
|---|---|
| resolveVoidMigMsg | MIG 訊息對照 |
| 日期預設 | 台灣時區 |
| validateVoidEligibility | 資格、狀態、已作廢 |
| buildTxFailureReport | 失敗彙整 |
| executeVoid | 發票/折讓作廢、回沖 |
7.3 ar-custom-lines.test.js(31 案)
| 群組 | 內容 |
|---|---|
| mapRawLinesToIssueLines | 零元過濾、taxTypeId |
| resolveIssueLinesForSource | NS/自訂、空列拋錯 |
| validateCustomLineTotalsMatchHeader | 未稅/稅額、容差 0.02 |
| mergeIssueLinesByItemAndUnitPrice | 同品項+品名合併、不同品名/單價/課稅別 |
| fillMissingLineTaxAmounts | 補稅、對帳 |
8. 建議 regression 順序
npm run test:ar-phase1— 開立+取號+發票本核心(CI 必綠)npm run test:ar-allowance && npm run test:ar-void && npm run test:ar-custom-lines— 同交付範圍延伸- 部署後帳上:開立 Suitelet 單張/合併/淨額各一筆(手動 checklist)
9. 新增 E2E 案例指引
在 test/ar-issue-from-sources.test.js 新增案例時:
- 使用
loadIssueLibForSources(),每案獨立 mock,避免 state 汙染。 - 來源交易用
defaultSourceTransaction/defaultAllowanceTransaction。 - 自訂明細補
customLinesByTxId並將useCustomLines設為T。 - 折讓需
arInvoiceRows模擬原發票銷項主檔。 - 斷言優先查
issueState.createdRecords、issueState.submitFieldsCalls。
範本見 ar-issue-from-sources.test.js 第一個 happy path 案例。
10. 修訂紀錄
| 日期 | 說明 |
|---|---|
| 2026-09-14 | 初版:彙整 test:ar-phase1(195 案)與 issueFromSources E2E(28 案)清單 |