(ns auto-ap.datomic.ledger (:require [auto-ap.datomic :refer [add-sorter-fields apply-pagination apply-sort-4 conn merge-query observable-query pull-many]] [auto-ap.datomic.accounts :as d-accounts] [auto-ap.graphql.utils :refer [extract-client-ids]] [clj-time.coerce :as coerce] [datomic.api :as dc])) (defn raw-graphql-ids [db args] (let [valid-clients (extract-client-ids (:clients args) (:client-id args) (when (:client-code args) [:client/code (:client-code args)])) query (if (:exact-match-id args) {:query {:find '[?e] :in '[$ ?e [?c ...]] :where '[[?e :journal-entry/client ?c]]} :args [db (:exact-match-id args) valid-clients]} (cond-> {:query {:find [] :in ['$ '[?clients ?start ?end]] :where '[[(iol-ion.query/scan-ledger $ ?clients ?start ?end) [[?e _ ?sort-default] ...]]]} :args [db [valid-clients (some-> (:start (:date-range args)) coerce/to-date) (some-> (:end (:date-range args)) coerce/to-date)]]} (:only-external args) (merge-query {:query {:where ['(not [?e :journal-entry/original-entity])]}}) (seq (:external-id-like args)) (merge-query {:query {:in ['?external-id-like] :where ['[?e :journal-entry/external-id ?external-id] '[(.contains ^String ?external-id ?external-id-like)]]} :args [(:external-id-like args)]}) (seq (:source args)) (merge-query {:query {:in ['?source] :where ['[?e :journal-entry/source ?source]]} :args [(:source args)]}) (:vendor-id args) (merge-query {:query {:in ['?vendor-id] :where ['[?e :journal-entry/vendor ?vendor-id]]} :args [(:vendor-id args)]}) (or (seq (:numeric-code args)) (:bank-account-id args) (not-empty (:location args))) (merge-query {:query {:where ['[?e :journal-entry/line-items ?li]]}}) (seq (:numeric-code args)) (merge-query {:query {:in ['[[?from-numeric-code ?to-numeric-code]]] :where ['[?li :journal-entry-line/account ?a] '(or-join [?a ?c] [?a :account/numeric-code ?c] [?a :bank-account/numeric-code ?c]) '[(>= ?c ?from-numeric-code)] '[(<= ?c ?to-numeric-code)]]} :args [(vec (for [{:keys [from to]} (:numeric-code args)] [(or from 0) (or to 99999)]))]}) (:amount-gte args) (merge-query {:query {:in ['?amount-gte] :where ['[?e :journal-entry/amount ?a] '[(>= ?a ?amount-gte)]]} :args [(:amount-gte args)]}) (:amount-lte args) (merge-query {:query {:in ['?amount-lte] :where ['[?e :journal-entry/amount ?a] '[(<= ?a ?amount-lte)]]} :args [(:amount-lte args)]}) (:bank-account-id args) (merge-query {:query {:in ['?a] :where ['[?li :journal-entry-line/account ?a]]} :args [(:bank-account-id args)]}) (:account-id args) (merge-query {:query {:in ['?a2] :where ['[?e :journal-entry/line-items ?li2] '[?li2 :journal-entry-line/account ?a2]]} :args [(:account-id args)]}) (not-empty (:location args)) (merge-query {:query {:in ['?location] :where ['[?li :journal-entry-line/location ?location]]} :args [(:location args)]}) (not-empty (:locations args)) (merge-query {:query {:in ['[?location ...]] :where ['[?li :journal-entry-line/location ?location]]} :args [(:locations args)]}) (:sort args) (add-sorter-fields {"client" ['[?e :journal-entry/client ?c] '[?c :client/name ?sort-client]] "date" ['[?e :journal-entry/date ?sort-date]] "vendor" ['[?e :journal-entry/vendor ?v] '[?v :vendor/name ?sort-vendor]] "amount" ['[?e :journal-entry/amount ?sort-amount]] "external-id" ['[?e :journal-entry/external-id ?sort-external-id]] "source" ['[?e :journal-entry/source ?sort-source]]} args) true (merge-query {:query {:find ['?sort-default '?e]}})))] (->> (observable-query query) (apply-sort-4 (assoc args :default-asc? true)) (apply-pagination args)))) (defn graphql-results [ids db _] (let [results (->> (pull-many db '[* {:journal-entry/client [:client/name :client/code :db/id] :journal-entry/vendor [:vendor/name :db/id] :journal-entry/line-items [* {:journal-entry-line/account [* {:account/type [*]} {:account/client-overrides [:account-client-override/name {:account-client-override/client [:db/id]}]} {:bank-account/type [*]}]}]}] ids) (map #(update % :journal-entry/date coerce/from-date)) (map (fn [je] (update je :journal-entry/line-items (fn [jels] (map #(update % :journal-entry-line/account d-accounts/clientize (:db/id (:journal-entry/client je))) jels))))) (filter (fn [je] (every? (fn [jel] (let [include-in-reports (-> jel :journal-entry-line/account :bank-account/include-in-reports)] (or (nil? include-in-reports) (true? include-in-reports)))) (:journal-entry/line-items je)))) (group-by :db/id))] (->> ids (map results) (filter identity) (map first)))) (defn get-graphql [args] (let [db (dc/db conn) {ids-to-retrieve :ids matching-count :count} (raw-graphql-ids db args)] [(->> (graphql-results ids-to-retrieve db args)) matching-count])) (defn filter-ids [ids] (if ids (->> (dc/q {:find ['?e] :in ['$ '[?e ...]] :where ['[?e :journal-entry/date]]} (dc/db conn) ids) (map first) vec) []))