跳轉到

程式資訊

  • 程式 IDPROGRAMCLASS
  • 所屬子系統:L.聯絡傳訊
  • 狀態:stable

程式類別代碼(ProgramClass)

本頁是開發者/系統參考,不是操作畫面

ProgramClass 是一份集中在程式碼裡的程式代碼清單Common/ProgramClass.cs),不是一支可以開啟、輸入資料的表單。系統並沒有提供「程式類別維護」的操作視窗——它沒有對應的 ViewModel、XAML 或 BLL。本頁說明這份清單的用途、它如何把一支功能跟「選單/權限/查詢 SP/超連結」串起來,以及維護人員新增功能時要怎麼登錄。一般終端使用者不會直接接觸到它。

功能簡介

ProgramClass(程式類別)是 TsERP 用來唯一識別每一支程式(表單/報表/工具)的字串代碼。系統內幾乎每一支可開啟的程式,都對應一個 ProgramClass(例如銷售訂單是 ORMAST、生產計劃查詢是 PRODUCTIONPLAN、公告通知是 COMMPR)。這個代碼本身只是一個名字,但它是許多子系統共用的「主鍵」:

  1. 選單:主選單上每個項目記的就是它的 ProgramClass,用來決定點下去要開哪支程式。
  2. 權限:使用者權限是按 ProgramClass.Name 一支一支授權(瀏覽/新增/修改/刪除/列印…)。
  3. 查詢 SP:查詢頁要呼叫哪一支 stored procedure,是用 ProgramClass.Nameproc_param 登錄表查出來的。
  4. 超連結:跨單據的點選跳轉(HyperLink)以 ProgramClass.Name 當目標程式識別。
  5. 其他:報表、行事曆事件類別、AutoPilot 排程任務等,也都用同一組代碼識別。

維護人員與開發者會用到這份清單;終端使用者只會間接受惠(點選單、被授權、按超連結時,背後都是這份代碼在運作)。

程式碼位置與結構

這份清單定義在 Common/ProgramClass.cs,是一個 C# 類別,內容是一長串靜態欄位宣告,每一行就是一個程式代碼:

public static ProgramClass ORMAST = new ProgramClass();   // 銷售訂單
public static ProgramClass COMMPR = new ProgramClass();   // 公告通知
public static ProgramClass PRODUCTIONPLAN = new ProgramClass();  // 生產計劃查詢

它的運作機制有三個重點:

  1. 代碼名稱=欄位名稱。建構子用 [CallerMemberName] 自動把欄位名(如 ORMAST)抓進 Name 屬性,所以 ProgramClass.ORMAST.Name 就是字串 "ORMAST",不需要另外手寫一次字串。
  2. 集中查找表。每個代碼在建構時會自己登記進一個內部字典 _lookup,提供 ProgramClass.TryParse("ORMAST", out var p) 由字串反查回物件——選單、超連結、導覽參數都靠它把資料庫裡存的字串還原成程式物件。
  3. 以群組分區。檔案用 #region(如 M.EISschedule)與註解把代碼分群,方便維護人員定位。少數代碼上方有 <summary> XML 註解補充用途(例如 INVENT1 註明「產品序號表(保固卡)」、EISDASH 註明「主管儀表板」)。

代碼名稱不可隨意更名或重排順序

代碼的 Name(=欄位名)會被寫進資料庫的選單、權限、proc_param、超連結紀錄等。一旦改名,舊資料就對不上、權限與查詢會失效。新增請往後加;既有代碼名稱請當成不可變更的契約。

一支程式如何「掛上」它的 ProgramClass

當開發者寫一支新表單的 ViewModel 時,會 override ProgramClass 屬性指向這份清單裡的代碼,例如:

public override ProgramClass ProgramClass => ProgramClass.WKPAPER;

