company 1099 works
This commit is contained in:
@@ -1,17 +1,32 @@
|
||||
(ns auto-ap.ssr.company.company-1099
|
||||
(:require
|
||||
[auto-ap.datomic :refer [apply-pagination-raw conn remove-nils]]
|
||||
[auto-ap.graphql.utils
|
||||
:refer [assert-can-see-client extract-client-ids is-admin?]]
|
||||
[auto-ap.datomic :refer [apply-pagination-raw conn]]
|
||||
[auto-ap.graphql.utils :refer [assert-can-see-client]]
|
||||
[auto-ap.routes.utils
|
||||
:refer [wrap-client-redirect-unauthenticated wrap-secure]]
|
||||
[auto-ap.ssr-routes :as ssr-routes]
|
||||
[auto-ap.ssr.components :as com]
|
||||
[auto-ap.ssr.form-cursor :as fc]
|
||||
[auto-ap.ssr.grid-page-helper :as helper]
|
||||
[auto-ap.ssr.nested-form-params :refer [wrap-nested-form-params]]
|
||||
[auto-ap.ssr.svg :as svg]
|
||||
[auto-ap.ssr.utils :refer [form-data->map html-response path->name]]
|
||||
[auto-ap.ssr.utils
|
||||
:refer [apply-middleware-to-all-handlers
|
||||
entity-id
|
||||
html-response
|
||||
main-transformer
|
||||
modal-response
|
||||
ref->enum-schema
|
||||
ref->select-options
|
||||
strip
|
||||
wrap-entity
|
||||
wrap-form-4xx-2
|
||||
wrap-schema-decode]]
|
||||
[bidi.bidi :as bidi]
|
||||
[cemerick.url :as url]
|
||||
[clojure.string :as str]
|
||||
[datomic.api :as dc]))
|
||||
[datomic.api :as dc]
|
||||
[hiccup.util :refer [url]]
|
||||
[malli.core :as mc]))
|
||||
|
||||
(def vendor-read '[:db/id
|
||||
:vendor/name
|
||||
@@ -74,7 +89,7 @@
|
||||
|
||||
(def grid-page
|
||||
(helper/build
|
||||
{:id "vendor-table"
|
||||
{:id "entity-table"
|
||||
:nav (com/company-aside-nav)
|
||||
:id-fn (comp :db/id second)
|
||||
:fetch-page fetch-page
|
||||
@@ -89,14 +104,10 @@
|
||||
:entity-name "Vendors"
|
||||
:route :company-1099-vendor-table
|
||||
:row-buttons (fn [request e]
|
||||
[(com/icon-button {:hx-get (str (bidi/path-for ssr-routes/only-routes
|
||||
[(com/icon-button {:hx-get (url (bidi/path-for ssr-routes/only-routes
|
||||
:company-1099-vendor-dialog
|
||||
:vendor-id (:db/id (second e)))
|
||||
"?"
|
||||
(url/map->query {:client-id (:db/id (first e))}))
|
||||
:hx-ext "debug"
|
||||
:hx-target "#modal-holder"
|
||||
:hx-swap "outerHTML"}
|
||||
{:client-id (:db/id (first e))})}
|
||||
svg/pencil)])
|
||||
:headers [{:key "Client"
|
||||
:name "Client"
|
||||
@@ -161,117 +172,200 @@
|
||||
(def table* (partial helper/table* grid-page))
|
||||
(def row* (partial helper/row* grid-page))
|
||||
|
||||
(defn vendor-save [{:keys [form-params identity route-params query-params] :as request}]
|
||||
(let [client-id (Long/parseLong (get query-params "client-id"))
|
||||
vendor-id (Long/parseLong (:vendor-id route-params))]
|
||||
(assert-can-see-client identity client-id)
|
||||
@(dc/transact conn [(remove-nils
|
||||
(-> (form-data->map form-params)
|
||||
(assoc :db/id (Long/parseLong (:vendor-id route-params)))
|
||||
(update :vendor/legal-entity-1099-type #(some->> % not-empty (keyword "legal-entity-1099-type")))
|
||||
(update :vendor/legal-entity-tin-type #(some->> % not-empty (keyword "legal-entity-tin-type")))))])
|
||||
(html-response
|
||||
(defn vendor-save [{:keys [form-params identity route-params query-params request-method] :as request
|
||||
{:keys [vendor-id]} :route-params
|
||||
{:keys [client-id]} :query-params}]
|
||||
|
||||
(row* identity [(dc/pull (dc/db conn) [:db/id :client/code] client-id)
|
||||
(dc/pull (dc/db conn) vendor-read vendor-id)
|
||||
(sum-for-client-vendor client-id vendor-id)
|
||||
] {:flash? true})
|
||||
:headers {"hx-trigger" "closeModal"})))
|
||||
(assert-can-see-client identity client-id)
|
||||
@(dc/transact conn [[:upsert-entity (assoc form-params :db/id (:vendor-id route-params))]])
|
||||
(html-response
|
||||
|
||||
(defn vendor-dialog [request]
|
||||
(let [vendor (dc/pull (dc/db conn) '[* {:vendor/legal-entity-1099-type [:db/ident]
|
||||
:vendor/legal-entity-tin-type [:db/ident]}] (Long/parseLong (:vendor-id (:params request))))] ;; TODO perms
|
||||
(html-response
|
||||
(row* identity [(dc/pull (dc/db conn) [:db/id :client/code] client-id)
|
||||
(dc/pull (dc/db conn) vendor-read vendor-id)
|
||||
(sum-for-client-vendor client-id vendor-id)
|
||||
] {:flash? true})
|
||||
:headers {"hx-trigger" "modalclose"
|
||||
"hx-retarget" (format "#entity-table tr[data-id=\"%d\"]" vendor-id)}))
|
||||
|
||||
(def default-vendor-read '[* {[:vendor/legal-entity-1099-type :xform iol-ion.query/ident] [:db/ident]
|
||||
[:vendor/legal-entity-tin-type :xform iol-ion.query/ident] [:db/ident]}])
|
||||
|
||||
|
||||
(def form-schema (mc/schema [:map
|
||||
[:vendor/address {:default {} }
|
||||
[:maybe
|
||||
[:map
|
||||
[:db/id {:optional true} [:maybe entity-id]]
|
||||
[:address/street1 {:optional true} [:maybe [:string {:decode/string strip}]]]
|
||||
[:address/street2 {:optional true} [:maybe [:string {:decode/string strip}]]]
|
||||
[:address/city {:optional true} [:maybe [:string {:decode/string strip}]]]
|
||||
[:address/state {:optional true} [:maybe [:string {:decode/string strip}]]]
|
||||
[:address/zip {:optional true} [:maybe [:re { :error/message "invalid zip"
|
||||
:decode/string strip} #"^(\d{5}|)$"]]]]]]
|
||||
[:vendor/legal-entity-name {:optional true} [:maybe [:string {:decode/string strip}]]]
|
||||
[:vendor/legal-entity-first-name {:optional true} [:maybe [:string {:decode/string strip}]]]
|
||||
[:vendor/legal-entity-middle-name {:optional true} [:maybe [:string {:decode/string strip}]]]
|
||||
[:vendor/legal-entity-last-name {:optional true} [:maybe [:string {:decode/string strip}]]]
|
||||
[:vendor/legal-entity-tin {:optional true} [:maybe [:string {:decode/string strip}]]]
|
||||
[:vendor/legal-entity-tin-type {:optional true} [:maybe (ref->enum-schema "legal-entity-tin-type")]]
|
||||
[:vendor/legal-entity-1099-type {:optional true} [:maybe (ref->enum-schema "legal-entity-1099-type")]]]))
|
||||
|
||||
(defn vendor-dialog [{{:keys [client-id]} :query-params {:keys [vendor-id]} :route-params :keys [entity form-params form-errors]}]
|
||||
(fc/start-form (or (when (seq form-params)
|
||||
form-params)
|
||||
(when entity
|
||||
(mc/decode form-schema entity main-transformer))
|
||||
{})
|
||||
form-errors
|
||||
(modal-response
|
||||
(com/modal
|
||||
{}
|
||||
[:form {:hx-post (str (bidi/path-for ssr-routes/only-routes
|
||||
:company-1099-vendor-save
|
||||
:request-method :post
|
||||
:vendor-id (Long/parseLong (:vendor-id (:params request))))
|
||||
"?"
|
||||
(url/map->query {:client-id (:client-id (:params request))}))
|
||||
:hx-target (format "#vendor-table tr[data-id=\"%d\"]" (:db/id vendor))
|
||||
:hx-swap "outerHTML swap:300ms"}
|
||||
[:fieldset {:class "hx-disable"}
|
||||
[:form {:hx-post (url (bidi/path-for ssr-routes/only-routes
|
||||
:company-1099-vendor-save
|
||||
:request-method :post
|
||||
:vendor-id vendor-id)
|
||||
{:client-id client-id})
|
||||
:class "w-full h-full max-w-2xl"
|
||||
:hx-swap "outerHTML swap:300ms"}
|
||||
|
||||
[:fieldset {:class "hx-disable w-full h-full"}
|
||||
(com/modal-card
|
||||
{}
|
||||
[:div.flex [:div.p-2 "Vendor 1099 Info"] [:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600 (:vendor/name vendor)]]
|
||||
[:div.space-y-6
|
||||
[:div.grid.grid-cols-6.gap-4
|
||||
|
||||
[:h4.text-xl.border-b.col-span-6 "Address"]
|
||||
[:div.col-span-6
|
||||
(com/field {:label "Street 1"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/street1])
|
||||
:value (-> vendor :vendor/address :address/street1)
|
||||
:placeholder "1700 Pennsylvania Ave"
|
||||
:autofocus true}))]
|
||||
[:div.col-span-6
|
||||
(com/field {:label "Street 2"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/street2])
|
||||
:value (-> vendor :vendor/address :address/street2)
|
||||
:placeholder "Suite 200"}))]
|
||||
[:div.col-span-3
|
||||
(com/field {:label "City"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/city])
|
||||
:value (-> vendor :vendor/address :address/city)
|
||||
:placeholder "Cupertino"}))]
|
||||
[:div.col-span-1
|
||||
(com/field {:label "State"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/state])
|
||||
:value (-> vendor :vendor/address :address/state)
|
||||
:placeholder "CA"}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "Zip"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/zip])
|
||||
:value (-> vendor :vendor/address :address/zip)
|
||||
:placeholder "98102"}))]
|
||||
[:h4.text-xl.border-b.col-span-6 "Legal Entity"]
|
||||
[:div.col-span-6
|
||||
(com/field {:label "Legal Entity Name"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-name])
|
||||
:value (-> vendor :vendor/legal-entity-name)
|
||||
:placeholder "Good Restaurant LLC"}))]
|
||||
[:div.col-span-6.text-center " - OR -"]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "First Name"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-first-name])
|
||||
:value (-> vendor :vendor/legal-entity-first-name)
|
||||
:placeholder "John"}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "Middle Name"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-middle-name])
|
||||
:value (-> vendor :vendor/legal-entity-middle-name)
|
||||
:placeholder "C."}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "Last Name"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-last-name])
|
||||
:value (-> vendor :vendor/legal-entity-last-name)
|
||||
:placeholder "Riley"}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "TIN"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-tin])
|
||||
:value (-> vendor :vendor/legal-entity-tin)
|
||||
:placeholder "John"}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "TIN Type"}
|
||||
(com/select {:name (path->name [:vendor/legal-entity-tin-type])
|
||||
:allow-blank? true
|
||||
:value (some-> vendor :vendor/legal-entity-tin-type :db/ident name)
|
||||
:options [["ein" "EIN"]
|
||||
["ssn" "SSN"]]}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "1099 Type"}
|
||||
(com/select {:name (path->name [:vendor/legal-entity-1099-type])
|
||||
:allow-blank? true
|
||||
:value (some-> vendor :vendor/legal-entity-1099-type :db/ident name)
|
||||
:options [["none" "None"]
|
||||
["misc" "Misc"]
|
||||
["landlord" "Landlord"]]}))]
|
||||
[:div.col-span-6
|
||||
(com/button {:color :primary}
|
||||
"Save")]]]
|
||||
[:div])]]))))
|
||||
[:div.flex [:div.p-2 "Vendor 1099 Info"] [:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600 (:vendor/name entity)]]
|
||||
[:div.grid.grid-cols-6.gap-x-4.gap-y-2
|
||||
|
||||
(fc/with-field :vendor/address ;; TODO support default
|
||||
(list [:h4.text-xl.border-b.col-span-6 "Address"]
|
||||
[:div.col-span-6
|
||||
(fc/with-field :db/id
|
||||
(com/hidden {:name (fc/field-name)
|
||||
:value (fc/field-value)}))
|
||||
|
||||
(fc/with-field :address/street1
|
||||
(com/validated-field {:label "Street 1"
|
||||
:errors (fc/field-errors)}
|
||||
(com/text-input {:name (fc/field-name)
|
||||
:class "w-full"
|
||||
:value (fc/field-value)
|
||||
:placeholder "1700 Pennsylvania Ave"
|
||||
:autofocus true})))]
|
||||
[:div.col-span-6
|
||||
(fc/with-field :address/street2
|
||||
(com/validated-field {:label "Street 2"
|
||||
:errors (fc/field-errors)}
|
||||
(com/text-input {:name (fc/field-name)
|
||||
:class "w-full"
|
||||
:value (fc/field-value)
|
||||
:placeholder "Suite 200"})))]
|
||||
[:div.col-span-3
|
||||
(fc/with-field :address/city
|
||||
(com/validated-field {:label "City"
|
||||
:errors (fc/field-errors)}
|
||||
(com/text-input {:name (fc/field-name)
|
||||
:class "w-full"
|
||||
:value (fc/field-value)
|
||||
:placeholder "Cupertino"})))]
|
||||
[:div.col-span-1
|
||||
(fc/with-field :address/state
|
||||
(com/validated-field {:label "State"
|
||||
:errors (fc/field-errors)}
|
||||
(com/text-input {:name (fc/field-name)
|
||||
:class "w-full"
|
||||
:value (fc/field-value)
|
||||
:placeholder "CA"})))]
|
||||
[:div.col-span-2
|
||||
(fc/with-field :address/zip
|
||||
(com/validated-field {:label "Zip"
|
||||
:errors (fc/field-errors)}
|
||||
(com/text-input {:name (fc/field-name)
|
||||
:class "w-full"
|
||||
:value (fc/field-value)
|
||||
:placeholder "98102"})))]))
|
||||
|
||||
[:h4.text-xl.border-b.col-span-6 "Legal Entity"]
|
||||
[:div.col-span-6
|
||||
(fc/with-field :vendor/legal-entity-name
|
||||
(com/validated-field {:label "Legal Entity Name"
|
||||
:errors (fc/field-errors)}
|
||||
(com/text-input {:name (fc/field-name)
|
||||
:class "w-full"
|
||||
:value (fc/field-value)
|
||||
:placeholder "Good Restaurant LLC"})))]
|
||||
[:div.col-span-6.text-center " - OR -"]
|
||||
[:div.col-span-2
|
||||
(fc/with-field :vendor/legal-entity-first-name
|
||||
(com/validated-field {:label "First Name"
|
||||
:errors (fc/field-errors)}
|
||||
(com/text-input {:name (fc/field-name)
|
||||
:value (fc/field-value)
|
||||
:placeholder "John"})))]
|
||||
[:div.col-span-2
|
||||
(fc/with-field :vendor/legal-entity-middle-name
|
||||
(com/validated-field {:label "Middle Name"
|
||||
:errors (fc/field-errors)}
|
||||
(com/text-input {:name (fc/field-name)
|
||||
:value (fc/field-value)
|
||||
:placeholder "C."})))]
|
||||
[:div.col-span-2
|
||||
(fc/with-field :vendor/legal-entity-last-name
|
||||
(com/validated-field {:label "Last Name"
|
||||
:errors (fc/field-errors)}
|
||||
(com/text-input {:name (fc/field-name)
|
||||
:value (fc/field-value)
|
||||
:placeholder "Riley"})))]
|
||||
[:div.col-span-2
|
||||
(fc/with-field :vendor/legal-entity-tin
|
||||
(com/validated-field {:label "TIN"
|
||||
:errors (fc/field-errors)}
|
||||
(com/text-input {:name (fc/field-name)
|
||||
:value (fc/field-value)
|
||||
:placeholder "John"})))]
|
||||
[:div.col-span-2
|
||||
(fc/with-field :vendor/legal-entity-tin-type
|
||||
(com/validated-field {:label "TIN Type"
|
||||
:errors (fc/field-errors)}
|
||||
(com/select {:name (fc/field-name)
|
||||
:allow-blank? true
|
||||
:value (some-> (fc/field-value) name)
|
||||
:options [["ein" "EIN"]
|
||||
["ssn" "SSN"]]})))]
|
||||
[:div.col-span-2
|
||||
(fc/with-field :vendor/legal-entity-1099-type
|
||||
(com/validated-field {:label "1099 Type"
|
||||
:errors (fc/field-errors)}
|
||||
(com/select {:name (fc/field-name)
|
||||
:allow-blank? true
|
||||
:value (some-> (fc/field-value) name) ;; TODO use ref stuff
|
||||
:options (ref->select-options "legal-entity-1099-type")})))]]
|
||||
[:div
|
||||
(com/form-errors {:errors (:errors fc/*form-errors*)})
|
||||
(com/validated-save-button {:errors form-errors} "Save rule")])]]))))
|
||||
|
||||
(def vendor-table (helper/table-route grid-page))
|
||||
(def page (helper/page-route grid-page))
|
||||
|
||||
(def key->handler
|
||||
(apply-middleware-to-all-handlers
|
||||
(->>
|
||||
{
|
||||
:company-1099 page
|
||||
:company-1099-vendor-table vendor-table
|
||||
:company-1099-vendor-dialog (-> vendor-dialog
|
||||
(wrap-entity [:route-params :vendor-id] default-vendor-read)
|
||||
(wrap-schema-decode :route-schema [:map [:vendor-id entity-id]]
|
||||
:query-schema [:map [:client-id entity-id]]))
|
||||
:company-1099-vendor-save (-> vendor-save
|
||||
(wrap-entity [:form-params :db/id] default-vendor-read)
|
||||
(wrap-schema-decode :form-schema form-schema
|
||||
:route-schema [:map [:vendor-id entity-id]]
|
||||
:query-schema [:map [:client-id entity-id]])
|
||||
(wrap-nested-form-params)
|
||||
(wrap-form-4xx-2 (-> vendor-dialog
|
||||
(wrap-entity [:form-params :db/id] default-vendor-read)
|
||||
(wrap-entity [:route-params :vendor-id] default-vendor-read)
|
||||
(wrap-schema-decode :route-schema [:map [:vendor-id entity-id]]
|
||||
:query-schema [:map [:client-id entity-id]]))))})
|
||||
(fn [h]
|
||||
(-> h
|
||||
(wrap-secure)
|
||||
(wrap-client-redirect-unauthenticated)))))
|
||||
|
||||
Reference in New Issue
Block a user