diff --git a/src/clj/auto_ap/parse.clj b/src/clj/auto_ap/parse.clj index cf721bd1..aebf6cb8 100644 --- a/src/clj/auto_ap/parse.clj +++ b/src/clj/auto_ap/parse.clj @@ -1,14 +1,18 @@ (ns auto-ap.parse - (:require - [auto-ap.parse.csv :as csv] - [auto-ap.parse.excel :as excel] - [auto-ap.parse.templates :as t] - [auto-ap.parse.util :as u] - [clj-fuzzy.metrics :as m] - [clojure.java.shell :as sh] - [clojure.set :as set] - [clojure.string :as str] - [auto-ap.logging :as alog])) + (:require [amazonica.aws.lambda :as lambda] + [amazonica.aws.s3 :as s3] + [auto-ap.logging :as alog] + [auto-ap.parse.csv :as csv] + [auto-ap.parse.excel :as excel] + [auto-ap.parse.templates :as t] + [auto-ap.parse.util :as u] + [auto-ap.ssr.vendor :as vendors] + [clj-fuzzy.metrics :as m] + [clojure.data.json :as json] + [clojure.java.io :as io] + [clojure.java.shell :as sh] + [clojure.set :as set] + [clojure.string :as str])) (def last-text (atom nil)) @@ -57,12 +61,44 @@ (defmulti parse-file (fn [_ filename] (.toLowerCase (last (str/split filename #"\." ))))) +(defn invoke-glimpse2 [f] + (doto + (-> (lambda/invoke {:function-name "glimpse2" :payload + (json/write-str + (alog/peek ::x {"url" (str "https://" "data.prod.app.integreatconsult.com" "/" f ) }))}) + :payload + slurp + json/read-str) + println)) + +(defn glimpse2 [file] + (try + (let [tmp-key (str "glimpse2/import/" (java.util.UUID/randomUUID) ".pdf") + _ (with-open [f (io/input-stream file)] + (s3/put-object {:bucket-name "data.prod.app.integreatconsult.com" + :key tmp-key + :input-stream f})) + g (invoke-glimpse2 tmp-key) ] + [ {:date (u/parse-value :clj-time "yyyy-MM-dd" (str/trim (get g "date"))) + :customer-identifier (get g "customer_identifier") + :account-number (not-empty (get g "account_number")) + :vendor-code (-> (vendors/best-match (get g "vendor_identifier") ) + (get "label")) + :total (get g "total") + :invoice-number (get g "invoice_number")}] + ) + (catch Exception e + (alog/warn ::glimpse2-not-work :error e) + nil))) + (defmethod parse-file "pdf" [file _] - (-> (sh/sh "pdftotext" "-layout" file "-") - :out - parse)) + (or + (-> (sh/sh "pdftotext" "-layout" file "-") + :out + parse) + (alog/peek ::glimpse2-result (glimpse2 file)))) (defmethod parse-file "csv" diff --git a/src/clj/auto_ap/ssr/invoice/import.clj b/src/clj/auto_ap/ssr/invoice/import.clj index f9a8b15e..995fb15a 100644 --- a/src/clj/auto_ap/ssr/invoice/import.clj +++ b/src/clj/auto_ap/ssr/invoice/import.clj @@ -337,16 +337,21 @@ (com/content-card {} [:div.px-4.py-3.space-y-4 - + {:x-data (hx/json {"a" false}) + "@started" "a=true" + "@completed" "a=false"} + + #_[:div.bg-red-50.p-8 {:x-show "a"} "HELLO THERE"] + [:div.flex.justify-between.items-center [:h1.text-2xl.mb-3.font-bold "Import new invoices"] - + [:div.flex.gap-2.items-baseline "Trouble with the new upload experience?" - [:a {:href (bidi/path-for client-routes/routes :import-invoices )} + [:a {:href (bidi/path-for client-routes/routes :import-invoices)} (com/pill {:color :secondary} "Go back to previous version")]]] [:div#page-notification.notification.block {:style {:display "none"}}] - - + + [:form {:action (bidi/path-for ssr-routes/only-routes ::route/import-file) @@ -355,7 +360,7 @@ (fc/start-form form-params form-errors [:div.flex.gap-4 - + (fc/with-field :force-client (com/validated-field {:label "Force client" :errors (fc/field-errors)} @@ -370,7 +375,7 @@ (fc/with-field :force-location (com/validated-field {:label "Force location" :errors (fc/field-errors)} - + (com/text-input {:name (fc/field-name) :value (fc/field-value) :size 2}))) @@ -385,18 +390,29 @@ :url (bidi/path-for ssr-routes/only-routes :vendor-search) :value (fc/field-value) :content-fn (fn [c] (pull-attr (dc/db conn) :vendor/name c))})]))]) - [:div.bg-blue-100.border-2.border-dashed.rounded-lg.border-blue-300.p-4.w-full.text-center.cursor-pointer.h-64.flex.items-center.justify-center.text-blue-700.text-lg "Drop files to upload here"]] - [:script - (hiccup/raw - "ezcater_dropzone = new Dropzone (\"#upload\", { - success: function (file, response) { - document.getElementById(\"page-notification\").innerHTML = response; - document.getElementById(\"page-notification\").style[\"display\"] = \"block\"; - document.body.dispatchEvent(new Event('invalidated')); - }, - acceptedFiles: '.xls,.xlsx,.pdf,.csv', - disablePreviews: true - });")]])) + [:div {":class" "a ? 'htmx-request' : ''"} + [:div.bg-blue-100.border-2.border-dashed.rounded-lg.border-blue-300.p-4.w-full.text-center.cursor-pointer.h-64.flex.items-center.justify-center.text-blue-700.text-lg + [:div.htmx-indicator.flex.items-center + (svg/spinner {:class "inline w-4 h-4 text-blue-700"}) + [:div.ml-3 "Loading..."]] + [:div.htmx-indicator-hidden "Drop files to upload here"]] + [:script + (hiccup/raw + "ezcater_dropzone = new Dropzone (\"#upload\", { + init: function() { + this.on('addedfile', () => { document.getElementById('upload').dispatchEvent(new Event('started', {bubbles:true})) }); + }, + + success: function (file, response) { + document.getElementById(\"page-notification\").innerHTML = response; + document.getElementById(\"page-notification\").style[\"display\"] = \"block\"; + document.getElementById('upload').dispatchEvent(new Event('completed', {bubbles:true})) + document.body.dispatchEvent(new Event('invalidated')); + }, + acceptedFiles: '.xls,.xlsx,.pdf,.csv', + disablePreviews: true + }) + ")]]]])) :fetch-page fetch-page :oob-render diff --git a/src/clj/auto_ap/ssr/vendor.clj b/src/clj/auto_ap/ssr/vendor.clj index 3aaa8c41..0f41f0a8 100644 --- a/src/clj/auto_ap/ssr/vendor.clj +++ b/src/clj/auto_ap/ssr/vendor.clj @@ -7,6 +7,19 @@ [datomic.api :as dc] [ring.middleware.json :refer [wrap-json-response]])) +(defn best-match [q] + + (let [name-like-ids (when (not-empty q) + (map (comp #(Long/parseLong %) :id) + (solr/query solr/impl "vendors" + {"query" (cond-> (format "name:(%s*)" (str/upper-case (solr/escape q))) + true (str " hidden:false")) + "fields" "id" + "limit" 300}))) + valid-clients (for [n name-like-ids] + {"value" n "label" (pull-attr (dc/db conn) :vendor/name n)})] + (first valid-clients))) + (defn search [{:keys [clients query-params identity]}] (let [name-like-ids (when (not-empty (get query-params "q"))