(ns user (:require [auto-ap.datomic :refer [uri]] [auto-ap.utils :refer [by]] [datomic.api :as d] [clojure.data.csv :as csv] [clj-time.coerce :as c] [clj-time.core :as t] [clojure.java.io :as io] [clojure.string :as str]) (:import [org.apache.commons.io.input BOMInputStream])) (defn mark-until-date [client end] (let [conn (d/connect uri)] (doseq [p (->> (d/query {:query {:find '[?e] :in '[$ ?client ?end ] :where [ '[?e :invoice/client ?c] '[?c :client/code ?client] '[?e :invoice/date ?d ] '[(<= ?d ?end) ]]} :args [(d/db conn) client (c/to-date end)]}) (mapv first) (mapv (fn [i] {:db/id i :invoice/exclude-from-ledger true})) (partition-all 100))] @(d/transact conn p) (println "process 100")) (doseq [p (->> (d/query {:query {:find '[?e] :in '[$ ?client ?end ] :where [ '[?e :transaction/client ?c] '[?c :client/code ?client] '[?e :transaction/date ?d ] '[(<= ?d ?end) ]]} :args [(d/db conn) client (c/to-date end)]}) (mapv first) (mapv (fn [i] {:db/id i :transaction/approval-status :transaction-approval-status/excluded})) (partition-all 100))] @(d/transact conn p) (println "process 100")))) (defn unapprove-all [] (let [conn (d/connect uri)] (doseq [p (->> (d/query {:query {:find '[?e] :in '[$ ] :where ['[?e :transaction/date ?d ]]} :args [(d/db conn)]}) (mapv first) (mapv (fn [i] {:db/id i :transaction/approval-status :transaction-approval-status/unapproved})) (partition-all 100))] @(d/transact conn p) (println "process 100")))) (defn load-accounts [conn] (let [[header & rows] (-> "master-account-list.csv" (io/resource) io/input-stream (BOMInputStream.) (io/reader) csv/read-csv) headers (map read-string header) code->existing-account (by :account/numeric-code (map first (d/query {:query {:find ['(pull ?e [:account/numeric-code :db/id])] :in ['$] :where ['[?e :account/name]]} :args [(d/db conn)]}))) also-merge-txes (fn [also-merge old-account-id] (if old-account-id (let [[sunset-account] (first (d/query {:query {:find ['?a ] :in ['$ '?ac ] :where ['[?a :account/numeric-code ?ac]]} :args [(d/db conn) also-merge ]}))] (into (mapv (fn [[entity id sunset-account]] [:db/add entity id old-account-id]) (d/query {:query {:find ['?e '?id '?a ] :in ['$ '?ac ] :where ['[?a :account/numeric-code ?ac] '[?e ?at ?a] '[?at :db/ident ?id]]} :args [(d/db conn) also-merge ]})) [[:db/retractEntity sunset-account]])) [])) txes (transduce (comp (map (fn ->map [r] (into {} (map vector header r)))) (map (fn parse-map [r] {:old-account-id (:db/id (code->existing-account (or (if (= (get r "IOL Account #") "NEW") nil (Integer/parseInt (get r "IOL Account #"))) (Integer/parseInt (get r "Account #"))))) :new-account-number (Integer/parseInt (get r "Account #")) :name (get r "Default Name") :location (when-not (str/blank? (get r "Forced Location")) (get r "Forced Location")) :also-merge (when-not (str/blank? (get r "IOL # additional")) (Integer/parseInt (get r "IOL # additional"))) :account-type (keyword "account-type" (str/lower-case (get r "Account Type"))) :applicability (keyword "account-applicability" (condp = (get r "Visiblity (Per-customer, Visible by default, hidden by default)") "Visible by default" "global" "Hidden by default" "optional" "Per Customer" "customized"))})) (mapcat (fn ->tx [{:keys [old-account-id new-account-number name location also-merge account-type applicability]}] (let [tx [(cond-> {:account/name name :account/type account-type :account/account-set "default" :account/applicability applicability :account/numeric-code new-account-number} old-account-id (assoc :db/id old-account-id) location (assoc :account/location location))]] (if also-merge (into tx (also-merge-txes also-merge old-account-id)) tx) )))) conj [] rows)] @(d/transact conn txes))) (defn find-bad-accounts [] (set (map second (d/query {:query {:find ['(pull ?x [*]) '?z] :in ['$] :where ['[?e :account/numeric-code ?z] '[(<= ?z 9999)] '[?x ?a ?e]]} :args [(d/db (d/connect uri))]})))) (defn delete-4-digit-accounts [] @(d/transact (d/connect uri) (transduce (comp (map first) (map (fn [old-account-id] [:db/retractEntity old-account-id]))) conj [] (d/query {:query {:find ['?e] :in ['$] :where ['[?e :account/numeric-code ?z] '[(<= ?z 9999)]]} :args [(d/db (d/connect uri))]}))) ) (defn find-conflicting-accounts [] (filter (fn [[k v]] (> (count v) 1)) (reduce (fn [acc [e z]] (update acc z conj e)) {} (d/query {:query {:find ['?e '?z] :in ['$] :where ['[?e :account/numeric-code ?z]]} :args [(d/db (d/connect uri))]})))) (defn customize-accounts [customer filename] (let [conn (d/connect uri) [header & rows] (-> filename (io/resource) io/input-stream (BOMInputStream.) (io/reader) csv/read-csv) [client-id] (first (d/query (-> {:query {:find ['?e] :in ['$ '?z] :where [['?e :client/code '?z]]} :args [(d/db (d/connect uri)) customer]}))) _ (println client-id) headers (map read-string header) code->existing-account (by :account/numeric-code (map first (d/query {:query {:find ['(pull ?e [:account/numeric-code :db/id])] :in ['$] :where ['[?e :account/name]]} :args [(d/db conn)]}))) txes (transduce (comp (filter (fn [[_ account _ override-name]] (and (not (str/blank? override-name)) (not (str/blank? account))))) (map (fn parse-map [[_ account account-name override-name _ type]] (let [code (Integer/parseInt account) existing-id (:db/id (code->existing-account code))] (cond-> {:account/client-overrides [{:account-client-override/client client-id :account-client-override/name override-name}]} existing-id (assoc :db/id existing-id) (not existing-id) (assoc :account/applicability :account-applicability/customized :account/name account-name :account/account-set "default" :account/numeric-code code :account/code (str code) :account/type (keyword "account-type" (str/lower-case type)))))))) conj [] rows)] @(d/transact conn txes))) (defn cash-flow-simple [] (let [total-cash (reduce (fn [total [credit debit]] (- (+ total credit) debit)) 0.0 (d/query {:query {:find '[?debit ?credit] :in '[$ ?client] :where ['[?j :journal-entry/client ?c] '[?c :client/code ?client] '[?j :journal-entry/line-items ?je] '[?je :journal-entry-line/account ?ba] '[?ba :bank-account/type :bank-account-type/check] '[(get-else $ ?je :journal-entry-line/debit 0.0) ?debit] '[(get-else $ ?je :journal-entry-line/credit 0.0) ?credit]]} :args [(d/db (d/connect uri)) "CBC"]})) bills-due-soon (d/query {:query {:find '[?due ?outstanding] :in '[$ ?client ?due-before] :where ['[?i :invoice/client ?c] '[?c :client/code ?client] '[?i :invoice/status :invoice-status/unpaid] '[?i :invoice/due ?due] '[(<= ?due ?due-before)] '[?i :invoice/outstanding-balance ?outstanding]]} :args [(d/db (d/connect uri)) "CBC" (c/to-date (t/plus (auto-ap.time/local-now) (t/days 7)))]}) outstanding-checks (reduce + 0.0 (map first (d/query {:query {:find '[?amount] :in '[$ ?client ?due-before] :where ['[?p :payment/client ?c] '[?c :client/code ?client] '[?p :payment/status :payment-status/pending] '[?p :payment/amount ?amount] '(or [?p :payment/type :payment-type/debit] [?p :payment/type :payment-type/check])]} :args [(d/db (d/connect uri)) "CBC" (c/to-date (t/plus (auto-ap.time/local-now) (t/days 7)))]})))] [total-cash bills-due-soon outstanding-checks]) #_(->> (d/query {:query {:find '[?account-type-ident ?date ?debit ?credit] :in '[$ ?client] :where ['[?j :journal-entry/line-items ?je] '[?j :journal-entry/date ?date] '[?je :journal-entry-line/account ?a] '[(get-else $ ?je :journal-entry-line/debit 0.0) ?debit] '[(get-else $ ?je :journal-entry-line/credit 0.0) ?credit] '[?a :account/type ?account-type] '[?account-type :db/ident ?account-type-ident]]} :args [(d/db (d/connect uri)) "CBC"]}) (reduce (fn [result [account-type date debit credit]] (let [date (clj-time.coerce/from-date date)] (let [year-month (str (clj-time.core/year date) "-" (clj-time.core/month date))] (-> result (update-in [year-month account-type :debit] (fn [existing-debit] (+ (or existing-debit 0.0) debit))) (update-in [year-month account-type :credit] (fn [existing-credit] (+ (or existing-credit 0.0) credit))) (update-in [year-month account-type :count] #(inc (or % 0))))))) {}))) (defn attach-signature [client-code filename] @(d/transact (d/connect uri) [{:db/id [:client/code client-code] :client/signature-file (str "https://s3.amazonaws.com/integreat-signature-images/" filename)}]))