Initial Commit

This commit is contained in:
Steve Schafer 2025-07-13 08:15:02 -06:00
parent 2aede797ea
commit 72d424a3f8
72 changed files with 4137 additions and 1 deletions

52
.classpath Normal file
View file

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="test" value="true"/>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="target/generated-sources/annotations">
<attributes>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

97
.factorypath Normal file
View file

@ -0,0 +1,97 @@
<factorypath>
<factorypathentry kind="VARJAR" id="M2_REPO/javax/servlet/javax.servlet-api/3.0.1/javax.servlet-api-3.0.1.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/mysql/mysql-connector-java/8.0.11/mysql-connector-java-8.0.11.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/com/google/protobuf/protobuf-java/2.6.0/protobuf-java-2.6.0.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/commons-fileupload/commons-fileupload/1.3.3/commons-fileupload-1.3.3.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/commons-io/commons-io/2.2/commons-io-2.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/apache/commons/commons-csv/1.5/commons-csv-1.5.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/com/fasterxml/jackson/core/jackson-core/2.9.5/jackson-core-2.9.5.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/com/fasterxml/jackson/core/jackson-databind/2.9.5/jackson-databind-2.9.5.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/com/fasterxml/jackson/core/jackson-annotations/2.9.0/jackson-annotations-2.9.0.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/jstl/jstl/1.2/jstl-1.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/taglibs/standard/1.1.2/standard-1.1.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/seleniumhq/selenium/selenium-java/4.1.2/selenium-java-4.1.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/seleniumhq/selenium/selenium-api/4.1.2/selenium-api-4.1.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/seleniumhq/selenium/selenium-chrome-driver/4.1.2/selenium-chrome-driver-4.1.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/com/google/auto/service/auto-service-annotations/1.0.1/auto-service-annotations-1.0.1.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/com/google/auto/service/auto-service/1.0.1/auto-service-1.0.1.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/com/google/auto/auto-common/1.2/auto-common-1.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/com/google/guava/guava/31.0.1-jre/guava-31.0.1-jre.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/checkerframework/checker-qual/3.12.0/checker-qual-3.12.0.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/com/google/errorprone/error_prone_annotations/2.7.1/error_prone_annotations-2.7.1.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/com/google/j2objc/j2objc-annotations/1.3/j2objc-annotations-1.3.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/seleniumhq/selenium/selenium-chromium-driver/4.1.2/selenium-chromium-driver-4.1.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/seleniumhq/selenium/selenium-json/4.1.2/selenium-json-4.1.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/seleniumhq/selenium/selenium-devtools-v85/4.1.2/selenium-devtools-v85-4.1.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/seleniumhq/selenium/selenium-devtools-v95/4.1.2/selenium-devtools-v95-4.1.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/seleniumhq/selenium/selenium-devtools-v96/4.1.2/selenium-devtools-v96-4.1.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/seleniumhq/selenium/selenium-devtools-v97/4.1.2/selenium-devtools-v97-4.1.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/seleniumhq/selenium/selenium-edge-driver/4.1.2/selenium-edge-driver-4.1.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/seleniumhq/selenium/selenium-firefox-driver/4.1.2/selenium-firefox-driver-4.1.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/seleniumhq/selenium/selenium-firefox-xpi-driver/4.1.2/selenium-firefox-xpi-driver-4.1.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/seleniumhq/selenium/selenium-ie-driver/4.1.2/selenium-ie-driver-4.1.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/seleniumhq/selenium/selenium-opera-driver/4.1.2/selenium-opera-driver-4.1.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/seleniumhq/selenium/selenium-remote-driver/4.1.2/selenium-remote-driver-4.1.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/com/beust/jcommander/1.82/jcommander-1.82.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-buffer/4.1.73.Final/netty-buffer-4.1.73.Final.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-codec-http/4.1.73.Final/netty-codec-http-4.1.73.Final.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-codec/4.1.73.Final/netty-codec-4.1.73.Final.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-handler/4.1.73.Final/netty-handler-4.1.73.Final.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-tcnative-classes/2.0.46.Final/netty-tcnative-classes-2.0.46.Final.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-common/4.1.73.Final/netty-common-4.1.73.Final.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-transport-classes-epoll/4.1.73.Final/netty-transport-classes-epoll-4.1.73.Final.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-transport-classes-kqueue/4.1.73.Final/netty-transport-classes-kqueue-4.1.73.Final.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-transport-native-epoll/4.1.73.Final/netty-transport-native-epoll-4.1.73.Final.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-transport-native-kqueue/4.1.73.Final/netty-transport-native-kqueue-4.1.73.Final.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-transport-native-unix-common/4.1.73.Final/netty-transport-native-unix-common-4.1.73.Final.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-transport/4.1.73.Final/netty-transport-4.1.73.Final.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-resolver/4.1.73.Final/netty-resolver-4.1.73.Final.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/opentelemetry/opentelemetry-api/1.10.1/opentelemetry-api-1.10.1.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/opentelemetry/opentelemetry-context/1.10.1/opentelemetry-context-1.10.1.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/opentelemetry/opentelemetry-exporter-logging/1.10.1/opentelemetry-exporter-logging-1.10.1.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/opentelemetry/opentelemetry-sdk-metrics/1.10.1-alpha/opentelemetry-sdk-metrics-1.10.1-alpha.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/opentelemetry/opentelemetry-sdk-logs/1.10.1-alpha/opentelemetry-sdk-logs-1.10.1-alpha.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/opentelemetry/opentelemetry-sdk-common/1.10.1/opentelemetry-sdk-common-1.10.1.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/opentelemetry/opentelemetry-sdk-extension-autoconfigure-spi/1.10.1/opentelemetry-sdk-extension-autoconfigure-spi-1.10.1.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/opentelemetry/opentelemetry-sdk-extension-autoconfigure/1.10.1-alpha/opentelemetry-sdk-extension-autoconfigure-1.10.1-alpha.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/opentelemetry/opentelemetry-sdk-trace/1.10.1/opentelemetry-sdk-trace-1.10.1.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/opentelemetry/opentelemetry-sdk/1.10.1/opentelemetry-sdk-1.10.1.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/opentelemetry/opentelemetry-semconv/1.10.1-alpha/opentelemetry-semconv-1.10.1-alpha.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/ous/jtoml/2.0.0/jtoml-2.0.0.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/net/bytebuddy/byte-buddy/1.12.7/byte-buddy-1.12.7.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/apache/commons/commons-exec/1.3/commons-exec-1.3.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/asynchttpclient/async-http-client/2.12.3/async-http-client-2.12.3.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/asynchttpclient/async-http-client-netty-utils/2.12.3/async-http-client-netty-utils-2.12.3.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-codec-socks/4.1.60.Final/netty-codec-socks-4.1.60.Final.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-handler-proxy/4.1.60.Final/netty-handler-proxy-4.1.60.Final.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-transport-native-epoll/4.1.60.Final/netty-transport-native-epoll-4.1.60.Final-linux-x86_64.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/netty/netty-transport-native-kqueue/4.1.60.Final/netty-transport-native-kqueue-4.1.60.Final-osx-x86_64.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/reactivestreams/reactive-streams/1.0.3/reactive-streams-1.0.3.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/com/typesafe/netty/netty-reactive-streams/2.0.4/netty-reactive-streams-2.0.4.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/com/sun/activation/jakarta.activation/1.2.2/jakarta.activation-1.2.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/seleniumhq/selenium/selenium-http/4.1.2/selenium-http-4.1.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/net/jodah/failsafe/2.4.4/failsafe-2.4.4.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/seleniumhq/selenium/selenium-safari-driver/4.1.2/selenium-safari-driver-4.1.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/seleniumhq/selenium/selenium-support/4.1.2/selenium-support-4.1.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/github/bonigarcia/webdrivermanager/5.1.0/webdrivermanager-5.1.0.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/com/google/code/gson/gson/2.9.0/gson-2.9.0.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/com/github/docker-java/docker-java/3.2.13/docker-java-3.2.13.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/com/github/docker-java/docker-java-core/3.2.13/docker-java-core-3.2.13.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/com/github/docker-java/docker-java-api/3.2.13/docker-java-api-3.2.13.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/apache/commons/commons-compress/1.21/commons-compress-1.21.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/bouncycastle/bcpkix-jdk15on/1.64/bcpkix-jdk15on-1.64.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/bouncycastle/bcprov-jdk15on/1.64/bcprov-jdk15on-1.64.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/slf4j/jcl-over-slf4j/1.7.30/jcl-over-slf4j-1.7.30.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/com/github/docker-java/docker-java-transport-httpclient5/3.2.13/docker-java-transport-httpclient5-3.2.13.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/com/github/docker-java/docker-java-transport/3.2.13/docker-java-transport-3.2.13.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/apache/httpcomponents/client5/httpclient5/5.0.3/httpclient5-5.0.3.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/apache/httpcomponents/core5/httpcore5/5.0.2/httpcore5-5.0.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/commons-codec/commons-codec/1.13/commons-codec-1.13.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/net/java/dev/jna/jna/5.8.0/jna-5.8.0.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/brotli/dec/0.1.2/dec-0.1.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/apache/commons/commons-lang3/3.12.0/commons-lang3-3.12.0.jar" enabled="true" runInBatchMode="false"/>
</factorypath>

29
.gitignore vendored Normal file
View file

@ -0,0 +1,29 @@
/.attach_pid*
/*.html
/pages
/*.xls
/*.pdf
/sandy/
/amazon/
/amazon-steve*
*.log
/budget.sql
/budget/
/build/
/categorized.lst
/chromedriver
/databases.lst
/explore*.sql
/list-descriptions.sql
/load.sql
/export*
/gnucash*
/hrefs
/*.out
/*-urls
/tables.sql
/target
/temp.sql
/test-urls
/test_files
/upload.sql

37
.project Normal file
View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.stephenschafer.budget</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
</natures>
</projectDescription>

12
.settings/.jsdtscope Normal file
View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry excluding="**/bower_components/*|**/node_modules/*|**/*.min.js" kind="src" path="WebContent"/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.WebProject">
<attributes>
<attribute name="hide" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
<classpathentry kind="output" path=""/>
</classpath>

