Add importer for employer taxes
This commit is contained in:
parent
76520640d1
commit
c57b842c49
3 changed files with 148 additions and 139 deletions
|
@ -19,7 +19,8 @@
|
|||
(def data (import/read-grouped-csv "/home/ben/Downloads/2023-12-27_Pay-Item-Details_2023-12-2.csv"))
|
||||
(def imported
|
||||
(concat [(import/import-monthly-payroll data)]
|
||||
(import/import-individual-taxes data)))
|
||||
(import/import-individual-taxes data)
|
||||
[(import/import-employer-taxes data)]))
|
||||
|
||||
(dd/pretty-print
|
||||
(dd/diff
|
||||
|
@ -29,4 +30,9 @@
|
|||
(doseq [i imported]
|
||||
(println (import/render-transaction i)))
|
||||
|
||||
(dd/pretty-print
|
||||
(dd/diff
|
||||
(sort-postings (parse examples/employer-taxes))
|
||||
(sort-postings [(import/import-employer-taxes data)])))
|
||||
|
||||
)
|
||||
|
|
271
src/import.clj
271
src/import.clj
|
@ -36,16 +36,6 @@
|
|||
bigdec-or-zero))))]
|
||||
cleaned-records))
|
||||
|
||||
(defn monthly-payroll-trans [date desc receipt postings]
|
||||
{:date date :desc desc
|
||||
:meta {:program "Conservancy:Payroll"
|
||||
:project "Conservancy"
|
||||
:receipt receipt
|
||||
:approval "Financial/Employment-Records/memo-re-board-approval-of-payroll.txt"
|
||||
:tax-implication "W2"
|
||||
:payroll-type "US:General"}
|
||||
:postings postings})
|
||||
|
||||
(defn format-name [name]
|
||||
(case name
|
||||
"Sharp, Sage A" "Sharp-Sage-A"
|
||||
|
@ -81,144 +71,155 @@
|
|||
"OR Disability PFL" "US:OR:Disability:PFL"
|
||||
"NY Disability PFL" "US:NY:Disability:PFL"
|
||||
"OR TRANS STT" "US:OR:Tax:STT"
|
||||
"Fed Unemploy" "US:Unemployment"
|
||||
"IL Unemploy" "IL:Unemployment"
|
||||
"NY Unemploy" "NY:Unemployment"
|
||||
"OR Unemploy" "OR:Unemployment"
|
||||
cat))
|
||||
|
||||
(defn indiv-payroll-trans [date desc name receipt postings]
|
||||
{:date date :desc (format desc (format-name name))
|
||||
:meta {:project (if (= (format-name name) "Sharp-Sage-A") "Outreachy" "Conservancy")
|
||||
:program "Conservancy:Payroll"
|
||||
:entity (format-name name)
|
||||
:receipt receipt
|
||||
:approval "Financial/Employment-Records/memo-re-board-approval-of-payroll.txt"}
|
||||
:postings postings})
|
||||
|
||||
;; TODO: How do we know we used all the relevant data from the report? Didn't
|
||||
;; miss anything?
|
||||
|
||||
;; TODO: Split out the match amount into a separate transaction entry?
|
||||
|
||||
(defn import-monthly-payroll [groups]
|
||||
(monthly-payroll-trans
|
||||
"2023-12-29"
|
||||
"Monthly Payroll - December 2023 - Net Pay"
|
||||
"rt:19462/674660"
|
||||
(apply concat (for [[name records] groups]
|
||||
(let [name (format-name name)
|
||||
total-net-pay (->> records
|
||||
(filter #(= (:type %) "Net Pay"))
|
||||
(map :t-net-pay)
|
||||
(apply +)
|
||||
bigdec)
|
||||
total-reimbursement (->> records
|
||||
(filter #(= (:type %) "Reimbursement"))
|
||||
(map :t-reimbursement)
|
||||
(apply +)
|
||||
bigdec)
|
||||
total-net-pay-less-reimb (- total-net-pay total-reimbursement)
|
||||
pay-exp-trans [{:account "Expenses:Payroll:Salary"
|
||||
:amount total-net-pay-less-reimb
|
||||
:currency "USD"
|
||||
:meta (if (= name "Sharp-Sage-A")
|
||||
{:entity name
|
||||
:project "Outreachy"}
|
||||
{:entity name})}
|
||||
{:account "Assets:FR:Check2721"
|
||||
:amount (- total-net-pay-less-reimb)
|
||||
:currency "USD"
|
||||
:meta {:entity name}}]
|
||||
reimbursement-exp-trans [{:account "Expenses:Hosting"
|
||||
:amount total-reimbursement
|
||||
:currency "USD"
|
||||
:meta (if (= name "Sharp-Sage-A")
|
||||
{:entity name
|
||||
:project "Outreachy"
|
||||
:payroll-type "US:Reimbursement"}
|
||||
{:entity name
|
||||
:payroll-type "US:Reimbursement"})}
|
||||
{:account "Assets:FR:Check2721"
|
||||
:amount (- total-reimbursement)
|
||||
:currency "USD"
|
||||
:meta (if (= name "Sharp-Sage-A")
|
||||
{:entity name
|
||||
:project "Outreachy"
|
||||
:tax-implication "Reimbursement"}
|
||||
{:entity name
|
||||
:tax-implication "Reimbursement"})}]]
|
||||
(concat pay-exp-trans reimbursement-exp-trans))))
|
||||
#_(apply concat (for [x data :when (or (and (= (:type x) "Net Pay") (> (:t-net-pay x) 0))
|
||||
(and (= (:type x) "Reimbursement") (> (:t-reimbursement x) 0)))]
|
||||
(let [name (format-name (:name x))]
|
||||
(case (:type x)
|
||||
"Net Pay"
|
||||
"Reimbursement"
|
||||
[{:account "Expenses:Hosting"
|
||||
:amount (:t-reimbursement x)
|
||||
:currency "USD"
|
||||
:meta {:entity name
|
||||
:payroll-type "US:Reimbursement"}}
|
||||
{:account "Assets:FR:Check2721"
|
||||
:amount (- (:t-reimbursement x))
|
||||
:currency "USD"
|
||||
:meta {:entity name
|
||||
:tax-implication "Reimbursement"}}]))))))
|
||||
{:date "2023-12-29" :desc "Monthly Payroll - December 2023 - Net Pay"
|
||||
:meta {:program "Conservancy:Payroll"
|
||||
:project "Conservancy"
|
||||
:receipt "rt:19462/674660"
|
||||
:approval "Financial/Employment-Records/memo-re-board-approval-of-payroll.txt"
|
||||
:tax-implication "W2"
|
||||
:payroll-type "US:General"}
|
||||
:postings
|
||||
(apply concat (for [[name records] groups]
|
||||
(let [name (format-name name)
|
||||
total-net-pay (->> records
|
||||
(filter #(= (:type %) "Net Pay"))
|
||||
(map :t-net-pay)
|
||||
(apply +)
|
||||
bigdec)
|
||||
total-reimbursement (->> records
|
||||
(filter #(= (:type %) "Reimbursement"))
|
||||
(map :t-reimbursement)
|
||||
(apply +)
|
||||
bigdec)
|
||||
total-net-pay-less-reimb (- total-net-pay total-reimbursement)
|
||||
pay-exp-trans [{:account "Expenses:Payroll:Salary"
|
||||
:amount total-net-pay-less-reimb
|
||||
:currency "USD"
|
||||
:meta (if (= name "Sharp-Sage-A")
|
||||
{:entity name
|
||||
:project "Outreachy"}
|
||||
{:entity name})}
|
||||
{:account "Assets:FR:Check2721"
|
||||
:amount (- total-net-pay-less-reimb)
|
||||
:currency "USD"
|
||||
:meta {:entity name}}]
|
||||
reimbursement-exp-trans [{:account "Expenses:Hosting"
|
||||
:amount total-reimbursement
|
||||
:currency "USD"
|
||||
:meta (if (= name "Sharp-Sage-A")
|
||||
{:entity name
|
||||
:project "Outreachy"
|
||||
:payroll-type "US:Reimbursement"}
|
||||
{:entity name
|
||||
:payroll-type "US:Reimbursement"})}
|
||||
{:account "Assets:FR:Check2721"
|
||||
:amount (- total-reimbursement)
|
||||
:currency "USD"
|
||||
:meta (if (= name "Sharp-Sage-A")
|
||||
{:entity name
|
||||
:project "Outreachy"
|
||||
:tax-implication "Reimbursement"}
|
||||
{:entity name
|
||||
:tax-implication "Reimbursement"})}]]
|
||||
(concat pay-exp-trans reimbursement-exp-trans))))})
|
||||
|
||||
(defn import-individual-taxes [groups]
|
||||
;; Print the individual taxes blocks
|
||||
(for [[name records] groups]
|
||||
(indiv-payroll-trans
|
||||
"2023-12-29"
|
||||
"Monthly Payroll - December 2023 - TAXES - %s"
|
||||
name
|
||||
"rt:19462/674660"
|
||||
(let [r-super-lines (filter #(str/starts-with? (:category %) "403b") records)
|
||||
;; TODO: Have I got the liability/witholding right? Which is used in which report.
|
||||
r-witholding-lines (filter #(= (:type %) "Withholding") records)
|
||||
r-insurance-lines (filter #(and (= (:type %) "Withholding")
|
||||
(str/includes? (:category %) "NY Disability")) records)
|
||||
total-super (->> r-super-lines
|
||||
(map :t-retirement)
|
||||
(apply +)
|
||||
bigdec)]
|
||||
(concat
|
||||
(for [x r-super-lines]
|
||||
(if (= (:category x) "403b ER match")
|
||||
{:account "Expenses:Payroll:Salary"
|
||||
:amount (:t-retirement x)
|
||||
:currency "USD"
|
||||
:meta {:payroll-type "US:403b:Match"
|
||||
:invoice "rt:19403/675431"}}
|
||||
{:account "Expenses:Payroll:Salary"
|
||||
:amount (:t-retirement x)
|
||||
:currency "USD"
|
||||
:meta {:payroll-type "US:403b:Employee"
|
||||
:invoice "rt:19403/675431"}}))
|
||||
[{:account "Liabilities:Payable:Accounts"
|
||||
:amount (- total-super)
|
||||
:currency "USD"
|
||||
:meta {:invoice "rt:19403/675431"}}]
|
||||
(conj
|
||||
(vec (for [x r-witholding-lines]
|
||||
{:account "Expenses:Payroll:Salary"
|
||||
:amount (:t-withholding x)
|
||||
:currency "USD"
|
||||
:meta {:payroll-type (cat->acct (:category x))}}))
|
||||
{:account "Assets:FR:Check2721"
|
||||
:amount (- (reduce + (map :t-withholding r-witholding-lines)))
|
||||
:currency "USD"
|
||||
:meta {:tax-implication "W2"}})
|
||||
;; We seem to add these extra insurance lines for Karen (only). Confirm with Rosanne.
|
||||
(conj
|
||||
(vec (for [x r-insurance-lines]
|
||||
{:account "Expenses:Insurance"
|
||||
:amount (- (:t-withholding x))
|
||||
:currency "USD"
|
||||
:meta {:payroll-type (cat->acct (:category x))}}))
|
||||
{:account "Assets:FR:Check2721"
|
||||
:amount (bigdec (reduce + (map :t-withholding r-insurance-lines)))
|
||||
:currency "USD"
|
||||
:meta {}}))))))
|
||||
{:date "2023-12-29" :desc (format "Monthly Payroll - December 2023 - TAXES - %s" (format-name name))
|
||||
:meta {:project (if (= (format-name name) "Sharp-Sage-A") "Outreachy" "Conservancy")
|
||||
:program "Conservancy:Payroll"
|
||||
:entity (format-name name)
|
||||
:receipt "rt:19462/674660"
|
||||
:approval "Financial/Employment-Records/memo-re-board-approval-of-payroll.txt"}
|
||||
:postings
|
||||
(let [super-lines (filter #(str/starts-with? (:category %) "403b") records)
|
||||
;; TODO: Have I got the liability/witholding right? Which is used in which report.
|
||||
witholding-lines (filter #(= (:type %) "Withholding") records)
|
||||
insurance-lines (filter #(and (= (:type %) "Withholding")
|
||||
(str/includes? (:category %) "NY Disability")) records)
|
||||
total-super (->> super-lines
|
||||
(map :t-retirement)
|
||||
(apply +)
|
||||
bigdec)]
|
||||
(concat
|
||||
(for [x super-lines]
|
||||
(if (= (:category x) "403b ER match")
|
||||
{:account "Expenses:Payroll:Salary"
|
||||
:amount (:t-retirement x)
|
||||
:currency "USD"
|
||||
:meta {:payroll-type "US:403b:Match"
|
||||
:invoice "rt:19403/675431"}}
|
||||
{:account "Expenses:Payroll:Salary"
|
||||
:amount (:t-retirement x)
|
||||
:currency "USD"
|
||||
:meta {:payroll-type "US:403b:Employee"
|
||||
:invoice "rt:19403/675431"}}))
|
||||
[{:account "Liabilities:Payable:Accounts"
|
||||
:amount (- total-super)
|
||||
:currency "USD"
|
||||
:meta {:invoice "rt:19403/675431"}}]
|
||||
(conj
|
||||
(vec (for [x witholding-lines]
|
||||
{:account "Expenses:Payroll:Salary"
|
||||
:amount (:t-withholding x)
|
||||
:currency "USD"
|
||||
:meta {:payroll-type (cat->acct (:category x))}}))
|
||||
{:account "Assets:FR:Check2721"
|
||||
:amount (- (reduce + (map :t-withholding witholding-lines)))
|
||||
:currency "USD"
|
||||
:meta {:tax-implication "W2"}})
|
||||
;; We seem to add these extra insurance lines for Karen (only). Confirm with Rosanne.
|
||||
(conj
|
||||
(vec (for [x insurance-lines]
|
||||
{:account "Expenses:Insurance"
|
||||
:amount (- (:t-withholding x))
|
||||
:currency "USD"
|
||||
:meta {:payroll-type (cat->acct (:category x))}}))
|
||||
{:account "Assets:FR:Check2721"
|
||||
:amount (bigdec (reduce + (map :t-withholding insurance-lines)))
|
||||
:currency "USD"})))}))
|
||||
|
||||
;; TODO: TAXES - Employer
|
||||
(defn import-employer-taxes [groups]
|
||||
{:date "2023-12-29" :desc "Monthly Payroll - December 2023 - TAXES - Employer"
|
||||
:meta {:program "Conservancy:Payroll"
|
||||
:project "Conservancy"
|
||||
:receipt "rt:19462/674660"
|
||||
:approval "Financial/Employment-Records/memo-re-board-approval-of-payroll.txt"}
|
||||
:postings
|
||||
(let [total-emp-tax (reduce + (map :t-liability (apply concat (vals groups))))]
|
||||
(conj (vec (apply concat (for [[name records] groups]
|
||||
(let [name (format-name name)
|
||||
liability-lines (filter #(= (:type %) "Liability") records)]
|
||||
(for [x liability-lines]
|
||||
{:account "Expenses:Payroll:Tax"
|
||||
:amount (:t-liability x)
|
||||
:currency "USD"
|
||||
:meta (if (= name "Sharp-Sage-A")
|
||||
{:entity name
|
||||
:project "Outreachy"
|
||||
;; TODO: Check lack of ":Tax:" with Rosanne.
|
||||
:payroll-type (str/replace (cat->acct (:category x)) "Tax:" "")}
|
||||
{:entity name
|
||||
:payroll-type (str/replace (cat->acct (:category x)) "Tax:" "")})})))))
|
||||
{:account "Assets:FR:Check2721"
|
||||
:amount (- total-emp-tax)
|
||||
:currency "USD"
|
||||
:meta {:entity "Paychex"
|
||||
:tax-implication "Tax-Payment"}
|
||||
}))})
|
||||
|
||||
;; TODO: Fee
|
||||
|
||||
|
|
|
@ -2,11 +2,13 @@
|
|||
(:require [clojure.spec.alpha :as s]
|
||||
[clojure.walk :as walk]))
|
||||
|
||||
(s/def ::token (s/+ (set "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890-:./")))
|
||||
(s/def ::token (s/+ (set "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890-:")))
|
||||
|
||||
(s/def ::number (s/+ (set "01234567890-.")))
|
||||
|
||||
(s/def ::quoted-token (s/cat
|
||||
:_ #{\"}
|
||||
:token (s/+ (set "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890-:./ "))
|
||||
:token (s/+ (set "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890-:./% "))
|
||||
:_ #{\"}))
|
||||
|
||||
(s/def ::whitespace (s/+ #{\space}))
|
||||
|
@ -23,7 +25,7 @@
|
|||
(s/cat :_ ::whitespace
|
||||
:account ::token
|
||||
:_ ::whitespace
|
||||
:amount ::token
|
||||
:amount ::number
|
||||
:_ ::whitespace
|
||||
:currency ::token
|
||||
:_ #{\newline}
|
||||
|
|
Loading…
Reference in a new issue