ochintin-daicho (empty) → 0.1.0.0
raw patch · 7 files changed
+570/−0 lines, 7 filesdep +Globdep +basedep +bookkeepingsetup-changed
Dependencies added: Glob, base, bookkeeping, doctest, ochintin-daicho, text
Files
- LICENSE +21/−0
- README.md +17/−0
- Setup.hs +2/−0
- ochintin-daicho.cabal +51/−0
- src/Business/OchintinDaicho.hs +458/−0
- test/Doctest.hs +19/−0
- test/Spec.hs +2/−0
+ LICENSE view
@@ -0,0 +1,21 @@+MIT License++Copyright (c) 2017 Kadzuya OKAMOTO, http://www.arow.info++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.
+ README.md view
@@ -0,0 +1,17 @@+[](https://travis-ci.org/arowM/haskell-ochinchin-daicho)+[](https://hackage.haskell.org/package/ochinchin-daicho)+[](http://stackage.org/lts/package/ochinchin-daicho)+[](http://stackage.org/nightly/package/ochinchin-daicho)++# Haskell-ochinchin-daicho++A module to manage payroll books for Japanese companies.++おちんぎん台帳をHaskellで記述して管理できるモジュール。+源泉徴収簿や仕訳帳として出力できて Single source of truth な感じ。++## Build++```bash+$ stack build+```
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ ochintin-daicho.cabal view
@@ -0,0 +1,51 @@+name: ochintin-daicho+version: 0.1.0.0+synopsis: A module to manage payroll books for Japanese companies.+description:+ A module to manage payroll books for Japanese companies. This enable to export data to tax withholding book, etc...+homepage: https://github.com/arowM/haskell-ochintin-daicho#readme+license: MIT+license-file: LICENSE+author: Kadzuya Okamoto+maintainer: arow.okamoto+github@gmail.com+copyright: 2017 Kadzuya Okamoto+category: Business+build-type: Simple+extra-source-files: README.md+cabal-version: >=1.10++library+ hs-source-dirs: src+ exposed-modules: Business.OchintinDaicho+ build-depends: base >= 4.9 && < 5+ , bookkeeping >= 0.2.1.4+ , text >= 1.2.2.1+ default-language: Haskell2010+ ghc-options: -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates+ default-extensions: OverloadedStrings+ , RecordWildCards+ other-extensions: GeneralizedNewtypeDeriving++test-suite ochintin-daicho-test+ type: exitcode-stdio-1.0+ hs-source-dirs: test+ main-is: Spec.hs+ build-depends: base+ , ochintin-daicho+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ default-language: Haskell2010++test-suite doctest+ type: exitcode-stdio-1.0+ hs-source-dirs: test+ main-is: Doctest.hs+ build-depends: base+ , Glob+ , doctest >= 0.10+ , ochintin-daicho+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ default-language: Haskell2010++source-repository head+ type: git+ location: https://github.com/arowM/haskell-ochintin-daicho
+ src/Business/OchintinDaicho.hs view
@@ -0,0 +1,458 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE Strict #-}+{-# LANGUAGE StrictData #-}++{- |+Module : Business.OchintinDaicho++Copyright : Kadzuya Okamoto 2017+License : MIT++Stability : experimental+Portability : unknown++This module exports core functions and types for payroll books.+-}+module Business.OchintinDaicho+ (+ -- * Usage examples+ -- $setup++ -- * Types+ Person(..)+ , Payment(..)+ , Payments+ , Hours++ -- * Pretty printers+ , ppr++ -- * Converters+ , toBookkeeping++ -- * Convenient functions for 年末調整+ , _年度内課税支給金額+ , _年度内社会保険控除額+ , _年度内所得税控除額+ ) where++import Business.Bookkeeping+ (Amount(..), Category(..), CategoryType(..), CreditCategory(..), Date(..),+ DateTransactions, DebitCategory(..), Month(..), Transaction,+ Transactions, Year(..), activity, dateTrans, month, runTransactions, tAmount,+ year)+import Control.Monad (forM_)+import Data.Monoid ((<>))+import Data.Text (Text)+import qualified Data.Text as T+import qualified Data.Text.IO as T+import Data.String (IsString(..))+++{- $setup+>>> import Business.Bookkeeping hiding (ppr)+>>> :{+let+ taroYamada :: Person+ taroYamada = Person+ { name = "山田 太郎"+ , sex = "男"+ , payments = \y -> case y of+ 2017 ->+ [ ( (1, 10)+ , Payment+ { _賃金計算期間 = (2016, 12)+ , _労働日数 = 13+ , _労働時間数 = 13 * 5+ , _休日労働時間数 = 0+ , _早出残業時間数 = 0+ , _深夜労働時間数 = 0+ , _課税支給額 = 250000+ , _控除社会保険料 = \debit amount -> do+ dateTrans debit+ (CreditCategory $ Category "預り金" Liabilities)+ "健康保険料(社員負担分)"+ $ if (200000 < amount && amount < 300000)+ then 15000+ else error "undefined 健康保険料"+ dateTrans debit+ (CreditCategory $ Category "預り金" Liabilities)+ "厚生年金(社員負担分)"+ $ if (200000 < amount && amount < 300000)+ then 20000+ else error "undefined 厚生年金"+ dateTrans debit+ (CreditCategory $ Category "預り金" Liabilities)+ "雇用保険料(社員負担分)"+ $ if (200000 < amount && amount < 300000)+ then 1000+ else error "undefined 雇用保険料"+ , _所得税額 = \debit amount ->+ dateTrans debit+ (CreditCategory $ Category "預り金" Liabilities)+ "源泉所得税"+ $ if (200000 < amount && amount < 250000)+ then 5000+ else error $ "undefined 所得税額 for " <> show amount+ , _非課税支給額 = \credit -> do+ dateTrans+ (DebitCategory $ Category "旅費・交通費" Expenses)+ credit+ "立替交通費"+ 3000+ , _その他控除 = \debit ->+ dateTrans debit+ (CreditCategory $ Category "預り金" Liabilities)+ "親睦会費"+ 5000+ }+ )+ , ( (2, 10)+ , Payment+ { _賃金計算期間 = (2017, 1)+ , _労働日数 = 12+ , _労働時間数 = 12 * 5+ , _休日労働時間数 = 0+ , _早出残業時間数 = 0+ , _深夜労働時間数 = 0+ , _課税支給額 = 250000+ , _控除社会保険料 = \debit amount -> do+ dateTrans debit+ (CreditCategory $ Category "預り金" Liabilities)+ "健康保険料(社員負担分)"+ $ if (200000 < amount && amount < 300000)+ then 15000+ else error "undefined 健康保険料"+ dateTrans debit+ (CreditCategory $ Category "預り金" Liabilities)+ "厚生年金(社員負担分)"+ $ if (200000 < amount && amount < 300000)+ then 20000+ else error "undefined 厚生年金"+ dateTrans debit+ (CreditCategory $ Category "預り金" Liabilities)+ "雇用保険料(社員負担分)"+ $ if (200000 < amount && amount < 300000)+ then 1000+ else error "undefined 雇用保険料"+ , _所得税額 = \debit amount ->+ dateTrans debit+ (CreditCategory $ Category "預り金" Liabilities)+ "源泉所得税"+ $ if (200000 < amount && amount < 250000)+ then 5000+ else error $ "undefined 所得税額2 for " <> show amount+ , _非課税支給額 = \credit -> do+ dateTrans+ (DebitCategory $ Category "旅費・交通費" Expenses)+ credit+ "立替交通費"+ 4000+ , _その他控除 = \debit ->+ dateTrans debit+ (CreditCategory $ Category "預り金" Liabilities)+ "親睦会費"+ 5000+ }+ )+ ]+ _ ->+ []+ }+:}+-}++{-| 対象年度内の課税支給額総計++>>> _年度内課税支給金額 taroYamada 2017+Amount {unAmount = 500000}+-}+_年度内課税支給金額 :: Person -> Year -> Amount+_年度内課税支給金額 Person {..} =+ sum . map (_課税支給額 . snd) . payments++{-| 対象年度内の社会保険料等控除額総計++>>> _年度内社会保険控除額 taroYamada 2017+Amount {unAmount = 72000}+-}+_年度内社会保険控除額 :: Person -> Year -> Amount+_年度内社会保険控除額 Person {..} =+ sum . map (_算出保険料 . snd) . payments++{-| 対象年度内の所得税控除額総計++>>> _年度内所得税控除額 taroYamada 2017+Amount {unAmount = 10000}+-}+_年度内所得税控除額 :: Person -> Year -> Amount+_年度内所得税控除額 Person {..} =+ sum . map (_算出所得税 . snd) . payments++{-| A pretty printer for payroll books.++>>> ppr taroYamada 2017+氏名: 山田 太郎+性別: 男+<BLANKLINE>+== 2017年支給分 ==+<BLANKLINE>+支給日: 1月10日+賃金計算期間: 2016年12月+労働日数: 13日+労働時間数: 65時間+休日労働時間数: 0時間+早出残業時間数: 0時間+深夜労働時間数: 0時間+課税支給額: 250000円+控除社会保険料: 36000円+社会保険料等控除の金額: 214000円+所得税額: 5000円+非課税支給額: 3000円+その他控除: 5000円+--> 実支払額: 207000円+<BLANKLINE>+支給日: 2月10日+賃金計算期間: 2017年1月+労働日数: 12日+労働時間数: 60時間+休日労働時間数: 0時間+早出残業時間数: 0時間+深夜労働時間数: 0時間+課税支給額: 250000円+控除社会保険料: 36000円+社会保険料等控除の金額: 214000円+所得税額: 5000円+非課税支給額: 4000円+その他控除: 5000円+--> 実支払額: 208000円+<BLANKLINE>+-}+ppr :: Person -> Year -> IO ()+ppr Person {..} y = do+ T.putStrLn $ "氏名: " <> name+ T.putStrLn $ "性別: " <> sex+ T.putStrLn ""+ T.putStrLn . T.concat $+ [ "== "+ , tshow . unYear $ y+ , "年支給分 =="+ ]+ T.putStrLn ""+ forM_ (payments y) $ \((m, d), payment@(Payment {..})) -> do+ let+ (targetYear, targetMonth) = _賃金計算期間+ _算出保険料' = _算出保険料 payment+ _算出所得税' = _算出所得税 payment+ _非課税支給額総計' = _非課税支給額総計 payment+ _その他控除総計' = _その他控除総計 payment+ _実支払額' = _実支払額 payment+ T.putStrLn $ "支給日: " <> (tshow . unMonth) m <> "月" <> (tshow . unDate) d <> "日"+ T.putStrLn $ "賃金計算期間: " <> (tshow . unYear) targetYear <> "年" <> (tshow . unMonth) targetMonth <> "月"+ T.putStrLn $ "労働日数: " <> tshow _労働日数 <> "日"+ T.putStrLn $ "労働時間数: " <> (tshowIntegral) _労働時間数 <> "時間"+ T.putStrLn $ "休日労働時間数: " <> (tshowIntegral) _休日労働時間数 <> "時間"+ T.putStrLn $ "早出残業時間数: " <> (tshowIntegral) _早出残業時間数 <> "時間"+ T.putStrLn $ "深夜労働時間数: " <> (tshowIntegral) _深夜労働時間数 <> "時間"+ T.putStrLn $ "課税支給額: " <> (tshow . unAmount) _課税支給額 <> "円"+ T.putStrLn $ "控除社会保険料: " <> (tshow . unAmount) _算出保険料' <> "円"+ T.putStrLn $ "社会保険料等控除の金額: " <> (tshow . unAmount) (_課税支給額 - _算出保険料') <> "円"+ T.putStrLn $ "所得税額: " <> (tshow . unAmount) _算出所得税' <> "円"+ T.putStrLn $ "非課税支給額: " <> (tshow . unAmount) _非課税支給額総計' <> "円"+ T.putStrLn $ "その他控除: " <> (tshow . unAmount) _その他控除総計' <> "円"+ T.putStrLn $ "--> 実支払額: " <> (tshow . unAmount) _実支払額' <> "円"+ T.putStrLn ""++{-|++>>> :{+Business.Bookkeeping.ppr $ toBookkeeping taroYamada 2017+ (DebitCategory $ Category "給与手当" Expenses)+ (CreditCategory $ Category "普通預金" Liabilities)+:}+tDay: 2017-01-10+tDescription: 12月度+tSubDescription: 立替交通費+tDebit: 旅費・交通費 (Expenses)+tCredit: 普通預金 (Liabilities)+tAmount: 3000+<BLANKLINE>+tDay: 2017-01-10+tDescription: 12月度+tSubDescription: 健康保険料(社員負担分)+tDebit: 給与手当 (Expenses)+tCredit: 預り金 (Liabilities)+tAmount: 15000+<BLANKLINE>+tDay: 2017-01-10+tDescription: 12月度+tSubDescription: 厚生年金(社員負担分)+tDebit: 給与手当 (Expenses)+tCredit: 預り金 (Liabilities)+tAmount: 20000+<BLANKLINE>+tDay: 2017-01-10+tDescription: 12月度+tSubDescription: 雇用保険料(社員負担分)+tDebit: 給与手当 (Expenses)+tCredit: 預り金 (Liabilities)+tAmount: 1000+<BLANKLINE>+tDay: 2017-01-10+tDescription: 12月度+tSubDescription: 源泉所得税+tDebit: 給与手当 (Expenses)+tCredit: 預り金 (Liabilities)+tAmount: 5000+<BLANKLINE>+tDay: 2017-01-10+tDescription: 12月度+tSubDescription: 親睦会費+tDebit: 給与手当 (Expenses)+tCredit: 預り金 (Liabilities)+tAmount: 5000+<BLANKLINE>+tDay: 2017-01-10+tDescription: 12月度+tSubDescription: 給与支払い+tDebit: 給与手当 (Expenses)+tCredit: 普通預金 (Liabilities)+tAmount: 207000+<BLANKLINE>+tDay: 2017-02-10+tDescription: 1月度+tSubDescription: 立替交通費+tDebit: 旅費・交通費 (Expenses)+tCredit: 普通預金 (Liabilities)+tAmount: 4000+<BLANKLINE>+tDay: 2017-02-10+tDescription: 1月度+tSubDescription: 健康保険料(社員負担分)+tDebit: 給与手当 (Expenses)+tCredit: 預り金 (Liabilities)+tAmount: 15000+<BLANKLINE>+tDay: 2017-02-10+tDescription: 1月度+tSubDescription: 厚生年金(社員負担分)+tDebit: 給与手当 (Expenses)+tCredit: 預り金 (Liabilities)+tAmount: 20000+<BLANKLINE>+tDay: 2017-02-10+tDescription: 1月度+tSubDescription: 雇用保険料(社員負担分)+tDebit: 給与手当 (Expenses)+tCredit: 預り金 (Liabilities)+tAmount: 1000+<BLANKLINE>+tDay: 2017-02-10+tDescription: 1月度+tSubDescription: 源泉所得税+tDebit: 給与手当 (Expenses)+tCredit: 預り金 (Liabilities)+tAmount: 5000+<BLANKLINE>+tDay: 2017-02-10+tDescription: 1月度+tSubDescription: 親睦会費+tDebit: 給与手当 (Expenses)+tCredit: 預り金 (Liabilities)+tAmount: 5000+<BLANKLINE>+tDay: 2017-02-10+tDescription: 1月度+tSubDescription: 給与支払い+tDebit: 給与手当 (Expenses)+tCredit: 普通預金 (Liabilities)+tAmount: 208000+<BLANKLINE>++-}+toBookkeeping :: Person -> Year -> DebitCategory -> CreditCategory -> Transactions+toBookkeeping Person {..} y debit credit =+ year y $+ forM_ (payments y) $ \((m, d), payment@(Payment {..})) -> do+ let+ (_, targetMonth) = _賃金計算期間+ _算出保険料' = _算出保険料 payment+ _算出所得税' = _算出所得税 payment+ _非課税支給額総計' = _非課税支給額総計 payment+ _その他控除総計' = _その他控除総計 payment+ _実支払額' = _実支払額 payment+ month m $+ activity d (fromString $ (show . unMonth) targetMonth <> "月度") $ do+ _非課税支給額 credit+ _控除社会保険料 debit _課税支給額+ _所得税額 debit (_課税支給額 - _算出保険料')+ _その他控除 debit+ dateTrans debit credit "給与支払い" _実支払額'+++{- ==============+ - Types+ - ============== -}++{-| Main data type to represent payroll books for a person.+ -}+data Person = Person+ { name :: Text+ , sex :: Text+ , payments :: Year -> Payments+ }++{-| A type for handling `Payment` values.+ -}+type Payments = [((Month, Date), Payment)]++data Payment = Payment+ { _賃金計算期間 :: (Year, Month)+ , _労働日数 :: Int+ , _労働時間数 :: Hours+ , _休日労働時間数 :: Hours+ , _早出残業時間数 :: Hours+ , _深夜労働時間数 :: Hours+ , _課税支給額 :: Amount+ , _非課税支給額 :: CreditCategory -> DateTransactions+ , _控除社会保険料 :: DebitCategory -> Amount -> DateTransactions+ , _所得税額 :: DebitCategory -> Amount -> DateTransactions+ , _その他控除 :: DebitCategory -> DateTransactions+ }++newtype Hours = Hours { _unHours :: Int }+ deriving (Show, Read, Ord, Eq, Num, Enum, Integral, Real)+++-- Helper functions+tshow :: (Show a) => a -> T.Text+tshow = T.pack . show+++tshowIntegral :: (Integral a) => a -> T.Text+tshowIntegral a = T.pack . show $ (fromIntegral a :: Int)+++dummyDebit :: DebitCategory+dummyDebit = DebitCategory $ Category "DUMMY!" Expenses++dummyCredit :: CreditCategory+dummyCredit = CreditCategory $ Category "DUMMY!" Liabilities++_算出保険料 :: Payment -> Amount+_算出保険料 Payment {..} = sum . map tAmount . runDummyActivity $ _控除社会保険料 dummyDebit _課税支給額++_算出所得税 :: Payment -> Amount+_算出所得税 payment@(Payment {..}) = sum . map tAmount . runDummyActivity $ _所得税額 dummyDebit (_課税支給額 - _算出保険料 payment)++_非課税支給額総計 :: Payment -> Amount+_非課税支給額総計 Payment {..} = sum . map tAmount . runDummyActivity $ _非課税支給額 dummyCredit++_その他控除総計 :: Payment -> Amount+_その他控除総計 Payment {..} = sum . map tAmount . runDummyActivity $ _その他控除 dummyDebit++_実支払額 :: Payment -> Amount+_実支払額 payment@(Payment {..}) = _課税支給額 - _算出保険料 payment - _算出所得税 payment - _その他控除総計 payment + _非課税支給額総計 payment++runDummyActivity :: DateTransactions -> [Transaction]+runDummyActivity = runTransactions . year 1 . month 1 . activity 1 ""
+ test/Doctest.hs view
@@ -0,0 +1,19 @@+module Main where++import Data.Monoid ((<>))+import System.FilePath.Glob (glob)+import Test.DocTest (doctest)++main :: IO ()+main = glob "src/**/*.hs" >>= doDocTest++doDocTest :: [String] -> IO ()+doDocTest options = doctest $ options <> ghcExtensions++ghcExtensions :: [String]+ghcExtensions =+ [ "-XOverloadedStrings"+ , "-XRecordWildCards"+ , "-XStrict"+ , "-XStrictData"+ ]
+ test/Spec.hs view
@@ -0,0 +1,2 @@+main :: IO ()+main = putStrLn "Test suite not yet implemented"