顯示包含「Datatype」標籤的文章。顯示所有文章
顯示包含「Datatype」標籤的文章。顯示所有文章

2014年7月15日星期二

自製記帳軟件 - OACC_14.0.4 休假前檢討



大約在五月中旬,我終於鼓起勇氣去開發下一代的OACC。為什麼要鼓起勇氣呢?因為我知道這將會是一個浩大的工程,而且在其中也會有很多困難,不論是技術上及邏輯上的,要去克服。而最大的問題是,我有否這樣的一個決心呢?唔。。。

OACC的第一個版本是為我所工作的公司而編寫的,那次的開發很順利,速度也快。原因就在於我有很多數據在手,而且我也很熟悉自己公司的商業邏輯及需求。簡而言之,第一版的OACC是一個度身定造的軟件。

OACC第二版是在第一版的基礎上進行改良,加入很多泛用的功能,隱藏了第一版中為我司度身定造的特殊功能。其中,我花了很大氣力來實作Inventory的流程,FIFO,倉庫間的運轉與存量,引入Quotation,Purchase Order及Payment Terms。另方面亦加入了Aging Report及Bank Reconciliation等功能。

但是,這兩個版本的OACC都有一個先天性的問題,而這個問題糾結在我心中一直發酵,日夜在折磨著我。這個問題就是OACC並不是一個獨立的程式。這兩個版本的OACC都是使用Microsoft Access來開發User Interface,並使用Oracle MySQL作為後端Database。

當然,很多系統背後都是使用MySQL,SQL Server,Oracle SQL或MariaDB等,但是我的User Interface並不能在第一次使用時自動建立ODBC連線,使用者必須自己手動建立,雖然過程並不複雜,但是感覺就是不完美.可是,不完美在這裡卻代表了高靈活度.在設計OACC的EER時, 我自覺地只使用了INT,DECIMAL,DATE及VARCHAR等數種最基本的SQL Database資料形態.雖然只使用數種形態會浪費了Server上的儲存位元,但是可以大幅地提高OACC在不同品牌SQL Server之間的可移植性.

而使用Microsoft Access來開發User Interface使我糾結的原因在於:第一,前景不明;雖然在可見的將來Microsoft都不會放棄Access這成功的產品,但是要是有一天真的發生呢?那OACC將不可避免地被牽連.第二,單一平台;Microsoft Access發展了這麼長時間,Microsoft 從未如Excel或Word在其他平台上發布,在現在連Android都有了Microsoft Office Mobile的時候,Access依然缺席在其他平台之上.所以我決定使用另一種Program Language來開發下一代OACC, 雖然暫時心目中所想的是C#,但是這次休假我會好好去研究應該採用那一種Program Language.

除了這些問題外,最重要是我想做得更好,使OACC可應用的範圍更廣.這就帶出了另一個更重要更嚴肅的問題:到底OACC要走多遠.

Double Entry,Multi-Currency,Inventory,Aging,Bank Reconciliation,Cash Flow,Balance Sheet,Income Statement,Departmental Accounting,Financial Analysis及Investment Portfolio等等都已經在之前的兩個版本及另一個Database中實現了出來.那未來要走到那裡呢?Payroll,Human Resource, Group Companies Consolidation Statements,Customer Managing 如何實作這些都已經在心中成形,但是我還有一個更具野心卻未成形的想法,就是將Audit Procedure自動化.

將Audit Procedure自動化的困難有兩點:第一,Normalization; 第二,Flexibility.而這兩點是互相矛盾的.

關於Normalization的問題應該不難解決,只是我暫時未找到一個好的切入點.但是Flexibility則複雜得多.如果你也是從事會計行業的,就應該知道Accounting Standard的變化有多頻密,一年一小變,三年一大變.對Bookkeeping來說,很多這些的變化是可以置之不理,但是對Auditing來說,這些Standard就是生命的一部份.可對於一個Database來說,這些頻密的變化卻是非常要命的,因為經常地更改底層架構是不可能也不實際的.於是我要想出一個方法去應對.

”入數即核數 ”是一個夢想,縱使知道整個System的複雜度會因此而大幅提高,但我還是覺得值得的.

2013年9月27日星期五

