Add unit tests for each report, rendering and parsing

This commit is contained in:
Ben Sturmfels 2024-02-23 19:11:41 +11:00
parent 6ac0a45273
commit 69f13c9a52
Signed by: bsturmfels
GPG key ID: 023C05E2C9C068F0
3 changed files with 359 additions and 21 deletions

View file

@ -121,11 +121,11 @@
(let [total-net-pay (->> records
(filter #(= (:type %) "Net Pay"))
(map :amount)
(apply +))
(reduce + 0M))
total-reimbursement (->> records
(filter #(= (:type %) "Reimbursement"))
(map :amount)
(apply +))
(reduce + 0M))
actual-total-net-pay (- total-net-pay total-reimbursement)]
[{:account "Expenses:Payroll:Salary"
:amount actual-total-net-pay
@ -164,7 +164,7 @@
(str/starts-with? (:category %) "NY Disability")) records)
total-retirement (->> retirement-lines
(map :amount)
(apply +))
(reduce + 0M))
retirement-postings (for [{:keys [category amount]} retirement-lines]
(if (= category "403b ER match")
{:account "Expenses:Payroll:Salary"
@ -187,7 +187,7 @@
:currency "USD"
:meta {:payroll-type (cat->payroll-type category)}})
withholding-asset-postings [{:account "Assets:FR:Check2721"
:amount (- (reduce + (map :amount witholding-lines)))
:amount (- (reduce + 0M (map :amount witholding-lines)))
:currency "USD"
:meta {:tax-implication "W2"}}]
insurance-postings (for [{:keys [category amount]} insurance-lines]
@ -196,7 +196,7 @@
:currency "USD"
:meta {:payroll-type (cat->payroll-type category)}})
insurance-asset-postings [{:account "Assets:FR:Check2721"
:amount (reduce + (map :amount insurance-lines))
:amount (reduce + 0M (map :amount insurance-lines))
:currency "USD"}]]
{:date date :desc (format "Monthly Payroll - %s - TAXES - %s" period name)
:meta (assoc-project name {:project "Conservancy"
@ -227,7 +227,7 @@
name
{:entity name
:payroll-type (str/replace (cat->payroll-type category) "Tax:" "")})})
total-liabilities (->> liability-postings (map :amount) (reduce +))
total-liabilities (->> liability-postings (map :amount) (reduce + 0M))
unemploy-lines (filter #(and (= (:type %) "Liability")
(str/includes? (:category %) "Unemploy")) data)
unemploy-postings (for [{:keys [amount name category]} unemploy-lines]
@ -239,7 +239,7 @@
{:entity (first (str/split category #" "))
:memo name ; distinguishes multiple employees in one state
:payroll-type (str "US:" (cat->payroll-type category))})})
total-unemploy (->> unemploy-postings (map :amount) (reduce +))
total-unemploy (->> unemploy-postings (map :amount) (reduce + 0M))
asset-postings [{:account "Assets:FR:Check2721"
:amount (- (+ total-liabilities total-unemploy))
:currency "USD"
@ -283,12 +283,12 @@
(let [total-retirement (->> records
(filter #(= (:type %) "Retirement"))
(map :amount)
(reduce +))]
(reduce + 0M))]
{:account "Liabilities:Payable:Accounts",
:amount total-retirement,
:currency "USD",
:meta {:entity name}}))
total-liabilities (->> liability-postings (map :amount) (reduce +))
total-liabilities (->> liability-postings (map :amount) (reduce + 0M))
asset-postings [{:account "Assets:FR:Check1345"
:amount (- total-liabilities)
:currency "USD"}]]

View file

