1262 lines
56 KiB
Clojure
1262 lines
56 KiB
Clojure
(ns auto-ap.graphql
|
|
(:require [auto-ap.datomic :refer [merge-query uri]]
|
|
[auto-ap.datomic.checks :as d-checks]
|
|
[auto-ap.datomic.sales-orders :as d-sales-orders]
|
|
[auto-ap.datomic.users :as d-users]
|
|
[auto-ap.graphql.accounts :as gq-accounts]
|
|
[auto-ap.graphql.checks :as gq-checks]
|
|
[auto-ap.graphql.clients :as gq-clients]
|
|
[auto-ap.graphql.expected-deposit :as gq-expected-deposit]
|
|
[auto-ap.graphql.invoices :as gq-invoices]
|
|
[auto-ap.graphql.ledger :as gq-ledger]
|
|
[auto-ap.graphql.sales-orders :as gq-sales-orders]
|
|
[auto-ap.graphql.transaction-rules :as gq-transaction-rules]
|
|
[auto-ap.graphql.transactions :as gq-transactions]
|
|
[auto-ap.graphql.users :as gq-users]
|
|
[auto-ap.graphql.utils :refer [assert-admin assert-can-see-client]]
|
|
[auto-ap.graphql.vendors :as gq-vendors]
|
|
[auto-ap.graphql.yodlee-merchants :as ym]
|
|
[auto-ap.logging :refer [error-event info-event warn-event]]
|
|
[auto-ap.time :as time]
|
|
[clj-time.coerce :as coerce]
|
|
[clj-time.core :as t]
|
|
[clojure.string :as str]
|
|
[clojure.tools.logging :as log]
|
|
[clojure.walk :as walk]
|
|
[com.walmartlabs.lacinia :refer [execute]]
|
|
[com.walmartlabs.lacinia.schema :as schema]
|
|
[com.walmartlabs.lacinia.util :refer [attach-resolvers]]
|
|
[datomic.api :as d]
|
|
[unilog.context :as lc]
|
|
[yang.time :refer [time-it]])
|
|
(:import clojure.lang.IPersistentMap))
|
|
|
|
(def integreat-schema
|
|
{
|
|
:scalars {:id {:parse (schema/as-conformer #(when % (Long/parseLong %)))
|
|
:serialize (schema/as-conformer #(.toString %))}
|
|
:ident {:parse (schema/as-conformer (fn [x] {:db/ident x}))
|
|
:serialize (schema/as-conformer #(or (:ident %) (:db/ident %) %))}
|
|
:iso_date {:parse (schema/as-conformer #(time/parse % time/iso-date))
|
|
:serialize (schema/as-conformer #(time/unparse % time/iso-date))}
|
|
:money {:parse (schema/as-conformer #(if (and (string? %)
|
|
(not (str/blank? %)))
|
|
(Double/parseDouble %)
|
|
%))
|
|
:serialize (schema/as-conformer #(if (double? %)
|
|
(str %)
|
|
%))
|
|
}
|
|
:percentage {:parse (schema/as-conformer #(if (and (string? %)
|
|
(not (str/blank? %)))
|
|
(Double/parseDouble %)
|
|
%))
|
|
:serialize (schema/as-conformer #(if (double? %)
|
|
(str %)
|
|
%))}}
|
|
:objects
|
|
{
|
|
:message
|
|
{:fields {:message {:type 'String}}}
|
|
:location_match
|
|
{:fields {:location {:type 'String}
|
|
:match {:type 'String}
|
|
:id {:type :id}}}
|
|
|
|
:client
|
|
{:fields {:id {:type :id}
|
|
:name {:type 'String}
|
|
:code {:type 'String}
|
|
:week_a_debits {:type :money}
|
|
:week_a_credits {:type :money}
|
|
:week_b_debits {:type :money}
|
|
:week_b_credits {:type :money}
|
|
:email {:type 'String}
|
|
:address {:type :address}
|
|
:location_matches {:type '(list :location_match)}
|
|
:locations {:type '(list String)}
|
|
:matches {:type '(list String)}
|
|
:bank_accounts {:type '(list :bank_account)}
|
|
:forecasted_transactions {:type '(list :forecasted_transaction)}}}
|
|
:contact
|
|
{:fields {:id {:type :id}
|
|
:name {:type 'String}
|
|
:email {:type 'String}
|
|
:phone {:type 'String}}}
|
|
|
|
:bank_account
|
|
{:fields {:id {:type :id }
|
|
:type {:type :ident}
|
|
:start_date {:type :iso_date}
|
|
:number {:type 'String}
|
|
:sort_order {:type 'Int}
|
|
:visible {:type 'Boolean}
|
|
:include_in_reports {:type 'Boolean}
|
|
:routing {:type 'String}
|
|
:code {:type 'String}
|
|
:check_number {:type 'Int}
|
|
:name {:type 'String}
|
|
:bank_code {:type 'String}
|
|
:bank_name {:type 'String}
|
|
:yodlee_account_id {:type 'Int}
|
|
:locations {:type '(list String)}}}
|
|
:forecasted_transaction {:fields {:identifier {:type 'String}
|
|
:id {:type :id}
|
|
:day_of_month {:type 'Int}
|
|
:amount {:type :money}}}
|
|
:balance_sheet_account
|
|
{:fields {:id {:type 'String}
|
|
:amount {:type 'String}
|
|
:location {:type 'String}
|
|
:count {:type 'Int}
|
|
:numeric_code {:type 'Int}
|
|
:account_type {:type :account_type}
|
|
:name {:type 'String}}}
|
|
|
|
:balance_sheet
|
|
{:fields {:balance_sheet_accounts {:type '(list :balance_sheet_account)}
|
|
:comparable_balance_sheet_accounts {:type '(list :balance_sheet_account)}}}
|
|
|
|
:profit_and_loss_report_period
|
|
{:fields {:accounts {:type '(list :balance_sheet_account)}}}
|
|
|
|
:profit_and_loss_report
|
|
{:fields {:periods {:type '(list :profit_and_loss_report_period)}}}
|
|
|
|
:address
|
|
{:fields {:street1 {:type 'String}
|
|
:street2 {:type 'String}
|
|
:city {:type 'String}
|
|
:state {:type 'String}
|
|
:zip {:type 'String}}}
|
|
|
|
:terms_override
|
|
{:fields {:id {:type :id}
|
|
:client {:type :client}
|
|
:terms {:type 'Int}
|
|
}}
|
|
|
|
:schedule_payment_dom
|
|
{:fields {:id {:type :id}
|
|
:client {:type :client}
|
|
:dom {:type 'Int}}}
|
|
|
|
:vendor_account_override
|
|
{:fields {:id {:type :id}
|
|
:client {:type :client}
|
|
:account {:type :account}}}
|
|
|
|
:usage {:fields {:client_id {:type :id}
|
|
:count {:type 'Int}}}
|
|
|
|
:vendor
|
|
{:fields {:id {:type :id}
|
|
:name {:type 'String}
|
|
:code {:type 'String}
|
|
:terms {:type 'Int}
|
|
:hidden {:type 'Boolean}
|
|
:automatically_paid_when_due {:type '(list :client)}
|
|
:terms_overrides {:type '(list :terms_override)}
|
|
:schedule_payment_dom {:type '(list :schedule_payment_dom)}
|
|
:account_overrides {:type '(list :vendor_account_override)}
|
|
:usage {:type '(list :usage)}
|
|
|
|
:print_as {:type 'String}
|
|
:primary_contact {:type :contact}
|
|
:secondary_contact {:type :contact}
|
|
:address {:type :address}
|
|
|
|
:default_account {:type :account}
|
|
:invoice_reminder_schedule {:type 'String}}}
|
|
:reminder
|
|
{:fields {:id {:type 'Int}
|
|
:email {:type 'String}
|
|
:subject {:type 'String}
|
|
:body {:type 'String}
|
|
:scheduled {:type 'String}
|
|
:sent {:type 'String}
|
|
:vendor {:type :vendor}
|
|
}}
|
|
|
|
:journal_entry_line
|
|
{:fields {:id {:type :id}
|
|
:account {:type :account}
|
|
:location {:type 'String}
|
|
:debit {:type 'String}
|
|
:credit {:type 'String}
|
|
:running_balance {:type :money}}}
|
|
:journal_entry
|
|
{:fields {:id {:type :id}
|
|
:source {:type 'String}
|
|
:external_id {:type 'String}
|
|
:amount {:type 'String}
|
|
:note {:type 'String}
|
|
:cleared_against {:type 'String}
|
|
:client {:type :client}
|
|
:vendor {:type :vendor}
|
|
:alternate_description {:type 'String}
|
|
:date {:type 'String}
|
|
:line_items {:type '(list :journal_entry_line)}}}
|
|
|
|
|
|
:order_line_item
|
|
{:fields {:id {:type :id}
|
|
:item_name {:type 'String}
|
|
:total {:type :money}
|
|
:tax {:type :money}
|
|
:category {:type 'String}
|
|
:discount {:type :money}}}
|
|
:charge
|
|
{:fields {:id {:type :id}
|
|
:type_name {:type 'String}
|
|
:total {:type :money}
|
|
:tip {:type :money}}}
|
|
|
|
:sales_order
|
|
{:fields {:id {:type :id}
|
|
:location {:type 'String}
|
|
:external_id {:type 'String}
|
|
:total {:type :money}
|
|
:tip {:type :money}
|
|
:tax {:type :money}
|
|
:discount {:type :money}
|
|
:service_charge {:type :money}
|
|
:returns {:type :money}
|
|
:client {:type :client}
|
|
:date {:type 'String}
|
|
:charges {:type '(list :charge)}
|
|
:line_items {:type '(list :order_line_item)}}}
|
|
|
|
:expected_deposit
|
|
{:fields {:id {:type :id}
|
|
:location {:type 'String}
|
|
:external_id {:type 'String}
|
|
:total {:type :money}
|
|
:fee {:type :money}
|
|
:client {:type :client}
|
|
:date {:type 'String}}}
|
|
|
|
:check {:fields {:id {:type :id}
|
|
:type {:type 'String}
|
|
:amount {:type 'String}
|
|
:vendor {:type :vendor}
|
|
:date {:type 'String}
|
|
:bank_account {:type :bank_account}
|
|
:memo {:type 'String}
|
|
:s3_url {:type 'String}
|
|
:check_number {:type 'Int}
|
|
:status {:type 'String}
|
|
:invoices {:type '(list :invoice_payment)}
|
|
}}
|
|
|
|
:payment {:fields {:id {:type :id}
|
|
:type {:type :payment_type}
|
|
:original_id {:type 'Int}
|
|
:amount {:type 'String}
|
|
:vendor {:type :vendor}
|
|
:client {:type :client}
|
|
:date {:type 'String}
|
|
:bank_account {:type :bank_account}
|
|
:memo {:type 'String}
|
|
:s3_url {:type 'String}
|
|
:check_number {:type 'Int}
|
|
:status {:type :ident}
|
|
:transaction {:type :transaction}
|
|
:invoices {:type '(list :invoice_payment)}
|
|
}}
|
|
|
|
:yodlee_merchant {:fields {:id {:type :id}
|
|
:yodlee_id {:type 'String}
|
|
:name {:type 'String}}}
|
|
|
|
:forecast_match {:fields {:id {:type :id}
|
|
:identifier {:type 'String}}}
|
|
:transaction {:fields {:id {:type :id}
|
|
:amount {:type 'String}
|
|
:description_original {:type 'String}
|
|
:description_simple {:type 'String}
|
|
:location {:type 'String}
|
|
:forecast_match {:type :forecast_match}
|
|
:status {:type 'String}
|
|
:yodlee_merchant {:type :yodlee_merchant}
|
|
:client {:type :client}
|
|
:accounts {:type '(list :invoices_expense_accounts)}
|
|
:payment {:type :payment}
|
|
:vendor {:type :vendor}
|
|
:bank_account {:type :bank_account}
|
|
:date {:type 'String}
|
|
:post_date {:type 'String}
|
|
:approval_status {:type :transaction_approval_status}
|
|
:matched_rule {:type :transaction_rule}}}
|
|
|
|
:transaction_rule {:fields {:id {:type :id}
|
|
:note {:type 'String}
|
|
:client {:type :client}
|
|
:bank_account {:type :bank_account}
|
|
:yodlee_merchant {:type :yodlee_merchant}
|
|
:description {:type 'String}
|
|
:amount_lte {:type 'String}
|
|
:amount_gte {:type 'String}
|
|
:dom_lte {:type 'Int}
|
|
:dom_gte {:type 'Int}
|
|
:vendor {:type :vendor}
|
|
:accounts {:type '(list :percentage_account)}
|
|
:transaction_approval_status {:type :transaction_approval_status}}}
|
|
|
|
:invoice_payment
|
|
{:fields {:id {:type :id}
|
|
:amount {:type 'String}
|
|
:invoice_id {:type 'String}
|
|
:payment_id {:type 'String}
|
|
:payment {:type :payment}
|
|
:invoice {:type :invoice}}}
|
|
|
|
:user
|
|
{:fields {:id {:type :id}
|
|
:name {:type 'String}
|
|
:role {:type 'String}
|
|
:clients {:type '(list :client)}}}
|
|
|
|
:account_client_override
|
|
{:fields {:id {:type :id}
|
|
:client {:type :client}
|
|
:name {:type 'String}}}
|
|
|
|
:account {:fields {:id {:type :id}
|
|
:numeric_code {:type 'Int}
|
|
:type {:type :ident}
|
|
:applicability {:type :applicability}
|
|
:account_set {:type 'String}
|
|
:location {:type 'String}
|
|
:name {:type 'String}
|
|
:client_overrides {:type '(list :account_client_override)}}}
|
|
|
|
:invoices_expense_accounts
|
|
{:fields {:id {:type :id}
|
|
:invoice_id {:type 'String}
|
|
:account {:type :account}
|
|
:location {:type 'String}
|
|
|
|
:amount {:type 'String}}}
|
|
|
|
:percentage_account
|
|
{:fields {:id {:type :id}
|
|
:account {:type :account}
|
|
:location {:type 'String}
|
|
:percentage {:type :percentage}}}
|
|
:invoice
|
|
{:fields {:id {:type :id}
|
|
:original_id {:type 'Int}
|
|
:client_identifier {:type 'String}
|
|
:total {:type 'String}
|
|
:outstanding_balance {:type 'String}
|
|
:invoice_number {:type 'String}
|
|
:status {:type 'String}
|
|
:expense_accounts {:type '(list :invoices_expense_accounts)}
|
|
:date {:type :iso_date}
|
|
:due {:type :iso_date}
|
|
:client_id {:type 'Int}
|
|
:payments {:type '(list :invoice_payment)}
|
|
:vendor {:type :vendor}
|
|
:client {:type :client}
|
|
:scheduled_payment {:type :iso_date}}}
|
|
|
|
|
|
|
|
|
|
:invoice_page {:fields {:invoices {:type '(list :invoice)}
|
|
:outstanding {:type :money}
|
|
:count {:type 'Int}
|
|
:total {:type 'Int}
|
|
:start {:type 'Int}
|
|
:end {:type 'Int}}}
|
|
|
|
:payment_page {:fields {:payments {:type '(list :payment)}
|
|
:count {:type 'Int}
|
|
:total {:type 'Int}
|
|
:start {:type 'Int}
|
|
:end {:type 'Int}}}
|
|
|
|
:transaction_page {:fields {:data {:type '(list :transaction)}
|
|
:count {:type 'Int}
|
|
:total {:type 'Int}
|
|
:start {:type 'Int}
|
|
:end {:type 'Int}}}
|
|
|
|
:transaction_rule_page {:fields {:transaction_rules {:type '(list :transaction_rule)}
|
|
:count {:type 'Int}
|
|
:total {:type 'Int}
|
|
:start {:type 'Int}
|
|
:end {:type 'Int}}}
|
|
|
|
:ledger_page {:fields {:journal_entries {:type '(list :journal_entry)}
|
|
:count {:type 'Int}
|
|
:total {:type 'Int}
|
|
:start {:type 'Int}
|
|
:end {:type 'Int}}}
|
|
|
|
:sales_order_page {:fields {:sales_orders {:type '(list :sales_order)}
|
|
:count {:type 'Int}
|
|
:total {:type 'Int}
|
|
:start {:type 'Int}
|
|
:end {:type 'Int}}}
|
|
|
|
:reminder_page {:fields {:reminders {:type '(list :reminder)}
|
|
:count {:type 'Int}
|
|
:total {:type 'Int}
|
|
:start {:type 'Int}
|
|
:end {:type 'Int}}}
|
|
:check_result {:fields {:invoices {:type '(list :invoice)}
|
|
:pdf_url {:type 'String}}}
|
|
|
|
:expense_account_stat {:fields {:account {:type :account}
|
|
:total {:type 'String}}}
|
|
|
|
:invoice_stat {:fields {:name {:type 'String}
|
|
:paid {:type 'String}
|
|
:unpaid {:type 'String}}}
|
|
|
|
:import_ledger_entry_result {:fields {:external_id {:type 'String}
|
|
:error {:type 'String}
|
|
:status {:type 'String}}}
|
|
|
|
:import_ledger_result {:fields {:successful {:type '(list :import_ledger_entry_result)}
|
|
:existing {:type '(list :import_ledger_entry_result)}
|
|
:ignored {:type '(list :import_ledger_entry_result)}
|
|
:errors {:type '(list :import_ledger_entry_result)}
|
|
}}
|
|
|
|
:upcoming_transaction {:fields {:amount {:type :money}
|
|
:identifier {:type 'String}
|
|
:date {:type :iso_date}}}
|
|
|
|
:cash_flow_result {:fields {:beginning_balance {:type :money}
|
|
:invoices_due_soon {:type '(list :invoice)}
|
|
:outstanding_payments {:type :money}
|
|
:upcoming_credits {:type '(list :upcoming_transaction)}
|
|
:upcoming_debits {:type '(list :upcoming_transaction)}}}
|
|
}
|
|
|
|
|
|
|
|
:queries
|
|
{:expense_account_stats {:type '(list :expense_account_stat)
|
|
:args {:client_id {:type :id}}
|
|
:resolve :get-expense-account-stats}
|
|
|
|
:test_transaction_rule {:type '(list :transaction)
|
|
:args {:transaction_rule {:type :edit_transaction_rule}}
|
|
:resolve :test-transaction-rule}
|
|
|
|
:run_transaction_rule {:type '(list :transaction)
|
|
:args {:transaction_rule_id {:type :id}}
|
|
:resolve :run-transaction-rule}
|
|
|
|
:invoice_stats {:type '(list :invoice_stat)
|
|
:args {:client_id {:type :id}}
|
|
:resolve :get-invoice-stats}
|
|
|
|
:cash_flow {:type :cash_flow_result
|
|
:args {:client_id {:type :id}}
|
|
:resolve :get-cash-flow}
|
|
:potential_payment_matches {:type '(list :payment)
|
|
:args {:transaction_id {:type :id}}
|
|
:resolve :get-potential-payments}
|
|
|
|
:potential_transaction_rule_matches {:type '(list :transaction_rule)
|
|
:args {:transaction_id {:type :id}}
|
|
:resolve :get-transaction-rule-matches}
|
|
:balance_sheet {:type :balance_sheet
|
|
:args {:client_id {:type :id}
|
|
:date {:type :iso_date}}
|
|
:resolve :get-balance-sheet}
|
|
|
|
:profit_and_loss {:type :profit_and_loss_report
|
|
:args {:client_id {:type :id}
|
|
:periods {:type '(list :date_range)}}
|
|
:resolve :get-profit-and-loss}
|
|
|
|
|
|
|
|
:invoice_page {:type '(list :invoice_page)
|
|
:args {:import_status {:type 'String}
|
|
:date_range {:type :date_range}
|
|
:due_range {:type :date_range}
|
|
:status {:type :invoice_status}
|
|
:unresolved {:type 'Boolean}
|
|
:client_id {:type :id}
|
|
:vendor_id {:type :id}
|
|
:amount_lte {:type :money}
|
|
:amount_gte {:type :money}
|
|
:invoice_number_like {:type 'String}
|
|
:location {:type 'String}
|
|
:start {:type 'Int}
|
|
:per_page {:type 'Int}
|
|
:sort {:type '(list :sort_item)}}
|
|
|
|
:resolve :get-invoice-page}
|
|
|
|
:all_invoices {:type '(list :invoice)
|
|
:args {:client_id {:type :id}
|
|
:client_code {:type 'String}
|
|
:original_id {:type 'Int}
|
|
:statuses {:type '(list String)}}
|
|
:resolve :get-all-invoices}
|
|
|
|
:accounts {:type '(list :account)
|
|
:args {:account_set {:type 'String}}
|
|
:resolve :get-accounts}
|
|
|
|
:all_payments {:type '(list :payment)
|
|
:args {:client_id {:type :id}
|
|
:client_code {:type 'String}
|
|
:original_id {:type 'Int}
|
|
:statuses {:type '(list String)}}
|
|
:resolve :get-all-payments}
|
|
|
|
:all_expected_deposits {:type '(list :expected_deposit)
|
|
:args {:client_id {:type :id}
|
|
:client_code {:type 'String}}
|
|
:resolve :get-all-expected-deposits}
|
|
|
|
:all_sales_orders {:type '(list :sales_order)
|
|
:args {:client_id {:type :id}
|
|
:date_range {:type :date_range}
|
|
:client_code {:type 'String}}
|
|
:resolve :get-all-sales-orders}
|
|
|
|
:yodlee_merchants {:type '(list :yodlee_merchant)
|
|
:args {}
|
|
:resolve :get-yodlee-merchants}
|
|
|
|
:transaction_page {:type :transaction_page
|
|
:args {:filters {:type :transaction_filters}}
|
|
|
|
:resolve :get-transaction-page}
|
|
|
|
:transaction_rule_page {:type :transaction_rule_page
|
|
:args {:client_id {:type :id}
|
|
:vendor_id {:type :id}
|
|
:start {:type 'Int}
|
|
:per_page {:type 'Int}
|
|
:sort {:type '(list :sort_item)}
|
|
:asc {:type 'Boolean}}
|
|
:resolve :get-transaction-rule-page}
|
|
|
|
:ledger_page {:type :ledger_page
|
|
:args {:filters {:type :ledger_filters}}
|
|
:resolve :get-ledger-page}
|
|
|
|
:sales_order_page {:type :sales_order_page
|
|
:args {:client_id {:type :id}
|
|
:date_range {:type :date_range}
|
|
:total_lte {:type :money}
|
|
:total_gte {:type :money}
|
|
:start {:type 'Int}
|
|
:per_page {:type 'Int}
|
|
:sort {:type '(list :sort_item)}}
|
|
|
|
:resolve :get-sales-order-page}
|
|
|
|
:payment_page {:type '(list :payment_page)
|
|
:args {:client_id {:type :id}
|
|
:vendor_id {:type :id}
|
|
:date_range {:type :date_range}
|
|
:amount_lte {:type :money}
|
|
:amount_gte {:type :money}
|
|
:check_number_like {:type 'String}
|
|
:invoice_number {:type 'String}
|
|
:start {:type 'Int}
|
|
:per_page {:type 'Int}
|
|
:sort {:type '(list :sort_item)}}
|
|
|
|
:resolve :get-payment-page}
|
|
|
|
:client {:type '(list :client)
|
|
:resolve :get-client}
|
|
:vendor {:type '(list :vendor)
|
|
:resolve :get-vendor}
|
|
:user {:type '(list :user)
|
|
:resolve :get-user}
|
|
|
|
}
|
|
|
|
:input-objects
|
|
{
|
|
:sort_item
|
|
{:fields {:sort_key {:type 'String}
|
|
:sort_name {:type 'String}
|
|
:asc {:type 'Boolean}}}
|
|
|
|
:transaction_filters {:fields {:client_id {:type :id}
|
|
:vendor_id {:type :id}
|
|
:bank_account_id {:type :id}
|
|
:account_id {:type :id}
|
|
:date_range {:type :date_range}
|
|
:location {:type 'String}
|
|
:amount_lte {:type :money}
|
|
:amount_gte {:type :money}
|
|
:description {:type 'String}
|
|
:start {:type 'Int}
|
|
:per_page {:type 'Int}
|
|
:sort {:type '(list :sort_item)}
|
|
:approval_status {:type :transaction_approval_status}
|
|
:unresolved {:type 'Boolean}}}
|
|
|
|
:ledger_filters {:fields {:client_id {:type :id}
|
|
:vendor_id {:type :id}
|
|
:account_id {:type :id}
|
|
:amount_lte {:type :money}
|
|
:amount_gte {:type :money}
|
|
:bank_account_id {:type :id}
|
|
:date_range {:type :date_range}
|
|
:location {:type 'String}
|
|
:from_numeric_code {:type 'Int}
|
|
:to_numeric_code {:type 'Int}
|
|
:start {:type 'Int}
|
|
:per_page {:type 'Int}
|
|
:only_external {:type 'Boolean}
|
|
:external_id_like {:type 'String}
|
|
:sort {:type '(list :sort_item)}}}
|
|
:invoice_payment_amount {:fields {:invoice_id {:type :id}
|
|
:amount {:type 'Float}}}
|
|
:edit_location_match {:fields {:location {:type 'String}
|
|
:match {:type 'String}
|
|
:id {:type :id}}}
|
|
|
|
:edit_forecasted_transaction {:fields {:identifier {:type 'String}
|
|
:id {:type :id}
|
|
:day_of_month {:type 'Int}
|
|
:amount {:type :money}}}
|
|
|
|
|
|
:date_range {:fields {:start {:type :iso_date}
|
|
:end {:type :iso_date}}}
|
|
|
|
:import_ledger_line_item {:fields {:account_identifier {:type 'String}
|
|
:location {:type 'String}
|
|
:debit {:type 'String}
|
|
:credit {:type 'String}}}
|
|
:import_ledger_entry {:fields {:source {:type 'String}
|
|
:external_id {:type 'String}
|
|
:client_code {:type 'String}
|
|
:date {:type 'String}
|
|
:vendor_name {:type 'String}
|
|
:amount {:type 'String}
|
|
:note {:type 'String}
|
|
:cleared_against {:type 'String}
|
|
:line_items {:type '(list :import_ledger_line_item)}}}
|
|
|
|
:edit_client {:fields {:id {:type :id}
|
|
:name {:type 'String}
|
|
:code {:type 'String}
|
|
:email {:type 'String}
|
|
:week_a_credits {:type :money}
|
|
:week_a_debits {:type :money}
|
|
:week_b_credits {:type :money}
|
|
:week_b_debits {:type :money}
|
|
:address {:type :add_address}
|
|
:locations {:type '(list String)}
|
|
:matches {:type '(list String)}
|
|
:location_matches {:type '(list :edit_location_match)}
|
|
:bank_accounts {:type '(list :edit_bank_account)}
|
|
:forecasted_transactions {:type '(list :edit_forecasted_transaction)}
|
|
}}
|
|
:edit_bank_account
|
|
{:fields {:id {:type :id }
|
|
:code {:type 'String}
|
|
:type {:type :bank_account_type}
|
|
:start_date {:type :iso_date}
|
|
:number {:type 'String}
|
|
:check_number {:type 'Int}
|
|
:visible {:type 'Boolean}
|
|
:include_in_reports {:type 'Boolean}
|
|
:sort_order {:type 'Int}
|
|
:name {:type 'String}
|
|
:bank_code {:type 'String}
|
|
:routing {:type 'String}
|
|
:bank_name {:type 'String}
|
|
:locations {:type '(list String)}
|
|
:yodlee_account_id {:type 'Int}}}
|
|
:edit_user
|
|
{:fields {:id {:type :id}
|
|
:name {:type 'String}
|
|
:role {:type 'String}
|
|
:clients {:type '(list String)}}}
|
|
|
|
:add_contact
|
|
{:fields {:id {:type :id}
|
|
:name {:type 'String}
|
|
:email {:type 'String}
|
|
:phone {:type 'String}}}
|
|
:add_address
|
|
{:fields {:street1 {:type 'String}
|
|
:street2 {:type 'String}
|
|
:city {:type 'String}
|
|
:state {:type 'String}
|
|
:zip {:type 'String}}}
|
|
|
|
:add_terms_override
|
|
{:fields {:id {:type :id}
|
|
:client_id {:type :id}
|
|
:terms {:type 'Int}
|
|
}}
|
|
|
|
:add_account_override
|
|
{:fields {:id {:type :id}
|
|
:client_id {:type :id}
|
|
:account_id {:type :id}}}
|
|
|
|
:add_schedule_payment_dom
|
|
{:fields {:id {:type :id}
|
|
:client_id {:type :id}
|
|
:dom {:type 'Int}}}
|
|
|
|
:add_vendor
|
|
{:fields {:id {:type :id}
|
|
:name {:type 'String}
|
|
:terms {:type 'Int}
|
|
:terms_overrides {:type '(list :add_terms_override)}
|
|
:code {:type 'String}
|
|
:automatically_paid_when_due {:type '(list :id)}
|
|
|
|
:hidden {:type 'Boolean}
|
|
:print_as {:type 'String}
|
|
:primary_contact {:type :add_contact}
|
|
:secondary_contact {:type :add_contact}
|
|
:address {:type :add_address}
|
|
|
|
:default_account_id {:type :id}
|
|
:account_overrides {:type '(list :add_account_override)}
|
|
:schedule_payment_dom {:type '(list :add_schedule_payment_dom)}
|
|
:invoice_reminder_schedule {:type 'String}}}
|
|
|
|
:edit_expense_account
|
|
{:fields {:id {:type :id}
|
|
:account_id {:type :id}
|
|
:location {:type 'String}
|
|
:amount {:type 'String}}}
|
|
|
|
:add_invoice
|
|
{:fields {:id {:type :id}
|
|
:invoice_number {:type 'String}
|
|
:expense_accounts {:type '(list :edit_expense_account)}
|
|
:location {:type :iso_date}
|
|
:scheduled_payment {:type :iso_date}
|
|
:date {:type :iso_date}
|
|
:due {:type :iso_date}
|
|
:client_id {:type :id}
|
|
:vendor_id {:type :id}
|
|
:vendor_name {:type 'String}
|
|
:total {:type 'Float}}}
|
|
|
|
:edit_invoice
|
|
{:fields {:id {:type :id}
|
|
:invoice_number {:type 'String}
|
|
:expense_accounts {:type '(list :edit_expense_account)}
|
|
:date {:type :iso_date}
|
|
:scheduled_payment {:type :iso_date}
|
|
:due {:type :iso_date}
|
|
:total {:type 'Float}}}
|
|
:edit_transaction
|
|
{:fields {:id {:type :id}
|
|
:vendor_id {:type :id}
|
|
:forecast_match {:type :id}
|
|
:approval_status {:type :transaction_approval_status}
|
|
:accounts {:type '(list :edit_expense_account)}}}
|
|
|
|
:edit_percentage_account
|
|
{:fields {:id {:type :id}
|
|
:account_id {:type :id}
|
|
:location {:type 'String}
|
|
:percentage {:type :percentage}}}
|
|
|
|
:edit_transaction_rule
|
|
{:fields {:id {:type :id}
|
|
:description {:type 'String}
|
|
:note {:type 'String}
|
|
:bank_account_id {:type :id}
|
|
:client_id {:type :id}
|
|
:yodlee_merchant_id {:type :id}
|
|
:amount_lte {:type :money}
|
|
:amount_gte {:type :money}
|
|
:dom_lte {:type 'Int}
|
|
:dom_gte {:type 'Int}
|
|
:vendor_id {:type :id}
|
|
:accounts {:type '(list :edit_percentage_account)}
|
|
:transaction_approval_status {:type :transaction_approval_status}}}
|
|
|
|
:edit_account_client_override
|
|
{:fields {:id {:type :id}
|
|
:client_id {:type :id}
|
|
:name {:type 'String}}}
|
|
|
|
:edit_account
|
|
{:fields {:id {:type :id}
|
|
:type {:type :account_type}
|
|
:applicability {:type :applicability}
|
|
:numeric_code {:type 'Int}
|
|
:location {:type 'String}
|
|
:account_set {:type 'String}
|
|
:name {:type 'String}
|
|
:client_overrides {:type '(list :edit_account_client_override)}}}}
|
|
|
|
:enums {:payment_type {:values [{:enum-value :check}
|
|
{:enum-value :cash}
|
|
{:enum-value :debit}]}
|
|
:invoice_status {:values [{:enum-value :paid}
|
|
{:enum-value :unpaid}
|
|
{:enum-value :voided}]}
|
|
:bank_account_type {:values [{:enum-value :check}
|
|
{:enum-value :credit}
|
|
{:enum-value :cash}]}
|
|
:applicability {:values [{:enum-value :global}
|
|
{:enum-value :optional}
|
|
{:enum-value :customized}]}
|
|
:account_type {:values [{:enum-value :dividend}
|
|
{:enum-value :expense}
|
|
{:enum-value :asset}
|
|
{:enum-value :liability}
|
|
{:enum-value :equity}
|
|
{:enum-value :revenue}]}
|
|
:transaction_approval_status {:values [{:enum-value :approved}
|
|
{:enum-value :unapproved}
|
|
{:enum-value :requires_feedback}
|
|
{:enum-value :excluded}]}}
|
|
:mutations
|
|
{:reject_invoices {:type '(list :id)
|
|
:args {:invoices {:type '(list :id)}}
|
|
:resolve :mutation/reject-invoices}
|
|
|
|
:approve_invoices {:type '(list :id)
|
|
:args {:invoices {:type '(list :id)}}
|
|
:resolve :mutation/approve-invoices}
|
|
|
|
:bulk_change_transaction_status {:type :message
|
|
:args {:filters {:type :transaction_filters}
|
|
:status {:type :transaction_approval_status}
|
|
:ids {:type '(list :id)}}
|
|
:resolve :mutation/bulk-change-transaction-status}
|
|
|
|
:delete_external_ledger {:type :message
|
|
:args {:filters {:type :ledger_filters}
|
|
:ids {:type '(list :id)}}
|
|
:resolve :mutation/delete-external-ledger}
|
|
:delete_transactions {:type :message
|
|
:args {:filters {:type :transaction_filters}
|
|
:ids {:type '(list :id)}}
|
|
:resolve :mutation/delete-transactions}
|
|
:delete_transaction_rule {:type :id
|
|
:args {:transaction_rule_id {:type :id}}
|
|
:resolve :mutation/delete-transaction-rule}
|
|
:merge_vendors {:type :id
|
|
:args {:from {:type :id}
|
|
:to {:type :id}}
|
|
:resolve :mutation/merge-vendors}
|
|
|
|
:add_and_print_invoice {:type :check_result
|
|
:args {:invoice {:type :add_invoice}
|
|
:bank_account_id {:type :id}
|
|
:type {:type :payment_type}}
|
|
:resolve :mutation/add-and-print-invoice}
|
|
|
|
:print_checks {:type :check_result
|
|
:args {:invoice_payments {:type '(list :invoice_payment_amount)}
|
|
:bank_account_id {:type :id}
|
|
:type {:type :payment_type}
|
|
:client_id {:type :id}}
|
|
:resolve :mutation/print-checks}
|
|
|
|
:add_handwritten_check {:type :check_result
|
|
:args {:invoice_payments {:type '(list :invoice_payment_amount)}
|
|
:date {:type 'String}
|
|
:check_number {:type 'Int}
|
|
:bank_account_id {:type :id}}
|
|
:resolve :mutation/add-handwritten-check}
|
|
:edit_user {:type :user
|
|
:args {:edit_user {:type :edit_user}}
|
|
:resolve :mutation/edit-user}
|
|
|
|
:edit_client {:type :client
|
|
:args {:edit_client {:type :edit_client}}
|
|
:resolve :mutation/edit-client}
|
|
|
|
:upsert_vendor {:type :vendor
|
|
:args {:vendor {:type :add_vendor}}
|
|
:resolve :mutation/upsert-vendor}
|
|
|
|
:upsert_transaction_rule {:type :transaction_rule
|
|
:args {:transaction_rule {:type :edit_transaction_rule}}
|
|
:resolve :mutation/upsert-transaction-rule}
|
|
:add_invoice {:type :invoice
|
|
:args {:invoice {:type :add_invoice}}
|
|
:resolve :mutation/add-invoice}
|
|
|
|
:import_ledger {:type :import_ledger_result
|
|
:args {:entries {:type '(list :import_ledger_entry)}}
|
|
:resolve :mutation/import-ledger}
|
|
:edit_invoice {:type :invoice
|
|
:args {:invoice {:type :edit_invoice}}
|
|
:resolve :mutation/edit-invoice}
|
|
:upsert_account {:type :account
|
|
:args {:account {:type :edit_account}}
|
|
:resolve :mutation/upsert-account}
|
|
:edit_transaction {:type :transaction
|
|
:args {:transaction {:type :edit_transaction}}
|
|
:resolve :mutation/edit-transaction}
|
|
|
|
:match_transaction {:type :transaction
|
|
:args {:transaction_id {:type :id}
|
|
:payment_id {:type :id}}
|
|
:resolve :mutation/match-transaction}
|
|
|
|
:match_transaction_rules {:type '(list :transaction)
|
|
:args {:transaction_ids {:type '(list :id)}
|
|
:all {:type 'Boolean}
|
|
:transaction_rule_id {:type :id}}
|
|
:resolve :mutation/match-transaction-rules}
|
|
|
|
:unlink_transaction {:type :transaction
|
|
:args {:transaction_id {:type :id}}
|
|
:resolve :mutation/unlink-transaction}
|
|
:void_invoice {:type :invoice
|
|
:args {:invoice_id {:type :id}}
|
|
:resolve :mutation/void-invoice}
|
|
:unvoid_invoice {:type :invoice
|
|
:args {:invoice_id {:type :id}}
|
|
:resolve :mutation/unvoid-invoice}
|
|
|
|
:void_payment {:type :payment
|
|
:args {:payment_id {:type :id}}
|
|
:resolve :mutation/void-payment}
|
|
:edit_expense_accounts {:type :invoice
|
|
:args {:invoice_id {:type :id}
|
|
:expense_accounts {:type '(list :edit_expense_account)}}
|
|
:resolve :mutation/edit-expense-accounts}}})
|
|
|
|
|
|
(defn snake->kebab [s]
|
|
(str/replace s #"_" "-"))
|
|
|
|
(defn kebab [x]
|
|
(keyword (snake->kebab (name x))))
|
|
|
|
(defn kebab->snake [s]
|
|
(str/replace s #"-" "_"))
|
|
|
|
(defn snake [x]
|
|
(keyword (kebab->snake (name x))))
|
|
|
|
(defn ->graphql [m]
|
|
(walk/postwalk
|
|
(fn [node]
|
|
(cond
|
|
|
|
(keyword? node)
|
|
(snake node)
|
|
|
|
:else
|
|
node))
|
|
m))
|
|
|
|
(defn <-graphql [m]
|
|
(walk/postwalk
|
|
(fn [node]
|
|
(cond
|
|
|
|
(keyword? node)
|
|
(kebab node)
|
|
|
|
:else
|
|
node))
|
|
m))
|
|
|
|
|
|
(defn get-all-payments [context args value]
|
|
(assert-admin (:id context))
|
|
(map
|
|
->graphql
|
|
(first (d-checks/get-graphql (assoc (<-graphql args) :count Integer/MAX_VALUE)))))
|
|
|
|
(defn get-all-sales-orders [context args value]
|
|
(assert-admin (:id context))
|
|
(map
|
|
->graphql
|
|
(first (d-sales-orders/get-graphql (assoc (<-graphql args) :count Integer/MAX_VALUE)))))
|
|
|
|
(defn get-user [context args value]
|
|
(assert-admin (:id context))
|
|
|
|
(let [users (d-users/get-graphql args)]
|
|
(->graphql users)))
|
|
|
|
|
|
|
|
(defn print-checks [context args value]
|
|
|
|
(assert-can-see-client (:id context) (:client_id args))
|
|
(->graphql
|
|
(gq-checks/print-checks (map (fn [i] {:invoice-id (:invoice_id i)
|
|
:amount (:amount i)})
|
|
(:invoice_payments args))
|
|
(:client_id args)
|
|
(:bank_account_id args)
|
|
(:type args)
|
|
(:id context))))
|
|
|
|
(defn get-expense-account-stats [context {:keys [client_id] } value]
|
|
(let [result (cond-> {:query {:find ['?account '?account-name '(sum ?amount)]
|
|
:in ['$]
|
|
:where []}
|
|
:args [(d/db (d/connect uri)) client_id]}
|
|
client_id (merge-query {:query {:in ['?c]}
|
|
|
|
:args [client_id]})
|
|
(not client_id) (merge-query {:query {:where ['[?c :client/name]]}})
|
|
|
|
true (merge-query {:query {:where ['[?i :invoice/client ?c]
|
|
'[?i :invoice/expense-accounts ?expense-account]
|
|
'[?expense-account :invoice-expense-account/account ?account]
|
|
'[?account :account/name ?account-name]
|
|
'[?expense-account :invoice-expense-account/amount ?amount]]}})
|
|
|
|
true (d/query ))]
|
|
(for [[account-id account-name total] result]
|
|
{:account {:id account-id :name account-name} :total total })))
|
|
|
|
(defn categorize [x]
|
|
(cond (<= x 0) :due
|
|
(<= x 30 ) :due-30
|
|
(<= x 60 ) :due-60
|
|
:else :due-later))
|
|
|
|
(defn get-invoice-stats [context {:keys [client_id] } value]
|
|
(let [result (cond-> {:query {:find ['?name '(sum ?outstanding-balance) '(sum ?total)]
|
|
:in ['$]
|
|
:where []}
|
|
:args [(d/db (d/connect uri)) client_id]}
|
|
client_id (merge-query {:query {:in ['?c]}
|
|
:args [client_id]})
|
|
(not client_id) (merge-query {:query {:where ['[?c :client/name]]}})
|
|
|
|
true (merge-query {:query {:where ['[?i :invoice/client ?c]
|
|
'[?i :invoice/outstanding-balance ?outstanding-balance]
|
|
'[?i :invoice/total ?total]
|
|
'[?i :invoice/due ?date]
|
|
'[(.toInstant ^java.util.Date ?date) ?d2]
|
|
'[(.between java.time.temporal.ChronoUnit/DAYS (java.time.Instant/now) ?d2 ) ?d3]
|
|
'[(auto-ap.graphql/categorize ?d3) ?name]]}})
|
|
|
|
true (d/query ))
|
|
result (group-by first result)]
|
|
|
|
(for [[id name] [[:due "Due"] [:due-30 "0-30 days"] [:due-60 "31-60 days"] [:due-later ">60 days"] ]
|
|
:let [[[_ outstanding-balance total] ] (id result nil)
|
|
outstanding-balance (or outstanding-balance 0)
|
|
total (or total 0)]]
|
|
{:name name :unpaid outstanding-balance :paid (if (= :due id)
|
|
0
|
|
(- total outstanding-balance))})))
|
|
|
|
(defn has-fulfilled? [id date recent-fulfillments]
|
|
|
|
(seq (transduce
|
|
(filter (fn [[potential-id potential-date]]
|
|
(let [date (coerce/to-date-time date)
|
|
potential-date (coerce/to-date-time potential-date)]
|
|
(and (= id potential-id)
|
|
(<= (t/in-days (apply t/interval (sort [date potential-date]))) 10)))))
|
|
conj
|
|
[]
|
|
recent-fulfillments)))
|
|
|
|
(def first-week-a (coerce/to-date-time #inst "1999-12-27T00:00:00.000-07:00"))
|
|
|
|
(defn get-cash-flow [context {:keys [client_id]} value]
|
|
(when client_id
|
|
(let [{:client/keys [week-a-credits week-a-debits week-b-credits week-b-debits forecasted-transactions ]} (d/pull (d/db (d/connect uri)) '[*] client_id )
|
|
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 ?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)) client_id]}))
|
|
bills-due-soon (d/query {:query {:find '[?due ?outstanding ?invoice-number ?vendor-id]
|
|
:in '[$ ?client ?due-before]
|
|
:where ['[?i :invoice/client ?client]
|
|
'[?i :invoice/status :invoice-status/unpaid]
|
|
'[?i :invoice/due ?due]
|
|
'[(<= ?due ?due-before)]
|
|
'[?i :invoice/outstanding-balance ?outstanding]
|
|
'[?i :invoice/invoice-number ?invoice-number]
|
|
'[?i :invoice/vendor ?vendor-id]]}
|
|
:args [(d/db (d/connect uri)) client_id (coerce/to-date (t/plus (time/local-now) (t/days 180)))]})
|
|
outstanding-checks (reduce
|
|
+
|
|
0.0
|
|
(map first (d/query {:query {:find '[?amount]
|
|
:in '[$ ?client ?due-before]
|
|
:where ['[?p :payment/client ?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)) client_id (coerce/to-date (t/plus (time/local-now) (t/days 180)))]})))
|
|
recent-fulfillments (d/query {:query {:find '[?f ?d]
|
|
:in '[$ ?client ?min-date]
|
|
:where ['[?t :transaction/forecast-match ?f]
|
|
'[?t :transaction/date ?d]
|
|
'[?t :transaction/client ?client]
|
|
'[(>= ?d ?min-date)]]}
|
|
:args [(d/db (d/connect uri)) client_id (coerce/to-date (t/plus (time/local-now) (t/months -2)))]})
|
|
forecasted-transactions (for [{:forecasted-transaction/keys [amount identifier day-of-month]
|
|
:db/keys [id]} forecasted-transactions
|
|
month (range -1 7)
|
|
:let [next (t/plus (t/local-date (t/year (time/local-now))
|
|
(t/month (time/local-now))
|
|
day-of-month )
|
|
(t/months month))]
|
|
:when (not (has-fulfilled? id next recent-fulfillments))]
|
|
{:identifier identifier
|
|
:amount amount
|
|
:date (coerce/to-date-time next)})
|
|
is-week-a? (fn [d]
|
|
(= 0 (mod (t/in-weeks (t/interval first-week-a d)) 2)))]
|
|
|
|
{:beginning_balance total-cash
|
|
:outstanding_payments outstanding-checks
|
|
:invoices_due_soon (mapv (fn [[due outstanding invoice-number vendor-id]]
|
|
{:due (coerce/to-date-time due)
|
|
:invoice_number invoice-number
|
|
:vendor {:id vendor-id}
|
|
:outstanding_balance outstanding})
|
|
bills-due-soon)
|
|
:upcoming_credits (into (mapv
|
|
(fn [date]
|
|
{:amount (if (is-week-a? (coerce/to-date-time date))
|
|
(or week-a-credits 0)
|
|
(or week-b-credits 0))
|
|
:date (coerce/to-date-time date)})
|
|
(take (* 7 4) (time/day-of-week-seq 1)))
|
|
(filter #(>= (:amount %) 0) forecasted-transactions))
|
|
:upcoming_debits (into (mapv
|
|
(fn [date]
|
|
{:amount (- (if (is-week-a? (coerce/to-date-time date))
|
|
(or week-a-debits 0)
|
|
(or week-b-debits 0)))
|
|
:date (coerce/to-date-time date)})
|
|
(take (* 7 4) (time/day-of-week-seq 1)))
|
|
(filter #(< (:amount %) 0) forecasted-transactions))
|
|
})))
|
|
|
|
(def schema
|
|
(-> integreat-schema
|
|
(attach-resolvers {:get-invoice-page gq-invoices/get-invoice-page
|
|
:get-all-invoices gq-invoices/get-all-invoices
|
|
:get-all-payments get-all-payments
|
|
:get-all-expected-deposits gq-expected-deposit/get-all-expected-deposits
|
|
:get-all-sales-orders get-all-sales-orders
|
|
:get-payment-page gq-checks/get-payment-page
|
|
:get-potential-payments gq-checks/get-potential-payments
|
|
:get-accounts gq-accounts/get-accounts
|
|
:get-transaction-page gq-transactions/get-transaction-page
|
|
:get-ledger-page gq-ledger/get-ledger-page
|
|
:get-sales-order-page gq-sales-orders/get-sales-orders-page
|
|
:get-balance-sheet gq-ledger/get-balance-sheet
|
|
:get-profit-and-loss gq-ledger/get-profit-and-loss
|
|
:get-transaction-rule-page gq-transaction-rules/get-transaction-rule-page
|
|
:get-transaction-rule-matches gq-transaction-rules/get-transaction-rule-matches
|
|
:get-expense-account-stats get-expense-account-stats
|
|
:get-invoice-stats get-invoice-stats
|
|
:get-cash-flow get-cash-flow
|
|
:get-yodlee-merchants ym/get-yodlee-merchants
|
|
:get-client gq-clients/get-client
|
|
:get-user get-user
|
|
:mutation/add-handwritten-check gq-checks/add-handwritten-check
|
|
:mutation/delete-transaction-rule gq-transaction-rules/delete-transaction-rule
|
|
:mutation/print-checks print-checks
|
|
:mutation/reject-invoices gq-invoices/reject-invoices
|
|
:mutation/approve-invoices gq-invoices/approve-invoices
|
|
:mutation/edit-user gq-users/edit-user
|
|
:mutation/add-invoice gq-invoices/add-invoice
|
|
:mutation/add-and-print-invoice gq-invoices/add-and-print-invoice
|
|
:mutation/edit-invoice gq-invoices/edit-invoice
|
|
:mutation/edit-transaction gq-transactions/edit-transaction
|
|
:mutation/unlink-transaction gq-transactions/unlink-transaction
|
|
:mutation/bulk-change-transaction-status gq-transactions/bulk-change-status
|
|
:mutation/delete-external-ledger gq-ledger/delete-external-ledger
|
|
:mutation/delete-transactions gq-transactions/delete-transactions
|
|
:mutation/upsert-transaction-rule gq-transaction-rules/upsert-transaction-rule
|
|
:test-transaction-rule gq-transaction-rules/test-transaction-rule
|
|
:run-transaction-rule gq-transaction-rules/run-transaction-rule
|
|
:mutation/match-transaction gq-transactions/match-transaction
|
|
:mutation/match-transaction-rules gq-transactions/match-transaction-rules
|
|
:mutation/edit-client gq-clients/edit-client
|
|
:mutation/upsert-vendor gq-vendors/upsert-vendor
|
|
:mutation/upsert-account gq-accounts/upsert-account
|
|
:mutation/merge-vendors gq-vendors/merge-vendors
|
|
:mutation/void-invoice gq-invoices/void-invoice
|
|
:mutation/unvoid-invoice gq-invoices/unvoid-invoice
|
|
:mutation/void-payment gq-checks/void-check
|
|
:mutation/edit-expense-accounts gq-invoices/edit-expense-accounts
|
|
:mutation/import-ledger gq-ledger/import-ledger
|
|
:get-vendor gq-vendors/get-graphql})
|
|
schema/compile))
|
|
|
|
|
|
|
|
(defn simplify
|
|
"Converts all ordered maps nested within the map into standard hash maps, and
|
|
sequences into vectors, which makes for easier constants in the tests, and eliminates ordering problems."
|
|
[m]
|
|
(walk/postwalk
|
|
(fn [node]
|
|
(cond
|
|
(instance? IPersistentMap node)
|
|
(into {} node)
|
|
|
|
(seq? node)
|
|
(vec node)
|
|
|
|
(keyword? node)
|
|
(kebab node)
|
|
|
|
:else
|
|
node))
|
|
m))
|
|
|
|
(defn query
|
|
([id q]
|
|
(query id q nil ))
|
|
([id q v]
|
|
|
|
(lc/with-context {:query q}
|
|
(log/info "Executing query" q)
|
|
|
|
(try
|
|
(let [[result time] (time-it (simplify (execute schema q v {:id id})))]
|
|
|
|
(info-event "Query completed"
|
|
{:time (:time time)
|
|
:errors (seq (:errors result))})
|
|
(when (seq (:errors result))
|
|
(throw (ex-info "GraphQL error" {:result result})))
|
|
result)
|
|
|
|
(catch Exception e
|
|
(if-let [v (:validation-error (ex-data e))]
|
|
(warn-event "validation error" {:validation-error v
|
|
:data (ex-data e)})
|
|
(error-event "query error" {:error e}))
|
|
|
|
(throw e))))))
|