自製記帳軟件 - Voucher 實體到虛疑


說了Schema, 說了Datatype, 是應該開始便用 MySQL Workbench 來實作的了. 但在這之前, 還是讓我說說一些邏輯上的東西吧. 為什麼還要說個不停? 因為這是關係到 Database Normalization 啊, 說的是系統的成與敗啊, 所以還是讓我說吧.


資訊
上圖是一張很平凡的 Payment Voucher (這個字太多不同的中文譯名, 所以我乾脆用回英文算了), 其中包含了很多資訊, 每一項資訊都有特定的功能, 有些是可以再用的, 有些則否. 在設計 Schema 時, 我們必須想清楚什麼是最核心的最不可或缺的資訊. 而在複式簿記 (Double Entry Bookkeeping) 之中, "日期 (Date)", "詳細 (Description)", "賬目 (Account)", "借方金額 (Debit Amount)" 及 "貸方金額 (Credit Amount)" 就是最不可或缺的五項資訊. 只要有了這五項資訊, 就是用 Microsoft Excel 來作記錄, 再加上善用 Sort 及 Filter 功能, 大家都可以輕鬆完成一盤會計賬目. 當然用 Microsoft Excel 來造賬, 出現錯誤的機會是很高的. 這並不是因為它本身有什麼程式缺憾, 而是因為人手參與的頻率與程度太高. 而記帳軟件其中的一個面向就是要盡量減少人手參與, 這是在設計 Schema 及 User Interface 時要多加留心的.

複式簿記流程
在繼續之前, 還是要略略說說複式簿記的流程. 首先會計人員在取得原始憑據後或某些特定事件發生或達到某個日期後, 會根據不同性質而開立不同的傳票, 並在傳票上列明事項日期, 詳細, 借方及(或)貸方賬目與金額, 涉事人員或公司. 在一天結束後將該所有當天的傳票, 匯整成日誌並結算借貸雙方的金額. 日誌上的借貸雙方的金額必須相等方何再轉錄到分賬內.

手民之誤
或許你會說所有資料不都是人手輸入的, 所以免除手民之誤是個不可能的任務. 可我們不是要免除, 而是要減少, 而且是盡量減少! 那如何作才可以減少 Human Error 呢? 答案就是限制同樣的資料以人手輸入的次數. 換句話說, 就是有效地善用已經輸入的資料. 在複式簿記的實作中, 有很多的資料都是重複, 像是"傳票類型", "賬目", "客戶", "供應商", "員工", "產品", "物品"等的名稱與編號. 這些重複性的資訊, 我們應該獨立建造屬於它們的資料表 (Table), 以待日後可以容易選取使用及設計查詢 (Query). 這部份我們日後會慢慢的涉獵到, 現在先按下不表.

資料類型
之前說過的五項主要資料是 "日期", "詳細", "賬目", "借方金額" 及 "貸方金額", 但是為了有效地解讀賬冊, 光有他們是不夠的. 於是我們還要加上如上一段所列的資訊. 資訊有了一大堆, 但是我們還要把它們分類. 基本我們可以把它們分成三類:

Basic Data (基本資料類型): 包括 "日期", "詳細", "傳票類型", "客戶/供應商" 及 "員工"

Transaction Data (交易資料類型): 包括 "賬目", "借方金額" 及 "貸方金額"

Additional Transaction Data (輔助交易資料類型): 包括 "產品" 或 "物品", 及其單價和數量

上述三類資料類型, 即代表著三個獨立的資料表. 下圖顯示了這三種類型在 OrangeAcc 中的傳單介面中的分佈.


很累, 下回繼續...





2013年9月23日星期一

自製記帳軟件 - DataType


我很佩服那些操作手冊的作者, 可以那麼條理分明的寫出每一個步驟, 每一個動作; 而我每次寫到實作層面的時候總是會退縮不前, 要處理要表達的資訊實在是太多, 而每一項資訊本身就已經充滿了不同的意函, 如果要充分去說明其中的道理和原委, 可能到我力歇那一天都未完成. 傳聞那些操作手冊的作者的稿費相當之高, 能人所不能之價也.