@ -4,19 +4,315 @@
(ns import-test
(:require [import]
[clojure.java.io]
[clojure.test :as t]))
[clojure.string :as str]
[clojure.test :as t :refer [deftest is]]))
(t/deftest sample-import
(let [grouped-data (import/read-grouped-csv
(clojure.java.io/resource
"example-paychex-pay-item-details.csv"))
imported (concat (import/payroll "2023-12-29" "December 2023" "rt:19462/674660" grouped-data)
(import/individual-taxes "2023-12-29" "December 2023" "rt:19462/674660" "rt:19403/675431" grouped-data)
(import/employer-taxes "2023-12-29" "December 2023" "rt:19462/674660" grouped-data)
(import/payroll-fees "2023-12-29" "December 2023" "rt:19459/675387" "rt:19459/674887" 206.50M grouped-data)
(import/retirement "2024-01-02" "December 2023" "rt:19403/676724" "rt:19403/675431" grouped-data))]
(t/is (= (count imported) 6))))
(deftest payroll
(let [data (import/read-csv (clojure.java.io/resource "example-paychex-pay-item-details.csv"))
actual (import/payroll "DATE" "PERIOD" "TODO-PAY-RECEIPT" data)
expected '[{:date "DATE"
:desc "Monthly Payroll - PERIOD - Net Pay"
:meta
{:program "Conservancy:Payroll"
:project "Conservancy"
:receipt "TODO-PAY-RECEIPT"
:approval
"Financial/Employment-Records/memo-re-board-approval-of-payroll.txt"
:tax-implication "W2"
:payroll-type "US:General"}
:postings
({:account "Expenses:Payroll:Salary"
:amount 4134.49M
:currency "USD"
:meta {:entity "Citizen-Jack"}}
{:account "Assets:FR:Check2721"
:amount -4134.49M
:currency "USD"
:meta {:entity "Citizen-Jack"}}
{:account "Expenses:Hosting"
:amount 50M
:currency "USD"
:meta {:entity "Citizen-Jack" :payroll-type "US:Reimbursement"}}
{:account "Assets:FR:Check2721"
:amount -50M
:currency "USD"
:meta {:entity "Citizen-Jack" :tax-implication "Reimbursement"}}
{:account "Expenses:Payroll:Salary"
:amount 4347.39M
:currency "USD"
:meta {:entity "Citizen-Jill"}}
{:account "Assets:FR:Check2721"
:amount -4347.39M
:currency "USD"
:meta {:entity "Citizen-Jill"}}
{:account "Expenses:Hosting"
:amount 50M
:currency "USD"
:meta {:entity "Citizen-Jill" :payroll-type "US:Reimbursement"}}
{:account "Assets:FR:Check2721"
:amount -50M
:currency "USD"
:meta {:entity "Citizen-Jill" :tax-implication "Reimbursement"}})}]]
(is (= actual expected))))
(deftest individual-taxes
(let [data (import/read-csv (clojure.java.io/resource "example-paychex-pay-item-details.csv"))
actual (import/individual-taxes "DATE" "PERIOD" "TODO-PAY-RECEIPT" "TODO-RETIREMENT-INVOICE" data)
expected '({:date "DATE"
:desc "Monthly Payroll - PERIOD - TAXES - Citizen-Jack"
:meta
{:project "Conservancy"
:program "Conservancy:Payroll"
:entity "Citizen-Jack"
:receipt "TODO-PAY-RECEIPT"
:approval
"Financial/Employment-Records/memo-re-board-approval-of-payroll.txt"}
:postings
({:account "Expenses:Payroll:Salary"
:amount 1000M
:currency "USD"
:meta
{:payroll-type "US:403b:Employee"
:invoice "TODO-RETIREMENT-INVOICE"}}
{:account "Liabilities:Payable:Accounts"
:amount -1000M
:currency "USD"
:meta {:invoice "TODO-RETIREMENT-INVOICE"}}
{:account "Expenses:Payroll:Salary"
:amount 470.22M
:currency "USD"
:meta {:payroll-type "US:Tax:Income"}}
{:account "Expenses:Payroll:Salary"
:amount 88M
:currency "USD"
:meta {:payroll-type "US:Tax:Medicare"}}
{:account "Expenses:Payroll:Salary"
:amount 376.28M
:currency "USD"
:meta {:payroll-type "US:Tax:SocialSecurity"}}
{:account "Assets:FR:Check2721"
:amount -934.50M
:currency "USD"
:meta {:tax-implication "W2"}}
{:account "Assets:FR:Check2721" :amount 0M :currency "USD"})}
{:date "DATE"
:desc "Monthly Payroll - PERIOD - TAXES - Citizen-Jill"
:meta
{:project "Conservancy"
:program "Conservancy:Payroll"
:entity "Citizen-Jill"
:receipt "TODO-PAY-RECEIPT"
:approval
"Financial/Employment-Records/memo-re-board-approval-of-payroll.txt"}
:postings
({:account "Expenses:Payroll:Salary"
:amount 820M
:currency "USD"
:meta
{:payroll-type "US:403b:Employee"
:invoice "TODO-RETIREMENT-INVOICE"}}
{:account "Liabilities:Payable:Accounts"
:amount -820M
:currency "USD"
:meta {:invoice "TODO-RETIREMENT-INVOICE"}}
{:account "Expenses:Payroll:Salary"
:amount 681.01M
:currency "USD"
:meta {:payroll-type "US:Tax:Income"}}
{:account "Expenses:Payroll:Salary"
:amount 99.29M
:currency "USD"
:meta {:payroll-type "US:Tax:Medicare"}}
{:account "Expenses:Payroll:Salary"
:amount 41.08M
:currency "USD"
:meta {:payroll-type "US:OR:Disability:PFL"}}
{:account "Expenses:Payroll:Salary"
:amount 0M
:currency "USD"
:meta {:payroll-type "OR EE Work Bene"}}
{:account "Expenses:Payroll:Salary"
:amount 427.8M
:currency "USD"
:meta {:payroll-type "US:OR:Tax:Income"}}
{:account "Expenses:Payroll:Salary"
:amount 6.03M
:currency "USD"
:meta {:payroll-type "US:OR:Tax:STT"}}
{:account "Expenses:Payroll:Salary"
:amount 424.52M
:currency "USD"
:meta {:payroll-type "US:Tax:SocialSecurity"}}
{:account "Assets:FR:Check2721"
:amount -1679.73M
:currency "USD"
:meta {:tax-implication "W2"}}
{:account "Assets:FR:Check2721" :amount 0M :currency "USD"})})]
(is (= actual expected))))
(deftest employer-taxes
(let [data (import/read-csv (clojure.java.io/resource "example-paychex-pay-item-details.csv"))
actual (import/employer-taxes "DATE" "PERIOD" "TODO-PAY-RECEIPT" data)
expected '[{:date "DATE"
:desc "Monthly Payroll - PERIOD - TAXES - Employer"
:meta
{:program "Conservancy:Payroll"
:project "Conservancy"
:receipt "TODO-PAY-RECEIPT"
:approval
"Financial/Employment-Records/memo-re-board-approval-of-payroll.txt"}
:postings
({:account "Expenses:Payroll:Tax"
:amount 88M
:currency "USD"
:meta {:entity "Citizen-Jack" :payroll-type "US:Medicare"}}
{:account "Expenses:Payroll:Tax"
:amount 376.28M
:currency "USD"
:meta {:entity "Citizen-Jack" :payroll-type "US:SocialSecurity"}}
{:account "Expenses:Payroll:Tax"
:amount 99.28M
:currency "USD"
:meta {:entity "Citizen-Jill" :payroll-type "US:Medicare"}}
{:account "Expenses:Payroll:Tax"
:amount 0M
:currency "USD"
:meta
{:entity "Citizen-Jill" :payroll-type "US:OR:Disability:PFL"}}
{:account "Expenses:Payroll:Tax"
:amount 0M
:currency "USD"
:meta {:entity "Citizen-Jill" :payroll-type "OR ER Work Bene"}}
{:account "Expenses:Payroll:Tax"
:amount 424.52M
:currency "USD"
:meta {:entity "Citizen-Jill" :payroll-type "US:SocialSecurity"}}
{:account "Expenses:Payroll:Tax"
:amount 0M
:currency "USD"
:meta
{:entity "Fed"
:memo "Citizen-Jack"
:payroll-type "US:US:Unemployment"}}
{:account "Expenses:Payroll:Tax"
:amount 0M
:currency "USD"
:meta
{:entity "TN"
:memo "Citizen-Jack"
:payroll-type "US:TN Unemploy"}}
{:account "Expenses:Payroll:Tax"
:amount 0M
:currency "USD"
:meta
{:entity "Fed"
:memo "Citizen-Jill"
:payroll-type "US:US:Unemployment"}}
{:account "Expenses:Payroll:Tax"
:amount 0M
:currency "USD"
:meta
{:entity "OR"
:memo "Citizen-Jill"
:payroll-type "US:OR:Unemployment"}}
{:account "Assets:FR:Check2721"
:amount -988.08M
:currency "USD"
:meta {:entity "Paychex" :tax-implication "Tax-Payment"}})}]]
(is (= actual expected))))
(deftest payroll-fees
(let [data (import/read-csv (clojure.java.io/resource "example-paychex-pay-item-details.csv"))
actual (import/payroll-fees "DATE" "PERIOD" "TODO-FEES-RECEIPT" "TODO-FEES-INVOICE" 206.51 data)
expected '[{:date "DATE"
:payee "Paychex"
:desc "Monthly Payroll - PERIOD - Fee"
:meta
{:program "Conservancy:Payroll"
:project "Conservancy"
:receipt "TODO-FEES-RECEIPT"
:invoice "TODO-FEES-INVOICE"
:approval
"Financial/Employment-Records/memo-re-board-approval-of-payroll.txt"
:tax-implication "USA-Corporation"}
:postings
({:account "Expenses:Payroll:Fees"
:amount 103.26M
:currency "USD"
:meta {:entity "Citizen-Jack"}}
{:account "Expenses:Payroll:Fees"
:amount 103.25M
:currency "USD"
:meta {:entity "Citizen-Jill"}}
{:account "Assets:FR:Check2721" :amount -206.51 :currency "USD"})}]
]
(is (= actual expected))))
(deftest retirement
(let [data (import/read-csv (clojure.java.io/resource "example-paychex-pay-item-details.csv"))
actual (import/retirement "DATE" "PERIOD" "TODO-RETIREMENT-RECEIPT" "TODO-RETIREMENT-INVOICE" data)
expected '[{:date "DATE"
:desc
"ASCENSUS TRUST RET PLAN - ACH DEBIT - Vanguard 403(b) - PERIOD"
:meta
{:program "Conservancy:Payroll"
:project "Conservancy"
:receipt "TODO-RETIREMENT-RECEIPT"
:approval
"Financial/Employment-Records/memo-re-board-approval-of-payroll.txt"
:tax-implication "Retirement-Pretax"
:invoice "TODO-RETIREMENT-INVOICE"}
:postings
({:account "Liabilities:Payable:Accounts"
:amount 1000M
:currency "USD"
:meta {:entity "Citizen-Jack"}}
{:account "Liabilities:Payable:Accounts"
:amount 820M
:currency "USD"
:meta {:entity "Citizen-Jill"}}
{:account "Assets:FR:Check1345" :amount -1820M :currency "USD"})}]]
(is (= actual expected))))
(deftest render-transaction
(let [transaction '{:date "DATE"
:payee "Paychex"
:desc "Monthly Payroll - PERIOD - Fee"
:meta
{:program "Conservancy:Payroll"
:project "Conservancy"
:receipt "TODO-FEES-RECEIPT"
:invoice "TODO-FEES-INVOICE"
:approval
"Financial/Employment-Records/memo-re-board-approval-of-payroll.txt"
:tax-implication "USA-Corporation"}
:postings
({:account "Expenses:Payroll:Fees"
:amount 103.26M
:currency "USD"
:meta {:entity "Citizen-Jack"}}
{:account "Expenses:Payroll:Fees"
:amount 103.25M
:currency "USD"
:meta {:entity "Citizen-Jill"}}
{:account "Assets:FR:Check2721" :amount -206.51M :currency "USD"})}
actual (import/render-transaction transaction)
expected (str/triml "
DATE txn \"Paychex\" \"Monthly Payroll - PERIOD - Fee\"
program: \"Conservancy:Payroll\"
project: \"Conservancy\"
receipt: \"TODO-FEES-RECEIPT\"
invoice: \"TODO-FEES-INVOICE\"
approval: \"Financial/Employment-Records/memo-re-board-approval-of-payroll.txt\"
tax-implication: \"USA-Corporation\"
Expenses:Payroll:Fees 103.26 USD
entity: \"Citizen-Jack\"
Expenses:Payroll:Fees 103.25 USD
entity: \"Citizen-Jill\"
Assets:FR:Check2721 -206.51 USD
")]
(is (= actual expected))))
(comment
(t/run-all-tests)
)
)

