company 1099 works

This commit is contained in:
2023-10-26 11:04:44 -07:00
parent 351864da1b
commit 8c3d792b28
8 changed files with 279 additions and 281 deletions

View File

@@ -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)))))