EN · DE · RU · FR · ES

#653: V7_0_0_6__MigrateEmployeeAndCarryVacationDays.java

projectforge-business/src/main/java/org/projectforge/flyway/dbmigration/V7_0_0_6__MigrateEmployeeAndCarryVacationDays.java Typ: Java · Rolle: Komponente · Quelle: projectforge-business/src/main/java/org/projectforge/flyway/dbmigration/V7_0_0_6__MigrateEmployeeAndCarryVacationDays.java 157 Zeilen · 115 Code · 29 Kommentare · 13 leer
Flyway-Datenbankmigrationsskript. Teil der versionierten Migrationskette, die das Datenbankschema von ProjectForge weiterentwickelt.

Codestruktur

Paket: org.projectforge.flyway.dbmigration

Klassen: V7_0_0_6__MigrateEmployeeAndCarryVacationDays

Erweitert: BaseJavaMigration

Methoden (4): migrate, migrateEmployeesCarryVacationDays, migrateEmployeeTable, ensureMidnigt

Felder (1): log

Importe: 19 Pakete

Quellcode (gekürzt)

package org.projectforge.flyway.dbmigration;

import org.flywaydb.core.api.migration.BaseJavaMigration;
import org.flywaydb.core.api.migration.Context;
import org.projectforge.framework.time.PFDateTimeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.jdbc.datasource.SingleConnectionDataSource;
import org.springframework.jdbc.support.rowset.SqlRowSet;

import javax.sql.DataSource;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Year;
import java.time.ZoneId;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Seit ProjectForge Version 7 werden verbleibende Urlaubstage in einer neuen Tabelle verwaltet,
 * anstatt als Attribut des Mitarbeiters (ohne Jahresangabe).
 */
public class V7_0_0_6__MigrateEmployeeAndCarryVacationDays extends BaseJavaMigration {
  private static Logger log = LoggerFactory.getLogger(V7_0_0_6__MigrateEmployeeAndCarryVacationDays.class);

  @Override
  public void migrate(Context context) {
    DataSource ds = new SingleConnectionDataSource(context.getConnection(), true);
    migrateEmployeesCarryVacationDays(ds);
    migrateEmployeeTable(ds);
  }

  private void migrateEmployeesCarryVacationDays(DataSource ds) {
    log.info("Versuche, die vom Vorjahr übertragenen Urlaubstage der Mitarbeiter zu migrieren, falls diese Funktion genutzt wird.");
    JdbcTemplate jdbc = new JdbcTemplate(ds);

    // Nach der Installation von Version 7 (Snapshot) schlug der Cronjob zur jährlichen Aktualisierung der Resturlaubstage aufgrund eines Fehlers in EmployeeAttrDO.parent (Kotlin-NPE) fehl.
    // Daher das Installationsjahr ermitteln:
    int release7InstalledOnYear = Year.now().getValue();
    try {
      Timestamp release7InstalledOn = jdbc.queryForObject("select installed_on from t_flyway_schema_version where version='7.0.0'", Timestamp.class);
      release7InstalledOnYear = LocalDateTime.ofInstant(release7InstalledOn.toInstant(), PFDateTimeUtils.ZONE_UTC).getYear();
    } catch (Exception ex) {
      // OK, Datenbank scheint leer zu sein.
    }

    SqlRowSet rs = jdbc.queryForRowSet("select p.modifiedat as modifiedat,p.value as value,e.pk as pk,e.tenant_id as tenant from t_fibu_employee_attr as p inner join t_fibu_employee as e on p.parent=e.pk where propertyname = 'previousyearleave' order by pk");
    int counter = 0;
    Date now = new Date();
    SimpleJdbcInsert simpleJdbcInsert = new SimpleJdbcInsert(ds).withTableName("t_employee_vacation_remaining");
    while (rs.next()) {
      ++counter;
      Timestamp modifiedat = rs.getTimestamp("modifiedat");
      Integer employeeId = rs.getInt("pk");
      Integer tenantId = rs.getInt("tenant");
      BigDecimal value = rs.getBigDecimal("value");
      int year = LocalDateTime.ofInstant(modifiedat.toInstant(), ZoneId.of("UTC")).getYear();
      if (year > release7InstalledOnYear) {
        year = release7InstalledOnYear; // Urlaubstage wurden geändert, aber das Attribut 'previousyearleave' bezieht sich nicht auf das aktuelle Jahr.
      }
      Map<String, Object> parameters = new HashMap<String, Object>();
      parameters.put("pk", counter);
      parameters.put("deleted", false);
      parameters.put("created", now);
      parameters.put("last_update", now);
      parameters.put("tenant_id", tenantId);
      parameters.put("employee_id", employeeId);
      parameters.put("year", year);
      parameters.put("carry_vacation_days_from_previous_year", value);
      simpleJdbcInsert.execute(parameters);
    }
    if (counter > 0) {
      log.info("Anzahl erfolgreich migrierter Einträge: " + counter);
    } else {
      log.info("Keine Urlaubseinträge zum Migrieren gefunden (OK, falls die Urlaubsfunktion nicht genutzt wurde).");
    }
  }

  private void migrateEmployeeTable(DataSource ds) {
    JdbcTemplate jdbc = new JdbcTemplate(ds);
    String defaultTimeZoneString = null;
    try {
      defaultTimeZoneString = jdbc.queryForObject("select stringvalue from t_configuration where parameter = 'timezone'", String.class);
    } catch (Exception ex) {
      // OK, Datenbank scheint leer zu sein.
    }
    ZoneId zoneId;
    if (defaultTimeZoneString == null) {
      zoneId = ZoneId.systemDefault();
    } else {
      zoneId = ZoneId.of(defaultTimeZoneString);
      int counter = 0;
      log.info("Migration der Zeitstempelfelder der Mitarbeitertabelle.");
      SqlRowSet rs = jdbc.queryForRowSet("select pk, eintritt, austritt, birthday from t_fibu_employee");
      while (rs.next()) {
        ++counter;
        Integer pk = rs.getInt("pk");
        Timestamp eintrittOrig = rs.getTimestamp("eintritt");
        Timestamp austrittOrg = rs.getTimestamp("austritt");
        Timestamp birtdayOrig = rs.getTimestamp("birthday");

        LocalDate birthday = ensureMidnigt(birtdayOrig, ZoneId.of("UTC")); // Geburtstage wurden als UTC gespeichert
        LocalDate eintritt = ensureMidnigt(eintrittOrig, zoneId);
        LocalDate austritt = ensureMidnigt(austrittOrg, zoneId);

        jdbc.update("update t_fibu_employee set birthday=?, eintritt=?, austritt=? where pk=?", birthday, eintritt, austritt, pk);
      }
      if (counter > 0) {
        log.info("Anzahl erfolgreich migrierter Mitarbeiter: " + counter);
      } else {
        log.info("Keine Mitarbeitereinträge zum Migrieren gefunden (OK, falls keine Mitarbeiter verwendet werden).");
      }
    }
  }

// ... (gekürzt, insgesamt 134 Zeilen)

Git-Verlauf

868d6abb7 2025 -> 2026
63081666f Quelldatei-Header: 2024 -> 2025.
b6092df09 Copyright 2023 -> 2024
ab45d51fa Copyright 2001-2022 -> 2001-2023.
5f7ef41b8 Copyright 2021 -> 2022