Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| aa3f641bf2 | |||
| d4f89f39bd | |||
| 91a6c4a304 | |||
| ed648a2740 | |||
| 6330d7fd51 | |||
| c241964a8b | |||
| f3e0da2689 | |||
| 4421075bec | |||
| 71c79575c8 | |||
| 1866782111 | |||
| a7e76e00d3 | |||
| 1cadfe5bfc | |||
| c40be1c203 | |||
| 02026633ed | |||
| c4297a4be2 | |||
| fd52d3df6d | |||
| c320ef615d | |||
| 2a20ea7bdb | |||
| a56ad43852 | |||
| 188214dfbe | |||
| cdbe2cccc0 | |||
| 5152846478 | |||
| f5c5d546c5 | |||
| 5c9d54dabf | |||
| 96d5968fef | |||
| 88b39820ca | |||
| 25bedae873 | |||
| 1ec02d74a3 | |||
| 783d9f9bc0 |
@@ -0,0 +1,4 @@
|
|||||||
|
target/
|
||||||
|
dependency-reduced-pom.xml
|
||||||
|
tools/*.db
|
||||||
|
tools/*.html
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<profiles version="21">
|
||||||
|
<profile kind="CodeFormatterProfile" name="jFxKasse" version="21">
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="false"/>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"vscjava.vscode-java-pack",
|
||||||
|
"vscjava.vscode-maven",
|
||||||
|
"redhat.java"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "java",
|
||||||
|
"name": "Run jFxKasse",
|
||||||
|
"request": "launch",
|
||||||
|
"mainClass": "com.jFxKasse.application.JavaFX11Main",
|
||||||
|
"projectName": "jFxKasse",
|
||||||
|
"vmArgs": "--module-path ${env:PATH_TO_FX} --add-modules javafx.controls,javafx.fxml --add-opens javafx.graphics/com.sun.javafx.scene=ALL-UNNAMED"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "java",
|
||||||
|
"name": "Run jFxKasse (Maven)",
|
||||||
|
"request": "launch",
|
||||||
|
"mainClass": "com.jFxKasse.application.JavaFX11Main",
|
||||||
|
"projectName": "jFxKasse"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"java.project.sourcePaths": [
|
||||||
|
"src/main/java"
|
||||||
|
],
|
||||||
|
"java.project.outputPath": "target/classes",
|
||||||
|
"java.project.referencedLibraries": [],
|
||||||
|
"java.configuration.updateBuildConfiguration": "automatic",
|
||||||
|
"java.compile.nullAnalysis.mode": "automatic",
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"files.encoding": "utf8",
|
||||||
|
|
||||||
|
// Java formatter: point to workspace-local Eclipse formatter profile
|
||||||
|
"java.format.settings.url": ".vscode/eclipse-formatter.xml",
|
||||||
|
"java.format.settings.profile": "jFxKasse",
|
||||||
|
"[java]": {
|
||||||
|
"editor.defaultFormatter": "redhat.java"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "mvn compile",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "mvn compile",
|
||||||
|
"group": "build",
|
||||||
|
"problemMatcher": [
|
||||||
|
"$javac"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "mvn package",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "mvn package -DskipTests",
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"problemMatcher": [
|
||||||
|
"$javac"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "mvn clean",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "mvn clean",
|
||||||
|
"group": "build",
|
||||||
|
"problemMatcher": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "mvn javafx:run",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "mvn javafx:run",
|
||||||
|
"group": "build",
|
||||||
|
"problemMatcher": [
|
||||||
|
"$javac"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "mvn test",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "mvn test",
|
||||||
|
"group": "test",
|
||||||
|
"problemMatcher": [
|
||||||
|
"$javac"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,2 +1,82 @@
|
|||||||
# jFxKasse
|
# jFxKasse
|
||||||
easy payment system for small to middel sized events with a sales slip printer
|
|
||||||
|
Simple POS (Point of Sale) system for small to medium-sized events with receipt printer support.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Java JDK 21+
|
||||||
|
- Maven 3.9+
|
||||||
|
- Display >= 1366x768
|
||||||
|
|
||||||
|
## Video Tutorials (German | Deutsch)
|
||||||
|
[YouTube Video: jFxKasse - Kassensystem - Kurzanleitung](https://www.youtube.com/watch?v=DV9DDESw40I)
|
||||||
|
|
||||||
|
[YouTube Video: jFxKasse - Kassensystem - Installieren](https://www.youtube.com/watch?v=IY1bqRjwh0Q)
|
||||||
|
|
||||||
|
## Setup (VSCode on openSUSE Tumbleweed)
|
||||||
|
|
||||||
|
### 1. Install dependencies
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo zypper install java-21-openjdk java-21-openjdk-devel maven
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Install VSCode extensions
|
||||||
|
|
||||||
|
Open the project in VSCode. You will be prompted to install the recommended extensions:
|
||||||
|
|
||||||
|
- **Extension Pack for Java** (`vscjava.vscode-java-pack`)
|
||||||
|
- **Maven for Java** (`vscjava.vscode-maven`)
|
||||||
|
- **Language Support for Java** (`redhat.java`)
|
||||||
|
|
||||||
|
### 3. Build & Run
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Compile
|
||||||
|
mvn compile
|
||||||
|
|
||||||
|
# Run via Maven
|
||||||
|
mvn javafx:run
|
||||||
|
|
||||||
|
# Package as fat JAR
|
||||||
|
mvn package
|
||||||
|
java -jar target/jFxKasse-shaded.jar
|
||||||
|
```
|
||||||
|
|
||||||
|
Or use the preconfigured VSCode tasks (`Ctrl+Shift+B`) and launch configurations (`F5`).
|
||||||
|
|
||||||
|
## Screenshots
|
||||||
|
|
||||||
|
| Main View | Jobs | Positions | Settings |
|
||||||
|
|-----------|------|-----------|----------|
|
||||||
|
|  |  |  |  |
|
||||||
|
|
||||||
|
## Hardware
|
||||||
|
|
||||||
|
Tested with: [Epson TM T20II](https://www.epson.de/products/sd/pos-printer/epson-tm-t20ii). Other receipt printers should work as well.
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
### merge_db
|
||||||
|
|
||||||
|
Merges multiple SQLite databases into one file with automatic deduplication.
|
||||||
|
Reference tables (`category`, `positionen`) are deduplicated by content; `jobs` rows are appended in order with re-sequenced IDs to avoid conflicts.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python tools/merge_db.py -o OUTPUT_DB INPUT_DB [INPUT_DB ...]
|
||||||
|
|
||||||
|
# Example
|
||||||
|
python tools/merge_db.py -o merged.db 02.db 03.db 04.db
|
||||||
|
```
|
||||||
|
|
||||||
|
### generate_report
|
||||||
|
|
||||||
|
Generates a German HTML + PDF report from a [jFxKasse](https://git.mosad.xyz/localhorst/jFxKasse) SQLite database, including category/item tables, order KPIs, revenue breakdowns, and hourly trend charts per category.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python tools/generate_report.py kassendaten.db # → kassendaten_bericht.html
|
||||||
|
python tools/generate_report.py kassendaten.db -o out.html
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
GPL-3.0
|
||||||
@@ -1,42 +1,49 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
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">
|
||||||
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>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>com</groupId>
|
<groupId>com</groupId>
|
||||||
<artifactId>jFxKasse</artifactId>
|
<artifactId>jFxKasse</artifactId>
|
||||||
<version>0.2.0</version>
|
<version>0.4.0</version>
|
||||||
<name>jFxKasse</name>
|
<name>jFxKasse</name>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.source>21</maven.compiler.source>
|
||||||
|
<maven.compiler.target>21</maven.compiler.target>
|
||||||
|
<maven.compiler.release>21</maven.compiler.release>
|
||||||
|
<javafx.version>23.0.1</javafx.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit-jupiter</artifactId>
|
||||||
<version>4.12</version>
|
<version>6.0.3</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.openjfx</groupId>
|
<groupId>org.openjfx</groupId>
|
||||||
<artifactId>javafx-controls</artifactId>
|
<artifactId>javafx-controls</artifactId>
|
||||||
<version>11</version>
|
<version>${javafx.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.openjfx</groupId>
|
<groupId>org.openjfx</groupId>
|
||||||
<artifactId>javafx-fxml</artifactId>
|
<artifactId>javafx-fxml</artifactId>
|
||||||
<version>11</version>
|
<version>${javafx.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.jfoenix</groupId>
|
<groupId>com.jfoenix</groupId>
|
||||||
<artifactId>jfoenix</artifactId>
|
<artifactId>jfoenix</artifactId>
|
||||||
<version>9.0.8</version>
|
<version>9.0.10</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.xerial</groupId>
|
<groupId>org.xerial</groupId>
|
||||||
<artifactId>sqlite-jdbc</artifactId>
|
<artifactId>sqlite-jdbc</artifactId>
|
||||||
<version>3.23.1</version>
|
<version>3.51.2.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
@@ -46,11 +53,11 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.8.0</version>
|
<version>3.15.0</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<source>11</source>
|
<source>21</source>
|
||||||
<target>11</target>
|
<target>21</target>
|
||||||
<!--<release>11</release> -->
|
<release>21</release>
|
||||||
<showWarnings>true</showWarnings>
|
<showWarnings>true</showWarnings>
|
||||||
<showDeprecation>true</showDeprecation>
|
<showDeprecation>true</showDeprecation>
|
||||||
</configuration>
|
</configuration>
|
||||||
@@ -59,7 +66,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
<artifactId>exec-maven-plugin</artifactId>
|
<artifactId>exec-maven-plugin</artifactId>
|
||||||
<version>1.6.0</version>
|
<version>3.6.3</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<goals>
|
<goals>
|
||||||
@@ -71,17 +78,16 @@
|
|||||||
<mainClass>com.jFxKasse.application.Main</mainClass>
|
<mainClass>com.jFxKasse.application.Main</mainClass>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
<version>3.2.1</version>
|
<version>3.6.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<finalName>jFxKasse</finalName>
|
<finalName>jFxKasse</finalName>
|
||||||
<shadedArtifactAttached>true</shadedArtifactAttached>
|
<shadedArtifactAttached>true</shadedArtifactAttached>
|
||||||
<transformers>
|
<transformers>
|
||||||
<transformer
|
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||||
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
|
||||||
<mainClass>com.jFxKasse.application.JavaFX11Main</mainClass>
|
<mainClass>com.jFxKasse.application.JavaFX11Main</mainClass>
|
||||||
</transformer>
|
</transformer>
|
||||||
</transformers>
|
</transformers>
|
||||||
@@ -95,7 +101,16 @@
|
|||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.openjfx</groupId>
|
||||||
|
<artifactId>javafx-maven-plugin</artifactId>
|
||||||
|
<version>0.0.8</version>
|
||||||
|
<configuration>
|
||||||
|
<mainClass>com.jFxKasse.application.JavaFX11Main</mainClass>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
After Width: | Height: | Size: 123 KiB |
|
After Width: | Height: | Size: 128 KiB |
|
After Width: | Height: | Size: 107 KiB |
|
After Width: | Height: | Size: 83 KiB |
@@ -1,12 +1,8 @@
|
|||||||
package com.jFxKasse.application;
|
package com.jFxKasse.application;
|
||||||
|
|
||||||
import com.jFxKasse.application.Main;
|
public class JavaFX11Main {
|
||||||
|
|
||||||
public class JavaFX11Main
|
public static void main(String[] args) {
|
||||||
{
|
Main.main(args);
|
||||||
|
|
||||||
public static void main(String[] args)
|
|
||||||
{
|
|
||||||
Main.main(args);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,119 +1,153 @@
|
|||||||
package com.jFxKasse.application;
|
package com.jFxKasse.application;
|
||||||
|
|
||||||
import javafx.application.Application;
|
import com.jFxKasse.controller.MainWindowController;
|
||||||
import java.io.File;
|
import com.jFxKasse.controller.PrinterController;
|
||||||
import javafx.animation.Animation;
|
import com.jFxKasse.controller.XMLController;
|
||||||
import javafx.animation.KeyFrame;
|
import com.jFxKasse.controller.DBController;
|
||||||
import javafx.animation.Timeline;
|
import com.jFxKasse.controller.KeyController;
|
||||||
import javafx.fxml.FXMLLoader;
|
|
||||||
import javafx.stage.Stage;
|
import javafx.application.Application;
|
||||||
import javafx.util.Duration;
|
import java.io.File;
|
||||||
import com.jFxKasse.controller.MainWindowController;
|
import javafx.animation.Animation;
|
||||||
import com.jFxKasse.controller.PrinterController;
|
import javafx.animation.KeyFrame;
|
||||||
import com.jFxKasse.controller.XMLController;
|
import javafx.animation.Timeline;
|
||||||
import com.jFxKasse.controller.DBController;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.scene.Scene;
|
import javafx.stage.Stage;
|
||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.util.Duration;
|
||||||
|
import javafx.scene.Scene;
|
||||||
public class Main extends Application
|
import javafx.scene.layout.AnchorPane;
|
||||||
{
|
|
||||||
// path to config.xml and the database
|
public class Main extends Application {
|
||||||
public static String filepath;
|
// Path to config.xml and the database
|
||||||
|
public static String filepath;
|
||||||
private static String osName = System.getProperty("os.name");
|
|
||||||
|
private static String osName = System.getProperty("os.name");
|
||||||
private static String userHome = System.getProperty("user.home");
|
|
||||||
|
private static String userHome = System.getProperty("user.home");
|
||||||
private MainWindowController mwc;
|
|
||||||
|
private MainWindowController mwc;
|
||||||
private XMLController xmlc = new XMLController(filepath);
|
|
||||||
|
// Initialized in start() after filepath is set by main()
|
||||||
private DBController dbc = new DBController(filepath);
|
private XMLController xmlc;
|
||||||
|
|
||||||
private PrinterController pc = new PrinterController();
|
private DBController dbc;
|
||||||
|
|
||||||
private Stage primaryStage;
|
private PrinterController pc = new PrinterController();
|
||||||
|
|
||||||
@Override
|
private KeyController kc;
|
||||||
public void start(Stage primaryStage)
|
|
||||||
{
|
private Stage primaryStage;
|
||||||
this.primaryStage = primaryStage;
|
|
||||||
System.out.println("\nstarting jFxKasse\n");
|
@Override
|
||||||
mainWindow();
|
public void start(Stage primaryStage) {
|
||||||
}
|
this.primaryStage = primaryStage;
|
||||||
|
// filepath is set by main() before launch(); initialize controllers here
|
||||||
private void mainWindow()
|
xmlc = new XMLController(filepath);
|
||||||
{
|
dbc = new DBController(filepath);
|
||||||
try {
|
System.out.println("\nstarting jFxKasse\n");
|
||||||
FXMLLoader loader = new FXMLLoader(
|
mainWindow();
|
||||||
getClass().getResource("/fxml/MainWindow.fxml"));
|
}
|
||||||
|
|
||||||
AnchorPane pane = loader.load();
|
private void mainWindow() {
|
||||||
primaryStage.setTitle("jFxKasse"); // Title of window
|
try {
|
||||||
|
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/MainWindow.fxml"));
|
||||||
mwc = loader.getController(); // set the mwc as the JavaFx
|
|
||||||
// MainWindowController
|
AnchorPane pane = loader.load();
|
||||||
pc.searchPrinters(); // search for available printers
|
primaryStage.setTitle("jFxKasse"); // Window title
|
||||||
mwc.setMain(this, dbc, xmlc, pc); // set the created instances to the
|
|
||||||
// mwc
|
mwc = loader.getController(); // Set the MainWindowController
|
||||||
|
pc.searchPrinters(); // Search for available printers
|
||||||
firstStart(); // test if this is the first run
|
mwc.setMain(this, dbc, xmlc, pc); // Pass instances to the controller
|
||||||
|
|
||||||
Scene scene = new Scene(pane);
|
firstStart(); // Check if this is the first run
|
||||||
scene.getStylesheets().add(
|
|
||||||
Main.class.getResource("/css/application.css").toExternalForm());
|
Scene scene = new Scene(pane);
|
||||||
primaryStage.setScene(scene);
|
scene.getStylesheets().add(Main.class.getResource("/css/application.css").toExternalForm());
|
||||||
primaryStage.show(); // shows the stage
|
primaryStage.setScene(scene);
|
||||||
|
primaryStage.show(); // Show the stage
|
||||||
Timeline timeline = new Timeline(
|
|
||||||
new KeyFrame(Duration.seconds(1), ev -> {
|
// Attach the KeyController
|
||||||
mwc.updateTimeLabel(); // update time label on UI
|
kc = new KeyController(scene, mwc);
|
||||||
}));
|
|
||||||
timeline.setCycleCount(Animation.INDEFINITE);
|
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1), ev -> {
|
||||||
timeline.play();
|
mwc.updateTimeLabel(); // Update time label on UI
|
||||||
} catch (Exception e) {
|
}));
|
||||||
e.printStackTrace();
|
timeline.setCycleCount(Animation.INDEFINITE);
|
||||||
}
|
timeline.play();
|
||||||
}
|
}
|
||||||
|
catch (Exception e) {
|
||||||
public static void main(String[] args)
|
e.printStackTrace();
|
||||||
{
|
}
|
||||||
if (osName.contains("Windows")) {
|
}
|
||||||
System.out.println("FCK Windows");
|
|
||||||
filepath = userHome + "/Documents/jFxKasse/";
|
public static void main(String[] args) {
|
||||||
} else {
|
if (osName.contains("Windows")) {
|
||||||
filepath = userHome + "/jFxKasse/";
|
System.out.println("FCK Windows");
|
||||||
}
|
filepath = userHome + "/Documents/jFxKasse/";
|
||||||
launch(args);
|
}
|
||||||
}
|
else {
|
||||||
|
filepath = userHome + "/jFxKasse/";
|
||||||
/**
|
}
|
||||||
* Checks if the config.xml is preset.
|
launch(args);
|
||||||
*/
|
}
|
||||||
private void firstStart() throws Exception
|
|
||||||
{
|
/**
|
||||||
if (xmlc.loadSettings()) {
|
* Checks if the config.xml is present and initializes accordingly.
|
||||||
// config.xml found, app starting normal
|
*/
|
||||||
System.out.println("XML found!");
|
private void firstStart() throws Exception {
|
||||||
mwc.initUI(); // Starting the UI elements
|
if (xmlc.loadSettings()) {
|
||||||
mwc.setDBLabel(); // Set databese labels
|
// config.xml found, app starting normally
|
||||||
dbc.setDbname(xmlc.getDatabaseName()); // handover database name
|
System.out.println("XML found!");
|
||||||
dbc.connectDatabase(); // estabishing DB conection
|
mwc.initUI(); // Initialize the UI elements
|
||||||
mwc.fillTablePositionen(); // fill TreeTable 'Positionen'
|
mwc.setDBLabel(); // Set database labels
|
||||||
mwc.fillCategory();
|
dbc.setDbname(xmlc.getDatabaseName()); // Pass database name
|
||||||
mwc.fillPrinterSettings();
|
try {
|
||||||
mwc.fillTableJobs();
|
dbc.connectDatabase(); // Establish DB connection
|
||||||
mwc.loadGridButtons();
|
}
|
||||||
mwc.getSelectedCat(); // Load DB entries in Chois Box
|
catch (Exception e) {
|
||||||
mwc.createNewJob();
|
e.printStackTrace();
|
||||||
} else {
|
showErrorDialog("Datenbankfehler", "Die Datenbank konnte nicht geöffnet werden.",
|
||||||
// config.xml NOT found, first start of app
|
"Datei: " + xmlc.getDatabaseName() + ".db\n\n"
|
||||||
System.out.println("no XML found!");
|
+ "Bitte prüfen Sie, ob die Datei vorhanden und nicht beschädigt ist.\n"
|
||||||
xmlc.initXML(); // set default values
|
+ "Fehlermeldung: " + e.getMessage());
|
||||||
mwc.blockUI(true); // disable UI elements that need DB
|
return;
|
||||||
mwc.blockUnlock();
|
}
|
||||||
File dir = new File(filepath);
|
mwc.fillTablePositionen(); // Fill TreeTable 'Positions'
|
||||||
dir.mkdir(); // Create new Subfolder
|
mwc.fillCategory();
|
||||||
}
|
mwc.fillPrinterSettings();
|
||||||
}
|
mwc.fillTableJobs();
|
||||||
}
|
mwc.loadGridButtons();
|
||||||
|
mwc.getSelectedCat(); // Load DB entries in ChoiceBox
|
||||||
|
mwc.createNewJob();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// config.xml NOT found — first start of app
|
||||||
|
System.out.println("no XML found!");
|
||||||
|
xmlc.initXML(); // Set default values in memory
|
||||||
|
File dir = new File(filepath);
|
||||||
|
dir.mkdir(); // Create config directory
|
||||||
|
try {
|
||||||
|
xmlc.saveSettings(); // Persist defaults immediately so next start is normal
|
||||||
|
System.out.println("Default config.xml written.");
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
showErrorDialog("Konfigurationsfehler", "Die Konfigurationsdatei konnte nicht geschrieben werden.",
|
||||||
|
"Pfad: " + filepath + "config.xml\n\n" + "Bitte prüfen Sie die Schreibrechte.\n"
|
||||||
|
+ "Fehlermeldung: " + e.getMessage());
|
||||||
|
}
|
||||||
|
mwc.blockUI(true); // Disable UI elements that need a DB
|
||||||
|
mwc.blockUnlock(); // Show first-start hint, disable lock button
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Shows a modal error alert dialog on the JavaFX thread. */
|
||||||
|
private void showErrorDialog(String title, String header, String content) {
|
||||||
|
javafx.scene.control.Alert alert = new javafx.scene.control.Alert(javafx.scene.control.Alert.AlertType.ERROR);
|
||||||
|
alert.setTitle(title);
|
||||||
|
alert.setHeaderText(header);
|
||||||
|
alert.setContentText(content);
|
||||||
|
alert.setResizable(true);
|
||||||
|
alert.showAndWait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
package com.jFxKasse.application;
|
package com.jFxKasse.application;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import com.jFxKasse.controller.DBController;
|
import com.jFxKasse.controller.DBController;
|
||||||
import com.jFxKasse.controller.PrinterController;
|
import com.jFxKasse.controller.PrinterController;
|
||||||
import com.jFxKasse.controller.XMLController;
|
import com.jFxKasse.controller.XMLController;
|
||||||
|
|
||||||
import com.jFxKasse.datatypes.PrintDataSimple;
|
import com.jFxKasse.datatypes.PrintDataSimple;
|
||||||
|
import com.jFxKasse.datatypes.PrintDataSplitted;
|
||||||
|
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.scene.control.ButtonType;
|
import javafx.scene.control.ButtonType;
|
||||||
@@ -13,25 +16,20 @@ import javafx.scene.control.Label;
|
|||||||
import javafx.scene.layout.GridPane;
|
import javafx.scene.layout.GridPane;
|
||||||
import javafx.util.Pair;
|
import javafx.util.Pair;
|
||||||
|
|
||||||
public class PrintJob
|
public class PrintJob {
|
||||||
{
|
|
||||||
|
|
||||||
private TimeDate timedate = new TimeDate();
|
private TimeDate timedate = new TimeDate();
|
||||||
|
|
||||||
public void printJob(int jobID, XMLController xmlc, DBController dbc,
|
public void printJob(int jobID, XMLController xmlc, DBController dbc, PrinterController pc) {
|
||||||
PrinterController pc)
|
|
||||||
{
|
|
||||||
|
|
||||||
if ((xmlc.getPrintername().equals("Drucker auswählen")
|
if ((xmlc.getPrintername().equals("Drucker auswählen") || xmlc.getPrintername() == null)) {
|
||||||
|| xmlc.getPrintername() == null)) {
|
// No printer selected
|
||||||
// no printer selected
|
System.out.println("No printer configured!");
|
||||||
System.out.println("Kein Drucker eingestellt!!!");
|
|
||||||
|
|
||||||
// creates a dialog
|
// creates a dialog
|
||||||
Dialog<Pair<String, String>> dialog = new Dialog<>();
|
Dialog<Pair<String, String>> dialog = new Dialog<>();
|
||||||
dialog.setTitle("Kein Drucker");
|
dialog.setTitle("Kein Drucker");
|
||||||
dialog.setHeaderText("Es ist kein Drucker einestellt.\n"
|
dialog.setHeaderText("Es ist kein Drucker einestellt.\n" + "In den Einstellungen einen Drucker auswählen.");
|
||||||
+ "In den Einstellungen einen Drucker auswählen.");
|
|
||||||
|
|
||||||
dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK);
|
dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK);
|
||||||
|
|
||||||
@@ -40,32 +38,48 @@ public class PrintJob
|
|||||||
grid.setVgap(10);
|
grid.setVgap(10);
|
||||||
grid.setPadding(new Insets(20, 150, 10, 10));
|
grid.setPadding(new Insets(20, 150, 10, 10));
|
||||||
|
|
||||||
grid.add(new Label("Tipp:\n"
|
grid.add(
|
||||||
+ "Es kann ein virtueller Drucker installiert werden: \n\n"
|
new Label(
|
||||||
+ "www.cups-pdf.de"), 0, 0);
|
"Tipp:\n" + "Es kann ein virtueller Drucker installiert werden: \n\n" + "www.cups-pdf.de"),
|
||||||
|
0, 0);
|
||||||
|
|
||||||
dialog.getDialogPane().setContent(grid);
|
dialog.getDialogPane().setContent(grid);
|
||||||
dialog.setResizable(true);
|
dialog.setResizable(true);
|
||||||
dialog.showAndWait();
|
dialog.showAndWait();
|
||||||
|
|
||||||
} else {
|
}
|
||||||
// printer selected
|
else {
|
||||||
|
// Printer selected
|
||||||
pc.selectPrinter(xmlc.getPrintername());
|
pc.selectPrinter(xmlc.getPrintername());
|
||||||
|
/* Single bill or split by category */
|
||||||
if (xmlc.getCategorySplitted()) {
|
if (xmlc.getCategorySplitted()) {
|
||||||
// split the bills
|
// Split the bills
|
||||||
|
|
||||||
// TODO
|
PrintDataSplitted pdsplitted = new PrintDataSplitted(xmlc.getLinebreak(), xmlc.getOffsetHeader(),
|
||||||
|
xmlc.getOffsetFooter(), timedate.getSystemTime() + " " + timedate.getSystemDate(),
|
||||||
} else {
|
|
||||||
// one single bills
|
|
||||||
PrintDataSimple pds = new PrintDataSimple(xmlc.getLinebreak(),
|
|
||||||
xmlc.getOffsetHeader(), xmlc.getOffsetFooter(),
|
|
||||||
timedate.getSystemTime() + " " + timedate.getSystemDate(),
|
|
||||||
xmlc.getHeader(), xmlc.getFooter());
|
xmlc.getHeader(), xmlc.getFooter());
|
||||||
|
|
||||||
pds.setData(Integer.toString(jobID), dbc.getTime_Job(jobID),
|
pdsplitted.setData(Integer.toString(jobID), dbc.getTime_Job(jobID), dbc.getQuantity_Job(jobID),
|
||||||
dbc.getQuantity_Job(jobID), dbc.getName_Job(jobID),
|
dbc.getName_Job(jobID), dbc.getValue_Job(jobID), dbc.getCategory_Job(jobID),
|
||||||
dbc.getValue_Job(jobID), dbc.getCategory_Job(jobID),
|
dbc.getJobValue_Job(jobID));
|
||||||
|
|
||||||
|
System.out.println("Printing job ...");
|
||||||
|
|
||||||
|
ArrayList<String> printString = pdsplitted.getPrintStrings();
|
||||||
|
|
||||||
|
for (int i = 0; i < printString.size(); i++) {
|
||||||
|
pc.printString(printString.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Single bill
|
||||||
|
PrintDataSimple pds = new PrintDataSimple(xmlc.getLinebreak(), xmlc.getOffsetHeader(),
|
||||||
|
xmlc.getOffsetFooter(), timedate.getSystemTime() + " " + timedate.getSystemDate(),
|
||||||
|
xmlc.getHeader(), xmlc.getFooter());
|
||||||
|
|
||||||
|
pds.setData(Integer.toString(jobID), dbc.getTime_Job(jobID), dbc.getQuantity_Job(jobID),
|
||||||
|
dbc.getName_Job(jobID), dbc.getValue_Job(jobID), dbc.getCategory_Job(jobID),
|
||||||
dbc.getJobValue_Job(jobID));
|
dbc.getJobValue_Job(jobID));
|
||||||
System.out.println("Printing job ...");
|
System.out.println("Printing job ...");
|
||||||
pc.printString(pds.getPrintString());
|
pc.printString(pds.getPrintString());
|
||||||
|
|||||||
@@ -4,23 +4,18 @@ import java.text.DateFormat;
|
|||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
public class TimeDate
|
public class TimeDate {
|
||||||
{
|
public String getSystemTime() {
|
||||||
|
|
||||||
public String getSystemTime()
|
|
||||||
{
|
|
||||||
DateFormat dateFormat = new SimpleDateFormat("HH:mm");
|
DateFormat dateFormat = new SimpleDateFormat("HH:mm");
|
||||||
Date date = new Date();
|
Date date = new Date();
|
||||||
String time = dateFormat.format(date);
|
String time = dateFormat.format(date);
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSystemDate()
|
public String getSystemDate() {
|
||||||
{
|
|
||||||
DateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");
|
DateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");
|
||||||
Date date = new Date();
|
Date date = new Date();
|
||||||
String dateStr = dateFormat.format(date);
|
String dateStr = dateFormat.format(date);
|
||||||
return dateStr;
|
return dateStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,83 +11,77 @@ import com.jFxKasse.datatypes.tableDataJob;
|
|||||||
import com.jFxKasse.datatypes.tableDataPositionen;
|
import com.jFxKasse.datatypes.tableDataPositionen;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
public class DBController
|
public class DBController {
|
||||||
{
|
|
||||||
private Connection connection;
|
private Connection connection;
|
||||||
|
|
||||||
private String DB_PATH;
|
private String DB_PATH;
|
||||||
|
|
||||||
private String dbname;
|
private String dbname;
|
||||||
|
|
||||||
public void main()
|
public void main() {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
connection = DriverManager
|
connection = DriverManager.getConnection("jdbc:sqlite:" + DB_PATH + dbname + ".db");
|
||||||
.getConnection("jdbc:sqlite:" + DB_PATH + dbname + ".db");
|
}
|
||||||
} catch (SQLException e) {
|
catch (SQLException e) {
|
||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DBController(String path)
|
public DBController(String path) {
|
||||||
{
|
|
||||||
this.DB_PATH = path;
|
this.DB_PATH = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDbname(String dbname)
|
public void setDbname(String dbname) {
|
||||||
{
|
|
||||||
this.dbname = dbname;
|
this.dbname = dbname;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void connectDatabase()
|
public void connectDatabase() { // Connect to database
|
||||||
{ // connect to database
|
|
||||||
System.out.println("Connecting... DB name: " + dbname);
|
System.out.println("Connecting... DB name: " + dbname);
|
||||||
try {
|
try {
|
||||||
if (connection != null)
|
if (connection != null)
|
||||||
return;
|
return;
|
||||||
connection = DriverManager
|
connection = DriverManager.getConnection("jdbc:sqlite:" + DB_PATH + dbname + ".db");
|
||||||
.getConnection("jdbc:sqlite:" + DB_PATH + dbname + ".db");
|
|
||||||
if (!connection.isClosed())
|
if (!connection.isClosed())
|
||||||
System.out.println("DB connection established");
|
System.out.println("DB connection established");
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
Runtime.getRuntime().addShutdownHook(new Thread() {
|
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||||
public void run()
|
public void run() {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
if (!connection.isClosed() && connection != null) {
|
if (!connection.isClosed() && connection != null) {
|
||||||
connection.close();
|
connection.close();
|
||||||
if (connection.isClosed())
|
if (connection.isClosed())
|
||||||
System.out.println();
|
System.out.println();
|
||||||
}
|
}
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean existDB(String pPfad)
|
public boolean existDB(String pPfad) { // Check if the DB exists
|
||||||
{ // does the DB exists?
|
|
||||||
File varTmpDir = new File(pPfad);
|
File varTmpDir = new File(pPfad);
|
||||||
if (!varTmpDir.exists()) {
|
if (!varTmpDir.exists()) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCategoryNameFromPositionen(int pID)
|
public String getCategoryNameFromPositionen(int pID) {
|
||||||
{
|
|
||||||
int catInPos = 0;
|
int catInPos = 0;
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
ResultSet rs = stmt.executeQuery("SELECT posid, cat FROM positionen "
|
ResultSet rs = stmt.executeQuery("SELECT posid, cat FROM positionen " + "WHERE posid = " + pID + ";");
|
||||||
+ "WHERE posid = " + pID + ";");
|
|
||||||
catInPos = rs.getInt("cat");
|
catInPos = rs.getInt("cat");
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
||||||
@@ -97,10 +91,11 @@ public class DBController
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
ResultSet rs = stmt.executeQuery("SELECT catid, catname FROM category "
|
ResultSet rs = stmt
|
||||||
+ "WHERE catid = " + catInPos + ";");
|
.executeQuery("SELECT catid, catname FROM category " + "WHERE catid = " + catInPos + ";");
|
||||||
return rs.getString("catname");
|
return rs.getString("catname");
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return "keine Kategorie";
|
return "keine Kategorie";
|
||||||
@@ -108,34 +103,31 @@ public class DBController
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// table Position section //
|
// Table 'Positionen' section //
|
||||||
public void createTablePositionen()
|
public void createTablePositionen() { // Create table 'positionen'
|
||||||
{ // create table position
|
|
||||||
System.out.println("Creating table Positionen");
|
System.out.println("Creating table Positionen");
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
stmt.executeUpdate("DROP TABLE IF EXISTS positionen;");
|
stmt.executeUpdate("DROP TABLE IF EXISTS positionen;");
|
||||||
stmt.executeUpdate(
|
stmt.executeUpdate("CREATE TABLE positionen (posid, name, value, cat, color);");
|
||||||
"CREATE TABLE positionen (posid, name, value, cat, color);");
|
}
|
||||||
} catch (SQLException e) {
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
// create 25 demo/default data entries
|
// Create 25 demo/default data entries
|
||||||
for (int i = 0; i < 25; i++) {
|
for (int i = 0; i < 25; i++) {
|
||||||
fillPositionen_Positionen(i + 1, "Noch frei", (float) 0.00, 6,
|
fillPositionen_Positionen(i + 1, "Noch frei", (float) 0.00, 6, "#ad0000");
|
||||||
"#ad0000");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fillPositionen_Positionen(int pID, String pName, float pValue,
|
public void fillPositionen_Positionen(int pID, String pName, float pValue, int pCat, String pColor) { // Create new
|
||||||
int pCat, String pColor)
|
// entry in
|
||||||
{ // create new data in table
|
// table
|
||||||
System.out.println("Creating new positionen entry");
|
System.out.println("Creating new positionen entry");
|
||||||
try {
|
try {
|
||||||
PreparedStatement ps = connection.prepareStatement(
|
PreparedStatement ps = connection.prepareStatement("INSERT INTO positionen VALUES (?, ?, ?, ?, ?);");
|
||||||
"INSERT INTO positionen VALUES (?, ?, ?, ?, ?);");
|
|
||||||
ps.setInt(1, pID); // primary
|
ps.setInt(1, pID); // primary
|
||||||
ps.setString(2, pName);
|
ps.setString(2, pName);
|
||||||
ps.setFloat(3, pValue);
|
ps.setFloat(3, pValue);
|
||||||
@@ -146,144 +138,134 @@ public class DBController
|
|||||||
connection.setAutoCommit(false);
|
connection.setAutoCommit(false);
|
||||||
ps.executeBatch(); // SQL execution
|
ps.executeBatch(); // SQL execution
|
||||||
connection.setAutoCommit(true);
|
connection.setAutoCommit(true);
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName_Positionen(int pID)
|
public String getName_Positionen(int pID) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
ResultSet rs = stmt.executeQuery(
|
ResultSet rs = stmt.executeQuery("SELECT posid, name FROM positionen WHERE posid = " + pID + ";");
|
||||||
"SELECT posid, name FROM positionen WHERE posid = " + pID + ";");
|
|
||||||
return rs.getString("name");
|
return rs.getString("name");
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return "Error 404";
|
return "Error 404";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getValue_Positionen(int pID)
|
public String getValue_Positionen(int pID) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
ResultSet rs = stmt.executeQuery(
|
ResultSet rs = stmt.executeQuery("SELECT posid, value FROM positionen WHERE posid = " + pID + ";");
|
||||||
"SELECT posid, value FROM positionen WHERE posid = " + pID
|
|
||||||
+ ";");
|
|
||||||
return rs.getString("value");
|
return rs.getString("value");
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return "Error 404";
|
return "Error 404";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCat_Positionen(int pID)
|
public int getCat_Positionen(int pID) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
ResultSet rs = stmt.executeQuery(
|
ResultSet rs = stmt.executeQuery("SELECT catid, cat FROM positionen WHERE catid = " + pID + ";");
|
||||||
"SELECT catid, cat FROM positionen WHERE catid = " + pID + ";");
|
|
||||||
System.out.println("getCarTet: " + rs.getInt("cat"));
|
System.out.println("getCarTet: " + rs.getInt("cat"));
|
||||||
return rs.getInt("cat");
|
return rs.getInt("cat");
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getColor_Positionen(int pID)
|
public String getColor_Positionen(int pID) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
ResultSet rs = stmt.executeQuery(
|
ResultSet rs = stmt.executeQuery("SELECT posid, color FROM positionen WHERE posid = " + pID + ";");
|
||||||
"SELECT posid, color FROM positionen WHERE posid = " + pID
|
|
||||||
+ ";");
|
|
||||||
return rs.getString("color");
|
return rs.getString("color");
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return "Error 404";
|
return "Error 404";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName_Positionen(int pID, String pName)
|
public void setName_Positionen(int pID, String pName) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
stmt.executeUpdate("UPDATE positionen SET name = '" + pName
|
stmt.executeUpdate("UPDATE positionen SET name = '" + pName + "'WHERE posid =" + pID + ";");
|
||||||
+ "'WHERE posid =" + pID + ";");
|
}
|
||||||
} catch (SQLException e) {
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setValue_Positionen(int pID, String pValue)
|
public void setValue_Positionen(int pID, String pValue) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
stmt.executeUpdate("UPDATE positionen SET value = '" + pValue
|
stmt.executeUpdate("UPDATE positionen SET value = '" + pValue + "'WHERE posid =" + pID + ";");
|
||||||
+ "'WHERE posid =" + pID + ";");
|
}
|
||||||
} catch (SQLException e) {
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCat_Positionen(int pID, int pCat)
|
public void setCat_Positionen(int pID, int pCat) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
stmt.executeUpdate("UPDATE positionen SET cat = '" + pCat
|
stmt.executeUpdate("UPDATE positionen SET cat = '" + pCat + "'WHERE posid =" + pID + ";");
|
||||||
+ "'WHERE posid =" + pID + ";");
|
}
|
||||||
} catch (SQLException e) {
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setColor_Positionen(int pID, String pColor)
|
public void setColor_Positionen(int pID, String pColor) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
stmt.executeUpdate("UPDATE positionen SET color = '" + pColor
|
stmt.executeUpdate("UPDATE positionen SET color = '" + pColor + "'WHERE posid =" + pID + ";");
|
||||||
+ "'WHERE posid =" + pID + ";");
|
}
|
||||||
} catch (SQLException e) {
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<tableDataPositionen> ladeTabellePositionen()
|
public ArrayList<tableDataPositionen> ladeTabellePositionen() {
|
||||||
{
|
|
||||||
ArrayList<tableDataPositionen> daten = new ArrayList<>();
|
ArrayList<tableDataPositionen> daten = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
ResultSet rs = stmt.executeQuery("SELECT * FROM positionen;");
|
ResultSet rs = stmt.executeQuery("SELECT * FROM positionen;");
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
try {
|
try {
|
||||||
daten.add(new tableDataPositionen(rs.getInt("posid"),
|
daten.add(new tableDataPositionen(rs.getInt("posid"), rs.getString("name"), rs.getString("value"),
|
||||||
rs.getString("name"), rs.getString("value"),
|
|
||||||
rs.getString("cat"), rs.getString("color")));
|
rs.getString("cat"), rs.getString("color")));
|
||||||
} catch (Exception e) {
|
}
|
||||||
|
catch (Exception e) {
|
||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return daten;
|
return daten;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ausgebenSysoPositionen()
|
public void ausgebenSysoPositionen() {
|
||||||
{
|
|
||||||
System.out.println("Print positionen");
|
System.out.println("Print positionen");
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
@@ -296,21 +278,22 @@ public class DBController
|
|||||||
System.out.println(" ");
|
System.out.println(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// table Category section //
|
// Table 'Category' section //
|
||||||
public void createTableCategory()
|
public void createTableCategory() { // Create table 'category'
|
||||||
{ // create table position
|
System.out.println("Creating table Category");
|
||||||
System.out.println("Erstelle Tabelle Kategorie");
|
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
stmt.executeUpdate("DROP TABLE IF EXISTS category;");
|
stmt.executeUpdate("DROP TABLE IF EXISTS category;");
|
||||||
stmt.executeUpdate("CREATE TABLE category (catid, catname);");
|
stmt.executeUpdate("CREATE TABLE category (catid, catname);");
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -323,76 +306,71 @@ public class DBController
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName_Category(int pID, String pName)
|
public void setName_Category(int pID, String pName) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
stmt.executeUpdate("UPDATE category SET catname = '" + pName
|
stmt.executeUpdate("UPDATE category SET catname = '" + pName + "'WHERE catid =" + pID + ";");
|
||||||
+ "'WHERE catid =" + pID + ";");
|
}
|
||||||
} catch (SQLException e) {
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fillCategory_Category(int pID, String pName)
|
public void fillCategory_Category(int pID, String pName) {
|
||||||
{
|
|
||||||
|
|
||||||
System.out.println("Erstelle neuen Kategorie Eintrag");
|
System.out.println("Creating new category entry");
|
||||||
try {
|
try {
|
||||||
PreparedStatement ps = connection
|
PreparedStatement ps = connection.prepareStatement("INSERT INTO category VALUES (?, ?);");
|
||||||
.prepareStatement("INSERT INTO category VALUES (?, ?);");
|
|
||||||
ps.setInt(1, pID); // primary
|
ps.setInt(1, pID); // primary
|
||||||
ps.setString(2, pName);
|
ps.setString(2, pName);
|
||||||
ps.addBatch();
|
ps.addBatch();
|
||||||
connection.setAutoCommit(false);
|
connection.setAutoCommit(false);
|
||||||
ps.executeBatch(); // SQL execution
|
ps.executeBatch(); // SQL execution
|
||||||
connection.setAutoCommit(true);
|
connection.setAutoCommit(true);
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName_Category(int pID)
|
public String getName_Category(int pID) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
ResultSet rs = stmt.executeQuery(
|
ResultSet rs = stmt.executeQuery("SELECT catid, catname FROM category WHERE catid = " + pID + ";");
|
||||||
"SELECT catid, catname FROM category WHERE catid = " + pID
|
|
||||||
+ ";");
|
|
||||||
return rs.getString("catname");
|
return rs.getString("catname");
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return "Error 404";
|
return "Error 404";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// table Jobs section //
|
// Table 'Jobs' section //
|
||||||
public void erstelleTabelleJobs()
|
public void erstelleTabelleJobs() { // Create table 'jobs'
|
||||||
{ // create table jobs
|
|
||||||
System.out.println("Creating table Jobs");
|
System.out.println("Creating table Jobs");
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
stmt.executeUpdate("DROP TABLE IF EXISTS jobs;");
|
stmt.executeUpdate("DROP TABLE IF EXISTS jobs;");
|
||||||
stmt.executeUpdate(
|
stmt.executeUpdate(
|
||||||
"CREATE TABLE jobs (jobid, time, positionen_quantity, positionen_name, positionen_value, positionen_cat, state, jobvalue);");
|
"CREATE TABLE jobs (jobid, time, positionen_quantity, positionen_name, positionen_value, positionen_cat, state, jobvalue);");
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getLatestJobNumber_Job()
|
public int getLatestJobNumber_Job() {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
ResultSet rs = stmt.executeQuery(
|
ResultSet rs = stmt.executeQuery("SELECT jobid from jobs ORDER BY jobid DESC LIMIT 1;");
|
||||||
"SELECT jobid from jobs ORDER BY jobid DESC LIMIT 1;");
|
|
||||||
return rs.getInt("jobid");
|
return rs.getInt("jobid");
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
// System.err.println("Couldn't handle DB-Query");
|
// System.err.println("Couldn't handle DB-Query");
|
||||||
// e.printStackTrace();
|
// e.printStackTrace();
|
||||||
|
|
||||||
@@ -400,152 +378,138 @@ public class DBController
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTime_Job(int pID)
|
public String getTime_Job(int pID) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
ResultSet rs = stmt.executeQuery(
|
ResultSet rs = stmt.executeQuery("SELECT jobid, time FROM jobs WHERE jobid = " + pID + ";");
|
||||||
"SELECT jobid, time FROM jobs WHERE jobid = " + pID + ";");
|
|
||||||
return rs.getString("time");
|
return rs.getString("time");
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return "404";
|
return "404";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getQuantity_Job(int pID)
|
public String getQuantity_Job(int pID) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
ResultSet rs = stmt.executeQuery(
|
ResultSet rs = stmt.executeQuery("SELECT jobid, positionen_quantity FROM jobs WHERE jobid = " + pID + ";");
|
||||||
"SELECT jobid, positionen_quantity FROM jobs WHERE jobid = "
|
|
||||||
+ pID + ";");
|
|
||||||
return rs.getString("positionen_quantity");
|
return rs.getString("positionen_quantity");
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return "404";
|
return "404";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName_Job(int pID)
|
public String getName_Job(int pID) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
ResultSet rs = stmt.executeQuery(
|
ResultSet rs = stmt.executeQuery("SELECT jobid, positionen_name FROM jobs WHERE jobid = " + pID + ";");
|
||||||
"SELECT jobid, positionen_name FROM jobs WHERE jobid = " + pID
|
|
||||||
+ ";");
|
|
||||||
return rs.getString("positionen_name");
|
return rs.getString("positionen_name");
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return "404";
|
return "404";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getValue_Job(int pID)
|
public String getValue_Job(int pID) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
ResultSet rs = stmt.executeQuery(
|
ResultSet rs = stmt.executeQuery("SELECT jobid, positionen_value FROM jobs WHERE jobid = " + pID + ";");
|
||||||
"SELECT jobid, positionen_value FROM jobs WHERE jobid = " + pID
|
|
||||||
+ ";");
|
|
||||||
return rs.getString("positionen_value");
|
return rs.getString("positionen_value");
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return "404";
|
return "404";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCategory_Job(int pID)
|
public String getCategory_Job(int pID) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
ResultSet rs = stmt.executeQuery(
|
ResultSet rs = stmt.executeQuery("SELECT jobid, positionen_cat FROM jobs WHERE jobid = " + pID + ";");
|
||||||
"SELECT jobid, positionen_cat FROM jobs WHERE jobid = " + pID
|
|
||||||
+ ";");
|
|
||||||
return rs.getString("positionen_cat");
|
return rs.getString("positionen_cat");
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return "404";
|
return "404";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getState_Job(int pID)
|
public String getState_Job(int pID) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
ResultSet rs = stmt.executeQuery(
|
ResultSet rs = stmt.executeQuery("SELECT jobid, state FROM jobs WHERE jobid = " + pID + ";");
|
||||||
"SELECT jobid, state FROM jobs WHERE jobid = " + pID + ";");
|
|
||||||
return rs.getString("state");
|
return rs.getString("state");
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return "404";
|
return "404";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getJobValue_Job(int pID)
|
public String getJobValue_Job(int pID) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
ResultSet rs = stmt.executeQuery(
|
ResultSet rs = stmt.executeQuery("SELECT jobid, jobvalue FROM jobs WHERE jobid = " + pID + ";");
|
||||||
"SELECT jobid, jobvalue FROM jobs WHERE jobid = " + pID + ";");
|
|
||||||
return rs.getString("jobvalue");
|
return rs.getString("jobvalue");
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return "404";
|
return "404";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAllJobValue_Job()
|
public String getAllJobValue_Job() {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
ResultSet rs = stmt.executeQuery(
|
ResultSet rs = stmt
|
||||||
"SELECT state, jobvalue, SUM(jobvalue) AS ALLVALUE FROM jobs WHERE state = "
|
.executeQuery("SELECT state, jobvalue, SUM(jobvalue) AS ALLVALUE FROM jobs WHERE state = " + '"'
|
||||||
+ '"' + "verbucht" + '"' + ";");
|
|
||||||
return rs.getString("ALLVALUE");
|
|
||||||
} catch (SQLException e) {
|
|
||||||
System.err.println("Couldn't handle DB-Query");
|
|
||||||
e.printStackTrace();
|
|
||||||
return "0";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getJobCount()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
Statement stmt = connection.createStatement();
|
|
||||||
ResultSet rs = stmt.executeQuery(
|
|
||||||
"SELECT count(*) AS JOBCOUNT FROM jobs WHERE state = " + '"'
|
|
||||||
+ "verbucht" + '"' + ";");
|
+ "verbucht" + '"' + ";");
|
||||||
return rs.getString("JOBCOUNT");
|
return rs.getString("ALLVALUE");
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return "0";
|
return "0";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStatus_Jobs(int pID, String pStatus)
|
public String getJobCount() {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
stmt.executeUpdate("UPDATE jobs SET state = '" + pStatus
|
ResultSet rs = stmt.executeQuery(
|
||||||
+ "'WHERE jobid =" + pID + ";");
|
"SELECT count(*) AS JOBCOUNT FROM jobs WHERE state = " + '"' + "verbucht" + '"' + ";");
|
||||||
} catch (SQLException e) {
|
return rs.getString("JOBCOUNT");
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
|
System.err.println("Couldn't handle DB-Query");
|
||||||
|
e.printStackTrace();
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus_Jobs(int pID, String pStatus) {
|
||||||
|
try {
|
||||||
|
Statement stmt = connection.createStatement();
|
||||||
|
stmt.executeUpdate("UPDATE jobs SET state = '" + pStatus + "'WHERE jobid =" + pID + ";");
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<tableDataJob> loadTableJobs_Job()
|
public ArrayList<tableDataJob> loadTableJobs_Job() {
|
||||||
{
|
|
||||||
|
|
||||||
ArrayList<tableDataJob> tmp = new ArrayList<tableDataJob>();
|
ArrayList<tableDataJob> tmp = new ArrayList<tableDataJob>();
|
||||||
try {
|
try {
|
||||||
@@ -557,31 +521,29 @@ public class DBController
|
|||||||
|
|
||||||
String tablePosition = rs.getString("positionen_name");
|
String tablePosition = rs.getString("positionen_name");
|
||||||
|
|
||||||
tableDataJob data = new tableDataJob(rs.getInt("jobid"),
|
tableDataJob data = new tableDataJob(rs.getInt("jobid"), rs.getString("time"), tablePosition,
|
||||||
rs.getString("time"), tablePosition, rs.getString("state"),
|
rs.getString("state"), rs.getString("jobvalue"));
|
||||||
rs.getString("jobvalue"));
|
|
||||||
|
|
||||||
tmp.add(data);
|
tmp.add(data);
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fillJobs_Jobs(int pID, String pTime, String pPositionen_quantity,
|
public void fillJobs_Jobs(int pID, String pTime, String pPositionen_quantity, String pPositionen_name,
|
||||||
String pPositionen_name, String pPositionen_value,
|
String pPositionen_value, String pPositionen_cat, String pState, String pJobvalue) {
|
||||||
String pPositionen_cat, String pState, String pJobvalue)
|
System.out.println("Creating new job entry");
|
||||||
{
|
|
||||||
System.out.println("Create new Job Entry");
|
|
||||||
try {
|
try {
|
||||||
PreparedStatement ps = connection.prepareStatement(
|
PreparedStatement ps = connection.prepareStatement("INSERT INTO jobs VALUES (?, ?, ?, ?, ?, ?, ?, ?);");
|
||||||
"INSERT INTO jobs VALUES (?, ?, ?, ?, ?, ?, ?, ?);");
|
|
||||||
ps.setInt(1, pID); // primary
|
ps.setInt(1, pID); // primary
|
||||||
ps.setString(2, pTime);
|
ps.setString(2, pTime);
|
||||||
ps.setString(3, pPositionen_quantity);
|
ps.setString(3, pPositionen_quantity);
|
||||||
@@ -594,7 +556,8 @@ public class DBController
|
|||||||
connection.setAutoCommit(false);
|
connection.setAutoCommit(false);
|
||||||
ps.executeBatch(); // SQL execution
|
ps.executeBatch(); // SQL execution
|
||||||
connection.setAutoCommit(true);
|
connection.setAutoCommit(true);
|
||||||
} catch (SQLException e) {
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
System.err.println("Couldn't handle DB-Query");
|
System.err.println("Couldn't handle DB-Query");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,212 @@
|
|||||||
|
package com.jFxKasse.controller;
|
||||||
|
|
||||||
|
import javafx.event.EventHandler;
|
||||||
|
import javafx.scene.Scene;
|
||||||
|
import javafx.scene.input.KeyCode;
|
||||||
|
import javafx.scene.input.KeyEvent;
|
||||||
|
|
||||||
|
public class KeyController {
|
||||||
|
private MainWindowController mwc;
|
||||||
|
|
||||||
|
public KeyController(Scene scene, MainWindowController mwc) {
|
||||||
|
this.mwc = mwc;
|
||||||
|
|
||||||
|
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
|
||||||
|
@Override
|
||||||
|
public void handle(KeyEvent keyEvent) {
|
||||||
|
switch (mwc.getActiveTab()) {
|
||||||
|
case 0:
|
||||||
|
handleTabNewJob(keyEvent);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
handleTabJobs(keyEvent);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
handleTabPosEdit(keyEvent);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
handleTabSettings(keyEvent);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleTabNewJob(KeyEvent key) {
|
||||||
|
if ((key.getCode() == KeyCode.ENTER) && (!mwc.btnPrintBill.isDisabled())) {
|
||||||
|
mwc.btnPrintBillAction(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((key.getCode() == KeyCode.ESCAPE) && (!mwc.btnLock.isDisabled())) {
|
||||||
|
mwc.btnLockAction(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((key.getCode() == KeyCode.DELETE) && (!mwc.btnDeleteSelectedPosition.isDisabled())) {
|
||||||
|
mwc.btnDeleteSelectedPositionAction(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
handelGridButtons(key);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleTabJobs(KeyEvent key) {
|
||||||
|
if ((key.getCode() == KeyCode.ENTER) && (!mwc.btnReprintJob.isDisabled())) {
|
||||||
|
mwc.btnReprintJobAction(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((key.getCode() == KeyCode.DELETE) && (!mwc.btnCancelJob.isDisabled())) {
|
||||||
|
mwc.btnCancelJobAction(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((key.getCode() == KeyCode.S) && (!mwc.btnCalcStats.isDisabled())) {
|
||||||
|
mwc.btnCalcStatsAction(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleTabPosEdit(KeyEvent key) {
|
||||||
|
if ((key.getCode() == KeyCode.ENTER) && (!mwc.btnSaveEntry.isDisabled())) {
|
||||||
|
mwc.btnSaveEntryAction(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((key.getCode() == KeyCode.DELETE) && (!mwc.btnClearEntry.isDisabled())) {
|
||||||
|
mwc.btnClearEntryAction(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleTabSettings(KeyEvent key) {
|
||||||
|
if ((key.getCode() == KeyCode.ENTER) && (!mwc.btnSavePrinter.isDisabled())) {
|
||||||
|
mwc.btnSavePrinterAction(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((key.getCode() == KeyCode.ENTER) && (!mwc.btnSaveCat.isDisabled())) {
|
||||||
|
mwc.btnSaveCatAction(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((key.getCode() == KeyCode.ENTER) && (!mwc.btnCreateNewDatabase.isDisabled())) {
|
||||||
|
try {
|
||||||
|
mwc.btnCreateNewDatabaseAction(null);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handelGridButtons(KeyEvent key) {
|
||||||
|
|
||||||
|
switch (key.getCode()) {
|
||||||
|
case Q:
|
||||||
|
mwc.gridButton01Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case W:
|
||||||
|
mwc.gridButton02Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case E:
|
||||||
|
mwc.gridButton03Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case R:
|
||||||
|
mwc.gridButton04Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T:
|
||||||
|
mwc.gridButton05Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Z:
|
||||||
|
mwc.gridButton06Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case U:
|
||||||
|
mwc.gridButton07Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case I:
|
||||||
|
mwc.gridButton08Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case O:
|
||||||
|
mwc.gridButton09Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case P:
|
||||||
|
mwc.gridButton10Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case A:
|
||||||
|
mwc.gridButton11Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case S:
|
||||||
|
mwc.gridButton12Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case D:
|
||||||
|
mwc.gridButton13Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case F:
|
||||||
|
mwc.gridButton14Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case G:
|
||||||
|
mwc.gridButton15Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case H:
|
||||||
|
mwc.gridButton16Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case J:
|
||||||
|
mwc.gridButton17Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case K:
|
||||||
|
mwc.gridButton18Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case L:
|
||||||
|
mwc.gridButton19Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Y:
|
||||||
|
mwc.gridButton20Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case X:
|
||||||
|
mwc.gridButton21Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case C:
|
||||||
|
mwc.gridButton22Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case V:
|
||||||
|
mwc.gridButton23Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B:
|
||||||
|
mwc.gridButton24Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case N:
|
||||||
|
mwc.gridButton25Action(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* some parts are from http://www.mets-blog.com/java-pos-thermal-printer-example/
|
* Some parts are from http://www.mets-blog.com/java-pos-thermal-printer-example/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.jFxKasse.controller;
|
package com.jFxKasse.controller;
|
||||||
@@ -21,26 +21,23 @@ import javax.print.SimpleDoc;
|
|||||||
import javax.print.attribute.HashPrintRequestAttributeSet;
|
import javax.print.attribute.HashPrintRequestAttributeSet;
|
||||||
import javax.print.attribute.PrintRequestAttributeSet;
|
import javax.print.attribute.PrintRequestAttributeSet;
|
||||||
|
|
||||||
public class PrinterController implements Printable
|
public class PrinterController implements Printable {
|
||||||
{
|
// All available printers on this system
|
||||||
// All available Printers on this system
|
|
||||||
private PrintService[] printService;
|
private PrintService[] printService;
|
||||||
|
|
||||||
// selected printer
|
// Selected printer
|
||||||
private PrintService selectedPrinter;
|
private PrintService selectedPrinter;
|
||||||
|
|
||||||
private DocFlavor flavor;
|
private DocFlavor flavor;
|
||||||
|
|
||||||
public PrinterController()
|
public PrinterController() {
|
||||||
{
|
|
||||||
flavor = DocFlavor.BYTE_ARRAY.AUTOSENSE;
|
flavor = DocFlavor.BYTE_ARRAY.AUTOSENSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return A String array with all available printers
|
* @return A String array with all available printers
|
||||||
*/
|
*/
|
||||||
public String[] getAvailablePrinters()
|
public String[] getAvailablePrinters() {
|
||||||
{
|
|
||||||
int printerSize = PrinterJob.lookupPrintServices().length;
|
int printerSize = PrinterJob.lookupPrintServices().length;
|
||||||
String printers[] = new String[printerSize];
|
String printers[] = new String[printerSize];
|
||||||
|
|
||||||
@@ -51,10 +48,9 @@ public class PrinterController implements Printable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* searchs connected printers on the system
|
* Searches for connected printers on the system
|
||||||
*/
|
*/
|
||||||
public void searchPrinters()
|
public void searchPrinters() {
|
||||||
{
|
|
||||||
PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
|
PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
|
||||||
this.printService = PrintServiceLookup.lookupPrintServices(flavor, pras);
|
this.printService = PrintServiceLookup.lookupPrintServices(flavor, pras);
|
||||||
String printers[] = getAvailablePrinters();
|
String printers[] = getAvailablePrinters();
|
||||||
@@ -67,11 +63,11 @@ public class PrinterController implements Printable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects the printer via its name
|
* Selects the printer by its name
|
||||||
|
*
|
||||||
* @param printerName
|
* @param printerName
|
||||||
*/
|
*/
|
||||||
public void selectPrinter(String printerName)
|
public void selectPrinter(String printerName) {
|
||||||
{
|
|
||||||
String printers[] = getAvailablePrinters();
|
String printers[] = getAvailablePrinters();
|
||||||
|
|
||||||
for (int i = 0; i < printers.length; i++) {
|
for (int i = 0; i < printers.length; i++) {
|
||||||
@@ -83,13 +79,12 @@ public class PrinterController implements Printable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Prints a string to the selected printer
|
||||||
*
|
*
|
||||||
* @param input data as String
|
* @param text data as String
|
||||||
*/
|
*/
|
||||||
public void printString(String text)
|
public void printString(String text) {
|
||||||
{
|
|
||||||
PrintService service = selectedPrinter;
|
PrintService service = selectedPrinter;
|
||||||
DocPrintJob job = service.createPrintJob();
|
DocPrintJob job = service.createPrintJob();
|
||||||
|
|
||||||
@@ -98,21 +93,21 @@ public class PrinterController implements Printable
|
|||||||
bytes = text.getBytes(StandardCharsets.UTF_8);
|
bytes = text.getBytes(StandardCharsets.UTF_8);
|
||||||
Doc doc = new SimpleDoc(bytes, flavor, null);
|
Doc doc = new SimpleDoc(bytes, flavor, null);
|
||||||
job.print(doc, null);
|
job.print(doc, null);
|
||||||
} catch (Exception e) {
|
}
|
||||||
|
catch (Exception e) {
|
||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int print(Graphics g, PageFormat pf, int page) throws PrinterException
|
public int print(Graphics g, PageFormat pf, int page) throws PrinterException {
|
||||||
{
|
|
||||||
if (page > 0) { /* We have only one page, and 'page' is zero-based */
|
if (page > 0) { /* We have only one page, and 'page' is zero-based */
|
||||||
return NO_SUCH_PAGE;
|
return NO_SUCH_PAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* User (0,0) is typically outside the imageable area, so we must
|
* User (0,0) is typically outside the imageable area, so we must translate by
|
||||||
* translate by the X and Y values in the PageFormat to avoid clipping
|
* the X and Y values in the PageFormat to avoid clipping
|
||||||
*/
|
*/
|
||||||
Graphics2D g2d = (Graphics2D) g;
|
Graphics2D g2d = (Graphics2D) g;
|
||||||
g2d.translate(pf.getImageableX(), pf.getImageableY());
|
g2d.translate(pf.getImageableX(), pf.getImageableY());
|
||||||
@@ -120,21 +115,20 @@ public class PrinterController implements Printable
|
|||||||
return PAGE_EXISTS;
|
return PAGE_EXISTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void printBytes(byte[] bytes)
|
public void printBytes(byte[] bytes) {
|
||||||
{
|
|
||||||
PrintService service = selectedPrinter;
|
PrintService service = selectedPrinter;
|
||||||
DocPrintJob job = service.createPrintJob();
|
DocPrintJob job = service.createPrintJob();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Doc doc = new SimpleDoc(bytes, flavor, null);
|
Doc doc = new SimpleDoc(bytes, flavor, null);
|
||||||
job.print(doc, null);
|
job.print(doc, null);
|
||||||
} catch (Exception e) {
|
}
|
||||||
|
catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cutPaper()
|
public void cutPaper() {
|
||||||
{
|
|
||||||
byte[] cutP = new byte[] { 0x1d, 'V', 1 };
|
byte[] cutP = new byte[] { 0x1d, 'V', 1 };
|
||||||
printBytes(cutP);
|
printBytes(cutP);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ import java.io.InputStream;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
public class XMLController
|
public class XMLController {
|
||||||
{
|
|
||||||
|
|
||||||
private String databaseName = null;
|
private String databaseName = null;
|
||||||
|
|
||||||
private String printername = null;
|
private String printername = null;
|
||||||
@@ -26,18 +24,18 @@ public class XMLController
|
|||||||
|
|
||||||
private boolean categorySplitted;
|
private boolean categorySplitted;
|
||||||
|
|
||||||
|
private boolean autoPrintBill;
|
||||||
|
|
||||||
private String filePath = null;
|
private String filePath = null;
|
||||||
|
|
||||||
private Properties props = null;
|
private Properties props = null;
|
||||||
|
|
||||||
public XMLController(String filePath)
|
public XMLController(String filePath) {
|
||||||
{
|
|
||||||
this.filePath = filePath + "config.xml";
|
this.filePath = filePath + "config.xml";
|
||||||
props = new Properties();
|
props = new Properties();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveSettings() throws Exception
|
public void saveSettings() throws Exception { // Save settings to config.xml
|
||||||
{ // Save settings to config.xml
|
|
||||||
|
|
||||||
System.out.println("Saving XML");
|
System.out.println("Saving XML");
|
||||||
|
|
||||||
@@ -51,10 +49,20 @@ public class XMLController
|
|||||||
|
|
||||||
if (this.categorySplitted) {
|
if (this.categorySplitted) {
|
||||||
categorySplitted = "true";
|
categorySplitted = "true";
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
categorySplitted = "false";
|
categorySplitted = "false";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String autoPrintBill = null;
|
||||||
|
|
||||||
|
if (this.autoPrintBill) {
|
||||||
|
autoPrintBill = "true";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
autoPrintBill = "false";
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
props.setProperty("databasename", this.databaseName);
|
props.setProperty("databasename", this.databaseName);
|
||||||
props.setProperty("printername", this.printername);
|
props.setProperty("printername", this.printername);
|
||||||
@@ -64,16 +72,17 @@ public class XMLController
|
|||||||
props.setProperty("header", this.header);
|
props.setProperty("header", this.header);
|
||||||
props.setProperty("footer", this.footer);
|
props.setProperty("footer", this.footer);
|
||||||
props.setProperty("categorySplitted", categorySplitted);
|
props.setProperty("categorySplitted", categorySplitted);
|
||||||
|
props.setProperty("autoPrintBill", autoPrintBill);
|
||||||
|
|
||||||
outputStream = new FileOutputStream(filePath);
|
outputStream = new FileOutputStream(filePath);
|
||||||
props.storeToXML(outputStream, "jFxKasse settings");
|
props.storeToXML(outputStream, "jFxKasse settings");
|
||||||
outputStream.close();
|
outputStream.close();
|
||||||
} catch (IOException e) {
|
}
|
||||||
|
catch (IOException e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean loadSettings() throws Exception
|
public boolean loadSettings() throws Exception { // Read settings from config.xml
|
||||||
{ // reads the settings from config.xml
|
|
||||||
InputStream inputStream;
|
InputStream inputStream;
|
||||||
try {
|
try {
|
||||||
inputStream = new FileInputStream(filePath);
|
inputStream = new FileInputStream(filePath);
|
||||||
@@ -83,21 +92,22 @@ public class XMLController
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
this.linebreak = Integer.valueOf(props.getProperty("linebreak"));
|
this.linebreak = Integer.valueOf(props.getProperty("linebreak"));
|
||||||
} catch (Exception e) {
|
}
|
||||||
|
catch (Exception e) {
|
||||||
this.linebreak = 28;
|
this.linebreak = 28;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.offsetHeader = Integer
|
this.offsetHeader = Integer.valueOf(props.getProperty("offsetHeader"));
|
||||||
.valueOf(props.getProperty("offsetHeader"));
|
}
|
||||||
} catch (Exception e) {
|
catch (Exception e) {
|
||||||
this.offsetHeader = 1;
|
this.offsetHeader = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.offsetFooter = Integer
|
this.offsetFooter = Integer.valueOf(props.getProperty("offsetFooter"));
|
||||||
.valueOf(props.getProperty("offsetFooter"));
|
}
|
||||||
} catch (Exception e) {
|
catch (Exception e) {
|
||||||
this.offsetFooter = 2;
|
this.offsetFooter = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,23 +117,37 @@ public class XMLController
|
|||||||
try {
|
try {
|
||||||
if (props.getProperty("categorySplitted").equals("true")) {
|
if (props.getProperty("categorySplitted").equals("true")) {
|
||||||
this.categorySplitted = true;
|
this.categorySplitted = true;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
this.categorySplitted = false;
|
this.categorySplitted = false;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
}
|
||||||
|
catch (Exception e) {
|
||||||
this.categorySplitted = false;
|
this.categorySplitted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (props.getProperty("autoPrintBill").equals("true")) {
|
||||||
|
this.autoPrintBill = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.autoPrintBill = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
this.autoPrintBill = false;
|
||||||
|
}
|
||||||
|
|
||||||
inputStream.close();
|
inputStream.close();
|
||||||
return true;
|
return true;
|
||||||
} catch (IOException e) {
|
}
|
||||||
|
catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initXML()
|
public void initXML() {
|
||||||
{
|
|
||||||
this.printername = "Drucker auswählen";
|
this.printername = "Drucker auswählen";
|
||||||
|
|
||||||
this.offsetHeader = 1;
|
this.offsetHeader = 1;
|
||||||
@@ -133,88 +157,82 @@ public class XMLController
|
|||||||
|
|
||||||
this.categorySplitted = false;
|
this.categorySplitted = false;
|
||||||
|
|
||||||
|
this.autoPrintBill = false;
|
||||||
|
|
||||||
this.header = "XYZ GmbH";
|
this.header = "XYZ GmbH";
|
||||||
this.footer = "Vielen Dank für den Einkauf";
|
this.footer = "Vielen Dank für den Einkauf";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDatabaseName()
|
public String getDatabaseName() {
|
||||||
{
|
|
||||||
return databaseName;
|
return databaseName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDatabaseName(String databaseName)
|
public void setDatabaseName(String databaseName) {
|
||||||
{
|
|
||||||
this.databaseName = databaseName;
|
this.databaseName = databaseName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPrintername()
|
public String getPrintername() {
|
||||||
{
|
|
||||||
return printername;
|
return printername;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPrintername(String printername)
|
public void setPrintername(String printername) {
|
||||||
{
|
|
||||||
this.printername = printername;
|
this.printername = printername;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getLinebreak()
|
public int getLinebreak() {
|
||||||
{
|
|
||||||
return linebreak;
|
return linebreak;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLinebreak(int linebreak)
|
public void setLinebreak(int linebreak) {
|
||||||
{
|
|
||||||
this.linebreak = linebreak;
|
this.linebreak = linebreak;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getOffsetHeader()
|
public int getOffsetHeader() {
|
||||||
{
|
|
||||||
return offsetHeader;
|
return offsetHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOffsetHeader(int offsetHeader)
|
public void setOffsetHeader(int offsetHeader) {
|
||||||
{
|
|
||||||
this.offsetHeader = offsetHeader;
|
this.offsetHeader = offsetHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getOffsetFooter()
|
public int getOffsetFooter() {
|
||||||
{
|
|
||||||
return offsetFooter;
|
return offsetFooter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOffsetFooter(int offsetFooter)
|
public void setOffsetFooter(int offsetFooter) {
|
||||||
{
|
|
||||||
this.offsetFooter = offsetFooter;
|
this.offsetFooter = offsetFooter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getHeader()
|
public String getHeader() {
|
||||||
{
|
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHeader(String header)
|
public void setHeader(String header) {
|
||||||
{
|
|
||||||
this.header = header;
|
this.header = header;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getFooter()
|
public String getFooter() {
|
||||||
{
|
|
||||||
return footer;
|
return footer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFooter(String footer)
|
public void setFooter(String footer) {
|
||||||
{
|
|
||||||
this.footer = footer;
|
this.footer = footer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getCategorySplitted()
|
public boolean getCategorySplitted() {
|
||||||
{
|
|
||||||
return categorySplitted;
|
return categorySplitted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCategorySplitted(boolean categorySplitted)
|
public void setCategorySplitted(boolean categorySplitted) {
|
||||||
{
|
|
||||||
this.categorySplitted = categorySplitted;
|
this.categorySplitted = categorySplitted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getAutoPrintBill() {
|
||||||
|
return autoPrintBill;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutoPrintBill(boolean autoPrintBill) {
|
||||||
|
this.autoPrintBill = autoPrintBill;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.jFxKasse.datatypes;
|
||||||
|
|
||||||
|
public class Category {
|
||||||
|
private String categoryName;
|
||||||
|
|
||||||
|
private String positionsString = "\n";
|
||||||
|
|
||||||
|
public Category(String categoryName) {
|
||||||
|
this.categoryName = categoryName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCategoryName() {
|
||||||
|
return categoryName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPosition(int quantity, String name, String value, PrintData pd) {
|
||||||
|
for (int i = 0; i < quantity; i++) {
|
||||||
|
positionsString = positionsString + pd.setRight(pd.breakLines(name), value + " €") + "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPositionsString() {
|
||||||
|
return positionsString;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
package com.jFxKasse.datatypes;
|
package com.jFxKasse.datatypes;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class Job
|
public class Job {
|
||||||
{
|
|
||||||
|
|
||||||
private int jobnumber;
|
private int jobnumber;
|
||||||
|
|
||||||
private float jobvalue;
|
private float jobvalue;
|
||||||
@@ -19,48 +19,39 @@ public class Job
|
|||||||
|
|
||||||
private ArrayList<String> positionenCat;
|
private ArrayList<String> positionenCat;
|
||||||
|
|
||||||
public Job(int pJobnumber, String pTime)
|
public Job(int pJobnumber) {
|
||||||
{
|
|
||||||
this.jobnumber = pJobnumber;
|
this.jobnumber = pJobnumber;
|
||||||
this.jobtime = pTime;
|
|
||||||
|
|
||||||
positionenQuantity = new ArrayList<Integer>();
|
positionenQuantity = new ArrayList<Integer>();
|
||||||
positionenName = new ArrayList<String>();
|
positionenName = new ArrayList<String>();
|
||||||
positionenValue = new ArrayList<Float>();
|
positionenValue = new ArrayList<Float>();
|
||||||
positionenCat = new ArrayList<String>();
|
positionenCat = new ArrayList<String>();
|
||||||
|
|
||||||
// System.out.println("Größe: " + positionenName.size());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getJobnumber()
|
public void setJobtime(String jobtime) {
|
||||||
{
|
this.jobtime = jobtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getJobnumber() {
|
||||||
return this.jobnumber;
|
return this.jobnumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getJobtime()
|
public String getJobtime() {
|
||||||
{
|
|
||||||
return this.jobtime;
|
return this.jobtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getJobValue()
|
public float getJobValue() {
|
||||||
{
|
|
||||||
|
|
||||||
calcJobValue();
|
calcJobValue();
|
||||||
|
|
||||||
return this.jobvalue;
|
return this.jobvalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addPosition(String pPositionenName, float pPositionenValue,
|
public void addPosition(String pPositionenName, float pPositionenValue, String pPositionenCat) {
|
||||||
String pPositionenCat)
|
|
||||||
{
|
|
||||||
// System.out.println("addName");
|
|
||||||
|
|
||||||
for (int i = 0; i < positionenName.size(); i++) {
|
for (int i = 0; i < positionenName.size(); i++) {
|
||||||
if (positionenName.get(i).equals(pPositionenName)) {
|
if (positionenName.get(i).equals(pPositionenName)) {
|
||||||
// Item is already in list, increase quantity
|
// Item is already in list, increase quantity
|
||||||
positionenQuantity.set(i, positionenQuantity.get(i) + 1);
|
positionenQuantity.set(i, positionenQuantity.get(i) + 1);
|
||||||
// System.out.println("Item exists, increasing quantity");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,65 +64,44 @@ public class Job
|
|||||||
calcJobValue();
|
calcJobValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void printJobOnConsole()
|
public void printJobOnConsole() {
|
||||||
{
|
|
||||||
|
|
||||||
System.out.println("---------------------------------------------");
|
System.out.println("---------------------------------------------");
|
||||||
System.out.println("JobNummer: " + jobnumber);
|
System.out.println("JobNummer: " + jobnumber);
|
||||||
System.out.println("---------------------------------------------");
|
System.out.println("---------------------------------------------");
|
||||||
|
|
||||||
// System.out.println("Größe: " + positionenName.size());
|
|
||||||
|
|
||||||
for (int i = 0; i < positionenName.size(); i++) {
|
for (int i = 0; i < positionenName.size(); i++) {
|
||||||
|
|
||||||
System.out.println(
|
System.out.println(positionenQuantity.get(i) + " " + positionenName.get(i) + " " + positionenValue.get(i)
|
||||||
positionenQuantity.get(i) + " " + positionenName.get(i) + " "
|
+ " " + positionenCat.get(i));
|
||||||
+ positionenValue.get(i) + " " + positionenCat.get(i));
|
|
||||||
/*
|
|
||||||
* System.out.println("i is: " + i);
|
|
||||||
* System.out.println(positionenName.get(i));
|
|
||||||
* System.out.println(positionenQuantity.get(i));
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("---------------------------------------------");
|
System.out.println("---------------------------------------------");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<tableDataCurrentOrder> getCurrentJobPositionen()
|
public ArrayList<tableDataCurrentOrder> getCurrentJobPositionen() {
|
||||||
{
|
|
||||||
|
|
||||||
ArrayList<tableDataCurrentOrder> jobitems = new ArrayList<tableDataCurrentOrder>();
|
ArrayList<tableDataCurrentOrder> jobitems = new ArrayList<tableDataCurrentOrder>();
|
||||||
|
|
||||||
for (int i = 0; i < positionenName.size(); i++) {
|
for (int i = 0; i < positionenName.size(); i++) {
|
||||||
|
|
||||||
tableDataCurrentOrder tmp = new tableDataCurrentOrder(
|
tableDataCurrentOrder tmp = new tableDataCurrentOrder(positionenName.get(i), positionenQuantity.get(i));
|
||||||
positionenName.get(i), positionenQuantity.get(i));
|
|
||||||
|
|
||||||
jobitems.add(tmp);
|
jobitems.add(tmp);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return jobitems;
|
return jobitems;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void calcJobValue()
|
private void calcJobValue() {
|
||||||
{
|
|
||||||
|
|
||||||
jobvalue = 0;
|
jobvalue = 0;
|
||||||
|
|
||||||
for (int i = 0; i < positionenValue.size(); i++) {
|
for (int i = 0; i < positionenValue.size(); i++) {
|
||||||
|
jobvalue = jobvalue + (positionenQuantity.get(i) * positionenValue.get(i));
|
||||||
jobvalue = jobvalue
|
|
||||||
+ (positionenQuantity.get(i) * positionenValue.get(i));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// Round to two decimal places
|
||||||
|
jobvalue = BigDecimal.valueOf(jobvalue).setScale(2, RoundingMode.HALF_UP).floatValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String createPosQuantityDBString()
|
public String createPosQuantityDBString() {
|
||||||
{
|
|
||||||
String tmp = String.valueOf(positionenQuantity.get(0));
|
String tmp = String.valueOf(positionenQuantity.get(0));
|
||||||
for (int i = 1; i < positionenName.size(); i++) {
|
for (int i = 1; i < positionenName.size(); i++) {
|
||||||
|
|
||||||
@@ -140,8 +110,7 @@ public class Job
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String createPosNameDBString()
|
public String createPosNameDBString() {
|
||||||
{
|
|
||||||
String tmp = positionenName.get(0);
|
String tmp = positionenName.get(0);
|
||||||
for (int i = 1; i < positionenName.size(); i++) {
|
for (int i = 1; i < positionenName.size(); i++) {
|
||||||
|
|
||||||
@@ -150,8 +119,7 @@ public class Job
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String createPosValueDBString()
|
public String createPosValueDBString() {
|
||||||
{
|
|
||||||
String tmp = String.valueOf(positionenValue.get(0));
|
String tmp = String.valueOf(positionenValue.get(0));
|
||||||
for (int i = 1; i < positionenName.size(); i++) {
|
for (int i = 1; i < positionenName.size(); i++) {
|
||||||
|
|
||||||
@@ -160,8 +128,7 @@ public class Job
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String createPosCatDBString()
|
public String createPosCatDBString() {
|
||||||
{
|
|
||||||
String tmp = positionenCat.get(0);
|
String tmp = positionenCat.get(0);
|
||||||
for (int i = 1; i < positionenName.size(); i++) {
|
for (int i = 1; i < positionenName.size(); i++) {
|
||||||
|
|
||||||
@@ -170,8 +137,7 @@ public class Job
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deletePosName(String pPosName)
|
public void deletePosName(String pPosName) {
|
||||||
{
|
|
||||||
|
|
||||||
for (int i = 0; i < positionenName.size(); i++) {
|
for (int i = 0; i < positionenName.size(); i++) {
|
||||||
|
|
||||||
@@ -179,7 +145,8 @@ public class Job
|
|||||||
|
|
||||||
if (positionenQuantity.get(i) > 1) {
|
if (positionenQuantity.get(i) > 1) {
|
||||||
positionenQuantity.set(i, positionenQuantity.get(i) - 1);
|
positionenQuantity.set(i, positionenQuantity.get(i) - 1);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
positionenQuantity.remove(i);
|
positionenQuantity.remove(i);
|
||||||
positionenName.remove(i);
|
positionenName.remove(i);
|
||||||
@@ -194,8 +161,15 @@ public class Job
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean existsPosName(String pPosName)
|
public void clearAllPositions() {
|
||||||
{
|
positionenQuantity.clear();
|
||||||
|
positionenName.clear();
|
||||||
|
positionenValue.clear();
|
||||||
|
positionenCat.clear();
|
||||||
|
jobvalue = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean existsPosName(String pPosName) {
|
||||||
for (int i = 0; i < positionenName.size(); i++) {
|
for (int i = 0; i < positionenName.size(); i++) {
|
||||||
if (positionenName.get(i).equals(pPosName)) {
|
if (positionenName.get(i).equals(pPosName)) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.jFxKasse.datatypes;
|
package com.jFxKasse.datatypes;
|
||||||
|
|
||||||
public abstract class PrintData
|
public abstract class PrintData {
|
||||||
{
|
|
||||||
|
|
||||||
protected int headerSpace;
|
protected int headerSpace;
|
||||||
|
|
||||||
@@ -13,13 +12,13 @@ public abstract class PrintData
|
|||||||
|
|
||||||
protected String footer;
|
protected String footer;
|
||||||
|
|
||||||
protected String positionenQuantity;
|
protected String positionsQuantity;
|
||||||
|
|
||||||
protected String positionenName;
|
protected String positionsName;
|
||||||
|
|
||||||
protected String positionenValue;
|
protected String positionsValue;
|
||||||
|
|
||||||
protected String positionenCategory;
|
protected String positionsCategory;
|
||||||
|
|
||||||
protected String jobID;
|
protected String jobID;
|
||||||
|
|
||||||
@@ -30,7 +29,8 @@ public abstract class PrintData
|
|||||||
protected String jobValue;
|
protected String jobValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor with all data that is not in the DB
|
* Constructor with all data that is not stored in the DB
|
||||||
|
*
|
||||||
* @param lineBreak
|
* @param lineBreak
|
||||||
* @param headerSpace
|
* @param headerSpace
|
||||||
* @param footerSpace
|
* @param footerSpace
|
||||||
@@ -38,9 +38,8 @@ public abstract class PrintData
|
|||||||
* @param header
|
* @param header
|
||||||
* @param footer
|
* @param footer
|
||||||
*/
|
*/
|
||||||
public PrintData(int lineBreak, int headerSpace, int footerSpace,
|
public PrintData(int lineBreak, int headerSpace, int footerSpace, String timeAndDatePrint, String header,
|
||||||
String timeAndDatePrint, String header, String footer)
|
String footer) {
|
||||||
{
|
|
||||||
this.lineBreak = lineBreak;
|
this.lineBreak = lineBreak;
|
||||||
this.headerSpace = headerSpace;
|
this.headerSpace = headerSpace;
|
||||||
this.footerSpace = footerSpace;
|
this.footerSpace = footerSpace;
|
||||||
@@ -50,7 +49,8 @@ public abstract class PrintData
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set all Data that is in the DB
|
* Set all data that is stored in the DB
|
||||||
|
*
|
||||||
* @param jobID
|
* @param jobID
|
||||||
* @param timeAndDateOrder
|
* @param timeAndDateOrder
|
||||||
* @param positionenQuantity
|
* @param positionenQuantity
|
||||||
@@ -59,40 +59,38 @@ public abstract class PrintData
|
|||||||
* @param positionenCategory
|
* @param positionenCategory
|
||||||
* @param jobValue
|
* @param jobValue
|
||||||
*/
|
*/
|
||||||
public void setData(String jobID, String timeAndDateOrder,
|
public void setData(String jobID, String timeAndDateOrder, String positionsQuantity, String positionsName,
|
||||||
String positionenQuantity, String positionenName,
|
String positionsValue, String positionsCategory, String jobValue) {
|
||||||
String positionenValue, String positionenCategory, String jobValue)
|
|
||||||
{
|
|
||||||
this.jobID = jobID;
|
this.jobID = jobID;
|
||||||
this.timeAndDateOrder = timeAndDateOrder;
|
this.timeAndDateOrder = timeAndDateOrder;
|
||||||
this.positionenQuantity = positionenQuantity;
|
this.positionsQuantity = positionsQuantity;
|
||||||
this.positionenName = positionenName;
|
this.positionsName = positionsName;
|
||||||
this.positionenValue = positionenValue;
|
this.positionsValue = positionsValue;
|
||||||
this.positionenCategory = positionenCategory;
|
this.positionsCategory = positionsCategory;
|
||||||
this.jobValue = jobValue;
|
this.jobValue = jobValue;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Breaks a string with newlines after the max line length
|
||||||
*
|
*
|
||||||
* @param data String
|
* @param data String
|
||||||
* @return same String splitted with \n after the max. line lenght
|
* @return the same String split with \n after max line length
|
||||||
*/
|
*/
|
||||||
protected String breakLines(String data)
|
protected String breakLines(String data) {
|
||||||
{
|
|
||||||
boolean next = false;
|
boolean next = false;
|
||||||
|
|
||||||
int count = lineBreak;
|
int count = lineBreak;
|
||||||
|
|
||||||
if (data.length() > lineBreak) {
|
if (data.length() > lineBreak) {
|
||||||
// Needs to be splitted
|
// Needs to be split
|
||||||
next = true;
|
next = true;
|
||||||
} else {
|
}
|
||||||
// No need to be splitted
|
else {
|
||||||
|
// No need to split
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// first part
|
// First part
|
||||||
String tmp = data.substring(0, lineBreak);
|
String tmp = data.substring(0, lineBreak);
|
||||||
|
|
||||||
while (next) {
|
while (next) {
|
||||||
@@ -100,22 +98,22 @@ public abstract class PrintData
|
|||||||
try {
|
try {
|
||||||
tmp = tmp + "\n" + data.substring(count, lineBreak + count);
|
tmp = tmp + "\n" + data.substring(count, lineBreak + count);
|
||||||
count = count + lineBreak;
|
count = count + lineBreak;
|
||||||
} catch (Exception e) {
|
}
|
||||||
// data string not long enough
|
catch (Exception e) {
|
||||||
|
// Data string not long enough
|
||||||
next = false;
|
next = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// add the last part
|
// Add the last part
|
||||||
return tmp + "\n" + data.substring(count);
|
return tmp + "\n" + data.substring(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* prints a line of '--------'
|
* Prints a line of dashes '--------'
|
||||||
* @return
|
*
|
||||||
|
* @return separator line
|
||||||
*/
|
*/
|
||||||
protected String getSeparator()
|
protected String getSeparator() {
|
||||||
{
|
|
||||||
String tmp = "-";
|
String tmp = "-";
|
||||||
|
|
||||||
for (int i = 1; i < lineBreak; i++) {
|
for (int i = 1; i < lineBreak; i++) {
|
||||||
@@ -125,12 +123,12 @@ public abstract class PrintData
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sets a String into the center
|
* Centers a string within the line width
|
||||||
|
*
|
||||||
* @param data
|
* @param data
|
||||||
* @return the centered String
|
* @return the centered string
|
||||||
*/
|
*/
|
||||||
protected String setCenter(String data)
|
protected String setCenter(String data) {
|
||||||
{
|
|
||||||
int dataLenght = data.length();
|
int dataLenght = data.length();
|
||||||
int prefix = ((lineBreak - dataLenght) / 2);
|
int prefix = ((lineBreak - dataLenght) / 2);
|
||||||
String tmp = " ";
|
String tmp = " ";
|
||||||
@@ -139,18 +137,18 @@ public abstract class PrintData
|
|||||||
tmp = tmp + " ";
|
tmp = tmp + " ";
|
||||||
}
|
}
|
||||||
tmp = tmp + data;
|
tmp = tmp + data;
|
||||||
|
|
||||||
return breakLines(tmp);
|
return breakLines(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sets a String right-justified after an prefix
|
* Right-justifies a string after a prefix
|
||||||
|
*
|
||||||
* @param prefix
|
* @param prefix
|
||||||
* @param data
|
* @param data
|
||||||
* @return the right-justified String
|
* @return the right-justified string
|
||||||
*/
|
*/
|
||||||
protected String setRight(String prefix, String data)
|
protected String setRight(String prefix, String data) {
|
||||||
{
|
|
||||||
|
|
||||||
int prefixLenght = prefix.length();
|
int prefixLenght = prefix.length();
|
||||||
|
|
||||||
@@ -175,7 +173,7 @@ public abstract class PrintData
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How the print String or Strings are made
|
* Defines how the print string(s) are generated
|
||||||
*/
|
*/
|
||||||
abstract protected void generatePrintString();
|
abstract protected void generatePrintString();
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package com.jFxKasse.datatypes;
|
package com.jFxKasse.datatypes;
|
||||||
|
|
||||||
public class PrintDataSimple extends PrintData
|
public class PrintDataSimple extends PrintData {
|
||||||
{
|
|
||||||
|
|
||||||
private String printString;
|
private String printString;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor with all data that is not in the DB
|
* Constructor with all data that is not stored in the DB
|
||||||
|
*
|
||||||
* @param lineBreak
|
* @param lineBreak
|
||||||
* @param headerSpace
|
* @param headerSpace
|
||||||
* @param footerSpace
|
* @param footerSpace
|
||||||
@@ -14,28 +14,25 @@ public class PrintDataSimple extends PrintData
|
|||||||
* @param header
|
* @param header
|
||||||
* @param footer
|
* @param footer
|
||||||
*/
|
*/
|
||||||
public PrintDataSimple(int lineBreak, int headerSpace, int footerSpace,
|
public PrintDataSimple(int lineBreak, int headerSpace, int footerSpace, String timeAndDatePrint, String header,
|
||||||
String timeAndDatePrint, String header, String footer)
|
String footer) {
|
||||||
{
|
super(lineBreak, headerSpace, footerSpace, timeAndDatePrint, header, footer);
|
||||||
super(lineBreak, headerSpace, footerSpace, timeAndDatePrint, header,
|
|
||||||
footer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the String
|
* Generates the print string
|
||||||
* @return the final Print String
|
*
|
||||||
|
* @return the final print string
|
||||||
*/
|
*/
|
||||||
public String getPrintString()
|
public String getPrintString() {
|
||||||
{
|
|
||||||
generatePrintString();
|
generatePrintString();
|
||||||
return this.printString;
|
return this.printString;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void generatePrintString()
|
protected void generatePrintString() {
|
||||||
{
|
|
||||||
/* Header */
|
/* Header */
|
||||||
String header = "\n";
|
String header = " ";
|
||||||
for (int i = 1; i < headerSpace; i++) {
|
for (int i = 1; i < headerSpace; i++) {
|
||||||
header = header + "\n";
|
header = header + "\n";
|
||||||
}
|
}
|
||||||
@@ -45,28 +42,25 @@ public class PrintDataSimple extends PrintData
|
|||||||
|
|
||||||
/* Info */
|
/* Info */
|
||||||
|
|
||||||
String info = setRight("Bestellung: ", timeAndDateOrder) + "\n"
|
String info = setRight("Bestellung: ", timeAndDateOrder) + "\n" + setRight("Druck: ", timeAndDatePrint) + "\n"
|
||||||
+ setRight("Druck: ", timeAndDatePrint) + "\n"
|
|
||||||
+ setRight("Bestellnummer: ", jobID);
|
+ setRight("Bestellnummer: ", jobID);
|
||||||
|
|
||||||
/* Positionen */
|
/* Positionen */
|
||||||
|
|
||||||
String positionen = "\n";
|
String positionen = "\n";
|
||||||
|
|
||||||
int posCount = positionenQuantity.length()
|
int posCount = positionsQuantity.length() - positionsQuantity.replace(";", "").length() + 1;
|
||||||
- positionenQuantity.replace(";", "").length() + 1;
|
|
||||||
|
|
||||||
String[] positionQuantity = positionenQuantity.split(";");
|
String[] positionQuantity = positionsQuantity.split(";");
|
||||||
|
|
||||||
String[] positionName = positionenName.split(";");
|
String[] positionName = positionsName.split(";");
|
||||||
|
|
||||||
String[] positionValue = positionenValue.split(";");
|
String[] positionValue = positionsValue.split(";");
|
||||||
|
|
||||||
for (int i = 0; i < posCount; i++) { //All different posNames
|
for (int i = 0; i < posCount; i++) { // All different posNames
|
||||||
int quantity = Integer.parseInt(positionQuantity[i]);
|
int quantity = Integer.parseInt(positionQuantity[i]);
|
||||||
for (int j = 0; j < quantity; j++) { //quantities
|
for (int j = 0; j < quantity; j++) { // quantities
|
||||||
positionen = positionen + setRight(breakLines(positionName[i]),
|
positionen = positionen + setRight(breakLines(positionName[i]), positionValue[i] + " €") + "\n";
|
||||||
positionValue[i] + " €") + "\n";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,9 +79,8 @@ public class PrintDataSimple extends PrintData
|
|||||||
|
|
||||||
/* Build final Print String */
|
/* Build final Print String */
|
||||||
|
|
||||||
printString = header + "\n" + getSeparator() + "\n" + info + "\n"
|
printString = header + "\n" + getSeparator() + "\n" + info + "\n" + getSeparator() + "\n" + positionen + "\n"
|
||||||
+ getSeparator() + "\n" + positionen + "\n" + getSeparator() + "\n"
|
+ getSeparator() + "\n" + price + "\n" + getSeparator() + "\n" + footer;
|
||||||
+ price + "\n" + getSeparator() + "\n" + footer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,157 @@
|
|||||||
|
package com.jFxKasse.datatypes;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class PrintDataSplitted extends PrintData {
|
||||||
|
private ArrayList<String> printString = new ArrayList<String>();
|
||||||
|
|
||||||
|
private ArrayList<Category> categories = new ArrayList<Category>();
|
||||||
|
|
||||||
|
private int categoryCount = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor with all data that is not stored in the DB
|
||||||
|
*
|
||||||
|
* @param lineBreak
|
||||||
|
* @param headerSpace
|
||||||
|
* @param footerSpace
|
||||||
|
* @param timeAndDatePrint
|
||||||
|
* @param header
|
||||||
|
* @param footer
|
||||||
|
*/
|
||||||
|
public PrintDataSplitted(int lineBreak, int headerSpace, int footerSpace, String timeAndDatePrint, String header,
|
||||||
|
String footer) {
|
||||||
|
super(lineBreak, headerSpace, footerSpace, timeAndDatePrint, header, footer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the print strings
|
||||||
|
*
|
||||||
|
* @return the final array of print strings
|
||||||
|
*/
|
||||||
|
public ArrayList<String> getPrintStrings() {
|
||||||
|
generatePrintString();
|
||||||
|
return printString;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void generatePrintString() {
|
||||||
|
|
||||||
|
String firstBill;
|
||||||
|
|
||||||
|
/* Header */
|
||||||
|
String header = "-";
|
||||||
|
for (int i = 1; i < headerSpace; i++) {
|
||||||
|
header = header + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the final header
|
||||||
|
header = header + setCenter(this.header);
|
||||||
|
|
||||||
|
/* Info */
|
||||||
|
|
||||||
|
String info = setRight("Bestellung: ", timeAndDateOrder) + "\n" + setRight("Druck: ", timeAndDatePrint) + "\n"
|
||||||
|
+ setRight("Bestellnummer: ", jobID);
|
||||||
|
|
||||||
|
/* Splitted Bills by Category */
|
||||||
|
|
||||||
|
/* Price */
|
||||||
|
|
||||||
|
String price = setRight("Gesamt: ", (jobValue + " €"));
|
||||||
|
|
||||||
|
/* Footer */
|
||||||
|
|
||||||
|
String footer = setCenter(this.footer);
|
||||||
|
|
||||||
|
for (int i = 1; i < footerSpace; i++) {
|
||||||
|
footer = footer + "\n";
|
||||||
|
}
|
||||||
|
footer = footer + "_";
|
||||||
|
|
||||||
|
/* Build first Print String */
|
||||||
|
|
||||||
|
firstBill = header + "\n" + getSeparator() + "\n" + info + "\n" + getSeparator() + "\n"
|
||||||
|
+ setCenter("Bon wurde aufgeteilt") + "\n" + getSeparator() + "\n" + price + "\n" + getSeparator()
|
||||||
|
+ "\n" + footer;
|
||||||
|
|
||||||
|
printString.add(firstBill);
|
||||||
|
|
||||||
|
/* First bill ends here */
|
||||||
|
|
||||||
|
/* Category-specific extra bills */
|
||||||
|
|
||||||
|
String positions = null;
|
||||||
|
|
||||||
|
int posCount = positionsQuantity.length() - positionsQuantity.replace(";", "").length() + 1;
|
||||||
|
|
||||||
|
String[] positionQuantity = positionsQuantity.split(";");
|
||||||
|
String[] positionName = positionsName.split(";");
|
||||||
|
String[] positionValue = positionsValue.split(";");
|
||||||
|
String[] positionCategory = positionsCategory.split(";");
|
||||||
|
|
||||||
|
for (int i = 0; i < posCount; i++) { // All different posNames
|
||||||
|
int quantity = Integer.parseInt(positionQuantity[i]);
|
||||||
|
insertToCategory(quantity, positionName[i], positionValue[i], positionCategory[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loops through all categories
|
||||||
|
for (int i = 0; i < categories.size(); i++) {
|
||||||
|
|
||||||
|
String thisBill;
|
||||||
|
|
||||||
|
/* Header */
|
||||||
|
header = " ";
|
||||||
|
for (int o = 1; o < headerSpace; o++) {
|
||||||
|
header = header + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the final header
|
||||||
|
header = header + setCenter(this.header);
|
||||||
|
|
||||||
|
/* Info */
|
||||||
|
|
||||||
|
info = setRight("Bestellung: ", timeAndDateOrder) + "\n" + setRight("Druck: ", timeAndDatePrint) + "\n"
|
||||||
|
+ setRight("Bestellnummer: ", jobID);
|
||||||
|
|
||||||
|
/* Positions */
|
||||||
|
|
||||||
|
positions = categories.get(i).getPositionsString();
|
||||||
|
|
||||||
|
/* Footer */
|
||||||
|
|
||||||
|
footer = "\n";
|
||||||
|
|
||||||
|
for (int o = 2; o < footerSpace; o++) {
|
||||||
|
footer = footer + "\n";
|
||||||
|
}
|
||||||
|
footer = footer + "_";
|
||||||
|
|
||||||
|
thisBill = header + "\n" + getSeparator() + "\n" + info + "\n" + getSeparator() + "\n"
|
||||||
|
+ setCenter(categories.get(i).getCategoryName()) + "\n" + getSeparator() + positions + "\n"
|
||||||
|
+ getSeparator() + "\n" + footer;
|
||||||
|
|
||||||
|
printString.add(thisBill);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insertToCategory(int quantity, String name, String value, String category) {
|
||||||
|
boolean createNewCategorie = true;
|
||||||
|
for (int i = 0; i < categoryCount; i++) {
|
||||||
|
if (category.equals(categories.get(i).getCategoryName())) {
|
||||||
|
categories.get(i).addPosition(quantity, name, value, this);
|
||||||
|
createNewCategorie = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (createNewCategorie) {
|
||||||
|
// Position has a new category
|
||||||
|
categories.add(new Category(category));
|
||||||
|
categories.get(categoryCount).addPosition(quantity, name, value, this);
|
||||||
|
categoryCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -5,47 +5,38 @@ import javafx.beans.property.SimpleIntegerProperty;
|
|||||||
import javafx.beans.property.SimpleStringProperty;
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
import javafx.beans.property.StringProperty;
|
import javafx.beans.property.StringProperty;
|
||||||
|
|
||||||
public class tableDataCurrentOrder
|
public class tableDataCurrentOrder {
|
||||||
{
|
|
||||||
|
|
||||||
private final StringProperty position = new SimpleStringProperty();
|
private final StringProperty position = new SimpleStringProperty();
|
||||||
|
|
||||||
private final IntegerProperty quantity = new SimpleIntegerProperty();
|
private final IntegerProperty quantity = new SimpleIntegerProperty();
|
||||||
|
|
||||||
public tableDataCurrentOrder(final String pPosition, final Integer pQuantity)
|
public tableDataCurrentOrder(final String pPosition, final Integer pQuantity) {
|
||||||
{
|
|
||||||
this.position.set(pPosition);
|
this.position.set(pPosition);
|
||||||
this.quantity.set(pQuantity);
|
this.quantity.set(pQuantity);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringProperty positionProperty()
|
public StringProperty positionProperty() {
|
||||||
{
|
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IntegerProperty quantityProperty()
|
public IntegerProperty quantityProperty() {
|
||||||
{
|
|
||||||
return quantity;
|
return quantity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPosition()
|
public String getPosition() {
|
||||||
{
|
|
||||||
return positionProperty().get();
|
return positionProperty().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getQuantity()
|
public Integer getQuantity() {
|
||||||
{
|
|
||||||
return quantityProperty().get();
|
return quantityProperty().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setPosition(String pPosition)
|
public final void setPosition(String pPosition) {
|
||||||
{
|
|
||||||
positionProperty().set(pPosition);
|
positionProperty().set(pPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setQuantity(int pQuantity)
|
public final void setQuantity(int pQuantity) {
|
||||||
{
|
|
||||||
quantityProperty().set(pQuantity);
|
quantityProperty().set(pQuantity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,7 @@ import javafx.beans.property.SimpleIntegerProperty;
|
|||||||
import javafx.beans.property.SimpleStringProperty;
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
import javafx.beans.property.StringProperty;
|
import javafx.beans.property.StringProperty;
|
||||||
|
|
||||||
public class tableDataJob
|
public class tableDataJob {
|
||||||
{
|
|
||||||
|
|
||||||
private final IntegerProperty number = new SimpleIntegerProperty();
|
private final IntegerProperty number = new SimpleIntegerProperty();
|
||||||
|
|
||||||
@@ -18,9 +17,8 @@ public class tableDataJob
|
|||||||
|
|
||||||
private final StringProperty value = new SimpleStringProperty();
|
private final StringProperty value = new SimpleStringProperty();
|
||||||
|
|
||||||
public tableDataJob(final Integer pNumber, final String pTime,
|
public tableDataJob(final Integer pNumber, final String pTime, final String pPositionen, final String pStatus,
|
||||||
final String pPositionen, final String pStatus, final String pValue)
|
final String pValue) {
|
||||||
{
|
|
||||||
this.number.set(pNumber);
|
this.number.set(pNumber);
|
||||||
this.time.set(pTime);
|
this.time.set(pTime);
|
||||||
this.positionen.set(pPositionen);
|
this.positionen.set(pPositionen);
|
||||||
@@ -29,78 +27,63 @@ public class tableDataJob
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IntegerProperty numberProperty()
|
public IntegerProperty numberProperty() {
|
||||||
{
|
|
||||||
return number;
|
return number;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringProperty timeProperty()
|
public StringProperty timeProperty() {
|
||||||
{
|
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringProperty positionProperty()
|
public StringProperty positionProperty() {
|
||||||
{
|
|
||||||
return positionen;
|
return positionen;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringProperty statusProperty()
|
public StringProperty statusProperty() {
|
||||||
{
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringProperty valueProperty()
|
public StringProperty valueProperty() {
|
||||||
{
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getNumber()
|
public Integer getNumber() {
|
||||||
{
|
|
||||||
return numberProperty().get();
|
return numberProperty().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTime()
|
public String getTime() {
|
||||||
{
|
|
||||||
return timeProperty().get();
|
return timeProperty().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPosition()
|
public String getPosition() {
|
||||||
{
|
|
||||||
return positionProperty().get();
|
return positionProperty().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStatus()
|
public String getStatus() {
|
||||||
{
|
|
||||||
return statusProperty().get();
|
return statusProperty().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getValue()
|
public String getValue() {
|
||||||
{
|
|
||||||
return valueProperty().get();
|
return valueProperty().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setNumber(int pNumber)
|
public final void setNumber(int pNumber) {
|
||||||
{
|
|
||||||
numberProperty().set(pNumber);
|
numberProperty().set(pNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setTime(String pTime)
|
public final void setTime(String pTime) {
|
||||||
{
|
|
||||||
timeProperty().set(pTime);
|
timeProperty().set(pTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setPosition(String pPosition)
|
public final void setPosition(String pPosition) {
|
||||||
{
|
|
||||||
positionProperty().set(pPosition);
|
positionProperty().set(pPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setStatus(String pStatus)
|
public final void setStatus(String pStatus) {
|
||||||
{
|
|
||||||
statusProperty().set(pStatus);
|
statusProperty().set(pStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setValue(String pValue)
|
public final void setValue(String pValue) {
|
||||||
{
|
|
||||||
valueProperty().set(pValue);
|
valueProperty().set(pValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,21 +5,20 @@ import javafx.beans.property.SimpleIntegerProperty;
|
|||||||
import javafx.beans.property.SimpleStringProperty;
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
import javafx.beans.property.StringProperty;
|
import javafx.beans.property.StringProperty;
|
||||||
|
|
||||||
public class tableDataPositionen
|
public class tableDataPositionen { // Data object with id, name, value, color
|
||||||
{ // data-object with id, name, value, color
|
|
||||||
|
|
||||||
private final IntegerProperty id = new SimpleIntegerProperty();
|
private final IntegerProperty id = new SimpleIntegerProperty();
|
||||||
|
|
||||||
private final StringProperty name = new SimpleStringProperty();
|
private final StringProperty name = new SimpleStringProperty();
|
||||||
|
|
||||||
private final StringProperty value = new SimpleStringProperty();
|
private final StringProperty value = new SimpleStringProperty();
|
||||||
|
|
||||||
private final StringProperty cat = new SimpleStringProperty();
|
private final StringProperty cat = new SimpleStringProperty();
|
||||||
|
|
||||||
private final StringProperty color = new SimpleStringProperty();
|
private final StringProperty color = new SimpleStringProperty();
|
||||||
|
|
||||||
public tableDataPositionen(final int id, final String name, final String value, final String cat, final String color)
|
public tableDataPositionen(final int id, final String name, final String value, final String cat,
|
||||||
{
|
final String color) {
|
||||||
this.id.set(id);
|
this.id.set(id);
|
||||||
this.name.set(name);
|
this.name.set(name);
|
||||||
this.value.set(value);
|
this.value.set(value);
|
||||||
@@ -27,75 +26,63 @@ public class tableDataPositionen
|
|||||||
this.color.set(color);
|
this.color.set(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IntegerProperty idProperty()
|
public IntegerProperty idProperty() {
|
||||||
{
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringProperty nameProperty()
|
public StringProperty nameProperty() {
|
||||||
{
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringProperty valueProperty()
|
public StringProperty valueProperty() {
|
||||||
{
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringProperty catProperty() {
|
public StringProperty catProperty() {
|
||||||
return cat;
|
return cat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringProperty colorProperty()
|
public StringProperty colorProperty() {
|
||||||
{
|
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getID()
|
public int getID() {
|
||||||
{
|
|
||||||
return idProperty().get();
|
return idProperty().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName()
|
public String getName() {
|
||||||
{
|
|
||||||
return nameProperty().get();
|
return nameProperty().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getValue()
|
public String getValue() {
|
||||||
{
|
|
||||||
return valueProperty().get();
|
return valueProperty().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCat() {
|
public String getCat() {
|
||||||
return catProperty().get();
|
return catProperty().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getColor()
|
public String getColor() {
|
||||||
{
|
|
||||||
return colorProperty().get();
|
return colorProperty().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setID(int id)
|
public final void setID(int id) {
|
||||||
{
|
|
||||||
idProperty().set(id);
|
idProperty().set(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setName(String name)
|
public final void setName(String name) {
|
||||||
{
|
|
||||||
nameProperty().set(name);
|
nameProperty().set(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setValue(String value)
|
public final void setValue(String value) {
|
||||||
{
|
|
||||||
valueProperty().set(value);
|
valueProperty().set(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setCat(String cat) {
|
public final void setCat(String cat) {
|
||||||
catProperty().set(cat);
|
catProperty().set(cat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setColor(String color)
|
public final void setColor(String color) {
|
||||||
{
|
|
||||||
colorProperty().set(color);
|
colorProperty().set(color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
/* JavaFX CSS - Leave this comment until you have at least create one rule which uses -fx-Property */
|
/* JavaFX CSS - Leave this comment until you have at least one rule which uses -fx-Property */
|
||||||
@@ -0,0 +1,677 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
generate_report.py – Erstellt einen deutschen HTML-Bericht aus einer SQLite-Datenbank
|
||||||
|
(Schema: category, positionen, jobs) – erstellt mit jFxKasse.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python generate_report.py <database.db> [-o output.html]
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import shutil
|
||||||
|
import sqlite3
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from collections import defaultdict
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
SOFTWARE_NAME = "jFxKasse"
|
||||||
|
SOFTWARE_URL = "https://git.mosad.xyz/localhorst/jFxKasse"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Data helpers
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
def load_db(path: str) -> sqlite3.Connection:
|
||||||
|
con = sqlite3.connect(path)
|
||||||
|
con.row_factory = sqlite3.Row
|
||||||
|
return con
|
||||||
|
|
||||||
|
|
||||||
|
def parse_time(t: str) -> datetime:
|
||||||
|
return datetime.strptime(t.strip(), "%H:%M %d.%m.%Y")
|
||||||
|
|
||||||
|
|
||||||
|
def fmt_dt(dt: datetime) -> str:
|
||||||
|
return dt.strftime("%d.%m.%Y %H:%M Uhr")
|
||||||
|
|
||||||
|
|
||||||
|
def fmt_dur(td: timedelta) -> str:
|
||||||
|
total = int(td.total_seconds())
|
||||||
|
h, rem = divmod(total, 3600)
|
||||||
|
m = rem // 60
|
||||||
|
return f"{h} Std. {m} Min."
|
||||||
|
|
||||||
|
|
||||||
|
def fmt_eur(val) -> str:
|
||||||
|
try:
|
||||||
|
return f"{float(val):.2f} €"
|
||||||
|
except Exception:
|
||||||
|
return str(val)
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Chart helpers
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CHARTJS = "https://cdn.jsdelivr.net/npm/chart.js@4.4.3/dist/chart.umd.min.js"
|
||||||
|
|
||||||
|
_chart_id = 0
|
||||||
|
|
||||||
|
|
||||||
|
def next_id(prefix="chart") -> str:
|
||||||
|
global _chart_id
|
||||||
|
_chart_id += 1
|
||||||
|
return f"{prefix}_{_chart_id}"
|
||||||
|
|
||||||
|
|
||||||
|
PALETTE = [
|
||||||
|
"#c0392b",
|
||||||
|
"#2980b9",
|
||||||
|
"#27ae60",
|
||||||
|
"#8e44ad",
|
||||||
|
"#d35400",
|
||||||
|
"#16a085",
|
||||||
|
"#f39c12",
|
||||||
|
"#2c3e50",
|
||||||
|
"#7f8c8d",
|
||||||
|
"#e74c3c",
|
||||||
|
"#1abc9c",
|
||||||
|
"#9b59b6",
|
||||||
|
"#e67e22",
|
||||||
|
"#34495e",
|
||||||
|
"#95a5a6",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def bar_chart_html(
|
||||||
|
labels: list,
|
||||||
|
values: list,
|
||||||
|
xlabel: str = "",
|
||||||
|
ylabel: str = "",
|
||||||
|
color: str = "#2c3e50",
|
||||||
|
height: int = 280,
|
||||||
|
) -> str:
|
||||||
|
cid = next_id("bar")
|
||||||
|
data = {
|
||||||
|
"labels": labels,
|
||||||
|
"datasets": [
|
||||||
|
{
|
||||||
|
"label": ylabel,
|
||||||
|
"data": values,
|
||||||
|
"backgroundColor": color,
|
||||||
|
"borderRadius": 4,
|
||||||
|
"borderSkipped": False,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
opts = {
|
||||||
|
"responsive": True,
|
||||||
|
"maintainAspectRatio": False,
|
||||||
|
"plugins": {"legend": {"display": False}},
|
||||||
|
"scales": {
|
||||||
|
"x": {
|
||||||
|
"title": {
|
||||||
|
"display": bool(xlabel),
|
||||||
|
"text": xlabel,
|
||||||
|
"font": {"size": 11},
|
||||||
|
"color": "#555",
|
||||||
|
},
|
||||||
|
"grid": {"color": "#ebebeb"},
|
||||||
|
"ticks": {"color": "#555", "font": {"size": 10}},
|
||||||
|
},
|
||||||
|
"y": {
|
||||||
|
"title": {
|
||||||
|
"display": bool(ylabel),
|
||||||
|
"text": ylabel,
|
||||||
|
"font": {"size": 11},
|
||||||
|
"color": "#555",
|
||||||
|
},
|
||||||
|
"grid": {"color": "#ebebeb"},
|
||||||
|
"ticks": {"color": "#555", "font": {"size": 10}},
|
||||||
|
"beginAtZero": True,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
f'<div style="position:relative;height:{height}px;width:100%;margin:8px 0;">'
|
||||||
|
f'<canvas id="{cid}"></canvas></div>'
|
||||||
|
f"<script>(function(){{"
|
||||||
|
f'var ctx=document.getElementById("{cid}").getContext("2d");'
|
||||||
|
f'new Chart(ctx,{{type:"bar",'
|
||||||
|
f"data:{json.dumps(data, ensure_ascii=False)},"
|
||||||
|
f"options:{json.dumps(opts, ensure_ascii=False)}}});"
|
||||||
|
f"}})();</script>"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def pie_chart_html(labels: list, values: list, height: int = 280) -> str:
|
||||||
|
cid = next_id("pie")
|
||||||
|
colors = [PALETTE[i % len(PALETTE)] for i in range(len(labels))]
|
||||||
|
data = {
|
||||||
|
"labels": labels,
|
||||||
|
"datasets": [
|
||||||
|
{
|
||||||
|
"data": values,
|
||||||
|
"backgroundColor": colors,
|
||||||
|
"borderWidth": 2,
|
||||||
|
"borderColor": "#fff",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
opts = {
|
||||||
|
"responsive": True,
|
||||||
|
"maintainAspectRatio": False,
|
||||||
|
"plugins": {
|
||||||
|
"legend": {
|
||||||
|
"position": "right",
|
||||||
|
"labels": {
|
||||||
|
"font": {
|
||||||
|
"size": 11,
|
||||||
|
"family": "'Source Code Pro','Courier New',monospace",
|
||||||
|
},
|
||||||
|
"color": "#2c2c2c",
|
||||||
|
"padding": 14,
|
||||||
|
"boxWidth": 14,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
f'<div style="position:relative;height:{height}px;width:100%;margin:8px 0;">'
|
||||||
|
f'<canvas id="{cid}"></canvas></div>'
|
||||||
|
f"<script>(function(){{"
|
||||||
|
f'var ctx=document.getElementById("{cid}").getContext("2d");'
|
||||||
|
f'new Chart(ctx,{{type:"pie",'
|
||||||
|
f"data:{json.dumps(data, ensure_ascii=False)},"
|
||||||
|
f"options:{json.dumps(opts, ensure_ascii=False)}}});"
|
||||||
|
f"}})();</script>"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Analysis
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
def analyse(con: sqlite3.Connection) -> dict:
|
||||||
|
result = {}
|
||||||
|
|
||||||
|
result["categories"] = [
|
||||||
|
dict(r)
|
||||||
|
for r in con.execute("SELECT catid, catname FROM category ORDER BY catid")
|
||||||
|
]
|
||||||
|
|
||||||
|
result["positionen"] = [
|
||||||
|
dict(r)
|
||||||
|
for r in con.execute(
|
||||||
|
"SELECT p.posid, p.name, p.value, c.catname, p.color "
|
||||||
|
"FROM positionen p LEFT JOIN category c ON p.cat=c.catid "
|
||||||
|
"ORDER BY p.posid"
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
all_jobs = [dict(r) for r in con.execute("SELECT * FROM jobs ORDER BY jobid")]
|
||||||
|
|
||||||
|
times = [parse_time(j["time"]) for j in all_jobs]
|
||||||
|
result["first_job"] = min(times)
|
||||||
|
result["last_job"] = max(times)
|
||||||
|
result["duration"] = result["last_job"] - result["first_job"]
|
||||||
|
result["total_jobs"] = len(all_jobs)
|
||||||
|
result["storniert_count"] = sum(1 for j in all_jobs if j["state"] == "storniert")
|
||||||
|
result["verbucht_count"] = sum(1 for j in all_jobs if j["state"] == "verbucht")
|
||||||
|
|
||||||
|
vj = [j for j in all_jobs if j["state"] == "verbucht"]
|
||||||
|
values = [float(j["jobvalue"]) for j in vj]
|
||||||
|
result["sum_total"] = sum(values)
|
||||||
|
result["avg_value"] = sum(values) / len(values) if values else 0
|
||||||
|
|
||||||
|
min_val = min(values)
|
||||||
|
max_val = max(values)
|
||||||
|
result["min_job"] = next(j for j in vj if float(j["jobvalue"]) == min_val)
|
||||||
|
result["max_job"] = [j for j in vj if float(j["jobvalue"]) == max_val][-1]
|
||||||
|
|
||||||
|
# Overall hourly trend (verbucht, skip empty hours)
|
||||||
|
hour_counts: dict[str, int] = defaultdict(int)
|
||||||
|
for j in vj:
|
||||||
|
dt = parse_time(j["time"])
|
||||||
|
hour_counts[dt.strftime("%d.%m. %H:00")] += 1
|
||||||
|
sorted_hours = sorted(
|
||||||
|
hour_counts, key=lambda k: datetime.strptime(k, "%d.%m. %H:00")
|
||||||
|
)
|
||||||
|
result["trend_labels"] = sorted_hours
|
||||||
|
result["trend_values"] = [hour_counts[k] for k in sorted_hours]
|
||||||
|
|
||||||
|
# Per-category aggregations (expand semicolon-separated fields)
|
||||||
|
cat_units: dict[str, int] = defaultdict(int)
|
||||||
|
cat_revenue: dict[str, float] = defaultdict(float)
|
||||||
|
cat_pos_units: dict[str, dict[str, int]] = defaultdict(lambda: defaultdict(int))
|
||||||
|
cat_pos_revenue: dict[str, dict[str, float]] = defaultdict(
|
||||||
|
lambda: defaultdict(float)
|
||||||
|
)
|
||||||
|
cat_day_hour: dict[str, dict[str, dict[int, int]]] = defaultdict(
|
||||||
|
lambda: defaultdict(lambda: defaultdict(int))
|
||||||
|
)
|
||||||
|
|
||||||
|
for j in vj:
|
||||||
|
dt = parse_time(j["time"])
|
||||||
|
day = dt.strftime("%d.%m.%Y")
|
||||||
|
qtys = j["positionen_quantity"].split(";")
|
||||||
|
names = j["positionen_name"].split(";")
|
||||||
|
vals = j["positionen_value"].split(";")
|
||||||
|
cats = j["positionen_cat"].split(";")
|
||||||
|
for qty, name, val, cat in zip(qtys, names, vals, cats):
|
||||||
|
cat = cat.strip()
|
||||||
|
name = name.strip()
|
||||||
|
try:
|
||||||
|
q = int(qty.strip())
|
||||||
|
except ValueError:
|
||||||
|
q = 1
|
||||||
|
try:
|
||||||
|
v = float(val.strip())
|
||||||
|
except ValueError:
|
||||||
|
v = 0.0
|
||||||
|
cat_units[cat] += q
|
||||||
|
cat_revenue[cat] += v * q
|
||||||
|
cat_pos_units[cat][name] += q
|
||||||
|
cat_pos_revenue[cat][name] += v * q
|
||||||
|
cat_day_hour[cat][day][dt.hour] += q
|
||||||
|
|
||||||
|
result["cat_units"] = dict(cat_units)
|
||||||
|
result["cat_revenue"] = dict(cat_revenue)
|
||||||
|
result["cat_pos_units"] = {c: dict(p) for c, p in cat_pos_units.items()}
|
||||||
|
result["cat_pos_revenue"] = {c: dict(p) for c, p in cat_pos_revenue.items()}
|
||||||
|
result["cat_day_hour"] = {
|
||||||
|
cat: {day: dict(hours) for day, hours in days.items()}
|
||||||
|
for cat, days in cat_day_hour.items()
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# CSS
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CSS = """
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Source+Code+Pro:wght@400;600&display=swap');
|
||||||
|
|
||||||
|
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0;}
|
||||||
|
:root{
|
||||||
|
--ink:#1a1a1a;--paper:#f7f4ef;--rule:#d4c9b8;
|
||||||
|
--red:#c0392b;--muted:#6b6560;--accent:#2c3e50;--white:#fff;
|
||||||
|
}
|
||||||
|
body{font-family:'Source Code Pro','Courier New',monospace;background:var(--paper);
|
||||||
|
color:var(--ink);font-size:13px;line-height:1.7;}
|
||||||
|
.page-wrap{max-width:980px;margin:0 auto;padding:48px 40px;}
|
||||||
|
|
||||||
|
.report-header{border-top:4px solid var(--ink);border-bottom:2px solid var(--rule);
|
||||||
|
padding:28px 0 24px;margin-bottom:40px;}
|
||||||
|
.report-header h1{font-family:'Playfair Display',Georgia,serif;font-size:2.1rem;
|
||||||
|
letter-spacing:-0.02em;color:var(--ink);margin-bottom:4px;}
|
||||||
|
.report-header .sub{color:var(--muted);font-size:11px;letter-spacing:0.08em;text-transform:uppercase;}
|
||||||
|
.sw-link{display:inline-block;margin-top:10px;font-size:11px;color:var(--accent);
|
||||||
|
text-decoration:none;border-bottom:1px solid var(--accent);opacity:.8;}
|
||||||
|
.sw-link:hover{opacity:1;}
|
||||||
|
.meta-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));
|
||||||
|
gap:8px 24px;margin-top:18px;padding-top:16px;border-top:1px solid var(--rule);}
|
||||||
|
.meta-item{display:flex;flex-direction:column;gap:2px;}
|
||||||
|
.meta-label{font-size:10px;text-transform:uppercase;letter-spacing:0.1em;color:var(--muted);}
|
||||||
|
.meta-value{font-weight:600;color:var(--ink);font-size:12px;}
|
||||||
|
|
||||||
|
.section{margin-bottom:48px;}
|
||||||
|
.section-title{font-family:'Playfair Display',Georgia,serif;font-size:1.25rem;
|
||||||
|
border-bottom:2px solid var(--ink);padding-bottom:6px;margin-bottom:20px;color:var(--accent);}
|
||||||
|
.section-sub{font-size:10px;text-transform:uppercase;letter-spacing:0.1em;
|
||||||
|
color:var(--muted);margin-bottom:14px;margin-top:-10px;}
|
||||||
|
|
||||||
|
table{width:100%;border-collapse:collapse;font-size:12px;}
|
||||||
|
th{background:var(--ink);color:var(--paper);text-align:left;padding:8px 12px;
|
||||||
|
font-weight:600;letter-spacing:0.05em;font-size:10px;text-transform:uppercase;}
|
||||||
|
td{padding:7px 12px;border-bottom:1px solid var(--rule);vertical-align:top;}
|
||||||
|
tr:nth-child(even) td{background:rgba(0,0,0,.025);}
|
||||||
|
|
||||||
|
.kpi-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(155px,1fr));
|
||||||
|
gap:14px;margin-bottom:22px;}
|
||||||
|
.kpi-card{border:1px solid var(--rule);padding:15px 16px;background:var(--white);position:relative;}
|
||||||
|
.kpi-card::before{content:'';position:absolute;top:0;left:0;width:3px;height:100%;background:var(--red);}
|
||||||
|
.kpi-label{font-size:10px;text-transform:uppercase;letter-spacing:0.1em;color:var(--muted);margin-bottom:3px;}
|
||||||
|
.kpi-value{font-family:'Playfair Display',Georgia,serif;font-size:1.45rem;color:var(--ink);line-height:1.2;}
|
||||||
|
.kpi-sub{font-size:10px;color:var(--muted);margin-top:4px;}
|
||||||
|
|
||||||
|
.dot{display:inline-block;width:10px;height:10px;border-radius:50%;
|
||||||
|
margin-right:6px;vertical-align:middle;border:1px solid rgba(0,0,0,.15);}
|
||||||
|
|
||||||
|
.chart-grid-2{display:grid;grid-template-columns:repeat(auto-fit,minmax(420px,1fr));gap:24px;margin-top:8px;}
|
||||||
|
.chart-box{border:1px solid var(--rule);padding:18px 18px 14px;background:var(--white);}
|
||||||
|
.chart-box-title{font-size:11px;font-weight:600;text-transform:uppercase;
|
||||||
|
letter-spacing:0.08em;color:var(--accent);margin-bottom:3px;}
|
||||||
|
.chart-box-note{font-size:11px;color:var(--muted);margin-bottom:8px;}
|
||||||
|
|
||||||
|
.rule{border:none;border-top:1px solid var(--rule);margin:32px 0;}
|
||||||
|
|
||||||
|
.report-footer{border-top:2px solid var(--ink);padding-top:14px;margin-top:48px;
|
||||||
|
font-size:10px;color:var(--muted);display:flex;justify-content:space-between;flex-wrap:wrap;gap:4px;}
|
||||||
|
.report-footer a{color:inherit;}
|
||||||
|
|
||||||
|
@media print{
|
||||||
|
body{background:#fff;}
|
||||||
|
.page-wrap{padding:20px;}
|
||||||
|
.chart-grid-2{grid-template-columns:1fr 1fr;}
|
||||||
|
.section,.kpi-grid,.chart-box{page-break-inside:avoid;}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# HTML builder
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
def build_html(db_path: str, data: dict, export_time: datetime) -> str:
|
||||||
|
p = Path(db_path)
|
||||||
|
display_name = p.name
|
||||||
|
file_size_kb = p.stat().st_size / 1024
|
||||||
|
file_mtime = datetime.fromtimestamp(p.stat().st_mtime)
|
||||||
|
|
||||||
|
# ---- Header ----
|
||||||
|
header = f"""
|
||||||
|
<div class="report-header">
|
||||||
|
<div class="sub">Auswertungsbericht · Kassensystem</div>
|
||||||
|
<h1>{display_name}</h1>
|
||||||
|
<a class="sw-link" href="{SOFTWARE_URL}" target="_blank">Erstellt mit {SOFTWARE_NAME}</a>
|
||||||
|
<div class="meta-grid">
|
||||||
|
<div class="meta-item"><span class="meta-label">Dateiname</span>
|
||||||
|
<span class="meta-value">{display_name}</span></div>
|
||||||
|
<div class="meta-item"><span class="meta-label">Dateigröße</span>
|
||||||
|
<span class="meta-value">{file_size_kb:.1f} KB</span></div>
|
||||||
|
<div class="meta-item"><span class="meta-label">Erstellt am</span>
|
||||||
|
<span class="meta-value">{file_mtime.strftime('%d.%m.%Y %H:%M Uhr')}</span></div>
|
||||||
|
<div class="meta-item"><span class="meta-label">Export um</span>
|
||||||
|
<span class="meta-value">{export_time.strftime('%d.%m.%Y %H:%M Uhr')}</span></div>
|
||||||
|
</div>
|
||||||
|
</div>"""
|
||||||
|
|
||||||
|
# ---- Kategorien ----
|
||||||
|
cat_rows = "".join(
|
||||||
|
f'<tr><td>{c["catid"]}</td><td>{c["catname"]}</td></tr>'
|
||||||
|
for c in data["categories"]
|
||||||
|
)
|
||||||
|
section_cat = f"""
|
||||||
|
<div class="section">
|
||||||
|
<div class="section-title">Kategorien</div>
|
||||||
|
<table>
|
||||||
|
<thead><tr><th>#</th><th>Kategoriename</th></tr></thead>
|
||||||
|
<tbody>{cat_rows}</tbody>
|
||||||
|
</table>
|
||||||
|
</div>"""
|
||||||
|
|
||||||
|
# ---- Positionen ----
|
||||||
|
pos_rows = "".join(
|
||||||
|
f'<tr><td>{pos["posid"]}</td>'
|
||||||
|
f'<td><span class="dot" style="background:{pos["color"]};"></span>{pos["name"]}</td>'
|
||||||
|
f'<td>{fmt_eur(pos["value"])}</td>'
|
||||||
|
f'<td>{pos["catname"] or "–"}</td></tr>'
|
||||||
|
for pos in data["positionen"]
|
||||||
|
)
|
||||||
|
section_pos = f"""
|
||||||
|
<div class="section">
|
||||||
|
<div class="section-title">Positionen / Artikel</div>
|
||||||
|
<table>
|
||||||
|
<thead><tr><th>#</th><th>Bezeichnung</th><th>Preis</th><th>Kategorie</th></tr></thead>
|
||||||
|
<tbody>{pos_rows}</tbody>
|
||||||
|
</table>
|
||||||
|
</div>"""
|
||||||
|
|
||||||
|
# ---- Jobs ----
|
||||||
|
min_j = data["min_job"]
|
||||||
|
max_j = data["max_job"]
|
||||||
|
kpi_overview = f"""
|
||||||
|
<div class="kpi-grid">
|
||||||
|
<div class="kpi-card"><div class="kpi-label">Erster Auftrag</div>
|
||||||
|
<div class="kpi-value" style="font-size:.95rem;">{fmt_dt(data["first_job"])}</div></div>
|
||||||
|
<div class="kpi-card"><div class="kpi-label">Letzter Auftrag</div>
|
||||||
|
<div class="kpi-value" style="font-size:.95rem;">{fmt_dt(data["last_job"])}</div></div>
|
||||||
|
<div class="kpi-card"><div class="kpi-label">Betriebsdauer</div>
|
||||||
|
<div class="kpi-value" style="font-size:.95rem;">{fmt_dur(data["duration"])}</div></div>
|
||||||
|
<div class="kpi-card"><div class="kpi-label">Aufträge gesamt</div>
|
||||||
|
<div class="kpi-value">{data["total_jobs"]}</div></div>
|
||||||
|
<div class="kpi-card"><div class="kpi-label">Verbucht</div>
|
||||||
|
<div class="kpi-value" style="color:#27ae60;">{data["verbucht_count"]}</div></div>
|
||||||
|
<div class="kpi-card"><div class="kpi-label">Storniert</div>
|
||||||
|
<div class="kpi-value" style="color:#c0392b;">{data["storniert_count"]}</div></div>
|
||||||
|
</div>"""
|
||||||
|
|
||||||
|
kpi_deep = f"""
|
||||||
|
<div class="kpi-grid">
|
||||||
|
<div class="kpi-card"><div class="kpi-label">Gesamtumsatz</div>
|
||||||
|
<div class="kpi-value">{fmt_eur(data["sum_total"])}</div>
|
||||||
|
<div class="kpi-sub">nur verbuchte Aufträge</div></div>
|
||||||
|
<div class="kpi-card"><div class="kpi-label">Durchschnitt / Auftrag</div>
|
||||||
|
<div class="kpi-value">{fmt_eur(data["avg_value"])}</div>
|
||||||
|
<div class="kpi-sub">nur verbuchte Aufträge</div></div>
|
||||||
|
<div class="kpi-card"><div class="kpi-label">Kleinster Auftrag</div>
|
||||||
|
<div class="kpi-value">{fmt_eur(min_j["jobvalue"])}</div>
|
||||||
|
<div class="kpi-sub">Job #{min_j["jobid"]} · {min_j["time"]}</div></div>
|
||||||
|
<div class="kpi-card"><div class="kpi-label">Größter Auftrag</div>
|
||||||
|
<div class="kpi-value">{fmt_eur(max_j["jobvalue"])}</div>
|
||||||
|
<div class="kpi-sub">Job #{max_j["jobid"]} · {max_j["time"]}</div></div>
|
||||||
|
</div>"""
|
||||||
|
|
||||||
|
trend_chart = bar_chart_html(
|
||||||
|
data["trend_labels"],
|
||||||
|
data["trend_values"],
|
||||||
|
xlabel="Stunde",
|
||||||
|
ylabel="Anzahl Aufträge",
|
||||||
|
color="#2c3e50",
|
||||||
|
height=300,
|
||||||
|
)
|
||||||
|
|
||||||
|
section_jobs = f"""
|
||||||
|
<div class="section">
|
||||||
|
<div class="section-title">Auftragsübersicht</div>
|
||||||
|
<div class="section-sub">Alle Aufträge</div>
|
||||||
|
{kpi_overview}
|
||||||
|
<hr class="rule">
|
||||||
|
<div class="section-sub">Tiefenanalyse – nur verbuchte Aufträge</div>
|
||||||
|
{kpi_deep}
|
||||||
|
<hr class="rule">
|
||||||
|
<div class="section-sub">Trendverlauf – Aufträge pro Stunde (gesamte Datenbank)</div>
|
||||||
|
{trend_chart}
|
||||||
|
</div>"""
|
||||||
|
|
||||||
|
# ---- Pie 1: Einheiten je Kategorie ----
|
||||||
|
cu = data["cat_units"]
|
||||||
|
pie_units = pie_chart_html(
|
||||||
|
[f"{k} ({v} Stk.)" for k, v in cu.items()], list(cu.values()), height=300
|
||||||
|
)
|
||||||
|
note_units = " · ".join(
|
||||||
|
f"<strong>{k}</strong>: {v} Stk." for k, v in cu.items()
|
||||||
|
)
|
||||||
|
|
||||||
|
# ---- Pie 2: Umsatz je Kategorie ----
|
||||||
|
cr = data["cat_revenue"]
|
||||||
|
pie_revenue = pie_chart_html(
|
||||||
|
[f"{k} ({fmt_eur(v)})" for k, v in cr.items()], list(cr.values()), height=300
|
||||||
|
)
|
||||||
|
note_revenue = " · ".join(
|
||||||
|
f"<strong>{k}</strong>: {fmt_eur(v)}" for k, v in cr.items()
|
||||||
|
)
|
||||||
|
|
||||||
|
section_cat_pies = f"""
|
||||||
|
<div class="section">
|
||||||
|
<div class="section-title">Kategorienauswertung</div>
|
||||||
|
|
||||||
|
<div class="section-sub">Verkaufte Einheiten nach Kategorie (nur verbuchte Aufträge)</div>
|
||||||
|
<div class="chart-box" style="margin-bottom:28px;">
|
||||||
|
<div class="chart-box-title">Einheiten je Kategorie</div>
|
||||||
|
<div class="chart-box-note">{note_units}</div>
|
||||||
|
{pie_units}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section-sub">Umsatz nach Kategorie (nur verbuchte Aufträge)</div>
|
||||||
|
<div class="chart-box">
|
||||||
|
<div class="chart-box-title">Umsatz je Kategorie</div>
|
||||||
|
<div class="chart-box-note">{note_revenue}</div>
|
||||||
|
{pie_revenue}
|
||||||
|
</div>
|
||||||
|
</div>"""
|
||||||
|
|
||||||
|
# ---- Pie 3: Positionen je Kategorie ----
|
||||||
|
pos_pie_boxes = ""
|
||||||
|
for cat, pos_dict in sorted(data["cat_pos_units"].items()):
|
||||||
|
labels = list(pos_dict.keys())
|
||||||
|
values = list(pos_dict.values())
|
||||||
|
total = sum(values)
|
||||||
|
note = " · ".join(
|
||||||
|
f"<strong>{l}</strong>: {v}" for l, v in zip(labels, values)
|
||||||
|
)
|
||||||
|
pie = pie_chart_html(
|
||||||
|
[f"{l} ({v})" for l, v in zip(labels, values)], values, height=260
|
||||||
|
)
|
||||||
|
pos_pie_boxes += f"""
|
||||||
|
<div class="chart-box">
|
||||||
|
<div class="chart-box-title">{cat}</div>
|
||||||
|
<div class="chart-box-note">Gesamt: {total} Einheiten</div>
|
||||||
|
{pie}
|
||||||
|
<div class="chart-box-note" style="margin-top:10px;font-size:10px;line-height:1.8;">{note}</div>
|
||||||
|
</div>"""
|
||||||
|
|
||||||
|
section_pos_pies = f"""
|
||||||
|
<div class="section">
|
||||||
|
<div class="section-title">Positionen je Kategorie</div>
|
||||||
|
<div class="section-sub">Verkaufte Stückzahl pro Artikel, aufgeteilt nach Kategorie</div>
|
||||||
|
<div class="chart-grid-2">
|
||||||
|
{pos_pie_boxes}
|
||||||
|
</div>
|
||||||
|
</div>"""
|
||||||
|
|
||||||
|
# ---- Per-category trend per day ----
|
||||||
|
cat_names = sorted(data["cat_day_hour"].keys())
|
||||||
|
cat_trend_boxes = ""
|
||||||
|
for i, cat in enumerate(cat_names):
|
||||||
|
color = PALETTE[i % len(PALETTE)]
|
||||||
|
days = data["cat_day_hour"][cat]
|
||||||
|
for day in sorted(days, key=lambda d: datetime.strptime(d, "%d.%m.%Y")):
|
||||||
|
hours = days[day]
|
||||||
|
labels = [f"{h}:00" for h in sorted(hours)]
|
||||||
|
values = [hours[h] for h in sorted(hours)]
|
||||||
|
chart = bar_chart_html(
|
||||||
|
labels,
|
||||||
|
values,
|
||||||
|
xlabel="Stunde",
|
||||||
|
ylabel="Einheiten",
|
||||||
|
color=color,
|
||||||
|
height=220,
|
||||||
|
)
|
||||||
|
cat_trend_boxes += f"""
|
||||||
|
<div class="chart-box">
|
||||||
|
<div class="chart-box-title">{cat} · {day}</div>
|
||||||
|
{chart}
|
||||||
|
</div>"""
|
||||||
|
|
||||||
|
section_trends = f"""
|
||||||
|
<div class="section">
|
||||||
|
<div class="section-title">Trendverlauf pro Kategorie und Tag</div>
|
||||||
|
<div class="section-sub">Verkaufte Artikel-Einheiten pro Stunde</div>
|
||||||
|
<div class="chart-grid-2">
|
||||||
|
{cat_trend_boxes}
|
||||||
|
</div>
|
||||||
|
</div>"""
|
||||||
|
|
||||||
|
# ---- Footer ----
|
||||||
|
footer = f"""
|
||||||
|
<div class="report-footer">
|
||||||
|
<span>Exportiert am {export_time.strftime('%d.%m.%Y um %H:%M Uhr')}</span>
|
||||||
|
<span>Quelle: {display_name} ·
|
||||||
|
<a href="{SOFTWARE_URL}">{SOFTWARE_NAME}</a></span>
|
||||||
|
</div>"""
|
||||||
|
|
||||||
|
return f"""<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
|
<title>Bericht – {display_name}</title>
|
||||||
|
<script src="{CHARTJS}"></script>
|
||||||
|
<style>{CSS}</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="page-wrap">
|
||||||
|
{header}
|
||||||
|
{section_cat}
|
||||||
|
<hr class="rule">
|
||||||
|
{section_pos}
|
||||||
|
<hr class="rule">
|
||||||
|
{section_jobs}
|
||||||
|
<hr class="rule">
|
||||||
|
{section_cat_pies}
|
||||||
|
<hr class="rule">
|
||||||
|
{section_pos_pies}
|
||||||
|
<hr class="rule">
|
||||||
|
{section_trends}
|
||||||
|
{footer}
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>"""
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# CLI
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
def build_parser() -> argparse.ArgumentParser:
|
||||||
|
p = argparse.ArgumentParser(
|
||||||
|
prog="generate_report",
|
||||||
|
description="Erstellt einen deutschen HTML-Bericht aus einer jFxKasse SQLite-Datenbank.",
|
||||||
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
|
epilog=(
|
||||||
|
"Beispiele:\n"
|
||||||
|
" python generate_report.py kassendaten.db\n"
|
||||||
|
" python generate_report.py kassendaten.db -o bericht.html\n"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
p.add_argument("database", help="Pfad zur SQLite-Datenbankdatei")
|
||||||
|
p.add_argument(
|
||||||
|
"-o",
|
||||||
|
"--output",
|
||||||
|
metavar="OUTPUT_HTML",
|
||||||
|
help="Pfad zur Ausgabe-HTML-Datei (Standard: <dateiname>_bericht.html)",
|
||||||
|
)
|
||||||
|
return p
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = build_parser()
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
db_path = Path(args.database)
|
||||||
|
if not db_path.exists():
|
||||||
|
parser.error(f"Datei nicht gefunden: {db_path}")
|
||||||
|
|
||||||
|
out_path = (
|
||||||
|
Path(args.output)
|
||||||
|
if args.output
|
||||||
|
else db_path.with_name(db_path.stem + "_bericht.html")
|
||||||
|
)
|
||||||
|
|
||||||
|
print(f"[lade] {db_path.name}")
|
||||||
|
con = load_db(str(db_path))
|
||||||
|
|
||||||
|
print("[analyse] Daten werden ausgewertet …")
|
||||||
|
data = analyse(con)
|
||||||
|
con.close()
|
||||||
|
|
||||||
|
print("[render] HTML wird erstellt …")
|
||||||
|
html = build_html(str(db_path), data, datetime.now())
|
||||||
|
out_path.write_text(html, encoding="utf-8")
|
||||||
|
print(f"[fertig] HTML gespeichert: {out_path}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,281 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
merge_db.py – Merge multiple SQLite databases into one output file.
|
||||||
|
|
||||||
|
Rules
|
||||||
|
-----
|
||||||
|
* Tables `category` and `positionen` are deduplicated by ALL columns
|
||||||
|
(content-based identity, ignoring the local rowid/id column).
|
||||||
|
* Table `jobs` rows from later files are appended with a re-sequenced
|
||||||
|
`jobid` so IDs never clash across files.
|
||||||
|
* Rows are inserted in file order: the first file wins on deduplication
|
||||||
|
for reference tables; job rows from later files come after earlier ones.
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
python merge_db.py -o merged.db 02.db 03.db [04.db ...]
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import shutil
|
||||||
|
import sqlite3
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Helpers
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def get_table_names(con: sqlite3.Connection) -> list[str]:
|
||||||
|
cur = con.execute("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name")
|
||||||
|
return [row[0] for row in cur.fetchall()]
|
||||||
|
|
||||||
|
|
||||||
|
def get_columns(con: sqlite3.Connection, table: str) -> list[str]:
|
||||||
|
cur = con.execute(f'PRAGMA table_info("{table}")')
|
||||||
|
return [row[1] for row in cur.fetchall()]
|
||||||
|
|
||||||
|
|
||||||
|
def get_create_statement(con: sqlite3.Connection, table: str) -> str:
|
||||||
|
cur = con.execute(
|
||||||
|
"SELECT sql FROM sqlite_master WHERE type='table' AND name=?", (table,)
|
||||||
|
)
|
||||||
|
row = cur.fetchone()
|
||||||
|
return row[0] if row else None
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Merge logic per table type
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def merge_dedup_table(
|
||||||
|
src: sqlite3.Connection,
|
||||||
|
dst: sqlite3.Connection,
|
||||||
|
table: str,
|
||||||
|
id_col: str,
|
||||||
|
) -> tuple[int, int]:
|
||||||
|
"""
|
||||||
|
Merge a reference table using content-based deduplication.
|
||||||
|
|
||||||
|
Rows are compared on every column *except* `id_col`. If an identical
|
||||||
|
row already exists in `dst`, it is skipped; otherwise it is inserted
|
||||||
|
with a new auto-incremented id.
|
||||||
|
|
||||||
|
Returns (rows_read, rows_inserted).
|
||||||
|
"""
|
||||||
|
cols = get_columns(src, table)
|
||||||
|
content_cols = [c for c in cols if c != id_col]
|
||||||
|
|
||||||
|
if not content_cols:
|
||||||
|
return 0, 0
|
||||||
|
|
||||||
|
placeholders = ", ".join("?" * len(content_cols))
|
||||||
|
select_content = ", ".join(f'"{c}"' for c in content_cols)
|
||||||
|
|
||||||
|
# Build a set of existing content tuples for fast dedup lookup
|
||||||
|
existing: set[tuple] = set()
|
||||||
|
for row in dst.execute(f'SELECT {select_content} FROM "{table}"'):
|
||||||
|
existing.add(row)
|
||||||
|
|
||||||
|
src_rows = src.execute(f'SELECT {select_content} FROM "{table}"').fetchall()
|
||||||
|
inserted = 0
|
||||||
|
for row in src_rows:
|
||||||
|
key = tuple(row)
|
||||||
|
if key not in existing:
|
||||||
|
dst.execute(
|
||||||
|
f'INSERT INTO "{table}" ({select_content}) VALUES ({placeholders})',
|
||||||
|
row,
|
||||||
|
)
|
||||||
|
existing.add(key)
|
||||||
|
inserted += 1
|
||||||
|
|
||||||
|
return len(src_rows), inserted
|
||||||
|
|
||||||
|
|
||||||
|
def merge_jobs_table(
|
||||||
|
src: sqlite3.Connection,
|
||||||
|
dst: sqlite3.Connection,
|
||||||
|
table: str = "jobs",
|
||||||
|
id_col: str = "jobid",
|
||||||
|
) -> tuple[int, int]:
|
||||||
|
"""
|
||||||
|
Append job rows from `src` into `dst`, re-sequencing `id_col` so that
|
||||||
|
new IDs start after the current maximum in `dst`.
|
||||||
|
|
||||||
|
Duplicate detection is done on all columns except `id_col`; rows with
|
||||||
|
identical content are skipped.
|
||||||
|
|
||||||
|
Returns (rows_read, rows_inserted).
|
||||||
|
"""
|
||||||
|
cols = get_columns(src, table)
|
||||||
|
content_cols = [c for c in cols if c != id_col]
|
||||||
|
all_col_str = ", ".join(f'"{c}"' for c in cols)
|
||||||
|
content_str = ", ".join(f'"{c}"' for c in content_cols)
|
||||||
|
placeholders = ", ".join("?" * len(cols))
|
||||||
|
|
||||||
|
# Current max id in destination
|
||||||
|
row = dst.execute(f'SELECT MAX("{id_col}") FROM "{table}"').fetchone()
|
||||||
|
offset = (row[0] or 0)
|
||||||
|
|
||||||
|
# Existing content fingerprints for dedup
|
||||||
|
existing: set[tuple] = set()
|
||||||
|
for row in dst.execute(f'SELECT {content_str} FROM "{table}"'):
|
||||||
|
existing.add(tuple(row))
|
||||||
|
|
||||||
|
src_rows = src.execute(f'SELECT {all_col_str} FROM "{table}"').fetchall()
|
||||||
|
col_index = {c: i for i, c in enumerate(cols)}
|
||||||
|
id_idx = col_index[id_col]
|
||||||
|
|
||||||
|
inserted = 0
|
||||||
|
for row in src_rows:
|
||||||
|
content_key = tuple(row[col_index[c]] for c in content_cols)
|
||||||
|
if content_key in existing:
|
||||||
|
continue # skip duplicate content
|
||||||
|
new_id = row[id_idx] + offset
|
||||||
|
new_row = list(row)
|
||||||
|
new_row[id_idx] = new_id
|
||||||
|
dst.execute(
|
||||||
|
f'INSERT INTO "{table}" ({all_col_str}) VALUES ({placeholders})',
|
||||||
|
new_row,
|
||||||
|
)
|
||||||
|
existing.add(content_key)
|
||||||
|
inserted += 1
|
||||||
|
|
||||||
|
return len(src_rows), inserted
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Schema helpers
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def ensure_table(dst: sqlite3.Connection, src: sqlite3.Connection, table: str) -> None:
|
||||||
|
"""Create `table` in `dst` if it doesn't exist yet, using src's DDL."""
|
||||||
|
exists = dst.execute(
|
||||||
|
"SELECT 1 FROM sqlite_master WHERE type='table' AND name=?", (table,)
|
||||||
|
).fetchone()
|
||||||
|
if not exists:
|
||||||
|
ddl = get_create_statement(src, table)
|
||||||
|
if ddl:
|
||||||
|
dst.execute(ddl)
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Main merge routine
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Map table name → (id_column, merge_strategy)
|
||||||
|
# strategy: "dedup" → content-based dedup, new ids assigned
|
||||||
|
# "jobs" → append with id re-sequencing + content dedup
|
||||||
|
TABLE_CONFIG: dict[str, tuple[str, str]] = {
|
||||||
|
"category": ("catid", "dedup"),
|
||||||
|
"positionen": ("posid", "dedup"),
|
||||||
|
"jobs": ("jobid", "jobs"),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def merge_databases(input_files: list[Path], output_file: Path) -> None:
|
||||||
|
# Bootstrap: copy first file as the base for the output
|
||||||
|
print(f"[init] Bootstrapping output from '{input_files[0].name}' …")
|
||||||
|
shutil.copy2(input_files[0], output_file)
|
||||||
|
|
||||||
|
dst = sqlite3.connect(output_file)
|
||||||
|
dst.execute("PRAGMA journal_mode=WAL")
|
||||||
|
dst.execute("PRAGMA foreign_keys=OFF")
|
||||||
|
|
||||||
|
try:
|
||||||
|
for src_path in input_files[1:]:
|
||||||
|
print(f"\n[merge] Processing '{src_path.name}' …")
|
||||||
|
src = sqlite3.connect(src_path)
|
||||||
|
|
||||||
|
src_tables = get_table_names(src)
|
||||||
|
for table in src_tables:
|
||||||
|
ensure_table(dst, src, table)
|
||||||
|
config = TABLE_CONFIG.get(table)
|
||||||
|
|
||||||
|
if config is None:
|
||||||
|
# Unknown table: fall back to content-based dedup without
|
||||||
|
# special id handling – treat first column as the id.
|
||||||
|
cols = get_columns(src, table)
|
||||||
|
id_col = cols[0] if cols else None
|
||||||
|
if id_col:
|
||||||
|
read, ins = merge_dedup_table(src, dst, table, id_col)
|
||||||
|
print(f" [{table}] (fallback dedup on '{id_col}') "
|
||||||
|
f"read={read} inserted={ins}")
|
||||||
|
else:
|
||||||
|
id_col, strategy = config
|
||||||
|
if strategy == "dedup":
|
||||||
|
read, ins = merge_dedup_table(src, dst, table, id_col)
|
||||||
|
else:
|
||||||
|
read, ins = merge_jobs_table(src, dst, table, id_col)
|
||||||
|
print(f" [{table}] strategy={strategy} "
|
||||||
|
f"read={read} inserted={ins}")
|
||||||
|
|
||||||
|
dst.commit()
|
||||||
|
src.close()
|
||||||
|
|
||||||
|
finally:
|
||||||
|
dst.close()
|
||||||
|
|
||||||
|
print(f"\n[done] Output written to '{output_file}'")
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# CLI
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def build_parser() -> argparse.ArgumentParser:
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
prog="merge_db",
|
||||||
|
description=(
|
||||||
|
"Merge multiple SQLite databases into one output file.\n"
|
||||||
|
"Files are merged in the order they are provided.\n"
|
||||||
|
"Duplicate rows are detected by content and inserted only once."
|
||||||
|
),
|
||||||
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
|
epilog=(
|
||||||
|
"Examples:\n"
|
||||||
|
" python merge_db.py -o merged.db 02.db 03.db\n"
|
||||||
|
" python merge_db.py -o merged.db 02.db 03.db 04.db 05.db\n"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"inputs",
|
||||||
|
metavar="INPUT_DB",
|
||||||
|
nargs="+",
|
||||||
|
help="Input SQLite database files (in desired merge order)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-o", "--output",
|
||||||
|
metavar="OUTPUT_DB",
|
||||||
|
required=True,
|
||||||
|
help="Path for the merged output database (will be overwritten if it exists)",
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
parser = build_parser()
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
input_paths = [Path(p) for p in args.inputs]
|
||||||
|
output_path = Path(args.output)
|
||||||
|
|
||||||
|
# Validate inputs
|
||||||
|
for p in input_paths:
|
||||||
|
if not p.exists():
|
||||||
|
parser.error(f"Input file not found: {p}")
|
||||||
|
if not p.is_file():
|
||||||
|
parser.error(f"Not a file: {p}")
|
||||||
|
|
||||||
|
if len(input_paths) < 2:
|
||||||
|
parser.error("At least two input files are required.")
|
||||||
|
|
||||||
|
if output_path.exists():
|
||||||
|
print(f"[warn] Output file '{output_path}' already exists and will be overwritten.")
|
||||||
|
|
||||||
|
merge_databases(input_paths, output_path)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||