(ns auto-ap.datomic.ledger (:require [datomic.api :as d] [auto-ap.graphql.utils :refer [limited-clients]] [auto-ap.datomic :refer [merge-query apply-sort-3 apply-pagination add-sorter-fields conn]] [clj-time.coerce :as c] [auto-ap.datomic.accounts :as d-accounts])) (defn raw-graphql-ids [db args] (let [query (cond-> {:query {:find [] :in ['$ ] :where []} :args [db]} (:client-id args) (merge-query {:query {:in ['?client-id] :where ['[?e :journal-entry/client ?client-id]]} :args [(:client-id args)]}) (: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)]}) (:client-code args) (merge-query {:query {:in ['?client-code] :where ['[?e :journal-entry/client ?client-id] '[?client-id :client/code ?client-code]]} :args [(:client-code args)]}) (:start (:date-range args)) (merge-query {:query {:in ['?start-date] :where ['[?e :journal-entry/date ?date] '[(>= ?date ?start-date)]]} :args [(c/to-date (:start (:date-range args)))]}) (:end (:date-range args)) (merge-query {:query {:in ['?end-date] :where ['[?e :journal-entry/date ?date] '[(<= ?date ?end-date)]]} :args [(c/to-date (:end (:date-range args)))]}) (or (:from-numeric-code args) (:to-numeric-code args) (:bank-account-id args) (not-empty (:location args))) (merge-query {:query {:where ['[?e :journal-entry/line-items ?li]]}}) (or (:from-numeric-code args) (:to-numeric-code args)) (merge-query {:query {:in [] :where ['[?li :journal-entry-line/account ?a] '(or-join [?a ?c] [?a :account/numeric-code ?c] [?a :bank-account/numeric-code ?c])]} :args []}) (:from-numeric-code args) (merge-query {:query {:in ['?from-numeric-code] :where ['[(>= ?c ?from-numeric-code)]]} :args [(:from-numeric-code args)]}) (: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)]}) (:to-numeric-code args) (merge-query {:query {:in ['?to-numeric-code] :where ['[(<= ?c ?to-numeric-code)]]} :args [(:to-numeric-code args)]}) (not-empty (:location args)) (merge-query {:query {:in ['?location] :where ['[?li :journal-entry-line/location ?location]]} :args [(:location args)]}) (limited-clients (:id args)) (merge-query {:query {:in ['[?xx ...]] :where ['[?e :journal-entry/client ?xx]]} :args [(set (map :db/id (limited-clients (:id 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] :where ['[?e :journal-entry/date ?sort-default]]}}))] (->> query (d/query) (apply-sort-3 (update args :sort conj {:sort-key "default-2" :asc true})) (apply-pagination args)))) (defn graphql-results [ids db _] (let [results (->> (d/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 c/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 (d/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 (->> {:query {:find ['?e] :in ['$ '[?e ...]] :where ['[?e :journal-entry/date]]} :args [(d/db conn) ids]} (d/query) (map first) vec) []))