Rename lines/data to records, put currency on same line as amount, add docs
This commit is contained in:
parent
dc5692c718
commit
59a15c3d6f
1 changed files with 89 additions and 116 deletions
205
src/import.clj
205
src/import.clj
|
@ -65,10 +65,14 @@
|
|||
(assoc m :project (get projects name))
|
||||
m))
|
||||
|
||||
(defn total [records]
|
||||
(defn total
|
||||
"Sum the provided records."
|
||||
[records]
|
||||
(->> records (map :amount) (reduce + 0M)))
|
||||
|
||||
(defn total-by-type [type records]
|
||||
(defn total-by-type
|
||||
"Sum up the provided records that match this type."
|
||||
[type records]
|
||||
(->> records
|
||||
(filter #(= (:type %) type))
|
||||
(map :amount)
|
||||
|
@ -130,7 +134,7 @@
|
|||
|
||||
(defn net-pay
|
||||
"Return a net pay transaction."
|
||||
[date period receipt-no projects data]
|
||||
[date period receipt-no projects records]
|
||||
(let [template {:date date :desc (format "Monthly Payroll - %s - Net Pay" period)
|
||||
:meta {:program "Conservancy:Payroll"
|
||||
:project "Conservancy"
|
||||
|
@ -140,32 +144,28 @@
|
|||
:payroll-type "US:General"}
|
||||
:postings []}
|
||||
postings (flatten
|
||||
(for [[name records] (group-by :name data)]
|
||||
(let [total-net-pay (total-by-type "Net Pay" records)
|
||||
total-reimbursement (total-by-type "Reimbursement" records)
|
||||
(for [[name employee-records] (group-by :name records)]
|
||||
(let [total-net-pay (total-by-type "Net Pay" employee-records)
|
||||
total-reimbursement (total-by-type "Reimbursement" employee-records)
|
||||
actual-total-net-pay (- total-net-pay total-reimbursement)]
|
||||
[{:account "Expenses:Payroll:Salary"
|
||||
:amount actual-total-net-pay
|
||||
:currency "USD"
|
||||
:amount actual-total-net-pay :currency "USD"
|
||||
:meta (assoc-project projects name {:entity name})}
|
||||
{:account "Liabilities:Payable:Accounts"
|
||||
:amount (- actual-total-net-pay)
|
||||
:currency "USD"
|
||||
:amount (- actual-total-net-pay) :currency "USD"
|
||||
:meta {:entity name}}
|
||||
{:account "Expenses:Hosting"
|
||||
:amount total-reimbursement
|
||||
:currency "USD"
|
||||
:amount total-reimbursement :currency "USD"
|
||||
:meta (assoc-project projects name {:entity name :payroll-type "US:Reimbursement"})}
|
||||
{:account "Liabilities:Payable:Accounts"
|
||||
:amount (- total-reimbursement)
|
||||
:currency "USD"
|
||||
:amount (- total-reimbursement) :currency "USD"
|
||||
:meta (assoc-project projects name {:entity name :tax-implication "Reimbursement"})}])))]
|
||||
[(assoc template :postings postings)]))
|
||||
|
||||
(defn individual-taxes
|
||||
"Return a transaction of expenses/witholding for each employee."
|
||||
[date period receipt-no invoice-no projects data]
|
||||
(for [[name records] (group-by :name data)]
|
||||
[date period receipt-no invoice-no projects records]
|
||||
(for [[name employee-records] (group-by :name records)]
|
||||
(let [template {:date date :desc (format "Monthly Payroll - %s - TAXES - %s" period name)
|
||||
:meta (assoc-project
|
||||
projects name
|
||||
|
@ -175,47 +175,40 @@
|
|||
:invoice receipt-no
|
||||
:approval "Financial/Employment-Records/memo-re-board-approval-of-payroll.txt"})
|
||||
:postings []}
|
||||
retirement-lines (filter #(= (:type %) "Retirement") records)
|
||||
witholding-lines (filter #(= (:type %) "Withholding") records)
|
||||
retirement-records (filter #(= (:type %) "Retirement") employee-records)
|
||||
witholding-records (filter #(= (:type %) "Withholding") employee-records)
|
||||
;; We add these extra disability insurance/asset postings for NY only
|
||||
;; as discussed in beancount/doc/Payroll.md.
|
||||
insurance-lines (filter (fn [{:keys [category type]}]
|
||||
insurance-records (filter (fn [{:keys [category type]}]
|
||||
(and (= type "Withholding")
|
||||
(str/starts-with? category "NY Disability"))) records)
|
||||
total-retirement (total retirement-lines)
|
||||
retirement-postings (for [{:keys [category amount]} retirement-lines]
|
||||
(str/starts-with? category "NY Disability"))) employee-records)
|
||||
total-retirement (total retirement-records)
|
||||
retirement-postings (for [{:keys [category amount]} retirement-records]
|
||||
(if (= category "403b ER match")
|
||||
{:account "Expenses:Payroll:Salary"
|
||||
:amount amount
|
||||
:currency "USD"
|
||||
:amount amount :currency "USD"
|
||||
:meta {:payroll-type "US:403b:Match"
|
||||
:invoice invoice-no}}
|
||||
{:account "Expenses:Payroll:Salary"
|
||||
:amount amount
|
||||
:currency "USD"
|
||||
:amount amount :currency "USD"
|
||||
:meta {:payroll-type "US:403b:Employee"
|
||||
:invoice invoice-no}}))
|
||||
liability-postings [{:account "Liabilities:Payable:Accounts"
|
||||
:amount (- total-retirement)
|
||||
:currency "USD"
|
||||
:amount (- total-retirement) :currency "USD"
|
||||
:meta {:invoice invoice-no}}]
|
||||
withholding-postings (for [{:keys [category amount]} witholding-lines]
|
||||
withholding-postings (for [{:keys [category amount]} witholding-records]
|
||||
{:account "Expenses:Payroll:Salary"
|
||||
:amount amount
|
||||
:currency "USD"
|
||||
:amount amount :currency "USD"
|
||||
:meta {:payroll-type (cat->payroll-type category)}})
|
||||
withholding-asset-postings [{:account "Liabilities:Payable:Accounts"
|
||||
:amount (- (total witholding-lines))
|
||||
:currency "USD"
|
||||
:amount (- (total witholding-records)) :currency "USD"
|
||||
:meta {:tax-implication "W2"}}]
|
||||
insurance-postings (for [{:keys [category amount]} insurance-lines]
|
||||
insurance-postings (for [{:keys [category amount]} insurance-records]
|
||||
{:account "Expenses:Insurance"
|
||||
:amount (- amount)
|
||||
:currency "USD"
|
||||
:amount (- amount) :currency "USD"
|
||||
:meta {:payroll-type (cat->payroll-type category)}})
|
||||
insurance-asset-postings [{:account "Liabilities:Payable:Accounts"
|
||||
:amount (total insurance-lines)
|
||||
:currency "USD"}]
|
||||
:amount (total insurance-records) :currency "USD"}]
|
||||
all-postings (concat
|
||||
retirement-postings
|
||||
liability-postings
|
||||
|
@ -225,24 +218,21 @@
|
|||
insurance-asset-postings)]
|
||||
(assoc template :postings all-postings))))
|
||||
|
||||
;; TODO: Rename data to records?
|
||||
|
||||
(defn employer-taxes
|
||||
"Return an employer taxes transaction."
|
||||
[date period receipt-no projects data]
|
||||
[date period receipt-no projects records]
|
||||
(let [template {:date date :desc (format "Monthly Payroll - %s - TAXES - Employer" period)
|
||||
:meta {:program "Conservancy:Payroll"
|
||||
:project "Conservancy"
|
||||
:invoice receipt-no
|
||||
:approval "Financial/Employment-Records/memo-re-board-approval-of-payroll.txt"}
|
||||
:postings []}
|
||||
liability-lines (filter (fn [{:keys [category type]}]
|
||||
liability-records (filter (fn [{:keys [category type]}]
|
||||
(and (= type "Liability")
|
||||
(not (str/includes? category "Unemploy")))) data)
|
||||
liability-postings (for [{:keys [amount name category]} liability-lines]
|
||||
(not (str/includes? category "Unemploy")))) records)
|
||||
liability-postings (for [{:keys [amount name category]} liability-records]
|
||||
{:account "Expenses:Payroll:Tax"
|
||||
:amount amount
|
||||
:currency "USD"
|
||||
:amount amount :currency "USD"
|
||||
;; Use eg. "US:Medicare", not "US:Tax:Medicare" as
|
||||
;; in individual-taxes as confirmed by Rosanne.
|
||||
:meta (assoc-project
|
||||
|
@ -250,33 +240,29 @@
|
|||
name
|
||||
{:entity name
|
||||
:payroll-type (str/replace (cat->payroll-type category) "Tax:" "")})})
|
||||
;; Can this use total liability-lines?
|
||||
total-liabilities (total liability-postings)
|
||||
unemploy-lines (filter (fn [{:keys [category type]}]
|
||||
total-liabilities (total liability-records)
|
||||
unemploy-records (filter (fn [{:keys [category type]}]
|
||||
(and (= type "Liability")
|
||||
(str/includes? category "Unemploy"))) data)
|
||||
unemploy-postings (for [{:keys [amount name category]} unemploy-lines]
|
||||
(str/includes? category "Unemploy"))) records)
|
||||
unemploy-postings (for [{:keys [amount name category]} unemploy-records]
|
||||
{:account "Expenses:Payroll:Tax"
|
||||
:amount amount
|
||||
:currency "USD"
|
||||
:amount amount :currency "USD"
|
||||
:meta (assoc-project projects
|
||||
name
|
||||
{:entity (first (str/split category #" "))
|
||||
:memo name ; distinguishes multiple employees in one state
|
||||
:memo name ; distinguishes multiple employees in one state
|
||||
:payroll-type (str "US:" (cat->payroll-type category))})})
|
||||
;; Can this use total unemploy-lines?
|
||||
total-unemploy (total unemploy-postings)
|
||||
total-unemploy (total unemploy-records)
|
||||
asset-postings [{:account "Liabilities:Payable:Accounts"
|
||||
:amount (- (+ total-liabilities total-unemploy))
|
||||
:currency "USD"
|
||||
:amount (- (+ total-liabilities total-unemploy)) :currency "USD"
|
||||
:meta {:entity "Paychex"
|
||||
:tax-implication "Tax-Payment"}}]
|
||||
all-postings (concat liability-postings unemploy-postings asset-postings)]
|
||||
[(assoc template :postings all-postings)]))
|
||||
|
||||
(defn fees
|
||||
"Return a payroll fees transaction."
|
||||
[date period receipt-no invoice-no total-fees projects data]
|
||||
"Return a transaction paying payroll fees to Paychex payroll fees transaction."
|
||||
[date period receipt-no invoice-no total-fees projects records]
|
||||
(let [template {:date date :payee "Paychex" :desc (format "Monthly Payroll - %s - Fee" period)
|
||||
:meta {:program "Conservancy:Payroll"
|
||||
:project "Conservancy"
|
||||
|
@ -285,23 +271,21 @@
|
|||
:approval "Financial/Employment-Records/memo-re-board-approval-of-payroll.txt"
|
||||
:tax-implication "USA-Corporation"}
|
||||
:postings []}
|
||||
employees (distinct (map :name data))
|
||||
employees (distinct (map :name records))
|
||||
exact-fee-allocation (split-fee total-fees (count employees))
|
||||
employee-fees (map vector employees exact-fee-allocation)
|
||||
expense-postings (for [[name fee] employee-fees]
|
||||
{:account "Expenses:Payroll:Fees"
|
||||
:amount fee
|
||||
:currency "USD"
|
||||
:amount fee :currency "USD"
|
||||
:meta (assoc-project projects name {:entity name})})
|
||||
asset-postings [{:account "Assets:FR:Check2721"
|
||||
:amount (- total-fees)
|
||||
:currency "USD"}]
|
||||
:amount (- total-fees) :currency "USD"}]
|
||||
all-postings (concat expense-postings asset-postings)]
|
||||
[(assoc template :postings all-postings)]))
|
||||
|
||||
(defn retirement
|
||||
"Return a retirement transaction."
|
||||
[date period receipt-no invoice-no data]
|
||||
"Return a transaction paying off retirement liabilities."
|
||||
[date period receipt-no invoice-no records]
|
||||
(let [template {:date date :desc (format "ASCENSUS TRUST RET PLAN - ACH DEBIT - Vanguard 403(b) - %s" period)
|
||||
:meta {:program "Conservancy:Payroll"
|
||||
:project "Conservancy"
|
||||
|
@ -310,24 +294,21 @@
|
|||
:tax-implication "Retirement-Pretax"
|
||||
:invoice invoice-no}
|
||||
:postings []}
|
||||
liability-postings (for [[name records] (group-by :name data)]
|
||||
(let [total-retirement (total-by-type "Retirement" records)]
|
||||
liability-postings (for [[name employee-records] (group-by :name records)]
|
||||
(let [total-retirement (total-by-type "Retirement" employee-records)]
|
||||
{:account "Liabilities:Payable:Accounts"
|
||||
:amount total-retirement
|
||||
:currency "USD"
|
||||
:amount total-retirement :currency "USD"
|
||||
:meta {:entity name}}))
|
||||
total-liabilities (total liability-postings)
|
||||
asset-postings [{:account "Assets:FR:Check1345"
|
||||
:amount (- total-liabilities)
|
||||
:currency "USD"}]
|
||||
:amount (- total-liabilities) :currency "USD"}]
|
||||
all-postings (concat liability-postings asset-postings)]
|
||||
[(assoc template :postings all-postings)]))
|
||||
|
||||
|
||||
(defn net-pay-ach-debit
|
||||
;; TODO: Docstring
|
||||
"Return a net pay transaction."
|
||||
[date period receipt-no invoice-no projects data]
|
||||
"Return a transaction paying off net pay liabilities"
|
||||
[date period receipt-no invoice-no projects records]
|
||||
(let [template {:date date :desc (format "Monthly Payroll - %s - Net Pay - ACH debit" period)
|
||||
:meta {:program "Conservancy:Payroll"
|
||||
:project "Conservancy"
|
||||
|
@ -338,34 +319,29 @@
|
|||
:payroll-type "US:General"}
|
||||
:postings []}
|
||||
employee-postings (flatten
|
||||
(for [[name records] (group-by :name data)]
|
||||
(let [net-pay (total-by-type "Net Pay" records)
|
||||
reimbursements (total-by-type "Reimbursement" records)]
|
||||
(for [[name employee-records] (group-by :name records)]
|
||||
(let [net-pay (total-by-type "Net Pay" employee-records)
|
||||
reimbursements (total-by-type "Reimbursement" employee-records)]
|
||||
[{:account "Liabilities:Payable:Accounts"
|
||||
:amount (- net-pay reimbursements)
|
||||
:currency "USD"
|
||||
:amount (- net-pay reimbursements) :currency "USD"
|
||||
:meta (assoc-project projects name {:entity name})}
|
||||
{:account "Liabilities:Payable:Accounts"
|
||||
:amount reimbursements
|
||||
:currency "USD"
|
||||
:amount reimbursements :currency "USD"
|
||||
:meta (assoc-project projects name {:entity name})}])))
|
||||
total-net-pay (total-by-type "Net Pay" data)
|
||||
total-reimbursements (total-by-type "Reimbursement" data)
|
||||
total-net-pay (total-by-type "Net Pay" records)
|
||||
total-reimbursements (total-by-type "Reimbursement" records)
|
||||
total-net-pay-posting {:account "Assets:FR:Check2721"
|
||||
:amount (- (- total-net-pay total-reimbursements))
|
||||
:currency "USD"
|
||||
:amount (- (- total-net-pay total-reimbursements)) :currency "USD"
|
||||
:meta {:entity "Paychex" :tax-implication "W2"}}
|
||||
total-reimbursements-posting {:account "Assets:FR:Check2721"
|
||||
:amount (- total-reimbursements)
|
||||
:currency "USD"
|
||||
:amount (- total-reimbursements) :currency "USD"
|
||||
:meta {:entity "Paychex" :tax-implication "Reimbursement"}}
|
||||
all-postings (concat employee-postings [total-net-pay-posting total-reimbursements-posting])]
|
||||
[(assoc template :postings all-postings)]))
|
||||
|
||||
(defn taxes-ach-debit
|
||||
;; TODO: Docstring
|
||||
"Return an employer taxes transaction."
|
||||
[date period receipt-no invoice-no projects data]
|
||||
"Return a transaction paying off tax liabilities."
|
||||
[date period receipt-no invoice-no projects records]
|
||||
(let [template {:date date :desc (format "Monthly Payroll - %s - TAXES - ACH debit" period)
|
||||
:meta {:program "Conservancy:Payroll"
|
||||
:project "Conservancy"
|
||||
|
@ -373,35 +349,32 @@
|
|||
:invoice invoice-no
|
||||
:approval "Financial/Employment-Records/memo-re-board-approval-of-payroll.txt"}
|
||||
:postings []}
|
||||
liability-lines (filter (fn [{:keys [category type]}]
|
||||
liability-records (filter (fn [{:keys [category type]}]
|
||||
(and (= type "Liability")
|
||||
(not (str/includes? category "Unemploy")))) data)
|
||||
total-liabilities (total liability-lines)
|
||||
unemploy-lines (filter (fn [{:keys [category type]}]
|
||||
(not (str/includes? category "Unemploy")))) records)
|
||||
total-liabilities (total liability-records)
|
||||
unemploy-records (filter (fn [{:keys [category type]}]
|
||||
(and (= type "Liability")
|
||||
(str/includes? category "Unemploy"))) data)
|
||||
total-unemploy (total unemploy-lines)
|
||||
(str/includes? category "Unemploy"))) records)
|
||||
total-unemploy (total unemploy-records)
|
||||
liability-postings [{:account "Liabilities:Payable:Accounts"
|
||||
:amount (+ total-liabilities total-unemploy)
|
||||
:currency "USD"
|
||||
:meta {:entity "Paychex"}}]
|
||||
:amount (+ total-liabilities total-unemploy) :currency "USD"
|
||||
:meta {:entity "Paychex"}}]
|
||||
withholding-liability-postings (flatten
|
||||
(for [[name records] (group-by :name data)]
|
||||
(let [witholding-lines (filter #(= (:type %) "Withholding") records)
|
||||
insurance-lines (filter (fn [{:keys [category type]}]
|
||||
(and (= type "Withholding")
|
||||
(str/starts-with? category "NY Disability"))) records)]
|
||||
[{:account "Liabilities:Payable:Accounts"
|
||||
:amount (total witholding-lines)
|
||||
:currency "USD"
|
||||
:meta (assoc-project projects name {:entity name})}
|
||||
{:account "Liabilities:Payable:Accounts"
|
||||
:amount (- (total insurance-lines))
|
||||
:currency "USD"
|
||||
:meta (assoc-project projects name {:entity name})}])))
|
||||
(for [[name employee-records] (group-by :name records)]
|
||||
(let [witholding-records (filter #(= (:type %) "Withholding") employee-records)
|
||||
insurance-records (filter (fn [{:keys [category type]}]
|
||||
(and (= type "Withholding")
|
||||
(str/starts-with? category "NY Disability")))
|
||||
employee-records)]
|
||||
[{:account "Liabilities:Payable:Accounts"
|
||||
:amount (total witholding-records) :currency "USD"
|
||||
:meta (assoc-project projects name {:entity name})}
|
||||
{:account "Liabilities:Payable:Accounts"
|
||||
:amount (- (total insurance-records)) :currency "USD"
|
||||
:meta (assoc-project projects name {:entity name})}])))
|
||||
asset-postings [{:account "Assets:FR:Check2721"
|
||||
:amount (- (+ total-liabilities total-unemploy (total withholding-liability-postings)))
|
||||
:currency "USD"
|
||||
:amount (- (+ total-liabilities total-unemploy (total withholding-liability-postings))) :currency "USD"
|
||||
:meta {:entity "Paychex" :tax-implication "Tax-Payment"}}]
|
||||
all-postings (concat withholding-liability-postings liability-postings asset-postings)]
|
||||
[(assoc template :postings all-postings)]))
|
||||
|
|
Loading…
Reference in a new issue