View file

@ -0,0 +1,4 @@
eclipse.preferences.version=1
org.eclipse.jdt.apt.aptEnabled=true
org.eclipse.jdt.apt.genSrcDir=target/generated-sources/annotations
org.eclipse.jdt.apt.genTestSrcDir=target/generated-test-sources/test-annotations

View file

@ -0,0 +1,12 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
org.eclipse.jdt.core.compiler.processAnnotations=enabled
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8

View file

@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="com.stephenschafer.budget-0.0.1-SNAPSHOT">
<wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
<wb-resource deploy-path="/" source-path="/WebContent" tag="defaultRootSource"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/java/main"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/target/generated-sources/annotations"/>
<property name="context-root" value="com.stephenschafer.budget"/>
<property name="java-output-path" value="/com.stephenschafer.budget/build/classes"/>
</wb-module>
</project-modules>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<fixed facet="jst.web"/>
<fixed facet="wst.jsdt.web"/>
<fixed facet="java"/>
<installed facet="java" version="1.8"/>
<installed facet="jst.web" version="3.0"/>
<installed facet="wst.jsdt.web" version="1.0"/>
</faceted-project>

View file

@ -0,0 +1 @@
org.eclipse.wst.jsdt.launching.baseBrowserLibrary

View file

@ -0,0 +1 @@
Window

View file

@ -0,0 +1,2 @@
disabled=06target
eclipse.preferences.version=1

View file

@ -1,3 +1,3 @@
# com.stephenschafer.budget # com.stephenschafer.budget
Budget java app Create budget from downloaded CSV files

View file

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Class-Path:

View file

@ -0,0 +1,87 @@
<web-app
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<servlet>
<servlet-name>upload</servlet-name>
<servlet-class>com.stephenschafer.budget.UploadServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>upload</servlet-name>
<url-pattern>/upload</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>get-transaction</servlet-name>
<servlet-class>com.stephenschafer.budget.GetTransactionServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>get-transaction</servlet-name>
<url-pattern>/get-transaction</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>get-transactions</servlet-name>
<servlet-class>com.stephenschafer.budget.GetTransactionsServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>get-transactions</servlet-name>
<url-pattern>/get-transactions</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>get-recipient</servlet-name>
<servlet-class>com.stephenschafer.budget.GetRecipientServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>get-recipient</servlet-name>
<url-pattern>/get-recipient</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>get-accounts</servlet-name>
<servlet-class>com.stephenschafer.budget.GetAccountsServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>get-accounts</servlet-name>
<url-pattern>/get-accounts</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>get-budgets</servlet-name>
<servlet-class>com.stephenschafer.budget.GetBudgetsServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>get-budgets</servlet-name>
<url-pattern>/get-budgets</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>add-account</servlet-name>
<servlet-class>com.stephenschafer.budget.AddAccountServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>add-account</servlet-name>
<url-pattern>/add-account</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>save-distributions</servlet-name>
<servlet-class>com.stephenschafer.budget.SaveDistributionsServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>save-distributions</servlet-name>
<url-pattern>/save-distributions</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>save-recipient-distributions</servlet-name>
<servlet-class>com.stephenschafer.budget.SaveRecipientDistributionsServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>save-recipient-distributions</servlet-name>
<url-pattern>/save-recipient-distributions</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>delete-account</servlet-name>
<servlet-class>com.stephenschafer.budget.DeleteAccountServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>delete-account</servlet-name>
<url-pattern>/delete-account</url-pattern>
</servlet-mapping>
</web-app>

6
budget.properties Normal file
View file

@ -0,0 +1,6 @@
log-filename=budget.log
db-url=jdbc:mysql://localhost:3306/budget_2023?serverTimezone=UTC&useSSL=false
db-username=elephant
db-password=zsKRtBw6gPi0B0hMg1c2
trilium-url=http://nuc1:8080/etapi
trilium-password=scale-daughter-twiddling-educate-afraid

7
build-jar Executable file
View file

@ -0,0 +1,7 @@
#!/bin/sh
if mvn -f pom-jar.xml clean install > build-jar.log 2> build-jar.err.log; then
echo "success"
else
echo "failure"
exit 1
fi

587
category-regex.lst Normal file
View file