42
test/parse_test.clj Normal file
View file

@ -0,0 +1,42 @@
(ns parse-test
(:require [parse]
[clojure.string :as str]
[clojure.test :refer [deftest is]]))
(deftest test-parse
(let [transaction (str/triml "
DATE txn \"Paychex\" \"Monthly Payroll - PERIOD - Fee\"
program: \"Conservancy:Payroll\"
project: \"Conservancy\"
receipt: \"TODO-FEES-RECEIPT\"
invoice: \"TODO-FEES-INVOICE\"
approval: \"Financial/Employment-Records/memo-re-board-approval-of-payroll.txt\"
tax-implication: \"USA-Corporation\"
Expenses:Payroll:Fees 103.26 USD
entity: \"Citizen-Jack\"
Expenses:Payroll:Fees 103.25 USD
entity: \"Citizen-Jill\"
Assets:FR:Check2721 -206.51 USD
")
expected '[{:date "DATE"
:payee "Paychex"
:desc "Monthly Payroll - PERIOD - Fee"
:meta
{:program "Conservancy:Payroll"
:project "Conservancy"
:receipt "TODO-FEES-RECEIPT"
:invoice "TODO-FEES-INVOICE"
:approval
"Financial/Employment-Records/memo-re-board-approval-of-payroll.txt"
:tax-implication "USA-Corporation"}
:postings
({:account "Expenses:Payroll:Fees"
:amount 103.26M
:currency "USD"
:meta {:entity "Citizen-Jack"}}
{:account "Expenses:Payroll:Fees"
:amount 103.25M
:currency "USD"
:meta {:entity "Citizen-Jill"}}
{:account "Assets:FR:Check2721" :amount -206.51M :currency "USD"})}]]
(is (= (parse/parse transaction) expected))))