fixed excel import
This commit is contained in:
@@ -270,8 +270,18 @@
|
|||||||
(not can-submit))}]])))
|
(not can-submit))}]])))
|
||||||
|
|
||||||
(defn error-notification []
|
(defn error-notification []
|
||||||
(consume Consumer ["error"]
|
(consume Consumer ["error" "status"]
|
||||||
(fn [error]
|
(fn [error status]
|
||||||
(when error
|
(println status)
|
||||||
|
(cond error
|
||||||
^{:key error}
|
^{:key error}
|
||||||
[:div.has-text-danger.animated.fadeInUp {} error]))))
|
[:div.has-text-danger.animated.fadeInUp {} error]
|
||||||
|
|
||||||
|
(-> status :error first :message)
|
||||||
|
[:div.has-text-danger.animated.fadeInUp {} (-> status :error first :message)]
|
||||||
|
|
||||||
|
(-> status :error)
|
||||||
|
[:div.has-text-danger.animated.fadeInUp {} (-> status :error str)]
|
||||||
|
|
||||||
|
:else
|
||||||
|
nil))))
|
||||||
|
|||||||
@@ -3,11 +3,6 @@
|
|||||||
[auto-ap.views.utils :refer [bind-field]]
|
[auto-ap.views.utils :refer [bind-field]]
|
||||||
[re-frame.core :as re-frame]))
|
[re-frame.core :as re-frame]))
|
||||||
|
|
||||||
(defn dispatch-change [on-change-event start end]
|
|
||||||
(fn [_]
|
|
||||||
(re-frame/dispatch (into on-change-event [[:start] start]) )
|
|
||||||
(re-frame/dispatch (into on-change-event [[:end] end]))))
|
|
||||||
|
|
||||||
(defn number-filter [{:keys [value on-change-event]}]
|
(defn number-filter [{:keys [value on-change-event]}]
|
||||||
[:div.field
|
[:div.field
|
||||||
[:div.control
|
[:div.control
|
||||||
|
|||||||
@@ -1,168 +1,115 @@
|
|||||||
(ns auto-ap.views.pages.admin.excel-import
|
(ns auto-ap.views.pages.admin.excel-import
|
||||||
(:require [auto-ap.events :as all-events]
|
(:require
|
||||||
[auto-ap.forms :as forms]
|
[auto-ap.forms :as forms]
|
||||||
[auto-ap.subs :as subs]
|
[auto-ap.forms.builder :as form-builder]
|
||||||
[auto-ap.views.components.admin.side-bar :refer [admin-side-bar]]
|
[auto-ap.schema :as schema]
|
||||||
[auto-ap.views.components.layouts :refer [side-bar-layout]]
|
[auto-ap.views.components :as com]
|
||||||
[auto-ap.views.components.typeahead :refer [typeahead-v3]]
|
[auto-ap.views.components.admin.side-bar :refer [admin-side-bar]]
|
||||||
[auto-ap.views.utils :refer [bind-field dispatch-event]]
|
[auto-ap.views.components.layouts :refer [side-bar-layout]]
|
||||||
[re-frame.core :as re-frame]))
|
[auto-ap.views.utils :refer [with-user]]
|
||||||
|
[malli.core :as m]
|
||||||
(re-frame/reg-sub
|
[re-frame.core :as re-frame]
|
||||||
::excel-import
|
[reagent.core :as r]))
|
||||||
(fn [db]
|
|
||||||
(::excel-import db)))
|
|
||||||
|
|
||||||
(re-frame/reg-sub
|
|
||||||
::expense-accounts
|
|
||||||
(fn [db]
|
|
||||||
(::expense-accounts db)))
|
|
||||||
|
|
||||||
(re-frame/reg-event-db
|
|
||||||
::change
|
|
||||||
(fn [db [_ field v]]
|
|
||||||
(assoc-in db (into [::excel-import] field) v)))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(re-frame/reg-event-fx
|
(re-frame/reg-event-fx
|
||||||
::save
|
::save
|
||||||
[(forms/in-form ::excel-import)]
|
[ with-user (forms/in-form ::form)]
|
||||||
(fn [{{excel-import-data :data :as excel-import-form} :db}]
|
(fn [{:keys [db user]}]
|
||||||
(let [user @(re-frame/subscribe [::subs/token])]
|
{
|
||||||
{:db (-> excel-import-form
|
:http {:token user
|
||||||
(assoc :status :loading)
|
:method :post
|
||||||
(assoc :error nil))
|
:body (pr-str {:excel-rows (:excel-rows (:data db))})
|
||||||
:http {:token user
|
:headers {"Content-Type" "application/edn"}
|
||||||
:method :post
|
:uri (str "/api/invoices/upload-integreat")
|
||||||
:body (pr-str excel-import-data)
|
:owns-state {:single ::form}
|
||||||
:headers {"Content-Type" "application/edn"}
|
:on-success [::save-complete]}}))
|
||||||
:uri (str "/api/invoices/upload-integreat")
|
|
||||||
:on-success [::save-complete]
|
|
||||||
:on-error [::forms/save-error ::excel-import]}})))
|
|
||||||
|
|
||||||
(re-frame/reg-event-fx
|
(re-frame/reg-event-fx
|
||||||
::save-complete
|
::save-complete
|
||||||
(fn [{:keys [db]} [_ rows]]
|
(fn [{:keys [db]} [_ rows]]
|
||||||
{:db
|
(cond->
|
||||||
(-> db
|
{:db (assoc db ::result rows)}
|
||||||
(forms/save-succeeded ::excel-import)
|
(seq (:vendors-not-found rows)) (assoc :dispatch [::forms/start-form ::create-vendors ]))))
|
||||||
(assoc-in [::excel-import :rows] rows))}))
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
::result
|
||||||
|
(fn [db]
|
||||||
|
(::result db)))
|
||||||
|
|
||||||
(re-frame/reg-event-fx
|
|
||||||
::save-error
|
|
||||||
(fn [{:keys [db]}]
|
|
||||||
(println "ERROR")
|
|
||||||
{:dispatch [::change [:error] true]
|
|
||||||
:db (-> db
|
|
||||||
(assoc-in [::excel-import :rows] nil)
|
|
||||||
(assoc-in [::excel-import :saving?] false))}))
|
|
||||||
|
|
||||||
(re-frame/reg-event-db
|
|
||||||
::toggle-vendor
|
|
||||||
(fn [db [_ data]]
|
|
||||||
(update-in db [::excel-import :create-vendors] (fn [x]
|
|
||||||
(let [x (or x #{})]
|
|
||||||
(if (x data)
|
|
||||||
(disj x data)
|
|
||||||
(conj x data)))))))
|
|
||||||
(re-frame/reg-event-fx
|
(re-frame/reg-event-fx
|
||||||
::create-vendors
|
::create-vendors
|
||||||
(fn [{:keys [db]}]
|
[with-user (forms/in-form ::create-vendors)]
|
||||||
(let [excel-import (::excel-import db)]
|
(fn [{:keys [user db]}]
|
||||||
(println (::expense-accounts db))
|
{:graphql {:token user
|
||||||
{:graphql {:token (:user db)
|
:owns-state {:single ::create-vendors}
|
||||||
:query-obj {:venia/operation {:operation/type :mutation
|
:query-obj {:venia/operation {:operation/type :mutation
|
||||||
:operation/name "UpsertVendor"}
|
:operation/name "UpsertVendor"}
|
||||||
|
|
||||||
:venia/queries (map (fn [v ]
|
:venia/queries
|
||||||
{:query/data [:upsert-vendor
|
(for [[vendor-name {:keys [default-account]}] (:data db)]
|
||||||
{:vendor {:name v :default-account-id (-> db ::expense-accounts (get v) :default-account-id :id)}}
|
{:query/data [:upsert-vendor
|
||||||
[:id :name]]})
|
{:vendor {:name vendor-name :default-account-id (:id default-account)}}
|
||||||
|
[:id :name]]})}
|
||||||
(get-in db [::excel-import :create-vendors]))}
|
:on-success [::create-vendor-complete]}}))
|
||||||
:on-success [::create-vendor-complete]
|
|
||||||
:on-error [::create-vendor-error]}
|
|
||||||
:db (-> db
|
|
||||||
(assoc-in [::excel-import :saving-vendors?] true))})))
|
|
||||||
|
|
||||||
|
|
||||||
(re-frame/reg-event-db
|
(re-frame/reg-event-db
|
||||||
::create-vendor-complete
|
::create-vendor-complete
|
||||||
(fn [db [_ data]]
|
(fn [db _]
|
||||||
(-> db
|
(dissoc db ::result )))
|
||||||
(update-in [::excel-import :rows :vendors-not-found]
|
|
||||||
(fn [v]
|
(def missing-vendor-schema
|
||||||
(reduce disj v (get-in db [::excel-import :create-vendors]))))
|
(m/schema [:map-of :string
|
||||||
(update-in [::excel-import] dissoc :create-vendors))))
|
[:map
|
||||||
|
[:default-account schema/reference]]]))
|
||||||
|
|
||||||
|
(defn create-missing-vendors [{:keys [vendors]}]
|
||||||
|
(let [{:keys [data]} @(re-frame/subscribe [::forms/form ::create-vendors])
|
||||||
|
vendors-to-create (filter (fn [v] (:checked v))
|
||||||
|
(vals data))]
|
||||||
|
[form-builder/builder {:id ::create-vendors
|
||||||
|
:submit-event [::create-vendors]
|
||||||
|
:schema missing-vendor-schema}
|
||||||
|
[:article.message.is-warning.is-paddingless
|
||||||
|
[:div.message-header
|
||||||
|
"Some vendors could not be found"]
|
||||||
|
|
||||||
|
[:div.message-body
|
||||||
|
[:h2 "Check the vendors you want to create"]
|
||||||
|
(for [v vendors]
|
||||||
|
^{:key v}
|
||||||
|
[:div.field.is-grouped
|
||||||
|
[:div.control
|
||||||
|
[form-builder/raw-field-v2 {:field [v :checked]}
|
||||||
|
[com/checkbox {:label v}]]]
|
||||||
|
|
||||||
|
[:div.control
|
||||||
|
[form-builder/raw-field-v2 {:field [v :default-account]}
|
||||||
|
[com/search-backed-typeahead {:search-query (fn [i]
|
||||||
|
[:search_account
|
||||||
|
{:query i}
|
||||||
|
[:name :id :location]])}]]]])
|
||||||
|
[form-builder/error-notification]
|
||||||
|
[form-builder/submit-button {:disabled (when-not (seq vendors-to-create) "disabled")}
|
||||||
|
(str "Create " (count vendors-to-create) " vendors")]
|
||||||
|
[:div.is-clearfix]]]]))
|
||||||
|
|
||||||
(defn admin-excel-import-content []
|
(defn admin-excel-import-content []
|
||||||
[:div
|
[:div
|
||||||
(let [{{:keys [vendors-not-found already-imported imported]} :rows
|
(let [{:keys [vendors-not-found errors already-imported imported]} @(re-frame/subscribe [::result])]
|
||||||
:keys [create-vendors]
|
|
||||||
:or {create-vendors #{}}
|
|
||||||
:as excel-import-data} @(re-frame/subscribe [::excel-import])
|
|
||||||
data @(re-frame/subscribe [::expense-accounts])
|
|
||||||
form @(re-frame/subscribe [::forms/form ::excel-import])
|
|
||||||
|
|
||||||
|
|
||||||
chooseable-expense-accounts @(re-frame/subscribe [::subs/all-accounts])
|
|
||||||
change-event [::all-events/change-form [::expense-accounts]]]
|
|
||||||
[:div
|
[:div
|
||||||
[:h1.title "Import Invoices from Integreat Excel"]
|
[:h1.title "Import Invoices from Integreat Excel"]
|
||||||
(when (seq vendors-not-found)
|
(when (seq vendors-not-found)
|
||||||
[:article.message.is-warning.is-paddingless
|
[create-missing-vendors {:vendors vendors-not-found}]
|
||||||
[:div.message-header
|
)
|
||||||
"Some vendors could not be found"]
|
[form-builder/builder {:id ::form
|
||||||
|
:submit-event [::save]}
|
||||||
[:div.message-body
|
[form-builder/raw-field-v2 {:field :excel-rows}
|
||||||
[:h2 "Check the vendors you want to create"]
|
[:textarea.textarea {:rows "20"
|
||||||
[:div.columns
|
:type "text"}]]
|
||||||
(for [[i vendor-group] (map vector (range) (partition-all (max 1 (/ (count vendors-not-found) 3)) vendors-not-found))]
|
[form-builder/error-notification]
|
||||||
^{:key i}
|
[form-builder/submit-button "Import"]]
|
||||||
[:div.column
|
|
||||||
(for [v vendor-group]
|
|
||||||
^{:key v} [:div.field.is-grouped
|
|
||||||
[:p.control
|
|
||||||
[:label.checkbox
|
|
||||||
[:input {:value v
|
|
||||||
:checked (if (create-vendors v)
|
|
||||||
"checked"
|
|
||||||
"")
|
|
||||||
|
|
||||||
:type "checkbox"
|
|
||||||
:on-change (fn []
|
|
||||||
(re-frame/dispatch [::toggle-vendor v]))}]
|
|
||||||
(str " " v)]]
|
|
||||||
|
|
||||||
[:p.control
|
|
||||||
[bind-field
|
|
||||||
[typeahead-v3 {:entities chooseable-expense-accounts
|
|
||||||
:entity->text (fn [x ] (str (:numeric-code x) " - " (:name x)))
|
|
||||||
:type "typeahead-v3"
|
|
||||||
:field [v :default-account-id]
|
|
||||||
:event change-event
|
|
||||||
:subscription data}]]]])])]
|
|
||||||
[:div
|
|
||||||
[:button.button.is-pulled-right
|
|
||||||
{:on-click (dispatch-event [::create-vendors])
|
|
||||||
:disabled (when-not (seq create-vendors)
|
|
||||||
"disabled")
|
|
||||||
}
|
|
||||||
(str "Create " (count create-vendors) " vendors")]]
|
|
||||||
[:div.is-clearfix]]])
|
|
||||||
[bind-field
|
|
||||||
[:textarea.textarea {:rows "20"
|
|
||||||
:field :excel-rows
|
|
||||||
:type "text"
|
|
||||||
:event [::forms/change ::excel-import]
|
|
||||||
:subscription (:data form)}]]
|
|
||||||
|
|
||||||
[:button.button.is-large.is-pulled-right.is-primary {:on-click (dispatch-event [::save])
|
|
||||||
:class (str @(re-frame/subscribe [::forms/loading-class ::excel-import])
|
|
||||||
(when (:error form) " animated shake"))
|
|
||||||
:disabled (when (= :saving (:status form)) "disabled")} "Import"]
|
|
||||||
|
|
||||||
[:div.is-clearfix]
|
[:div.is-clearfix]
|
||||||
[:div.is-clearfix
|
[:div.is-clearfix
|
||||||
[:p
|
[:p
|
||||||
@@ -171,29 +118,49 @@
|
|||||||
[:p
|
[:p
|
||||||
(when already-imported
|
(when already-imported
|
||||||
(str already-imported " rows already imported."))]]
|
(str already-imported " rows already imported."))]]
|
||||||
(when-let [errors (:errors (:rows excel-import-data))]
|
(when errors
|
||||||
[:div
|
[:div
|
||||||
[:h3 (str "Import errors (" (min 100 (count errors)) " / " (count errors) " )")]
|
[:h3 (str "Import errors (" (min 100 (count errors)) " / " (count errors) " )")]
|
||||||
[:table.table.is-fullwidth
|
[:table.table.is-fullwidth
|
||||||
[:thead
|
[:thead
|
||||||
[:th "Date"]
|
[:td "Date"]
|
||||||
[:th "Invoice #"]
|
[:td "Invoice #"]
|
||||||
[:th "Client"]
|
[:td "Client"]
|
||||||
[:th "Vendor"]
|
[:td "Vendor"]
|
||||||
[:th "Amount"]
|
[:td "Amount"]
|
||||||
[:th "Errors"]]
|
[:td "Errors"]]
|
||||||
|
|
||||||
(for [{:keys [raw-date invoice-number client vendor-name amount] row-errors :errors} (take 100 errors)]
|
[:tbody
|
||||||
^{:key (str raw-date invoice-number client vendor-name amount)}
|
(for [{:keys [raw-date invoice-number client vendor-name amount] row-errors :errors} (take 100 errors)]
|
||||||
[:tr
|
^{:key (str raw-date invoice-number client vendor-name amount)}
|
||||||
[:td raw-date]
|
[:tr
|
||||||
[:td invoice-number]
|
[:td raw-date]
|
||||||
[:td client]
|
[:td invoice-number]
|
||||||
[:td vendor-name]
|
[:td client]
|
||||||
[:td amount]
|
[:td vendor-name]
|
||||||
[:td (map (fn [{:keys [info]}] ^{:key info} [:p info]) row-errors)]])]])])])
|
[:td amount]
|
||||||
|
[:td (map (fn [{:keys [info]}] ^{:key info} [:p info]) row-errors)]])]]])])])
|
||||||
|
|
||||||
|
|
||||||
(defn admin-excel-import-page []
|
(defn admin-excel-import-page-internal []
|
||||||
[side-bar-layout {:side-bar [admin-side-bar {}]
|
[side-bar-layout {:side-bar [admin-side-bar {}]
|
||||||
:main [admin-excel-import-content]}])
|
:main [admin-excel-import-content]}])
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
::mounted
|
||||||
|
(fn [_ _]
|
||||||
|
{:dispatch [::forms/start-form ::form]}))
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
::unmounted
|
||||||
|
(fn [{:keys [db]} _]
|
||||||
|
{:dispatch-n [[::forms/form-closing ::form]
|
||||||
|
[::forms/form-closing ::create-vendors]]
|
||||||
|
:db (dissoc db ::results)}))
|
||||||
|
|
||||||
|
(defn admin-excel-import-page []
|
||||||
|
(r/create-class
|
||||||
|
{:display-name "excel-import-page"
|
||||||
|
:component-will-unmount #(re-frame/dispatch-sync [::unmounted])
|
||||||
|
:component-did-mount #(re-frame/dispatch [::mounted])
|
||||||
|
:reagent-render admin-excel-import-page-internal}))
|
||||||
|
|||||||
Reference in New Issue
Block a user