跳轉到

程式資訊

  • 程式 IDTICKS_E
  • 所屬子系統:P.發票管理
  • 狀態:stable

新增銷項發票

功能簡介

「新增銷項發票」是一個小型的新增對話視窗(程式代碼 TICKS_E,視窗標題「銷項發票新增」)。它不是獨立的選單功能,而是在銷項發票主檔(TICKS)按下工具列 新增 時自動彈出的子視窗。

它的唯一任務是讓使用者先決定一張新發票的三個身分欄位——發票年度(所屬年月)憑證類別發票號碼——這三欄合起來組成發票的主鍵(發票鍵值)。按 儲存 後,主檔會接手:依憑證類別自動建立對應的明細列(序號),接著就回到銷項發票主畫面繼續填寫明細。

會用到它的人就是負責登打銷項發票(三聯式/二聯式/收銀機統一發票等)的會計或開單人員,位置在「開立/登打一張新發票」流程的最前一步。

為什麼新增要先跳一個小視窗?

銷項發票的明細列數量是固定配號的(一個發票字軌通常一次配 50 號)。系統必須先知道憑證類別發票號碼末兩碼,才能決定要預先鋪幾列、序號從幾號起跳。這個對話視窗就是用來收集這組「配號資訊」,所以放在主檔輸入之前。

前置需求

  • 權限:本視窗附屬於銷項發票TICKS),擁有 TICKS 的新增權限即可使用,不需另外開權限。
  • 基礎資料
資料 影響什麼
憑證類別代碼檔(C2142) 憑證類別下拉的可選值與右側說明文字;憑證類別也決定新增時要鋪幾列明細
系統日期 發票年度(所屬年月)的預設值(自動帶當下雙月申報期)

操作步驟

  1. 銷項發票主畫面按工具列的 新增,系統彈出「銷項發票新增」對話視窗。
  2. 確認或修改 發票年度(所屬年月):開窗時已自動帶入「目前申報期」(見欄位連動與附加功能),格式 yyyy-MM-dd(雙月期別,例如 2026-05-06)。
  3. 選擇 憑證類別:下拉清單來自代碼檔 C2142,預設帶 35。選定後右側唯讀文字框會顯示該類別的中文說明。
  4. 輸入 發票號碼(最多 10 碼)。
  5. 儲存:系統把三欄組成發票鍵值回傳給主檔,並自動鋪好明細列,視窗關閉、回到主畫面。
  6. 若不想新增,按 取消(或關閉視窗),不會建立任何資料。

新增銷項發票視窗

後續編輯都在主檔做

這個視窗只負責「決定發票身分+鋪明細列」。發票日期、客戶、品名、金額、稅額、課稅別等所有明細內容,都在回到銷項發票主畫面後才輸入;存檔、刪除、列印等動作也都在主檔操作。

欄位說明

