diff --git a/src/clj/auto_ap/datomic/invoices.clj b/src/clj/auto_ap/datomic/invoices.clj index c3ee1ab3..66acaa95 100644 --- a/src/clj/auto_ap/datomic/invoices.clj +++ b/src/clj/auto_ap/datomic/invoices.clj @@ -25,129 +25,132 @@ (update :invoice/status :db/ident) (rename-keys {:invoice-payment/_invoice :invoice/payments}))) -(defn raw-graphql-ids [db args] - (->> (cond-> {:query {:find [] - :in ['$] - :where ['[?e :invoice/client]]} - :args [(d/db (d/connect uri))]} +(defn raw-graphql-ids + ([args] + (raw-graphql-ids (d/db conn) args)) + ([db args] + (->> (cond-> {:query {:find [] + :in ['$] + :where ['[?e :invoice/client]]} + :args [(d/db (d/connect uri))]} - (:exact-match-id args) - (merge-query {:query {:in ['?e] - :where []} - :args [(:exact-match-id args)]}) - (limited-clients (:id args)) - (merge-query {:query {:in ['[?xx ...]] - :where ['[?e :invoice/client ?xx]]} - :args [ (set (map :db/id (limited-clients (:id args))))]}) - (:client-id args) - (merge-query {:query {:in ['?client-id] - :where ['[?e :invoice/client ?client-id]]} - :args [ (:client-id args)]}) + (:exact-match-id args) + (merge-query {:query {:in ['?e] + :where []} + :args [(:exact-match-id args)]}) + (limited-clients (:id args)) + (merge-query {:query {:in ['[?xx ...]] + :where ['[?e :invoice/client ?xx]]} + :args [ (set (map :db/id (limited-clients (:id args))))]}) + (:client-id args) + (merge-query {:query {:in ['?client-id] + :where ['[?e :invoice/client ?client-id]]} + :args [ (:client-id args)]}) - (:client-code args) - (merge-query {:query {:in ['?client-code] - :where ['[?e :invoice/client ?client-id] - '[?client-id :client/code ?client-code]]} - :args [ (:client-code args)]}) + (:client-code args) + (merge-query {:query {:in ['?client-code] + :where ['[?e :invoice/client ?client-id] + '[?client-id :client/code ?client-code]]} + :args [ (:client-code args)]}) - (:original-id args) - (merge-query {:query {:in ['?original-id] - :where [ - '[?e :invoice/client ?c] - '[?c :client/original-id ?original-id]]} - :args [ (cond-> (:original-id args) - (string? (:original-id args)) Long/parseLong )]}) + (:original-id args) + (merge-query {:query {:in ['?original-id] + :where [ + '[?e :invoice/client ?c] + '[?c :client/original-id ?original-id]]} + :args [ (cond-> (:original-id args) + (string? (:original-id args)) Long/parseLong )]}) - (:start (:date-range args)) (merge-query {:query {:in '[?start-date] - :where ['[?e :invoice/date ?date] - '[(>= ?date ?start-date)]]} - :args [(coerce/to-date (:start (:date-range args)))]}) + (:start (:date-range args)) (merge-query {:query {:in '[?start-date] + :where ['[?e :invoice/date ?date] + '[(>= ?date ?start-date)]]} + :args [(coerce/to-date (:start (:date-range args)))]}) - (:end (:date-range args)) (merge-query {:query {:in '[?end-date] - :where ['[?e :invoice/date ?date] - '[(<= ?date ?end-date)]]} - :args [(coerce/to-date (:end (:date-range args)))]}) + (:end (:date-range args)) (merge-query {:query {:in '[?end-date] + :where ['[?e :invoice/date ?date] + '[(<= ?date ?end-date)]]} + :args [(coerce/to-date (:end (:date-range args)))]}) - (:start (:due-range args)) (merge-query {:query {:in '[?start-due] - :where ['[?e :invoice/due ?due] - '[(>= ?due ?start-due)]]} - :args [(coerce/to-date (:start (:due-range args)))]}) + (:start (:due-range args)) (merge-query {:query {:in '[?start-due] + :where ['[?e :invoice/due ?due] + '[(>= ?due ?start-due)]]} + :args [(coerce/to-date (:start (:due-range args)))]}) - (:end (:due-range args)) (merge-query {:query {:in '[?end-due] - :where ['[?e :invoice/due ?due] - '[(<= ?due ?end-due)]]} - :args [(coerce/to-date (:end (:due-range args)))]}) + (:end (:due-range args)) (merge-query {:query {:in '[?end-due] + :where ['[?e :invoice/due ?due] + '[(<= ?due ?end-due)]]} + :args [(coerce/to-date (:end (:due-range args)))]}) - (:import-status args) - (merge-query {:query {:in ['?import-status] - :where ['[?e :invoice/import-status ?import-status]]} - :args [ (keyword "import-status" (:import-status args))]}) - (:status args) - (merge-query {:query {:in ['?status] - :where ['[?e :invoice/status ?status]]} - :args [ (:status args)]}) - (:vendor-id args) - (merge-query {:query {:in ['?vendor-id] - :where ['[?e :invoice/vendor ?vendor-id]]} - :args [ (:vendor-id args)]}) + (:import-status args) + (merge-query {:query {:in ['?import-status] + :where ['[?e :invoice/import-status ?import-status]]} + :args [ (keyword "import-status" (:import-status args))]}) + (:status args) + (merge-query {:query {:in ['?status] + :where ['[?e :invoice/status ?status]]} + :args [ (:status args)]}) + (:vendor-id args) + (merge-query {:query {:in ['?vendor-id] + :where ['[?e :invoice/vendor ?vendor-id]]} + :args [ (:vendor-id args)]}) - (:amount-gte args) - (merge-query {:query {:in ['?amount-gte] - :where ['[?e :invoice/total ?total-filter] - '[(>= ?total-filter ?amount-gte)]]} - :args [(:amount-gte args)]}) + (:amount-gte args) + (merge-query {:query {:in ['?amount-gte] + :where ['[?e :invoice/total ?total-filter] + '[(>= ?total-filter ?amount-gte)]]} + :args [(:amount-gte args)]}) - (:amount-lte args) - (merge-query {:query {:in ['?amount-lte] - :where ['[?e :invoice/total ?total-filter] - '[(<= ?total-filter ?amount-lte)]]} - :args [(:amount-lte args)]}) + (:amount-lte args) + (merge-query {:query {:in ['?amount-lte] + :where ['[?e :invoice/total ?total-filter] + '[(<= ?total-filter ?amount-lte)]]} + :args [(:amount-lte args)]}) - (seq (:invoice-number-like args)) - (merge-query {:query {:in ['?invoice-number-like] - :where ['[?e :invoice/invoice-number ?invoice-number] - '[(.contains ^String ?invoice-number ?invoice-number-like)]]} - :args [(:invoice-number-like args)]}) + (seq (:invoice-number-like args)) + (merge-query {:query {:in ['?invoice-number-like] + :where ['[?e :invoice/invoice-number ?invoice-number] + '[(.contains ^String ?invoice-number ?invoice-number-like)]]} + :args [(:invoice-number-like args)]}) - (:scheduled-payments args) - (merge-query {:query {:in [] - :where ['[?e :invoice/scheduled-payment]]} - :args []}) + (:scheduled-payments args) + (merge-query {:query {:in [] + :where ['[?e :invoice/scheduled-payment]]} + :args []}) - (:unresolved args) - (merge-query {:query {:in [] - :where ['(or-join [?e] - (not [?e :invoice/expense-accounts ]) - (and [?e :invoice/expense-accounts ?ea] - (not [?ea :invoice-expense-account/account])))]} - :args []}) + (:unresolved args) + (merge-query {:query {:in [] + :where ['(or-join [?e] + (not [?e :invoice/expense-accounts ]) + (and [?e :invoice/expense-accounts ?ea] + (not [?ea :invoice-expense-account/account])))]} + :args []}) - (seq (:location args)) - (merge-query {:query {:in ['?location] - :where ['[?e :invoice/expense-accounts ?eas] - '[?eas :invoice-expense-account/location ?location]]} - :args [(:location args)]}) + (seq (:location args)) + (merge-query {:query {:in ['?location] + :where ['[?e :invoice/expense-accounts ?eas] + '[?eas :invoice-expense-account/location ?location]]} + :args [(:location args)]}) - (:sort args) (add-sorter-fields {"client" ['[?e :invoice/client ?c] - '[?c :client/name ?sort-client]] - "vendor" ['[?e :invoice/vendor ?v] - '[?v :vendor/name ?sort-vendor]] - "description-original" ['[?e :transaction/description-original ?sort-description-original]] - "location" ['[?e :invoice/expense-accounts ?iea] - '[?iea :invoice-expense-account/location ?sort-location]] - "date" ['[?e :invoice/date ?sort-date]] - "due" ['[(get-else $ ?e :invoice/due #inst "2050-01-01") ?sort-due]] - "invoice-number" ['[?e :invoice/invoice-number ?sort-invoice-number]] - "total" ['[?e :invoice/total ?sort-total]] - "outstanding-balance" ['[?e :invoice/outstanding-balance ?sort-outstanding-balance]]} - args) - true - (merge-query {:query {:find ['?sort-default '?e ] - :where ['[?e :invoice/client] - '[?e :invoice/date ?sort-default]]}}) ) - (d/query) - (apply-sort-3 args) - (apply-pagination args))) + (:sort args) (add-sorter-fields {"client" ['[?e :invoice/client ?c] + '[?c :client/name ?sort-client]] + "vendor" ['[?e :invoice/vendor ?v] + '[?v :vendor/name ?sort-vendor]] + "description-original" ['[?e :transaction/description-original ?sort-description-original]] + "location" ['[?e :invoice/expense-accounts ?iea] + '[?iea :invoice-expense-account/location ?sort-location]] + "date" ['[?e :invoice/date ?sort-date]] + "due" ['[(get-else $ ?e :invoice/due #inst "2050-01-01") ?sort-due]] + "invoice-number" ['[?e :invoice/invoice-number ?sort-invoice-number]] + "total" ['[?e :invoice/total ?sort-total]] + "outstanding-balance" ['[?e :invoice/outstanding-balance ?sort-outstanding-balance]]} + args) + true + (merge-query {:query {:find ['?sort-default '?e ] + :where ['[?e :invoice/client] + '[?e :invoice/date ?sort-default]]}}) ) + (d/query) + (apply-sort-3 args) + (apply-pagination args)))) (defn graphql-results [ids db args] @@ -168,7 +171,7 @@ :where ['[?id :invoice/outstanding-balance ?o]] } :args [(d/db conn) - ids]}) + ids]}) (map last) (reduce + @@ -182,7 +185,7 @@ :where ['[?id :invoice/total ?o]] } :args [(d/db conn) - ids]}) + ids]}) (map last) (reduce + @@ -190,10 +193,10 @@ (defn get-graphql [args] - (let [db (d/db (d/connect uri)) + (let [db (d/db (d/connect uri)) {ids-to-retrieve :ids matching-count :count} (raw-graphql-ids db args) - outstanding (sum-outstanding ids-to-retrieve) - total-amount (sum-total-amount ids-to-retrieve)] + outstanding (sum-outstanding ids-to-retrieve) + total-amount (sum-total-amount ids-to-retrieve)] [(->> (graphql-results ids-to-retrieve db args)) @@ -258,7 +261,16 @@ set)] (into vendored-results vendorless-results))) - +(defn filter-ids [ids] + (if ids + (->> {:query {:find ['?e] + :in ['$ '[?e ...]] + :where ['[?e :invoice/date]]} + :args [(d/db conn) ids]} + (d/query) + (map first) + vec) + [])) (defn code-invoice [invoice] (let [db (d/db auto-ap.datomic/conn) diff --git a/src/clj/auto_ap/graphql/invoices.clj b/src/clj/auto_ap/graphql/invoices.clj index eea32edb..eb8ee6f8 100644 --- a/src/clj/auto_ap/graphql/invoices.clj +++ b/src/clj/auto_ap/graphql/invoices.clj @@ -1,17 +1,18 @@ (ns auto-ap.graphql.invoices (:require - [auto-ap.datomic :refer [audit-transact conn remove-nils uri]] + [auto-ap.datomic + :refer [audit-transact audit-transact-batch conn remove-nils uri]] [auto-ap.datomic.clients :as d-clients] [auto-ap.datomic.invoices :as d-invoices] [auto-ap.datomic.vendors :as d-vendors] [auto-ap.graphql.checks :as gq-checks] [auto-ap.graphql.utils + :as u :refer [<-graphql assert-admin assert-can-see-client assert-power-user - enum->keyword] - :as u] + enum->keyword]] [auto-ap.utils :refer [dollars=]] [clj-time.coerce :as coerce] [clj-time.core :as time] @@ -31,6 +32,7 @@ (let [args (assoc args :id (:id context)) [invoices invoice-count outstanding total-amount] (-> args + :filters (assoc :id (:id context)) (<-graphql) (update :status enum->keyword "invoice-status") @@ -208,18 +210,55 @@ (defn void-invoice [context {id :invoice_id} _] (let [invoice (d-invoices/get-by-id id) - _ (assert-can-see-client (:id context) (:db/id (:invoice/client invoice)))] - (audit-transact [{:db/id id - :invoice/total 0.0 + _ (assert-can-see-client (:id context) (:db/id (:invoice/client invoice)))] + (audit-transact [{:db/id id + :invoice/total 0.0 :invoice/outstanding-balance 0.0 - :invoice/status :invoice-status/voided - :invoice/expense-accounts (map (fn [ea] {:db/id (:db/id ea) - :invoice-expense-account/amount 0.0}) + :invoice/status :invoice-status/voided + :invoice/expense-accounts (map (fn [ea] {:db/id (:db/id ea) + :invoice-expense-account/amount 0.0}) (:invoice/expense-accounts invoice))}] (:id context)) (-> (d-invoices/get-by-id id) (->graphql (:id context))))) +(defn void-invoices [context args _] + (let [_ (assert-admin (:id context)) + args (assoc args :id (:id context)) + ids (some-> args + :filters + (assoc :id (:id context)) + (<-graphql) + (update :status enum->keyword "invoice-status") + (assoc :per-page Integer/MAX_VALUE) + d-invoices/raw-graphql-ids + :ids) + specific-ids (d-invoices/filter-ids (:ids args)) + all-ids (into (set ids) specific-ids)] + + (log/info "Voiding " (count all-ids) args) + (audit-transact + (->> all-ids + (d/q '[:find [(pull ?i [:db/id {:invoice/expense-accounts [:db/id]}]) ...] + :in $ [?i ...] + :where (not [_ :invoice-payment/invoice ?i])] + (d/db conn) + ) + (mapcat + (fn [i] + (into + [{:db/id (:db/id i) + :invoice/total 0.0 + :invoice/outstanding-balance 0.0 + :invoice/status :invoice-status/voided + }] + (map + (fn [iea] + [:db/retract (:db/id i) :invoice/expense-accounts (:db/id iea)]) + (:invoice/expense-accounts i)))))) + (:id context)) + {:message (str "Succesfully voided " (count all-ids))})) + (defn unvoid-invoice [context {id :invoice_id} _] (let [invoice (d-invoices/get-by-id id) _ (assert-can-see-client (:id context) (:db/id (:invoice/client invoice))) @@ -316,22 +355,7 @@ (def queries {:invoice_page {:type '(list :invoice_page) - :args {:import_status {:type 'String} - :exact_match_id {:type :id} - :date_range {:type :date_range} - :due_range {:type :date_range} - :status {:type :invoice_status} - :unresolved {:type 'Boolean} - :scheduled_payments {: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)}} + :args {:filters {:type :invoice_filters}} :resolve :get-invoice-page} :all_invoices {:type '(list :invoice) @@ -351,6 +375,10 @@ :void_invoice {:type :invoice :args {:invoice_id {:type :id}} :resolve :mutation/void-invoice} + :void_invoices {:type :message + :args {:filters {:type :invoice_filters} + :ids {:type '(list :id)}} + :resolve :mutation/void-invoices} :unvoid_invoice {:type :invoice :args {:invoice_id {:type :id}} :resolve :mutation/unvoid-invoice} @@ -400,7 +428,24 @@ {:fields {:id {:type :id} :account_id {:type :id} :location {:type 'String} - :amount {:type :money}}}}) + :amount {:type :money}}} + + :invoice_filters {:fields {:import_status {:type 'String} + :exact_match_id {:type :id} + :date_range {:type :date_range} + :due_range {:type :date_range} + :status {:type :invoice_status} + :unresolved {:type 'Boolean} + :scheduled_payments {: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)}}}}) (def enums {:invoice_status {:values [{:enum-value :paid} @@ -416,6 +461,7 @@ :mutation/add-and-print-invoice add-and-print-invoice :mutation/edit-invoice edit-invoice :mutation/void-invoice void-invoice + :mutation/void-invoices void-invoices :mutation/unvoid-invoice unvoid-invoice :mutation/unautopay-invoice unautopay-invoice :mutation/edit-expense-accounts edit-expense-accounts}) diff --git a/src/clj/auto_ap/routes/exports.clj b/src/clj/auto_ap/routes/exports.clj index 4d50b6c8..888d720c 100644 --- a/src/clj/auto_ap/routes/exports.clj +++ b/src/clj/auto_ap/routes/exports.clj @@ -197,6 +197,7 @@ :journal-entry-line/credit {:journal-entry-line/account [:bank-account/include-in-reports :bank-account/bank-name + :bank-account/numeric-code :bank-account/code :bank-account/visible :bank-account/name @@ -312,6 +313,7 @@ (log/info "Executing raw query " (get query-params "query" )) (statsd/time! [(str "export.time") {:tags #{"export:raw"}}] (into (list) (apply d/q (read-string (get query-params "query" )) (into [(d/db conn)] (read-string (get query-params "args" "[]"))))))))) + (defroutes export-routes (routes (wrap-routes api-key-authed-routes diff --git a/src/clj/auto_ap/yodlee/core.clj b/src/clj/auto_ap/yodlee/core.clj index a494bbfc..02391f25 100644 --- a/src/clj/auto_ap/yodlee/core.clj +++ b/src/clj/auto_ap/yodlee/core.clj @@ -11,6 +11,47 @@ [unilog.context :as lc] [yang.scheduler :as scheduler])) +(def known-bad-yodlee-ids ;; these yodlee ids are ones we wish we could manually delete + (set [ + 3432269925 + 3432269925 + 3440074569 + 3440074568 + 3451368964 + 3453413513 + 3453413398 + 3325396245 + 3451368962 + 2987488002 + 3021618678 + 3021618674 + 3025625892 + 3052944039 + 3052944035 + 3079067192 + 3079067193 + 3079067193 + 3122287847 + 3122287842 + 3189405320 + 3189405320 + 3189405321 + 3189405321 + 3189405319 + 3189405319 + 3248171256 + 3248171256 + 3248171257 + 3248171257 + 3248171254 + 3291944265 + 3291944267 + 3291944267 + 3310943251 + 3387770449 + 3387770447 + 3432269929])) + (defn auth-header ([cob-session] (str "{cobSession=" cob-session "}")) ([cob-session user-session] (str "{cobSession=" cob-session ",userSession=" user-session "}"))) diff --git a/src/cljs/auto_ap/views/components/invoice_table.cljs b/src/cljs/auto_ap/views/components/invoice_table.cljs index a1f8dd4c..56969c77 100644 --- a/src/cljs/auto_ap/views/components/invoice_table.cljs +++ b/src/cljs/auto_ap/views/components/invoice_table.cljs @@ -20,31 +20,34 @@ [auto-ap.views.components.expense-accounts-dialog :as expense-accounts-dialog] [auto-ap.views.pages.data-page :as data-page])) +(defn data-params->query-params [params] + {:exact-match-id (some-> params :exact-match-id str) + :start (:start params 0) + :sort (:sort params) + :per-page (:per-page params) + + :vendor-id (:id (:vendor params)) + :date-range (:date-range params) + :due-range (:due-range params) + :amount-gte (:amount-gte (:amount-range params)) + :amount-lte (:amount-lte (:amount-range params)) + :location (:location params) + :unresolved (:unresolved params) + :scheduled-payments (:scheduled-payments params) + :invoice-number-like (:invoice-number-like params) + :client-id (:id @(re-frame/subscribe [::subs/client])) + :import-status (:import-status params) + :status (condp = @(re-frame/subscribe [::subs/active-page]) + :invoices nil + :import-invoices nil + :unpaid-invoices :unpaid + :paid-invoices :paid + :voided-invoices :voided)}) + (defn query [params] {:venia/queries [[:invoice_page - { - :exact-match-id (some-> params :exact-match-id str) - :start (:start params 0) - :sort (:sort params) - :per-page (:per-page params) - - :vendor-id (:id (:vendor params)) - :date-range (:date-range params) - :due-range (:due-range params) - :amount-gte (:amount-gte (:amount-range params)) - :amount-lte (:amount-lte (:amount-range params)) - :location (:location params) - :unresolved (:unresolved params) - :scheduled-payments (:scheduled-payments params) - :invoice-number-like (:invoice-number-like params) - :client-id (:id @(re-frame/subscribe [::subs/client])) - :import-status (:import-status params) - :status (condp = @(re-frame/subscribe [::subs/active-page]) - :invoices nil - :import-invoices nil - :unpaid-invoices :unpaid - :paid-invoices :paid - :voided-invoices :voided)} + {:filters (data-params->query-params params)} + [[:invoices [:id :total :outstanding-balance :invoice-number :date :due :status :client-identifier :scheduled-payment :source-url :similarity [:vendor [:name :id]] [:expense_accounts [:amount :id :location @@ -229,7 +232,7 @@ (defn invoice-table [{:keys [id check-boxes overrides actions data-page checkable-fn]}] (let [selected-client @(re-frame/subscribe [::subs/client]) - {:keys [data status table-params]} @(re-frame/subscribe [::data-page/page data-page]) + {:keys [data status params table-params]} @(re-frame/subscribe [::data-page/page data-page]) selected-client @(re-frame/subscribe [::subs/client]) is-loading? (= :loading (:state status)) @@ -261,7 +264,8 @@ ^{:key (or (:id (first invoices)) "init")} [grid/table {:fullwidth true} [grid/header {} - [grid/row {} + [grid/row {:id "header" + :entity params} (when-not selected-client [grid/sortable-header-cell {:sort-key "client" :sort-name "Client"} "Client"]) [grid/sortable-header-cell {:sort-key "vendor" :sort-name "Vendor"} diff --git a/src/cljs/auto_ap/views/pages/transactions/table.cljs b/src/cljs/auto_ap/views/pages/transactions/table.cljs index 4a4426f7..e1edf714 100644 --- a/src/cljs/auto_ap/views/pages/transactions/table.cljs +++ b/src/cljs/auto_ap/views/pages/transactions/table.cljs @@ -95,7 +95,6 @@ (for [{:keys [client account vendor approval-status payment expected-deposit status bank-account description-original date amount id yodlee-merchant ] :as i} (:data data)] ^{:key id} [grid/row {:class (:class i) :id id :entity i} - (println expected-deposit) (when-not selected-client [grid/cell {} (:name client)]) diff --git a/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs b/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs index ef754577..7de0cd07 100644 --- a/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs +++ b/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs @@ -1,38 +1,35 @@ (ns auto-ap.views.pages.unpaid-invoices - (:require [auto-ap.effects.forward :as forward] - [auto-ap.events :as events] - [auto-ap.forms :as forms] - [auto-ap.status :as status] - [auto-ap.subs :as subs] - [auto-ap.views.components.dropdown :refer [drop-down]] - [auto-ap.views.components.expense-accounts-dialog - :as - expense-accounts-dialog] - [auto-ap.views.components.invoice-table :as table] - [auto-ap.views.components.invoices.side-bar - :as - side-bar - :refer - [invoices-side-bar]] - [auto-ap.views.components.layouts - :refer - [appearing-side-bar side-bar-layout]] - [auto-ap.views.components.modal :as modal] - [auto-ap.views.pages.data-page :as data-page] - [auto-ap.views.pages.invoices.advanced-print-checks - :as - advanced-print-checks] - [auto-ap.views.pages.invoices.common :refer [invoice-read]] - [auto-ap.views.pages.invoices.form :as form] - [auto-ap.views.pages.invoices.handwritten-checks :as handwritten-checks] - [auto-ap.views.utils :refer [dispatch-event dispatch-event-with-propagation with-user]] - [clojure.set :as set] - [clojure.string :as str] - [goog.string :as gstring] - [re-frame.core :as re-frame] - [reagent.core :as r] - [vimsical.re-frame.fx.track :as track] - [auto-ap.views.components.buttons :as buttons])) + (:require + [auto-ap.effects.forward :as forward] + [auto-ap.events :as events] + [auto-ap.forms :as forms] + [auto-ap.status :as status] + [auto-ap.subs :as subs] + [auto-ap.views.components.buttons :as buttons] + [auto-ap.views.components.dropdown :refer [drop-down]] + [auto-ap.views.components.expense-accounts-dialog + :as expense-accounts-dialog] + [auto-ap.views.components.invoice-table :as table] + [auto-ap.views.components.invoices.side-bar + :as side-bar + :refer [invoices-side-bar]] + [auto-ap.views.components.layouts + :refer [appearing-side-bar side-bar-layout]] + [auto-ap.views.components.modal :as modal] + [auto-ap.views.pages.data-page :as data-page] + [auto-ap.views.pages.invoices.advanced-print-checks + :as advanced-print-checks] + [auto-ap.views.pages.invoices.common :refer [invoice-read]] + [auto-ap.views.pages.invoices.form :as form] + [auto-ap.views.pages.invoices.handwritten-checks :as handwritten-checks] + [auto-ap.views.utils + :refer [dispatch-event dispatch-event-with-propagation with-user]] + [clojure.set :as set] + [clojure.string :as str] + [goog.string :as gstring] + [re-frame.core :as re-frame] + [reagent.core :as r] + [vimsical.re-frame.fx.track :as track])) (re-frame/reg-event-fx ::params-change @@ -131,15 +128,68 @@ :status :unpaid #_#_:date (date->str (c/now) standard) :location (first (:locations @(re-frame/subscribe [::subs/client])))}]})) +(re-frame/reg-event-fx + ::voided-selected + (fn [cofx [_]] + {:dispatch-n [[::modal/modal-closed] + [::params-change @(re-frame/subscribe [::data-page/params ::page])]]})) +(re-frame/reg-event-fx + ::void-selected + (fn [cofx [_ which]] + (let [checked-params (get which "header") + specific-invoices (map :id (vals (dissoc which "header")))] + {:graphql {:token (-> cofx :db :user) + :owns-state {:single ::void-selected} + :query-obj + {:venia/operation {:operation/type :mutation + :operation/name "DeleteTransactions"} + :venia/queries [{:query/data + [:void-invoices + {:filters (some-> checked-params table/data-params->query-params) + :ids specific-invoices} + [:message]]}]} + :on-success (fn [result] + [::voided-selected])} + :dispatch [::data-page/reset-checked ::page]}))) + +(re-frame/reg-event-fx + ::void-selected-requested + (fn [_ [_ which]] + (let [to-delete (if (get which "header") + "all visible invoices" + (str (count which) " invoices"))] + + + {:dispatch [::modal/modal-requested {:title "Confirmation" + :body [:div (str "Are you sure you want to void " to-delete "?")] + :cancel? true + :confirm {:value "Void" + :class "is-danger" + :status-from [::status/single ::void-selected] + :on-click (dispatch-event [::void-selected which] )} + :close-event [::status/completed ::void-selected]}]}))) + +(defn void-selected-button [] + (let [status @(re-frame/subscribe [::status/single ::void-selected]) + checked-invoices @(re-frame/subscribe [::data-page/checked :invoices]) + is-admin? @(re-frame/subscribe [::subs/is-admin?])] + (when is-admin? + [:button.button.is-danger {:on-click (dispatch-event [::void-selected-requested checked-invoices]) + :class (status/class-for status) + :disabled (or (status/disabled-for status) + (not (seq checked-invoices)))} + "Void"]))) (defn pay-button [] (let [current-client @(re-frame/subscribe [::subs/client]) - checked-invoices (vals @(re-frame/subscribe [::data-page/checked :invoices])) + checked-invoices @(re-frame/subscribe [::data-page/checked :invoices]) print-checks-status @(re-frame/subscribe [::status/single ::print-checks])] [:div [:div.is-pulled-right [:div.buttons + [void-selected-button] + [buttons/new-button {:event [::new-invoice-clicked] :name "Invoice" :class "is-primary"}] @@ -172,7 +222,7 @@ (if (> balance 0.001) (list ^{: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 (status/disabled-for print-checks-status)} "Print checks from " name] ^{: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]) (list @@ -181,18 +231,23 @@ (when (> balance 0.001) ^{:key "advanced-divider"} [:hr.dropdown-divider]) - (when (and (= 1 (count (set (map (comp :id :vendor) checked-invoices)))) + (when (and (= 1 (count (set (map (comp :id :vendor) (vals 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 (vals checked-invoices)]) :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 (vals checked-invoices)]) :disabled (status/disabled-for print-checks-status)} "Advanced..."]))]]))]] [:div.is-pulled-right {:style {:margin-right "0.5rem"}} - (into [:div.tags ] (map (fn [{:keys [id invoice-number]}] - [:span.tag.is-medium invoice-number - [:button.delete.is-small {:on-click - (dispatch-event [::data-page/remove-check :invoices id])}]]) checked-invoices))]])) + (into [:div.tags ] (map (fn [[z {:keys [id invoice-number]}]] + (if (= z "header") + [:span.tag.is-medium "All visible invoices" + [:button.delete.is-small {:on-click + (dispatch-event [::data-page/remove-check :invoices z])}]] + [:span.tag.is-medium invoice-number + [:button.delete.is-small {:on-click + (dispatch-event [::data-page/remove-check :invoices id])}]])) + checked-invoices))]])) (defn unpaid-invoices-content [{:keys [status]}]