fixes bugs.
This commit is contained in:
@@ -75,8 +75,8 @@
|
|||||||
(assoc :per-page Integer/MAX_VALUE)
|
(assoc :per-page Integer/MAX_VALUE)
|
||||||
(d-transactions/raw-graphql-ids )
|
(d-transactions/raw-graphql-ids )
|
||||||
:ids)
|
:ids)
|
||||||
specific-ids (d-transactions/filter-ids (:ids args))]
|
specific-ids (d-transactions/filter-ids (seq (:ids args)))]
|
||||||
(if (:ids args)
|
(if (seq (:ids args))
|
||||||
(set specific-ids)
|
(set specific-ids)
|
||||||
(set ids))))
|
(set ids))))
|
||||||
|
|
||||||
@@ -190,10 +190,12 @@
|
|||||||
(audit-transact-batch
|
(audit-transact-batch
|
||||||
(map (fn [t]
|
(map (fn [t]
|
||||||
(let [locations (client->locations (-> t :transaction/client :db/id))]
|
(let [locations (client->locations (-> t :transaction/client :db/id))]
|
||||||
[:upsert-transaction (cond-> t
|
(doto
|
||||||
(:approval_status args) (assoc :transaction/approval-status (enum->keyword (:approval_status args) "transaction-approval-status"))
|
[:upsert-transaction (cond-> t
|
||||||
(:vendor args) (assoc :transaction/vendor (:vendor args))
|
(:approval_status args) (assoc :transaction/approval-status (enum->keyword (:approval_status args) "transaction-approval-status"))
|
||||||
(seq (:accounts args)) (assoc :transaction/accounts (maybe-code-accounts t (:accounts args) locations)))]))
|
(:vendor args) (assoc :transaction/vendor (:vendor args))
|
||||||
|
(seq (:accounts args)) (assoc :transaction/accounts (maybe-code-accounts t (:accounts args) locations)))]
|
||||||
|
clojure.pprint/pprint)))
|
||||||
transactions)
|
transactions)
|
||||||
(:id context))
|
(:id context))
|
||||||
{:message (str "Successfully coded " (count all-ids) " transactions.")}))
|
{:message (str "Successfully coded " (count all-ids) " transactions.")}))
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
(ns auto-ap.parse.templates
|
(ns auto-ap.parse.templates
|
||||||
(:require [auto-ap.parse.util :as u]
|
(:require [auto-ap.parse.util :as u]
|
||||||
[auto-ap.logging :as alog]
|
[auto-ap.logging :as alog]
|
||||||
[clojure.string :as str]))
|
[clj-time.core :as time]
|
||||||
|
[clojure.string :as str]
|
||||||
|
[auto-ap.time :as atime]))
|
||||||
|
|
||||||
|
|
||||||
(def pdf-templates
|
(def pdf-templates
|
||||||
@@ -13,7 +15,7 @@
|
|||||||
:date #"\s+([0-9]+/[0-9]+/[0-9]+)"
|
:date #"\s+([0-9]+/[0-9]+/[0-9]+)"
|
||||||
:invoice-number #"\s+[0-9]+/[0-9]+/[0-9]+\s+([0-9]+)"}
|
:invoice-number #"\s+[0-9]+/[0-9]+/[0-9]+\s+([0-9]+)"}
|
||||||
:parser {:date [:clj-time "MM/dd/yyyy"]}}
|
:parser {:date [:clj-time "MM/dd/yyyy"]}}
|
||||||
|
|
||||||
{:vendor "Gstar Seafood"
|
{:vendor "Gstar Seafood"
|
||||||
:keywords [#"G Star Seafood"]
|
:keywords [#"G Star Seafood"]
|
||||||
:extract {:total #"Total\s{2,}([\d\-,]+\.\d{2,2}+)"
|
:extract {:total #"Total\s{2,}([\d\-,]+\.\d{2,2}+)"
|
||||||
@@ -42,10 +44,10 @@
|
|||||||
:total #"INVOICE TOTAL\s+([0-9.]+)"}
|
:total #"INVOICE TOTAL\s+([0-9.]+)"}
|
||||||
:parser {:date [:clj-time "MM/dd/yy"]}
|
:parser {:date [:clj-time "MM/dd/yy"]}
|
||||||
:multi #"\f\f"}
|
:multi #"\f\f"}
|
||||||
|
|
||||||
|
|
||||||
;; IMPACT PAPER
|
;; IMPACT PAPER
|
||||||
{:vendor "Impact Paper & Ink LTD"
|
{:vendor "Impact Paper & Ink LTD"
|
||||||
:keywords [#"650-692-5598"]
|
:keywords [#"650-692-5598"]
|
||||||
:extract {:total #"Total Amount\s+\$([\d\.\,\-]+)"
|
:extract {:total #"Total Amount\s+\$([\d\.\,\-]+)"
|
||||||
:account-number #"CUST. #\n.*?/\d{4,}\s+(.*?)\n"
|
:account-number #"CUST. #\n.*?/\d{4,}\s+(.*?)\n"
|
||||||
@@ -94,7 +96,7 @@
|
|||||||
:total #"Total Invoice\s+([\-]?[0-9.]+)"}
|
:total #"Total Invoice\s+([\-]?[0-9.]+)"}
|
||||||
:parser {:date [:clj-time "MM/dd/yy"]
|
:parser {:date [:clj-time "MM/dd/yy"]
|
||||||
:total [:trim-commas-and-negate nil]}}
|
:total [:trim-commas-and-negate nil]}}
|
||||||
|
|
||||||
{:vendor "Ben E. Keith"
|
{:vendor "Ben E. Keith"
|
||||||
:keywords [#"BEN E. KEITH"]
|
:keywords [#"BEN E. KEITH"]
|
||||||
:extract {:date #"Customer No Mo Day Yr.*?\n.*?\d{5,}\s{2,}(\d+\s+\d+\s+\d+)"
|
:extract {:date #"Customer No Mo Day Yr.*?\n.*?\d{5,}\s{2,}(\d+\s+\d+\s+\d+)"
|
||||||
@@ -104,7 +106,7 @@
|
|||||||
:parser {:date [:month-day-year nil]
|
:parser {:date [:month-day-year nil]
|
||||||
:total [:trim-commas-and-negate nil]}}
|
:total [:trim-commas-and-negate nil]}}
|
||||||
|
|
||||||
;; SOUTHBAY FRESH
|
;; SOUTHBAY FRESH
|
||||||
{:vendor "Southbay Fresh Produce"
|
{:vendor "Southbay Fresh Produce"
|
||||||
:keywords [#"(SOUTH BAY FRESH PRODUCE|SOUTH BAY PRODUCE)"]
|
:keywords [#"(SOUTH BAY FRESH PRODUCE|SOUTH BAY PRODUCE)"]
|
||||||
:extract {:date #"^([0-9]+/[0-9]+/[0-9]+)"
|
:extract {:date #"^([0-9]+/[0-9]+/[0-9]+)"
|
||||||
@@ -115,25 +117,25 @@
|
|||||||
:multi #"\n"
|
:multi #"\n"
|
||||||
:multi-match? #"^[0-9]+/[0-9]+/[0-9]+\s+INV "}
|
:multi-match? #"^[0-9]+/[0-9]+/[0-9]+\s+INV "}
|
||||||
|
|
||||||
;; DON VITO
|
;; DON VITO
|
||||||
{:vendor "Don Vito Ozuna Food Corp"
|
{:vendor "Don Vito Ozuna Food Corp"
|
||||||
:keywords [#"408-465-2010"]
|
:keywords [#"408-465-2010"]
|
||||||
:extract {:date #"([0-9]+/[0-9]+/[0-9]+)"
|
:extract {:date #"([0-9]+/[0-9]+/[0-9]+)"
|
||||||
:customer-identifier #"Bill To.*?\n(.*?)\s{2,}"
|
:customer-identifier #"Bill To.*?\n(.*?)\s{2,}"
|
||||||
:invoice-number #"(?:[0-9]+/[0-9]+/[0-9]+)\s{2,}(\d+)"
|
:invoice-number #"(?:[0-9]+/[0-9]+/[0-9]+)\s{2,}(\d+)"
|
||||||
:total #"Please remit payment to\s{2,}\$([\-0-9.]+)"}
|
:total #"Please remit payment to\s{2,}\$([\-0-9.]+)"}
|
||||||
:parser {:date [:clj-time "MM/dd/yyyy"]} }
|
:parser {:date [:clj-time "MM/dd/yyyy"]}}
|
||||||
|
|
||||||
;; DON VITO STATEMENT
|
;; DON VITO STATEMENT
|
||||||
{:vendor "Don Vito Ozuna Food Corp"
|
{:vendor "Don Vito Ozuna Food Corp"
|
||||||
:keywords [#"Don Vito Ozuna Food Corp.*?\n.*?Statement"]
|
:keywords [#"Don Vito Ozuna Food Corp.*?\n.*?Statement"]
|
||||||
:extract {:date #"([0-9]+/[0-9]+/[0-9]+)"
|
:extract {:date #"([0-9]+/[0-9]+/[0-9]+)"
|
||||||
:customer-identifier #"To:.*?\n\s*(.*)?\s{2,}"
|
:customer-identifier #"To:.*?\n\s*(.*)?\s{2,}"
|
||||||
:invoice-number #"INV #(\d+)"
|
:invoice-number #"INV #(\d+)"
|
||||||
:total #"Amount \$([\d\-\.]+?)\.\s{2,}"}
|
:total #"Amount \$([\d\-\.]+?)\.\s{2,}"}
|
||||||
:parser {:date [:clj-time "MM/dd/yyyy"]}
|
:parser {:date [:clj-time "MM/dd/yyyy"]}
|
||||||
:multi #"\n"
|
:multi #"\n"
|
||||||
:multi-match? #"\d+/\d+/\d+.*?INV"}
|
:multi-match? #"\d+/\d+/\d+.*?INV"}
|
||||||
|
|
||||||
;; PFG - LEDYARD
|
;; PFG - LEDYARD
|
||||||
{:vendor "Performance Food Group - LEDYARD"
|
{:vendor "Performance Food Group - LEDYARD"
|
||||||
@@ -221,8 +223,8 @@
|
|||||||
:total [:trim-commas nil]}
|
:total [:trim-commas nil]}
|
||||||
:multi (. java.util.regex.Pattern (compile (-> \formfeed str) java.util.regex.Pattern/CASE_INSENSITIVE))
|
:multi (. java.util.regex.Pattern (compile (-> \formfeed str) java.util.regex.Pattern/CASE_INSENSITIVE))
|
||||||
:multi-match? #"(Total\s+[0-9\.]+|Total Order)"}
|
:multi-match? #"(Total\s+[0-9\.]+|Total Order)"}
|
||||||
|
|
||||||
;; AUTO-CHLOR
|
;; AUTO-CHLOR
|
||||||
{:vendor "Auto-Chlor"
|
{:vendor "Auto-Chlor"
|
||||||
:keywords [#"AUTO-CHLOR"]
|
:keywords [#"AUTO-CHLOR"]
|
||||||
:extract {:date #"DATE : ([0-9]+/[0-9]+/[0-9]+)"
|
:extract {:date #"DATE : ([0-9]+/[0-9]+/[0-9]+)"
|
||||||
@@ -254,7 +256,7 @@
|
|||||||
:multi #"\n"
|
:multi #"\n"
|
||||||
:multi-match? #"^\s+.*?\d{6,}.*?\$"}
|
:multi-match? #"^\s+.*?\d{6,}.*?\$"}
|
||||||
|
|
||||||
;; C & L
|
;; C & L
|
||||||
{:vendor "C&L Produce"
|
{:vendor "C&L Produce"
|
||||||
:keywords [#"440 Franklin Street"]
|
:keywords [#"440 Franklin Street"]
|
||||||
:extract {:date #"([0-9]+/[0-9]+/[0-9]+)"
|
:extract {:date #"([0-9]+/[0-9]+/[0-9]+)"
|
||||||
@@ -368,7 +370,7 @@
|
|||||||
:total [:trim-commas nil]}}
|
:total [:trim-commas nil]}}
|
||||||
|
|
||||||
|
|
||||||
;; Breakthru Bev
|
;; Breakthru Bev
|
||||||
{:vendor "Wine Warehouse"
|
{:vendor "Wine Warehouse"
|
||||||
:keywords [#"BREAKTHRU BEVERAGE"]
|
:keywords [#"BREAKTHRU BEVERAGE"]
|
||||||
:extract {:date #"Invoice Date:\s+([0-9]+/[0-9]+/[0-9]+)"
|
:extract {:date #"Invoice Date:\s+([0-9]+/[0-9]+/[0-9]+)"
|
||||||
@@ -377,7 +379,7 @@
|
|||||||
:account-number #"Customer #:\s+(\d+)"}
|
:account-number #"Customer #:\s+(\d+)"}
|
||||||
:parser {:date [:clj-time "MM/dd/yyyy"]
|
:parser {:date [:clj-time "MM/dd/yyyy"]
|
||||||
:total [:trim-commas nil]}}
|
:total [:trim-commas nil]}}
|
||||||
|
|
||||||
;; THE WATER PROS
|
;; THE WATER PROS
|
||||||
{:vendor "The Water Pros"
|
{:vendor "The Water Pros"
|
||||||
:keywords [#"The Water Pros, Inc"]
|
:keywords [#"The Water Pros, Inc"]
|
||||||
@@ -418,7 +420,7 @@
|
|||||||
:parser {:date [:clj-time "MM/dd/yyyy"]
|
:parser {:date [:clj-time "MM/dd/yyyy"]
|
||||||
:total [:trim-commas nil]}}
|
:total [:trim-commas nil]}}
|
||||||
|
|
||||||
;; PACIFIC SEAFOOD
|
;; PACIFIC SEAFOOD
|
||||||
{:vendor "Pacific Seafood"
|
{:vendor "Pacific Seafood"
|
||||||
:keywords [#"(pacseafood|PACIFIC FRESH)"]
|
:keywords [#"(pacseafood|PACIFIC FRESH)"]
|
||||||
:extract {:date #"DATE(?:.*\n.*(?=([0-9]+/[0-9]+/[0-9]+)))([0-9]+/[0-9]+/[0-9]+)"
|
:extract {:date #"DATE(?:.*\n.*(?=([0-9]+/[0-9]+/[0-9]+)))([0-9]+/[0-9]+/[0-9]+)"
|
||||||
@@ -490,7 +492,7 @@
|
|||||||
:parser {:date [:clj-time "MM/dd/yyyy"]
|
:parser {:date [:clj-time "MM/dd/yyyy"]
|
||||||
:total [:trim-commas-and-negate nil]}}
|
:total [:trim-commas-and-negate nil]}}
|
||||||
|
|
||||||
;; A&B
|
;; A&B
|
||||||
{:vendor "A&B Produce"
|
{:vendor "A&B Produce"
|
||||||
:keywords [#"ABProduce"]
|
:keywords [#"ABProduce"]
|
||||||
:extract {:date #"^\s+([0-9]+/[0-9]+/[0-9]+)"
|
:extract {:date #"^\s+([0-9]+/[0-9]+/[0-9]+)"
|
||||||
@@ -623,7 +625,7 @@
|
|||||||
:parser {:date [:clj-time "MM/dd/yy"]
|
:parser {:date [:clj-time "MM/dd/yy"]
|
||||||
:total [:trim-commas nil]}}
|
:total [:trim-commas nil]}}
|
||||||
|
|
||||||
;; JFC
|
;; JFC
|
||||||
{:vendor "JFC International"
|
{:vendor "JFC International"
|
||||||
:keywords [#"48490 MILMONT DRIVE"]
|
:keywords [#"48490 MILMONT DRIVE"]
|
||||||
:extract {:date #"([0-9]+/[0-9]+/[0-9]+)"
|
:extract {:date #"([0-9]+/[0-9]+/[0-9]+)"
|
||||||
@@ -723,7 +725,7 @@
|
|||||||
:total #"Invoice Total:\s+([\d\-,]+\.\d{2,2}+)"}
|
:total #"Invoice Total:\s+([\d\-,]+\.\d{2,2}+)"}
|
||||||
:parser {:date [:clj-time "MM/dd/yyyy"]
|
:parser {:date [:clj-time "MM/dd/yyyy"]
|
||||||
:total [:trim-commas-and-negate nil]}}
|
:total [:trim-commas-and-negate nil]}}
|
||||||
|
|
||||||
{:vendor "Mani Imports"
|
{:vendor "Mani Imports"
|
||||||
:keywords [#"Mani Imports"]
|
:keywords [#"Mani Imports"]
|
||||||
:extract {:date #"Order Date\s+([0-9]+/[0-9]+/[0-9]+)"
|
:extract {:date #"Order Date\s+([0-9]+/[0-9]+/[0-9]+)"
|
||||||
@@ -731,7 +733,7 @@
|
|||||||
:invoice-number #"Invoice Number:\s+(.*?)\n"
|
:invoice-number #"Invoice Number:\s+(.*?)\n"
|
||||||
:total #"Invoice Total:\s+([\d\-,]+\.\d{2,2}+)"}
|
:total #"Invoice Total:\s+([\d\-,]+\.\d{2,2}+)"}
|
||||||
:parser {:date [:clj-time "MM/dd/yyyy"]
|
:parser {:date [:clj-time "MM/dd/yyyy"]
|
||||||
:total [:trim-commas-and-negate nil]} }
|
:total [:trim-commas-and-negate nil]}}
|
||||||
{:vendor "Reel Produce"
|
{:vendor "Reel Produce"
|
||||||
:keywords [#"REEL Produce, Inc" #"Statem"]
|
:keywords [#"REEL Produce, Inc" #"Statem"]
|
||||||
:extract {:date #"\s*([0-9]+/[0-9]+/[0-9]+)"
|
:extract {:date #"\s*([0-9]+/[0-9]+/[0-9]+)"
|
||||||
@@ -789,15 +791,36 @@
|
|||||||
(and
|
(and
|
||||||
(seq r)
|
(seq r)
|
||||||
(->> r first not-empty))))
|
(->> r first not-empty))))
|
||||||
|
(take 4)
|
||||||
(map
|
(map
|
||||||
(fn [[customer-number _ _ _ invoice-number date amount :as row]]
|
(fn [[customer-number _ _ _ invoice-number date amount :as row]]
|
||||||
|
(println "DAT E is" date)
|
||||||
{:customer-identifier customer-number
|
{:customer-identifier customer-number
|
||||||
:text (str/join " " row)
|
:text (str/join " " row)
|
||||||
:full-text (str/join " " row)
|
:full-text (str/join " " row)
|
||||||
:date (u/parse-value :clj-time "MM/dd/yyyy" (str/trim date))
|
:date (try (or (u/parse-value :clj-time "MM/dd/yyyy" (str/trim date))
|
||||||
|
(try
|
||||||
|
(atime/as-local-time
|
||||||
|
(time/plus (time/date-time 1900 1 1)
|
||||||
|
(time/days (dec (dec (Integer/parseInt "45663"))))))
|
||||||
|
(catch Exception e
|
||||||
|
nil)
|
||||||
|
))
|
||||||
|
|
||||||
|
(catch Exception e
|
||||||
|
(try
|
||||||
|
(atime/as-local-time
|
||||||
|
(time/plus (time/date-time 1900 1 1)
|
||||||
|
(time/days (dec (dec (Integer/parseInt "45663"))))))
|
||||||
|
(catch Exception e
|
||||||
|
nil)
|
||||||
|
)
|
||||||
|
))
|
||||||
:invoice-number invoice-number
|
:invoice-number invoice-number
|
||||||
:total (str amount)
|
:total (str amount)
|
||||||
:vendor-code vendor})))
|
:vendor-code vendor})))
|
||||||
conj
|
conj
|
||||||
[]
|
[]
|
||||||
sheet)))}])
|
sheet)))}])
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -388,7 +388,7 @@
|
|||||||
|
|
||||||
(defn daily-results
|
(defn daily-results
|
||||||
([client location]
|
([client location]
|
||||||
(daily-results client location (time/plus (time/now) (time/days -30)) (time/now)))
|
(daily-results client location (time/plus (time/now) (time/days -10)) (time/now)))
|
||||||
([client location start end]
|
([client location start end]
|
||||||
(capture-context->lc
|
(capture-context->lc
|
||||||
(->
|
(->
|
||||||
@@ -458,7 +458,7 @@
|
|||||||
(:payout_entries result)))))))
|
(:payout_entries result)))))))
|
||||||
|
|
||||||
(defn payouts
|
(defn payouts
|
||||||
([client location] (payouts client location (time/plus (time/now) (time/days -30)) (time/now)))
|
([client location] (payouts client location (time/plus (time/now) (time/days -10)) (time/now)))
|
||||||
([client location start end]
|
([client location start end]
|
||||||
(with-context-as {:location (:square-location/client-location location)} lc
|
(with-context-as {:location (:square-location/client-location location)} lc
|
||||||
(de/chain (manifold-api-call
|
(de/chain (manifold-api-call
|
||||||
@@ -599,7 +599,7 @@
|
|||||||
(apply de/zip
|
(apply de/zip
|
||||||
(for [square-location (:client/square-locations client)
|
(for [square-location (:client/square-locations client)
|
||||||
:when (:square-location/client-location square-location)]
|
:when (:square-location/client-location square-location)]
|
||||||
(upsert client square-location (time/plus (time/now) (time/days -30)) (time/now)))))
|
(upsert client square-location (time/plus (time/now) (time/days -10)) (time/now)))))
|
||||||
([client location start end]
|
([client location start end]
|
||||||
(capture-context->lc
|
(capture-context->lc
|
||||||
(de/chain (daily-results client location start end)
|
(de/chain (daily-results client location start end)
|
||||||
@@ -618,7 +618,7 @@
|
|||||||
:when (:square-location/client-location square-location)]
|
:when (:square-location/client-location square-location)]
|
||||||
(upsert-payouts client square-location))))
|
(upsert-payouts client square-location))))
|
||||||
([client location]
|
([client location]
|
||||||
(upsert-payouts client location (time/plus (time/now) (time/days -30)) (time/now)))
|
(upsert-payouts client location (time/plus (time/now) (time/days -10)) (time/now)))
|
||||||
([client location start end]
|
([client location start end]
|
||||||
(with-context-as {:source "Square payout loading"
|
(with-context-as {:source "Square payout loading"
|
||||||
:client (:client/code client)} lc
|
:client (:client/code client)} lc
|
||||||
@@ -825,7 +825,7 @@
|
|||||||
(apply de/zip
|
(apply de/zip
|
||||||
(for [square-location (:client/square-locations client)
|
(for [square-location (:client/square-locations client)
|
||||||
:when (:square-location/client-location square-location)]
|
:when (:square-location/client-location square-location)]
|
||||||
(remove-voided-orders client square-location (time/plus (time/now) (time/days -30)) (time/now)))))
|
(remove-voided-orders client square-location (time/plus (time/now) (time/days -10)) (time/now)))))
|
||||||
([client location start end]
|
([client location start end]
|
||||||
(let [start (max-date start (coerce/to-date-time #inst "2024-04-15T00:00:00-08:00"))]
|
(let [start (max-date start (coerce/to-date-time #inst "2024-04-15T00:00:00-08:00"))]
|
||||||
(capture-context->lc
|
(capture-context->lc
|
||||||
|
|||||||
319
src/clj/auto_ap/ssr/company.clj.bak
Normal file
319
src/clj/auto_ap/ssr/company.clj.bak
Normal file
@@ -0,0 +1,319 @@
|
|||||||
|
(ns auto-ap.ssr.company
|
||||||
|
(:require [amazonica.aws.s3 :as s3]
|
||||||
|
[auto-ap.datomic :refer [conn pull-attr]]
|
||||||
|
[auto-ap.datomic.clients :refer [full-read]]
|
||||||
|
[auto-ap.graphql.utils :refer [assert-can-see-client]]
|
||||||
|
[auto-ap.permissions :as permissions]
|
||||||
|
[auto-ap.solr :as solr]
|
||||||
|
[auto-ap.ssr-routes :as ssr-routes]
|
||||||
|
[auto-ap.ssr.components :as com]
|
||||||
|
[auto-ap.ssr.hx :as hx]
|
||||||
|
[auto-ap.ssr.svg :as svg]
|
||||||
|
[auto-ap.ssr.ui :refer [base-page]]
|
||||||
|
[auto-ap.ssr.utils :refer [html-response]]
|
||||||
|
[bidi.bidi :as bidi]
|
||||||
|
[cemerick.url :as url]
|
||||||
|
[clojure.java.io :as io]
|
||||||
|
[clojure.string :as str]
|
||||||
|
[config.core :refer [env]]
|
||||||
|
[datomic.api :as dc]
|
||||||
|
[ring.middleware.json :refer [wrap-json-response]])
|
||||||
|
(:import [java.util UUID]
|
||||||
|
(org.apache.commons.codec.binary Base64)))
|
||||||
|
|
||||||
|
(defn please-select-client-screen* []
|
||||||
|
[:div.grid.grid-cols-3
|
||||||
|
(com/content-card {}
|
||||||
|
[:div.col-span-1.p-4 {:class "p-4 sm:p-6"}
|
||||||
|
[:h3 {:class "mb-4 text-xl font-semibold dark:text-white"}
|
||||||
|
"Please select a company"]])])
|
||||||
|
|
||||||
|
(defn signature [request]
|
||||||
|
(let [signature-file (pull-attr (dc/db conn) :client/signature-file (:db/id (:client request)))]
|
||||||
|
(com/content-card {:class " w-[748px]"
|
||||||
|
:hx-target "this"
|
||||||
|
:hx-swap "outerHTML"}
|
||||||
|
[:div.col-span-1.p-4 {:class "p-4 sm:p-6 space-y-4 overflow-visible "
|
||||||
|
}
|
||||||
|
[:h3 {:class "mb-4 text-xl font-semibold dark:text-white"}
|
||||||
|
"Signature"]
|
||||||
|
[:div#signature-notification.notification.block {:style {:display "none"}}]
|
||||||
|
[:div {:x-data (hx/json {"signature" nil
|
||||||
|
"editing" false
|
||||||
|
"existing" (boolean signature-file)})
|
||||||
|
:hx-put (bidi/path-for ssr-routes/only-routes
|
||||||
|
:company-update-signature)
|
||||||
|
:hx-trigger "accepted"
|
||||||
|
:hx-vals "js:{signatureData: event.detail.signatureData}"}
|
||||||
|
[:div.htmx-indicator
|
||||||
|
[:div.bg-gray-100.flex.items-center.text-green-500.justify-center.rounded.rounded-lg.border.border-gray-400 {:style {:width "696px" :height "261px"}}
|
||||||
|
(svg/spinner {:class "w-4 h-4 text-primary-300"})
|
||||||
|
[:div.ml-3 "Loading..."]]]
|
||||||
|
|
||||||
|
[:div.htmx-indicator-hidden
|
||||||
|
(when signature-file
|
||||||
|
[:img.rounded.rounded-lg.border.border-gray-300.bg-gray-50 {:src signature-file
|
||||||
|
:width 696
|
||||||
|
:height 261
|
||||||
|
:x-show "existing && !editing"}])
|
||||||
|
[:canvas.rounded.rounded-lg.border.border-gray-300
|
||||||
|
|
||||||
|
|
||||||
|
{:style {:width 696
|
||||||
|
:height 261}
|
||||||
|
:x-init "signature= new SignaturePad($el); signature.off()"
|
||||||
|
":class" "editing ? 'bg-white' : 'bg-gray-50' "
|
||||||
|
:width 696
|
||||||
|
:height 261
|
||||||
|
:x-show "existing ? editing: true"}]]
|
||||||
|
|
||||||
|
|
||||||
|
[:div.flex.gap-2.justify-end
|
||||||
|
(com/button {:color :primary
|
||||||
|
:x-show "!editing"
|
||||||
|
"@click" "signature.clear(); signature.on(); editing=true;"}
|
||||||
|
"New signature")
|
||||||
|
(com/button {:color :primary
|
||||||
|
:x-show "editing"
|
||||||
|
"@click" "signature.clear();"}
|
||||||
|
"Clear")
|
||||||
|
|
||||||
|
(com/button {:color :primary
|
||||||
|
"@click" "$data.signatureData=signature.toDataURL('image/png'); signature.off(); editing=false; $dispatch('accepted', {signatureData: $data.signatureData}) "
|
||||||
|
:x-show "editing"}
|
||||||
|
"Accept")]]
|
||||||
|
|
||||||
|
[:div
|
||||||
|
[:div.flex.justify-center " - or -"]
|
||||||
|
[:form {:hx-post (bidi/path-for ssr-routes/only-routes
|
||||||
|
:company-upload-signature)
|
||||||
|
:hx-disinherit "hx-vals"
|
||||||
|
:hx-encoding "multipart/form-data"
|
||||||
|
#_#_:hx-target "#signature-notification"
|
||||||
|
:hx-swap "outerHTML"
|
||||||
|
:id "upload"
|
||||||
|
:hx-trigger "z"
|
||||||
|
}
|
||||||
|
[:div.htmx-indicator
|
||||||
|
[:div.bg-gray-100.flex.items-center.text-green-500.justify-center.rounded.rounded-lg.border.border-gray-400 {:style {:width "696px" :height "261px"}}
|
||||||
|
(svg/spinner {:class "w-4 h-4 text-primary-300"})
|
||||||
|
[:div.ml-3 "Loading..."]]]
|
||||||
|
[:div.htmx-indicator-hidden
|
||||||
|
[:div.border-2.border-dashed.rounded-lg.p-4.w-full.text-center.cursor-pointer.h-64.flex.items-center.justify-center.text-lg.relative
|
||||||
|
{:x-data (hx/json {"files" nil
|
||||||
|
"hovering" false})
|
||||||
|
:x-dispatch:z "files"
|
||||||
|
":class" "{'bg-blue-100': !hovering,
|
||||||
|
'border-blue-300': !hovering,
|
||||||
|
'text-blue-700': !hovering,
|
||||||
|
'bg-green-100': hovering,
|
||||||
|
'border-green-300': hovering,
|
||||||
|
'text-green-700': hovering
|
||||||
|
}"}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[:input {:type "file"
|
||||||
|
:name "file"
|
||||||
|
:class "absolute inset-0 m-0 p-0 w-full h-full outline-none opacity-0",
|
||||||
|
:x-on:change "files = $event.target.files;",
|
||||||
|
:x-on:dragover "hovering = true",
|
||||||
|
:x-on:dragleave "hovering = false",
|
||||||
|
:x-on:drop "hovering = false"}]
|
||||||
|
[:div.flex.flex-col.space-2
|
||||||
|
[:div
|
||||||
|
[:ul {:x-show "files != null"}
|
||||||
|
[:template {:x-for "f in files"}
|
||||||
|
[:li (com/pill {:color :primary :x-text "f.name"})]]]]
|
||||||
|
|
||||||
|
|
||||||
|
[:div.htmx-indicator-hidden "Drop a signature file (696x261 pixels jpeg) here."]]]] ]]])))
|
||||||
|
|
||||||
|
(defn upload-signature-data [{{:strs [signatureData]} :form-params client :client :as request}]
|
||||||
|
(let [prefix "data:image/png;base64,"]
|
||||||
|
(when signatureData
|
||||||
|
(when-not (str/starts-with? signatureData prefix)
|
||||||
|
(throw (ex-info "Invalid signature image" {:validation-error (str "Invalid signature image.")})))
|
||||||
|
(let [signature-id (str (UUID/randomUUID))
|
||||||
|
raw-bytes (Base64/decodeBase64 (subs signatureData (count prefix)))]
|
||||||
|
(s3/put-object :bucket-name "integreat-signature-images" #_(:data-bucket env)
|
||||||
|
:key (str signature-id ".png")
|
||||||
|
:input-stream (io/make-input-stream raw-bytes {})
|
||||||
|
:metadata {:content-type "image/png"
|
||||||
|
:content-length (count raw-bytes)}
|
||||||
|
:canned-acl "public-read")
|
||||||
|
@(dc/transact conn [{:db/id (:db/id client)
|
||||||
|
:client/signature-file (str "https://integreat-signature-images.s3.amazonaws.com/" signature-id ".png")}])
|
||||||
|
(html-response
|
||||||
|
(signature request))))))
|
||||||
|
|
||||||
|
(defn upload-signature-file [{{:strs [signatureData]} :form-params client :client user :identity :as request}]
|
||||||
|
(assert-can-see-client user client)
|
||||||
|
(let [{:strs [file]} (:multipart-params request) ]
|
||||||
|
(try
|
||||||
|
(let [signature-id (str (UUID/randomUUID)) ]
|
||||||
|
(s3/put-object :bucket-name "integreat-signature-images" #_(:data-bucket env)
|
||||||
|
:key (str signature-id ".jpg")
|
||||||
|
:input-stream (io/input-stream (:tempfile file))
|
||||||
|
:metadata {:content-type "image/jpeg"
|
||||||
|
:content-length (:length (:tempfile file))}
|
||||||
|
:canned-acl "public-read")
|
||||||
|
@(dc/transact conn [{:db/id (:db/id client)
|
||||||
|
:client/signature-file (str "https://integreat-signature-images.s3.amazonaws.com/" signature-id ".jpg")}])
|
||||||
|
(html-response
|
||||||
|
(signature request)))
|
||||||
|
(catch Exception e
|
||||||
|
(println e)
|
||||||
|
#_(-> result
|
||||||
|
(assoc :error? true)
|
||||||
|
(update :results conj {:filename filename
|
||||||
|
:response (.getMessage e)
|
||||||
|
:sample (:sample (ex-data e))
|
||||||
|
:template (:template (ex-data e))}))))
|
||||||
|
#_(html-response [:div#page-notification.p-4.rounded-lg
|
||||||
|
{:class (if (:error? results)
|
||||||
|
"bg-red-50 text-red-700"
|
||||||
|
"bg-primary-50 text-primary-700")}
|
||||||
|
[:table
|
||||||
|
[:thead
|
||||||
|
[:tr [:td "File"] [:td "Result"]
|
||||||
|
[:td "Template"]
|
||||||
|
(if (:error? results)
|
||||||
|
[:td "Sample match"])]
|
||||||
|
#_[:tr "Result"]
|
||||||
|
#_[:tr "Template"]]
|
||||||
|
(for [r (:results results)]
|
||||||
|
[:tr
|
||||||
|
[:td.p-2.border
|
||||||
|
{:class (if (:error? results)
|
||||||
|
"bg-red-50 text-red-700 border-red-300"
|
||||||
|
"bg-primary-50 text-primary-700 border-green-500")}
|
||||||
|
(:filename r)]
|
||||||
|
[:td.p-2.border
|
||||||
|
{:class (if (:error? results)
|
||||||
|
"bg-red-50 text-red-700 border-red-300"
|
||||||
|
"bg-primary-50 text-primary-700 border-green-500")}
|
||||||
|
(:response r)]
|
||||||
|
[:td.p-2.border
|
||||||
|
{:class (if (:error? results)
|
||||||
|
"bg-red-50 text-red-700 border-red-300"
|
||||||
|
"bg-primary-50 text-primary-700 border-green-500")}
|
||||||
|
"Template: " (:template r)]
|
||||||
|
(if (:error? results)
|
||||||
|
[:td.p-2.border
|
||||||
|
{:class "bg-red-50 text-red-700 border-red-300"}
|
||||||
|
|
||||||
|
[:ul
|
||||||
|
(for [[k v] (dissoc (:sample r) :template :source-url :full-text :text)]
|
||||||
|
[:li (name k) ": " (str v)])]
|
||||||
|
#_(:template r)])])]]
|
||||||
|
:headers
|
||||||
|
{"hx-trigger" "invalidated"})))
|
||||||
|
|
||||||
|
(defn main-content* [{:keys [client identity] :as request}]
|
||||||
|
(if-not client
|
||||||
|
(please-select-client-screen*)
|
||||||
|
(let [client (dc/pull (dc/db conn) full-read (:db/id client))]
|
||||||
|
[:div
|
||||||
|
[:div.grid.grid-cols-3.gap-4
|
||||||
|
(com/content-card {}
|
||||||
|
[:div.col-span-1.p-4 {:class "p-4 sm:p-6"}
|
||||||
|
[:h3 {:class "mb-4 text-xl font-semibold dark:text-white"}
|
||||||
|
(:client/name client)]
|
||||||
|
(when-let [address (-> client :client/address)]
|
||||||
|
[:div.flex.flex-col.gap-1.text-lg.dark:text-white.text-gray-700
|
||||||
|
[:p (-> address :address/street1)]
|
||||||
|
[:p (-> address :address/street2)]
|
||||||
|
[:p (-> address :address/city) " "
|
||||||
|
(-> address :address/state) ", "
|
||||||
|
(-> address :address/zip)]])])
|
||||||
|
(com/content-card {}
|
||||||
|
[:div.col-span-1.p-4 {:class "p-4 sm:p-6"}
|
||||||
|
[:h3 {:class "mb-4 text-xl font-semibold dark:text-white"}
|
||||||
|
"Downloads"]
|
||||||
|
[:a {:href (str (assoc (url/url (str (:base-url env) "/api/vendors/company/export"))
|
||||||
|
:query {"client" (:client/code client)}))}
|
||||||
|
(com/button {:color :primary}
|
||||||
|
"Download vendor list"
|
||||||
|
(com/button-icon {} svg/download))]])
|
||||||
|
[:div]]
|
||||||
|
(when (permissions/can? identity {:client client :subject :signature :activity :edit})
|
||||||
|
(signature request))])))
|
||||||
|
|
||||||
|
(defn page [{:keys [identity matched-route] :as request}]
|
||||||
|
(base-page
|
||||||
|
request
|
||||||
|
(com/page {:nav com/company-aside-nav
|
||||||
|
:client-selection (:client-selection request)
|
||||||
|
:request request
|
||||||
|
:client (:client request)
|
||||||
|
:clients (:clients request)
|
||||||
|
:identity (:identity request)
|
||||||
|
:app-params {:hx-get (bidi/path-for ssr-routes/only-routes
|
||||||
|
:company)
|
||||||
|
:hx-trigger "clientSelected from:body"
|
||||||
|
:hx-select "#app-contents"
|
||||||
|
:hx-swap "outerHTML swap:300ms"}}
|
||||||
|
(com/breadcrumbs {}
|
||||||
|
[:a {:href (bidi/path-for ssr-routes/only-routes
|
||||||
|
:company)}
|
||||||
|
"My Company"])
|
||||||
|
(main-content* request))
|
||||||
|
"My Company"))
|
||||||
|
|
||||||
|
(defn search [{:keys [clients query-params]}]
|
||||||
|
(let [valid-client-ids (set (map :db/id clients))
|
||||||
|
name-like-ids (when (not-empty (get query-params "q"))
|
||||||
|
(set (map (comp #(Long/parseLong %) :id)
|
||||||
|
(solr/query solr/impl "clients"
|
||||||
|
{"query" (format "_text_:(%s*)" (str/upper-case (solr/escape (get query-params "q"))))
|
||||||
|
"fields" "id"
|
||||||
|
"limit" 300}))))
|
||||||
|
valid-clients (for [n name-like-ids
|
||||||
|
:when (valid-client-ids n)]
|
||||||
|
{"value" n "label" (pull-attr (dc/db conn) :client/name n)})]
|
||||||
|
{:body (take 10 valid-clients)}))
|
||||||
|
|
||||||
|
(def search (wrap-json-response search))
|
||||||
|
|
||||||
|
|
||||||
|
(defn bank-account-search [{:keys [route-params query-params clients]}]
|
||||||
|
(let [valid-client-ids (set (map :db/id clients))
|
||||||
|
selected-client-id (Long/parseLong (get route-params :db/id))
|
||||||
|
bank-accounts (when (valid-client-ids selected-client-id)
|
||||||
|
(->> (dc/pull (dc/db conn) [{:client/bank-accounts [:db/id :bank-account/name]}]
|
||||||
|
selected-client-id)
|
||||||
|
:client/bank-accounts
|
||||||
|
(filter (fn [{:keys [bank-account/name]}]
|
||||||
|
(str/includes? (or (some-> name str/upper-case) "")
|
||||||
|
(or (some-> query-params
|
||||||
|
(get "q")
|
||||||
|
str/upper-case)
|
||||||
|
"__"))))
|
||||||
|
(map (fn [{:keys [db/id bank-account/name]}]
|
||||||
|
{"value" id "label" name}))))]
|
||||||
|
{:body (take 10 bank-accounts)}))
|
||||||
|
|
||||||
|
(def bank-account-search (wrap-json-response bank-account-search))
|
||||||
|
|
||||||
|
(defn bank-account-typeahead* [{:keys [client-id name value]}]
|
||||||
|
(if client-id
|
||||||
|
(com/typeahead {:name name
|
||||||
|
:class "w-96"
|
||||||
|
:placeholder "Search..."
|
||||||
|
:url (bidi/path-for ssr-routes/only-routes :bank-account-search
|
||||||
|
:db/id client-id)
|
||||||
|
:value value
|
||||||
|
:value-fn (some-fn :db/id identity)
|
||||||
|
:content-fn (some-fn :bank-account/name #(pull-attr (dc/db conn) :bank-account/name %))})
|
||||||
|
[:span.text-xs.text-gray-500 "Please select a client before selecting a bank account."
|
||||||
|
[:input {:type "hidden"
|
||||||
|
:name name}]]))
|
||||||
|
|
||||||
|
(defn bank-account-typeahead [{:keys [query-params clients]}]
|
||||||
|
(html-response (bank-account-typeahead* {:client-id ((set (map :db/id clients))
|
||||||
|
(some->> "client-id"
|
||||||
|
(get query-params)
|
||||||
|
not-empty
|
||||||
|
Long/parseLong))
|
||||||
|
:name (get query-params "name")})))
|
||||||
Reference in New Issue
Block a user