@ -0,0 +1,587 @@
accounting, CHECK # 4046, , firstbank, , peakview
auto.equipment, .*garmin.*, i,
auto.gasoline, .*CONOCO.*, , chase
auto.gasoline, .*SHELL OIL.*
auto.gasoline, CONOCO .*, citi
auto.license, AIR CARE COLORADO.*, , chase
auto.services, .*PEDERSEN TOYOTA.*
auto.subscriptions, .*AARP ROADSIDE.*, , chase
auto.subscriptions, ROADSIDE ASSISTANCE.*, , chase
bank-fees, .* FEE, , firstbank
cellphone, .* VZ WIRELESS VW, , firstbank
clothing, .* barefoot shoes .*, i
clothing, .* cotton .* leggings .*, i
clothing, .* Grip Socks .*
clothing, .* House Shoes .*
clothing, .* Orthopeic Flip Flops .*
clothing, .* Underwear .*
clothing, .*columbia.*, i,
clothing, .*dress belt.*, i,
clothing, .*Flip Flop Socks.*, , amz.sandy.retail.ord
clothing, .*LLBEANINC.*
clothing, .*Nightgown.*
clothing, .*Wireless Bra.*, , amz.sandy.retail.ord
clothing, Cotton Tops.*
clothing, Gaiam.*
clothing, HAFLINGER.*
clothing, HiGropcore.*
clothing, Hugh Ugoli.*
clothing, Island Genius.*
clothing, LeIsfIt.*
clothing, MACYS.*, , chase
clothing, PAYPAL \*ZAPPOS.*, , chase
clothing, vanity fair .* nylon brief .*, i
clothing, Weintee .*
communication, .*DISCORD.*
computer.equipment, .* Charger Cable .*
computer.equipment, .* Charging Cable.*
computer.equipment, .* Computer Power Supply .*
computer.equipment, .* ipad .*, i
computer.equipment, .* Lightning Cable .*
computer.equipment, .* Magnetic Fast Charger .*
computer.equipment, .* mechanical keyboard .*, i,
computer.equipment, .* Power Adapter .*
computer.equipment, .* Power Over Ethernet .*
computer.equipment, .*3\.5mm jack.*, i,
computer.equipment, .*APPLE\.COM/US.*
computer.equipment, .*av cable.*, i,
computer.equipment, .*BESTBUY.*, , chase
computer.equipment, .*CANAKIT.*, , chase
computer.equipment, .*cyberpower.*, i,
computer.equipment, .*data charging cable.*, i,
computer.equipment, .*deskstar.*, i,
computer.equipment, .*DVD Drive.*
computer.equipment, .*flash memory.*, i,
computer.equipment, .*led display.*, i,
computer.equipment, .*mid tower case.*, i,
computer.equipment, .*mini plug.*, i,
computer.equipment, .*monitor cable.*, i,
computer.equipment, .*NEWEGG.*
computer.equipment, .*oem drive.*, i,
computer.equipment, .*scanner.*, i,
computer.equipment, .*videosecu.*, i,
computer.equipment, .*Wireless Vertical Ergonomic Optical Mouse.*, , amz.sandy.retail.ord
computer.equipment, Arducam .*
computer.equipment, Corsair .*
computer.equipment, HGST .*
computer.equipment, Micro HDMI to HDMI Adapter.*
computer.equipment, Mohu Leaf .*
computer.equipment, NETGEAR .*
computer.equipment, Raspberry Pi .*
computer.equipment, SiliconDust HDHomeRun .*
computer.equipment, U6 PRO .*
computer.equipment, WWZMDiB .*
computer.software, DejaOffice, , amz.sandy.dig.ord, 10
computer.software, File Manager, , amz.sandy.dig.ord, 10
computer.subscriptions, .*APPLE\.COM/BILL.*
computer.supplies, .* Compressed Air Duster .*
computer.supplies, .* Compressed Gas Duster.*
dental.services, NORTHERN COLORADO ENDO.*, , discover
dental.services, OWENS DENTAL.*
dental.services, RECLAIM DENTISTRY .*
dental.services, THE THERMOGRAM CENTER .*, , discover
dining, .*AUSTINS AMERICAN .*, , chase
dining, .*MOOT HOUSE.*
dining, .*Simmer ECOM.*, , chase
dining, .*SIMMER.*Food.*Drink.*
dining, .*YOUNG.*CAFE.*
education, PAYPAL \*DAILYOM .*, , chase
education, PAYPAL \*WHOLE WOMAN .*, , chase
entertainment.books, .*BN PAPERSRC .*, , chase, , Barnes and Noble
entertainment.books, Barnes \& Noble Inc .*, , paypal, 10
entertainment.games, Humble Bundle.*, , paypal, 10
entertainment.games, Valve Corp.*, , paypal, 10
entertainment.subscriptions.spotify, Spotify USA .*, , paypal, 10
entertainment.subscriptions.gaia, .*GAIA.*
entertainment.subscriptions.netflix, .*NETFLIX.*
entertainment.subscriptions.patreon, .*PATREON *MEMBER.*
entertainment.subscriptions.samsung, .*SAMSUNG.*, , chase
entertainment.subscriptions.spotify, .*SPOTIFY.*
entertainment.subscriptions.youtube, .*YOUTUBE SUBSC.*
entertainment.subscriptions.apple, Apple Services .*-10\.79 .*, , paypal
computer.support, Apple Services .*7\.99 .*, , paypal
computer.support, Apple Services .*2\.99 .*, , paypal
computer.support, Apple Services .*3\.99 .*, , paypal
entertainment.subscriptions.comcast, CABLE COMCAST.*, , firstbank
entertainment.subscriptions.antenna, CHANNELS .*
entertainment.subscriptions.newspaper, Ft Coll Coloradoan.*
entertainment.subscriptions.google, Google .* .2\.17 USD.*, , paypal, 10
entertainment.subscriptions.hallmark, Hallmark Movies Now, , amz.sandy.dig.ord, 10
entertainment.subscriptions.hbo, HBO, , amz.sandy.dig.ord, 10
entertainment.subscriptions.hulu, Hulu .*, , paypal, 10
entertainment.subscriptions.netflix, Netflix, , amz.sandy.dig.ord, 10
entertainment.subscriptions.netflix, Netflix\.com .*, , paypal, 10
entertainment.subscriptions.paramount, Paramount\+ with SHOWTIME, , amz.sandy.dig.ord, 10
entertainment.subscriptions.patreon, Patreon .*, , paypal, 10
entertainment.subscriptions.hulu, PAYPAL \*HULU.*, , chase
entertainment.subscriptions.samsung, PAYPAL \*SAMSUNGELEC .*, , chase
entertainment.tvshows/cds, Prime Video.*
entertainment.subscriptions.samsung, Samsung Electronics America.*, , paypal, 10
entertainment.subscriptions.starz, STARZ, , amz.sandy.dig.ord, 10
entertainment.subscriptions.tivo, TIVO PLATFORM TECH.*
entertainment.subscriptions.tivo, TIVOPLATTECH.*, , chase
entertainment.books, .*, , amz.sandy.dig.ord
entertainment.books, .*, , amz.steve.dig.ord
entertainment.books, .*transmetropolitan.*, i,
entertainment.books, Alternative Cures.*
entertainment.books, BOOKSHOP\.ORG .*
entertainment.books, this is not a game, i,
entertainment.books, uncanny x.men.*, i,
entertainment.books, zero history, i,
entertainment.equipment, .*amplifier.*, i,
entertainment.equipment, .*speakers.*, i,
entertainment.equipment, wii.*, i,
entertainment.games, .* Jigsaw Puzzle .*
entertainment.games, .*ARENANETLLC.*
entertainment.games, .*HUMBLEBUNDL.*
entertainment.games, .*STEAM GAMES.*
entertainment.tvshows/cds, .* Avengers: Endgame, , amz.sandy.dig.ord, 10
entertainment.tvshows/cds, Battle Los Angeles, , amz.sandy.dig.ord, 10
entertainment.tvshows/cds, Battleship, , amz.sandy.dig.ord, 10
entertainment.tvshows/cds, Black Panther .*, , amz.sandy.dig.ord, 10
entertainment.tvshows/cds, Captain Marvel, , amz.sandy.dig.ord, 10
entertainment.tvshows/cds, Fantastic Fungi Remastered, , , 10
entertainment.tvshows/cds, Jesse Stone .*, , amz.sandy.dig.ord, 10
entertainment.tvshows/cds, Jupiter Ascending, , amz.sandy.dig.ord, 10
entertainment.tvshows/cds, Justice League, , amz.sandy.dig.ord, 10
entertainment.tvshows/cds, Knives Out, , amz.sandy.dig.ord, 10
entertainment.tvshows/cds, Looper .*, , amz.sandy.dig.ord, 10
entertainment.tvshows/cds, Lungs: The B.Sides, , amz.sandy.dig.ord, 10
entertainment.tvshows/cds, people of the wind, i,
entertainment.tvshows/cds, Predestination, , amz.sandy.dig.ord, 10
entertainment.tvshows/cds, Spider.Man: .*, , amz.sandy.dig.ord, 10
entertainment.tvshows/cds, Star Wars: .*, , amz.sandy.dig.ord, 10
entertainment.tvshows/cds, Wild, , amz.sandy.dig.ord, 10
home.yard-garden.equipment, .*Soil Moisture Meter.*
home.yard-garden.equipment, WayinTop .*
home.yard-garden.supplies, .*BATH NURSERY.*, , chase
home.yard-garden.supplies, .*GULLEY GREENHOUSE.*, , chase
home.yard-garden.supplies, .*HIGHMOWINGS.*
home.yard-garden.supplies, .*URBAN FARMER.*
home.yard-garden.supplies, .*URBANFARMER.*
gifts, .*ETSY GIFTCARD.*, , chase
donations, .*GREENAMERIC .*
donations, .*Rocky Mountain PBS.*
donations, .*THUNDERBIRD.*
donations, .*WIKIPEDIA.*
misc, Ancestry\.com .*, , paypal
gifts, CHECK # 4044, , firstbank, , leah
dues-subscriptions-memberships, CHECK # 4077, , firstbank, , aarp
donations, CPT12.*
donations, Green America .*, , paypal, 10
groceries, .* Almond Flour.*
groceries, .* Microgreens Growing Kit.*
groceries, .* Nutritional Yeast .*
groceries, .* Protein Bar.*
groceries, .* SuperFood Starter Culture .*
groceries, .* Yogurt Starter Culture .*
groceries, .*\(panda01\), , amz.sandy.retail.ord
groceries, .*Bee Pollen.*, , amz.sandy.retail.ord
groceries, .*Breath Mints.*, , amz.sandy.retail.ord
groceries, .*Collagen Peptides.*
groceries, .*FAIRCHILDS VINEGAR.*, , chase
groceries, .*Gelatin Powder.*
groceries, .*INSTACART.*
groceries, .*KING SOOPERS.*, , chase
groceries, .*Macadamia Nuts.*
groceries, .*Manuka Honey.*, , amz.sandy.retail.ord
groceries, .*NATIVE HILL.*
groceries, .*Organic.*, i, , -1
groceries, .*Plantain Chips.*, , amz.sandy.retail.ord
groceries, .*Pork Rinds.*
groceries, .*RED ROBIN.*
groceries, .*ribeye.*, i,
groceries, .*SWEETMARIAS.*
groceries, .*THRIVEMARKE.*
groceries, .*Top Sirloin Steak.*, , amz.sandy.retail.ord
groceries, .*Yogurt Coconut.*
groceries, BochaSweet.*, , amz.sandy.retail.ord
groceries, Bulletproof XCT MCT Oil.*
groceries, Califia Farms.*
groceries, CELTIC OCEAN .*, , chase
groceries, COSTCO WHSE .*, , citi
groceries, Essenzefruits.*
groceries, Instacart .*, , paypal, 10
groceries, Kerrygold.*
groceries, Large paper bag fee.*
groceries, LILY'S.*, i
groceries, LUCKY.*MARKET.*
groceries, MT. CAPRA.*
groceries, NATURAL GROCERS FC.*
groceries, PALEOVALLEY .*, , chase
groceries, PAYPAL .IHERB LLC .*
groceries, PAYPAL \*WILDERNESSP .*, , chase
groceries, Pecan Shop .*
groceries, Pork Loin Chop .*
groceries, PUR Gum .*
groceries, SPROUTS FARMERS MAR .*, , chase
groceries, Sweet Maria.*, , paypal, 10
groceries, Vital Farms.*, i, amz.sandy.retail.ord
groceries, Wild Planet .*
groceries, Wilderness Poets .*, , paypal, 10
groceries, Wilderness Poets.*, , amz.sandy.retail.ord
health.equipment, .* Pulse Oximeter .*
personal.care, .* sleep mask .*, i
health.equipment, .*APOLLONEURO .*
health.equipment, .*balance disc.*, i,
health.equipment, .*heart rate sensor.*, i,
health.equipment, .*INAP SLEEP THERAPY.*, , chase
health.equipment, .*inversion therapy chair.*, i,
health.equipment, .*NOVAALAB.*
health.equipment, .*RINGCONN.*
health.equipment, .*SOMNICSHEAL.*
health.equipment, Apollo Neuroscience.*, , paypal
health.equipment, INAP SLEEP .*
health.equipment, LifePro.*
health.equipment, Omron .*
health.equipment, Optimal Circadian Health.*, , paypal
health.equipment, Oxygen Research Institute .*, , paypal
health.equipment, PAYPAL \*HEALTHYLINE .*, , chase
health.supplies, .* Hearing Aid Batteries.*
health.supplies, .*Breathable Strips.*, i,
health.supplies, .*Hypoallergenic Tape.*, i,
health.supplies, Dynarex .*
health.supplies, Nasacort .*
health.supplies, Polident .*
personal.care, Vibrant Blue Oils.*, , paypal
personal.electronics, Walmart\.com .* -24\.90.*, , paypal
hobby.equipment, uxcell .*
hobby.supplies, .* Acrylic Plastic Cement.*
hobby.supplies, .* rubber roller .*, i
hobby.supplies, .* Wood Screws.*
hobby.supplies, HATCHBOX .*
hobby.supplies, speedball .*, i
home.housewares, .*Bamboo Toilet Stool .*, , amz.sandy.retail.ord
home.appliances, LABIGO.*
home.housewares, .* blueair .* filter .*, i
home.appliances, .* Cordless Stick Vacuum .*
home.appliances, .* Dremel .*
home.appliances, .* Extension Cord .*
home.appliances, .* Extension Cord.*
home.housewares, .* replacement filter for levoit .*, i
home.appliances, .* Lithium Coin Battery .*
home.appliances, .*BLACK\+DECKER dustbuster.*, , amz.sandy.retail.ord
home.appliances, .* BLUEAIR .* Air Purifier.*, , amz.sandy.retail.ord
home.appliances, BLUEAIR Air Purifier.*, , amz.sandy.retail.ord
home.housewares, BLUEAIR Blue Pure .* Replacement Filter.*, , amz.sandy.retail.ord
home.appliances, .*cordless phone.*, i,
home.appliances, .*EMF Meter.*
home.appliances, .*HOME DEPOT.*
home.appliances, .*JOSEPH S HARDWARE.*, , chase
personal.electronics, .*LED Neck Reading Light.*
home.appliances, .*LOWES\.COM.*
home.appliances, .*Phone Headset.*
home.appliances, .*power strip.*, i,
home.appliances, .*PURE WATER PRODUCTS.*
home.appliances, BLACK+DECKER dustbuster.*
home.housewares, BLUEAIR .* Filter
home.appliances, Dremel.*
home.appliances, Kidde .*
home.appliances, levoit .*, i
home.appliances, Portable Charger Power Bank .*
home.appliances, Ryhiac .*
home.appliances, Sunlite .*
home.appliances, SUPRUS .*
home.appliances, Temtop .*
home.housewares, .* Toilet Lid Cover.*
home.furnishings, .*ART\.COM.*
home.furnishings, .*COLORADO BLINDS.*, , chase
home.furnishings, .*FURNITURE ROW.*, , chase
home.housewares, .*Toilet Seat.*
home.furnishings, .*Wall calendar.*, i,
home.furnishings, California Design Den.*
home.furnishings, HOME SMILE.*
home.furnishings, oskas .*
home.furnishings, PAYPAL \*BED BATH .*, , chase
home.furnishings, PUDDING CABIN .*
home.furnishings, CHECK # 4037, , firstbank, , move couch
home.maintenance, CHECK # 4041, , firstbank, , chimney cleaners
home.repair, CHECK # 4072, , firstbank, , freezer repair
home.repair, CHECK # 4073, , firstbank, , freezer repair
home.repair, CHECK # 4076, , firstbank, , fence repair
home.repair, CHECK # 4089, , firstbank, , fix water line in laundry room
home.housewares, .* hand soap.*, i, , 10
home.housewares, .* Light Bulb.*, , , 10
home.housewares, Everyone.*
home.housewares, MRS\. MEYER'S.*
home.housewares, PUREBURG .*
home.housewares, Quilted Northern .*
income, INTEREST EARNED, , firstbank
income, INVESTMENT EDWARD JONES, , firstbank
income, PAYROLL TRINET.*, , firstbank
income, XXSOC SEC SSA.*, , firstbank
insurance.auto, .* SAFECO, , firstbank
insurance.auto, Safeco Corporation .*
insurance.life, .*transamerica.*, i, , 10
insurance.medical, .* HUMANA.*, , firstbank
insurance.product, asurion .*, i, , , breville
internet-services, .*GODADDY\.COM.*
internet-services, .*GOOGLE STORAGE.*
internet-services, .*NAMECHEAP.*
internet-services, .*NETDORM.*
internet-services, Amazon Drive, , amz.sandy.dig.ord, 10
internet-services, NAME-CHEAP.*
internet-services, FORT COLLINS CONNEXION .*, , discover
internet-services, VISA FORT COLLINS CONNEXION.*, , firstbank
investment, MONEYLINK SCHWAB.*, , firstbank
investment, TRANSFER PAYPAL, , firstbank
home.appliances, .* Coffee Maker .*
home.appliances, .*COMFEE.*Electric Kettle.*, , amz.sandy.retail.ord
home.appliances, .*food processor.*, i,
home.appliances, Instant Pot.*
home.appliances, Vitamix .*
home.housewares, .* Pill Cutter .*
home.housewares, hemp mats .*, i
home.housewares, Melitta .*
home.housewares, Seventh Generation .*, , , 10
home.housewares, .* coffee mug .*, i
home.housewares, .* cutting board.*, i
home.housewares, .* Dish Drying Mat .*
home.housewares, .* Jar Lids.*
home.housewares, .* Kitchen Utensils .*
home.housewares, .* Knife Edge Guards.*
home.housewares, .* Mason Jar Shaker Lids .*
home.housewares, .* Rubber Spatula.*
home.housewares, .* spatula .*, i
home.housewares, .*Coffee Carafe Tea Pot.*, , amz.sandy.retail.ord
home.housewares, .*Dish Towels.*, , amz.sandy.retail.ord
home.housewares, .*Donut Pan.*
home.housewares, .*Foam Ear Plugs.*
home.housewares, .*Food Storage Containers.*
home.housewares, .*GREENPAN.*
home.housewares, .*kitchen knife.*, i,
home.housewares, Euro Cuisine.*
home.housewares, Fino Pour-Over Coffee Brewing Filter Cone.*
home.housewares, GMISUN Oil Dispenser.*
home.housewares, GreenPan.*
home.housewares, IDEATECH.*
home.housewares, LOVE MOMENT.*
home.housewares, Misen .*
home.housewares, Noble Home .*
home.housewares, OXO .*
home.housewares, Pour Over Coffee Dripper.*
home.housewares, souper cubes .*, i
home.housewares, SPLF .*
home.housewares, TeamFar .*
home.housewares, Wooden Spurtle .*
home.housewares, Zeppoli .*
medical.services, .* UCHEALTH .*, , chase
medical.services, .* UCHEALTH .*, , discover
medical.services, .*Ortho Spine Ctr Rockies.*
medical.services, .*PERFORMANCE PHYSICAL THER.*
medical.services, .*UCHEALTH .*, , discover
medical.services, .*UCHEALTH.*, , chase
medical.services, ACCTVERIFY ATLAS\.MD, , firstbank
medical.services, ADVANCED MEDICAL IMAGING.*, , chase
medical.services, AUDIOLOGY GROUP .*
health.practitioners, CHECK # 4035, , firstbank, , shelby kahl
medical.services, CHECK # 4036, , firstbank, ,
health.practitioners, CHECK # 4038, , firstbank, , shelby kahl
health.practitioners, CHECK # 4039, , firstbank, , shelby kahl
health.practitioners, CHECK # 4042, , firstbank, , shelby kahl
health.practitioners, CHECK # 4043, , firstbank, , shelby kahl
health.practitioners, CHECK # 4045, , firstbank, , shelby kahl
health.practitioners, CHECK # 4048, , firstbank, , shelby kahl
health.practitioners, CHECK # 4053, , firstbank, , shelby kahl
medical.services, CHECK # 4071, , firstbank, , copay kidney dr.
health.practitioners, CHECK # 4075, , firstbank, , ashley
health.practitioners, CHECK # 4078, , firstbank, , shelby kahl
health.practitioners, CHECK # 4081, , firstbank, , shelby kahl
health.practitioners, CHECK # 4082, , firstbank, , shelby kahl
health.practitioners, CHECK # 4083, , firstbank, , shelby kahl
health.practitioners, CHECK # 4085, , firstbank, , shelby kahl
health.practitioners, CHECK # 4086, , firstbank, , shelby kahl
health.practitioners, CHECK # 4090, , firstbank, , shelby kahl
supplements, CHECK # 4091, , firstbank, , shelby kahl
medical.services, CHIROPRACTIC ASSOCIATES.*
health.practitioners, IV NUTRITION .*
medical.services, NORTH VISTA.*
medical.services, OBGA MY OBGYN .*, , discover
medical.services, UCHEALTH .*, , firstbank
medical.subscriptions, DFC OF NOC ATLAS\.MD, , firstbank
medical.subscriptions, DFC OF NOCO .*, , chase
medical.subscriptions, DFC OF NOCO .*, , discover
medical.supplies, WALGREENS .*, , chase
medicines, .*BELMAR PHARMACY.*, , chase
medicines, .*EBM MEDICAL.*, , chase
medicines, .*SAFEWAY.*
medicines, GOOD DAY PHARMACY.*
medicines, UpSpring .*
dues-subscriptions-memberships, CHECK # 4047, , firstbank, , AARP
dues-subscriptions-memberships, CONSUMERREPORTS.*, , chase
dues-subscriptions-memberships, prime membership fee, i, amz.sandy.dig.ord, 10
mortgage, CASH PENNYMAC.*, , firstbank
office.supplies, .*Ballpoint Pens.*, , amz.sandy.retail.ord
office.supplies, .*Magnifying Glass.*
office.supplies, .*NOKBOX.*, , chase
office.supplies, .*Spiral Notebook.*
office.supplies, HP Printer Paper .*
office.supplies, HP.*Ink Cartridge.*
office.supplies, Pentel .*
passports, CHECK # 4050, , firstbank, , larimer county clerk
passports, PAYMENT PASSPORTSERVICES, , firstbank, , us dept of state
passports, PAYMENT PASSPORTSERVICES, , firstbank, , us dept of state
payment, .* CHASE CREDIT CRD, , firstbank
payment, .*AMAZON PRIME.*, , chase
payment, .*ANNUAL MEMBERSHIP FEE.*, , chase
payment, .*Payment Thank You.*
payment, AMAZON MKTPL.*, , chase
payment, Amazon Prime.*, , chase
payment, Amazon\.com.*
payment, AMZN Mktp.*
payment, CASHBACK BONUS REDEMPTION .*, , discover
payment, INST XFER PAYPAL, , firstbank
payment, Kindle Svcs.*, , chase, 10
payment, PAYMENT CITI.*, , firstbank
payment, PAYPAL \*.*, , chase, 10, , 2025
payment, PHONE PAY DISCOVER, , firstbank
payment, PHONE PAYMENT .*, , discover
payment, PP\*.*, , chase, 10
payment, Prime Video Channels .*, , chase, 10
payment, WHOLEFDS.*
personal.care, .* Scalp Serum .*
personal.care, .* Shaving Soap .*
personal.care, .*dental care.*, i,
personal.care, .*Dental Floss.*, , amz.sandy.retail.ord
personal.care, .*Eye Cream.*, , amz.sandy.retail.ord
personal.care, .*Eye Wrinkle Cream.*, , amz.sandy.retail.ord
personal.care, .*HENSONSHAVI.*
personal.care, .*Nail File.*, i,
personal.care, .*shave soap.*, i,
personal.care, .*Skin Scraping Tool.*, , amz.sandy.retail.ord
personal.care, .*VIBRANTBLUE .*
personal.care, AYR Saline.*
personal.care, Biossance.*, , amz.sandy.retail.ord
personal.care, Elysian Honey.*
personal.care, Kiss My Face.*
personal.care, Life-flo.*
personal.care, MagniLife.*
personal.care, micropore tape .*, i
personal.care, MyChelle Dermaceuticals .*
personal.care, Nioxin .*
personal.care, OraWellness .*
personal.care, PAYPAL \*BIOSSANCE .*, , chase
personal.care, PROFOUND HEALTH LTD .*, , , , eye drops
personal.care, Sondery .*
personal.care, The Naked Bee .*
personal.care, THG Beauty Limited .*, , paypal
personal.care, Zeasorb AF Jock Itch Powder.*
personal.electronics, .* apple watch .*, i
personal.care, .* toothbrush .*, i
personal.electronics, LiCB .* Watch Battery.*
personal.electronics, Moto G .*
personal.electronics, PAYPAL .WALMART COM .*, , , , hearing aid batteries
personal.electronics, Poetic Revolution .*
personal.electronics, RingConn .*
dues-subscriptions-memberships, .*BUFFMUFF.*
dues-subscriptions-memberships, CHECK # 4070, , firstbank, , green america
dues-subscriptions-memberships, GANNETT MEDIA .*, , chase
dues-subscriptions-memberships, Google .* -1\.08 USD.*, , paypal, 10
dues-subscriptions-memberships, Google .* -3\.26 USD.*, , paypal, 10
dues-subscriptions-memberships, INSTAPAPER .*, , chase
dues-subscriptions-memberships, PAYPAL \*CONSUMERLAB .*, , chase
supplements, .* Boron Complex .*
supplements, .*Ancestral Supplements.*, , amz.sandy.retail.ord
supplements, .*ANTIAGINGCO.*
supplements, .*BioGaia Gastrus.*, , amz.sandy.retail.ord
supplements, .*Glutamine.*
supplements, .*Gummies.*
supplements, .*LIFEEXTENSI.*
supplements, .*Melatonin.*, , amz.sandy.retail.ord
supplements, .*PUREFORMULA .*
supplements, .*SEEKHEALTH.*
supplements, .*SOMALIFE.*
supplements, .*Veggie Capsules.*, , amz.sandy.retail.ord
supplements, Biosil.*, , amz.sandy.retail.ord
supplements, Biotics.*, , amz.sandy.retail.ord
supplements, Boiron.*, , amz.sandy.retail.ord
supplements, Cardiovascular Research.*
supplements, CHECK # 4040, , firstbank, , shelby kahl
supplements, Designs for Health.*
supplements, Doctor's Best.*
supplements, Dr\. Berg.*
supplements, Dr\. Clark.*
supplements, Dr\. Mercola.*
supplements, DrFormulas.*
supplements, Enzymedica.*
supplements, FULLSCRIPT.*, , chase
supplements, Garden of Life.*
supplements, Health Thru Nutrition.*
supplements, HealthForce.*
supplements, Horbäach.*
supplements, Hyland's.*
supplements, iHerb.*, , paypal, 10
supplements, Jarrow.*
supplements, keto chow .*, i
supplements, Life Extension.*
supplements, Living Silica Collagen Booster Liquid.*
supplements, Magnesium L Threonate Capsules.*
supplements, MARCO PHARMA.*
supplements, MICROVASCULAR.*, , chase, , endocaylx
supplements, MIRACLES OF HEALTH .*, , chase
supplements, multivitamin .*, i
supplements, Nattokinase .*
supplements, Natural Factors.*
supplements, Nature's Way .*
supplements, NEORA.*
supplements, New Chapter .*
supplements, Nordic Naturals .*
supplements, NOW .*
supplements, Nutricost.*
supplements, PAYPAL \*LIFE ENTH .*, , chase
supplements, PAYPAL \*SWANSONHEAL .*, , chase, ,
supplements, PAYPAL \*VITACOSTCOM .*, , chase
supplements, Premier Research Labs .*
supplements, Pure Encapsulations .*
supplements, PureFormulas .*, , paypal, 10
supplements, Renew Life .*
supplements, RnA ReSet .*
supplements, SeabuckWonders .*, i
supplements, SeekingHealth .*, , paypal, 10
supplements, SOLARAY .*, i
supplements, Solgar .*
supplements, Source Naturals .*
supplements, Standard Process .*
supplements, SUBSCRIBE .* SAVE .*, , chase, , paleo valley
supplements, Swanson Health Products.*, , paypal
supplements, Teliaoils .*
supplements, THORNE .*
supplements, Trace Minerals Mega-Mag.*
supplements, Vital Earth .*
supplements, Zazzee .*
taxes.refunds, .* DEPT REVENUE, , firstbank
taxes.refunds, TAX REF IRS TREAS.*, , firstbank
taxes, TAXES PEAKVIEW.*, , firstbank
taxes, USATAXPYMT IRS.*, , firstbank
tips, .*Amazon Tips.*, , chase
unknown, .*OCHEALTH .*
supplements, CHECK # 4034, , firstbank, , shelby kahl
unknown, CHECK # 4084, , firstbank, ,
unknown, CHECK # 4088, , firstbank, ,
unknown, Colorado Interactive.*, , paypal
unknown, Google .* -31\.15.*, , paypal
unknown, MICROSOFT.*, , discover
unknown, PAYPAL \*COLORADOINT .*, , chase
unknown, Spigen .*
utilities.garbage, .* REPUBLICSERVICES, , firstbank
utilities.electricity/water, CITY OF FORT COLLINS .*, , discover
utilities.electricity/water, VISA CITY OF FORT COLLINS.*, , firstbank
utilities.gas, XCELENERGY.*, , firstbank
vision.eyewear, DOOViC.*
vision.eyewear, ThinOptics .*
vision.services, .*EYECARE ASSOCIATES.*, , chase
vision.services, EYECARE ASSOCIATES .*, , discover
home.yard-garden.equipment, .* Drip Irrigation .*
home.yard-garden.equipment, .* Replacement Spool for Black and Decker String Trimmer .*
home.yard-garden.equipment, .*APEX GARDEN Replacement Canopy Top.*, , amz.sandy.retail.ord
home.yard-garden.equipment, .*ETSY INC.*
home.yard-garden.equipment, .*Water Hose Nozzle.*
home.yard-garden.equipment, Bug Zapper.*, , amz.sandy.retail.ord
home.yard-garden.equipment, Drip Irrigation .*
home.yard-garden.equipment, ego power.*, i
home.yard-garden.equipment, Flame King .*
home.yard-garden.equipment, Yzert .*
home.yard-garden.services, .*ROYAL TURF.*
home.yard-garden.services, CHECK # 4052, , firstbank, , chris coopenhaver
home.yard-garden.services, CHECK # 4080, , firstbank, , chris coopenhaver
medical.services, CHECK # 4087, , firstbank, , hospital?

