(ns auto-ap.parse.templates-test (:require [auto-ap.parse :as sut] [clojure.test :refer [deftest is testing]] [clojure.java.io :as io] [clojure.string :as str] [clj-time.core :as time])) (deftest parse-bonanza-produce-invoice-03881260 (testing "Should parse Bonanza Produce invoice 03881260 with customer identifier including address" (let [pdf-file (io/file "dev-resources/INVOICE - 03881260.pdf") ;; Extract text same way parse-file does pdf-text (:out (clojure.java.shell/sh "pdftotext" "-layout" (str pdf-file) "-")) results (sut/parse pdf-text) result (first results)] (is (some? results) "parse should return a result") (is (some? result) "Template should match and return a result") (when result (println "DEBUG: customer-identifier =" (pr-str (:customer-identifier result))) (println "DEBUG: account-number =" (pr-str (:account-number result))) (is (= "Bonanza Produce" (:vendor-code result))) (is (= "03881260" (:invoice-number result))) ;; Date is parsed as org.joda.time.DateTime - compare year/month/day (let [d (:date result)] (is (= 2026 (time/year d))) (is (= 1 (time/month d))) (is (= 20 (time/day d)))) ;; Customer identifier includes name, account-number includes street address ;; Together they form the full customer identification (is (= "NICK THE GREEK" (:customer-identifier result))) (is (= "600 VISTA WAY" (str/trim (:account-number result)))) (is (= "NICK THE GREEK 600 VISTA WAY" (str (:customer-identifier result) " " (str/trim (:account-number result))))) ;; Total is parsed as string, not number (per current behavior) (is (= "23.22" (:total result))))))) (deftest parse-bonanza-produce-statement-13595522 (testing "Should parse Bonanza Produce statement 13595522 with multiple invoices" (let [pdf-file (io/file "dev-resources/13595522.pdf") pdf-text (:out (clojure.java.shell/sh "pdftotext" "-layout" (str pdf-file) "-")) results (sut/parse pdf-text)] (is (some? results) "parse should return results") (is (= 4 (count results)) "Should parse 4 invoices from statement") (doseq [result results] (is (= "Bonanza Produce" (:vendor-code result))) (is (= "600 VISTA WAY" (:customer-identifier result)))) (is (= "03876838" (:invoice-number (nth results 0)))) (is (= "03877314" (:invoice-number (nth results 1)))) (is (= "03878619" (:invoice-number (nth results 2)))) (is (= "03879035" (:invoice-number (nth results 3)))) (is (= "891.65" (:total (nth results 0)))) (is (= "720.33" (:total (nth results 1)))) (is (= "853.16" (:total (nth results 2)))) (is (= "1066.60" (:total (nth results 3))))))) (deftest parse-bonanza-produce-invoice-03882095 (testing "Should parse Bonanza Produce invoice 03882095 with customer identifier including address" (let [pdf-file (io/file "dev-resources/INVOICE - 03882095.pdf") pdf-text (:out (clojure.java.shell/sh "pdftotext" "-layout" (str pdf-file) "-")) results (sut/parse pdf-text) result (first results)] (is (some? results) "parse should return a result") (is (some? result) "Template should match and return a result") (when result (is (= "Bonanza Produce" (:vendor-code result))) (is (= "03882095" (:invoice-number result))) (let [d (:date result)] (is (= 2026 (time/year d))) (is (= 1 (time/month d))) (is (= 23 (time/day d)))) (is (= "NICK THE GREEK" (:customer-identifier result))) (is (= "600 VISTA WAY" (str/trim (:account-number result)))) (is (= "946.24" (:total result))))))) (deftest parse-bonanza-produce-invoice-03932070 (testing "Should parse a Bonanza invoice whose bill-to block carries a mixed-case, punctuated street address" (let [pdf-file (io/file "dev-resources/Bonanza Sample Reno 2.pdf") pdf-text (:out (clojure.java.shell/sh "pdftotext" "-layout" (str pdf-file) "-")) results (sut/parse pdf-text) result (first results)] (is (some? result) "Template should match and return a result") (when result (is (= "Bonanza Produce" (:vendor-code result))) (is (= "03932070" (:invoice-number result))) (let [d (:date result)] (is (= 2026 (time/year d))) (is (= 8 (time/month d))) (is (= 4 (time/day d)))) ;; "10310 N McCARRAN BLVD STE.400" has both lowercase letters and a ;; period; an uppercase/digit-only capture used to drop it entirely, ;; leaving the invoice with no identifier to match a client against. (is (= "10310 N McCARRAN BLVD STE.400" (str/trim (:account-number result)))) (is (str/starts-with? (:customer-identifier result) "NICK THE GREEK")) (is (str/includes? (:customer-identifier result) "McCARRAN")) (is (= "524.17" (:total result))))))) (deftest parse-bonanza-produce-invoice-03933054 (testing "Should keep parsing the sibling Reno location whose address was already extractable" (let [pdf-file (io/file "dev-resources/Bonanza Sample Reno.pdf") pdf-text (:out (clojure.java.shell/sh "pdftotext" "-layout" (str pdf-file) "-")) results (sut/parse pdf-text) result (first results)] (is (some? result) "Template should match and return a result") (when result (is (= "Bonanza Produce" (:vendor-code result))) (is (= "03933054" (:invoice-number result))) (let [d (:date result)] (is (= 2026 (time/year d))) (is (= 8 (time/month d))) (is (= 7 (time/day d)))) (is (= "5140 KIETZKE" (str/trim (:account-number result)))) (is (str/starts-with? (:customer-identifier result) "NICK THE GREEK")) (is (str/includes? (:customer-identifier result) "KIETZKE")) ;; Two-page invoice: the totals only appear on the final page. (is (= "955.75" (:total result))))))) (deftest parse-reel-produce-statement-28676 (testing "Should parse the Reel Produce statement layout that no longer prints 'Reel Produce' on the page" (let [pdf-file (io/file "dev-resources/Statement1_from_REEL_Produce_Inc.28676.pdf") pdf-text (:out (clojure.java.shell/sh "pdftotext" "-layout" (str pdf-file) "-")) results (sut/parse pdf-text)] (is (seq results) "Template should match and return results") (is (= 7 (count results)) "Should parse 7 invoices from statement") (doseq [result results] (is (= "Reel Produce" (:vendor-code result))) (is (= "Sushi Confidential - San Jose" (:customer-identifier result)))) (is (= ["454379" "454826" "455120" "455683" "456654" "456774" "457171"] (mapv :invoice-number results))) (is (= ["1003.10" "530.85" "605.00" "1187.40" "164.00" "675.60" "265.75"] (mapv :total results))) ;; totals add up to the statement's $4,431.70 amount due (is (= 4431.70 (->> results (map #(Double/parseDouble (:total %))) (reduce +)))) (let [d (:date (first results))] (is (= 2026 (time/year d))) (is (= 6 (time/month d))) (is (= 23 (time/day d)))))))