之後框架就用這個屬性的 .Name(即 "WKPAPER")去做權限檢查、查詢 SP 解析、超連結比對等。換句話說:

  • 沒有在 Common/ProgramClass.cs 宣告代碼 → ViewModel 無法 override → 這支程式無法被選單、權限、查詢系統正確識別。
  • 宣告了代碼但沒有任何 ViewModel 使用它 → 這個代碼目前是「保留/未啟用」狀態(檔內有多筆標 //系統保留,例如 LoginMenuATTACHMENT 等基礎機制用代碼)。

維護步驟(新增一支程式時)

這是給開發/維護人員的流程,不是終端使用者操作

新增一支新功能、要讓它能進選單並被權限與查詢系統認得時,通常依序:

  1. Common/ProgramClass.cs 適當的 #region 區段內,往後新增一行靜態欄位宣告(命名用大寫英文代碼,與該功能既有 VFP/資料庫代碼一致):

    public static ProgramClass MYFORM = new ProgramClass();   // 我的新表單
    
  2. 在新表單的 ViewModel override ProgramClass 屬性指向它:

    public override ProgramClass ProgramClass => ProgramClass.MYFORM;
    
  3. 主選單/程式清單登錄這個代碼,使用者才看得到入口(這步在系統設定/資料庫端,不在本檔)。

  4. 權限設定對需要的角色開放此 ProgramClass(瀏覽/新增/修改/刪除/列印)。
  5. 若該程式有查詢頁,須在 proc_param 登錄表把 ProgramClass.Name 對應到要呼叫的查詢 SP,否則查詢會找不到 SP 而靜默回空。

代碼命名慣例

主檔/單據用主表英文名(ORMASTPURCH);列印頁在主代碼後加 PRINTPURCHPRINTSLIYPRINT);查詢報表常見 XXX_QRY1REC_QRY0 之類的編號;轉單/轉傳票工具常見「來源 TO 目的」型(ODTOSAPUTORAWKTOMP)。新增時請沿用同模組的既有風格。

欄位說明(清單項目的組成)

清單裡每一筆「項目」其實就是一個靜態欄位。一個 ProgramClass 物件對外只暴露一個屬性:

欄位 說明/格式/預設
Name 程式代碼字串,唯讀。自動等於欄位名稱(透過 [CallerMemberName]),不需手填。例:ProgramClass.COMMPR.Name"COMMPR"ToString() 也回傳此值。

延伸搭配(不是 ProgramClass 自己的欄位,而是其他資料表用 Name 去對應的內容):

對應資料 由哪裡提供 說明
選單/程式清單 NavigateProgramParameters.ProgramClass(字串) 選單項目存的就是代碼字串;ProgramClassEnum 屬性用 TryParse 把它還原成物件
權限 權限設定表,以 ProgramClass.Name 為主鍵 一支程式一筆權限,分瀏覽/新增/修改/刪除/列印等動作
查詢 SP proc_param 登錄表 SheetNoMethod.GetQueryProcedure(programClass) 以代碼查出要跑的查詢 SP
多語系翻譯 LanguageService.GetTranslateText(ProgramClass.Name, key) 以代碼為命名空間查欄位/訊息的中英對照

欄位連動與附加功能