7
deploy Executable file
View file

@ -0,0 +1,7 @@
#!/bin/sh
echo "deploying budget"
PROJECT="$HOME/projects/com.stephenschafer.budget/target"
WAR="com.stephenschafer.budget-0.0.1-SNAPSHOT.war"
cp $PROJECT/$WAR .
mv ./$WAR ./budget.war
mv ./budget.war /disk1/tomcat/webapps

121
pom-jar.xml Normal file
View file

@ -0,0 +1,121 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.stephenschafer</groupId>
<artifactId>budget</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/libs
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>libs/</classpathPrefix>
<mainClass>
com.stephenschafer.budget.Amazon
</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>5.8</version>
</dependency>
</dependencies>
</project>

114
pom.xml Normal file
View file

@ -0,0 +1,114 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.stephenschafer</groupId>
<artifactId>com.stephenschafer.budget</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<includes>
<include>**/*Example.java</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>5.8</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.4.1</version>
</dependency>
</dependencies>
</project>

5
rebuild Executable file
View file

@ -0,0 +1,5 @@
#!/bin/sh
cd $HOME/projects/com.stephenschafer.budget
if mvn clean package; then
./deploy
fi

3
run Executable file
View file

@ -0,0 +1,3 @@
#!/bin/bash
cd "$(dirname "${BASH_SOURCE[0]}")"
java -cp target/*.jar com.stephenschafer.budget.schema.Schema "$@"

4
run-categorize Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
cd "$(dirname "${BASH_SOURCE[0]}")"
./run categorize budget.properties

4
run-debug Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
cd "$(dirname "${BASH_SOURCE[0]}")"
JVM_ARGS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8004"
java $JVM_ARGS -cp target/*.jar com.stephenschafer.budget.schema.Schema "$@"

4
run-debug-categorize Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
cd "$(dirname "${BASH_SOURCE[0]}")"
./run-debug categorize budget.properties

4
run-debug-load Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
cd "$(dirname "${BASH_SOURCE[0]}")"
./run-debug load-csv budget.properties trilium Budget

4
run-load-csv Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
cd "$(dirname "${BASH_SOURCE[0]}")"
./run load-csv budget.properties trilium Budget

4
run-load-regex Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
cd "$(dirname "${BASH_SOURCE[0]}")"
./run load-regex budget.properties

4
run-process Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
cd "$(dirname "${BASH_SOURCE[0]}")"
./run process budget.properties

6
send Executable file
View file

@ -0,0 +1,6 @@
#!/bin/sh
echo "sending budget to stephenschafer.com"
PROJECT="$HOME/projects/com.stephenschafer.budget/target"
WAR="com.stephenschafer.budget-0.0.1-SNAPSHOT.war"
scp $PROJECT/$WAR steve@stephenschafer.com:~
ssh steve@stephenschafer.com "bin/deploy-budget"

2
show-tables.sql Normal file
View file

@ -0,0 +1,2 @@
select table_schema, table_name
from information_schema.tables where table_schema = 'budget_2024' and table_name like '%sandy%retail%return%';

View file

@ -0,0 +1,150 @@
package com.stephenschafer.budget.schema;
import java.util.regex.Pattern;
public class CatRegex {
private final Pattern pattern;
private final String category;
private final String source;
private final int priority;
private final String extraDescription;
private final Integer year;
private int id;
public CatRegex(final int id, final Pattern pattern, final String category, final String source,
final int priority, final String extraDescription, final Integer year) {
this.id = id;
this.pattern = pattern;
this.category = category;
this.source = source;
this.priority = priority;
this.extraDescription = extraDescription;
this.year = year;
}
public CatRegex(final String line) {
final String[] parts = line.split(",");
final String category = parts[0].trim();
final String regex = parts[1].trim();
String flagsString = "";
String source = "";
int priority = 0;
String extraDescription = "";
Integer year = null;
if (parts.length > 2) {
flagsString = parts[2].trim();
if (parts.length > 3) {
source = parts[3].trim();
if (parts.length > 4) {
final String priorityString = parts[4].trim();
if (priorityString.length() > 0) {
try {
priority = Integer.parseInt(priorityString);
}
catch (final NumberFormatException e) {
System.out.println(
"Invalid priority in reegex line: " + line + "<br/>");
}
}
if (parts.length > 5) {
extraDescription = parts[5].trim();
if (parts.length > 6) {
final String yearString = parts[6].trim();
if (yearString.length() > 0) {
try {
year = Integer.valueOf(yearString);
}
catch (final NumberFormatException e) {
System.out.println(
"Invalid year in reegex line: " + line + "<br/>");
}
}
if (parts.length > 7) {
System.out.println("Too many parts in " + line);
}
}
}
}
}
}
int flags = 0;
if (flagsString.indexOf("i") >= 0) {
flags |= Pattern.CASE_INSENSITIVE;
}
if (flagsString.indexOf("m") >= 0) {
flags |= Pattern.MULTILINE;
}
pattern = Pattern.compile(regex, flags);
this.category = category;
this.source = source.length() == 0 ? null : source;
this.priority = priority;
this.extraDescription = extraDescription;
this.year = year;
}
public String getSource() {
return source;
}
public Pattern getPattern() {
return pattern;
}
public String getCategory() {
return category;
}
public int getPriority() {
return priority;
}
@Override
public int hashCode() {
int hashCode = 0;
if (source != null) {
hashCode += source.hashCode();
}
return hashCode + pattern.hashCode();
}
@Override
public boolean equals(final Object obj) {
if (obj instanceof CatRegex) {
final CatRegex that = (CatRegex) obj;
if (!source.equals(that.source) || !pattern.equals(that.pattern)) {
return false;
}
}
return true;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append(category);
sb.append(": ");
sb.append(pattern.toString());
if (source != null && source.trim().length() > 0) {
sb.append(" (" + source + ")");
}
sb.append(", ");
sb.append(priority);
return sb.toString();
}
public String getExtraDescription() {
return extraDescription;
}
public int getId() {
return id;
}
public void setId(final int id) {
this.id = id;
}
public Integer getYear() {
return year;
}
}

View file

@ -0,0 +1,37 @@
package com.stephenschafer.budget.schema;
import java.util.Map;
class Category {
final int id;
final Integer parentId;
final String name;
public Category(final int id, final Integer parentId, final String name) {
this.id = id;
this.parentId = parentId;
this.name = name;
}
String getFullName(final Map<Integer, Category> categories) {
final StringBuilder sb = new StringBuilder();
if (parentId != null) {
final Category parentCategory = categories.get(parentId);
sb.append(parentCategory.getFullName(categories));
}
sb.append(name);
return sb.toString();
}
public int getId() {
return id;
}
public Integer getParentId() {
return parentId;
}
public String getName() {
return name;
}
}

View file

@ -0,0 +1,75 @@
package com.stephenschafer.budget.schema;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class Config {
private final Properties systemProperties;
private final Properties properties;
private String triliumUrl;
private String triliumPassword;
private String logFilename;
private String dbUrl;
private String dbUsername;
private String dbPassword;
public Config() {
systemProperties = System.getProperties();
properties = new Properties();
}
public void load(final String fileName) throws FileNotFoundException, IOException {
String propertiesFileName = fileName;
if (propertiesFileName == null) {
propertiesFileName = systemProperties.getProperty("properties-filename");
}
if (propertiesFileName != null) {
final File propertiesFile = new File(propertiesFileName);
try (InputStream inStream = new FileInputStream(propertiesFile)) {
properties.load(inStream);
}
}
triliumUrl = getProperty("trilium-url");
triliumPassword = getProperty("trilium-password");
logFilename = getProperty("log-filename");
dbUrl = getProperty("db-url");
dbUsername = getProperty("db-username");
dbPassword = getProperty("db-password");
}
private String getProperty(final String name) {
String triliumUrl = systemProperties.getProperty(name);
if (triliumUrl == null) {
triliumUrl = properties.getProperty(name);
}
return triliumUrl;
}
public String getTriliumUrl() {
return triliumUrl;
}
public String getTriliumPassword() {
return triliumPassword;
}
public String getLogFilename() {
return logFilename;
}
public String getDbUrl() {
return dbUrl;
}
public String getDbUsername() {
return dbUsername;
}
public String getDbPassword() {
return dbPassword;
}
}

View file

@ -0,0 +1,690 @@
package com.stephenschafer.budget.schema;
import java.io.Serializable;
import java.net.SocketException;
import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Queue;
import java.util.concurrent.Executor;
import java.util.logging.Level;
import java.util.logging.Logger;
public class DbConnectionPool implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger LOGGER;
private final String uRL;
private final String username;
private final String password;
private final String driver;
private final Queue<PooledConnection> connections;
private long openConnectionIndex;
private final Map<Long, OpenConnectionInfo> openConnections;
private long timeout;
static {
LOGGER = Logger.getLogger(DbConnectionPool.class.getName());
}
public DbConnectionPool(final String dbDriver, final String dbName, final String dbUsername,
final String dbPassword) throws ClassNotFoundException, SQLException {
connections = new LinkedList<>();
openConnectionIndex = 0L;
openConnections = new HashMap<>();
timeout = 900000L;
driver = dbDriver;
uRL = dbName;
username = dbUsername;
password = dbPassword;
validateConnection();
}
public final void validateConnection() throws ClassNotFoundException, SQLException {
DbConnectionPool.LOGGER.log(Level.FINEST, "Testing connection pool");
DbConnectionPool.LOGGER.log(Level.FINEST, "Instantiating " + driver + "\n");
Class.forName(driver);
DbConnectionPool.LOGGER.log(Level.FINEST, "Connecting");
final Connection connection = DriverManager.getConnection(uRL, username, password);
try {
final DatabaseMetaData dbmd = connection.getMetaData();
DbConnectionPool.LOGGER.log(Level.FINEST,
"Connection to " + dbmd.getDatabaseProductName() + " "
+ dbmd.getDatabaseProductVersion() + " successful.");
}
finally {
connection.close();
}
connection.close();
}
public final void clear() throws SQLException {
synchronized (this) {
while (!connections.isEmpty()) {
final PooledConnection connection = connections.remove();
connection.reallyClose();
}
}
}
public final PooledConnection getConnection(final int transactionIsolation,
final boolean readOnly, final boolean autoCommit) throws SQLException {
while (true) {
PooledConnection oldConnection;
final long timeout;
synchronized (this) {
if (connections.isEmpty()) {
oldConnection = null;
}
else {
oldConnection = connections.remove();
}
timeout = this.timeout;
}
if (oldConnection == null) {
DbConnectionPool.LOGGER.log(Level.FINEST, "Connecting");
SQLException exception = null;
int retryCount = 0;
while (retryCount < 10) {
Connection newConnection;
try {
newConnection = DriverManager.getConnection(uRL, username, password);
}
catch (final SQLException e) {
if (!(e.getCause() instanceof SocketException)) {
throw e;
}
exception = e;
DbConnectionPool.LOGGER.log(Level.FINEST, "Retrying", e);
try {
Thread.sleep(1000L);
}
catch (final InterruptedException ex) {
}
++retryCount;
newConnection = null;
}
if (newConnection != null) {
newConnection.setAutoCommit(true);
newConnection.setTransactionIsolation(transactionIsolation);
newConnection.setReadOnly(readOnly);
newConnection.setAutoCommit(autoCommit);
final long index = incrementOpenConnectionCount();
return new PooledConnection(newConnection, index);
}
}
if (exception != null) {
throw exception;
}
}
if (oldConnection != null) {
if (oldConnection.isClosed()) {
DbConnectionPool.LOGGER.log(Level.WARNING,
"Pooled connection was already closed");
}
else {
Label_0430: {
Label_0418: {
if ((timeout != 0L) && (System.currentTimeMillis()
- oldConnection.getLastAccess() >= timeout)) {
break Label_0418;
}
try {
oldConnection.setAutoCommit(true);
oldConnection.setTransactionIsolation(transactionIsolation);
oldConnection.setReadOnly(readOnly);
oldConnection.setAutoCommit(autoCommit);
synchronized (this) {
final Long key = Long.valueOf(oldConnection.getIndex());
final OpenConnectionInfo info = openConnections.get(key);
if (info != null) {
DbConnectionPool.LOGGER.log(Level.WARNING,
"Overwriting open connection info: " + key + " "
+ info);
}
openConnections.put(key, new OpenConnectionInfo());
}
return oldConnection;
}
catch (final Exception e2) {
DbConnectionPool.LOGGER.log(Level.SEVERE,
"Unable to reuse DB connection", e2);
break Label_0430;
}
}
DbConnectionPool.LOGGER.log(Level.FINEST, "DB connection timed out");
try {
oldConnection.reallyClose();
}
catch (final Exception e2) {
DbConnectionPool.LOGGER.log(Level.SEVERE,
"Unable to really close DB connection", e2);
}
}
}
}
}
}
private long incrementOpenConnectionCount() {
synchronized (this) {
final long index = openConnectionIndex++;
final Long key = Long.valueOf(index);
final OpenConnectionInfo info = openConnections.get(key);
if (info != null) {
DbConnectionPool.LOGGER.log(Level.WARNING,
"Overwriting open connection info: " + key + " " + info);
}
openConnections.put(key, new OpenConnectionInfo());
return index;
}
}
protected final void add(final PooledConnection connection) {
synchronized (this) {
final OpenConnectionInfo info = openConnections.remove(
Long.valueOf(connection.getIndex()));
if (info == null) {
DbConnectionPool.LOGGER.log(Level.WARNING,
"adding orphaned connection: " + connection.getIndex());
}
else {
connections.offer(connection);
}
}
}
public final long getOpenConnectionIndex() {
synchronized (this) {
return openConnectionIndex;
}
}
public final OpenConnectionInfo getOpenConnectionInfo(final long index) {
synchronized (this) {
return openConnections.get(Long.valueOf(index));
}
}
public final int getOpenConnectionCount() {
synchronized (this) {
return openConnections.size();
}
}
public final int getPooledConnectionCount() {
synchronized (this) {
return connections.size();
}
}
@Override
public final String toString() {
final StringBuilder buf = new StringBuilder();
buf.append("DB ");
buf.append(uRL);
buf.append(" ");
synchronized (this) {
buf.append("open: ");
buf.append(openConnections.size());
buf.append(", pooled: ");
buf.append(connections.size());
buf.append(", next: ");
buf.append(openConnectionIndex);
}
return buf.toString();
}
public final long getTimeout() {
synchronized (this) {
return timeout;
}
}
public final void setTimeout(final long timeout) {
synchronized (this) {
this.timeout = timeout;
}
}
public final String getDriver() {
return driver;
}
public final String getURL() {
return uRL;
}
public final String getPassword() {
return password;
}
public final String getUsername() {
return username;
}
public synchronized Map<Long, Long> getOpenConnections() {
final Map<Long, Long> map = new HashMap<>();
for (final Long index : openConnections.keySet()) {
final OpenConnectionInfo info = openConnections.get(index);
map.put(index, Long.valueOf(info.timestamp));
}
return map;
}
public static final class OpenConnectionInfo {
public final long timestamp;
private final List<StackTraceElement> stackTrace;
public OpenConnectionInfo() {
timestamp = System.currentTimeMillis();
final StackTraceElement[] steArray = Thread.currentThread().getStackTrace();
final List<StackTraceElement> stackTrace = new ArrayList<>(
steArray.length);
StackTraceElement[] array;
for (int length = (array = steArray).length, i = 0; i < length; ++i) {
final StackTraceElement element = array[i];
stackTrace.add(element);
}
this.stackTrace = Collections.unmodifiableList(stackTrace);
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("Timestamp: ");
sb.append(new Date(timestamp));
sb.append("\n");
for (final StackTraceElement element : stackTrace) {
sb.append(element);
sb.append("\n");
}
return sb.toString();
}
}
public class PooledConnection implements Connection {
private final Connection connection;
private long lastAccess;
private boolean autoCommit;
private boolean readOnly;
private final long index;
public PooledConnection(final Connection connection, final long index) {
lastAccess = System.currentTimeMillis();
autoCommit = false;
readOnly = false;
this.index = index;
this.connection = connection;
try {
autoCommit = connection.getAutoCommit();
}
catch (final SQLException e) {
DbConnectionPool.LOGGER.log(Level.WARNING, "Unable to get auto commit", e);
}
try {
readOnly = connection.isReadOnly();
}
catch (final SQLException e) {
DbConnectionPool.LOGGER.log(Level.WARNING, "Unable to get read only", e);
}
}
public void clearPool() throws SQLException {
clear();
}
@Override
public String nativeSQL(final String sql) throws SQLException {
return connection.nativeSQL(sql);
}
@Override
public int hashCode() {
return connection.hashCode();
}
@Override
public Map<String, Class<?>> getTypeMap() throws SQLException {
return connection.getTypeMap();
}
@Override
public PreparedStatement prepareStatement(final String sql) throws SQLException {
final PreparedStatement stmt = connection.prepareStatement(sql);
if (connection.getAutoCommit() != autoCommit || connection.isReadOnly() != readOnly) {
final StringBuilder sb = new StringBuilder();
String sep = "";
if (connection.getAutoCommit() != autoCommit) {
sb.append(sep);
sep = " and ";
sb.append("autoCommit has changed from " + autoCommit);
}
if (connection.isReadOnly() != readOnly) {
sb.append(sep);
sep = " and ";
sb.append("readOnly has changed from " + readOnly);
}
sb.append(" in ");
sb.append(stmt);
DbConnectionPool.LOGGER.log(Level.WARNING, sb.toString());
}
return stmt;
}
@Override
public void setTransactionIsolation(final int level) throws SQLException {
connection.setTransactionIsolation(level);
}
@Override
public String getCatalog() throws SQLException {
return connection.getCatalog();
}
@Override
public int getTransactionIsolation() throws SQLException {
return connection.getTransactionIsolation();
}
@Override
public void releaseSavepoint(final Savepoint savepoint) throws SQLException {
connection.releaseSavepoint(savepoint);
}
@Override
public int getHoldability() throws SQLException {
return connection.getHoldability();
}
@Override
public CallableStatement prepareCall(final String sql, final int resultSetType,
final int resultSetConcurrency, final int resultSetHoldability)
throws SQLException {
return connection.prepareCall(sql, resultSetType, resultSetConcurrency,
resultSetHoldability);
}
@Override
public boolean getAutoCommit() throws SQLException {
return connection.getAutoCommit();
}
@Override
public Statement createStatement() throws SQLException {
return connection.createStatement();
}
@Override
public CallableStatement prepareCall(final String sql) throws SQLException {
return connection.prepareCall(sql);
}
@Override
public void setAutoCommit(final boolean autoCommit) throws SQLException {
this.autoCommit = autoCommit;
connection.setAutoCommit(autoCommit);
}
@Override
public PreparedStatement prepareStatement(final String sql, final int autoGeneratedKeys)
throws SQLException {
return connection.prepareStatement(sql, autoGeneratedKeys);
}
@Override
public void setReadOnly(final boolean readOnly) throws SQLException {
this.readOnly = readOnly;
connection.setReadOnly(readOnly);
}
@Override
public CallableStatement prepareCall(final String sql, final int resultSetType,
final int resultSetConcurrency) throws SQLException {
return connection.prepareCall(sql, resultSetType, resultSetConcurrency);
}
@Override
public SQLWarning getWarnings() throws SQLException {
return connection.getWarnings();
}
@Override
public PreparedStatement prepareStatement(final String sql, final int resultSetType,
final int resultSetConcurrency) throws SQLException {
return connection.prepareStatement(sql, resultSetType, resultSetConcurrency);
}
@Override
public boolean equals(final Object obj) {
return connection.equals(obj);
}
@Override
public PreparedStatement prepareStatement(final String sql, final int[] columnIndexes)
throws SQLException {
return connection.prepareStatement(sql, columnIndexes);
}
@Override
public boolean isClosed() throws SQLException {
return connection.isClosed();
}
@Override
public PreparedStatement prepareStatement(final String sql, final int resultSetType,
final int resultSetConcurrency, final int resultSetHoldability)
throws SQLException {
return connection.prepareStatement(sql, resultSetType, resultSetConcurrency,
resultSetHoldability);
}
@Override
public void commit() throws SQLException {
connection.commit();
}
@Override
public void clearWarnings() throws SQLException {
connection.clearWarnings();
}
@Override
public void setCatalog(final String catalog) throws SQLException {
connection.setCatalog(catalog);
}
@Override
public void close() {
add(this);
lastAccess = System.currentTimeMillis();
}
public void reallyClose() throws SQLException {
connection.close();
}
@Override
public String toString() {
return connection.toString();
}
@Override
public DatabaseMetaData getMetaData() throws SQLException {
return connection.getMetaData();
}
@Override
public void rollback() throws SQLException {
connection.rollback();
}
@Override
public Savepoint setSavepoint(final String name) throws SQLException {
return connection.setSavepoint(name);
}
@Override
public boolean isReadOnly() throws SQLException {
return connection.isReadOnly();
}
@Override
public Statement createStatement(final int resultSetType, final int resultSetConcurrency)
throws SQLException {
return connection.createStatement(resultSetType, resultSetConcurrency);
}
@Override
public void rollback(final Savepoint savepoint) throws SQLException {
connection.rollback(savepoint);
}
@Override
public PreparedStatement prepareStatement(final String sql, final String[] columnNames)
throws SQLException {
return connection.prepareStatement(sql, columnNames);
}
@Override
public Savepoint setSavepoint() throws SQLException {
return connection.setSavepoint();
}
@Override
public Statement createStatement(final int resultSetType, final int resultSetConcurrency,
final int resultSetHoldability) throws SQLException {
return connection.createStatement(resultSetType, resultSetConcurrency,
resultSetHoldability);
}
@Override
public void setTypeMap(final Map<String, Class<?>> map) throws SQLException {
connection.setTypeMap(map);
}
@Override
public void setHoldability(final int holdability) throws SQLException {
connection.setHoldability(holdability);
}
public long getLastAccess() {
return lastAccess;
}
@Override
public Array createArrayOf(final String arg0, final Object[] arg1) throws SQLException {
return connection.createArrayOf(arg0, arg1);
}
@Override
public Blob createBlob() throws SQLException {
return connection.createBlob();
}
@Override
public Clob createClob() throws SQLException {
return connection.createClob();
}
@Override
public NClob createNClob() throws SQLException {
return connection.createNClob();
}
@Override
public SQLXML createSQLXML() throws SQLException {
return connection.createSQLXML();
}
@Override
public Struct createStruct(final String arg0, final Object[] arg1) throws SQLException {
return connection.createStruct(arg0, arg1);
}
@Override
public Properties getClientInfo() throws SQLException {
return connection.getClientInfo();
}
@Override
public String getClientInfo(final String arg0) throws SQLException {
return connection.getClientInfo(arg0);
}
@Override
public boolean isValid(final int arg0) throws SQLException {
return connection.isValid(arg0);
}
@Override
public void setClientInfo(final Properties arg0) throws SQLClientInfoException {
connection.setClientInfo(arg0);
}
@Override
public void setClientInfo(final String arg0, final String arg1)
throws SQLClientInfoException {
connection.setClientInfo(arg0, arg1);
}
@Override
public boolean isWrapperFor(final Class<?> arg0) throws SQLException {
return connection.isWrapperFor(arg0);
}
@Override
public <T> T unwrap(final Class<T> arg0) throws SQLException {
return connection.unwrap(arg0);
}
public long getIndex() {
return index;
}
@Override
public void setSchema(final String schema) throws SQLException {
connection.setSchema(schema);
}
@Override
public String getSchema() throws SQLException {
return connection.getSchema();
}
@Override
public void abort(final Executor executor) throws SQLException {
connection.abort(executor);
}
@Override
public void setNetworkTimeout(final Executor executor, final int milliseconds)
throws SQLException {
connection.setNetworkTimeout(executor, milliseconds);
}
@Override
public int getNetworkTimeout() throws SQLException {
return connection.getNetworkTimeout();
}
}
}

View file

@ -0,0 +1,12 @@
package com.stephenschafer.budget.schema;
import java.math.BigDecimal;
import java.util.Date;
class Detail {
int transactionId;
String source;
String description;
Date date;
BigDecimal amount;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,61 @@
package com.stephenschafer.budget.schema;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
class UnresolvedItem implements Comparable<UnresolvedItem> {
private final int year;
private final String source;
private final String description;
private final java.sql.Date date;
private final BigDecimal amount;
public UnresolvedItem(final int year, final String source, final String description,
final java.sql.Date date, final BigDecimal amount) {
this.year = year;
this.source = source;
this.description = description;
this.date = date;
this.amount = amount;
}
@Override
public int compareTo(final UnresolvedItem that) {
if (this.year < that.year) {
return -1;
}
if (this.year > that.year) {
return 1;
}
String thisSource = source;
if (thisSource == null) {
thisSource = "";
}
String thatSource = that.source;
if (thatSource == null) {
thatSource = "";
}
final int comparison = thisSource.compareTo(thatSource);
if (comparison != 0) {
return comparison;
}
String thisdescription = description;
if (thisdescription == null) {
thisdescription = "";
}
String thatdescription = that.description;
if (thatdescription == null) {
thatdescription = "";
}
return thisdescription.compareTo(thatdescription);
}
public String replace(final String string) {
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
return string.replace("${year}", String.valueOf(year)).replace("${source}", source).replace(
"${description}", description).replace("${date}", df.format(date)).replace("${amount}",
amount.setScale(2, RoundingMode.HALF_UP).toPlainString());
}
}

View file

@ -0,0 +1,22 @@
package com.stephenschafer.budget.schema;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
public class Util {
public static String getResourceAsString(final String resourceName) throws IOException {
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
final StringBuilder sb = new StringBuilder();
try (final Reader reader = new InputStreamReader(
classLoader.getResourceAsStream(resourceName))) {
final char[] buffer = new char[0x1000];
int charsRead = reader.read(buffer);
while (charsRead >= 0) {
sb.append(buffer, 0, charsRead);
charsRead = reader.read(buffer);
}
}
return sb.toString();
}
}

View file

@ -0,0 +1,11 @@
function showDetail(h2, categoryId) {
var tr = document.body.querySelector("#cat" + categoryId);
if(tr.style.display == "none") {
tr.style.display = "";
h2.style.fontWeight = "bold";
}
else {
tr.style.display = "none";
h2.style.fontWeight = "normal";
}
}

View file

@ -0,0 +1,17 @@
<tr>
<td>
<h2 style="cursor: pointer; font-weight: normal; " onclick="showDetail(this, ${id})">${name}</h2>
</td>
<td style="text-align: right">
<h2 style="font-weight: normal; ">${amount}</h2>
</td>
</tr>
<tr id="cat${id}" style="display: none">
<td colspan="2">
<table>
<tr>
<th>Source</th>
<th>Description</th>
<th>Date</th>
<th style="text-align: right">Amount</th>
</tr>

View file

@ -0,0 +1 @@
update ${databaseName}.transaction set extra_description = '', regex_id = null

View file

@ -0,0 +1,6 @@
create table ${databaseName}.category (
id int not null primary key auto_increment,
parent_category_id int,
name text not null,
constraint unique key (parent_category_id, name)
)

View file

@ -0,0 +1,10 @@
create table ${databaseName}.regex (
id int not null primary key auto_increment,
category_id int,
regex text not null,
flags int,
source varchar(32),
priority int,
description text,
year int
)

View file

@ -0,0 +1,5 @@
create table ${databaseName}.transaction_regex_mtm (
regex_id int not null,
transaction_id int not null,
primary key (transaction_id, regex_id)
)

View file

@ -0,0 +1,12 @@
create table ${databaseName}.transaction (
id int not null primary key auto_increment,
source varchar(32),
unique_identifier varchar(64),
type varchar(64),
description text,
extra_description text,
date date,
amount decimal(10,2),
optional int default 0,
regex_id int
)

View file

@ -0,0 +1,3 @@
create table ${databaseName}.years (
year int not null primary key
)

View file

@ -0,0 +1 @@
select table_rows from information_schema.tables where table_schema = ? and table_name = ?

View file

@ -0,0 +1,5 @@
select
id,
parent_category_id,
name
from ${databaseName}.category

View file

@ -0,0 +1,8 @@
select
transaction_date,
description,
category,
type,
amount
from ${databaseName}.chase

View file

@ -0,0 +1 @@
select id from ${databaseName}.category where name = ? and parent_category_id = ?

View file

@ -0,0 +1,7 @@
select
status,
date,
description,
debit,
credit
from ${databaseName}.citi

View file

@ -0,0 +1,15 @@
select
m.monetary_component_type_code as type,
i.${productNameCol} as name,
i.digital_order_item_id as order_id,
i.order_date as date,
sum(m.transaction_amount) as amount
from ${databaseName}.${digOrdItems} i
left outer join ${databaseName}.${digOrders} o on o.order_id = i.order_id
left outer join ${databaseName}.${digOrdersMonetary} m on m.digital_order_item_id = i.digital_order_item_id
group by
i.${productNameCol},
i.digital_order_item_id,
i.order_date,
m.monetary_component_type_code

View file

@ -0,0 +1,14 @@
select
m.monetary_component_type as type,
i.${productNameCol} as name,
i.digital_order_item_id as order_id,
i.order_date as date,
-sum(m.transaction_amount) as amount
from ${databaseName}.${digOrdItems} i
inner join ${databaseName}.${digOrdReturnsMonetary} m on m.digital_order_item_id = i.digital_order_item_id
group by
i.${productNameCol},
i.digital_order_item_id,
i.order_date,
m.monetary_component_type

View file

@ -0,0 +1,7 @@
select
trans_date,
post_date,
description,
amount,
category
from ${databaseName}.discover

View file

@ -0,0 +1,6 @@
select
date,
description,
type,
amount
from ${databaseName}.first_bank

View file

@ -0,0 +1,13 @@
select
date,
time,
time_zone,
name,
type,
status,
currency,
amount,
receipt_id,
balance
from ${databaseName}.paypal

View file

@ -0,0 +1,10 @@
select
id,
category_id,
regex,
flags,
source,
priority,
description,
year
from ${databaseName}.regex

View file

@ -0,0 +1,8 @@
select
website as website,
product_name as name,
order_id as order_id,
date(order_date) as date,
total_owed as amount
from ${databaseName}.${retailOrders} o

View file

@ -0,0 +1 @@
select id from ${databaseName}.category where name = ? and parent_category_id is null

View file

@ -0,0 +1,3 @@
select t.id, t.date, t.source, t.description, t.amount
from ${databaseName}.transaction t
where t.regex_id is null

View file

@ -0,0 +1,3 @@
select
year
from ${databaseName}.years

View file

@ -0,0 +1 @@
insert into ${databaseName}.category (name, parent_category_id) values (?, ?)

View file

@ -0,0 +1,9 @@
insert into ${databaseName}.regex (
category_id,
regex,
flags,
source,
priority,
description,
year
) values (?, ?, ?, ?, ?, ?, ?)

View file

@ -0,0 +1 @@
insert into ${databaseName}.category (name) values (?)

View file

@ -0,0 +1,8 @@
insert into ${databaseName}.transaction (
source,
unique_identifier,
type,
description,
date,
amount
) values (?, ?, ?, ?, ?, ?)

View file

@ -0,0 +1 @@
insert into ${databaseName}.transaction_regex_mtm (regex_id, transaction_id) values (?, ?)

View file

@ -0,0 +1,3 @@
insert into ${databaseName}.years (
year
) values (?)

View file

@ -0,0 +1 @@
update ${databaseName}.transaction set extra_description = ? where id = ?

View file

@ -0,0 +1 @@
update ${databaseName}.transaction set regex_id = ? where id = ?