欄位 必填 說明 / 格式 / 預設
發票年度(所屬年月) 申報期別,格式 yyyy-MM-ddMaskInfo="InvoiceYearMonth")。預設=目前申報期,由 DateTimeWrapper.GetInvoiceYearMonth() 算出
憑證類別 代碼下拉,來源代碼檔 C2142。預設 35。右側唯讀框顯示該類別說明(SelectedItem.Description
發票號碼 最多 10 碼字串,預設空白。與所屬年月、憑證類別合併成發票鍵值,並決定明細列序號起跳值

三欄合起來就是主鍵

儲存 時,系統用 發票鍵值 = 所屬年月 + 憑證類別 + 發票號碼 當主檔主鍵,並把公司代碼固定設為 1。因此同一年月+同一類別+同一發票號碼只能有一張,重複新增會在主檔存檔時被擋。

欄位連動與附加功能

這一節說明「輸入某欄位/按某按鈕後,系統實際會做什麼」,全部來自程式碼(Ticks_eViewModelTicksViewModel.VirtualAfterAddNew)與 VFP 原始的新增邏輯(ticks.scx 配號程序)。

開窗即帶預設值

當對話視窗建立時(Ticks_eViewModel 建構子),系統自動:

  • 憑證類別 設成 35(一般銷項三聯式統一發票的常用類別)。
  • 發票年度(所屬年月) 設成 DateTimeWrapper.GetInvoiceYearMonth() 算出的「目前申報期」。其推算規則為:

    1. 取今天的年、月。
    2. 若月份是偶數,往前退一個月變成單數月(例如 6 月 → 5 月)。
    3. 組成「年-單數起始月-下一個偶數結束月」,例如今天在 6 月時得到 2026-05-06

    也就是說新增時所屬年月會直接落在「當下所在的雙月申報期」,多數情況不必再手動改期別。

選憑證類別 → 右側自動顯示說明

當你在 憑證類別 下拉選定一個代碼,右側的唯讀文字框會即時顯示該代碼在 C2142 代碼檔的中文說明(透過 SelectedItem.Description 綁定),方便確認選到正確的憑證類別。

儲存 → 組發票鍵值並回傳主檔

儲存SaveCommand)時,系統把你輸入的三欄包成一個暫存主檔物件(MasterItem)並關閉視窗(DialogResult = true)。接著主檔(TicksViewModel.VirtualAfterAddNew)會做以下連鎖動作:

  1. 清空明細:先把明細區既有的列全部清掉。
  2. 寫入主檔身分:把 公司代碼 設為 1;把對話視窗回傳的 所屬年月/憑證類別/發票號碼 寫進主檔,並組出 發票鍵值=所屬年月+憑證類別+發票號碼
  3. 依憑證類別鋪明細列(這是新增最關鍵的自動行為):

    • 憑證類別 = 36(收銀機統一發票/彙總):只建立 1 列明細,序號 00
    • 其他憑證類別:一次鋪 50 列明細,序號連號。起跳號由發票號碼末兩碼決定——
      • 發票號碼末兩碼是 00 → 序號 0049
      • 發票號碼末兩碼不是 00 → 序號 5099(程式內以 fix = 50 位移)。
    • 每一列都會預先帶好 所屬年月/憑證類別/發票號碼/發票鍵值,並以三碼字串設定排列順序

    為什麼是 50 列、又分 00 起跳或 50 起跳

    統一發票一本(一個字軌)通常含 50 個號碼。系統用末兩碼判斷你登打的是前半本(00–49)還是後半本(50–99),自動把對應半本的 50 列空白序號一次鋪好,你只要逐列填客戶與金額即可,不必一張一張手動新增明細。此規則與 VFP 舊版的配號程序完全一致。

  4. 鋪完明細後回到主畫面,焦點落在明細區,即可開始輸入第一列發票內容。

末兩碼判斷只看你打的發票號碼

系統是直接拿你在本視窗輸入的發票號碼末兩碼來決定序號起跳,不會自動去資料庫找下一個可用號。若你打錯號碼末碼(例如該打前半本卻打成非 00 結尾),鋪出來的序號半本就會不對,請在這一步就確認發票號碼正確。

取消 / 關閉視窗

取消ExitButton_Click)或直接關閉視窗會把 DialogResult 設為 false,主檔的新增流程隨即中止,不會建立主檔也不會鋪任何明細。

常見問題

為什麼新增發票要先跳一個小視窗,不能直接在主畫面打?

因為銷項發票的明細列是「整本配號」一次鋪好的,系統必須先知道憑證類別(決定鋪 1 列還是 50 列)和發票號碼末兩碼(決定序號從 00 還是 50 起跳),才能正確產生明細。這個視窗就是用來先收集這組資訊;填完按 儲存 後,剩下的內容都回到銷項發票主畫面輸入。

按儲存後明細區出現一大排空白列(00~49 或 50~99),是正常的嗎?

正常。除了憑證類別 36 只給 1 列外,其餘類別會自動鋪 50 列空白序號,對應統一發票一本(半本)的號碼。你只要把實際開立的那幾列填上客戶與金額,沒用到的空白列在主檔存檔時會依規則處理,不必逐列刪除。

明細的序號從 50 開始而不是 00,是哪裡設定的?

是由你在本視窗輸入的發票號碼末兩碼決定的:末兩碼是 00 → 序號 0049;末兩碼不是 00 → 序號 5099。若起跳號不如預期,請回到本視窗確認發票號碼輸入正確(這個判斷不會自動抓資料庫的下一個號)。

發票年度(所屬年月)為什麼一開窗就帶了一個日期?我可以改嗎?

開窗時系統會自動帶「目前雙月申報期」(由系統日期換算,偶數月會退到前一個單數月起算)。可以直接覆寫成你要登打的申報期,格式為 yyyy-MM-dd 的雙月期別。詳細推算規則見開窗即帶預設值

三欄都填了,回到主檔卻存不進去、說重複?

主檔以 發票鍵值(所屬年月+憑證類別+發票號碼) 為唯一主鍵。若這組身分已經存在一張發票,主檔存檔時會擋下。請改用唯一的發票號碼,或回銷項發票用查詢方式找出既有那張來修改。

相關功能


需補截圖清單

以下截圖待功能 runtime 驗收後補拍(放 docs/P-Invoice/images/):

  1. ticks_e-step1.png — 「銷項發票新增」對話視窗全貌(含發票年度、憑證類別+右側說明、發票號碼三欄與儲存/取消按鈕)