這份清單沒有「輸入欄位後重算」之類的畫面互動(它不是表單)。但它在程式碼層面有幾個重要的連動行為,維護時務必了解:

  • 改了欄位名,等於改了整個系統的識別主鍵。代碼的 Name 會散落在資料庫的選單、權限、proc_param、超連結、行事曆事件等多張表。所以新增代碼用「往後加」,不要更名、不要刪除、不要調整既有順序語意——順序本身不影響功能(靠字典查找),但把既有代碼改名會讓舊資料對不上。

  • TryParse 反查決定字串能不能變回程式。當系統從資料庫讀到一個程式代碼字串(例如超連結要跳到 ORMAST),會呼叫 ProgramClass.TryParse("ORMAST", out var p)。若清單裡沒有這個代碼,反查失敗,超連結會回報「No valid program class found.」、導覽參數的 ProgramClassEnum 會是 null。所以資料庫裡用到的代碼,清單裡一定要有對應宣告。

  • 超連結跳轉以代碼為目標。跨單據點選跳轉(HyperLink)時,HyperLinkExecute(programClass, …)TryParse 驗證代碼存在(反查不到就回「No valid program class found.」),再用 CanHyperLink 檢查使用者對該代碼有沒有權限(沒權限即回「無權限執行此程式」並中止)。權限通過後若該代碼還沒在目前系統的程式清單中(CheckIsInSystem 為否),會先把它加進上方選單列(AddProgram)再切頁——也就是說,真正會擋住跳轉的是「代碼不存在」或「沒有權限」,而不是「沒掛在選單上」。

  • ViewModel override 決定權限與查詢套用到哪支。框架用 ViewModel 的 ProgramClass 屬性 .Name 去查權限、查查詢 SP、查翻譯。若兩支不同表單不小心 override 成同一個代碼,它們會共用同一筆權限與查詢設定(這通常是 bug,新增時要確認代碼唯一)。

  • 保留代碼(//系統保留)不要拿來當業務功能用。清單開頭有一批標註 //系統保留 的代碼(LoginMenuSettingTODOLISTLIBRARYATTACHMENTMESSAGETITLE 等),它們是登入、選單、待辦、附件等基礎機制在用的。新增業務功能請另起新代碼,不要重用這些。

  • <summary> 註解是給維護人員的線索。少數容易混淆的代碼有 XML 註解澄清用途,例如 CLAIM 註明「索賠單(保固卡索賠,與應收扣款 ARCLAIM 不同功能)」、CMPLAIN 註明「抱怨單」。維護時遇到名稱相近的代碼,先看註解再動手,避免掛錯。

常見問題

為什麼開不起「程式類別」這個功能?選單裡找不到?

因為它不是一支可開啟的表單,只是程式碼裡的代碼清單(Common/ProgramClass.cs)。系統沒有提供「程式類別維護」的操作畫面,自然不會出現在選單。要查或改代碼,請開發人員直接編輯這個 .cs 檔。

新增了一支表單,但超連結/導覽跳不過去,回報「No valid program class found.」?

代表那個程式代碼字串在 ProgramClass 清單裡反查不到。請確認已在 Common/ProgramClass.cs 宣告對應代碼,且字串拼寫(大小寫)與資料庫/選單裡登錄的完全一致。TryParse 是大小寫敏感的精確比對。

查詢頁按了「查詢」卻一直回空,沒有錯誤?

代碼有宣告、表單也開得起來,但查詢 SP 沒登錄。查詢頁是用 ProgramClass.Nameproc_param 找要跑的 SP;若沒登錄,系統查不到 SP 就會靜默回空。請補登 proc_param 對應(這是新增查詢功能的必要步驟,常被遺漏)。

可以把某個代碼改名/刪掉,讓清單乾淨一點嗎?

不建議。代碼的 Name 會寫進資料庫的選單、權限、proc_param、超連結等多張表。改名或刪除會讓舊資料對不上,造成權限失效、查詢找不到 SP、超連結斷掉。確定某代碼完全沒在用才考慮移除,且要連同資料庫端一起清。

兩支表單的權限好像綁在一起,改一個另一個也變?

很可能兩支 ViewModel override ProgramClass 指到了同一個代碼。因為權限與查詢都是以 ProgramClass.Name 為主鍵,共用代碼就會共用設定。請讓每支表單各自宣告並使用唯一的代碼。

相關功能


需補截圖清單

本頁為開發者/系統參考,描述的是程式碼清單而非操作畫面,原則上不需要操作截圖。若日後要補圖輔助說明,建議補:

  1. images/programclass-step1.pngCommon/ProgramClass.cs 程式碼節錄(展示靜態欄位宣告與 #region 分區)
  2. images/programclass-step2.png — ViewModel 中 override ProgramClass 的寫法範例