diff --git a/src/cljs/auto_ap/routes.cljs b/src/cljs/auto_ap/routes.cljs index 3e8b9886..7701f1e9 100644 --- a/src/cljs/auto_ap/routes.cljs +++ b/src/cljs/auto_ap/routes.cljs @@ -23,4 +23,5 @@ "transactions/" {"" :transactions} "ledger/" {"" :ledger "profit-and-loss" :profit-and-loss - "balance-sheet" :balance-sheet}}]) + "balance-sheet" :balance-sheet + "external-import" :external-import-ledger}}]) diff --git a/src/cljs/auto_ap/views/main.cljs b/src/cljs/auto_ap/views/main.cljs index 9367543a..7e036ce3 100644 --- a/src/cljs/auto_ap/views/main.cljs +++ b/src/cljs/auto_ap/views/main.cljs @@ -14,6 +14,7 @@ [auto-ap.views.pages.transactions :refer [transactions-page]] [auto-ap.views.pages.ledger :refer [ledger-page]] [auto-ap.views.pages.ledger.balance-sheet :refer [balance-sheet-page]] + [auto-ap.views.pages.ledger.external-import :refer [external-import-page]] [auto-ap.views.pages.ledger.profit-and-loss :refer [profit-and-loss-page]] [auto-ap.views.pages.login :refer [login-page]] [auto-ap.views.pages.checks :refer [checks-page]] @@ -86,6 +87,8 @@ (defmethod page :needs-activation [_] [needs-activation-page]) +(defmethod page :external-import-ledger [_] + [external-import-page]) (defmethod page :admin-excel-import [_] [admin-excel-import-page]) diff --git a/src/cljs/auto_ap/views/pages/ledger/balance_sheet.cljs b/src/cljs/auto_ap/views/pages/ledger/balance_sheet.cljs index 9b8fde33..56e058d4 100644 --- a/src/cljs/auto_ap/views/pages/ledger/balance_sheet.cljs +++ b/src/cljs/auto_ap/views/pages/ledger/balance_sheet.cljs @@ -63,7 +63,8 @@ ["2500 Other Liabilities" 2500 2599] ["2600 Split Accounts" 2600 2699] ["2700 Current Portion of Long-Term Debt" 2700 2799] - ["2800 Notes Payable" 2800 3000]]}) + ["2800 Notes Payable" 2800 3000] + ]}) (re-frame/reg-event-db ::received diff --git a/src/cljs/auto_ap/views/pages/ledger/external_import.cljs b/src/cljs/auto_ap/views/pages/ledger/external_import.cljs new file mode 100644 index 00000000..2c79a53e --- /dev/null +++ b/src/cljs/auto_ap/views/pages/ledger/external_import.cljs @@ -0,0 +1,87 @@ +(ns auto-ap.views.pages.ledger.external-import + (:require [auto-ap.subs :as subs] + [auto-ap.views.components.layouts :refer [side-bar-layout]] + [goog.string :as gstring] + [auto-ap.forms :as forms] + [auto-ap.utils :refer [by]] + [auto-ap.views.pages.ledger.side-bar :refer [ledger-side-bar]] + [auto-ap.views.utils :refer [date->str date-picker bind-field local-now standard ->$ str->date dispatch-event]] + [cljs-time.core :as t] + [re-frame.core :as re-frame] + [reagent.core :as r] + [clojure.string :as str])) + + +(re-frame/reg-sub + ::loading + (fn [db] + (-> db ::loading))) + + + +(defn textarea->table [{:keys [headings value on-change]} & children] + (let [text-form (r/atom "") + table-form (r/atom nil)] + (fn [{:keys [headings value on-change]}] + [:form.form + (if value + [:div + [:table.table + [:thead + [:tr + (list + (for [[heading-name _] headings] + [:th heading-name]))]] + (list + (for [row value] + [:tr + (list + (for [cell row] + [:td [:input.input {:value cell}]]))]))] + children] + [:div + [:h1.title.is-2 "External Import"] + [:div.field + [:p.help "Paste manual ledger entries below."] + [:textarea.textarea {:on-change #(reset! text-form (.. % -target -value))} @text-form]] + [:button.button.is-primary.is-pulled-right.is-large {:on-click (fn [e] + (.preventDefault e) + (on-change + (drop 1 + (mapv + #(str/split % "\t") + (str/split @text-form #"\n")))))} + "Evaluate"]])]))) + +(def balance-sheet-content + (with-meta + (fn [] + (let [current-client @(re-frame/subscribe [::subs/client]) + user @(re-frame/subscribe [::subs/user]) + {:keys [data active? error id]} @(re-frame/subscribe [::forms/form ::form]) ] + (if @(re-frame/subscribe [::loading]) + [:div [:i.icon.fa.fa-spin.fa-spinner]] + [:div + + [bind-field + [textarea->table {:type "textarea->table" + :field [::line-items] + :headings [["Id" :id] + ["Client" :client-code] + ["Source" :source] + ["Total" :amount] + ["Vendor" :vendor-id] + ["Date" :date] + ["Account" :account] + ["Location" :location] + ["Debit" :debit] + ["Credit" :credit]] + :event [::forms/change ::form] + :subscription data} + [:button.button.is-primary.is-pulled-right.is-large "Import"]]]]))) + {})) + +(defn external-import-page [] + [side-bar-layout + {:side-bar [ledger-side-bar] + :main [balance-sheet-content]}]) diff --git a/src/cljs/auto_ap/views/pages/ledger/profit_and_loss.cljs b/src/cljs/auto_ap/views/pages/ledger/profit_and_loss.cljs index f94dbeaf..6b798396 100644 --- a/src/cljs/auto_ap/views/pages/ledger/profit_and_loss.cljs +++ b/src/cljs/auto_ap/views/pages/ledger/profit_and_loss.cljs @@ -35,7 +35,6 @@ (re-frame/reg-sub ::accounts (fn [db [_ type only-location]] - (println (::report db)) (->> db ::report :balance-sheet-accounts @@ -162,7 +161,7 @@ (defn grouping [{:keys [header accounts comparable-accounts groupings]}] - (println accounts) + (for [[grouping-name from to] groupings :let [matching-accounts (filter #(<= from (:numeric-code %) to) diff --git a/src/cljs/auto_ap/views/pages/ledger/side_bar.cljs b/src/cljs/auto_ap/views/pages/ledger/side_bar.cljs index 55d26c10..da1bcb1d 100644 --- a/src/cljs/auto_ap/views/pages/ledger/side_bar.cljs +++ b/src/cljs/auto_ap/views/pages/ledger/side_bar.cljs @@ -6,7 +6,8 @@ [re-frame.core :as re-frame])) (defn ledger-side-bar [] - (let [ap @(re-frame/subscribe [::subs/active-page])] + (let [ap @(re-frame/subscribe [::subs/active-page]) + user @(re-frame/subscribe [::subs/user])] [:div [:ul.menu-list @@ -29,4 +30,9 @@ [:span {:class "icon icon-accounting-abacus" :style {:font-size "25px"}}] [:span {:class "name"} "Balance Sheet"]]] - ]])) + (when (= "admin" (:user/role user)) + [:li.menu-item + [:a.item {:href (bidi/path-for routes/routes :external-import-ledger) + :class [(active-when ap = :external-import-ledger)]} + [:span.icon [:i {:class "fa fa-download"}]] + [:span {:class "name"} "External Import"]]])]])) diff --git a/src/cljs/auto_ap/views/utils.cljs b/src/cljs/auto_ap/views/utils.cljs index 4cb0ce6b..4a1b09f3 100644 --- a/src/cljs/auto_ap/views/utils.cljs +++ b/src/cljs/auto_ap/views/utils.cljs @@ -173,6 +173,22 @@ keys (dissoc keys :field :subscription :event :spec)] (into [dom keys] (with-keys rest)))) +(defmethod do-bind "textarea->table" [dom {:keys [field event subscription class spec] :as keys :or {precision 2}} & rest] + (let [field (if (keyword? field) [field] field) + event (if (keyword? event) [event] event) + keys (assoc keys + :on-change (fn [x] + (re-frame/dispatch (-> event + (conj field) + (conj x)))) + :value (get-in subscription field) + + :class (str class + (when (and spec (not (s/valid? spec (get-in subscription field)))) + " is-danger"))) + keys (dissoc keys :field :subscription :event :spec)] + (into [dom keys] (with-keys rest)))) + (defmethod do-bind :default [dom {:keys [field event subscription class spec] :as keys} & rest] (let [field (if (keyword? field) [field] field) event (if (keyword? event) [event] event)