這一篇文章的用意是使大家在繼續我的唐吉訶德之路前, 先對手上的長矛- MySQL - 有一個初步認識. 否則大家只會像是瞎子摸象. MySQL 是一個 Database Management System (DBMS) 軟件, 顧名思義, 她的作用是管理不同的資料庫, 包括保全, 備份及輸入輸出都是她的職責. 而資料的儲存則是 Storage Engine 所負責.  在 MySQL 5.5之前, 預設的 Storage Engine 是 MyISAM, 而在5.5版或之後則是 InnoDB. InnoDB 取代 MyISAM 的原因最主要是穩定與效率. 雖然 InnoDB 會比MyISAM 佔據更多的儲存空間, 但在今天每MB的硬體成本只是港幣十分之一仙, 這個缺點已經變得無足輕重了.


上圖是一位熱心網友所製作的 MySQL Datatype 表的截圖, 完整的表可以在 KIM BRIGGS WEBSITE 中觀看及下載. 你或許會發現這表是根據 MySQL 5.0 版本所製成, 但是到現在仍然是適用的, 畢竟如果把 Schema 看成是根據幾何學繪成的藍圖, 你就不能夠隨便改動其中點線面的定義. 

在我自製的記帳軟件的 Schema 之中, 在考慮了一般記帳的需要, Micosoft Access 的限制和開發難度後, 我只集中地使用了幾種 Datatype, 它們包括了: TINYINT, INT, DECIMAL, VARCHAR, DATE, 及 TIMESTAMP. 或許我應該承認懶惰也是一大因素, 可是為了完成這個唐吉訶德式的壯舉, 我是看書看 Blog 都看到眼睛壊了. 為了讓大家進一步理解 Datatype 的選擇與設計考量, 以下我將會逐一簡單的說明一下:

TINYINT ( 1 byte ) - UNSIGNED 數值範圍從 0 到 255
這個 TINYINT 主要是用來作為 "選項數值", 例如 YES/NO, 表單種類及公司類別等. 記著一點, 由於此 Datatype 的數值範圍很小, 所以只適用一些你可以控制而不會自然增長的地方.

INT ( 4 bytes ) - UNSIGNED 數值範圍從 0 到 4,294,967,295
這個 INT 主要是用來作為 "編號數值", 例如表單編號, 客戶編號及產品編號等. 由於此 Datatype 的數值範圍比較大, 所以適用於一些會自然增長但不需要小數位的地方.

DECIMAL ( M+2 ) - 十進位範圍: 點數位前0到64, 點數位後0到30
這個 DECIMAL 主要是用來作為 "絕對數值", 例如金額及數量等. 由於此 Datatype 的數值範圍很大, 在設置適當的前提下你不會遇到任何限制, 就算你的公司是香港中央結算有限公司都沒有問題 (理論上). 有另一個 Datatype 跟 DECIMAL 很相似的就是 DOUBLE, 兩者的數值範圍都是一樣, 但是 DECIMAL 是一個固定數值 (Fixed), 而 DOUBLE 卻是一個浮點數值 (Float). 在記帳中少不免總會有加減乘除的動作, 而在追求精準平衡的時候, 你可不會想在報表中出現一些微少的差異, 重複當年 Microsoft Excel 2007 的 Bug 吧. 為了準確性, DECIMAL 基本是你唯一的選擇.

VARCHAR ( M char's ) - 字數限制從 0 到 65,535 個單位元字母或符號 (中文字是雙位元)
這個 VARCHAR 主要是用來作為 "文字欄", 例如表單明細, 名稱及其他混合資料等.

DATE ( 3 bytes ) - 日期範圍從 "1000-01-01" 到 "9999-12-31"
這個 DATE 主要是用來作為 "日期欄", 例如表單日期及結算日期等.

TIMESTAMP ( 4 bytes ) - 範圍從 '1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07' UTC
這個 TIMESTAMP 是一個系統自動生成的時間戳, 其一可以用來作為修復數據錯誤的依據, 另外還可以用作追蹤員工工作進度之用. (我是魔鬼...哈哈哈!)

以上六種 Datatype 基本上就是我那個自製記帳軟件的 Schema 的所用到的點線面定義, 如何組合它們就留待下一篇再說了.

PS. 寫這篇文章比寫書摘要累十倍也不止!