Merge branch 'side-panel' of bitbucket.org:brycecovertoperations/integreat into side-panel
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
[dk.ative/docjure "1.12.0"]
|
||||
[org.clojure/java.jdbc "0.7.3"]
|
||||
[cljsjs/dropzone "4.3.0-0"]
|
||||
[cljsjs/recharts "1.4.2-0"]
|
||||
[clj-fuzzy "0.4.1"]
|
||||
[honeysql "0.9.2"]
|
||||
[com.walmartlabs/lacinia "0.25.0"]
|
||||
@@ -47,6 +48,7 @@
|
||||
[com.amazonaws/aws-java-sdk-sqs "1.11.282"]
|
||||
[com.amazonaws/aws-java-sdk-s3 "1.11.282"]
|
||||
[org.clojure/data.json "0.2.6"]
|
||||
[org.clojure/data.csv "0.1.4"]
|
||||
[cider/cider-nrepl "0.16.0"]
|
||||
[io.rkn/conformity "0.5.1"]
|
||||
[hiccup "1.0.5"]]
|
||||
@@ -74,7 +76,6 @@
|
||||
[javax.servlet/servlet-api "2.5"]
|
||||
[figwheel-sidecar "0.5.13"]
|
||||
[com.cemerick/piggieback "0.2.2"]
|
||||
[org.clojure/data.csv "0.1.4"]
|
||||
]
|
||||
|
||||
:plugins [[lein-figwheel "0.5.13"]
|
||||
@@ -83,7 +84,8 @@
|
||||
:jvm-opts ["-Dconfig=config/dev.edn" "--add-modules" "java.xml.bind"]}
|
||||
:uberjar {:prep-tasks [["cljsbuild" "once" "min"] "compile"]}
|
||||
:provided {:dependencies [[org.clojure/clojurescript "1.10.238"]
|
||||
[reagent "0.7.0"]
|
||||
[reagent "0.7.0" ]
|
||||
[cljsjs/react-transition-group "2.4.0-0"]
|
||||
[re-frame "0.10.2"]
|
||||
[com.andrewmcveigh/cljs-time "0.5.2"]]}}
|
||||
|
||||
|
||||
25
resources/payout-list.csv
Normal file
25
resources/payout-list.csv
Normal file
@@ -0,0 +1,25 @@
|
||||
[:vendor/name],[:vendor/print-as],[:vendor/default-expense-account],[:vendor/address],[:vendor/address :address/street1],[:vendor/address :address/street2],[:vendor/address :address/city],[:vendor/address :address/state],[:vendor/address :address/zip],[:vendor/primary-contact :contact/name],[:vendor/primary-contact :contact/email],[:vendor/primary-contact :contact/phone],[:vendor/secondary-contact :contact/name],[:vendor/secondary-contact :contact/email],[:vendor/secondary-contact :contact/phone],[:vendor/invoice-reminder-schedule]
|
||||
PAY OUTS - CB 5110 Food Cost,,5110,,,,,,,,,,,,,
|
||||
PAY OUTS - CB 5910 Paperware Cost,,5910,,,,,,,,,,,,,
|
||||
PAY OUTS - CB 7210 Flowers and ST Decorations,,7210,,,,,,,,,,,,,
|
||||
PAY OUTS - CB 7315 Freight and Fuel Charges,,7315,,,,,,,,,,,,,
|
||||
PAY OUTS - CB 7315 Freight and Fuel Charges,,7315,,,,,,,,,,,,,
|
||||
PAY OUTS - CB 7320 Kitchen Supplies,,7320,,,,,,,,,,,,,
|
||||
PAY OUTS - CB 7410 Cleaning Supplies,,7410,,,,,,,,,,,,,
|
||||
PAY OUTS - CB 7450 Building Cleaning & Maintenance,,7450,,,,,,,,,,,,,
|
||||
PAY OUTS - CB 7460 Repairs to Equipment,,7460,,,,,,,,,,,,,
|
||||
PAY OUTS - CB 7461 Contract Labor,,7461,,,,,,,,,,,,,
|
||||
PAY OUTS - CB 7510 Office Supplies,,7510,,,,,,,,,,,,,
|
||||
PAY OUTS - HQ 9160 Meals and Entertainment - HQ,,9160,,,,,,,,,,,,,
|
||||
PAY OUTS - HQ 9180 Food Research - HQ,,9180,,,,,,,,,,,,,
|
||||
PAY OUTS - meals,,9160,,,,,,,,,,,,,
|
||||
PAY OUTS - WG 5110 Food Cost,,5110,,,,,,,,,,,,,
|
||||
PAY OUTS - WG 5910 Paperware Cost,,5910,,,,,,,,,,,,,
|
||||
PAY OUTS - WG 7210 Flowers and ST Decorations,,7210,,,,,,,,,,,,,
|
||||
PAY OUTS - WG 7315 Freight and Fuel Charges,,7315,,,,,,,,,,,,,
|
||||
PAY OUTS - WG 7320 Kitchen Supplies,,7320,,,,,,,,,,,,,
|
||||
PAY OUTS - WG 7410 Cleaning Supplies,,7410,,,,,,,,,,,,,
|
||||
PAY OUTS - WG 7450 Building Cleaning & Maintenance,,7450,,,,,,,,,,,,,
|
||||
PAY OUTS - WG 7460 Repairs to Equipment,,7460,,,,,,,,,,,,,
|
||||
PAY OUTS - WG 7460 Contract Labor,,7461,,,,,,,,,,,,,
|
||||
PAY OUTS - WG 7510 Office Supplies,,7510,,,,,,,,,,,,,
|
||||
|
10525
resources/public/css/bulma.css
vendored
Normal file
10525
resources/public/css/bulma.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
resources/public/css/bulma.css.map
Normal file
1
resources/public/css/bulma.css.map
Normal file
File diff suppressed because one or more lines are too long
3
resources/public/css/bulma.min.css
vendored
3
resources/public/css/bulma.min.css
vendored
File diff suppressed because one or more lines are too long
@@ -68,9 +68,6 @@
|
||||
animation: flashPrimary 1.0s ease both;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
.left-nav {
|
||||
width: 300px;
|
||||
}
|
||||
.nav.is-dark {
|
||||
background-color: #232B2D;
|
||||
color: #F6F7F7;
|
||||
@@ -146,7 +143,7 @@ nav.navbar .navbar-item.is-active {
|
||||
font-weight: 700;
|
||||
}
|
||||
.aside .main {
|
||||
padding: 40px;
|
||||
padding: 40px 10px 40px 30px;
|
||||
color: #6F7B7E;
|
||||
}
|
||||
|
||||
@@ -186,7 +183,7 @@ nav.navbar .navbar-item.is-active {
|
||||
font-weight: 500;
|
||||
}
|
||||
.messages {
|
||||
padding: 40px 20px;
|
||||
padding: 40px 40px 0px 20px;
|
||||
}
|
||||
.message {
|
||||
padding: 40px 20px;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<html class="has-navbar-fixed-top">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
@@ -7,7 +7,7 @@
|
||||
<title>Integreat</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha256-eZrrJcwDc/3uDhsdt61sL2oOBY362qM3lon1gyExkL0=" crossorigin="anonymous" />
|
||||
<link href="/css/font.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="/css/bulma.min.css" integrity="sha256-HEtF7HLJZSC3Le1HcsWbz1hDYFPZCqDhZa9QsCgVUdw=" crossorigin="anonymous" />
|
||||
<link rel="stylesheet" href="/css/bulma.min.css" />
|
||||
<link rel="stylesheet" href="/css/bulma-calendar.min.css" />
|
||||
<link rel="stylesheet" href="/css/bulma-badge.min.css" />
|
||||
<link rel="stylesheet" href="/css/animate.css" />
|
||||
|
||||
132
resources/vendor-list.csv
Normal file
132
resources/vendor-list.csv
Normal file
@@ -0,0 +1,132 @@
|
||||
[:vendor/name],[:vendor/print-as],[:vendor/default-expense-account],[:vendor/address],[:vendor/address :address/street1],[:vendor/address :address/street2],[:vendor/address :address/city],[:vendor/address :address/state],[:vendor/address :address/zip],[:vendor/primary-contact :contact/name],[:vendor/primary-contact :contact/email],[:vendor/primary-contact :contact/phone],[:vendor/secondary-contact :contact/name],[:vendor/secondary-contact :contact/email],[:vendor/secondary-contact :contact/phone],[:vendor/invoice-reminder-schedule]
|
||||
Aaron mendoza guadarama,,9220,,,,,,,,,,,,,
|
||||
ABC Insurance Services ,,8511,,3401 Pacific Blvd,,San Mateo,CA,94403,,,,,,,
|
||||
"ADP, INC",,9315,,"504 CLINTON CENTER DR, STE 4400",,CLINTON,MS,39056,,,,,,,
|
||||
"ANAGO FRANCHISING, INC",,7415,,"1460 KOLL CIRCLE, SUITE B",,SAN JOSE,CA,95112,,,,,,,
|
||||
Andy Younan,,A3304,,,,,,,,,,,,,
|
||||
ARC LOCKSMITH,,7440,,,,,,,,,,,,,
|
||||
Bakemart,,5110,,,,,,,,,,,,,
|
||||
Bank of America - Los Angeles,Bank of America,A1298,,P O BOX 301200,,LOS ANGELES,CA,90030-1200,,,,,,,
|
||||
Bay lighting supply,,8310,,979 el camino real,,Santa Clara,CA,95050,,,,,,,
|
||||
Beaucanon,,5510,,1006 Monticello Road,,Napa,CA,94558,,,,,,,
|
||||
Bellaginevera,,5110,,,,,,,,,,,,,
|
||||
Benedetto Di Giallorenzo,,7440,,,,,,,,,,,,,
|
||||
Big Basin Cafe,,5220,,14471 Big Basin Way,,Saratoga,CA,95070,,,,,,,
|
||||
Big Four Restaurant,,9160,,,,,,,,,,,,,
|
||||
BLUE SHIELD OF CA,,6040,,,,LOS ANGELES,CA,90074-5331,,,,,,,
|
||||
Brendon Dias,,9220,,P. O. Box 4258,,Santa Cruz,CA,95063,,,,,,,
|
||||
BURR PLUMBING,,7440,,1645 ALMADEN RD,,SAN JOSE,CA,95125,,,,,,,
|
||||
CAPITAL ONE,,A1298,,P O BOX 60599 ,,CITY OF INDUSTRY,CA,91716-0599,,,,,,,
|
||||
Central Storage,,9383,,,,,,,,,,,,,
|
||||
Champion Plumbing,,7440,,,,San Jose,Ca,,,,,,,,
|
||||
CHASE,,A1298,,P O BOX 94014,,PALATINE,IL,60094-4014,,,,,,,
|
||||
City of Saratoga,,8130,,,,,,,,,,,,,
|
||||
Clark Pest Control,,7450,,PO BOX 1480,,Lodi,CA,95241,,,,,,,
|
||||
Classic Mix - Galloway Company,,5110,,,,,,,,,,,,,
|
||||
Clyde Zaya,,A3301,,,,,,,,,,,,,
|
||||
COCA-COLA,,5210,,,,LOS ANGELES,CA,90074-3158,,,,,,,
|
||||
COLD Brew,,7420,,,,,,,,,,,,,
|
||||
COLD CRAFT INC,,7460,,P.O. BOX 32024,,LOS GATOS,CA,95032-0104,,,,,,,
|
||||
COSTCO WHOLESALE,,9190,,PO BOX 34783,,SEATTLE,WA,98124-1783,,,,,,,
|
||||
Creative drinks inc.,,7460,,p.o. box 842,,Los Gatos,CA,95031-0842,,,,,,,
|
||||
D.G.HEATING & AIR CONDITIONING,,7460,,,,,,,,,,,,,
|
||||
DANNY APPLIANCE,,7460,,,,,,,,,,,,,
|
||||
David Correa,,A1280,,P.O. Box 12084,,Pleasanton,CA,94588,,,,,,,
|
||||
DMV,,9170,,PO BOX 942897,,SACRAMENTO,CA,94297-0897,,,,,,,
|
||||
E M Fire Protection,,7450,,1120 Eaton Ave #5,,San Carlos,Ca,94070,,,,,,,
|
||||
EDGAR MENDOZA,,7461,,,,,,,,,,,,,
|
||||
EDWARD P. MATHEWSON,,9310,,"152 NORTH THIRD ST, STE 800",,SAN JOSE,CA,95112,,,,,,,
|
||||
Enter Design & Lights,,7440,,1167 Chess Dr Suite # B,,Foster City,CA,94404,,,,,,,
|
||||
Felix Amerian,,7244,,,,,,,,,,,,,
|
||||
FIRESHIELD,,7460,,7450 DOWDY STREET,,GILROY,CA,95020,,,,,,,
|
||||
Friuli italian wine imports llc,,4510,,3130 rubino dr #105,,San Jose,CA,95125,,,,,,,
|
||||
"G & T TECH, Inc",,7460,,P O BOX 5762,,REDWOOD CITY,CA,94063,,,,,,,
|
||||
Givmar Precision Machining,,7460,,1904 Colony Street,,Mountain View,CA,94043,,,,,,,
|
||||
Greenback,,8210,,,,,,,,,,,,,
|
||||
Grim fire protection,,7440,,p.o.box 1118,,Boulder Creek,Ca,95006,,,,,,,
|
||||
hacienda produce company,,5120,,p.o. box 8443,,San Jose,Ca,95155,,,,,,,
|
||||
HD ELECTRIC,,7440,,"1090 LINCOLN AVE, SUITE 10",,SAN JOSE,CA,95125,,,,,,,
|
||||
HEALTH SMART FOODS,,5110,,,,,,,,,,,,,
|
||||
Heart String Music,,7244,,2273 Old Milddlefield Way,,Mountian View,CA,94043,,,,,,,
|
||||
Hugo Wainginger,,7246,,,,,,,,,,,,,
|
||||
ICE CREAM SOLUTIONS,,5110,,P O BOX 33816,,GRANADA HILLSE,CA,9139,,,,,,,
|
||||
Impact Paper & Ink LTD,,7510,,1590 Gilbreth Rd,,Burlingame,CA,94010,,,,,,,
|
||||
IRS,,9710,,P. O. Box 37900,,Heartford,CT,6176,,,,,,,
|
||||
J Drains,,A1520,,,,,,,,,,,,,
|
||||
j&b,,7460,,411 lewis rd-425,,San Jose,CA,95111,,,,,,,
|
||||
J&T Handyman,,7440,,100 PANORAMA WAY,,LOS GATOS,CA,,,,,,,,
|
||||
JCA ARCHITECT & DESIGN,,7440,,1028 LINCOLN AVE,,SAN JOSE,CA,95125,,,,,,,
|
||||
Jeff Hickey,,7440,,,,,,,,,,,,,
|
||||
Jeff Mullen,,A3301,,,,,,,,,,,,,
|
||||
JESSE SALECDA,,5110,,,,,,,,,,,,,
|
||||
Kelex Security,,8351,,2959 s. winchester BLVD ste 100,,Campbell,CA,95008,,,,,,,
|
||||
lang vo,,A1240,,,,,,,,,,,,,
|
||||
Le Boulanger,,5140,,305 NORTH MATHILDA AVE.,,SUNNYVALE,CA,94085,,,,,,,
|
||||
Leslie Kurnick,,A1260,,1667 Page St.,,San Francisco,CA,94117,,,,,,,
|
||||
LIMPIO CLEANING,,7415,,,,,,,,,,,,,
|
||||
"M.E. Fox & Company, Inc",,5410,,P.O. Box 60000,,San Francisco,CA,94160,,,,,,,
|
||||
Mahnaz Khazan,,8430,,15219 Sobey rd.,,Saratoga,CA,95070,,,,,,,
|
||||
MARGUARD PAINTING,,7450,,P.O. BOX 8482,,SAN JOSE,CA,95155,,,,,,,
|
||||
Marz Vodka,,5610,,2350 mission college blvd suite 1152,,Santa Clara,CA,95054,,,,,,,
|
||||
"METHOD CONSTRUCTION, INC.",,7440,,PO BOX 2702,,GILROY,CA,95020-4446,,,,,,,
|
||||
METRO PUBLISHING INC,,9110,,BOX 39000 ,,SAN FRANCISCO,CA,94139,,,,,,,
|
||||
Midwest,,8511,,PO BOX 9560,,SPRINGFIELD,IL,62791-9560,,,,,,,
|
||||
Mike Windows,,7460,,4501 SNELL AVE #1202,,SAN JOSE,CA,95136,,,,,,,
|
||||
MOOD MUZAK LLC,,7246,,P O BOX 71070,,CHARLOTTE,NC,28272-1070,,,,,,,
|
||||
"Mr. Freeze, Inc.",,5110,,186 Cleveland Ave,,San Jose,CA,95128,,,,,,,
|
||||
Muscardini cellars llc,,4510,,9380 Sonoma Highway,,Kenwood,CA,95452,,,,,,,
|
||||
Newport Fish Co.,,5114,,457 South Canal ST. So.,,San Francisco,CA,94080,,,,,,,
|
||||
NISSAN MOTOR ACCEPTANCE CORP,,7310,,,,,,,,,,,,,
|
||||
Office of Tourism,,9730,,PO Box 101711,,Pasadena,CA,91189,,,,,,,
|
||||
Olsen's Pressure Washing,,7450,,,,,,,,,,,,,
|
||||
Open table,,7250,,P.O. Box 8395,,Pasadena,CA,91109-8395,,,,,,,
|
||||
P & R PAPER SUPPLY CO,,5910,,2000 University Ave. ,,Berkley,CA,92373,,,,,,,
|
||||
PACIFIC HARVEST SEAFOOD - San Juan,,5114,,P.O. BOX 788,,SAN JUAN BAUTISTA ,CA,95045,,,,,,,
|
||||
PACIFIC PRODUCE,,5120,,P. O. BOX 879,,SOUTH SAN FRANCISCO,CA,94080,,,,,,,
|
||||
Pacific seafood - Boston,,5114,,po box 842757,,Boston,MA,02284-2757,,,,,,,
|
||||
Paja Glen,,8210,,,,,,,,,,,,,
|
||||
Palo Alto Foods,,5110,,,,,,,,,,,,,
|
||||
PETTY ACCOUNT Groceries,,5110,,,,,,,,,,,,,
|
||||
PETTY ACCOUNT Hardware,,7320,,,,,,,,,,,,,
|
||||
Ridge vineyards,,4510,,p.o.box 742749,,los angeles,ca,95070,,,,,,,
|
||||
Rimon,,8110,,,,,,,,,,,,,
|
||||
ROBERT'S GARDENING,,7415,,949 S 11TH ST ,,SAN JOSE,CA,95112,,,,,,,
|
||||
Rombauer Vineyards,,5510,,Department 33313 PO Box 39000,,San Francisco,CA,94139-3313,,,,,,,
|
||||
ROYAL SATELITE,,7160,,,,,,,,,,,,,
|
||||
Ruben sanchez,,A2110,,,,,,,,,,,,,
|
||||
Ruchi Gowda,,5510,,3550 Marsh Manor Way,,San Jose ,CA,95121,,,,,,,
|
||||
Ruzz0 scholl & murphy,,8120,,,,,,,,,,,,,
|
||||
S & S BOOKKEEPING,,9315,,3160 DE LA CRUZ BLVD STE 226,,SANTA CLARA,CA,95054,,,,,,,
|
||||
S.C.C D.T.A.C.,,9730,,,,,,,,,,,,,
|
||||
SAFEGUARD BUSINESS SYS.,,7510,,PO BOX 88043 ,,CHICAGO,IL,60680-1043,,,,,,,
|
||||
SAN JOSE GIANTS,,8210,,P.O. BOX 21727 ,,SAN JOSE,CA,95151,,,,,,,
|
||||
Savannah Chanelle,,5510,,3600 Congress Spring Rd,,Saratoga,CA,95070,,,,,,,
|
||||
SCC Tax Collector,,9730,,"70 West Hedding Street East Wing, 6th Floor ",,San Jose,CA,95110-1767,,,,,,,
|
||||
SILICON VALLEY CARDIOLOGY,,6040,,"1950 UNIVERSITY AVE, #160",,E. PALO ALTO,CA,94303,,,,,,,
|
||||
Silver mountian winery,,5510,,,,,,,,,,,,,
|
||||
Silver oak cellars,,5510,,7370 Highway 128,,Healdsburg,CA,95448,,,,,,,
|
||||
SJP SIGNS,,9110,,1752 JUNCTION AVE,,SAN JOSE,CA,95112,,,,,,,
|
||||
"Skurnik Wines West, LLC",,4510,,P. O. Box 421,,Syosset,NY,11791-1315,,,,,,,
|
||||
Smart plumbers&rooter,,7440,,,,,,,,,,,,,
|
||||
SOFT SERVE PARTS,,7460,,3245 E. PATRICK SUITE A ,,LAS VEGAS,NV,89120,,,,,,,
|
||||
SOOTER CONSULTING INC,,8110,,PO BOX 2301,,MORGAN HILL,CA,95038,,,,,,,
|
||||
SOUTH BAY REFRIGERATION INC,,7460,,P O BOX 54323,,SAN JOSE,CA,95154,,,,,,,
|
||||
"SOUTHWEST TRADERS, INC.",,5110,,,,,,,,,,,,,
|
||||
ST. LUCY SCHOOL,,9150,,76 KENNEDY AVE,,CAMPBELL,CA,95008,,,,,,,
|
||||
STATE FARM INSURANCE SUPPORT CENTER,,6040,,P O BOX 68001 ,,DALLAS,TX,75368-001,,,,,,,
|
||||
SUNLAND CANDY WHOLESALE,,5110,,3232 N. FIGUEROA ST,,LOS ANGELES,CA,90065,,,,,,,
|
||||
Supernova Spirits Inc.,,5610,,2350 Mission College Blvd suite 1152,,Santa Clara,CA,95054,,,,,,,
|
||||
Surveillance Solutions,,8110,,15466 Los Gatos Bvld #109-256,,Los Gatos,CA,95032,,,,,,,
|
||||
TACKTIX GRAPHIX ,,9110,,14938 CAMDEN AVE. #209 ,,SAN JOSE,CA,95124,,,,,,,
|
||||
THE HARDFORD,,9382,,LOCKBOX 0234 PO 7247,,PHILADELPHIA,PA,19170-0234,,,,,,,
|
||||
The Iceman,,7460,,530 Lawrence Expy # 425,,Sunnyvale,CA,94085,,,,,,,
|
||||
TOBIASON AND ROOK BUILDERS ,,7440,,1161 GLENN AVE,,SAN JOSE,CA,95125,,,,,,,
|
||||
Troung Gia LLC,,8210,,1966 Cape Hilda Place,,San Jose,CA,95133,,,,,,,
|
||||
UNITED CONTRACT SERVICES,,7415,,"1161 RINGWOOD COURT, STE 170",,SAN JOSE,CA,95131,,,,,,,
|
||||
VALLEY IMAGES,,7340,,1925 KYLE PARK CT.,,SAN JOSE,CA,95125,,,,,,,
|
||||
VERIZON WIRELESS ,,9380,,P O BOX 660108,,DALLAS,TX,75266-0108,,,,,,,
|
||||
WELLS FARGO FINANCIAL CARDS ,,A1298,,P O BOX 30358,,LOS ANGELES,CA,90030-0358,,,,,,,
|
||||
WEST VALLEY COLLECTION,,8330,,PO BOX 60248,,LOS ANGELES,CA,90060-0248,,,,,,,
|
||||
"West Valley Collection & Recycling, LLC",,7450,,1333 Old Oakland,,San Jose,CA,95112,,,,,,,
|
||||
Western Freezers Specialty Equipment,,7460,,42285 Osgood Rd. Unit F,,Fremont,CA,94539,,,,,,,
|
||||
Winchester printing,,9350,,2383 moorpark Ave.,,San Jose,CA,95128,,,,,,,
|
||||
|
@@ -749,3 +749,15 @@
|
||||
|
||||
(defn migrate-users [conn]
|
||||
[(load-users (users/get-all))])
|
||||
|
||||
(defn merge-query [query-part-1 query-part-2]
|
||||
(-> query-part-1
|
||||
(update-in [:query :find] into (get-in query-part-2 [:query :find]))
|
||||
(update-in [:query :in] into (get-in query-part-2 [:query :in]))
|
||||
(update-in [:query :where] into (get-in query-part-2 [:query :where]))
|
||||
(update-in [:args] into (get-in query-part-2 [:args]))))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -62,9 +62,11 @@
|
||||
:auto-ap/add-import-status {:txes auto-ap.datomic.migrate.invoice-converter/add-import-status :requires [:auto-ap/add-default-location-2]}
|
||||
:auto-ap/add-import-status-existing-invoices {:txes-fn 'auto-ap.datomic.migrate.invoice-converter/add-import-status-existing-invoices :requires [:auto-ap/add-import-status]}
|
||||
:auto-ap/fix-check-numbers {:txes-fn 'auto-ap.datomic.migrate.check-numbers/fix-check-numbers :requires [:auto-ap/add-import-status-existing-invoices]}
|
||||
:auto-ap/add-new-vendors {:txes-fn 'auto-ap.datomic.migrate.add-new-vendors/add-new-vendors :requires [:auto-ap/fix-check-numbers]}
|
||||
}]
|
||||
(println "Conforming database...")
|
||||
(println (c/ensure-conforms conn norms-map))
|
||||
(d/release conn)
|
||||
(println "Done")))
|
||||
#_(-main)
|
||||
|
||||
|
||||
27
src/clj/auto_ap/datomic/migrate/add_new_vendors.clj
Normal file
27
src/clj/auto_ap/datomic/migrate/add_new_vendors.clj
Normal file
@@ -0,0 +1,27 @@
|
||||
(ns auto-ap.datomic.migrate.add-new-vendors
|
||||
(:require [datomic.api :as d]
|
||||
[auto-ap.datomic :refer [uri]]
|
||||
[clojure.data.csv :as csv]
|
||||
[clojure.java.io :as io]
|
||||
[clojure.string :as str])
|
||||
(:import [org.apache.commons.io.input BOMInputStream]))
|
||||
|
||||
(defn add-new-vendors [conn]
|
||||
(let [[header & rows] (-> "vendor-list.csv" (io/resource) io/input-stream (BOMInputStream.) (io/reader) csv/read-csv)
|
||||
headers (map read-string header)
|
||||
new-vendors [(reduce
|
||||
(fn [rows r]
|
||||
(conj rows (reduce
|
||||
(fn [r [header value]]
|
||||
(condp = header
|
||||
[:vendor/address] r
|
||||
[:vendor/default-expense-account] (assoc-in r header (Integer/parseInt (str/replace value #"A" "")))
|
||||
[:vendor/invoice-reminder-schedule] r
|
||||
(assoc-in r header value)))
|
||||
{}
|
||||
(map vector headers r))))
|
||||
[]
|
||||
rows)]]
|
||||
(println (ffirst new-vendors))
|
||||
new-vendors
|
||||
))
|
||||
@@ -3,11 +3,17 @@
|
||||
[auto-ap.datomic :refer [uri]]))
|
||||
|
||||
(defn get-graphql [args]
|
||||
(prn (->> (d/q '[:find (pull ?e [*])
|
||||
:where [?e :vendor/name]]
|
||||
(d/db (d/connect uri)))
|
||||
(map first)
|
||||
(take 5)))
|
||||
|
||||
(->> (d/q '[:find (pull ?e [*])
|
||||
:where [?e :vendor/name]]
|
||||
(d/db (d/connect uri)))
|
||||
(->> (d/q '[:find (pull ?e [*])
|
||||
:where [?e :vendor/name]]
|
||||
(d/db (d/connect uri)))
|
||||
(map first)
|
||||
|
||||
#_(map (fn [c]
|
||||
(update c :client/bank-accounts
|
||||
(fn [bas]
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
[buddy.auth :refer [throw-unauthorized]]
|
||||
[auto-ap.utils :refer [by]]
|
||||
[auto-ap.graphql.utils :refer [assert-admin can-see-client? assert-can-see-client]]
|
||||
[auto-ap.datomic :refer [uri merge-query]]
|
||||
[datomic.api :as d]
|
||||
[auto-ap.expense-accounts :as e-expense-accounts]
|
||||
[auto-ap.datomic.clients :as d-clients]
|
||||
[auto-ap.datomic.checks :as d-checks]
|
||||
[auto-ap.datomic.users :as d-users]
|
||||
@@ -199,12 +202,31 @@
|
||||
:start {:type 'Int}
|
||||
:end {:type 'Int}}}
|
||||
:check_result {:fields {:invoices {:type '(list :invoice)}
|
||||
:pdf_url {:type 'String}}}}
|
||||
:pdf_url {:type 'String}}}
|
||||
|
||||
:expense_account_stat {:fields {:expense_account_id {:type 'Int}
|
||||
:expense_account_name {:type 'String}
|
||||
:total {:type 'String}}}
|
||||
|
||||
:invoice_stat {:fields {:name {:type 'String}
|
||||
:paid {:type 'String}
|
||||
:unpaid {:type 'String}}}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
:queries
|
||||
{:invoice_page {:type '(list :invoice_page)
|
||||
{:expense_account_stats {:type '(list :expense_account_stat)
|
||||
:args {:client_id {:type :id}}
|
||||
:resolve :get-expense-account-stats}
|
||||
|
||||
:invoice_stats {:type '(list :invoice_stat)
|
||||
:args {:client_id {:type :id}}
|
||||
:resolve :get-invoice-stats}
|
||||
|
||||
:invoice_page {:type '(list :invoice_page)
|
||||
:args {:import_status {:type 'String}
|
||||
:status {:type 'String}
|
||||
:client_id {:type :id}
|
||||
@@ -465,6 +487,61 @@
|
||||
(:bank_account_id args)
|
||||
(:type args))))
|
||||
|
||||
(defn get-expense-account-stats [context {:keys [client_id] } value]
|
||||
(let [result (cond-> {:query {:find ['?expense-account-id '(sum ?amount)]
|
||||
:in ['$]
|
||||
:where []}
|
||||
:args [(d/db (d/connect uri)) client_id]}
|
||||
client_id (merge-query {:query {:in ['?c]}
|
||||
|
||||
:args [client_id]})
|
||||
(not client_id) (merge-query {:query {:where ['[?c :client/name]]}})
|
||||
|
||||
true (merge-query {:query {:where ['[?i :invoice/client ?c]
|
||||
'[?i :invoice/expense-accounts ?expense-account]
|
||||
'[?expense-account :invoice-expense-account/expense-account-id ?expense-account-id]
|
||||
'[?expense-account :invoice-expense-account/amount ?amount]]}})
|
||||
true (doto println)
|
||||
|
||||
true (d/query ))]
|
||||
(for [[expense-account-id total] result]
|
||||
{:expense_account_id expense-account-id :total total :expense_account_name (-> expense-account-id e-expense-accounts/expense-accounts :name)})))
|
||||
|
||||
(defn categorize [x]
|
||||
(cond (<= x 0) :due
|
||||
(<= x 30 ) :due-30
|
||||
(<= x 60 ) :due-60
|
||||
:else :due-later))
|
||||
|
||||
(defn get-invoice-stats [context {:keys [client_id] } value]
|
||||
(let [result (cond-> {:query {:find ['?name '(sum ?outstanding-balance) '(sum ?total)]
|
||||
:in ['$]
|
||||
:where []}
|
||||
:args [(d/db (d/connect uri)) client_id]}
|
||||
client_id (merge-query {:query {:in ['?c]}
|
||||
:args [client_id]})
|
||||
(not client_id) (merge-query {:query {:where ['[?c :client/name]]}})
|
||||
|
||||
true (merge-query {:query {:where ['[?i :invoice/client ?c]
|
||||
'[?i :invoice/outstanding-balance ?outstanding-balance]
|
||||
'[?i :invoice/total ?total]
|
||||
'[?i :invoice/date ?date]
|
||||
'[(.toInstant ^java.util.Date ?date) ?d2]
|
||||
'[(.between java.time.temporal.ChronoUnit/DAYS (java.time.Instant/now) ?d2 ) ?d3]
|
||||
'[(+ 30 ?d3) ?d4]
|
||||
'[(auto-ap.graphql/categorize ?d4) ?name]]}})
|
||||
|
||||
true (d/query ))
|
||||
result (group-by first result)]
|
||||
|
||||
(for [[id name] [[:due "Due"] [:due-30 "0-30 days"] [:due-60 "31-60 days"] [:due-later ">60 days"] ]
|
||||
:let [[[_ outstanding-balance total] ] (id result nil)
|
||||
outstanding-balance (or outstanding-balance 0)
|
||||
total (or total 0)]]
|
||||
{:name name :unpaid outstanding-balance :paid (if (= :due id)
|
||||
0
|
||||
(- total outstanding-balance))})))
|
||||
|
||||
|
||||
|
||||
(def schema
|
||||
@@ -474,6 +551,8 @@
|
||||
:get-all-payments get-all-payments
|
||||
:get-payment-page gq-checks/get-payment-page
|
||||
:get-transaction-page gq-transactions/get-transaction-page
|
||||
:get-expense-account-stats get-expense-account-stats
|
||||
:get-invoice-stats get-invoice-stats
|
||||
|
||||
:get-client gq-clients/get-client
|
||||
:get-user get-user
|
||||
@@ -523,7 +602,11 @@
|
||||
([id q v]
|
||||
(println "executing graphql query" id q v)
|
||||
(try
|
||||
(time (simplify (execute schema q v {:id id})))
|
||||
(let [result (time (simplify (execute schema q v {:id id})))]
|
||||
(when (seq (:errors result))
|
||||
(throw (ex-info "GraphQL error" {:result result})))
|
||||
result)
|
||||
|
||||
(catch Exception e
|
||||
(if-let [v (:validation-error (ex-data e))]
|
||||
(println "validation error" v)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
:in ['$ '?code]
|
||||
:where ['[?id :client/code ?code]]}
|
||||
:args [(d/db (d/connect uri)) code]}))
|
||||
(throw (ex-info "Client is not unique" {:validation-error "Client is not unique"}))))
|
||||
(throw (ex-info "Client is not unique" {:validation-error (str "Client code '" code "' is not unique.")}))))
|
||||
|
||||
(defn edit-client [context {:keys [edit_client new_bank_accounts] :as args} value]
|
||||
(assert-admin (:id context))
|
||||
|
||||
@@ -21,7 +21,15 @@
|
||||
:body (pr-str (ql/query (:identity r) (query-params "query") variables ))
|
||||
:headers {"Content-Type" "application/edn"}})
|
||||
(catch Exception e
|
||||
{:status 400
|
||||
:body (pr-str {:data (merge {:message (.getMessage e)} (ex-data e))})
|
||||
:headers {"Content-Type" "application/edn"}}))))
|
||||
(if-let [result (:result (ex-data e))]
|
||||
{:status 400
|
||||
:body (pr-str result)
|
||||
:headers {"Content-Type" "application/edn"}}
|
||||
(if-let [message (:validation-error (ex-data e) )]
|
||||
{:status 400
|
||||
:body (pr-str {:errors [(merge {:message message} (ex-data e))]})
|
||||
:headers {"Content-Type" "application/edn"}}
|
||||
{:status 500
|
||||
:body (pr-str {:errors [(merge {:message (.getMessage e)} (ex-data e))]})
|
||||
:headers {"Content-Type" "application/edn"}}))))))
|
||||
wrap-secure))
|
||||
|
||||
@@ -28,16 +28,16 @@
|
||||
(s/def ::bank-accounts (s/coll-of ::bank-account))
|
||||
|
||||
(s/def ::location string?)
|
||||
(s/def ::locations (s/coll-of ::location))
|
||||
(s/def ::locations (s/coll-of ::location :min-count 1))
|
||||
|
||||
(s/def ::email (s/nilable (s/and string? (s/or :is-email #(re-matches email-regex %)
|
||||
:is-empty #(= % "")))))
|
||||
|
||||
|
||||
(s/def ::client (s/keys :req-un [::name ::code]
|
||||
(s/def ::client (s/keys :req-un [::name ::code ::locations]
|
||||
:opt-un [::email
|
||||
::address
|
||||
::locations
|
||||
|
||||
::bank-accounts
|
||||
::id]))
|
||||
|
||||
|
||||
@@ -337,6 +337,7 @@
|
||||
9365 {:name "Office Maintenance - HQ" :parent 9300 :location "HQ" }
|
||||
9370 {:name "Utilities - HQ" :parent 9300 :location "HQ" }
|
||||
9380 {:name "Telephone - HQ" :parent 9300 :location "HQ" }
|
||||
9383 {:name "Storage - HQ" :parent 9380 :location "HQ" }
|
||||
9500 {:name "HQ Interest and Bank Expenses" :parent nil :location "HQ" }
|
||||
9510 {:name "Bank Fees - HQ" :parent 9500 :location "HQ" }
|
||||
9520 {:name "NSF Fees - HQ" :parent 9500 :location "HQ" }
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
[auto-ap.effects :as effects]
|
||||
[pushy.core :as pushy]
|
||||
[auto-ap.history :as p]
|
||||
[bidi.bidi :as bidi]))
|
||||
[bidi.bidi :as bidi]
|
||||
[cljsjs.recharts]))
|
||||
|
||||
(defn dev-setup []
|
||||
(when true
|
||||
|
||||
@@ -132,6 +132,7 @@
|
||||
(swap! timeouts dissoc key))
|
||||
time))))
|
||||
|
||||
|
||||
(re-frame/reg-fx
|
||||
:graphql
|
||||
(fn [{:keys [query on-success on-error token variables query-obj]}]
|
||||
@@ -148,7 +149,7 @@
|
||||
(when on-error
|
||||
(->> response
|
||||
:body
|
||||
:data
|
||||
:errors
|
||||
(dates->date-times)
|
||||
(conj on-error)
|
||||
(re-frame/dispatch)))
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
::initialize-db
|
||||
(fn [{:keys [db]} [_ token]]
|
||||
(let [handler (:handler (bidi/match-route routes/routes (.. js/window -location -pathname)))]
|
||||
(prn (and token (get (jwt->data token) "user/role")))
|
||||
(cond
|
||||
(and (not= :login handler) (not token))
|
||||
{:redirect "/login"
|
||||
@@ -25,7 +26,7 @@
|
||||
:active-page :login
|
||||
:user token)}
|
||||
|
||||
(and token (= "none" (get (jwt->data token) "role") ))
|
||||
(and token (= "none" (or (get (jwt->data token) "role") (get (jwt->data token) "user/role")) ))
|
||||
{:redirect "/needs-activation"
|
||||
:db (assoc db/default-db
|
||||
:active-page :needs-activation
|
||||
@@ -76,7 +77,8 @@
|
||||
(fn [db [_ {clients :client vendors :vendor :as x}]]
|
||||
(-> db
|
||||
(assoc :clients (by :id clients) )
|
||||
(assoc :vendors (by :id vendors) ))))
|
||||
(assoc :vendors (by :id vendors) )
|
||||
(assoc :client (when (= 1 (count clients)) (->> clients first :id ))))))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::swap-client
|
||||
|
||||
@@ -54,6 +54,12 @@
|
||||
(fn [db]
|
||||
(vals (:vendors db))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::sorted-vendors
|
||||
:<- [::vendors]
|
||||
(fn [vendors]
|
||||
(sort-by :name vendors)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::admin
|
||||
(fn [db]
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
(ns auto-ap.views.components.layouts
|
||||
(:require
|
||||
[cljsjs.react-transition-group]
|
||||
[reagent.core :as reagent]
|
||||
[re-frame.core :as re-frame]
|
||||
[bidi.bidi :as bidi]
|
||||
[auto-ap.routes :as routes]
|
||||
@@ -8,7 +10,8 @@
|
||||
[auto-ap.views.utils :refer [active-when active-when= login-url dispatch-event]]
|
||||
|
||||
[auto-ap.views.components.vendor-dialog :refer [vendor-dialog]]))
|
||||
|
||||
(def css-transition-group
|
||||
(reagent/adapt-react-class js/ReactTransitionGroup.CSSTransition))
|
||||
(defn login-dropdown []
|
||||
(let [user (re-frame/subscribe [::subs/user])
|
||||
menu (re-frame/subscribe [::subs/menu])]
|
||||
@@ -28,7 +31,7 @@
|
||||
(let [client (re-frame/subscribe [::subs/client])
|
||||
clients (re-frame/subscribe [::subs/clients])
|
||||
menu (re-frame/subscribe [::subs/menu])]
|
||||
[:nav {:class "navbar has-shadow"}
|
||||
[:nav {:class "navbar has-shadow is-fixed-top"}
|
||||
[:div {:class "container"}
|
||||
[:div {:class "navbar-brand"}
|
||||
[:a {:class "navbar-item", :href "../"}
|
||||
@@ -52,52 +55,56 @@
|
||||
[:span]
|
||||
[:span]]
|
||||
[:div.navbar-end
|
||||
[:div { :class (str "navbar-item has-dropdown " (when (get-in @menu [:client :active?]) "is-active"))}
|
||||
[:a {:class "navbar-link login" :on-click (fn [] (re-frame/dispatch [::events/toggle-menu :client]))} "Client: " (if @client (:name @client)
|
||||
"All")]
|
||||
[:div {:class "navbar-dropdown"}
|
||||
[:a {:class "navbar-item"
|
||||
:on-click (fn []
|
||||
(re-frame/dispatch [::events/toggle-menu :client])
|
||||
(re-frame/dispatch [::events/swap-client nil]))
|
||||
} "All"]
|
||||
[:hr {:class "navbar-divider"}]
|
||||
(for [{:keys [name id] :as client} @clients]
|
||||
^{:key id }
|
||||
(when (> (count @clients) 1)
|
||||
[:div { :class (str "navbar-item has-dropdown " (when (get-in @menu [:client :active?]) "is-active"))}
|
||||
[:a {:class "navbar-link login" :on-click (fn [] (re-frame/dispatch [::events/toggle-menu :client]))} "Client: " (if @client (:name @client)
|
||||
"All")]
|
||||
[:div {:class "navbar-dropdown"}
|
||||
[:a {:class "navbar-item"
|
||||
:on-click (fn []
|
||||
(re-frame/dispatch [::events/toggle-menu :client])
|
||||
(re-frame/dispatch [::events/swap-client client]))
|
||||
} name])]]]]
|
||||
(re-frame/dispatch [::events/swap-client nil]))
|
||||
} "All"]
|
||||
[:hr {:class "navbar-divider"}]
|
||||
(for [{:keys [name id] :as client} @clients]
|
||||
^{:key id }
|
||||
[:a {:class "navbar-item"
|
||||
:on-click (fn []
|
||||
(re-frame/dispatch [::events/toggle-menu :client])
|
||||
(re-frame/dispatch [::events/swap-client client]))
|
||||
} name])]])]]
|
||||
[login-dropdown]]]))
|
||||
|
||||
(defn footer []
|
||||
[:footer {:class "footer"}
|
||||
[:div {:class "container"}
|
||||
[:div {:class "content has-text-centered"}
|
||||
[:p
|
||||
[:strong "Integreat"]]
|
||||
[:p
|
||||
[:a {:class "icon", :href "https://github.com/dansup/bulma-templates"}
|
||||
[:i {:class "fa fa-github"}]]]]]])
|
||||
[:footer {:style {:padding "1em"}}
|
||||
[:div {:class "content has-text-centered"}
|
||||
[:p
|
||||
[:strong "Integreat"] ]]])
|
||||
|
||||
(defn side-bar-layout [{:keys [side-bar main ap bottom right-side-bar]}]
|
||||
(defn appearing-side-bar [{:keys [visible?]} & children ]
|
||||
(let [final-state (reagent/atom visible?)]
|
||||
(fn [{:keys [visible?]} & children]
|
||||
[css-transition-group {:in visible? :class-names {:exitDone "bounce animated" :exit "fadeOutRight animated" :enter "fadeInRight animated"} :timeout 300 :onEnter (fn [] (reset! final-state true )) :onExited (fn [] (reset! final-state false))}
|
||||
(if (or @final-state visible?)
|
||||
[:aside {:class "column is-3 aside menu" :style {:height "calc(100vh - 46px)" :overflow "auto"}}
|
||||
[:div.sub-main {} children ]]
|
||||
[:div])])))
|
||||
|
||||
(defn side-bar-layout [{:keys [side-bar main ap bottom right-side-bar right-side-bar-visible?]}]
|
||||
(let [ap @(re-frame/subscribe [::subs/active-page])
|
||||
client @(re-frame/subscribe [::subs/client])]
|
||||
[:div
|
||||
[navbar ap]
|
||||
[:div {:class "columns ", :id "mail-app"}
|
||||
[:aside {:class "column is-narrow aside menu hero is-fullheight"}
|
||||
[:div.main.left-nav
|
||||
side-bar]]
|
||||
[:div {:class "column messages hero is-fullheight", :id "message-feed"}
|
||||
[:div {:class "columns has-shadow", :style {:margin-bottom "0px" :height "calc(100vh - 46px)" } :id "mail-app" }
|
||||
[:aside {:class "column aside menu is-2 " }
|
||||
[:div.main.left-nav
|
||||
[:div side-bar
|
||||
]]]
|
||||
[:div {:class "column messages hero " :style { :overflow "auto" }, :id "message-feed"}
|
||||
^{:key (str "active-page-" (:name client))}
|
||||
[:div.inbox-messages main]]
|
||||
(when right-side-bar
|
||||
[:aside.fadeInRight.animated {:class "column aside is-narrow menu hero is-fullheight" :style {:animation-duration "0.75s"}}
|
||||
[:div.sub-main
|
||||
right-side-bar]])]
|
||||
[footer]
|
||||
[appearing-side-bar {:visible? right-side-bar-visible?} right-side-bar]]
|
||||
#_[footer]
|
||||
bottom
|
||||
[:div#dz-hidden]]))
|
||||
|
||||
|
||||
@@ -10,10 +10,12 @@
|
||||
[auto-ap.views.pages.unpaid-invoices :refer [unpaid-invoices-page]]
|
||||
[auto-ap.views.pages.import-invoices :refer [import-invoices-page]]
|
||||
[auto-ap.views.pages.paid-invoices :refer [paid-invoices-page]]
|
||||
[auto-ap.views.pages.needs-activation :refer [needs-activation-page]]
|
||||
[auto-ap.views.pages.transactions :refer [transactions-page]]
|
||||
[auto-ap.views.pages.login :refer [login-page]]
|
||||
[auto-ap.views.pages.checks :refer [checks-page]]
|
||||
[auto-ap.views.pages.admin :refer [admin-page]]
|
||||
[auto-ap.views.pages.home :refer [home-page]]
|
||||
[auto-ap.views.pages.admin.clients :refer [admin-clients-page]]
|
||||
[auto-ap.views.pages.admin.vendors :refer [admin-vendors-page]]
|
||||
[auto-ap.views.pages.admin.excel-import :refer [admin-excel-import-page]]
|
||||
@@ -59,12 +61,16 @@
|
||||
(admin-yodlee-page))
|
||||
|
||||
(defmethod page :index [_]
|
||||
[side-bar-layout {:side-bar [:div]
|
||||
:main [:h1 "Home"]}])
|
||||
(home-page)
|
||||
)
|
||||
|
||||
(defmethod page :login [_]
|
||||
[login-page])
|
||||
|
||||
(defmethod page :needs-activation [_]
|
||||
[needs-activation-page])
|
||||
|
||||
|
||||
(defmethod page :admin-excel-import [_]
|
||||
[admin-excel-import-page])
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
(:require-macros [cljs.core.async.macros :refer [go]]
|
||||
[clojure.string :as str])
|
||||
(:require [re-frame.core :as re-frame]
|
||||
|
||||
[reagent.core :as reagent]
|
||||
[clojure.spec.alpha :as s]
|
||||
[clojure.string :as str]
|
||||
@@ -17,151 +18,149 @@
|
||||
[auto-ap.routes :as routes]
|
||||
[bidi.bidi :as bidi]))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
(re-frame/reg-sub
|
||||
::form
|
||||
(fn [db [_ x]]
|
||||
(-> db ::forms x)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::loading-class
|
||||
(fn [db [_ x]]
|
||||
(if (= (get-in db [::forms x :status]) "loading")
|
||||
"is-loading"
|
||||
"")))
|
||||
|
||||
(defn start-form [db form data]
|
||||
(assoc-in db [::forms form] {:error nil
|
||||
:status nil
|
||||
:data data}))
|
||||
(defn stop-form [db form]
|
||||
(update db ::forms dissoc form))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::form-closing
|
||||
(fn [db [_ f]]
|
||||
|
||||
(-> db
|
||||
(assoc-in [:admin :adding-client?] false)
|
||||
(stop-form f))))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::new
|
||||
(fn [{:keys [db]} [_ client-id]]
|
||||
{:db (-> db (assoc-in [:admin :adding-client?] true)
|
||||
(assoc-in [:admin :new-client] {:new-account {:type :check}}))}))
|
||||
(fn [db [_ client-id]]
|
||||
(-> db
|
||||
(assoc-in [:admin :adding-client?] true)
|
||||
(start-form ::new-client (assoc {} :new-account {:type :check})))))
|
||||
|
||||
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::edit-client-clicked
|
||||
(fn [{:keys [db]} [_ client-id]]
|
||||
{:db (-> db
|
||||
(assoc-in [:admin :new-client] (assoc (get (:clients db) client-id) :new-account {:type :check}))
|
||||
(start-form ::new-client (assoc (get (:clients db) client-id) :new-account {:type :check}))
|
||||
(assoc-in [:admin :adding-client? ] true))}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::save
|
||||
(fn [{:keys [db]} _]
|
||||
(let [edited-client (-> (:client @(re-frame/subscribe [::subs/admin]))
|
||||
(dissoc :location))]
|
||||
{:db (assoc-in db [:admin :client :saving?] true)
|
||||
:graphql
|
||||
{:token (-> db :user)
|
||||
:query-obj {:venia/operation {:operation/type :mutation
|
||||
:operation/name "EditClient"}
|
||||
:venia/queries [{:query/data [:edit-client
|
||||
{:edit-client
|
||||
(-> edited-client
|
||||
(update :bank-accounts #(seq (into % (map (fn [ba] (dissoc ba :is-new?)) (:new-bank-accounts edited-client)))))
|
||||
(dissoc :new-account)
|
||||
(dissoc :new-bank-accounts)
|
||||
)}
|
||||
[:id :name :code :email [:address [:street1 :street2 :city :state :zip]] [:bank-accounts [:id :number :check-number :name :code :bank-code :bank-name :routing]]]]}]}
|
||||
:on-success [::save-complete]
|
||||
:on-error [::save-error]}})))
|
||||
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::save-new-client
|
||||
(fn [{:keys [db]} _]
|
||||
(let [new-client (-> (:new-client @(re-frame/subscribe [::subs/admin]))
|
||||
(dissoc :location))]
|
||||
{:db (assoc-in db [:admin :client :saving?] true)
|
||||
:graphql
|
||||
{:token (-> db :user)
|
||||
:query-obj {:venia/operation {:operation/type :mutation
|
||||
:operation/name "EditClient"}
|
||||
:venia/queries [{:query/data [:edit-client
|
||||
{:edit-client
|
||||
;; TODO - hard code fields we want
|
||||
(-> new-client
|
||||
(update :bank-accounts #(seq (into % (map (fn [ba] (dissoc ba :is-new?)) (:new-bank-accounts new-client)))))
|
||||
(dissoc :new-bank-accounts))
|
||||
}
|
||||
[:id :name :code :email [:address [:street1 :street2 :city :state :zip]] [:bank-accounts [:id :number :check-number :name :code :bank-code :bank-name :routing]]]
|
||||
]}]}
|
||||
:on-success [::save-complete]
|
||||
:on-error [::save-error]}})))
|
||||
[(re-frame/path [::forms ::new-client])]
|
||||
(fn [{{new-client-data :data :as new-client-form} :db} _]
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
(let [new-client-req {:id (:id new-client-data),
|
||||
:name (:name new-client-data)
|
||||
:code (:code new-client-data) ;; TODO add validation can't change
|
||||
:email (:email new-client-data)
|
||||
:locations (:locations new-client-data)
|
||||
:address {:street1 (:street1 (:address new-client-data))
|
||||
:street2 (:street2 (:address new-client-data)),
|
||||
:city (:city (:address new-client-data))
|
||||
:state (:state (:address new-client-data))
|
||||
:zip (:zip (:address new-client-data))}
|
||||
:bank-accounts (map (fn [{:keys [number name check-number type id code bank-name routing bank-code]}]
|
||||
{:number number
|
||||
:name name
|
||||
:check-number check-number
|
||||
:type type
|
||||
:id id
|
||||
:code (str (:code new-client-data) "-" code)
|
||||
:bank-name bank-name
|
||||
:routing routing
|
||||
:bank-code bank-code})
|
||||
(:bank-accounts new-client-data))}
|
||||
user @(re-frame/subscribe [::subs/token])]
|
||||
|
||||
(if (s/valid? ::entity/client new-client-req)
|
||||
|
||||
{:db (-> new-client-form
|
||||
(assoc :status :loading)
|
||||
(assoc :error nil))
|
||||
:graphql
|
||||
{:token user
|
||||
:query-obj {:venia/operation {:operation/type :mutation
|
||||
:operation/name "EditClient"}
|
||||
:venia/queries [{:query/data [:edit-client
|
||||
{:edit-client new-client-req}
|
||||
[:id :name :code :email :locations [:address [:street1 :street2 :city :state :zip]] [:bank-accounts [:id :number :check-number :name :code :bank-code :bank-name :routing]]]]}]}
|
||||
:on-success [::save-complete]
|
||||
:on-error [::save-error]}}
|
||||
{:db new-client-form}))))
|
||||
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::save-complete
|
||||
(fn [{:keys [db]} [_ client]]
|
||||
|
||||
|
||||
{:dispatch [::events/modal-completed :auto-ap.views.pages.admin.clients/edit]
|
||||
:db (-> db
|
||||
(assoc-in [:admin :adding-client?] false)
|
||||
(update :admin dissoc :new-client)
|
||||
|
||||
|
||||
(assoc-in [:admin :client] nil)
|
||||
(assoc-in [:clients (:id (:edit-client client))] (:edit-client client)))}))
|
||||
(fn [db [_ client]]
|
||||
(-> db
|
||||
(stop-form ::new-client)
|
||||
(assoc-in [:admin :adding-client?] false)
|
||||
(assoc-in [:clients (:id (:edit-client client))] (:edit-client client)))))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::save-error
|
||||
(fn [db [_ client]]
|
||||
[(re-frame/path [::forms ::new-client])]
|
||||
(fn [db [_ result]]
|
||||
(-> db
|
||||
(assoc-in [:admin :client :saving?] false)
|
||||
(assoc-in [:admin :client :error] true))))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::change
|
||||
(fn [db [_ path value]]
|
||||
|
||||
(assoc-in db (concat [:admin :client] path)
|
||||
value)))
|
||||
(assoc :status :error)
|
||||
(assoc :error (:message (first result))))))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::change-new
|
||||
[(re-frame/path [::forms ::new-client :data])]
|
||||
(fn [db [_ path value]]
|
||||
|
||||
(assoc-in db (concat [:admin :new-client] path)
|
||||
value)))
|
||||
(assoc-in db path value)))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::add-location
|
||||
(fn [{:keys [db]} _]
|
||||
(let [client (:client @(re-frame/subscribe [::subs/admin]))]
|
||||
{:db (-> db
|
||||
(update-in [:admin :client :locations] conj (:location client))
|
||||
(update-in [:admin :client] dissoc :location))})))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
(re-frame/reg-event-db
|
||||
::add-new-location
|
||||
(fn [{:keys [db]} _]
|
||||
(let [client (:new-client @(re-frame/subscribe [::subs/admin]))]
|
||||
{:db (-> db
|
||||
(update-in [:admin :new-client :locations] conj (:location client))
|
||||
(update-in [:admin :new-client] dissoc :location))})))
|
||||
[(re-frame/path [::forms ::new-client :data])]
|
||||
(fn [client _]
|
||||
(-> client
|
||||
(update :locations conj (:location client))
|
||||
(dissoc :location))))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::add-new-bank-account
|
||||
(fn [{:keys [db]} _]
|
||||
(let [client (:client @(re-frame/subscribe [::subs/admin]))
|
||||
_ (prn (s/explain-data ::entity/bank-account (:new-account client)))
|
||||
new-bank-account (:new-account client)
|
||||
new-bank-account (-> new-bank-account
|
||||
(update :code #(str (:code client) "-" %))
|
||||
(update :check-number #(if (seq %) (js/parseInt %) nil))
|
||||
(update :yodlee-account-id #(if (seq %) (js/parseInt %) nil))
|
||||
(assoc :is-new? true))]
|
||||
{:db (-> db
|
||||
(update-in [:admin :client :new-bank-accounts] (fn [bank-accounts]
|
||||
(conj bank-accounts new-bank-account)))
|
||||
(update-in [:admin :client :new-account] {:type :check}))})))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::add-new-new-bank-account
|
||||
(fn [{:keys [db]} _]
|
||||
(let [client (:new-client @(re-frame/subscribe [::subs/admin]))
|
||||
new-bank-account (:new-account client)
|
||||
new-bank-account (-> new-bank-account
|
||||
(update :code #(str (:code client) "-" %))
|
||||
(update :check-number #(if (seq %) (js/parseInt %) nil))
|
||||
(update :yodlee-account-id #(if (seq %) (js/parseInt %) nil))
|
||||
(assoc :is-new? true))]
|
||||
{:db (-> db
|
||||
(update-in [:admin :new-client :new-bank-accounts] (fn [bank-accounts]
|
||||
(conj bank-accounts new-bank-account)))
|
||||
(update-in [:admin :new-client] dissoc :new-account))})))
|
||||
[(re-frame/path [::forms ::new-client :data])]
|
||||
(fn [{:keys [new-account] :as client} _]
|
||||
(let [new-account (-> new-account
|
||||
(update :check-number #(if (seq %) (js/parseInt %) nil))
|
||||
(update :yodlee-account-id #(if (seq %) (js/parseInt %) nil)))]
|
||||
(if ((->> client (:bank-accounts)
|
||||
(map :code)
|
||||
set) (:code new-account))
|
||||
client
|
||||
(-> client
|
||||
(update :bank-accounts conj new-account )
|
||||
(assoc :new-account {:type :check}))))))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::remove-new-bank-account
|
||||
(fn [db [_ index]]
|
||||
(update-in db [:admin :new-client :new-bank-accounts]
|
||||
[(re-frame/path [::forms ::new-client :data])]
|
||||
(fn [db [_ code]]
|
||||
(update db :bank-accounts
|
||||
(fn [bas]
|
||||
(vec (concat (take index bas)
|
||||
(drop (inc index) bas)))))))
|
||||
(filter #(not= (:code %) code) bas)))))
|
||||
|
||||
(defn clients-table []
|
||||
(let [clients (re-frame/subscribe [::subs/clients])
|
||||
@@ -182,161 +181,7 @@
|
||||
[:td (str/join ", " locations)]
|
||||
[:td email]])]]))
|
||||
|
||||
(defn clients-modal []
|
||||
(let [original-client-code (:code (:client @(re-frame/subscribe [::subs/admin])))]
|
||||
(fn []
|
||||
(let [editing-client (:client @(re-frame/subscribe [::subs/admin]))]
|
||||
[action-modal {:id ::edit
|
||||
:title (str "Edit " (:name editing-client))
|
||||
:action-text "Save"
|
||||
:save-event [::save]}
|
||||
[horizontal-field
|
||||
[:label.label "Name"]
|
||||
[:div.control
|
||||
[bind-field
|
||||
[:input.input {:type "text"
|
||||
:field :name
|
||||
:spec ::entity/name
|
||||
:event ::change
|
||||
:subscription editing-client}]]]]
|
||||
|
||||
[horizontal-field
|
||||
[:label.label "Client code"]
|
||||
[:div.control
|
||||
[bind-field
|
||||
[:input.input {:type "code"
|
||||
:field :code
|
||||
:disabled (if (str/blank? original-client-code)
|
||||
""
|
||||
"disabled")
|
||||
:spec ::entity/code
|
||||
:event ::change
|
||||
:subscription editing-client}]]]]
|
||||
|
||||
[horizontal-field
|
||||
[:label.label "Email"]
|
||||
[:div.control
|
||||
[bind-field
|
||||
[:input.input {:type "email"
|
||||
:field :email
|
||||
:spec ::entity/email
|
||||
:event ::change
|
||||
:subscription editing-client}]]]]
|
||||
|
||||
[horizontal-field
|
||||
[:label.label "Locations"]
|
||||
[:div.control
|
||||
[:div.field.has-addons
|
||||
[:p.control
|
||||
[bind-field
|
||||
[:input.input {:type "text"
|
||||
:field :location
|
||||
:event ::change
|
||||
:subscription editing-client}]]]
|
||||
[:p.control [:button.button.is-primary {:on-click (dispatch-event [::add-location])} "Add"]]]
|
||||
[:ul
|
||||
(for [location (:locations editing-client)]
|
||||
^{:key location} [:li location ])]]]
|
||||
[:h2.subtitle "Address"]
|
||||
|
||||
|
||||
[address-field {:field [:address]
|
||||
:event ::change
|
||||
:subscription editing-client}]
|
||||
[:h2.subtitle "Add account"]
|
||||
[horizontal-field
|
||||
[:label.label "Acct code"]
|
||||
[:div.control
|
||||
[:div.field.has-addons.is-extended
|
||||
[:p.control [:a.button.is-static (:code editing-client) "-" ]]
|
||||
[:p.control
|
||||
[bind-field
|
||||
[:input.input {:type "code"
|
||||
:field [:new-account :code]
|
||||
:spec ::entity/code
|
||||
:event ::change
|
||||
:subscription editing-client}]]]]]]
|
||||
|
||||
[horizontal-field
|
||||
[:label.label "Bank"]
|
||||
[:div.control
|
||||
|
||||
[bind-field
|
||||
[:input.input {:placeholder "Bank Name"
|
||||
:type "text"
|
||||
:field [:new-account :bank-name]
|
||||
:event ::change
|
||||
:subscription editing-client}]]]
|
||||
[:div.control
|
||||
|
||||
[bind-field
|
||||
[:input.input {:placeholder "Routing"
|
||||
:type "text"
|
||||
:field [:new-account :routing]
|
||||
:event ::change
|
||||
:subscription editing-client}]]]
|
||||
[:div.control
|
||||
|
||||
[bind-field
|
||||
[:input.input {:placeholder "Code"
|
||||
:type "text"
|
||||
:field [:new-account :bank-code]
|
||||
:event ::change
|
||||
:subscription editing-client}]]]]
|
||||
[horizontal-field
|
||||
[:label.label "Account"]
|
||||
[:div.control
|
||||
[bind-field
|
||||
[:input.input {:placeholder "Nickname"
|
||||
:type "text"
|
||||
:field [:new-account :name]
|
||||
:event ::change
|
||||
:subscription editing-client}]]]
|
||||
[:div.control
|
||||
[bind-field
|
||||
[:input.input {:placeholder "Acct #"
|
||||
:type "text"
|
||||
:field [:new-account :number]
|
||||
:event ::change
|
||||
:subscription editing-client}]]]
|
||||
[:div.control
|
||||
[bind-field
|
||||
[:input.input {:placeholder "Check #"
|
||||
:type "text"
|
||||
:field [:new-account :check-number]
|
||||
:event ::change
|
||||
:subscription editing-client}]]]]
|
||||
[horizontal-field
|
||||
[:label.label "Yodlee Account"]
|
||||
[:div.control
|
||||
[bind-field
|
||||
[:input.input {:placeholder "Yodlee Account #"
|
||||
:type "text"
|
||||
:field [:new-account :yodlee-account-id]
|
||||
:event ::change
|
||||
:subscription editing-client}]]]
|
||||
[:div.control
|
||||
[:button.button.is-primary.is-pulled-right {:on-click (dispatch-event [::add-new-bank-account])
|
||||
:disabled (if (and (s/valid? ::entity/bank-account (:new-account editing-client))
|
||||
(not ((set (map :code (:bank-accounts editing-client)))
|
||||
(str (:code editing-client) "-" (-> editing-client :new-account :code)))))
|
||||
""
|
||||
"disabled")} "Add"]]]
|
||||
|
||||
|
||||
|
||||
[:h2.subtitle "Bank Accounts"]
|
||||
[horizontal-field
|
||||
nil
|
||||
[:div.control
|
||||
[:ul
|
||||
|
||||
(for [{:keys [code name number check-number id]} (:bank-accounts editing-client)]
|
||||
^{:key id} [:li code ": " name])
|
||||
(for [[index {:keys [name code number check-number]}] (map vector (range) (:new-bank-accounts editing-client))]
|
||||
^{:key index} [:li [:strong "* " code ": " name] [:button.button {:on-click (dispatch-event [::remove-new-bank-account index])} [:span.icon [:i.fa.fa-times]]]])]]]
|
||||
|
||||
(when (:saving? editing-client) [:div.is-overlay {:style {"backgroundColor" "rgba(150,150,150, 0.5)"}}])]))))
|
||||
|
||||
(defn admin-clients-content []
|
||||
[:div
|
||||
@@ -346,19 +191,20 @@
|
||||
[:h1.title "Clients"]
|
||||
[:div.is-pulled-right
|
||||
[:a.button.is-primary.is-large {:on-click (dispatch-event [::new])} "New client"]]
|
||||
[clients-table]
|
||||
(when editing-client
|
||||
[clients-modal])])])
|
||||
[clients-table]])])
|
||||
|
||||
|
||||
(defn side-bar-form [_ children]
|
||||
[:div [:a.delete.is-pulled-right {:on-click (dispatch-event [::form-closing ::new-client])}] [:div children]])
|
||||
|
||||
(defn new-client-form []
|
||||
(let [new-client (:new-client @(re-frame/subscribe [::subs/admin]))]
|
||||
[:div
|
||||
[:form
|
||||
[:section.section {:style {:padding-bottom "0.75em" :padding-top "0.75em"}}
|
||||
[:h1.title "Add client"]
|
||||
(let [{error :error new-client :data } @(re-frame/subscribe [::form ::new-client])]
|
||||
|
||||
[side-bar-form {}
|
||||
[:form
|
||||
[:h1.title.is-2 "Add client"]
|
||||
[:div.field
|
||||
[:label.label "Name"]
|
||||
[:p.help "Name"]
|
||||
[:div.control
|
||||
[bind-field
|
||||
[:input.input {:type "text"
|
||||
@@ -368,7 +214,7 @@
|
||||
:subscription new-client}]]]]
|
||||
|
||||
[:div.field
|
||||
[:label.label "Client code"]
|
||||
[:p.help "Client code"]
|
||||
[:div.control
|
||||
[bind-field
|
||||
[:input.input {:type "code"
|
||||
@@ -378,7 +224,7 @@
|
||||
:subscription new-client}]]]]
|
||||
|
||||
[:div.field
|
||||
[:label.label "Email"]
|
||||
[:p.help "Email"]
|
||||
[:div.control
|
||||
[bind-field
|
||||
[:input.input {:type "email"
|
||||
@@ -388,7 +234,7 @@
|
||||
:subscription new-client}]]]]
|
||||
|
||||
[:div.field
|
||||
[:label.label "Locations"]
|
||||
[:p.help "Locations"]
|
||||
[:div.control
|
||||
[:div.field.has-addons
|
||||
[:p.control
|
||||
@@ -401,130 +247,149 @@
|
||||
[:ul
|
||||
(for [location (:locations new-client)]
|
||||
^{:key location} [:li location ])]]]
|
||||
]
|
||||
|
||||
[:section.section {:style {:padding-bottom "0.75em" :padding-top "0.75em"}}
|
||||
[:h2.subtitle "Address"]
|
||||
[address-field {:field [:address]
|
||||
:event ::change-new
|
||||
:subscription new-client}]]
|
||||
[:div {:style {:padding-bottom "0.75em" :padding-top "0.75em"}}
|
||||
[:h2.subtitle "Address"]
|
||||
[address-field {:field [:address]
|
||||
:event ::change-new
|
||||
:subscription new-client}]]
|
||||
[:nav.panel
|
||||
[:p.panel-heading "Bank accounts"]
|
||||
(for [{:keys [type code name number check-number id]} (:bank-accounts new-client)]
|
||||
(if id
|
||||
^{:key code}
|
||||
|
||||
[:a.panel-block {:style {:position "relative"}}
|
||||
[:span.panel-icon
|
||||
(if (= type :check)
|
||||
[:span.icon-check-payment-sign]
|
||||
[:span.icon-accounting-bill])]
|
||||
code ": " name]
|
||||
|
||||
^{:key code}
|
||||
[:li [:strong "* " code ": " name] [:button.button {:on-click (dispatch-event [::remove-new-bank-account code])} [:span.icon [:i.fa.fa-times]]]]))
|
||||
[:div.panel-block
|
||||
[:nav.level
|
||||
[:div.level-item.has-text-centered
|
||||
[:button.button.is-outlined.is-primary.is-fullwidth "Add Checking Account"]]
|
||||
[:div.level-item.has-text-centered
|
||||
|
||||
[:button.button.is-outlined.is-primary.is-fullwidth "Add Cash Account"]]]]
|
||||
#_(for [[index {:keys [name code number check-number]}] (map vector (range) (:new-bank-accounts new-client))]
|
||||
^{:key index} [:li [:strong "* " code ": " name] [:button.button {:on-click (dispatch-event [::remove-new-bank-account index])} [:span.icon [:i.fa.fa-times]]]])]
|
||||
|
||||
[:section.section {:style {:padding-bottom "0.75em" :padding-top "0.75em" :background "hsl(0, 0%, 96%)"}}
|
||||
[:h2.subtitle "Add bank account"]
|
||||
[:label.label "General"]
|
||||
[horizontal-field
|
||||
nil
|
||||
[:div.control
|
||||
[:p.help "Account Code"]
|
||||
[:div.field.has-addons.is-extended
|
||||
[:p.control [:a.button.is-static (:code new-client) "-" ]]
|
||||
[:p.control
|
||||
[bind-field
|
||||
[:input.input {:type "code"
|
||||
:field [:new-account :code]
|
||||
:spec ::entity/code
|
||||
:event ::change-new
|
||||
:subscription new-client}]]]]]
|
||||
#_[:h2.subtitle "Add bank account"]
|
||||
#_[:div {:style {:padding-bottom "0.75em" :padding-top "0.75em" :background "hsl(0, 0%, 96%)"}}
|
||||
[:label.label "General"]
|
||||
[horizontal-field
|
||||
nil
|
||||
[:div.control
|
||||
[:p.help "Account Code"]
|
||||
[:div.field.has-addons.is-extended
|
||||
[:p.control [:a.button.is-static (:code new-client) "-" ]]
|
||||
[:p.control
|
||||
[bind-field
|
||||
[:input.input {:type "code"
|
||||
:field [:new-account :code]
|
||||
:spec ::entity/code
|
||||
:event ::change-new
|
||||
:subscription new-client}]]]]]
|
||||
|
||||
[:div.control
|
||||
[:p.help "Nickname"]
|
||||
[bind-field
|
||||
[:input.input {:placeholder "BOA Checking #1"
|
||||
:type "text"
|
||||
:field [:new-account :name]
|
||||
:event ::change-new
|
||||
:subscription new-client}]]]]
|
||||
[:div.control
|
||||
[:p.help "Nickname"]
|
||||
[bind-field
|
||||
[:input.input {:placeholder "BOA Checking #1"
|
||||
:type "text"
|
||||
:field [:new-account :name]
|
||||
:event ::change-new
|
||||
:subscription new-client}]]]]
|
||||
|
||||
[:label.label "Bank"]
|
||||
[horizontal-field
|
||||
nil
|
||||
[:div.control
|
||||
[:p.help "Bank Name"]
|
||||
[bind-field
|
||||
[:input.input {:placeholder "Bank of America"
|
||||
:type "text"
|
||||
:field [:new-account :bank-name]
|
||||
:event ::change-new
|
||||
:subscription new-client}]]]
|
||||
[:div.control
|
||||
[:p.help "Routing #"]
|
||||
[bind-field
|
||||
[:input.input {:placeholder "104819123"
|
||||
:type "text"
|
||||
:field [:new-account :routing]
|
||||
:event ::change-new
|
||||
:subscription new-client}]]]
|
||||
[:div.control
|
||||
[:p.help "Bank code"]
|
||||
[bind-field
|
||||
[:input.input {:placeholder "12/10123"
|
||||
:type "text"
|
||||
:field [:new-account :bank-code]
|
||||
:event ::change-new
|
||||
:subscription new-client}]]]]
|
||||
[:label.label "Bank"]
|
||||
[horizontal-field
|
||||
nil
|
||||
[:div.control
|
||||
[:p.help "Bank Name"]
|
||||
[bind-field
|
||||
[:input.input {:placeholder "Bank of America"
|
||||
:type "text"
|
||||
:field [:new-account :bank-name]
|
||||
:event ::change-new
|
||||
:subscription new-client}]]]
|
||||
[:div.control
|
||||
[:p.help "Routing #"]
|
||||
[bind-field
|
||||
[:input.input {:placeholder "104819123"
|
||||
:type "text"
|
||||
:field [:new-account :routing]
|
||||
:event ::change-new
|
||||
:subscription new-client}]]]
|
||||
[:div.control
|
||||
[:p.help "Bank code"]
|
||||
[bind-field
|
||||
[:input.input {:placeholder "12/10123"
|
||||
:type "text"
|
||||
:field [:new-account :bank-code]
|
||||
:event ::change-new
|
||||
:subscription new-client}]]]]
|
||||
|
||||
[:label.label "Checking account"]
|
||||
[horizontal-field
|
||||
nil
|
||||
[:div.control
|
||||
[:p.help "Account #"]
|
||||
[bind-field
|
||||
[:input.input {:placeholder "123456789"
|
||||
:type "text"
|
||||
:field [:new-account :number]
|
||||
:event ::change-new
|
||||
:subscription new-client}]]]
|
||||
[:div.control
|
||||
[:p.help "Check Number"]
|
||||
[bind-field
|
||||
[:input.input {:placeholder "10000"
|
||||
:type "text"
|
||||
:field [:new-account :check-number]
|
||||
:event ::change-new
|
||||
:subscription new-client}]]]]
|
||||
[:label.label "Checking account"]
|
||||
[horizontal-field
|
||||
nil
|
||||
[:div.control
|
||||
[:p.help "Account #"]
|
||||
[bind-field
|
||||
[:input.input {:placeholder "123456789"
|
||||
:type "text"
|
||||
:field [:new-account :number]
|
||||
:event ::change-new
|
||||
:subscription new-client}]]]
|
||||
[:div.control
|
||||
[:p.help "Check Number"]
|
||||
[bind-field
|
||||
[:input.input {:placeholder "10000"
|
||||
:type "text"
|
||||
:field [:new-account :check-number]
|
||||
:event ::change-new
|
||||
:subscription new-client}]]]]
|
||||
|
||||
[:div.field
|
||||
[:label.label "Yodlee Account"]
|
||||
[:div.control
|
||||
[bind-field
|
||||
[:input.input {:placeholder "Yodlee Account #"
|
||||
:type "text"
|
||||
:field [:new-account :yodlee-account-id]
|
||||
:event ::change-new
|
||||
:subscription new-client}]]]
|
||||
]
|
||||
[:div.field
|
||||
[:div.control
|
||||
(println (s/explain-data ::entity/bank-account (:new-account new-client)))
|
||||
[:button.button.is-primary {:disabled (if (and (doto (s/valid? ::entity/bank-account (:new-account new-client)) println)
|
||||
(not ((set (map :code (:new-bank-accounts new-client)))
|
||||
(str (:code new-client) "-" (-> new-client :new-account :code)))))
|
||||
""
|
||||
"disabled")
|
||||
:on-click (dispatch-event [::add-new-new-bank-account])} "Add"]]]]
|
||||
[:div.field
|
||||
[:label.label "Yodlee Account"]
|
||||
[:div.control
|
||||
[bind-field
|
||||
[:input.input {:placeholder "Yodlee Account #"
|
||||
:type "text"
|
||||
:field [:new-account :yodlee-account-id]
|
||||
:event ::change-new
|
||||
:subscription new-client}]]]
|
||||
]
|
||||
[:div.field
|
||||
[:div.control
|
||||
#_(println (s/explain-data ::entity/bank-account (:new-account new-client)))
|
||||
[:button.button.is-primary {:disabled (if (and (doto (s/valid? ::entity/bank-account (:new-account new-client)) println)
|
||||
(not ((set (map :code (:new-bank-accounts new-client)))
|
||||
(str (:code new-client) "-" (-> new-client :new-account :code)))))
|
||||
""
|
||||
"disabled")
|
||||
:on-click (dispatch-event [::add-new-bank-account])} "Add"]]]]
|
||||
|
||||
[:section.section {:style {:padding-bottom "0.75em" :padding-top "0.75em"}}
|
||||
[:h2.subtitle "Bank Accounts"]
|
||||
[:div.field
|
||||
nil
|
||||
[:div.control
|
||||
[:ul
|
||||
|
||||
(for [{:keys [code name number check-number id]} (:bank-accounts new-client)]
|
||||
^{:key id} [:li code ": " name])
|
||||
(for [[index {:keys [name code number check-number]}] (map vector (range) (:new-bank-accounts new-client))]
|
||||
^{:key index} [:li [:strong "* " code ": " name] [:button.button {:on-click (dispatch-event [::remove-new-bank-account index])} [:span.icon [:i.fa.fa-times]]]])]]]]
|
||||
|
||||
#_(when (:saving? new-client) [:div.is-overlay {:style {"backgroundColor" "rgba(150,150,150, 0.5)"}}])
|
||||
(println (s/explain-data ::entity/client new-client))
|
||||
[:submit.button.is-large.is-primary {:disabled (if (s/valid? ::entity/client new-client)
|
||||
""
|
||||
"disabled")
|
||||
:on-click (dispatch-event [::save-new-client])} "Save"]]]))
|
||||
|
||||
|
||||
#_(when (:saving? new-client) [:div.is-overlay {:style {"backgroundColor" "rgba(150,150,150, 0.5)"}}])
|
||||
#_(println (s/explain-data ::entity/client new-client))
|
||||
|
||||
(when error
|
||||
[:div.notification.is-warning.animated.fadeInUp
|
||||
error])
|
||||
|
||||
[:submit.button.is-large.is-primary {:disabled (if (s/valid? ::entity/client new-client)
|
||||
""
|
||||
"disabled")
|
||||
:on-click (dispatch-event [::save-new-client])
|
||||
:class (str @(re-frame/subscribe [::loading-class ::new-client]) (when error " animated shake"))} "Save"]]]))
|
||||
|
||||
(defn admin-clients-page []
|
||||
(let [{:keys [adding-client?]} @(re-frame/subscribe [::subs/admin])]
|
||||
[side-bar-layout {:side-bar [admin-side-bar {}]
|
||||
:main [admin-clients-content]
|
||||
:right-side-bar (when adding-client?
|
||||
[new-client-form])}]))
|
||||
:right-side-bar-visible? adding-client?
|
||||
:right-side-bar [new-client-form]}]))
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
(set (mapcat :in (::s/problems (s/explain-data spec v)))))
|
||||
|
||||
(defn vendors-table []
|
||||
(let [vendors (re-frame/subscribe [::subs/vendors])
|
||||
(let [vendors (re-frame/subscribe [::subs/sorted-vendors])
|
||||
editing-vendor (:editing @(re-frame/subscribe [::subs/admin]))]
|
||||
|
||||
[:table {:class "table", :style {:width "100%"}}
|
||||
|
||||
110
src/cljs/auto_ap/views/pages/home.cljs
Normal file
110
src/cljs/auto_ap/views/pages/home.cljs
Normal file
@@ -0,0 +1,110 @@
|
||||
(ns auto-ap.views.pages.home
|
||||
(:require [auto-ap.views.components.layouts :refer [side-bar-layout]]
|
||||
[re-frame.core :as re-frame]
|
||||
[auto-ap.subs :as subs]
|
||||
[reagent.core :as r]))
|
||||
|
||||
|
||||
(def pie-chart (r/adapt-react-class js/Recharts.PieChart))
|
||||
(def pie (r/adapt-react-class js/Recharts.Pie))
|
||||
(def bar-chart (r/adapt-react-class js/Recharts.BarChart))
|
||||
(def x-axis (r/adapt-react-class js/Recharts.XAxis))
|
||||
(def y-axis (r/adapt-react-class js/Recharts.YAxis))
|
||||
(def bar (r/adapt-react-class js/Recharts.Bar))
|
||||
(def legend (r/adapt-react-class js/Recharts.Legend))
|
||||
(def cell (r/adapt-react-class js/Recharts.Cell))
|
||||
(def tool-tip (r/adapt-react-class js/Recharts.Tooltip))
|
||||
|
||||
(def colors ["hsl(171, 100%, 41%)" "hsl(217, 71%, 53%)" "hsl(141, 71%, 48%)" "hsl(48, 100%, 67%)" "hsl(348, 100%, 61%)" "hsl(217, 71%, 53%)"])
|
||||
(def light-colors ["hsl(171, 60%, 80%)" "hsl(217, 71%, 53%)" "hsl(141, 71%, 48%)" "hsl(48, 100%, 67%)" "hsl(348, 100%, 61%)" "hsl(217, 71%, 53%)"])
|
||||
|
||||
(defn make-pie-chart
|
||||
[{:keys [width height data]}]
|
||||
[pie-chart {:width width
|
||||
:height height}
|
||||
[pie {:fill "#82ca9d"
|
||||
:data data
|
||||
:dataKey "value"
|
||||
:inner-radius 20}
|
||||
(map (fn [x y]
|
||||
^{:key y}
|
||||
[cell {:key y :fill (colors y)}]) data (range))
|
||||
]
|
||||
[tool-tip]
|
||||
[legend]])
|
||||
|
||||
(defn make-bar-chart [{:keys [width height data]}]
|
||||
[bar-chart {:width width :height height :data data :fill "#FFFFFF"}
|
||||
[tool-tip]
|
||||
[bar {:dataKey "paid" :fill (get colors 0) :stackId "a" :name "Paid"}]
|
||||
[bar {:dataKey "unpaid" :fill (get light-colors 0) :stackId "a" :name "Unpaid"}]
|
||||
|
||||
[x-axis {:dataKey "name"}]
|
||||
[y-axis]
|
||||
[legend]]
|
||||
)
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::received
|
||||
(fn [db [_ {:keys [expense-account-stats invoice-stats]}]]
|
||||
(let [expense-account-stats (->> expense-account-stats
|
||||
(map #(update % :total (fn [t] (js/parseFloat t))))
|
||||
(sort-by :total)
|
||||
(reverse)
|
||||
(take 5))
|
||||
top-5 (vec (take 5 expense-account-stats))
|
||||
rest (drop 5 expense-account-stats)
|
||||
other {:expense-account-id 0 :expense-account-name "Other" :total (reduce + 0 (map :total rest))}]
|
||||
(cond-> db
|
||||
(seq top-5)
|
||||
(assoc ::top-expense-categories (conj top-5 other))
|
||||
|
||||
(seq invoice-stats)
|
||||
(assoc ::invoice-stats invoice-stats)
|
||||
|
||||
|
||||
)
|
||||
)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::invoice-stats
|
||||
(fn [db]
|
||||
(println (::invoice-stats db))
|
||||
(::invoice-stats db)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::top-expense-categories
|
||||
(fn [db]
|
||||
(::top-expense-categories db)))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::mounted
|
||||
(fn [{:keys [db]} _]
|
||||
{:db (assoc db ::top-expense-categories nil)
|
||||
:graphql {:token (-> db :user)
|
||||
:query-obj {:venia/queries [[:expense_account_stats
|
||||
{:client-id (:id @(re-frame/subscribe [::subs/client]))}
|
||||
[:expense-account-id :total :expense-account-name]]
|
||||
[:invoice_stats
|
||||
{:client-id (:id @(re-frame/subscribe [::subs/client]))}
|
||||
[:name :paid :unpaid]]]}
|
||||
:on-success [::received]}}))
|
||||
|
||||
(defn home-content []
|
||||
(let [client-id (-> @(re-frame/subscribe [::subs/client]) :id)]
|
||||
^{:key client-id}
|
||||
[side-bar-layout {:side-bar [:div]
|
||||
:main [:div [:h1.title "Home"]
|
||||
[:h1.title.is-4 "Top expense categories"]
|
||||
(let [expense-categories @(re-frame/subscribe [::top-expense-categories])]
|
||||
(make-pie-chart {:width 800 :height 500 :data (clj->js
|
||||
(map (fn [x] {:name (:expense-account-name x) :value (:total x)}) expense-categories))}))
|
||||
[:h1.title.is-4 "Upcoming Bills"]
|
||||
(make-bar-chart {:width 800 :height 500 :data (clj->js
|
||||
@(re-frame/subscribe [::invoice-stats]))})]}]))
|
||||
|
||||
|
||||
(defn home-page []
|
||||
(let [client-id (-> @(re-frame/subscribe [::subs/client]) :id)]
|
||||
(re-frame/dispatch [::mounted])
|
||||
^{:key client-id} [home-content]))
|
||||
@@ -641,7 +641,10 @@
|
||||
(let [data @(re-frame/subscribe [::edit-invoice])
|
||||
change-event [::events/change-form [::edit-invoice]]
|
||||
locations (get-in @(re-frame/subscribe [::subs/clients-by-id]) [(:client-id data) :locations])
|
||||
min-total (- (:total (:original data)) (:outstanding-balance (:original data)))
|
||||
min-total (if (= (:total (:original data)) (:outstanding-balance (:original data)))
|
||||
nil
|
||||
|
||||
(- (:total (:original data)) (:outstanding-balance (:original data))))
|
||||
|
||||
should-select-location? (and locations
|
||||
(> (count locations) 1))]
|
||||
@@ -650,7 +653,7 @@
|
||||
:action-text "Save"
|
||||
:save-event [::edit-invoice-save]
|
||||
:can-submit? (and #_(s/valid? ::invoice/invoice data)
|
||||
(>= (:total data) min-total))}
|
||||
(or (not min-total) (>= (:total data) min-total)))}
|
||||
|
||||
[horizontal-field
|
||||
[:label.label "Date"]
|
||||
@@ -741,7 +744,14 @@
|
||||
[:div.dropdown-trigger
|
||||
[:button.button.is-success {:aria-haspopup true
|
||||
:on-click (dispatch-event [::print-checks-clicked ])
|
||||
:disabled (if (seq checked-invoices)
|
||||
:disabled (if (and (seq checked-invoices)
|
||||
(->> checked-invoices
|
||||
vals
|
||||
(group-by #(get-in % [:vendor :id]))
|
||||
(reduce-kv (fn [negative? _ invoices]
|
||||
(or negative? (< (reduce + 0 (map (fn [x] (-> x :outstanding-balance js/parseFloat)) invoices) ) 0)))
|
||||
false)
|
||||
not))
|
||||
""
|
||||
"disabled")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user