(ns auto-ap.subs (:require [re-frame.core :as re-frame] [auto-ap.utils :refer [by]] [clojure.string :as str] [goog.crypt.base64 :as base64] [minisearch :as ms])) (set! *warn-on-infer* true) (def MiniSearch (if ms (aget ms "default") nil)) (re-frame/reg-sub ::client (fn [db] (get (:clients db) (:client db)))) (re-frame/reg-sub ::clients (fn [db] (when (:user db) (sort-by :name (vals (:clients db)))))) (re-frame/reg-sub ::all-accounts (fn [db] (:accounts db))) (re-frame/reg-sub ::all-accounts-by-id (fn [db] (by :id (:accounts db)))) (defn clientize-account [account client] (let [override (->> (:client-overrides account) (filter (fn [co] (= (:id (:client co)) (:id client)))) first)] (condp = (:applicability account) nil (assoc account :name (or (:name override) (:name account))) :global (assoc account :name (or (:name override) (:name account))) :optional (when override (assoc account :name (or (:name override) (:name account)))) :customized (when override (assoc account :name (or (:name override) (:name account))))))) (re-frame/reg-sub ::accounts :<- [::all-accounts] :<- [::client] (fn [[accounts client] [_ client-override]] (transduce (comp (map #(clientize-account % (or client-override client))) (filter identity)) conj [] accounts))) (re-frame/reg-sub ::accounts-index :<- [::accounts] (fn [accounts] (doto (MiniSearch. #js {:fields #js ["numeric-code" "name" "content"] :storeFields #js ["id" "numeric-code" "name" "content"]}) (.addAll (clj->js (map (fn [v] {:id (:id v) :name (:name v) :numeric-code (:numeric-code v) :content (str (:numeric-code v) " " (:name v))}) accounts)))))) (re-frame/reg-sub ::account (fn [[_ client]] [(re-frame/subscribe [::accounts-by-id client])]) (fn [[as] [_ _ i]] (as i))) (defn accounts-by-id [accounts client] (by :id (map #(clientize-account % client) accounts))) (re-frame/reg-sub ::accounts-by-id (fn [[_ client-override]] [(re-frame/subscribe [::accounts client-override]) (re-frame/subscribe [::client])]) (fn [[accounts client] ] (accounts-by-id accounts client))) (re-frame/reg-sub ::bank-accounts :<- [::clients] :<- [::client] (fn [[clients client]] (if client (:bank-accounts client) (reduce (fn [result {:keys [bank-accounts]}] (into result bank-accounts)) [] clients)))) (re-frame/reg-sub ::bank-accounts-by-id :<- [::bank-accounts] (fn [as] (by :id as))) ;; Bank accounts only, not including cash (re-frame/reg-sub ::real-bank-accounts :<- [::client] (fn [client] (->> client :bank-accounts (filter #(= (:type %) :check)) (sort-by :sort-order)))) (re-frame/reg-sub ::real-bank-accounts-for-client (fn [db [_ {:keys [id]}]] (sort-by :sort-order (-> db :clients (get id) :bank-accounts )))) (re-frame/reg-sub ::locations-for-client (fn [db [_ client]] (:locations (get (:clients db) (or client (:client db)))))) (re-frame/reg-sub ::forecasted-transactions-for-client (fn [db [_ client]] (:forecasted-transactions (get (:clients db) (or client (:client db)))))) (re-frame/reg-sub ::locations-for-client-or-bank-account (fn [db [_ client-id bank-account-id]] (let [client (get (:clients db) (or client-id (:client db))) client-locations (:locations client) bank-account-locations (-> (by :id (:bank-accounts client)) (get bank-account-id) :locations)] (or (seq bank-account-locations) client-locations)))) (re-frame/reg-sub ::clients-by-id (fn [db] (when (:user db) (:clients db)))) (re-frame/reg-sub ::menu-active? (fn [db [_ id]] (-> db :menu (get id) :active?))) (re-frame/reg-sub ::menu (fn [db] (:menu db))) (re-frame/reg-sub ::is-initial-loading? (fn [db] (:is-initial-loading? db))) (re-frame/reg-sub ::modal-state (fn [db [_ id status-from]] (if status-from (assoc (get (:modal-state db) id) :error-message (get-in db [:auto-ap.forms/forms status-from :error]) :saving? (= (get-in db [:auto-ap.forms/forms status-from :status]) :loading)) (get (:modal-state db) id)))) (re-frame/reg-sub ::token (fn [db] (:user db))) (re-frame/reg-sub ::vendors :<- [::is-admin?] :<- [::all-vendors] (fn [[is-admin all-vendors]] (filter #(or (not (:hidden %)) is-admin) all-vendors))) (re-frame/reg-sub ::searchable-vendors :<- [::is-admin?] :<- [::client] :<- [::all-vendors] (fn [[is-admin client all-vendors]] (cond is-admin all-vendors client (filter (fn [{:keys [hidden usage name] :as vendor}] (or (not hidden) (-> (first (filter #(= (:client-id %) (:id client)) usage)) (:count 0) (> 0)))) all-vendors) :else (filter #(not (:hidden %)) all-vendors)))) (re-frame/reg-sub ::searchable-vendors-index :<- [::searchable-vendors] (fn [searchable-vendors] (doto (MiniSearch. #js {:fields #js ["name" "content"] :storeFields #js ["id" "name" "content" "usage"]}) (.addAll (clj->js (map (fn [v] {:id (:id v) :name (:name v) :content (:name v) :usage (:usage v)}) searchable-vendors)))))) (re-frame/reg-sub ::all-vendors-index :<- [::all-vendors] (fn [all-vendors] (doto (MiniSearch. #js {:fields #js ["name" "content"] :storeFields #js ["id" "name" "content" "usage"]}) (.addAll (clj->js (map (fn [v] {:id (:id v) :name (:name v) :content (:name v) :usage (:usage v)}) all-vendors)))))) (re-frame/reg-sub ::all-vendors (fn [db] (vals (:vendors db)))) (re-frame/reg-sub ::vendors-by-id (fn [db] (:vendors db))) (re-frame/reg-sub ::vendor-default-account (fn [db [_ v client]] (let [accounts (accounts-by-id (:accounts db) client) vendor (if (map? v) v (-> (:vendors db) (get v))) client-override (->> (:account-overrides vendor) (filter #(= (:id (:client %)) (:id client)) ) first :account :id) default-id (:id (:default-account vendor)) i (or client-override default-id)] (accounts i)))) (re-frame/reg-sub ::sorted-vendors :<- [::vendors] (fn [vendors] (sort-by :name vendors))) (re-frame/reg-sub ::sorted-all-vendors :<- [::all-vendors] (fn [all-vendors] (sort-by :name all-vendors))) (re-frame/reg-sub ::admin (fn [db] (:admin db))) (re-frame/reg-sub ::is-admin? :<- [::user] (fn [user] (= "admin" (:user/role user)))) (re-frame/reg-sub ::is-power-user? :<- [::user] (fn [user] (or (= "power-user" (:user/role user)) (= "power_user" (:user/role user))))) (re-frame/reg-sub ::user (fn [db] (when (:user db) (js->clj (.parse js/JSON (base64/decodeString (second (str/split (:user db) #"\.")))) :keywordize-keys true)))) (re-frame/reg-sub ::active-page (fn [db] (:active-page db))) (re-frame/reg-sub ::pending-invoices (fn [db] (:pending (:invoices db)))) (re-frame/reg-sub ::status (fn [db] (:status db))) (re-frame/reg-sub ::new-invoice-form (fn [db] (:new-invoice db))) (re-frame/reg-sub ::query-params (fn [db] (:query-params db))) (re-frame/reg-sub ::page-failure (fn [db] (when-let [error (-> db :page-failure first)] (if (= 500 (:status error)) "System error occured. If you are stuck, please notify ben@integreatconsult.com." (:message error))))) (re-frame/reg-sub ::yodlee-merchants (fn [db] (:yodlee-merchants db)))