added the ability to credit invoices. Also made it so check numbers pop up for intuit even if they're not in the description.
This commit is contained in:
@@ -487,7 +487,9 @@
|
|||||||
:auto-ap/add-source-url-admin-only {:txes [[{:db/ident :invoice/source-url-admin-only
|
:auto-ap/add-source-url-admin-only {:txes [[{:db/ident :invoice/source-url-admin-only
|
||||||
:db/doc "Can only admins see this invoice?"
|
:db/doc "Can only admins see this invoice?"
|
||||||
:db/valueType :db.type/boolean
|
:db/valueType :db.type/boolean
|
||||||
:db/cardinality :db.cardinality/one}]]}}
|
:db/cardinality :db.cardinality/one}]]}
|
||||||
|
:auto-ap/add-payment-type-credit {:txes [[{:db/ident :payment-type/credit
|
||||||
|
:db/doc "Credit for negative invoices"}]]}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -300,32 +300,8 @@
|
|||||||
:charges {:type '(list :charge)}
|
:charges {:type '(list :charge)}
|
||||||
:line_items {:type '(list :order_line_item)}}}
|
:line_items {:type '(list :order_line_item)}}}
|
||||||
|
|
||||||
: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_merchant {:fields {:id {:type :id}
|
||||||
:yodlee_id {:type 'String}
|
:yodlee_id {:type 'String}
|
||||||
@@ -352,13 +328,7 @@
|
|||||||
:accounts {:type '(list :percentage_account)}
|
:accounts {:type '(list :percentage_account)}
|
||||||
:transaction_approval_status {:type :transaction_approval_status}}}
|
: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
|
:user
|
||||||
{:fields {:id {:type :id}
|
{:fields {:id {:type :id}
|
||||||
@@ -392,11 +362,7 @@
|
|||||||
:start {:type 'Int}
|
:start {:type 'Int}
|
||||||
:end {: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_rule_page {:fields {:transaction_rules {:type '(list :transaction_rule)}
|
:transaction_rule_page {:fields {:transaction_rules {:type '(list :transaction_rule)}
|
||||||
:count {:type 'Int}
|
:count {:type 'Int}
|
||||||
@@ -459,9 +425,7 @@
|
|||||||
:potential_transaction_rule_matches {:type '(list :transaction_rule)
|
:potential_transaction_rule_matches {:type '(list :transaction_rule)
|
||||||
:args {:transaction_id {:type :id}}
|
:args {:transaction_id {:type :id}}
|
||||||
:resolve :get-transaction-rule-matches}
|
:resolve :get-transaction-rule-matches}
|
||||||
:potential_payment_matches {:type '(list :payment)
|
|
||||||
:args {:transaction_id {:type :id}}
|
|
||||||
:resolve :get-potential-payments}
|
|
||||||
|
|
||||||
:test_transaction_rule {:type '(list :transaction)
|
:test_transaction_rule {:type '(list :transaction)
|
||||||
:args {:transaction_rule {:type :edit_transaction_rule}}
|
:args {:transaction_rule {:type :edit_transaction_rule}}
|
||||||
@@ -499,12 +463,7 @@
|
|||||||
:args {:account_set {:type 'String}}
|
:args {:account_set {:type 'String}}
|
||||||
:resolve :get-accounts}
|
: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_sales_orders {:type '(list :sales_order)
|
:all_sales_orders {:type '(list :sales_order)
|
||||||
:args {:client_id {:type :id}
|
:args {:client_id {:type :id}
|
||||||
@@ -546,20 +505,7 @@
|
|||||||
:sort {:type '(list :sort_item)}}
|
:sort {:type '(list :sort_item)}}
|
||||||
:resolve :get-sales-order-page}
|
:resolve :get-sales-order-page}
|
||||||
|
|
||||||
:payment_page {:type '(list :payment_page)
|
|
||||||
:args {:client_id {:type :id}
|
|
||||||
:vendor_id {:type :id}
|
|
||||||
:payment_type {:type :payment_type}
|
|
||||||
:exact_match_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)
|
:client {:type '(list :client)
|
||||||
:resolve :get-client}
|
:resolve :get-client}
|
||||||
@@ -590,8 +536,7 @@
|
|||||||
:only_external {:type 'Boolean}
|
:only_external {:type 'Boolean}
|
||||||
:external_id_like {:type 'String}
|
:external_id_like {:type 'String}
|
||||||
:sort {:type '(list :sort_item)}}}
|
:sort {:type '(list :sort_item)}}}
|
||||||
:invoice_payment_amount {:fields {:invoice_id {:type :id}
|
|
||||||
:amount {:type :money}}}
|
|
||||||
:edit_location_match {:fields {:location {:type 'String}
|
:edit_location_match {:fields {:location {:type 'String}
|
||||||
:match {:type 'String}
|
:match {:type 'String}
|
||||||
:id {:type :id}}}
|
:id {:type :id}}}
|
||||||
@@ -747,10 +692,7 @@
|
|||||||
:name {:type 'String}
|
:name {:type 'String}
|
||||||
:client_overrides {:type '(list :edit_account_client_override)}}}}
|
:client_overrides {:type '(list :edit_account_client_override)}}}}
|
||||||
|
|
||||||
:enums {:payment_type {:values [{:enum-value :check}
|
:enums {
|
||||||
{:enum-value :cash}
|
|
||||||
{:enum-value :debit}]}
|
|
||||||
|
|
||||||
:processor {:values [{:enum-value :na}
|
:processor {:values [{:enum-value :na}
|
||||||
{:enum-value :doordash}
|
{:enum-value :doordash}
|
||||||
{:enum-value :uber_eats}
|
{:enum-value :uber_eats}
|
||||||
@@ -790,19 +732,6 @@
|
|||||||
:to {:type :id}}
|
:to {:type :id}}
|
||||||
:resolve :mutation/merge-vendors}
|
:resolve :mutation/merge-vendors}
|
||||||
|
|
||||||
: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
|
:edit_user {:type :user
|
||||||
:args {:edit_user {:type :edit_user}}
|
:args {:edit_user {:type :edit_user}}
|
||||||
:resolve :mutation/edit-user}
|
:resolve :mutation/edit-user}
|
||||||
@@ -827,9 +756,7 @@
|
|||||||
:args {:account {:type :edit_account}}
|
:args {:account {:type :edit_account}}
|
||||||
:resolve :mutation/upsert-account}
|
:resolve :mutation/upsert-account}
|
||||||
|
|
||||||
:void_payment {:type :payment
|
}})
|
||||||
:args {:payment_id {:type :id}}
|
|
||||||
:resolve :mutation/void-payment}}})
|
|
||||||
|
|
||||||
|
|
||||||
(defn snake->kebab [s]
|
(defn snake->kebab [s]
|
||||||
@@ -869,11 +796,7 @@
|
|||||||
m))
|
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]
|
(defn get-all-sales-orders [context args value]
|
||||||
(assert-admin (:id context))
|
(assert-admin (:id context))
|
||||||
@@ -889,17 +812,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
(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]
|
(defn get-expense-account-stats [context {:keys [client_id] } value]
|
||||||
(let [result (cond-> {:query {:find ['?account '?account-name '(sum ?amount)]
|
(let [result (cond-> {:query {:find ['?account '?account-name '(sum ?amount)]
|
||||||
@@ -1058,12 +971,9 @@
|
|||||||
|
|
||||||
(def schema
|
(def schema
|
||||||
(-> integreat-schema
|
(-> integreat-schema
|
||||||
(attach-resolvers {:mutation/void-payment gq-checks/void-check
|
(attach-resolvers {
|
||||||
:get-yodlee-provider-account-page gq-yodlee2/get-yodlee-provider-account-page
|
:get-yodlee-provider-account-page gq-yodlee2/get-yodlee-provider-account-page
|
||||||
:get-all-payments get-all-payments
|
|
||||||
:get-all-sales-orders get-all-sales-orders
|
: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-accounts gq-accounts/get-accounts
|
||||||
:get-ledger-page gq-ledger/get-ledger-page
|
:get-ledger-page gq-ledger/get-ledger-page
|
||||||
:get-sales-order-page gq-sales-orders/get-sales-orders-page
|
:get-sales-order-page gq-sales-orders/get-sales-orders-page
|
||||||
@@ -1078,9 +988,7 @@
|
|||||||
:get-intuit-bank-accounts gq-intuit-bank-accounts/get-intuit-bank-accounts
|
:get-intuit-bank-accounts gq-intuit-bank-accounts/get-intuit-bank-accounts
|
||||||
:get-client gq-clients/get-client
|
:get-client gq-clients/get-client
|
||||||
:get-user get-user
|
:get-user get-user
|
||||||
:mutation/add-handwritten-check gq-checks/add-handwritten-check
|
|
||||||
:mutation/delete-transaction-rule gq-transaction-rules/delete-transaction-rule
|
:mutation/delete-transaction-rule gq-transaction-rules/delete-transaction-rule
|
||||||
:mutation/print-checks print-checks
|
|
||||||
:mutation/edit-user gq-users/edit-user
|
:mutation/edit-user gq-users/edit-user
|
||||||
:mutation/delete-external-ledger gq-ledger/delete-external-ledger
|
:mutation/delete-external-ledger gq-ledger/delete-external-ledger
|
||||||
:mutation/upsert-transaction-rule gq-transaction-rules/upsert-transaction-rule
|
:mutation/upsert-transaction-rule gq-transaction-rules/upsert-transaction-rule
|
||||||
@@ -1093,6 +1001,7 @@
|
|||||||
:mutation/import-ledger gq-ledger/import-ledger
|
:mutation/import-ledger gq-ledger/import-ledger
|
||||||
:mutation/request-import gq-requests/request-import
|
:mutation/request-import gq-requests/request-import
|
||||||
:get-vendor gq-vendors/get-graphql})
|
:get-vendor gq-vendors/get-graphql})
|
||||||
|
gq-checks/attach
|
||||||
gq-plaid/attach
|
gq-plaid/attach
|
||||||
gq-import-batches/attach
|
gq-import-batches/attach
|
||||||
gq-transactions/attach
|
gq-transactions/attach
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
(ns auto-ap.graphql.checks
|
(ns auto-ap.graphql.checks
|
||||||
(:require [amazonica.aws.s3 :as s3]
|
(:require
|
||||||
|
[amazonica.aws.s3 :as s3]
|
||||||
[auto-ap.datomic :refer [audit-transact remove-nils]]
|
[auto-ap.datomic :refer [audit-transact remove-nils]]
|
||||||
[auto-ap.datomic.bank-accounts :as d-bank-accounts]
|
[auto-ap.datomic.bank-accounts :as d-bank-accounts]
|
||||||
[auto-ap.datomic.checks :as d-checks]
|
[auto-ap.datomic.checks :as d-checks]
|
||||||
@@ -8,8 +9,7 @@
|
|||||||
[auto-ap.datomic.transactions :as d-transactions]
|
[auto-ap.datomic.transactions :as d-transactions]
|
||||||
[auto-ap.datomic.vendors :as d-vendors]
|
[auto-ap.datomic.vendors :as d-vendors]
|
||||||
[auto-ap.graphql.utils
|
[auto-ap.graphql.utils
|
||||||
:refer
|
:refer [->graphql <-graphql assert-admin assert-can-see-client enum->keyword]]
|
||||||
[->graphql <-graphql assert-can-see-client enum->keyword]]
|
|
||||||
[auto-ap.numeric :refer [num->words]]
|
[auto-ap.numeric :refer [num->words]]
|
||||||
[auto-ap.time :refer [iso-date local-now parse]]
|
[auto-ap.time :refer [iso-date local-now parse]]
|
||||||
[auto-ap.utils :refer [by dollars-0?]]
|
[auto-ap.utils :refer [by dollars-0?]]
|
||||||
@@ -19,13 +19,14 @@
|
|||||||
[clj-time.format :as f]
|
[clj-time.format :as f]
|
||||||
[clojure.edn :as edn]
|
[clojure.edn :as edn]
|
||||||
[clojure.java.io :as io]
|
[clojure.java.io :as io]
|
||||||
|
[clojure.set :as set]
|
||||||
[clojure.string :as str]
|
[clojure.string :as str]
|
||||||
[config.core :refer [env]]
|
[com.walmartlabs.lacinia.util :refer [attach-resolvers]]
|
||||||
[clojure.tools.logging :as log]
|
[config.core :refer [env]])
|
||||||
[clojure.set :as set])
|
(:import
|
||||||
(:import java.io.ByteArrayOutputStream
|
(java.io ByteArrayOutputStream)
|
||||||
java.text.DecimalFormat
|
(java.text DecimalFormat)
|
||||||
java.util.UUID))
|
(java.util UUID)))
|
||||||
|
|
||||||
(def parser (f/formatter "MM/dd/YYYY"))
|
(def parser (f/formatter "MM/dd/YYYY"))
|
||||||
(defn date->str [t]
|
(defn date->str [t]
|
||||||
@@ -58,12 +59,9 @@
|
|||||||
(let [{:keys [bank-account paid-to client check date amount memo] {print-as :vendor/print-as vendor-name :vendor/name :as vendor} :vendor} check
|
(let [{:keys [bank-account paid-to client check date amount memo] {print-as :vendor/print-as vendor-name :vendor/name :as vendor} :vendor} check
|
||||||
df (DecimalFormat. "#,###.00")
|
df (DecimalFormat. "#,###.00")
|
||||||
word-amount (num->words amount)
|
word-amount (num->words amount)
|
||||||
|
|
||||||
amount (str "--" (.format df amount) "--")]
|
amount (str "--" (.format df amount) "--")]
|
||||||
|
|
||||||
[:table {:num-cols 12 :border false :leading 11 :widths (distribute [2 3 3 3 3 3 3 3 3 2 2 2])}
|
[:table {:num-cols 12 :border false :leading 11 :widths (distribute [2 3 3 3 3 3 3 3 3 2 2 2])}
|
||||||
[(let [{:keys [:client/name] {:keys [:address/street1 :address/street2 :address/city :address/state :address/zip]} :client/address} client]
|
[(let [{:keys [:client/name] {:keys [:address/street1 :address/city :address/state :address/zip]} :client/address} client]
|
||||||
|
|
||||||
[:cell {:colspan 4 } [:paragraph {:leading 14} name "\n" street1 "\n" (str city ", " state " " zip)] ])
|
[:cell {:colspan 4 } [:paragraph {:leading 14} name "\n" street1 "\n" (str city ", " state " " zip)] ])
|
||||||
(let [{:keys [:bank-account/bank-name :bank-account/bank-code] } bank-account]
|
(let [{:keys [:bank-account/bank-name :bank-account/bank-code] } bank-account]
|
||||||
[:cell {:colspan 6 :align :center} [:paragraph {:style :bold} bank-name] [:paragraph {:size 8 :leading 8} bank-code]])
|
[:cell {:colspan 6 :align :center} [:paragraph {:style :bold} bank-name] [:paragraph {:size 8 :leading 8} bank-code]])
|
||||||
@@ -108,9 +106,7 @@
|
|||||||
[[:cell {:colspan 2}]
|
[[:cell {:colspan 2}]
|
||||||
[:cell {:colspan 10 :leading 30}
|
[:cell {:colspan 10 :leading 30}
|
||||||
[:phrase {:size 18 :ttf-name "public/micrenc.ttf"} (str "c" check "c a" (:bank-account/routing bank-account) "a " (:bank-account/number bank-account) "c")]]]
|
[:phrase {:size 18 :ttf-name "public/micrenc.ttf"} (str "c" check "c a" (:bank-account/routing bank-account) "a " (:bank-account/number bank-account) "c")]]]
|
||||||
|
|
||||||
[[:cell {:colspan 12 :leading 18} [:spacer]]]
|
[[:cell {:colspan 12 :leading 18} [:spacer]]]
|
||||||
|
|
||||||
[[:cell]
|
[[:cell]
|
||||||
(into
|
(into
|
||||||
[:cell {:colspan 9}]
|
[:cell {:colspan 9}]
|
||||||
@@ -230,6 +226,12 @@
|
|||||||
:payment/invoices (map :db/id invoices)})
|
:payment/invoices (map :db/id invoices)})
|
||||||
|
|
||||||
(defmethod invoices->entities :payment-type/check [invoices vendor client bank-account type index invoice-amounts]
|
(defmethod invoices->entities :payment-type/check [invoices vendor client bank-account type index invoice-amounts]
|
||||||
|
(when (<= (->> invoices
|
||||||
|
(map (comp invoice-amounts :db/id))
|
||||||
|
(reduce + 0.0))
|
||||||
|
0.001)
|
||||||
|
(throw (ex-info "The selected invoices do not have an outstanding balance."
|
||||||
|
{:validation-error "The selected invoices do not have an outstanding balance."})))
|
||||||
(let [uuid (str (UUID/randomUUID))
|
(let [uuid (str (UUID/randomUUID))
|
||||||
memo (str "Invoice #'s: "
|
memo (str "Invoice #'s: "
|
||||||
(str/join ", "
|
(str/join ", "
|
||||||
@@ -269,6 +271,12 @@
|
|||||||
|
|
||||||
|
|
||||||
(defmethod invoices->entities :payment-type/debit [invoices vendor client bank-account type index invoice-amounts]
|
(defmethod invoices->entities :payment-type/debit [invoices vendor client bank-account type index invoice-amounts]
|
||||||
|
(when (<= (->> invoices
|
||||||
|
(map (comp invoice-amounts :db/id))
|
||||||
|
(reduce + 0.0))
|
||||||
|
0.001)
|
||||||
|
(throw (ex-info "The selected invoices do not have an outstanding balance."
|
||||||
|
{:validation-error "The selected invoices do not have an outstanding balance."})))
|
||||||
(let [payment (assoc (base-payment invoices vendor client bank-account type index invoice-amounts)
|
(let [payment (assoc (base-payment invoices vendor client bank-account type index invoice-amounts)
|
||||||
:payment/type :payment-type/debit
|
:payment/type :payment-type/debit
|
||||||
:payment/memo (str "Debit Invoice #'s: "
|
:payment/memo (str "Debit Invoice #'s: "
|
||||||
@@ -281,7 +289,32 @@
|
|||||||
(conj payment)
|
(conj payment)
|
||||||
(into (invoice-payments invoices invoice-amounts)))))
|
(into (invoice-payments invoices invoice-amounts)))))
|
||||||
|
|
||||||
|
(defmethod invoices->entities :payment-type/credit [invoices vendor client bank-account type index invoice-amounts]
|
||||||
|
(when (>= (->> invoices
|
||||||
|
(map (comp invoice-amounts :db/id))
|
||||||
|
(reduce + 0.0))
|
||||||
|
0.001)
|
||||||
|
(throw (ex-info "The selected invoices do not have an outstanding balance."
|
||||||
|
{:validation-error "The selected invoices do not have an outstanding balance."})))
|
||||||
|
(let [payment (assoc (base-payment invoices vendor client bank-account type index invoice-amounts)
|
||||||
|
:payment/type :payment-type/credit
|
||||||
|
:payment/memo (str "Debit Invoice #'s: "
|
||||||
|
(str/join ", "
|
||||||
|
(map (fn [i]
|
||||||
|
(str (:invoice/invoice-number i) "(" (invoice-amounts (:db/id i)) ")"))
|
||||||
|
invoices)))
|
||||||
|
:payment/status :payment-status/pending)]
|
||||||
|
(-> []
|
||||||
|
(conj payment)
|
||||||
|
(into (invoice-payments invoices invoice-amounts)))))
|
||||||
|
|
||||||
(defmethod invoices->entities :payment-type/cash [invoices vendor client bank-account type index invoice-amounts]
|
(defmethod invoices->entities :payment-type/cash [invoices vendor client bank-account type index invoice-amounts]
|
||||||
|
(when (<= (->> invoices
|
||||||
|
(map (comp invoice-amounts :db/id))
|
||||||
|
(reduce + 0.0))
|
||||||
|
0.001)
|
||||||
|
(throw (ex-info "The selected invoices do not have an outstanding balance."
|
||||||
|
{:validation-error "The selected invoices do not have an outstanding balance."})))
|
||||||
(let [payment (assoc (base-payment invoices vendor client bank-account type index invoice-amounts)
|
(let [payment (assoc (base-payment invoices vendor client bank-account type index invoice-amounts)
|
||||||
:payment/type :payment-type/cash
|
:payment/type :payment-type/cash
|
||||||
:payment/memo (str "Cash Invoice #'s: "
|
:payment/memo (str "Cash Invoice #'s: "
|
||||||
@@ -307,7 +340,7 @@
|
|||||||
:client-id client-id
|
:client-id client-id
|
||||||
:invoices (map :invoice/invoice-number invoices)}))))
|
:invoices (map :invoice/invoice-number invoices)}))))
|
||||||
|
|
||||||
(defn print-checks [invoice-payments client-id bank-account-id type id]
|
(defn print-checks-internal [invoice-payments client-id bank-account-id type id]
|
||||||
(let [type (keyword "payment-type" (name type))
|
(let [type (keyword "payment-type" (name type))
|
||||||
invoices (d-invoices/get-multi (map :invoice-id invoice-payments))
|
invoices (d-invoices/get-multi (map :invoice-id invoice-payments))
|
||||||
client (d-clients/get-by-id client-id)
|
client (d-clients/get-by-id client-id)
|
||||||
@@ -321,17 +354,6 @@
|
|||||||
(let [message (str "The bank account " (:bank-account/name bank-account) " does not have a starting check number. Please ask the integreat staff to initialize it.")]
|
(let [message (str "The bank account " (:bank-account/name bank-account) " does not have a starting check number. Please ask the integreat staff to initialize it.")]
|
||||||
(throw (ex-info message
|
(throw (ex-info message
|
||||||
{:validation-error message}))))
|
{:validation-error message}))))
|
||||||
|
|
||||||
_ (if (->> invoices-grouped-by-vendor
|
|
||||||
vals
|
|
||||||
(map (fn [payments]
|
|
||||||
(->> payments
|
|
||||||
(map (comp invoice-amounts :db/id))
|
|
||||||
(reduce + 0.0))))
|
|
||||||
(filter #(<= % 0.0))
|
|
||||||
seq)
|
|
||||||
(throw (ex-info "The selected invoices do not have an outstanding balance."
|
|
||||||
{:validation-error "The selected invoices do not have an outstanding balance."})))
|
|
||||||
checks (->> (for [[[vendor-id invoices] index] (map vector invoices-grouped-by-vendor (range))]
|
checks (->> (for [[[vendor-id invoices] index] (map vector invoices-grouped-by-vendor (range))]
|
||||||
(invoices->entities invoices (vendors vendor-id) client bank-account type index invoice-amounts))
|
(invoices->entities invoices (vendors vendor-id) client bank-account type index invoice-amounts))
|
||||||
(reduce into [])
|
(reduce into [])
|
||||||
@@ -431,3 +453,120 @@
|
|||||||
|
|
||||||
(-> (d-checks/get-by-id id)
|
(-> (d-checks/get-by-id id)
|
||||||
(->graphql))))
|
(->graphql))))
|
||||||
|
|
||||||
|
(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 print-checks [context args value]
|
||||||
|
|
||||||
|
(assert-can-see-client (:id context) (:client_id args))
|
||||||
|
(->graphql
|
||||||
|
(print-checks-internal (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))))
|
||||||
|
|
||||||
|
(def objects
|
||||||
|
{: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)}}}
|
||||||
|
:invoice_payment
|
||||||
|
{:fields {:id {:type :id}
|
||||||
|
:amount {:type 'String}
|
||||||
|
:invoice_id {:type 'String}
|
||||||
|
:payment_id {:type 'String}
|
||||||
|
:payment {:type :payment}
|
||||||
|
:invoice {:type :invoice}}}
|
||||||
|
:payment_page {:fields {:payments {:type '(list :payment)}
|
||||||
|
:count {:type 'Int}
|
||||||
|
:total {:type 'Int}
|
||||||
|
:start {:type 'Int}
|
||||||
|
:end {:type 'Int}}}})
|
||||||
|
|
||||||
|
(def queries
|
||||||
|
{: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}
|
||||||
|
:payment_page {:type '(list :payment_page)
|
||||||
|
:args {:client_id {:type :id}
|
||||||
|
:vendor_id {:type :id}
|
||||||
|
:payment_type {:type :payment_type}
|
||||||
|
:exact_match_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}
|
||||||
|
:potential_payment_matches {:type '(list :payment)
|
||||||
|
:args {:transaction_id {:type :id}}
|
||||||
|
:resolve :get-potential-payments}})
|
||||||
|
|
||||||
|
(def mutations
|
||||||
|
{: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}
|
||||||
|
:void_payment {:type :payment
|
||||||
|
:args {:payment_id {:type :id}}
|
||||||
|
:resolve :mutation/void-payment}})
|
||||||
|
|
||||||
|
(def input-objects
|
||||||
|
{:invoice_payment_amount {:fields {:invoice_id {:type :id}
|
||||||
|
:amount {:type :money}}}})
|
||||||
|
|
||||||
|
(def enums
|
||||||
|
{:payment_type {:values [{:enum-value :check}
|
||||||
|
{:enum-value :cash}
|
||||||
|
{:enum-value :debit}
|
||||||
|
{:enum-value :credit}]}})
|
||||||
|
|
||||||
|
(def resolvers
|
||||||
|
{:get-potential-payments get-potential-payments
|
||||||
|
:get-payment-page get-payment-page
|
||||||
|
:get-all-payments get-all-payments
|
||||||
|
:mutation/void-payment void-check
|
||||||
|
:mutation/print-checks print-checks
|
||||||
|
:mutation/add-handwritten-check add-handwritten-check
|
||||||
|
})
|
||||||
|
|
||||||
|
(defn attach [schema]
|
||||||
|
(->
|
||||||
|
(merge-with merge schema
|
||||||
|
{:objects objects
|
||||||
|
:queries queries
|
||||||
|
:mutations mutations
|
||||||
|
:input-objects input-objects
|
||||||
|
:enums enums})
|
||||||
|
(attach-resolvers resolvers)))
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
(:require
|
(:require
|
||||||
[auto-ap.datomic :refer [conn]]
|
[auto-ap.datomic :refer [conn]]
|
||||||
[auto-ap.import.transactions :as t]
|
[auto-ap.import.transactions :as t]
|
||||||
|
[auto-ap.time :as atime]
|
||||||
[auto-ap.intuit.core :as i]
|
[auto-ap.intuit.core :as i]
|
||||||
[auto-ap.utils :refer [allow-once]]
|
[auto-ap.utils :refer [allow-once]]
|
||||||
[clj-time.coerce :as coerce]
|
[clj-time.coerce :as coerce]
|
||||||
@@ -10,7 +11,9 @@
|
|||||||
[datomic.api :as d]
|
[datomic.api :as d]
|
||||||
[mount.core :as mount]
|
[mount.core :as mount]
|
||||||
[unilog.context :as lc]
|
[unilog.context :as lc]
|
||||||
[yang.scheduler :as scheduler]))
|
[yang.scheduler :as scheduler]
|
||||||
|
[clojure.string :as str]
|
||||||
|
[clojure.tools.logging :as log]))
|
||||||
|
|
||||||
(defn get-intuit-bank-accounts [db]
|
(defn get-intuit-bank-accounts [db]
|
||||||
(d/q '[:find ?external-id ?ba ?c
|
(d/q '[:find ?external-id ?ba ?c
|
||||||
@@ -22,10 +25,18 @@
|
|||||||
db))
|
db))
|
||||||
|
|
||||||
(defn intuit->transaction [transaction]
|
(defn intuit->transaction [transaction]
|
||||||
{:transaction/description-original (:Memo/Description transaction)
|
(let [check-number (when (not (str/blank? (:Num transaction)))
|
||||||
|
(try
|
||||||
|
(Integer/parseInt (:Num transaction))
|
||||||
|
(catch NumberFormatException e
|
||||||
|
(log/warn "Got an invalid check number " e)
|
||||||
|
nil)))]
|
||||||
|
(cond-> {:transaction/description-original (:Memo/Description transaction)
|
||||||
:transaction/amount (Double/parseDouble (:Amount transaction))
|
:transaction/amount (Double/parseDouble (:Amount transaction))
|
||||||
:transaction/date (coerce/to-date (auto-ap.time/parse (:Date transaction) auto-ap.time/iso-date))
|
:transaction/date (coerce/to-date (atime/parse (:Date transaction) atime/iso-date))
|
||||||
:transaction/status "POSTED"})
|
:transaction/status "POSTED"}
|
||||||
|
check-number (assoc :transaction/check-number check-number))))
|
||||||
|
|
||||||
|
|
||||||
(defn intuits->transactions [transactions bank-account-id client-id]
|
(defn intuits->transactions [transactions bank-account-id client-id]
|
||||||
(->> transactions
|
(->> transactions
|
||||||
|
|||||||
@@ -145,20 +145,20 @@
|
|||||||
:class "is-primary"}]
|
:class "is-primary"}]
|
||||||
|
|
||||||
(when current-client
|
(when current-client
|
||||||
|
(let [balance (->> checked-invoices
|
||||||
|
(map (comp js/parseFloat :outstanding-balance))
|
||||||
|
(reduce + 0)
|
||||||
|
)]
|
||||||
[drop-down {:header [:button.button.is-primary {:aria-haspopup true
|
[drop-down {:header [:button.button.is-primary {:aria-haspopup true
|
||||||
:on-click (dispatch-event [::events/toggle-menu ::print-checks ])
|
:on-click (dispatch-event [::events/toggle-menu ::print-checks ])
|
||||||
:disabled (or (status/disabled-for print-checks-status) (not (seq checked-invoices)))
|
:disabled (or (status/disabled-for print-checks-status) (not (seq checked-invoices)))
|
||||||
:class (status/class-for @(re-frame/subscribe [::status/single ::print-checks]))}
|
:class (status/class-for @(re-frame/subscribe [::status/single ::print-checks]))}
|
||||||
"Pay "
|
"Pay "
|
||||||
(when (> (count checked-invoices ))
|
(when (> (count checked-invoices ) 0)
|
||||||
(str
|
(str
|
||||||
(count checked-invoices)
|
(count checked-invoices)
|
||||||
" invoices "
|
" invoices "
|
||||||
"(" (->> checked-invoices
|
"(" (gstring/format "$%.2f" balance ) ")"))
|
||||||
(map (comp js/parseFloat :outstanding-balance))
|
|
||||||
(reduce + 0)
|
|
||||||
(gstring/format "$%.2f" ))
|
|
||||||
")"))
|
|
||||||
[:span " "]
|
[:span " "]
|
||||||
[:span.icon.is-small [:i.fa.fa-angle-down {:aria-hidden "true"}]]]
|
[:span.icon.is-small [:i.fa.fa-angle-down {:aria-hidden "true"}]]]
|
||||||
:id ::print-checks
|
:id ::print-checks
|
||||||
@@ -169,18 +169,25 @@
|
|||||||
(if (= :cash type)
|
(if (= :cash type)
|
||||||
^{:key id} [:a.dropdown-item {:on-click (dispatch-event [::print-checks id :cash])
|
^{:key id} [:a.dropdown-item {:on-click (dispatch-event [::print-checks id :cash])
|
||||||
:disabled (status/disabled-for print-checks-status)} "With cash"]
|
:disabled (status/disabled-for print-checks-status)} "With cash"]
|
||||||
|
(if (> balance 0.001)
|
||||||
(list
|
(list
|
||||||
^{:key (str id "-check")} [:a.dropdown-item {:on-click (dispatch-event-with-propagation [::print-checks id :check])
|
^{:key (str id "-check")} [:a.dropdown-item {:on-click (dispatch-event-with-propagation [::print-checks id :check])
|
||||||
:disabled (doto (status/disabled-for print-checks-status) println)} "Print checks from " name]
|
:disabled (doto (status/disabled-for print-checks-status) println)} "Print checks from " name]
|
||||||
^{:key (str id "-debit")} [:a.dropdown-item {:on-click (dispatch-event-with-propagation [::print-checks id :debit])
|
^{:key (str id "-debit")} [:a.dropdown-item {:on-click (dispatch-event-with-propagation [::print-checks id :debit])
|
||||||
:disabled (status/disabled-for print-checks-status)} "Debit from " name])))
|
:disabled (status/disabled-for print-checks-status)} "Debit from " name])
|
||||||
^{:key "advanced-divider"} [:hr.dropdown-divider]
|
(list
|
||||||
|
^{:key (str id "-credit")} [:a.dropdown-item {:on-click (dispatch-event-with-propagation [::print-checks id :credit])
|
||||||
|
:disabled (status/disabled-for print-checks-status)} "Credit from " name]))))
|
||||||
|
(when (> balance 0.001)
|
||||||
|
^{:key "advanced-divider"} [:hr.dropdown-divider])
|
||||||
|
|
||||||
(when (= 1 (count (set (map (comp :id :vendor) checked-invoices))))
|
(when (and (= 1 (count (set (map (comp :id :vendor) checked-invoices))))
|
||||||
|
(> balance 0.001))
|
||||||
^{:key "handwritten"} [:a.dropdown-item {:on-click (dispatch-event-with-propagation [::handwritten-checks/show checked-invoices])
|
^{:key "handwritten"} [:a.dropdown-item {:on-click (dispatch-event-with-propagation [::handwritten-checks/show checked-invoices])
|
||||||
:disabled (status/disabled-for print-checks-status)} "Handwritten Check..."])
|
:disabled (status/disabled-for print-checks-status)} "Handwritten Check..."])
|
||||||
|
(when (> balance 0.001)
|
||||||
^{:key "advanced"} [:a.dropdown-item {:on-click (dispatch-event-with-propagation [::advanced-print-checks/show checked-invoices])
|
^{:key "advanced"} [:a.dropdown-item {:on-click (dispatch-event-with-propagation [::advanced-print-checks/show checked-invoices])
|
||||||
:disabled (status/disabled-for print-checks-status)} "Advanced..."])]])]]
|
:disabled (status/disabled-for print-checks-status)} "Advanced..."]))]]))]]
|
||||||
[:div.is-pulled-right {:style {:margin-right "0.5rem"}}
|
[:div.is-pulled-right {:style {:margin-right "0.5rem"}}
|
||||||
(into [:div.tags ] (map (fn [{:keys [id invoice-number]}]
|
(into [:div.tags ] (map (fn [{:keys [id invoice-number]}]
|
||||||
[:span.tag.is-medium invoice-number
|
[:span.tag.is-medium invoice-number
|
||||||
|
|||||||
Reference in New Issue
Block a user