diff --git a/src/clj/auto_ap/datomic/migrate.clj b/src/clj/auto_ap/datomic/migrate.clj index 3fdc47a7..2bbe92e1 100644 --- a/src/clj/auto_ap/datomic/migrate.clj +++ b/src/clj/auto_ap/datomic/migrate.clj @@ -7,6 +7,7 @@ [auto-ap.datomic.migrate.add-general-ledger :as add-general-ledger] [auto-ap.datomic.migrate.ledger :as ledger] [auto-ap.datomic.migrate.sales :as sales] + [auto-ap.datomic.migrate.vendors :as vendors] [auto-ap.datomic.migrate.clients :as clients] [auto-ap.datomic.migrate.audit :as audit] [auto-ap.datomic.migrate.yodlee2 :as yodlee2] @@ -339,7 +340,10 @@ clients/norms-map ledger/norms-map yodlee2/norms-map - audit/norms-map) + audit/norms-map + + vendors/norms-map + ) ] (println "Conforming database...") (c/ensure-conforms conn norms-map) diff --git a/src/clj/auto_ap/datomic/migrate/vendors.clj b/src/clj/auto_ap/datomic/migrate/vendors.clj new file mode 100644 index 00000000..e116c248 --- /dev/null +++ b/src/clj/auto_ap/datomic/migrate/vendors.clj @@ -0,0 +1,44 @@ +(ns auto-ap.datomic.migrate.vendors + (:require [datomic.api :as d] + [auto-ap.datomic :refer [uri]])) + +(def norms-map {:add-1099-stuff {:txes [[{:db/ident :vendor/legal-entity-first-name + :db/doc "The first name for the legal entity" + :db/valueType :db.type/string + :db/cardinality :db.cardinality/one} + + {:db/ident :vendor/legal-entity-middle-name + :db/doc "The first name for the legal entity" + :db/valueType :db.type/string + :db/cardinality :db.cardinality/one} + + {:db/ident :vendor/legal-entity-last-name + :db/doc "The first name for the legal entity" + :db/valueType :db.type/string + :db/cardinality :db.cardinality/one} + + {:db/ident :vendor/legal-entity-tin + :db/doc "The ssn or ein for the legal entity" + :db/valueType :db.type/string + :db/cardinality :db.cardinality/one} + + {:db/ident :vendor/legal-entity-tin-type + :db/doc "The ssn or ein for the legal entity" + :db/valueType :db.type/ref + :db/cardinality :db.cardinality/one} + + {:db/ident :vendor/legal-entity-1099-type + :db/doc "The ssn or ein for the legal entity" + :db/valueType :db.type/ref + :db/cardinality :db.cardinality/one}]]} + :add-1099-enums {:txes [[{:db/ident :legal-entity-tin-type/ssn} + {:db/ident :legal-entity-tin-type/ein} + + {:db/ident :legal-entity-1099-type/none} + {:db/ident :legal-entity-1099-type/misc} + {:db/ident :legal-entity-1099-type/landlord}]]}}) + + + + + diff --git a/src/clj/auto_ap/datomic/vendors.clj b/src/clj/auto_ap/datomic/vendors.clj index 9644bc5d..d73d19d1 100644 --- a/src/clj/auto_ap/datomic/vendors.clj +++ b/src/clj/auto_ap/datomic/vendors.clj @@ -3,6 +3,11 @@ [auto-ap.graphql.utils :refer [limited-clients ]] [auto-ap.datomic :refer [uri conn merge-query]])) +(defn <-datomic [a] + (cond-> a + (:vendor/legal-entity-tin-type a) (update :vendor/legal-entity-tin-type :db/ident) + (:vendor/legal-entity-1099-type a) (update :vendor/legal-entity-1099-type :db/ident))) + (defn cleanse [id vendor] (let [clients (if-let [clients (limited-clients id)] (set (map :db/id clients)) @@ -20,6 +25,8 @@ :vendor/terms-overrides [* {:vendor-terms-override/client [:client/name :client/code :db/id]}] :vendor/schedule-payment-dom [* {:vendor-schedule-payment-dom/client [:client/name :client/code :db/id]}] :vendor/automatically-paid-when-due [:db/id :client/name] + :vendor/legal-entity-tin-type [:db/ident :db/id] + :vendor/legal-entity-1099-type [:db/ident :db/id] :vendor/default-account [:db/id :account/numeric-code :account/name]}]) (defn get-usages [args] @@ -57,12 +64,15 @@ (d/query) (map first) (map #(cleanse (:id args) %)) + (map <-datomic) (map #(assoc % :usage (get usages (:db/id %))))))) (defn get-by-id [id] (->> (d/q '[:find (pull ?e [* {:default-account [:account/name :db/id :account/location] + :vendor/legal-entity-tin-type [:db/ident :db/id] + :vendor/legal-entity-1099-type [:db/ident :db/id] :vendor/account-overrides [* {:vendor-account-override/client [:client/name :db/id] :vendor-account-override/account [:account/name :account/numeric-code :db/id]}] :vendor/terms-overrides [* {:vendor-terms-override/client [:client/name :db/id]}] @@ -73,6 +83,7 @@ (d/db (d/connect uri)) id) (map first) + (map <-datomic) (first))) diff --git a/src/clj/auto_ap/graphql.clj b/src/clj/auto_ap/graphql.clj index d4b3c0fe..3e203ad6 100644 --- a/src/clj/auto_ap/graphql.clj +++ b/src/clj/auto_ap/graphql.clj @@ -211,7 +211,16 @@ :address {:type :address} :default_account {:type :account} - :invoice_reminder_schedule {:type 'String}}} + :invoice_reminder_schedule {:type 'String} + + :legal_entity_first_name {:type 'String} + :legal_entity_middle_name {:type 'String} + :legal_entity_last_name {:type 'String} + :legal_entity_tin {:type 'String} + :legal_entity_tin_type {:type :tin_type} + :legal_entity_1099_type {:type :type_1099} + + }} :reminder {:fields {:id {:type 'Int} :email {:type 'String} @@ -798,7 +807,15 @@ :default_account_id {:type :id} :account_overrides {:type '(list :add_account_override)} :schedule_payment_dom {:type '(list :add_schedule_payment_dom)} - :invoice_reminder_schedule {:type 'String}}} + :invoice_reminder_schedule {:type 'String} + + :legal_entity_first_name {:type 'String} + :legal_entity_middle_name {:type 'String} + :legal_entity_last_name {:type 'String} + :legal_entity_tin {:type 'String} + :legal_entity_tin_type {:type :tin_type} + :legal_entity_1099_type {:type :type_1099} + }} :edit_expense_account {:fields {:id {:type :id} @@ -873,6 +890,11 @@ :enums {:payment_type {:values [{:enum-value :check} {:enum-value :cash} {:enum-value :debit}]} + :tin_type {:values [{:enum-value :ein} + {:enum-value :ssn}]} + :type_1099 {:values [{:enum-value :none} + {:enum-value :misc} + {:enum-value :landlord}]} :invoice_status {:values [{:enum-value :paid} {:enum-value :unpaid} {:enum-value :voided}]} diff --git a/src/clj/auto_ap/graphql/vendors.clj b/src/clj/auto_ap/graphql/vendors.clj index ae736b49..c92fb166 100644 --- a/src/clj/auto_ap/graphql/vendors.clj +++ b/src/clj/auto_ap/graphql/vendors.clj @@ -1,5 +1,5 @@ (ns auto-ap.graphql.vendors - (:require [auto-ap.graphql.utils :refer [->graphql assert-can-see-client assert-admin is-admin?]] + (:require [auto-ap.graphql.utils :refer [->graphql assert-can-see-client assert-admin is-admin? enum->keyword]] [auto-ap.datomic.vendors :as d-vendors] [auto-ap.time :refer [parse iso-date]] [datomic.api :as d] @@ -40,45 +40,49 @@ (:id ao) (assoc :db/id (:id ao)))) schedule_payment_dom) transaction (cond-> - [(remove-nils #:vendor {:db/id (if id - id - "vendor") - :name name - :code code - :hidden hidden - :terms terms - :print-as print_as - :default-account default_account_id - :invoice-reminder-schedule (keyword invoice_reminder_schedule) - - - :address (when address - (remove-nils #:address {:db/id (if (:id address) - (:id address) - "address") - :street1 (:street1 address) - :street2 (:street2 address) - :city (:city address) - :state (:state address) - :zip (:zip address)})) - :primary-contact (when primary_contact + [(remove-nils (cond-> #:vendor {:db/id (if id + id + "vendor") + :name name + :code code + :hidden hidden + :terms terms + :print-as print_as + :default-account default_account_id + :invoice-reminder-schedule (keyword invoice_reminder_schedule) + :address (when address + (remove-nils #:address {:db/id (if (:id address) + (:id address) + "address") + :street1 (:street1 address) + :street2 (:street2 address) + :city (:city address) + :state (:state address) + :zip (:zip address)})) + :primary-contact (when primary_contact - (remove-nils #:contact {:db/id (if (:id primary_contact) - (:id primary_contact) - "primary") - :name (:name primary_contact) - :phone (:phone primary_contact) - :email (:email primary_contact)})) - - :secondary-contact (when secondary_contact + (remove-nils #:contact {:db/id (if (:id primary_contact) + (:id primary_contact) + "primary") + :name (:name primary_contact) + :phone (:phone primary_contact) + :email (:email primary_contact)})) + :secondary-contact (when secondary_contact - (remove-nils #:contact {:db/id (if (:id secondary_contact) - (:id secondary_contact) - "secondary") - :name (:name secondary_contact) - :phone (:phone secondary_contact) - :email (:email secondary_contact)}) - )})] + (remove-nils #:contact {:db/id (if (:id secondary_contact) + (:id secondary_contact) + "secondary") + :name (:name secondary_contact) + :phone (:phone secondary_contact) + :email (:email secondary_contact)}) + )} + (is-admin? (:id context)) (assoc + :vendor/legal-entity-first-name (:legal_entity_first_name in) + :vendor/legal-entity-middle-name (:legal_entity_middle_name in) + :vendor/legal-entity-last-name (:legal_entity_last_name in) + :vendor/legal-entity-tin (:legal_entity_tin in) + :vendor/legal-entity-tin-type (enum->keyword (:legal_entity_tin_type in) "legal-entity-tin-type") + :vendor/legal-entity-1099-type (enum->keyword (:legal_entity_1099_type in) "legal-entity-1099-type"))))] (is-admin? (:id context)) (conj [:reset (if id id "vendor") :vendor/account-overrides account-overrides]) (is-admin? (:id context)) (conj [:reset (if id id "vendor") :vendor/terms-overrides terms-overrides]) (is-admin? (:id context)) (conj [:reset (if id id "vendor") :vendor/schedule-payment-dom schedule-payment-dom]) @@ -91,9 +95,10 @@ _ (log/info "Upserting vendor" transaction) transaction-result (audit-transact transaction (:id context))] - (-> (d-vendors/get-by-id (or (-> transaction-result :tempids (get "vendor")) - id)) - (->graphql)))) + (doto (-> (d-vendors/get-by-id (or (-> transaction-result :tempids (get "vendor")) + id)) + (->graphql)) + log/info))) (defn merge-vendors [context {:keys [from to]} value] (let [transaction (->> (d/query {:query {:find '[?x ?a2] diff --git a/src/cljs/auto_ap/events.cljs b/src/cljs/auto_ap/events.cljs index b3a06c8f..82be0970 100644 --- a/src/cljs/auto_ap/events.cljs +++ b/src/cljs/auto_ap/events.cljs @@ -25,6 +25,9 @@ [:primary-contact [:name :phone :email :id]] [:secondary-contact [:id :name :phone :email]] :print-as :invoice-reminder-schedule :code + :legal-entity-first-name :legal-entity-middle-name :legal-entity-last-name + :legal-entity-tin :legal-entity-tin-type + :legal-entity-1099-type [:address [:street1 :street2 :city :state :zip]]]) (defn client-query [token] diff --git a/src/cljs/auto_ap/views/components/vendor_dialog.cljs b/src/cljs/auto_ap/views/components/vendor_dialog.cljs index 6fa33e7f..30687ac2 100644 --- a/src/cljs/auto_ap/views/components/vendor_dialog.cljs +++ b/src/cljs/auto_ap/views/components/vendor_dialog.cljs @@ -89,7 +89,7 @@ (re-frame/reg-event-fx ::save [with-user with-is-admin? (forms/triggers-loading ::vendor-form) (forms/in-form ::vendor-form)] - (fn [{:keys [user is-admin?] {{:keys [name hidden print-as terms invoice-reminder-schedule primary-contact automatically-paid-when-due schedule-payment-dom secondary-contact address default-account terms-overrides account-overrides id] :as data} :data} :db} _] + (fn [{:keys [user is-admin?] {{:keys [name hidden print-as terms invoice-reminder-schedule primary-contact automatically-paid-when-due schedule-payment-dom secondary-contact address default-account terms-overrides account-overrides id legal-entity-tin legal-entity-tin-type legal-entity-first-name legal-entity-last-name legal-entity-middle-name legal-entity-1099-type] :as data} :data} :db} _] (println data) (when (s/valid? ::entity/vendor data) { :graphql @@ -97,37 +97,45 @@ :owns-state {:single ::vendor-form} :query-obj {:venia/operation {:operation/type :mutation :operation/name "UpsertVendor"} :venia/queries [{:query/data [:upsert-vendor - {:vendor (cond-> {:id id - :name name - :print-as print-as - :terms terms - :default-account-id (:id default-account) - :address address - :primary-contact primary-contact - :secondary-contact secondary-contact - :invoice-reminder-schedule invoice-reminder-schedule} - is-admin? (assoc :hidden hidden - :terms-overrides (mapv - (fn [{:keys [client override id]}] - {:id id - :client-id (:id client) - :terms override}) - terms-overrides) - :account-overrides (mapv - (fn [{:keys [client override id]}] - {:id id - :client-id (:id client) - :account-id (:id override)}) - account-overrides) - :schedule-payment-dom (mapv - (fn [{:keys [client override id]}] - {:id id - :client-id (:id client) - :dom override}) - schedule-payment-dom) - :automatically-paid-when-due (mapv - :id - automatically-paid-when-due)))} + {:vendor (doto (cond-> {:id id + :name name + :print-as print-as + :terms terms + :default-account-id (:id default-account) + :address address + :primary-contact primary-contact + :secondary-contact secondary-contact + :invoice-reminder-schedule invoice-reminder-schedule} + is-admin? (assoc :hidden hidden + :terms-overrides (mapv + (fn [{:keys [client override id]}] + {:id id + :client-id (:id client) + :terms override}) + terms-overrides) + :account-overrides (mapv + (fn [{:keys [client override id]}] + {:id id + :client-id (:id client) + :account-id (:id override)}) + account-overrides) + :schedule-payment-dom (mapv + (fn [{:keys [client override id]}] + {:id id + :client-id (:id client) + :dom override}) + schedule-payment-dom) + :automatically-paid-when-due (mapv + :id + automatically-paid-when-due) + :legal-entity-first-name legal-entity-first-name + :legal-entity-middle-name legal-entity-middle-name + :legal-entity-last-name legal-entity-last-name + :legal-entity-tin legal-entity-tin + :legal-entity-tin-type (some-> legal-entity-tin-type clojure.core/name not-empty keyword) + :legal-entity-1099-type (some-> legal-entity-1099-type clojure.core/name not-empty keyword) + )) + println)} events/vendor-query]}]} :on-success [::save-complete]}}))) @@ -392,7 +400,74 @@ :spec ::entity/invoice-reminder-schedule :event change-event :subscription data}]] - " Never"]]]])) + " Never"]]] + + [:h2.subtitle "Legal Entity"] + [horizontal-field + [:label.label "Name"] + [:div.control + [bind-field + [:input.input {:type "text" + :placeholder "First Name" + :field [:legal-entity-first-name] + :spec ::contact/name + :event change-event + :subscription data}]]] + + [:div.control + [bind-field + [:input.input {:type "text" + :placeholder "Middle Name" + :field [:legal-entity-middle-name] + :spec ::contact/name + :event change-event + :subscription data}]]] + + [:div.control + [bind-field + [:input.input {:type "text" + :placeholder "Last Name" + :field [:legal-entity-last-name] + :spec ::contact/name + :event change-event + :subscription data}]]]] + [horizontal-field + [:label.label "TIN"] + [:div.control + [bind-field + [:input.input {:type "text" + :placeholder "SSN or EIN" + :field [:legal-entity-tin] + :size "12" + :spec ::contact/name + :event change-event + :subscription data}]]] + + [:div.control + [:div.select + [bind-field + [:select {:type "select" + :field [:legal-entity-tin-type] + :event change-event + :subscription data} + [:option {:value nil} ""] + [:option {:value "ein"} "EIN"] + [:option {:value "ssn"} "SSN"]]]]]] + + [horizontal-field + [:label.label "1099 Type"] + [:div.control + [:div.select + [bind-field + [:select {:type "select" + :field [:legal-entity-1099-type] + :event change-event + :subscription data} + [:option {:value nil} ""] + [:option {:value "none"} "Don't 1099"] + [:option {:value "misc"} "Misc"] + [:option {:value "landlord"} "Landlord"]]]]]] + ])) (defn vendor-dialog [{:keys [save-event] }] (let [clients @(re-frame/subscribe [::subs/clients])