From f72980f63b397571c8c9f783efbb9a2651906e88 Mon Sep 17 00:00:00 2001 From: Rajdeep Roy Chowdhury Date: Tue, 10 Nov 2026 22:06:57 +0530 Subject: [PATCH 01/11] feat: added jgit as dependency Signed-off-by: Rajdeep Roy Chowdhury --- .github/workflows/build.yml | 62 ++--- build.gradle.kts | 2 + gradle/libs.versions.toml | 113 ++++---- .../openconsignment/common/AppConfig.java | 5 +- .../controller/MainController.java | 60 ++++- .../controller/WelcomeScreenController.java | 2 +- .../service/BackupService.java | 63 +++++ .../openconsignment/service/BuyerService.java | 2 +- .../service/SupplierService.java | 2 +- .../service/TransportService.java | 2 +- src/main/resources/fxml/Main.fxml | 241 +++++++++++------- .../resources/fxml/report/BuyerLedger.fxml | 9 +- .../resources/fxml/report/SupplierLedger.fxml | 9 +- .../fxml/report/TransportLedger.fxml | 9 +- .../di/ConfigurationModuleTest.java | 12 +- 15 files changed, 376 insertions(+), 217 deletions(-) create mode 100644 src/main/java/openconsignment/service/BackupService.java diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 210b5af..47cd00f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,32 +1,32 @@ -name: JavaFX Build (Gradle) - -on: - push: - pull_request: - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set up JDK - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: 17 - cache: gradle - - - name: Make Gradle executable - run: chmod +x gradlew - - - name: Build using Gradle - run: ./gradlew clean build - - - name: Upload JAR artifact - uses: actions/upload-artifact@v4 - with: - name: satyam-consignment +name: JavaFX Build (Gradle) + +on: + push: + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up JDK + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 17 + cache: gradle + + - name: Make Gradle executable + run: chmod +x gradlew + + - name: Build using Gradle + run: ./gradlew clean build + + - name: Upload JAR artifact + uses: actions/upload-artifact@v4 + with: + name: OpenConsignment path: build/libs/* \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 3e918a1..9d055b4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,6 +32,8 @@ dependencies { implementation(libs.javafx.graphics) implementation(libs.javafx.fxml) + implementation(libs.jgit) + compileOnly(libs.lombok) annotationProcessor(libs.lombok) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 92efa9f..77afec8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,65 +1,68 @@ -[versions] -javafx = "17.0.18" -controlsfx = "11.2.2" -jasperreports = "6.21.5" -sqlite = "3.34.0" -olap4j = "1.2.0" -#itext = "2.1.7" -lombok = "1.18.20" -dagger = "2.52" -testfx = "4.0.18" -testfxCore = "4.0.17" -monocle = "17.0.10" -hamcrest = "2.2" -#junit = "5.10.1" -junitbom = "5.10.2" +[versions] +javafx = "17.0.18" +controlsfx = "11.2.2" +jasperreports = "6.21.5" +sqlite = "3.34.0" +olap4j = "1.2.0" +#itext = "2.1.7" +lombok = "1.18.20" +dagger = "2.52" +testfx = "4.0.18" +testfxCore = "4.0.17" +monocle = "17.0.10" +hamcrest = "2.2" +#junit = "5.10.1" +junitbom = "5.10.2" mockito = "5.14.2" slf4j = "2.0.17" log4j = "2.24.3" snakeyaml = "2.3" - -spotless = "7.0.2" -shadow = "7.1.2" -javafxPlugin = "0.1.0" - -[libraries] -controlsfx = { module = "org.controlsfx:controlsfx", version.ref = "controlsfx" } -jasperreports = { module = "net.sf.jasperreports:jasperreports", version.ref = "jasperreports" } -sqlite = { module = "org.xerial:sqlite-jdbc", version.ref = "sqlite" } +jgit = "7.8.1.202611041320-r" + +spotless = "7.0.2" +shadow = "7.1.2" +javafxPlugin = "0.1.0" + +[libraries] +controlsfx = { module = "org.controlsfx:controlsfx", version.ref = "controlsfx" } +jasperreports = { module = "net.sf.jasperreports:jasperreports", version.ref = "jasperreports" } +sqlite = { module = "org.xerial:sqlite-jdbc", version.ref = "sqlite" } olap4j = { module = "org.olap4j:olap4j", version.ref = "olap4j" } slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" } snakeyaml = { module = "org.yaml:snakeyaml", version.ref = "snakeyaml" } log4j-slf4j2-impl = { module = "org.apache.logging.log4j:log4j-slf4j2-impl", version.ref = "log4j" } log4j-core = { module = "org.apache.logging.log4j:log4j-core", version.ref = "log4j" } -#itext = { module = "com.lowagie:itext", version.ref = "itext" } - -javafx-controls = { module = "org.openjfx:javafx-controls", version.ref = "javafx" } -javafx-base = { module = "org.openjfx:javafx-base", version.ref = "javafx" } -javafx-graphics = { module = "org.openjfx:javafx-graphics", version.ref = "javafx" } -javafx-fxml = { module = "org.openjfx:javafx-fxml", version.ref = "javafx" } - -lombok = { module = "org.projectlombok:lombok", version.ref = "lombok" } - -dagger = { module = "com.google.dagger:dagger", version.ref = "dagger" } -dagger-compiler = { module = "com.google.dagger:dagger-compiler", version.ref = "dagger" } - -testfx-junit5 = { module = "org.testfx:testfx-junit5", version.ref = "testfx" } -testfx-core = { module = "org.testfx:testfx-core", version.ref = "testfxCore" } -testfx-monocle = { module = "org.testfx:openjfx-monocle", version.ref = "monocle" } - -hamcrest = { module = "org.hamcrest:hamcrest", version.ref = "hamcrest" } - -#junit-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit" } -#junit-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit" } -junit-bom = { module = "org.junit:junit-bom", version.ref = "junitbom" } -junit-jupiter = { module = "org.junit.jupiter:junit-jupiter" } -junit-platform-launcher = { module = "org.junit.platform:junit-platform-launcher" } - -mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockito" } -mockito-junit-jupiter = { module = "org.mockito:mockito-junit-jupiter", version.ref = "mockito" } - -[plugins] -javafx = { id = "org.openjfx.javafxplugin", version.ref = "javafxPlugin" } -spotless = { id = "com.diffplug.spotless", version.ref = "spotless" } -#shadow = { id = "com.gradleup.shadow", version.ref = "shadow" } +#itext = { module = "com.lowagie:itext", version.ref = "itext" } + +javafx-controls = { module = "org.openjfx:javafx-controls", version.ref = "javafx" } +javafx-base = { module = "org.openjfx:javafx-base", version.ref = "javafx" } +javafx-graphics = { module = "org.openjfx:javafx-graphics", version.ref = "javafx" } +javafx-fxml = { module = "org.openjfx:javafx-fxml", version.ref = "javafx" } + +jgit = { module = "org.eclipse.jgit:org.eclipse.jgit", version.ref = "jgit"} + +lombok = { module = "org.projectlombok:lombok", version.ref = "lombok" } + +dagger = { module = "com.google.dagger:dagger", version.ref = "dagger" } +dagger-compiler = { module = "com.google.dagger:dagger-compiler", version.ref = "dagger" } + +testfx-junit5 = { module = "org.testfx:testfx-junit5", version.ref = "testfx" } +testfx-core = { module = "org.testfx:testfx-core", version.ref = "testfxCore" } +testfx-monocle = { module = "org.testfx:openjfx-monocle", version.ref = "monocle" } + +hamcrest = { module = "org.hamcrest:hamcrest", version.ref = "hamcrest" } + +#junit-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit" } +#junit-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit" } +junit-bom = { module = "org.junit:junit-bom", version.ref = "junitbom" } +junit-jupiter = { module = "org.junit.jupiter:junit-jupiter" } +junit-platform-launcher = { module = "org.junit.platform:junit-platform-launcher" } + +mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockito" } +mockito-junit-jupiter = { module = "org.mockito:mockito-junit-jupiter", version.ref = "mockito" } + +[plugins] +javafx = { id = "org.openjfx.javafxplugin", version.ref = "javafxPlugin" } +spotless = { id = "com.diffplug.spotless", version.ref = "spotless" } +#shadow = { id = "com.gradleup.shadow", version.ref = "shadow" } shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" } diff --git a/src/main/java/openconsignment/common/AppConfig.java b/src/main/java/openconsignment/common/AppConfig.java index 91fce8b..939bb6e 100644 --- a/src/main/java/openconsignment/common/AppConfig.java +++ b/src/main/java/openconsignment/common/AppConfig.java @@ -10,6 +10,7 @@ @NoArgsConstructor public class AppConfig { private String organizationName; + private String githubPAT; public static AppConfig forOrganization(String organizationName) { AppConfig configuration = new AppConfig(); @@ -18,10 +19,6 @@ public static AppConfig forOrganization(String organizationName) { return configuration; } - public String organizationName() { - return organizationName; - } - public void validate() { if (organizationName == null || organizationName.isBlank()) { throw new IllegalArgumentException("organizationName must not be blank"); diff --git a/src/main/java/openconsignment/controller/MainController.java b/src/main/java/openconsignment/controller/MainController.java index 73a0e4e..4b9457c 100644 --- a/src/main/java/openconsignment/controller/MainController.java +++ b/src/main/java/openconsignment/controller/MainController.java @@ -6,11 +6,12 @@ import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.Button; -import javafx.scene.control.MenuItem; import javafx.scene.layout.BorderPane; import javax.inject.Inject; import openconsignment.common.ViewLoader; +import openconsignment.service.BackupService; +@SuppressWarnings("unused") public class MainController implements Initializable { @FXML @@ -25,14 +26,13 @@ public class MainController implements Initializable { @FXML private Button master_btn; - @FXML - private MenuItem welcome_screen; - private final ViewLoader viewLoader; + private final BackupService backupService; @Inject - public MainController(ViewLoader viewLoader) { + public MainController(ViewLoader viewLoader, BackupService backupService) { this.viewLoader = viewLoader; + this.backupService = backupService; } @Override @@ -74,4 +74,54 @@ private void showCollectionHistory(ActionEvent event) { private void showPaymentHistory(ActionEvent event) { viewLoader.loadCenter("/fxml/history/PaymentHistory.fxml", root); } + + @FXML + private void showBillEntryScreen(ActionEvent event) { + viewLoader.loadCenter("/fxml/entry/BillEntry.fxml", root); + } + + @FXML + private void showCollectionEntryScreen(ActionEvent event) { + viewLoader.loadCenter("/fxml/entry/CollectionEntry.fxml", root); + } + + @FXML + private void showPaymentEntryScreen(ActionEvent event) { + viewLoader.loadCenter("/fxml/entry/PaymentEntry.fxml", root); + } + + @FXML + private void showSupplierLedger(ActionEvent event) { + viewLoader.loadCenter("/fxml/report/SupplierLedger.fxml", root); + } + + @FXML + private void showBuyerLedger(ActionEvent event) { + viewLoader.loadCenter("/fxml/report/BuyerLedger.fxml", root); + } + + @FXML + private void showTransportLedger(ActionEvent event) { + viewLoader.loadCenter("/fxml/report/TransportLedger.fxml", root); + } + + @FXML + private void showSupplierMaster(ActionEvent event) { + viewLoader.loadCenter("/fxml/master/MasterSupplier.fxml", root); + } + + @FXML + private void showBuyerMaster(ActionEvent event) { + viewLoader.loadCenter("/fxml/master/MasterBuyer.fxml", root); + } + + @FXML + private void showTransportMaster(ActionEvent event) { + viewLoader.loadCenter("/fxml/master/MasterTransport.fxml", root); + } + + @FXML + private void checkSync(ActionEvent event) { + backupService.checkSync(); + } } diff --git a/src/main/java/openconsignment/controller/WelcomeScreenController.java b/src/main/java/openconsignment/controller/WelcomeScreenController.java index 73e0d70..2f46b9c 100644 --- a/src/main/java/openconsignment/controller/WelcomeScreenController.java +++ b/src/main/java/openconsignment/controller/WelcomeScreenController.java @@ -41,6 +41,6 @@ private void handleOpenGithub(ActionEvent event) { @Override public void initialize(URL url, ResourceBundle rb) { - organization_name.setText(configuration.organizationName()); + organization_name.setText(configuration.getOrganizationName()); } } diff --git a/src/main/java/openconsignment/service/BackupService.java b/src/main/java/openconsignment/service/BackupService.java new file mode 100644 index 0000000..760e611 --- /dev/null +++ b/src/main/java/openconsignment/service/BackupService.java @@ -0,0 +1,63 @@ +package openconsignment.service; + +import java.io.File; +import java.io.IOException; +import javax.inject.Inject; +import javax.inject.Singleton; +import openconsignment.common.AppConfig; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.PullResult; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Singleton +public class BackupService { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + private AppConfig appConfig; + + @Inject + public BackupService(AppConfig appConfig) { + this.appConfig = appConfig; + } + + public boolean checkSync() { + // Implementation for checking sync + logger.info("executing called"); + try { + pull(); + } catch (IOException | GitAPIException e) { + logger.error("Error during git pull", e); + return false; + } + logger.info("checkSync called"); + return true; + } + + public void pull() throws IOException, GitAPIException { + logger.info("executing git pull"); + String repoPath = "Satyam-Database-2026-27"; + String branchName = "main"; + String username = "drcbabu81"; + String token = appConfig.getGithubPAT(); + + logger.info("token is {}", token); + + try (Git git = Git.open(new File(repoPath))) { + + PullResult result = git.pull() + .setRemote("origin") + .setRemoteBranchName(branchName) + .setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, token)) + .call(); + + if (result.isSuccessful()) { + logger.info("Successfully pulled: {}", branchName); + } else { + throw new IllegalStateException("Pull failed for branch: " + branchName); + } + } + } +} diff --git a/src/main/java/openconsignment/service/BuyerService.java b/src/main/java/openconsignment/service/BuyerService.java index 823f1e6..fb2c33d 100644 --- a/src/main/java/openconsignment/service/BuyerService.java +++ b/src/main/java/openconsignment/service/BuyerService.java @@ -49,7 +49,7 @@ public void renameBuyer(String oldName, String newName) throws SQLException { public void generatePdf(String buyerName, boolean isAgewise) throws SQLException, JRException { Map payload = new HashMap<>(); - payload.put(Constants.ORGANIZATION_NAME_KEY, configuration.organizationName()); + payload.put(Constants.ORGANIZATION_NAME_KEY, configuration.getOrganizationName()); payload.put("buyerName", buyerName); if (isAgewise) { diff --git a/src/main/java/openconsignment/service/SupplierService.java b/src/main/java/openconsignment/service/SupplierService.java index 7f8eb0e..9f8175f 100644 --- a/src/main/java/openconsignment/service/SupplierService.java +++ b/src/main/java/openconsignment/service/SupplierService.java @@ -50,7 +50,7 @@ public void renameSupplier(String oldName, String newName) throws SQLException { public void generatePdf(String supplierName, boolean isAgewise) throws SQLException, JRException { Map payload = new HashMap<>(); - payload.put(Constants.ORGANIZATION_NAME_KEY, configuration.organizationName()); + payload.put(Constants.ORGANIZATION_NAME_KEY, configuration.getOrganizationName()); payload.put("supplierName", supplierName); if (isAgewise) { diff --git a/src/main/java/openconsignment/service/TransportService.java b/src/main/java/openconsignment/service/TransportService.java index 8007adc..dfe86e0 100644 --- a/src/main/java/openconsignment/service/TransportService.java +++ b/src/main/java/openconsignment/service/TransportService.java @@ -46,7 +46,7 @@ public void generatePdf(String transportName, String fromDate, String toDate) th transportRepository.getTransportReportFor(transportName, fromDate, toDate); Map payload = new HashMap<>(); - payload.put(Constants.ORGANIZATION_NAME_KEY, configuration.organizationName()); + payload.put(Constants.ORGANIZATION_NAME_KEY, configuration.getOrganizationName()); payload.put("transportName", transportName); payload.put("fromDate", fromDate); payload.put("toDate", toDate); diff --git a/src/main/resources/fxml/Main.fxml b/src/main/resources/fxml/Main.fxml index 6357a76..3990073 100644 --- a/src/main/resources/fxml/Main.fxml +++ b/src/main/resources/fxml/Main.fxml @@ -1,97 +1,144 @@ - - - - - - - - - - - -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/src/main/resources/fxml/report/BuyerLedger.fxml b/src/main/resources/fxml/report/BuyerLedger.fxml index d01305e..47ea9e7 100644 --- a/src/main/resources/fxml/report/BuyerLedger.fxml +++ b/src/main/resources/fxml/report/BuyerLedger.fxml @@ -3,12 +3,11 @@ - - + + @@ -50,4 +49,4 @@ - + diff --git a/src/main/resources/fxml/report/SupplierLedger.fxml b/src/main/resources/fxml/report/SupplierLedger.fxml index 4745eb1..3e8c83c 100644 --- a/src/main/resources/fxml/report/SupplierLedger.fxml +++ b/src/main/resources/fxml/report/SupplierLedger.fxml @@ -3,12 +3,11 @@ - - + + @@ -51,4 +50,4 @@ - + diff --git a/src/main/resources/fxml/report/TransportLedger.fxml b/src/main/resources/fxml/report/TransportLedger.fxml index 01aa234..02caf53 100644 --- a/src/main/resources/fxml/report/TransportLedger.fxml +++ b/src/main/resources/fxml/report/TransportLedger.fxml @@ -3,12 +3,11 @@ - - + + @@ -48,4 +47,4 @@ - + diff --git a/src/test/java/openconsignment/di/ConfigurationModuleTest.java b/src/test/java/openconsignment/di/ConfigurationModuleTest.java index 0a09125..63e681e 100644 --- a/src/test/java/openconsignment/di/ConfigurationModuleTest.java +++ b/src/test/java/openconsignment/di/ConfigurationModuleTest.java @@ -30,7 +30,7 @@ void missingFileIsCopiedFromBundledResourceAndLoaded() throws IOException { AppConfig configuration = load(file); assertEquals(bundled, Files.readString(file)); - assertEquals(configuration.organizationName(), load(file).organizationName()); + assertEquals(configuration.getOrganizationName(), load(file).getOrganizationName()); } @Test @@ -45,7 +45,7 @@ void emptyExistingFileIsRejectedAndPreserved() throws IOException { void loadsUtf8OrganizationNameAndTrimsWhitespace() throws IOException { Path file = Files.writeString(tempDir.resolve("application.yaml"), "organizationName: \" Café Agencies \"\n"); - assertEquals("Café Agencies", load(file).organizationName()); + assertEquals("Café Agencies", load(file).getOrganizationName()); } @Test @@ -55,8 +55,8 @@ void loadedConfigurationDoesNotChangeWhenFileIsEdited() throws IOException { Files.writeString(file, "organizationName: Second\n"); - assertEquals("First", configuration.organizationName()); - assertEquals("Second", load(file).organizationName()); + assertEquals("First", configuration.getOrganizationName()); + assertEquals("Second", load(file).getOrganizationName()); } @Test @@ -86,7 +86,7 @@ void existingConfigurationIsLoadedWithoutBeingOverwritten() throws IOException { String content = "# Custom settings\norganizationName: External Organization\n"; Path file = Files.writeString(tempDir.resolve("application.yaml"), content); - assertEquals("External Organization", load(file).organizationName()); + assertEquals("External Organization", load(file).getOrganizationName()); assertEquals(content, Files.readString(file)); } @@ -136,7 +136,7 @@ void developmentRunUsesConfigurationInWorkingDirectory() throws IOException { void bindsNumericScalarToStringProperty() throws IOException { Path file = Files.writeString(tempDir.resolve("application.yaml"), "organizationName: 123\n"); - assertEquals("123", load(file).organizationName()); + assertEquals("123", load(file).getOrganizationName()); } @Test From 95acf0ebb8516f1697c6745c57c288f74acefa40 Mon Sep 17 00:00:00 2001 From: Rajdeep Roy Chowdhury Date: Wed, 11 Nov 2026 00:10:11 +0530 Subject: [PATCH 02/11] feat: improved application.yaml Signed-off-by: Rajdeep Roy Chowdhury --- .../java/openconsignment/common/AppConfig.java | 14 +++++++++++++- .../openconsignment/service/BackupService.java | 13 ++++++++----- src/main/resources/application.yaml | 6 ++++++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/main/java/openconsignment/common/AppConfig.java b/src/main/java/openconsignment/common/AppConfig.java index 939bb6e..35bf0db 100644 --- a/src/main/java/openconsignment/common/AppConfig.java +++ b/src/main/java/openconsignment/common/AppConfig.java @@ -10,7 +10,8 @@ @NoArgsConstructor public class AppConfig { private String organizationName; - private String githubPAT; + private String financialYear; + private Github github; public static AppConfig forOrganization(String organizationName) { AppConfig configuration = new AppConfig(); @@ -19,6 +20,17 @@ public static AppConfig forOrganization(String organizationName) { return configuration; } + @Getter + @Setter + @NoArgsConstructor + public static class Github { + private String repoName; + private String token; + private String username; + private String branchName; + private String remoteName; + } + public void validate() { if (organizationName == null || organizationName.isBlank()) { throw new IllegalArgumentException("organizationName must not be blank"); diff --git a/src/main/java/openconsignment/service/BackupService.java b/src/main/java/openconsignment/service/BackupService.java index 760e611..c273187 100644 --- a/src/main/java/openconsignment/service/BackupService.java +++ b/src/main/java/openconsignment/service/BackupService.java @@ -38,17 +38,20 @@ public boolean checkSync() { public void pull() throws IOException, GitAPIException { logger.info("executing git pull"); - String repoPath = "Satyam-Database-2026-27"; - String branchName = "main"; - String username = "drcbabu81"; - String token = appConfig.getGithubPAT(); + + AppConfig.Github github = appConfig.getGithub(); + String repoPath = github.getRepoName(); + String username = github.getUsername(); + String token = github.getToken(); + String branchName = github.getBranchName(); + String remoteName = github.getRemoteName(); logger.info("token is {}", token); try (Git git = Git.open(new File(repoPath))) { PullResult result = git.pull() - .setRemote("origin") + .setRemote(remoteName) .setRemoteBranchName(branchName) .setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, token)) .call(); diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index aada7ee..a239e1c 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1 +1,7 @@ organizationName: "SATYAM AGENCIES" +github: + token: "" + username: "drcbabu81" + branchName: "main" + remoteName: "origin-https" + repoName: "Satyam-Database-2026-27" \ No newline at end of file From b8e636ddb1a4af844a118bb8c2d9deb7a152cb81 Mon Sep 17 00:00:00 2001 From: Rajdeep Roy Chowdhury Date: Wed, 11 Nov 2026 18:19:19 +0530 Subject: [PATCH 03/11] feat: added code related hash compare Signed-off-by: Rajdeep Roy Chowdhury --- scripts/configure-backup.py | 9 +++++++++ .../java/openconsignment/common/Utils.java | 20 +++++++++++++++++++ .../service/BackupService.java | 20 ++++++++++++++++++- 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/scripts/configure-backup.py b/scripts/configure-backup.py index 28a5ce9..df7b9ae 100755 --- a/scripts/configure-backup.py +++ b/scripts/configure-backup.py @@ -69,6 +69,7 @@ def init_github_repository(): return github_username = "drcbabu81" repo_url = f"git@github.com:{github_username}/{repo_name}.git" + repo_url_https = f"https://github.com/{github_username}/{repo_name}.git" try: logger.info(f"cloning {repo_name}") @@ -76,6 +77,14 @@ def init_github_repository(): ["git", "clone", repo_url], check=True, capture_output=True, text=True ) + repo_path = os.path.abspath(repo_name) + + subprocess.run( + ["git", "remote", "add", "origin-https", repo_url_https], + cwd=repo_path, + check=True, capture_output=True, text=True + ) + if (Path(repo_name) / ".git").is_dir(): logger.info("clone successful") else: diff --git a/src/main/java/openconsignment/common/Utils.java b/src/main/java/openconsignment/common/Utils.java index a1f3a42..81d56b0 100644 --- a/src/main/java/openconsignment/common/Utils.java +++ b/src/main/java/openconsignment/common/Utils.java @@ -3,11 +3,16 @@ import java.awt.*; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.MessageDigest; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; +import java.util.HexFormat; import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -118,4 +123,19 @@ public static String nextVoucherNumber(String lastVoucher) { return "0"; } } + + public static String md5sum(Path path) throws Exception { + MessageDigest digest = MessageDigest.getInstance("MD5"); + + try (InputStream input = Files.newInputStream(path)) { + byte[] buffer = new byte[8192]; + int bytesRead; + + while ((bytesRead = input.read(buffer)) != -1) { + digest.update(buffer, 0, bytesRead); + } + } + + return HexFormat.of().formatHex(digest.digest()); + } } diff --git a/src/main/java/openconsignment/service/BackupService.java b/src/main/java/openconsignment/service/BackupService.java index c273187..a09a5a7 100644 --- a/src/main/java/openconsignment/service/BackupService.java +++ b/src/main/java/openconsignment/service/BackupService.java @@ -2,9 +2,12 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Path; import javax.inject.Inject; import javax.inject.Singleton; import openconsignment.common.AppConfig; +import openconsignment.common.Constants; +import openconsignment.common.Utils; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.PullResult; import org.eclipse.jgit.api.errors.GitAPIException; @@ -33,7 +36,22 @@ public boolean checkSync() { return false; } logger.info("checkSync called"); - return true; + + try { + String localFileHash = Utils.md5sum(Path.of(Constants.DATABASE_FILE_NAME)); + String repoFileHash = + Utils.md5sum(Path.of(appConfig.getGithub().getRepoName() + "/" + Constants.DATABASE_FILE_NAME)); + boolean result = 0 == localFileHash.compareTo(repoFileHash); + logger.info( + "Checksync result = {}, localFileHash = {}, repoFileHash = {}", + result, + localFileHash, + repoFileHash); + return result; + } catch (Exception ex) { + logger.error(ex.toString()); + return false; + } } public void pull() throws IOException, GitAPIException { From 39ab2f9c8ab52ec48d1eeec05a391b60c665faf9 Mon Sep 17 00:00:00 2001 From: Rajdeep Roy Chowdhury Date: Thu, 12 Nov 2026 10:37:08 +0530 Subject: [PATCH 04/11] feat: ui feedback added Signed-off-by: Rajdeep Roy Chowdhury --- .../controller/MainController.java | 15 ++++++++- .../report/SupplierLedgerController.java | 11 +++---- .../service/BackupService.java | 31 +++++++++---------- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/src/main/java/openconsignment/controller/MainController.java b/src/main/java/openconsignment/controller/MainController.java index 4b9457c..eab93cb 100644 --- a/src/main/java/openconsignment/controller/MainController.java +++ b/src/main/java/openconsignment/controller/MainController.java @@ -5,9 +5,11 @@ import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.Initializable; +import javafx.scene.control.Alert; import javafx.scene.control.Button; import javafx.scene.layout.BorderPane; import javax.inject.Inject; +import openconsignment.common.Utils; import openconsignment.common.ViewLoader; import openconsignment.service.BackupService; @@ -122,6 +124,17 @@ private void showTransportMaster(ActionEvent event) { @FXML private void checkSync(ActionEvent event) { - backupService.checkSync(); + boolean synced = false; + try { + synced = backupService.checkSync(); + } catch (Exception e) { + Utils.showAlert("Error", Alert.AlertType.ERROR); + } + + if (synced) { + Utils.showAlert("Data is Synced", Alert.AlertType.INFORMATION); + } else { + Utils.showAlert("Not Synced", Alert.AlertType.WARNING); + } } } diff --git a/src/main/java/openconsignment/controller/report/SupplierLedgerController.java b/src/main/java/openconsignment/controller/report/SupplierLedgerController.java index 340d15c..7f552c8 100644 --- a/src/main/java/openconsignment/controller/report/SupplierLedgerController.java +++ b/src/main/java/openconsignment/controller/report/SupplierLedgerController.java @@ -15,15 +15,14 @@ import javafx.scene.control.RadioButton; import javafx.scene.control.ToggleGroup; import javax.inject.Inject; +import lombok.extern.slf4j.Slf4j; import net.sf.jasperreports.engine.*; import openconsignment.common.Constants; import openconsignment.common.Utils; import openconsignment.service.SupplierService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +@Slf4j public class SupplierLedgerController implements Initializable { - private static final Logger logger = LoggerFactory.getLogger(SupplierLedgerController.class); @FXML private ComboBox supplier_name_combo; @@ -57,7 +56,7 @@ public void initialize(URL url, ResourceBundle rb) { supplier_name_combo.setItems(FXCollections.observableArrayList(supplierList)); } catch (SQLException ex) { Utils.showAlert(ex.toString()); - logger.error(ex.toString(), ex); + log.error(ex.toString(), ex); } } @@ -70,7 +69,7 @@ private void generatePDF(ActionEvent event) { Utils.showAlert("Report Successfully Generated", AlertType.INFORMATION); } catch (IOException | SQLException | JRException ex) { Utils.showAlert(ex.toString()); - logger.error(ex.toString(), ex); + log.error(ex.toString(), ex); } } @@ -81,7 +80,7 @@ private void launchPdf(ActionEvent event) { Utils.showAlert("PDF opened successfully.", AlertType.INFORMATION); } catch (IOException ex) { Utils.showAlert(ex.toString()); - logger.error(ex.toString(), ex); + log.error(ex.toString(), ex); } } } diff --git a/src/main/java/openconsignment/service/BackupService.java b/src/main/java/openconsignment/service/BackupService.java index a09a5a7..ef95c25 100644 --- a/src/main/java/openconsignment/service/BackupService.java +++ b/src/main/java/openconsignment/service/BackupService.java @@ -5,6 +5,7 @@ import java.nio.file.Path; import javax.inject.Inject; import javax.inject.Singleton; +import lombok.extern.slf4j.Slf4j; import openconsignment.common.AppConfig; import openconsignment.common.Constants; import openconsignment.common.Utils; @@ -12,50 +13,48 @@ import org.eclipse.jgit.api.PullResult; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +@Slf4j @Singleton public class BackupService { - private Logger logger = LoggerFactory.getLogger(this.getClass()); - private AppConfig appConfig; + private final AppConfig appConfig; @Inject public BackupService(AppConfig appConfig) { this.appConfig = appConfig; } - public boolean checkSync() { + public boolean checkSync() throws Exception { // Implementation for checking sync - logger.info("executing called"); + log.info("executing called"); try { pull(); } catch (IOException | GitAPIException e) { - logger.error("Error during git pull", e); - return false; + log.error("Error during git pull", e); + throw e; } - logger.info("checkSync called"); + log.info("checkSync called"); try { String localFileHash = Utils.md5sum(Path.of(Constants.DATABASE_FILE_NAME)); String repoFileHash = Utils.md5sum(Path.of(appConfig.getGithub().getRepoName() + "/" + Constants.DATABASE_FILE_NAME)); boolean result = 0 == localFileHash.compareTo(repoFileHash); - logger.info( - "Checksync result = {}, localFileHash = {}, repoFileHash = {}", + log.info( + "CheckSync result = {}, localFileHash = {}, repoFileHash = {}", result, localFileHash, repoFileHash); return result; } catch (Exception ex) { - logger.error(ex.toString()); - return false; + log.error(ex.toString()); + throw ex; } } public void pull() throws IOException, GitAPIException { - logger.info("executing git pull"); + log.info("executing git pull"); AppConfig.Github github = appConfig.getGithub(); String repoPath = github.getRepoName(); @@ -64,7 +63,7 @@ public void pull() throws IOException, GitAPIException { String branchName = github.getBranchName(); String remoteName = github.getRemoteName(); - logger.info("token is {}", token); + log.info("token is {}", token); try (Git git = Git.open(new File(repoPath))) { @@ -75,7 +74,7 @@ public void pull() throws IOException, GitAPIException { .call(); if (result.isSuccessful()) { - logger.info("Successfully pulled: {}", branchName); + log.info("Successfully pulled: {}", branchName); } else { throw new IllegalStateException("Pull failed for branch: " + branchName); } From 1dcc03aa853d939087471a9bfff1f1ca4a1fce84 Mon Sep 17 00:00:00 2001 From: Rajdeep Roy Chowdhury Date: Thu, 12 Nov 2026 11:04:59 +0530 Subject: [PATCH 05/11] feat: partially implemented upload Signed-off-by: Rajdeep Roy Chowdhury --- .../controller/MainController.java | 16 ++++++ .../service/BackupService.java | 53 ++++++++++++------- src/main/resources/fxml/Main.fxml | 2 +- 3 files changed, 52 insertions(+), 19 deletions(-) diff --git a/src/main/java/openconsignment/controller/MainController.java b/src/main/java/openconsignment/controller/MainController.java index eab93cb..f79a285 100644 --- a/src/main/java/openconsignment/controller/MainController.java +++ b/src/main/java/openconsignment/controller/MainController.java @@ -7,6 +7,7 @@ import javafx.fxml.Initializable; import javafx.scene.control.Alert; import javafx.scene.control.Button; +import javafx.scene.control.ButtonType; import javafx.scene.layout.BorderPane; import javax.inject.Inject; import openconsignment.common.Utils; @@ -137,4 +138,19 @@ private void checkSync(ActionEvent event) { Utils.showAlert("Not Synced", Alert.AlertType.WARNING); } } + + @FXML + private void upload(ActionEvent event) { + try { + Alert alert = + new Alert(Alert.AlertType.CONFIRMATION, "Do you want to upload?", ButtonType.YES, ButtonType.NO); + if (alert.showAndWait().orElse(ButtonType.NO) != ButtonType.YES) { + return; + } + backupService.push(); + Utils.showAlert("Successfully uploaded", Alert.AlertType.INFORMATION); + } catch (Exception e) { + Utils.showAlert("Error", Alert.AlertType.ERROR); + } + } } diff --git a/src/main/java/openconsignment/service/BackupService.java b/src/main/java/openconsignment/service/BackupService.java index ef95c25..7011c06 100644 --- a/src/main/java/openconsignment/service/BackupService.java +++ b/src/main/java/openconsignment/service/BackupService.java @@ -12,6 +12,7 @@ import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.PullResult; import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.transport.PushResult; import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; @Slf4j @@ -26,31 +27,23 @@ public BackupService(AppConfig appConfig) { } public boolean checkSync() throws Exception { - // Implementation for checking sync log.info("executing called"); try { pull(); - } catch (IOException | GitAPIException e) { + return compareDatabaseHashes(); + } catch (Exception e) { log.error("Error during git pull", e); throw e; } - log.info("checkSync called"); + } - try { - String localFileHash = Utils.md5sum(Path.of(Constants.DATABASE_FILE_NAME)); - String repoFileHash = - Utils.md5sum(Path.of(appConfig.getGithub().getRepoName() + "/" + Constants.DATABASE_FILE_NAME)); - boolean result = 0 == localFileHash.compareTo(repoFileHash); - log.info( - "CheckSync result = {}, localFileHash = {}, repoFileHash = {}", - result, - localFileHash, - repoFileHash); - return result; - } catch (Exception ex) { - log.error(ex.toString()); - throw ex; - } + public boolean compareDatabaseHashes() throws Exception { + String localFileHash = Utils.md5sum(Path.of(Constants.DATABASE_FILE_NAME)); + String repoFileHash = + Utils.md5sum(Path.of(appConfig.getGithub().getRepoName() + "/" + Constants.DATABASE_FILE_NAME)); + boolean result = 0 == localFileHash.compareTo(repoFileHash); + log.info("CheckSync result = {}, localFileHash = {}, repoFileHash = {}", result, localFileHash, repoFileHash); + return result; } public void pull() throws IOException, GitAPIException { @@ -80,4 +73,28 @@ public void pull() throws IOException, GitAPIException { } } } + + public void push() throws IOException, GitAPIException { + log.info("executing git push"); + + AppConfig.Github github = appConfig.getGithub(); + String repoPath = github.getRepoName(); + String username = github.getUsername(); + String token = github.getToken(); + String branchName = github.getBranchName(); + String remoteName = github.getRemoteName(); + + log.info("token is {}", token); + + try (Git git = Git.open(new File(repoPath))) { + Iterable results = git.push() + .setRemote(remoteName) + .setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, token)) + .call(); + + for (PushResult result : results) { + log.info(result.getMessages()); + } + } + } } diff --git a/src/main/resources/fxml/Main.fxml b/src/main/resources/fxml/Main.fxml index 3990073..b3a5781 100644 --- a/src/main/resources/fxml/Main.fxml +++ b/src/main/resources/fxml/Main.fxml @@ -64,7 +64,7 @@ - + From abb8ba2d78e072f2e4ae978a24ffe1fc48acb878 Mon Sep 17 00:00:00 2001 From: Rajdeep Roy Chowdhury Date: Thu, 12 Nov 2026 11:28:33 +0530 Subject: [PATCH 06/11] test: test repo added Signed-off-by: Rajdeep Roy Chowdhury --- src/main/resources/application.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index a239e1c..f87a711 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,7 +1,7 @@ organizationName: "SATYAM AGENCIES" github: token: "" - username: "drcbabu81" + username: "razdeep" branchName: "main" remoteName: "origin-https" - repoName: "Satyam-Database-2026-27" \ No newline at end of file + repoName: "Satyam-Database-2001-02" \ No newline at end of file From 78826516a18e6e7cb51600a6270b8d990a0bac28 Mon Sep 17 00:00:00 2001 From: Rajdeep Roy Chowdhury Date: Fri, 13 Nov 2026 10:21:47 +0530 Subject: [PATCH 07/11] feat: download feature added Signed-off-by: Rajdeep Roy Chowdhury --- .../controller/MainController.java | 22 ++++++- .../service/BackupService.java | 61 ++++++++++++++++++- src/main/resources/fxml/Main.fxml | 2 +- 3 files changed, 80 insertions(+), 5 deletions(-) diff --git a/src/main/java/openconsignment/controller/MainController.java b/src/main/java/openconsignment/controller/MainController.java index f79a285..80a3151 100644 --- a/src/main/java/openconsignment/controller/MainController.java +++ b/src/main/java/openconsignment/controller/MainController.java @@ -10,10 +10,12 @@ import javafx.scene.control.ButtonType; import javafx.scene.layout.BorderPane; import javax.inject.Inject; +import lombok.extern.slf4j.Slf4j; import openconsignment.common.Utils; import openconsignment.common.ViewLoader; import openconsignment.service.BackupService; +@Slf4j @SuppressWarnings("unused") public class MainController implements Initializable { @@ -147,10 +149,26 @@ private void upload(ActionEvent event) { if (alert.showAndWait().orElse(ButtonType.NO) != ButtonType.YES) { return; } - backupService.push(); + backupService.upload(); Utils.showAlert("Successfully uploaded", Alert.AlertType.INFORMATION); } catch (Exception e) { - Utils.showAlert("Error", Alert.AlertType.ERROR); + log.error(e.toString()); + Utils.showAlert(e.toString(), Alert.AlertType.ERROR); + } + } + + public void download(ActionEvent actionEvent) { + try { + Alert alert = + new Alert(Alert.AlertType.CONFIRMATION, "Do you want to download?", ButtonType.YES, ButtonType.NO); + if (alert.showAndWait().orElse(ButtonType.NO) != ButtonType.YES) { + return; + } + backupService.download(); + Utils.showAlert("Successfully downloaded", Alert.AlertType.INFORMATION); + } catch (Exception e) { + log.error(e.toString()); + Utils.showAlert(e.toString(), Alert.AlertType.ERROR); } } } diff --git a/src/main/java/openconsignment/service/BackupService.java b/src/main/java/openconsignment/service/BackupService.java index 7011c06..d11dd1c 100644 --- a/src/main/java/openconsignment/service/BackupService.java +++ b/src/main/java/openconsignment/service/BackupService.java @@ -2,7 +2,9 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.StandardCopyOption; import javax.inject.Inject; import javax.inject.Singleton; import lombok.extern.slf4j.Slf4j; @@ -12,6 +14,7 @@ import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.PullResult; import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.transport.PushResult; import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; @@ -46,7 +49,19 @@ public boolean compareDatabaseHashes() throws Exception { return result; } - public void pull() throws IOException, GitAPIException { + private void copyRepoToLocal() throws IOException { + AppConfig.Github github = appConfig.getGithub(); + String repoPath = github.getRepoName(); + + log.info("Copying {} to {}", repoPath, Constants.DATABASE_FILE_NAME); + Files.copy( + Path.of(new File(repoPath + "/" + Constants.DATABASE_FILE_NAME).toURI()), + Path.of(new File(Constants.DATABASE_FILE_NAME).toURI()), + StandardCopyOption.REPLACE_EXISTING); + log.info("Copied {} to {}", repoPath, Constants.DATABASE_FILE_NAME); + } + + private void pull() throws IOException, GitAPIException { log.info("executing git pull"); AppConfig.Github github = appConfig.getGithub(); @@ -74,7 +89,43 @@ public void pull() throws IOException, GitAPIException { } } - public void push() throws IOException, GitAPIException { + public void download() throws GitAPIException, IOException { + pull(); + copyRepoToLocal(); + } + + private void copyLocalToRepo() throws IOException { + AppConfig.Github github = appConfig.getGithub(); + String repoPath = github.getRepoName(); + + log.info("Copying {} to {}", Constants.DATABASE_FILE_NAME, repoPath); + Files.copy( + Path.of(new File(Constants.DATABASE_FILE_NAME).toURI()), + Path.of(new File(repoPath + "/" + Constants.DATABASE_FILE_NAME).toURI()), + StandardCopyOption.REPLACE_EXISTING); + log.info("Copied {} to {}", Constants.DATABASE_FILE_NAME, repoPath); + } + + private void addAndCommit() throws IOException, GitAPIException { + + log.info("executing add and commit"); + + AppConfig.Github github = appConfig.getGithub(); + String repoPath = github.getRepoName(); + + try (Git git = Git.open(new File(repoPath))) { + + // Stage changes + git.add().addFilepattern(".").call(); + + // Commit changes + RevCommit commit = git.commit().setMessage("Automated backup").call(); + + log.info("Commit: " + commit.getId().getName()); + } + } + + private void push() throws IOException, GitAPIException { log.info("executing git push"); AppConfig.Github github = appConfig.getGithub(); @@ -97,4 +148,10 @@ public void push() throws IOException, GitAPIException { } } } + + public void upload() throws GitAPIException, IOException { + copyLocalToRepo(); + addAndCommit(); + push(); + } } diff --git a/src/main/resources/fxml/Main.fxml b/src/main/resources/fxml/Main.fxml index b3a5781..2f6c3a9 100644 --- a/src/main/resources/fxml/Main.fxml +++ b/src/main/resources/fxml/Main.fxml @@ -65,7 +65,7 @@ - + From 3b2fcea982887e7a802b4c92ed3ce6f6f60c608d Mon Sep 17 00:00:00 2001 From: Rajdeep Roy Chowdhury Date: Sat, 14 Nov 2026 19:41:17 +0530 Subject: [PATCH 08/11] fix: empty commit bug fixed Signed-off-by: Rajdeep Roy Chowdhury --- .../controller/MainController.java | 4 +++ .../service/BackupService.java | 25 ++++++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/main/java/openconsignment/controller/MainController.java b/src/main/java/openconsignment/controller/MainController.java index 80a3151..b3420d8 100644 --- a/src/main/java/openconsignment/controller/MainController.java +++ b/src/main/java/openconsignment/controller/MainController.java @@ -14,6 +14,7 @@ import openconsignment.common.Utils; import openconsignment.common.ViewLoader; import openconsignment.service.BackupService; +import org.eclipse.jgit.api.errors.EmptyCommitException; @Slf4j @SuppressWarnings("unused") @@ -151,6 +152,9 @@ private void upload(ActionEvent event) { } backupService.upload(); Utils.showAlert("Successfully uploaded", Alert.AlertType.INFORMATION); + } catch (EmptyCommitException e) { + log.info(e.toString()); + Utils.showAlert("Data is already synced. " + e, Alert.AlertType.INFORMATION); } catch (Exception e) { log.error(e.toString()); Utils.showAlert(e.toString(), Alert.AlertType.ERROR); diff --git a/src/main/java/openconsignment/service/BackupService.java b/src/main/java/openconsignment/service/BackupService.java index d11dd1c..87d8b1a 100644 --- a/src/main/java/openconsignment/service/BackupService.java +++ b/src/main/java/openconsignment/service/BackupService.java @@ -5,6 +5,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import javax.inject.Inject; import javax.inject.Singleton; import lombok.extern.slf4j.Slf4j; @@ -40,10 +42,14 @@ public boolean checkSync() throws Exception { } } + private String getRepoFileHash() throws Exception { + return Utils.md5sum(Path.of(appConfig.getGithub().getRepoName() + "/" + Constants.DATABASE_FILE_NAME)); + } + public boolean compareDatabaseHashes() throws Exception { String localFileHash = Utils.md5sum(Path.of(Constants.DATABASE_FILE_NAME)); - String repoFileHash = - Utils.md5sum(Path.of(appConfig.getGithub().getRepoName() + "/" + Constants.DATABASE_FILE_NAME)); + String repoFileHash = getRepoFileHash(); + boolean result = 0 == localFileHash.compareTo(repoFileHash); log.info("CheckSync result = {}, localFileHash = {}, repoFileHash = {}", result, localFileHash, repoFileHash); return result; @@ -118,8 +124,21 @@ private void addAndCommit() throws IOException, GitAPIException { // Stage changes git.add().addFilepattern(".").call(); + // Current time in string + String currentTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + String repoFileHash = "null"; + try { + repoFileHash = getRepoFileHash(); + } catch (Exception e) { + log.error(e.toString()); + } + + String message = "Backed up at " + currentTime + "; database hash = " + repoFileHash; + // Commit changes - RevCommit commit = git.commit().setMessage("Automated backup").call(); + RevCommit commit = + git.commit().setMessage(message).setAllowEmpty(false).call(); log.info("Commit: " + commit.getId().getName()); } From 4b35edd912a58d05d293a88b69f7f0277cb6817e Mon Sep 17 00:00:00 2001 From: Rajdeep Roy Chowdhury Date: Sat, 14 Nov 2026 20:00:58 +0530 Subject: [PATCH 09/11] feat: yaml config formalized Signed-off-by: Rajdeep Roy Chowdhury --- .../openconsignment/common/AppConfig.java | 18 ++++---- .../controller/WelcomeScreenController.java | 9 ++-- .../service/BackupService.java | 20 ++++----- .../openconsignment/service/BuyerService.java | 2 +- .../service/SupplierService.java | 2 +- .../service/TransportService.java | 2 +- src/main/resources/application.yaml | 9 ++-- .../di/ConfigurationModuleTest.java | 42 +++++++++---------- 8 files changed, 52 insertions(+), 52 deletions(-) diff --git a/src/main/java/openconsignment/common/AppConfig.java b/src/main/java/openconsignment/common/AppConfig.java index 35bf0db..ec59801 100644 --- a/src/main/java/openconsignment/common/AppConfig.java +++ b/src/main/java/openconsignment/common/AppConfig.java @@ -9,13 +9,13 @@ @Setter @NoArgsConstructor public class AppConfig { - private String organizationName; - private String financialYear; + private String organization; + private String year; private Github github; public static AppConfig forOrganization(String organizationName) { AppConfig configuration = new AppConfig(); - configuration.setOrganizationName(organizationName); + configuration.setOrganization(organizationName); configuration.validate(); return configuration; } @@ -24,17 +24,17 @@ public static AppConfig forOrganization(String organizationName) { @Setter @NoArgsConstructor public static class Github { - private String repoName; + private String repository; private String token; private String username; - private String branchName; - private String remoteName; + private String branch; + private String remote; } public void validate() { - if (organizationName == null || organizationName.isBlank()) { - throw new IllegalArgumentException("organizationName must not be blank"); + if (organization == null || organization.isBlank()) { + throw new IllegalArgumentException("organization must not be blank"); } - organizationName = organizationName.strip(); + organization = organization.strip(); } } diff --git a/src/main/java/openconsignment/controller/WelcomeScreenController.java b/src/main/java/openconsignment/controller/WelcomeScreenController.java index 2f46b9c..937816d 100644 --- a/src/main/java/openconsignment/controller/WelcomeScreenController.java +++ b/src/main/java/openconsignment/controller/WelcomeScreenController.java @@ -9,13 +9,12 @@ import javafx.scene.control.Hyperlink; import javafx.scene.text.Text; import javax.inject.Inject; +import lombok.extern.slf4j.Slf4j; import openconsignment.common.AppConfig; import openconsignment.common.Utils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +@Slf4j public class WelcomeScreenController implements Initializable { - private static final Logger logger = LoggerFactory.getLogger(WelcomeScreenController.class); private final AppConfig configuration; @FXML @@ -35,12 +34,12 @@ private void handleOpenGithub(ActionEvent event) { Utils.launchBrowser(url); } catch (IOException ex) { Utils.showAlert(ex.toString()); - logger.error(ex.toString(), ex); + log.error(ex.toString(), ex); } } @Override public void initialize(URL url, ResourceBundle rb) { - organization_name.setText(configuration.getOrganizationName()); + organization_name.setText(configuration.getOrganization()); } } diff --git a/src/main/java/openconsignment/service/BackupService.java b/src/main/java/openconsignment/service/BackupService.java index 87d8b1a..a0fb714 100644 --- a/src/main/java/openconsignment/service/BackupService.java +++ b/src/main/java/openconsignment/service/BackupService.java @@ -43,7 +43,7 @@ public boolean checkSync() throws Exception { } private String getRepoFileHash() throws Exception { - return Utils.md5sum(Path.of(appConfig.getGithub().getRepoName() + "/" + Constants.DATABASE_FILE_NAME)); + return Utils.md5sum(Path.of(appConfig.getGithub().getRepository() + "/" + Constants.DATABASE_FILE_NAME)); } public boolean compareDatabaseHashes() throws Exception { @@ -57,7 +57,7 @@ public boolean compareDatabaseHashes() throws Exception { private void copyRepoToLocal() throws IOException { AppConfig.Github github = appConfig.getGithub(); - String repoPath = github.getRepoName(); + String repoPath = github.getRepository(); log.info("Copying {} to {}", repoPath, Constants.DATABASE_FILE_NAME); Files.copy( @@ -71,11 +71,11 @@ private void pull() throws IOException, GitAPIException { log.info("executing git pull"); AppConfig.Github github = appConfig.getGithub(); - String repoPath = github.getRepoName(); + String repoPath = github.getRepository(); String username = github.getUsername(); String token = github.getToken(); - String branchName = github.getBranchName(); - String remoteName = github.getRemoteName(); + String branchName = github.getBranch(); + String remoteName = github.getRemote(); log.info("token is {}", token); @@ -102,7 +102,7 @@ public void download() throws GitAPIException, IOException { private void copyLocalToRepo() throws IOException { AppConfig.Github github = appConfig.getGithub(); - String repoPath = github.getRepoName(); + String repoPath = github.getRepository(); log.info("Copying {} to {}", Constants.DATABASE_FILE_NAME, repoPath); Files.copy( @@ -117,7 +117,7 @@ private void addAndCommit() throws IOException, GitAPIException { log.info("executing add and commit"); AppConfig.Github github = appConfig.getGithub(); - String repoPath = github.getRepoName(); + String repoPath = github.getRepository(); try (Git git = Git.open(new File(repoPath))) { @@ -148,11 +148,11 @@ private void push() throws IOException, GitAPIException { log.info("executing git push"); AppConfig.Github github = appConfig.getGithub(); - String repoPath = github.getRepoName(); + String repoPath = github.getRepository(); String username = github.getUsername(); String token = github.getToken(); - String branchName = github.getBranchName(); - String remoteName = github.getRemoteName(); + String branchName = github.getBranch(); + String remoteName = github.getRemote(); log.info("token is {}", token); diff --git a/src/main/java/openconsignment/service/BuyerService.java b/src/main/java/openconsignment/service/BuyerService.java index fb2c33d..7eb6aa4 100644 --- a/src/main/java/openconsignment/service/BuyerService.java +++ b/src/main/java/openconsignment/service/BuyerService.java @@ -49,7 +49,7 @@ public void renameBuyer(String oldName, String newName) throws SQLException { public void generatePdf(String buyerName, boolean isAgewise) throws SQLException, JRException { Map payload = new HashMap<>(); - payload.put(Constants.ORGANIZATION_NAME_KEY, configuration.getOrganizationName()); + payload.put(Constants.ORGANIZATION_NAME_KEY, configuration.getOrganization()); payload.put("buyerName", buyerName); if (isAgewise) { diff --git a/src/main/java/openconsignment/service/SupplierService.java b/src/main/java/openconsignment/service/SupplierService.java index 9f8175f..a476ff3 100644 --- a/src/main/java/openconsignment/service/SupplierService.java +++ b/src/main/java/openconsignment/service/SupplierService.java @@ -50,7 +50,7 @@ public void renameSupplier(String oldName, String newName) throws SQLException { public void generatePdf(String supplierName, boolean isAgewise) throws SQLException, JRException { Map payload = new HashMap<>(); - payload.put(Constants.ORGANIZATION_NAME_KEY, configuration.getOrganizationName()); + payload.put(Constants.ORGANIZATION_NAME_KEY, configuration.getOrganization()); payload.put("supplierName", supplierName); if (isAgewise) { diff --git a/src/main/java/openconsignment/service/TransportService.java b/src/main/java/openconsignment/service/TransportService.java index dfe86e0..4785790 100644 --- a/src/main/java/openconsignment/service/TransportService.java +++ b/src/main/java/openconsignment/service/TransportService.java @@ -46,7 +46,7 @@ public void generatePdf(String transportName, String fromDate, String toDate) th transportRepository.getTransportReportFor(transportName, fromDate, toDate); Map payload = new HashMap<>(); - payload.put(Constants.ORGANIZATION_NAME_KEY, configuration.getOrganizationName()); + payload.put(Constants.ORGANIZATION_NAME_KEY, configuration.getOrganization()); payload.put("transportName", transportName); payload.put("fromDate", fromDate); payload.put("toDate", toDate); diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index f87a711..e147632 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,7 +1,8 @@ -organizationName: "SATYAM AGENCIES" +organization: "SATYAM AGENCIES" +#year: 2001-02 github: token: "" username: "razdeep" - branchName: "main" - remoteName: "origin-https" - repoName: "Satyam-Database-2001-02" \ No newline at end of file + branch: "main" + remote: "origin-https" + repository: "Satyam-Database-2001-02" \ No newline at end of file diff --git a/src/test/java/openconsignment/di/ConfigurationModuleTest.java b/src/test/java/openconsignment/di/ConfigurationModuleTest.java index 63e681e..ee15ee2 100644 --- a/src/test/java/openconsignment/di/ConfigurationModuleTest.java +++ b/src/test/java/openconsignment/di/ConfigurationModuleTest.java @@ -30,7 +30,7 @@ void missingFileIsCopiedFromBundledResourceAndLoaded() throws IOException { AppConfig configuration = load(file); assertEquals(bundled, Files.readString(file)); - assertEquals(configuration.getOrganizationName(), load(file).getOrganizationName()); + assertEquals(configuration.getOrganization(), load(file).getOrganization()); } @Test @@ -42,33 +42,33 @@ void emptyExistingFileIsRejectedAndPreserved() throws IOException { } @Test - void loadsUtf8OrganizationNameAndTrimsWhitespace() throws IOException { - Path file = Files.writeString(tempDir.resolve("application.yaml"), "organizationName: \" Café Agencies \"\n"); + void loadsUtf8OrganizationAndTrimsWhitespace() throws IOException { + Path file = Files.writeString(tempDir.resolve("application.yaml"), "organization: \" Café Agencies \"\n"); - assertEquals("Café Agencies", load(file).getOrganizationName()); + assertEquals("Café Agencies", load(file).getOrganization()); } @Test void loadedConfigurationDoesNotChangeWhenFileIsEdited() throws IOException { - Path file = Files.writeString(tempDir.resolve("application.yaml"), "organizationName: First\n"); + Path file = Files.writeString(tempDir.resolve("application.yaml"), "organization: First\n"); AppConfig configuration = load(file); - Files.writeString(file, "organizationName: Second\n"); + Files.writeString(file, "organization: Second\n"); - assertEquals("First", configuration.getOrganizationName()); - assertEquals("Second", load(file).getOrganizationName()); + assertEquals("First", configuration.getOrganization()); + assertEquals("Second", load(file).getOrganization()); } @Test - void rejectsBlankOrganizationName() throws IOException { - Path file = Files.writeString(tempDir.resolve("application.yaml"), "organizationName: \" \"\n"); + void rejectsBlankOrganization() throws IOException { + Path file = Files.writeString(tempDir.resolve("application.yaml"), "organization: \" \"\n"); assertThrows(IllegalArgumentException.class, () -> load(file)); } @Test void rejectsMalformedYaml() throws IOException { - Path file = Files.writeString(tempDir.resolve("application.yaml"), "organizationName: [\n"); + Path file = Files.writeString(tempDir.resolve("application.yaml"), "organization: [\n"); assertThrows(YAMLException.class, () -> load(file)); } @@ -83,16 +83,16 @@ void missingOrganizationNameIsRejectedWithoutBundledFallback() throws IOExceptio @Test void existingConfigurationIsLoadedWithoutBeingOverwritten() throws IOException { - String content = "# Custom settings\norganizationName: External Organization\n"; + String content = "# Custom settings\norganization: External Organization\n"; Path file = Files.writeString(tempDir.resolve("application.yaml"), content); - assertEquals("External Organization", load(file).getOrganizationName()); + assertEquals("External Organization", load(file).getOrganization()); assertEquals(content, Files.readString(file)); } @Test void malformedConfigurationErrorIdentifiesSourceFile() throws IOException { - Path file = Files.writeString(tempDir.resolve("application.yaml"), "organizationName: [\n"); + Path file = Files.writeString(tempDir.resolve("application.yaml"), "organization: [\n"); YAMLException error = assertThrows(YAMLException.class, () -> load(file)); @@ -134,14 +134,14 @@ void developmentRunUsesConfigurationInWorkingDirectory() throws IOException { @Test void bindsNumericScalarToStringProperty() throws IOException { - Path file = Files.writeString(tempDir.resolve("application.yaml"), "organizationName: 123\n"); + Path file = Files.writeString(tempDir.resolve("application.yaml"), "organization: 123\n"); - assertEquals("123", load(file).getOrganizationName()); + assertEquals("123", load(file).getOrganization()); } @Test void rejectsMappingOrganizationName() throws IOException { - Path file = Files.writeString(tempDir.resolve("application.yaml"), "organizationName: {name: Example}\n"); + Path file = Files.writeString(tempDir.resolve("application.yaml"), "organization: {name: Example}\n"); assertThrows(YAMLException.class, () -> load(file)); } @@ -155,22 +155,22 @@ void rejectsNonMappingDocument() throws IOException { @Test void rejectsNullOrganizationName() throws IOException { - Path file = Files.writeString(tempDir.resolve("application.yaml"), "organizationName: null\n"); + Path file = Files.writeString(tempDir.resolve("application.yaml"), "organization: null\n"); assertThrows(IllegalArgumentException.class, () -> load(file)); } @Test void rejectsEmptyOrganizationName() throws IOException { - Path file = Files.writeString(tempDir.resolve("application.yaml"), "organizationName: \"\"\n"); + Path file = Files.writeString(tempDir.resolve("application.yaml"), "organization: \"\"\n"); assertThrows(IllegalArgumentException.class, () -> load(file)); } @Test void rejectsDuplicateKeys() throws IOException { - Path file = Files.writeString( - tempDir.resolve("application.yaml"), "organizationName: First\norganizationName: Second\n"); + Path file = + Files.writeString(tempDir.resolve("application.yaml"), "organization: First\norganization: Second\n"); assertThrows(YAMLException.class, () -> load(file)); } From 69d4a4565687a5d61fa6e3227d4c055904a864b3 Mon Sep 17 00:00:00 2001 From: Rajdeep Roy Chowdhury Date: Sat, 14 Nov 2026 20:15:32 +0530 Subject: [PATCH 10/11] feat: year mentioned in banner Signed-off-by: Rajdeep Roy Chowdhury --- .../controller/WelcomeScreenController.java | 4 + src/main/resources/application.yaml | 2 +- src/main/resources/fxml/WelcomeScreen.fxml | 122 ++++++++++-------- 3 files changed, 73 insertions(+), 55 deletions(-) diff --git a/src/main/java/openconsignment/controller/WelcomeScreenController.java b/src/main/java/openconsignment/controller/WelcomeScreenController.java index 937816d..68f870d 100644 --- a/src/main/java/openconsignment/controller/WelcomeScreenController.java +++ b/src/main/java/openconsignment/controller/WelcomeScreenController.java @@ -20,6 +20,9 @@ public class WelcomeScreenController implements Initializable { @FXML private Text organization_name; + @FXML + private Text year; + @Inject public WelcomeScreenController(AppConfig configuration) { this.configuration = configuration; @@ -41,5 +44,6 @@ private void handleOpenGithub(ActionEvent event) { @Override public void initialize(URL url, ResourceBundle rb) { organization_name.setText(configuration.getOrganization()); + year.setText(configuration.getYear()); } } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index e147632..8167cdc 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,5 +1,5 @@ organization: "SATYAM AGENCIES" -#year: 2001-02 +year: 2001-02 github: token: "" username: "razdeep" diff --git a/src/main/resources/fxml/WelcomeScreen.fxml b/src/main/resources/fxml/WelcomeScreen.fxml index 645c681..ad21a09 100644 --- a/src/main/resources/fxml/WelcomeScreen.fxml +++ b/src/main/resources/fxml/WelcomeScreen.fxml @@ -1,54 +1,68 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 3c2d68c03b168584ad3b9bbe3987f35cf95e5f9b Mon Sep 17 00:00:00 2001 From: Rajdeep Roy Chowdhury Date: Sat, 14 Nov 2026 22:03:53 +0530 Subject: [PATCH 11/11] feat: implemented git clone on absent repo Signed-off-by: Rajdeep Roy Chowdhury --- .../service/BackupService.java | 54 ++++++++++++++++++- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/src/main/java/openconsignment/service/BackupService.java b/src/main/java/openconsignment/service/BackupService.java index a0fb714..4c7a4b9 100644 --- a/src/main/java/openconsignment/service/BackupService.java +++ b/src/main/java/openconsignment/service/BackupService.java @@ -2,6 +2,7 @@ import java.io.File; import java.io.IOException; +import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; @@ -18,6 +19,7 @@ import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.transport.PushResult; +import org.eclipse.jgit.transport.URIish; import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; @Slf4j @@ -31,6 +33,49 @@ public BackupService(AppConfig appConfig) { this.appConfig = appConfig; } + private void cloneRepo() throws GitAPIException, IOException, URISyntaxException { + + log.info("executing git clone"); + + AppConfig.Github github = appConfig.getGithub(); + String repoPath = github.getRepository(); + String username = github.getUsername(); + String token = github.getToken(); + String branchName = github.getBranch(); + String remoteName = github.getRemote(); + + if (Files.exists(Path.of(repoPath))) { + log.info("skipping git clone as repo already exist"); + return; + } + + String repoUrl = "https://github.com/" + username + "/" + repoPath + ".git"; + + try (Git ignored = Git.cloneRepository() + .setURI(repoUrl) + .setDirectory(new File(repoPath)) + .setBranch(branchName) + .setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, token)) + .call()) { + + log.info("Authenticated clone successful"); + } + + try (Git git = Git.open(new File(repoPath))) { + + // HTTPS remote + git.remoteAdd() + .setName(remoteName) + .setUri(new URIish("https://github.com/" + username + "/" + repoPath + ".git")) + .call(); + + git.remoteSetUrl() + .setRemoteName("origin") + .setRemoteUri(new URIish("git@github.com:" + username + "/" + repoPath + ".git")) + .call(); + } + } + public boolean checkSync() throws Exception { log.info("executing called"); try { @@ -67,7 +112,7 @@ private void copyRepoToLocal() throws IOException { log.info("Copied {} to {}", repoPath, Constants.DATABASE_FILE_NAME); } - private void pull() throws IOException, GitAPIException { + private void pull() throws IOException, GitAPIException, URISyntaxException { log.info("executing git pull"); AppConfig.Github github = appConfig.getGithub(); @@ -77,6 +122,11 @@ private void pull() throws IOException, GitAPIException { String branchName = github.getBranch(); String remoteName = github.getRemote(); + if (!Files.exists(Path.of(repoPath))) { + log.info("cloning {}", repoPath); + cloneRepo(); + } + log.info("token is {}", token); try (Git git = Git.open(new File(repoPath))) { @@ -95,7 +145,7 @@ private void pull() throws IOException, GitAPIException { } } - public void download() throws GitAPIException, IOException { + public void download() throws GitAPIException, IOException, URISyntaxException { pull(); copyRepoToLocal(); }