diff --git a/pom.xml b/pom.xml index 108fb87b7..f1e651a77 100644 --- a/pom.xml +++ b/pom.xml @@ -217,6 +217,9 @@ pl.project13.maven git-commit-id-plugin + + true + org.codehaus.mojo diff --git a/src/main/java/org/tb/auth/AfterLogin.java b/src/main/java/org/tb/auth/AfterLogin.java index 65a8c1817..517ba4187 100644 --- a/src/main/java/org/tb/auth/AfterLogin.java +++ b/src/main/java/org/tb/auth/AfterLogin.java @@ -7,6 +7,7 @@ import static org.tb.common.util.TimeFormatUtils.timeFormatMinutes; import static org.tb.common.util.UrlUtils.absoluteUrl; +import java.time.Duration; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; @@ -16,7 +17,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.struts.util.MessageResources; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tb.common.GlobalConstants; import org.tb.common.Warning; @@ -35,7 +35,7 @@ @Component @Slf4j -@RequiredArgsConstructor(onConstructor_ = { @Autowired}) +@RequiredArgsConstructor public class AfterLogin { private final TimereportHelper timereportHelper; @@ -210,25 +210,19 @@ private void addWarnings(Employeecontract employeecontract, MessageResources res } public void handleOvertime(Employeecontract employeecontract, HttpSession session) { - double overtimeStatic = employeecontract.getOvertimeStatic(); - int otStaticMinutes = (int) (overtimeStatic * 60); + Duration overtimeStatic = employeecontract.getOvertimeStatic(); + long otStaticMinutes = overtimeStatic.toMinutes(); - int overtime; - if (employeecontract.getUseOvertimeOld() != null && !employeecontract.getUseOvertimeOld()) { - //use new overtime computation with static + dynamic overtime - //need the LocalDate from the day after reportAcceptanceDate, so the latter is not used twice in overtime computation: - LocalDate dynamicDate; - if (employeecontract.getReportAcceptanceDate() == null || employeecontract.getReportAcceptanceDate().equals(employeecontract.getValidFrom())) { - dynamicDate = employeecontract.getValidFrom(); - } else { - dynamicDate = addDays(employeecontract.getReportAcceptanceDate(), 1); - } - int overtimeDynamic = timereportHelper.calculateOvertime(dynamicDate, today(), employeecontract, true); - overtime = otStaticMinutes + overtimeDynamic; - // if after SALAT-Release 1.83, no Release was accepted yet, use old overtime computation + //use new overtime computation with static + dynamic overtime + //need the LocalDate from the day after reportAcceptanceDate, so the latter is not used twice in overtime computation: + LocalDate dynamicDate; + if (employeecontract.getReportAcceptanceDate() == null || employeecontract.getReportAcceptanceDate().equals(employeecontract.getValidFrom())) { + dynamicDate = employeecontract.getValidFrom(); } else { - overtime = timereportHelper.calculateOvertimeTotal(employeecontract); + dynamicDate = addDays(employeecontract.getReportAcceptanceDate(), 1); } + long overtimeDynamic = timereportHelper.calculateOvertime(dynamicDate, today(), employeecontract, true); + long overtime = otStaticMinutes + overtimeDynamic; boolean overtimeIsNegative = overtime < 0; @@ -249,7 +243,7 @@ public void handleOvertime(Employeecontract employeecontract, HttpSession sessio if (validUntil != null && validUntil.isBefore(currentDate) && !validUntil.isBefore(start)) { currentDate = validUntil; } - int monthlyOvertime = 0; + long monthlyOvertime = 0; if (!(validUntil != null && validUntil.isBefore(start) || validFrom.isAfter(currentDate))) { monthlyOvertime = timereportHelper.calculateOvertime(start, currentDate, employeecontract, false); } diff --git a/src/main/java/org/tb/auth/LoginEmployeeAction.java b/src/main/java/org/tb/auth/LoginEmployeeAction.java index 009c470de..f668f9ea2 100644 --- a/src/main/java/org/tb/auth/LoginEmployeeAction.java +++ b/src/main/java/org/tb/auth/LoginEmployeeAction.java @@ -258,10 +258,9 @@ private void generateEmployeeOrders(LocalDate today, Employeecontract employeeco } if (suborder.getCustomerorder().getSign().equals(GlobalConstants.CUSTOMERORDER_SIGN_VACATION) && !suborder.getSign().equalsIgnoreCase(GlobalConstants.SUBORDER_SIGN_OVERTIME_COMPENSATION)) { - employeeorder.setDebithours(employeecontract - .getDailyWorkingTime() - * employeecontract - .getVacationEntitlement()); + // TODO reduce VacationEntitlement if contract is not running the whole year + var vacationBudget = employeecontract.getDailyWorkingTime().multipliedBy(employeecontract.getVacationEntitlement()); + employeeorder.setDebithours(vacationBudget); employeeorder.setDebithoursunit(GlobalConstants.DEBITHOURS_UNIT_TOTALTIME); } else { // not decided yet diff --git a/src/main/java/org/tb/common/AuditedEntity.java b/src/main/java/org/tb/common/AuditedEntity.java index a8c7b47b2..93ee19b92 100644 --- a/src/main/java/org/tb/common/AuditedEntity.java +++ b/src/main/java/org/tb/common/AuditedEntity.java @@ -2,6 +2,7 @@ import java.time.LocalDateTime; import java.util.Objects; +import javax.persistence.EntityListeners; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @@ -14,6 +15,7 @@ import org.springframework.data.annotation.LastModifiedBy; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.domain.Persistable; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; /** * Contains information about creation edits made to database columns common to @@ -24,6 +26,7 @@ @Getter @Setter @MappedSuperclass +@EntityListeners(AuditingEntityListener.class) abstract public class AuditedEntity implements Persistable { @Id diff --git a/src/main/java/org/tb/common/DataValidation.java b/src/main/java/org/tb/common/DataValidation.java index 6ac211e96..5070dc5c9 100644 --- a/src/main/java/org/tb/common/DataValidation.java +++ b/src/main/java/org/tb/common/DataValidation.java @@ -18,12 +18,6 @@ public static void isTrue(boolean expression, ErrorCode errorCode) { } } - public static void isInRange(double value, double min, double max, ErrorCode errorCode) { - if(value < min || value > max) { - throw new InvalidDataException(errorCode); - } - } - public static void lengthIsInRange(String value, int min, int max, ErrorCode errorCode) { if(value == null || value.length() < min || value.length() > max) { throw new InvalidDataException(errorCode); diff --git a/src/main/java/org/tb/common/DurationMinutesConverter.java b/src/main/java/org/tb/common/DurationMinutesConverter.java new file mode 100644 index 000000000..386f48912 --- /dev/null +++ b/src/main/java/org/tb/common/DurationMinutesConverter.java @@ -0,0 +1,22 @@ +package org.tb.common; + +import java.time.Duration; +import javax.persistence.AttributeConverter; +import javax.persistence.Converter; + +@Converter +public class DurationMinutesConverter implements AttributeConverter { + + @Override + public Integer convertToDatabaseColumn(Duration duration) { + if(duration == null) return null; + return (int) duration.toMinutes(); + } + + @Override + public Duration convertToEntityAttribute(Integer minutes) { + if(minutes == null) return null; + return Duration.ofMinutes(minutes); + } + +} diff --git a/src/main/java/org/tb/common/GlobalConstants.java b/src/main/java/org/tb/common/GlobalConstants.java index 05b17d54c..739e21daf 100644 --- a/src/main/java/org/tb/common/GlobalConstants.java +++ b/src/main/java/org/tb/common/GlobalConstants.java @@ -13,11 +13,7 @@ public class GlobalConstants { public static final int STARTING_YEAR = 2007; - public static final double MAX_HOURS_PER_DAY = 10.0; - - public static final double MAX_DEBITHOURS = 10000.0; - public static final double MAX_OVERTIME = 10000.0; - public static final double MIN_OVERTIME = -10000.0; + public static final int MAX_HOURS_PER_DAY = 10; public static final int COMMENT_MAX_LENGTH = 32000; diff --git a/src/main/java/org/tb/common/jsptags/FormatDurationTag.java b/src/main/java/org/tb/common/jsptags/FormatDurationTag.java new file mode 100644 index 000000000..40ce09964 --- /dev/null +++ b/src/main/java/org/tb/common/jsptags/FormatDurationTag.java @@ -0,0 +1,31 @@ +package org.tb.common.jsptags; + +import java.io.IOException; +import java.time.Duration; +import java.time.LocalDate; +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.JspWriter; +import javax.servlet.jsp.tagext.TagSupport; +import lombok.Setter; +import org.tb.common.util.DurationUtils; + +@Setter +public class FormatDurationTag extends TagSupport { + + private Duration value; + + @Override + public int doStartTag() throws JspException { + if(value != null) { + JspWriter out = pageContext.getOut(); + try { + out.print(DurationUtils.format(value)); + return super.doStartTag(); + } catch (IOException e) { + throw new JspException(e); + } + } + return SKIP_BODY; + } + +} diff --git a/src/main/java/org/tb/common/util/DateUtils.java b/src/main/java/org/tb/common/util/DateUtils.java index 0e788f848..aae5ebc74 100644 --- a/src/main/java/org/tb/common/util/DateUtils.java +++ b/src/main/java/org/tb/common/util/DateUtils.java @@ -11,7 +11,6 @@ import static org.tb.common.GlobalConstants.DEFAULT_DATE_FORMAT; import static org.tb.common.GlobalConstants.DEFAULT_LOCALE; import static org.tb.common.GlobalConstants.DEFAULT_TIMEZONE_ID; -import static org.tb.common.GlobalConstants.MINUTES_PER_HOUR; import static org.tb.common.GlobalConstants.STARTING_YEAR; import java.text.ParseException; @@ -304,26 +303,6 @@ public static int getLastDayOfMonth(LocalDate date) { return date.getMonthValue(); } - /** - * calculates worktime from begin/end times in a form - * - * @return double - decimal hours - */ - public static double calculateTime(int hrbegin, int minbegin, int hrend, int minend) { - double worktime; - - int hours = hrend - hrbegin; - int minutes = minend - minbegin; - - if (minutes < 0) { - hours -= 1; - minutes += MINUTES_PER_HOUR; - } - worktime = hours * 1. + minutes / 60.; - - return worktime; - } - /** * Takes a LocalDate and a number of days. Changes the LocalDate by adding (amount is positive) or subtracting (amount is negative) * the number of days to it. For example, you have some LocalDate and need the next day: input parameters are (date, 1). diff --git a/src/main/java/org/tb/common/util/DurationUtils.java b/src/main/java/org/tb/common/util/DurationUtils.java new file mode 100644 index 000000000..e779fbc09 --- /dev/null +++ b/src/main/java/org/tb/common/util/DurationUtils.java @@ -0,0 +1,124 @@ +package org.tb.common.util; + +import static java.lang.Math.abs; +import static org.tb.common.GlobalConstants.MINUTES_PER_HOUR; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.Duration; +import lombok.experimental.UtilityClass; + +@UtilityClass +public class DurationUtils { + + public static String format(Duration duration) { + if(duration == null) { + return ""; + } + if(duration.isZero()) { + return "0:00"; + } + StringBuilder sb = new StringBuilder(); + if(duration.isNegative()) { + sb.append('-'); + } + sb.append(abs(duration.toHours())).append(':'); + sb.append(String.format("%02d", abs(duration.toMinutesPart()))); + return sb.toString(); + } + + public static Duration parseDuration(String value) { + if(value == null || value.trim().isEmpty()) { + return Duration.ZERO; + } + boolean negative = value.startsWith("-"); + if(negative) { + value = value.substring(1); + } + int minutes = 0; + if(value.contains(":")) { + String[] split = value.split(":"); + if(!split[0].isEmpty()) { + minutes = Integer.parseInt(split[0]) * MINUTES_PER_HOUR; + } + if(split.length > 1 && !split[1].isEmpty()) { + minutes += Integer.parseInt(split[1]); + } + } else { + minutes = Integer.parseInt(value) * MINUTES_PER_HOUR; + } + if(negative) { + minutes = minutes * -1; + } + + return Duration.ofMinutes(minutes); + } + + public static boolean validateDuration(String value) { + if(value == null || value.trim().isEmpty()) { + return true; + } + // cut leading minues + if(value.startsWith("-")) { + value = value.substring(1); + } + try { + // check if hours:minutes + if(value.contains(":")) { + String[] split = value.split(":"); + if(split.length > 2) { + return false; + } + if(!split[0].isEmpty()) { + int hours = Integer.parseInt(split[0]); + // negative value is not allowed. Minues sign must be present at the very start of the value, which was already cut + if(hours < 0) { + return false; + } + } + if(split.length == 2 && !split[1].isEmpty()) { + int minutes = Integer.parseInt(split[1]); + // negative value is not allowed. Minues sign must be present at the very start of the value, which was already cut + if(minutes < 0) { + return false; + } + // minutes may be no more than 59 + if(minutes > 59) { + return false; + } + } + // check hours only as no ":" in value + } else { + int hours = Integer.parseInt(value); + // negative value is not allowed. Minues sign must be present at the very start of the value, which was already cut + if(hours < 0) { + return false; + } + } + return true; + } catch (NumberFormatException e) { + return false; + } + } + + public static String decimalFormat(Duration duration) { + if(duration == null) { + return ""; + } + if(duration.isZero()) { + return "0,00"; + } + StringBuilder sb = new StringBuilder(); + if(duration.isNegative()) { + sb.append('-'); + } + sb.append(abs(duration.toHours())).append(','); + int minutesDecimal = BigDecimal.valueOf(duration.toMinutesPart()) + .multiply(BigDecimal.valueOf(100)) + .divide(BigDecimal.valueOf(MINUTES_PER_HOUR), RoundingMode.HALF_UP) + .intValueExact(); + sb.append(String.format("%02d", abs(minutesDecimal))); + return sb.toString(); + } + +} diff --git a/src/main/java/org/tb/common/util/ExcelArchivierer.java b/src/main/java/org/tb/common/util/ExcelArchivierer.java index a90dabb3e..58dfa73dc 100644 --- a/src/main/java/org/tb/common/util/ExcelArchivierer.java +++ b/src/main/java/org/tb/common/util/ExcelArchivierer.java @@ -4,6 +4,8 @@ import static org.tb.common.GlobalConstants.DEFAULT_TIMEZONE_ID; import java.io.IOException; +import java.math.BigDecimal; +import java.math.RoundingMode; import java.time.ZoneId; import java.util.Date; import java.util.HashMap; @@ -148,7 +150,7 @@ private static Workbook createInvoiceExcel(ShowInvoiceForm showInvoiceForm, Http // ab hier ggf. Timereports ausgeben List invoiceTimereportViewHelpers = invoiceSuborderViewHelper.getInvoiceTimereportViewHelperList(); if (request.getSession().getAttribute("timereportsbox") != null && ((Boolean) request.getSession().getAttribute("timereportsbox")) - && invoiceTimereportViewHelpers.size() > 0) { + && !invoiceTimereportViewHelpers.isEmpty()) { for (InvoiceTimereportHelper invoiceTimereportViewHelper : invoiceTimereportViewHelpers) { if (invoiceTimereportViewHelper.isVisible()) { rowIndex = addTimereportDataRow(workbook, rowIndex, invoiceTimereportViewHelper, request, factory); @@ -258,7 +260,7 @@ private static int addSuborderDataRow(Workbook workbook, int rowIndex, InvoiceSu if (request.getSession().getAttribute("targethoursbox") != null && ((Boolean) request.getSession().getAttribute("targethoursbox"))) { cell = row.createCell(colIndex, Cell.CELL_TYPE_NUMERIC); if (invoiceSuborderViewHelper.getDebithours() != null) { - cell.setCellValue(invoiceSuborderViewHelper.getDebithours() / 24); + cell.setCellValue((double) invoiceSuborderViewHelper.getDebithours().toMinutes() / 24); } else { cell.setCellValue(0L); } diff --git a/src/main/java/org/tb/common/util/TimeFormatUtils.java b/src/main/java/org/tb/common/util/TimeFormatUtils.java index a29513dd0..6d2a4b128 100644 --- a/src/main/java/org/tb/common/util/TimeFormatUtils.java +++ b/src/main/java/org/tb/common/util/TimeFormatUtils.java @@ -1,6 +1,7 @@ package org.tb.common.util; -import java.math.BigDecimal; +import static org.tb.common.GlobalConstants.MINUTES_PER_HOUR; + import java.math.RoundingMode; import java.text.NumberFormat; import java.util.Locale; @@ -23,16 +24,8 @@ public class TimeFormatUtils { return timeMinutesFormat; }); - public static String decimalFormatHours(double hoursDecimal) { - return hoursDecimalFormatHolder.get().format(hoursDecimal); - } - - public static String decimalFormatMinutes(double minutesDecimal) { - return hoursDecimalFormatHolder.get().format(minutesDecimal / 60); - } - public static String decimalFormatHoursAndMinutes(long hours, long minutes) { - double hoursDecimal = ((double)minutes / 60) + hours; + double hoursDecimal = ((double)minutes / MINUTES_PER_HOUR) + hours; return hoursDecimalFormatHolder.get().format(hoursDecimal); } @@ -40,13 +33,12 @@ public static String timeFormatHoursAndMinutes(long hours, long minutes) { return hours + ":" + timeMinutesFormatHolder.get().format(Math.abs(minutes)); } - public static String timeFormatMinutes(long minutes) { - return timeFormatHoursAndMinutes(minutes / 60, minutes % 60); + public static String decimalFormatMinutes(long minutes) { + return decimalFormatHoursAndMinutes(minutes / MINUTES_PER_HOUR, minutes % MINUTES_PER_HOUR); } - public static String timeFormatHours(double hoursDecimal) { - BigDecimal minutesValue = BigDecimal.valueOf(hoursDecimal * 60).setScale(0, RoundingMode.HALF_UP); - return timeFormatMinutes(minutesValue.longValue()); + public static String timeFormatMinutes(long minutes) { + return timeFormatHoursAndMinutes(minutes / MINUTES_PER_HOUR, minutes % MINUTES_PER_HOUR); } } diff --git a/src/main/java/org/tb/dailyreport/AddDailyReportForm.java b/src/main/java/org/tb/dailyreport/AddDailyReportForm.java index 7b979b892..63032a8e1 100644 --- a/src/main/java/org/tb/dailyreport/AddDailyReportForm.java +++ b/src/main/java/org/tb/dailyreport/AddDailyReportForm.java @@ -3,6 +3,7 @@ import static org.tb.common.GlobalConstants.MINUTES_PER_HOUR; import static org.tb.common.util.DateUtils.today; +import java.time.Duration; import javax.servlet.http.HttpServletRequest; import lombok.Getter; import lombok.Setter; @@ -29,7 +30,6 @@ public class AddDailyReportForm extends ActionForm { private String order; private String suborder; private String status; - private Double hours; private Boolean training; private int selectedHourBegin; private int selectedMinuteBegin; @@ -48,13 +48,6 @@ public AddDailyReportForm() { setReferenceday(DateUtils.format(today())); } - public Double getHours() { - return DateUtils.calculateTime(this.selectedHourBegin, - this.selectedMinuteBegin, - this.selectedHourEnd, - this.selectedMinuteEnd); - } - @Override public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { ActionErrors errors = new ActionErrors(); @@ -97,9 +90,26 @@ public void reset() { selectedHourEnd = 0; selectedMinuteEnd = 0; referenceday = DateUtils.format(DateUtils.today()); - hours = 8.0; training = false; numberOfSerialDays = 0; } + public void recalcDurationFromBeginAndEnd() { + Duration duration = Duration.ofHours(selectedHourEnd) + .plusMinutes(selectedMinuteEnd) + .minusHours(selectedHourBegin) + .minusMinutes(selectedMinuteBegin); + this.selectedHourDuration = duration.toHoursPart(); + this.selectedMinuteDuration = duration.toMinutesPart(); + } + + public void recalcEndFromBeginAndDuration() { + Duration duration = Duration.ofHours(selectedHourEnd) + .plusMinutes(selectedMinuteEnd) + .plusHours(selectedHourDuration) + .plusMinutes(selectedMinuteDuration); + this.selectedHourEnd = duration.toHoursPart(); + this.selectedMinuteEnd = duration.toMinutesPart(); + } + } diff --git a/src/main/java/org/tb/dailyreport/ShowDailyReportAction.java b/src/main/java/org/tb/dailyreport/ShowDailyReportAction.java index 2225b8615..c03a3ad74 100644 --- a/src/main/java/org/tb/dailyreport/ShowDailyReportAction.java +++ b/src/main/java/org/tb/dailyreport/ShowDailyReportAction.java @@ -440,16 +440,12 @@ private ActionForward doRefreshTimereports(ActionMapping mapping, HttpServletReq date = DateUtils.getEndOfMonth(date); } request.setAttribute("showOvertimeUntil", reportForm.getShowOvertimeUntil()); - int overtime; - if (ec.getReportAcceptanceDate().isBefore(date) && ec.getUseOvertimeOld() == false) { - Double overtimeStatic = ec.getOvertimeStatic(); - int otStaticMinutes = (int) (overtimeStatic * 60); - LocalDate dynamicDate = DateUtils.addDays(ec.getReportAcceptanceDate(), 1); - int overtimeDynamic = timereportHelper.calculateOvertime(dynamicDate, date, ec, true); - overtime = otStaticMinutes + overtimeDynamic; - } else { - overtime = timereportHelper.calculateOvertime(ec.getValidFrom(), date, ec, true); - } + + long otStaticMinutes = ec.getOvertimeStatic().toMinutes(); + LocalDate dynamicDate = DateUtils.addDays(ec.getReportAcceptanceDate(), 1); + long overtimeDynamic = timereportHelper.calculateOvertime(dynamicDate, date, ec, true); + long overtime = otStaticMinutes + overtimeDynamic; + boolean overtimeUntilIsNeg = overtime < 0; request.getSession().setAttribute("overtimeUntilIsNeg", overtimeUntilIsNeg); request.getSession().setAttribute("enddate", DateUtils.format(date)); diff --git a/src/main/java/org/tb/dailyreport/ShowReleaseAction.java b/src/main/java/org/tb/dailyreport/ShowReleaseAction.java index af27efa2a..c054f004b 100644 --- a/src/main/java/org/tb/dailyreport/ShowReleaseAction.java +++ b/src/main/java/org/tb/dailyreport/ShowReleaseAction.java @@ -4,6 +4,7 @@ import static org.tb.common.util.DateUtils.getDateFormStrings; import static org.tb.common.util.DateUtils.today; +import java.time.Duration; import java.time.LocalDate; import java.util.ArrayList; import java.util.LinkedList; @@ -247,14 +248,9 @@ protected ActionForward executeAuthenticated(ActionMapping mapping, // set new acceptance date in employee contract employeecontract.setReportAcceptanceDate(acceptanceDate); //compute overtimeStatic and set it in employee contract - double otStatic = timereportHelper.calculateOvertime(employeecontract.getValidFrom(), employeecontract.getReportAcceptanceDate(), + long otStatic = timereportHelper.calculateOvertime(employeecontract.getValidFrom(), employeecontract.getReportAcceptanceDate(), employeecontract, true); - employeecontract.setOvertimeStatic(otStatic / 60.0); - - //only used the first time a release is accepted after SALAT-Release 1.83: - if (employeecontract.getUseOvertimeOld() == null || employeecontract.getUseOvertimeOld()) { - employeecontract.setUseOvertimeOld(false); - } + employeecontract.setOvertimeStatic(Duration.ofMinutes(otStatic)); employeecontractDAO.save(employeecontract, loginEmployee); } @@ -298,9 +294,9 @@ protected ActionForward executeAuthenticated(ActionMapping mapping, releaseForm.setAcceptanceYear(acceptanceDateArray[2]); // recompute overtimeStatic and set it in employeecontract - double otStatic = timereportHelper.calculateOvertime(employeecontract.getValidFrom(), employeecontract.getReportAcceptanceDate(), + long otStatic = timereportHelper.calculateOvertime(employeecontract.getValidFrom(), employeecontract.getReportAcceptanceDate(), employeecontract, true); - employeecontract.setOvertimeStatic(otStatic / 60.0); + employeecontract.setOvertimeStatic(Duration.ofMinutes(otStatic)); } request.getSession().setAttribute("reopenDays", diff --git a/src/main/java/org/tb/dailyreport/ShowTrainingAction.java b/src/main/java/org/tb/dailyreport/ShowTrainingAction.java index d2d9cf024..507aefff3 100644 --- a/src/main/java/org/tb/dailyreport/ShowTrainingAction.java +++ b/src/main/java/org/tb/dailyreport/ShowTrainingAction.java @@ -85,12 +85,16 @@ protected boolean refreshTraining(HttpServletRequest request, ShowTrainingForm t List trainingOverviews; List employeecontracts = employeecontractDAO.getVisibleEmployeeContractsOrderedByEmployeeSign(); - employeecontracts.removeIf(c -> c.getFreelancer() || c.getDailyWorkingTime() <= 0 || c.getEmployeeorders() == null); + employeecontracts.removeIf(c -> c.getFreelancer() + || c.getDailyWorkingTime().toMinutes() <= 0 + || c.getEmployeeorders() == null); request.getSession().setAttribute("employeecontracts", employeecontracts); // refresh all relevant attributes - if (trainingForm.getEmployeeContractId() == -1 || employeecontract.getFreelancer() || employeecontract.getDailyWorkingTime() <= 0 - || employeecontract.getEmployeeorders() == null) { + if (trainingForm.getEmployeeContractId() == -1 + || employeecontract.getFreelancer() + || employeecontract.getDailyWorkingTime().toMinutes() <= 0 + || employeecontract.getEmployeeorders() == null) { // get the training times for specific year, all employees, all orders (project Training) and order i976 (CommonTraining) trainingOverviews = getTrainingOverviewsForAll(startdate, enddate, employeecontractDAO, orderID, employeecontracts, year); @@ -140,7 +144,9 @@ private String init(HttpServletRequest request, ShowTrainingForm trainingForm, E return forward; } - employeecontracts.removeIf(c -> c.getFreelancer() || c.getDailyWorkingTime() <= 0 || c.getEmployeeorders() == null); + employeecontracts.removeIf(c -> c.getFreelancer() + || c.getDailyWorkingTime().toMinutes() <= 0 + || c.getEmployeeorders() == null); if (ec == null) { request.setAttribute("errorMessage", "No employee contract found for employee - please call system administrator."); @@ -154,7 +160,9 @@ private String init(HttpServletRequest request, ShowTrainingForm trainingForm, E // If all Employees are to be shown, get a list of TrainingOverviews with an entry for each Employeecontract. // Is the case if All Employees preselected on other page or current logged-in employee has no training, e.g. as admin. - if (employeeContractId == -1 || ec.getFreelancer() || ec.getDailyWorkingTime() <= 0 || ec.getEmployeeorders() == null) { + if (employeeContractId == -1 + || ec.getFreelancer() + || ec.getDailyWorkingTime().toMinutes() <= 0 || ec.getEmployeeorders() == null) { trainingOverview = getTrainingOverviewsForAll(startdate, enddate, employeecontractDAO, orderID, employeecontracts, year); request.getSession().setAttribute("currentEmployeeId", -1L); diff --git a/src/main/java/org/tb/dailyreport/StoreDailyReportAction.java b/src/main/java/org/tb/dailyreport/StoreDailyReportAction.java index 7920a61d6..5e4b251e2 100644 --- a/src/main/java/org/tb/dailyreport/StoreDailyReportAction.java +++ b/src/main/java/org/tb/dailyreport/StoreDailyReportAction.java @@ -6,6 +6,7 @@ import java.io.IOException; import java.text.ParseException; +import java.time.Duration; import java.time.LocalDate; import java.util.Collections; import java.util.List; @@ -100,9 +101,7 @@ public ActionForward executeAuthenticated(ActionMapping mapping, AddDailyReportF if (request.getParameter("task") != null && request.getParameter("task").equals("adjustBeginTime")) { refreshWorkdayAvailability = true; - Double dailyWorkingTime = employeeContract.getDailyWorkingTime(); - dailyWorkingTime *= 60; - int dailyWorkingTimeMinutes = dailyWorkingTime.intValue(); + Duration dailyWorkingTime = employeeContract.getDailyWorkingTime(); Customerorder selectedOrder = customerorderDAO.getCustomerorderById(form.getOrderId()); boolean standardOrder = customerorderHelper.isOrderStandard(selectedOrder); Boolean workingDayAvailable = (Boolean) request.getSession().getAttribute("workingDayIsAvailable"); @@ -128,7 +127,7 @@ public ActionForward executeAuthenticated(ActionMapping mapping, AddDailyReportF LocalDate today = DateUtils.today(); if (standardOrder) { int minutes = form.getSelectedHourBegin() * MINUTES_PER_HOUR + form.getSelectedMinuteBegin(); - minutes += dailyWorkingTimeMinutes; + minutes += dailyWorkingTime.toMinutes(); int hours = minutes / MINUTES_PER_HOUR; minutes = minutes % MINUTES_PER_HOUR; // round down to next minute increment @@ -147,8 +146,8 @@ public ActionForward executeAuthenticated(ActionMapping mapping, AddDailyReportF // TODO wird dieser Code je durchlaufen? if (standardOrder) { - int hours = dailyWorkingTimeMinutes / MINUTES_PER_HOUR; - int minutes = dailyWorkingTimeMinutes % MINUTES_PER_HOUR; + int hours = dailyWorkingTime.toHoursPart(); + int minutes = dailyWorkingTime.toMinutesPart(); // round down to next minute increment minutes = minutes / MINUTE_INCREMENT * MINUTE_INCREMENT; @@ -190,10 +189,9 @@ public ActionForward executeAuthenticated(ActionMapping mapping, AddDailyReportF Customerorder selectedOrder = customerorderDAO.getCustomerorderById(form.getOrderId()); boolean standardOrder = customerorderHelper.isOrderStandard(selectedOrder); if (standardOrder) { - Double dailyWorkingTime = employeeContract.getDailyWorkingTime(); - int dailyWorkingTimeMinutes = (int)(dailyWorkingTime * MINUTES_PER_HOUR); - int hours = dailyWorkingTimeMinutes / MINUTES_PER_HOUR; - int minutes = dailyWorkingTimeMinutes % MINUTES_PER_HOUR; + Duration dailyWorkingTime = employeeContract.getDailyWorkingTime(); + int hours = dailyWorkingTime.toHoursPart(); + int minutes = dailyWorkingTime.toMinutesPart(); // round down to next minute increment minutes = minutes / MINUTE_INCREMENT * MINUTE_INCREMENT; diff --git a/src/main/java/org/tb/dailyreport/TimereportService.java b/src/main/java/org/tb/dailyreport/TimereportService.java index 8ff66f508..e25bf891f 100644 --- a/src/main/java/org/tb/dailyreport/TimereportService.java +++ b/src/main/java/org/tb/dailyreport/TimereportService.java @@ -41,6 +41,7 @@ import static org.tb.common.util.DateUtils.max; import static org.tb.common.util.DateUtils.min; +import java.time.Duration; import java.time.LocalDate; import java.time.Year; import java.time.YearMonth; @@ -51,9 +52,8 @@ import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; -import lombok.Setter; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import org.tb.auth.AuthorizedUser; @@ -74,15 +74,15 @@ @Slf4j @Component @Transactional -@Setter(onMethod_ = { @Autowired }) +@RequiredArgsConstructor public class TimereportService { - private EmployeecontractDAO employeecontractDAO; - private ReferencedayDAO referencedayDAO; - private EmployeeorderDAO employeeorderDAO; - private TimereportDAO timereportDAO; - private PublicholidayDAO publicholidayDAO; - private OvertimeDAO overtimeDAO; + private final EmployeecontractDAO employeecontractDAO; + private final ReferencedayDAO referencedayDAO; + private final EmployeeorderDAO employeeorderDAO; + private final TimereportDAO timereportDAO; + private final PublicholidayDAO publicholidayDAO; + private final OvertimeDAO overtimeDAO; public void createTimereports(AuthorizedUser authorizedUser, long employeeContractId, long employeeOrderId, LocalDate referenceDay, String taskDescription, boolean trainingFlag, int durationHours, int durationMinutes, int numberOfSerialDays) @@ -175,17 +175,16 @@ public long calculateOvertimeMinutes(LocalDate start, LocalDate end, long employ long effectiveWorkDays = weekdays - effectivePublicHolidayCount; // calculate working time - long dailyWorkingTimeInMinutes = (long)(employeecontract.getDailyWorkingTime() * MINUTES_PER_HOUR); + long dailyWorkingTimeInMinutes = employeecontract.getDailyWorkingTime().toMinutes(); long expectedWorkingTimeInMinutes = dailyWorkingTimeInMinutes * effectiveWorkDays; long actualWorkingTimeInMinutes = timereportDAO.getTotalDurationMinutesForEmployeecontract(employeecontractId, effectiveStart, effectiveEnd); if (useOverTimeAdjustment && start.equals(employeecontract.getValidFrom())) { - double overtime = overtimeDAO.getOvertimesByEmployeeContractId(employeecontractId) + long overtimeInMinutes = overtimeDAO.getOvertimesByEmployeeContractId(employeecontractId) .stream() //.filter(o -> o.getRefDate()) TODO introduce this date to allow to provide a date when the adjustment is effective - .map(Overtime::getTime) - .mapToDouble(Double::doubleValue) + .map(Overtime::getTimeMinutes) + .mapToLong(Duration::toMinutes) .sum(); - long overtimeInMinutes = (long) (overtime * MINUTES_PER_HOUR); actualWorkingTimeInMinutes += overtimeInMinutes; } @@ -219,12 +218,12 @@ private void checkAndSaveTimereports(AuthorizedUser authorizedUser, List timereports) throws Bu if(employeeorder.getDebithoursunit() == null) { return; // no budget defined! } - long debitMinutesTemp = (long) (employeeorder.getDebithours() * MINUTES_PER_HOUR); + long debitMinutesTemp = employeeorder.getDebithours().toMinutes(); // increase debit minutes if timereport exists (update case) by the time of that timereport // because this time is read from the database query, too. This is a trick to circumvent this special case. if(timereports.size() == 1 && !timereports.get(0).isNew()) { diff --git a/src/main/java/org/tb/dailyreport/TrainingRepository.java b/src/main/java/org/tb/dailyreport/TrainingRepository.java index a5eb24192..ac95a6933 100644 --- a/src/main/java/org/tb/dailyreport/TrainingRepository.java +++ b/src/main/java/org/tb/dailyreport/TrainingRepository.java @@ -12,7 +12,7 @@ public interface TrainingRepository extends CrudRepository { @Query(""" select t.employeecontract.id, sum(t.durationhours), sum(t.durationminutes) from Timereport t - where t.employeecontract.freelancer is false and t.employeecontract.dailyWorkingTime > 0 + where t.employeecontract.freelancer is false and t.employeecontract.dailyWorkingTimeMinutes > 0 and t.referenceday.refdate >= :begin and t.referenceday.refdate <= :end and t.training = true group by t.employeecontract.id """) @@ -20,7 +20,7 @@ select t.employeecontract.id, sum(t.durationhours), sum(t.durationminutes) from @Query(""" select t.employeecontract.id, sum(t.durationhours), sum(t.durationminutes) from Timereport t - where t.employeecontract.freelancer=false and t.employeecontract.dailyWorkingTime > 0 + where t.employeecontract.freelancer=false and t.employeecontract.dailyWorkingTimeMinutes > 0 and t.referenceday.refdate >= :begin and t.referenceday.refdate <= :end and t.suborder.customerorder.id = :customerorderId and t.suborder.sign not like 'x_%' group by t.employeecontract.id diff --git a/src/main/java/org/tb/dailyreport/viewhelper/TimereportHelper.java b/src/main/java/org/tb/dailyreport/viewhelper/TimereportHelper.java index 9234eaa8e..f4536e3ed 100644 --- a/src/main/java/org/tb/dailyreport/viewhelper/TimereportHelper.java +++ b/src/main/java/org/tb/dailyreport/viewhelper/TimereportHelper.java @@ -3,8 +3,8 @@ import static java.time.DayOfWeek.SATURDAY; import static java.time.DayOfWeek.SUNDAY; import static org.tb.common.GlobalConstants.MINUTES_PER_HOUR; -import static org.tb.common.util.DateUtils.today; +import java.time.Duration; import java.time.LocalDate; import java.util.List; import java.util.Objects; @@ -14,7 +14,6 @@ import lombok.extern.slf4j.Slf4j; import org.apache.struts.action.ActionMessage; import org.apache.struts.action.ActionMessages; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tb.common.GlobalConstants; import org.tb.common.util.DateUtils; @@ -37,7 +36,7 @@ */ @Component @Slf4j -@RequiredArgsConstructor(onConstructor_ = { @Autowired}) +@RequiredArgsConstructor public class TimereportHelper { private final TimereportDAO timereportDAO; @@ -49,69 +48,14 @@ public class TimereportHelper { * refreshes hours after change of begin/end times */ public void refreshHours(AddDailyReportForm reportForm) { - Double hours = reportForm.getHours(); - if (hours < 0.0) { - reportForm.setSelectedHourDuration(0); - reportForm.setSelectedMinuteDuration(0); - return; - } - - reportForm.setHours(hours); - - // int hourDuration = hours.intValue(); - // int minuteDuration = (int) ((hours.doubleValue() - Math.floor(hours.doubleValue()) )*60.); - - // in der alten rechnug gabs einen rundungsfehler, der geschied jezt nicht mehr - long minuteDurationlong; - int hourDurationInteger = hours.intValue(); - minuteDurationlong = Math.round((hours - hours.intValue()) * MINUTES_PER_HOUR); - int minuteDuration = (int) minuteDurationlong; - - // clean possible truncation errors - if (minuteDuration % GlobalConstants.MINUTE_INCREMENT != 0) { - if (minuteDuration % GlobalConstants.MINUTE_INCREMENT > 2.5) { - minuteDuration += 5 - minuteDuration % GlobalConstants.MINUTE_INCREMENT; - } else if (minuteDuration % GlobalConstants.MINUTE_INCREMENT < 2.5) { - minuteDuration -= minuteDuration % GlobalConstants.MINUTE_INCREMENT; - } - } - - reportForm.setSelectedHourDuration(hourDurationInteger); - reportForm.setSelectedMinuteDuration(minuteDuration); + reportForm.recalcDurationFromBeginAndEnd(); } /** * refreshes period after change of hours */ public boolean refreshPeriod(HttpServletRequest request, AddDailyReportForm reportForm) { - // calculate end hour/minute - double hours = reportForm.getSelectedHourDuration() + reportForm.getSelectedMinuteDuration() / (double)MINUTES_PER_HOUR; - reportForm.setHours(hours); - request.getSession().setAttribute("hourDuration", hours); - - int hoursEnd = reportForm.getSelectedHourBegin() + reportForm.getHours().intValue(); - double dMinutes = (reportForm.getHours() - - Math.floor(reportForm.getHours())) * MINUTES_PER_HOUR; - - int minutesEnd = reportForm.getSelectedMinuteBegin() + Double.valueOf(dMinutes).intValue(); - - // // clean possible truncation errors - if (minutesEnd % GlobalConstants.MINUTE_INCREMENT != 0) { - if (minutesEnd % GlobalConstants.MINUTE_INCREMENT > 2.5) { - minutesEnd += 5 - minutesEnd % GlobalConstants.MINUTE_INCREMENT; - } else if (minutesEnd % GlobalConstants.MINUTE_INCREMENT < 2.5) { - minutesEnd -= minutesEnd % GlobalConstants.MINUTE_INCREMENT; - } - } - - if (minutesEnd >= MINUTES_PER_HOUR) { - minutesEnd -= MINUTES_PER_HOUR; - hoursEnd++; - } - - reportForm.setSelectedHourEnd(hoursEnd); - reportForm.setSelectedMinuteEnd(minutesEnd); - + reportForm.recalcEndFromBeginAndDuration(); return true; } @@ -314,23 +258,14 @@ public int[] calculateLaborTimeAsArray(List timereports) { * * @return Returns true, if the maximal labor time is extended, false otherwise */ - public boolean checkLaborTimeMaximum(List timereports, double maximalDailyLaborTime) { - int laborTimeHour = 0; - int laborTimeMinute = 0; + public boolean checkLaborTimeMaximum(List timereports, int maxDailyLaborTimeHours) { - for (Timereport timereport : timereports) { + Duration actual = timereports.stream() + .map(t -> Duration.ofHours(t.getDurationhours()).plusMinutes(t.getDurationminutes())) + .reduce(Duration.ZERO, Duration::plus); - int hours = timereport.getDurationhours(); - int minutes = timereport.getDurationminutes(); - - laborTimeHour += hours; - laborTimeMinute += minutes; - } - laborTimeHour += laborTimeMinute / MINUTES_PER_HOUR; - laborTimeMinute = laborTimeMinute % MINUTES_PER_HOUR; - - double laborTime = laborTimeHour + (double)laborTimeMinute / MINUTES_PER_HOUR; - return laborTime > maximalDailyLaborTime; + // check actual is not greater than the max labor time + return !Duration.ofHours(maxDailyLaborTimeHours).minus(actual).isNegative(); } /** @@ -340,7 +275,7 @@ public String calculateQuittingTime(Workingday workingday, HttpServletRequest re String N_A = "n/a"; if (workingday == null) return N_A; try { - int timeHoursInt = 0; + long timeHoursLong = 0; int timeMinutesInt = 0; if (timeSwitch.equals("quittingtime")) { @@ -348,21 +283,16 @@ public String calculateQuittingTime(Workingday workingday, HttpServletRequest re String[] laborTimeArray = labortimeString.split(":"); String laborTimeHoursString = laborTimeArray[0]; String laborTimeMinutesString = laborTimeArray[1]; - int laborTimeHoursInt = Integer.parseInt(laborTimeHoursString); - int laborTimeMinutesInt = Integer.parseInt(laborTimeMinutesString); - timeHoursInt = laborTimeHoursInt; - timeMinutesInt = laborTimeMinutesInt; + timeHoursLong = Long.parseLong(laborTimeHoursString); + timeMinutesInt = Integer.parseInt(laborTimeMinutesString); } if (timeSwitch.equals("workingDayEnds")) { Employeecontract employeecontract = (Employeecontract) request.getSession().getAttribute("loginEmployeeContract"); - Double dailyWorkingTime = employeecontract.getDailyWorkingTime(); - int dailyWorkingTimeHours = dailyWorkingTime.intValue(); - int dailyWorkingTimeMinutes = Integer.parseInt(dailyWorkingTime.toString().replace(".", ":").split(":")[1]) * 6; - timeHoursInt = dailyWorkingTimeHours; - timeMinutesInt = dailyWorkingTimeMinutes; + timeHoursLong = employeecontract.getDailyWorkingTime().toHours(); + timeMinutesInt = employeecontract.getDailyWorkingTime().toMinutesPart(); } - int quittingtimeHours = workingday.getStarttimehour() + workingday.getBreakhours() + timeHoursInt; + long quittingtimeHours = workingday.getStarttimehour() + workingday.getBreakhours() + timeHoursLong; int quittingtimeMinutes = workingday.getStarttimeminute() + workingday.getBreakminutes() + timeMinutesInt; quittingtimeHours += quittingtimeMinutes / MINUTES_PER_HOUR; quittingtimeMinutes = quittingtimeMinutes % MINUTES_PER_HOUR; @@ -391,20 +321,7 @@ public String calculateQuittingTime(Workingday workingday, HttpServletRequest re } } - /** - * @return Returns the minutes of overtime, might be negative - */ - public int calculateOvertimeTotal(Employeecontract employeecontract) { - - LocalDate today = today(); - - LocalDate contractBegin = employeecontract.getValidFrom(); - - return calculateOvertime(contractBegin, today, employeecontract, true); - - } - - public int calculateOvertime(LocalDate start, LocalDate end, Employeecontract employeecontract, boolean useOverTimeAdjustment) { + public long calculateOvertime(LocalDate start, LocalDate end, Employeecontract employeecontract, boolean useOverTimeAdjustment) { // do not consider invalid(outside of the validity of the contract) days if (employeecontract.getValidUntil() != null && end.isAfter(employeecontract.getValidUntil())) { @@ -429,10 +346,7 @@ public int calculateOvertime(LocalDate start, LocalDate end, Employeecontract em diffDays -= numberOfHolidays; // calculate working time - double dailyWorkingTime = employeecontract.getDailyWorkingTime() * MINUTES_PER_HOUR; - if (dailyWorkingTime % 1 != 0) { - throw new RuntimeException("daily working time must be multiple of 0.05: " + employeecontract.getDailyWorkingTime()); - } + long dailyWorkingTime = employeecontract.getDailyWorkingTime().toMinutes(); long expectedWorkingTimeInMinutes = (long) dailyWorkingTime * diffDays; long actualWorkingTimeInMinutes = 0; List reports = timereportDAO.getTimereportsByDatesAndEmployeeContractId(employeecontract.getId(), start, end); @@ -442,17 +356,17 @@ public int calculateOvertime(LocalDate start, LocalDate end, Employeecontract em } } - int overtimeMinutes; + long overtimeMinutes; if (useOverTimeAdjustment && start.equals(employeecontract.getValidFrom())) { long overtimeAdjustmentMinutes = 0; List overtimes = overtimeDAO .getOvertimesByEmployeeContractId(employeecontract.getId()); for (Overtime ot : overtimes) { - overtimeAdjustmentMinutes += ot.getTime() * MINUTES_PER_HOUR; + overtimeAdjustmentMinutes += ot.getTimeMinutes().toMinutes(); } - overtimeMinutes = (int) (actualWorkingTimeInMinutes - expectedWorkingTimeInMinutes + overtimeAdjustmentMinutes); + overtimeMinutes = actualWorkingTimeInMinutes - expectedWorkingTimeInMinutes + overtimeAdjustmentMinutes; } else { - overtimeMinutes = (int) (actualWorkingTimeInMinutes - expectedWorkingTimeInMinutes); + overtimeMinutes = actualWorkingTimeInMinutes - expectedWorkingTimeInMinutes; } if (end.isAfter(start) || end.isEqual(start)) { diff --git a/src/main/java/org/tb/dailyreport/viewhelper/TrainingHelper.java b/src/main/java/org/tb/dailyreport/viewhelper/TrainingHelper.java index e79956053..65ba4b7d6 100644 --- a/src/main/java/org/tb/dailyreport/viewhelper/TrainingHelper.java +++ b/src/main/java/org/tb/dailyreport/viewhelper/TrainingHelper.java @@ -1,5 +1,7 @@ package org.tb.dailyreport.viewhelper; +import static org.tb.common.GlobalConstants.MINUTES_PER_HOUR; + import org.tb.employee.Employeecontract; public class TrainingHelper { @@ -17,45 +19,36 @@ public static int[] getHoursMin(Object[] time) { return intTime; } - public static int getMinutesForHourDouble(Double doubleValue) { - int hours = doubleValue.intValue(); - doubleValue = doubleValue - hours; - int minutes = doubleValue.intValue() * 60; - minutes += hours * 60; - return minutes; - } - public static String fromDBtimeToString(Employeecontract ec, int hours, int minutes) { - int trainingDays = 0; - int trainingHours = 0; - int trainingMinutes = 0; - int restMinutes; + long trainingDays = 0; + long trainingHours = 0; + long trainingMinutes = 0; - int totalTrainingMinutes = hours * 60 + minutes; + long totalTrainingMinutes = hours * MINUTES_PER_HOUR + minutes; - int dailyWorkingTimeMinutes = getMinutesForHourDouble(ec.getDailyWorkingTime()); + long dailyWorkingTimeMinutes = ec.getDailyWorkingTime().toMinutes(); if (dailyWorkingTimeMinutes != 0) { trainingDays = totalTrainingMinutes / dailyWorkingTimeMinutes; - restMinutes = totalTrainingMinutes % dailyWorkingTimeMinutes; - trainingHours = restMinutes / 60; - trainingMinutes = restMinutes % 60; + var restMinutes = totalTrainingMinutes % dailyWorkingTimeMinutes; + trainingHours = restMinutes / MINUTES_PER_HOUR; + trainingMinutes = restMinutes % MINUTES_PER_HOUR; } StringBuilder trainingString = new StringBuilder(); if (trainingDays < 10) { - trainingString.append(0); + trainingString.append('0'); } trainingString.append(trainingDays); trainingString.append(':'); if (trainingHours < 10) { - trainingString.append(0); + trainingString.append('0'); } trainingString.append(trainingHours); trainingString.append(':'); if (trainingMinutes < 10) { - trainingString.append(0); + trainingString.append('0'); } trainingString.append(trainingMinutes); diff --git a/src/main/java/org/tb/dailyreport/viewhelper/VacationViewer.java b/src/main/java/org/tb/dailyreport/viewhelper/VacationViewer.java index ba9317bca..5fd536ea9 100644 --- a/src/main/java/org/tb/dailyreport/viewhelper/VacationViewer.java +++ b/src/main/java/org/tb/dailyreport/viewhelper/VacationViewer.java @@ -3,16 +3,17 @@ import static java.math.RoundingMode.DOWN; import static java.util.Locale.GERMAN; import static org.tb.common.util.DateUtils.today; -import static org.tb.common.util.TimeFormatUtils.timeFormatHours; import static org.tb.common.util.TimeFormatUtils.timeFormatMinutes; import java.io.Serializable; import java.math.BigDecimal; import java.text.NumberFormat; +import java.time.Duration; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; import javax.servlet.http.HttpSession; +import org.tb.common.util.DurationUtils; import org.tb.dailyreport.TimereportDAO; import org.tb.employee.Employeecontract; import org.tb.order.Employeeorder; @@ -23,18 +24,18 @@ public class VacationViewer implements Serializable { private static final long serialVersionUID = 1L; private final Employeecontract employeecontract; private String suborderSign; - private double budget; + private Duration budget; private int usedVacationMinutes; public VacationViewer(Employeecontract employeecontract) { this.employeecontract = employeecontract; } - public double getBudget() { + public Duration getBudget() { return budget; } - public void setBudget(double budget) { + public void setBudget(Duration budget) { this.budget = budget; } @@ -59,7 +60,7 @@ public void addVacationMinutes(int minutes) { } public boolean isVacationBudgetExceeded() { - return usedVacationMinutes > (budget * 60); + return usedVacationMinutes > budget.toMinutes(); } public String getUsedVacationString() { @@ -67,8 +68,7 @@ public String getUsedVacationString() { usedVacation.append(timeFormatMinutes(this.usedVacationMinutes)); BigDecimal dailyWorkingTimeMinutes = BigDecimal - .valueOf(employeecontract.getDailyWorkingTime()) - .multiply(BigDecimal.valueOf(60)); + .valueOf(employeecontract.getDailyWorkingTime().toMinutes()); if(dailyWorkingTimeMinutes.compareTo(BigDecimal.ZERO) > 0) { BigDecimal usedVacationDays = BigDecimal.valueOf(this.usedVacationMinutes) .setScale(2, DOWN) @@ -86,14 +86,12 @@ public String getUsedVacationString() { public String getBudgetVacationString() { StringBuilder budgetVacation = new StringBuilder(); - budgetVacation.append(timeFormatHours(this.budget)); + budgetVacation.append(DurationUtils.format(this.budget)); BigDecimal dailyWorkingTimeMinutes = BigDecimal - .valueOf(employeecontract.getDailyWorkingTime()) - .multiply(BigDecimal.valueOf(60)); + .valueOf(employeecontract.getDailyWorkingTime().toMinutes()); if(dailyWorkingTimeMinutes.compareTo(BigDecimal.ZERO) > 0) { - BigDecimal usedVacationDays = BigDecimal.valueOf(this.budget) - .multiply(BigDecimal.valueOf(60)) + BigDecimal usedVacationDays = BigDecimal.valueOf(this.budget.toMinutes()) .setScale(2, DOWN) .divide(dailyWorkingTimeMinutes, DOWN); NumberFormat nf = NumberFormat.getNumberInstance(GERMAN); diff --git a/src/main/java/org/tb/dailyreport/viewhelper/matrix/DayAndWorkingHourCount.java b/src/main/java/org/tb/dailyreport/viewhelper/matrix/DayAndWorkingHourCount.java index b47e24137..858b06523 100644 --- a/src/main/java/org/tb/dailyreport/viewhelper/matrix/DayAndWorkingHourCount.java +++ b/src/main/java/org/tb/dailyreport/viewhelper/matrix/DayAndWorkingHourCount.java @@ -1,21 +1,21 @@ package org.tb.dailyreport.viewhelper.matrix; -import static org.tb.common.util.TimeFormatUtils.timeFormatHours; - +import java.time.Duration; import java.time.LocalDate; import lombok.Data; +import org.tb.common.util.DurationUtils; @Data public class DayAndWorkingHourCount { private int day; - private double workingHour; + private Duration workingHour; private LocalDate date; private boolean publicHoliday; private boolean satSun; private String weekDay; private String publicHolidayName; - public DayAndWorkingHourCount(int day, double workingHour, LocalDate date) { + public DayAndWorkingHourCount(int day, Duration workingHour, LocalDate date) { this.day = day; this.date = date; this.workingHour = workingHour; @@ -25,13 +25,8 @@ public DayAndWorkingHourCount(int day, double workingHour, LocalDate date) { this.publicHolidayName = null; } - public double getRoundWorkingHour() { - long duration = (long) (workingHour * 100); - return (double) duration / 100.0; - } - public String getWorkingHourString() { - return timeFormatHours(workingHour); + return DurationUtils.format(workingHour); } public String getDayString() { diff --git a/src/main/java/org/tb/dailyreport/viewhelper/matrix/MatrixHelper.java b/src/main/java/org/tb/dailyreport/viewhelper/matrix/MatrixHelper.java index 31146b1b0..8ef3cf5e4 100644 --- a/src/main/java/org/tb/dailyreport/viewhelper/matrix/MatrixHelper.java +++ b/src/main/java/org/tb/dailyreport/viewhelper/matrix/MatrixHelper.java @@ -17,9 +17,7 @@ import static java.time.DayOfWeek.THURSDAY; import static java.time.DayOfWeek.TUESDAY; import static java.time.DayOfWeek.WEDNESDAY; -import static org.tb.common.GlobalConstants.MINUTES_PER_HOUR; import static org.tb.common.GlobalConstants.SUBORDER_INVOICE_YES; -import static org.tb.common.util.DateUtils.format; import static org.tb.common.util.DateUtils.formatDayOfMonth; import static org.tb.common.util.DateUtils.formatMonth; import static org.tb.common.util.DateUtils.formatYear; @@ -28,6 +26,7 @@ import static org.tb.common.util.DateUtils.today; import java.time.DayOfWeek; +import java.time.Duration; import java.time.LocalDate; import java.util.ArrayList; import java.util.Collections; @@ -157,7 +156,7 @@ public ReportWrapper getEmployeeMatrix(LocalDate dateFirst, LocalDate dateLast, List publicHolidayList = phDAO.getPublicHolidaysBetween(dateFirst, dateLast); List dayHoursCount = new ArrayList<>(); - double dayHoursTarget = fillDayHoursCount(dateFirst, dateLast, validFrom, validUntil, dayHoursCount, publicHolidayList); + int workdayCount = fillDayHoursCount(dateFirst, dateLast, validFrom, validUntil, dayHoursCount, publicHolidayList); //setting publicholidays(status and name) and weekend for dayandworkinghourcount and bookingday in mergedreportlist handlePublicHolidays(dateFirst, dateLast, mergedReportList, dayHoursCount, publicHolidayList); @@ -166,28 +165,27 @@ public ReportWrapper getEmployeeMatrix(LocalDate dateFirst, LocalDate dateLast, Collections.sort(mergedReportList); //calculate dayhourssum - double dayHoursSum = 0.0; + Duration dayHoursSum = Duration.ZERO; for (DayAndWorkingHourCount dayAndWorkingHourCount : dayHoursCount) { - dayHoursSum += dayAndWorkingHourCount.getWorkingHour(); + dayHoursSum = dayHoursSum.plus(dayAndWorkingHourCount.getWorkingHour()); } - dayHoursSum = ((double) Math.round(dayHoursSum * 100)) / 100; + + Duration dayHoursTarget = Duration.ZERO; //calculate dayhourstarget if (employeeContractId == -1) { List employeeContractList = ecDAO.getEmployeeContracts(); - double dailyWorkingTime = 0.0; + Duration dailyWorkingTime = Duration.ZERO; for (Employeecontract employeeContract : employeeContractList) { - dailyWorkingTime += employeeContract.getDailyWorkingTime(); + dailyWorkingTime = dailyWorkingTime.plus(employeeContract.getDailyWorkingTime()); } - dayHoursTarget = dayHoursTarget * dailyWorkingTime; + dayHoursTarget = dailyWorkingTime.multipliedBy(workdayCount); } else { - dayHoursTarget = dayHoursTarget * Objects.requireNonNull(employeecontract).getDailyWorkingTime(); + dayHoursTarget = employeecontract.getDailyWorkingTime().multipliedBy(workdayCount); } - dayHoursTarget = ((double) Math.round(dayHoursTarget * 100)) / 100; //calculate dayhoursdiff - double dayHoursDiff = dayHoursSum - dayHoursTarget; - dayHoursDiff = ((double) Math.round(dayHoursDiff * 100)) / 100; + Duration dayHoursDiff = dayHoursSum.minus(dayHoursTarget); return new ReportWrapper(mergedReportList, dayHoursCount, dayHoursSum, dayHoursTarget, dayHoursDiff); } @@ -209,20 +207,20 @@ private String extendedTaskDescription(Timereport tr, boolean withSign) { return sb.toString(); } - private double fillDayHoursCount(LocalDate dateFirst, LocalDate dateLast, LocalDate validFrom, LocalDate validUntil, List dayHoursCount, List publicHolidayList) { + private int fillDayHoursCount(LocalDate dateFirst, LocalDate dateLast, LocalDate validFrom, LocalDate validUntil, List dayHoursCount, List publicHolidayList) { //fill dayhourscount list with dayandworkinghourcounts for the time between dateFirst and dateLast LocalDate dateLoop = dateFirst; int day = 0; while (dateLoop.isAfter(dateFirst) && dateLoop.isBefore(dateLast) || dateLoop.equals(dateFirst) || dateLoop.equals(dateLast)) { day++; - dayHoursCount.add(new DayAndWorkingHourCount(day, 0, dateLoop)); + dayHoursCount.add(new DayAndWorkingHourCount(day, Duration.ZERO, dateLoop)); dateLoop = DateUtils.addDays(dateLoop, 1); } day = 0; dateLoop = dateFirst; - double dayHoursTarget = 0.0; + int workdayCount = 0; while (dateLoop.isAfter(dateFirst) && dateLoop.isBefore(dateLast) || dateLoop.equals(dateFirst) || dateLoop.equals(dateLast)) { day++; @@ -241,7 +239,7 @@ private double fillDayHoursCount(LocalDate dateFirst, LocalDate dateLast, LocalD dateLoop.isBefore(validUntil) || dateLoop.equals(validFrom) || dateLoop.equals(validUntil))) { - dayHoursTarget++; + workdayCount++; } } //setting publicholidays and weekend for dayhourscount(status and name) @@ -261,7 +259,7 @@ private double fillDayHoursCount(LocalDate dateFirst, LocalDate dateLast, LocalD } dateLoop = DateUtils.addDays(dateLoop, 1); } - return dayHoursTarget; + return workdayCount; } private void handlePublicHolidays(LocalDate dateFirst, LocalDate dateLast, List mergedReportList, List dayHoursCount, List publicHolidayList) { @@ -280,9 +278,16 @@ private void handlePublicHolidays(LocalDate dateFirst, LocalDate dateLast, List< for (int i = 0; i < dayHoursCount.size(); i++) { DayAndWorkingHourCount dayAndWorkingHourCount = dayHoursCount.get(i); if (dayAndWorkingHourCount.getDay() == day) { - DayAndWorkingHourCount otherDayAndWorkingHourCount = new DayAndWorkingHourCount(day, - (bookingDay.getDurationHours() * MINUTES_PER_HOUR + bookingDay.getDurationMinutes() + dayAndWorkingHourCount.getWorkingHour() * MINUTES_PER_HOUR) / MINUTES_PER_HOUR, bookingDay - .getDate()); + Duration workingHour = Duration.ZERO; + workingHour = workingHour + .plusHours(bookingDay.getDurationHours()) + .plusMinutes(bookingDay.getDurationMinutes()) + .plus(dayAndWorkingHourCount.getWorkingHour()); + DayAndWorkingHourCount otherDayAndWorkingHourCount = new DayAndWorkingHourCount( + day, + workingHour, + bookingDay.getDate() + ); otherDayAndWorkingHourCount.setPublicHoliday(dayAndWorkingHourCount.isPublicHoliday()); otherDayAndWorkingHourCount.setPublicHolidayName(dayAndWorkingHourCount.getPublicHolidayName()); otherDayAndWorkingHourCount.setSatSun(dayAndWorkingHourCount.isSatSun()); diff --git a/src/main/java/org/tb/dailyreport/viewhelper/matrix/MergedReport.java b/src/main/java/org/tb/dailyreport/viewhelper/matrix/MergedReport.java index 0586d4dec..d25704478 100644 --- a/src/main/java/org/tb/dailyreport/viewhelper/matrix/MergedReport.java +++ b/src/main/java/org/tb/dailyreport/viewhelper/matrix/MergedReport.java @@ -90,11 +90,6 @@ public int compareTo(MergedReport o) { return (this.customOrder.getSign() + this.subOrder.getSign()).compareTo(o.customOrder.getSign() + o.subOrder.getSign()); } - public Double getRoundSum() { - long duration = (long) (sumHours * 100); - return (double) duration / 100.0; - } - public String getSumString() { return timeFormatMinutes(sumMinutes); } diff --git a/src/main/java/org/tb/dailyreport/viewhelper/matrix/ReportWrapper.java b/src/main/java/org/tb/dailyreport/viewhelper/matrix/ReportWrapper.java index a2f57b5f6..d2e5d52e5 100644 --- a/src/main/java/org/tb/dailyreport/viewhelper/matrix/ReportWrapper.java +++ b/src/main/java/org/tb/dailyreport/viewhelper/matrix/ReportWrapper.java @@ -1,18 +1,21 @@ package org.tb.dailyreport.viewhelper.matrix; -import static org.tb.common.util.TimeFormatUtils.timeFormatHours; +import static org.tb.common.util.DurationUtils.format; +import java.time.Duration; import java.util.List; +import lombok.Getter; +@Getter public class ReportWrapper { private final List mergedReportList; private final List dayAndWorkingHourCountList; - private final double dayHoursSum; - private final double dayHoursTarget; - private double dayHoursDiff; + private final Duration dayHoursSum; + private final Duration dayHoursTarget; + private final Duration dayHoursDiff; - public ReportWrapper(List mergedReportList, List dayAndWorkingHourCountList, double dayHoursSum, double dayHoursTarget, double dayHoursDiff) { + public ReportWrapper(List mergedReportList, List dayAndWorkingHourCountList, Duration dayHoursSum, Duration dayHoursTarget, Duration dayHoursDiff) { this.mergedReportList = mergedReportList; this.dayAndWorkingHourCountList = dayAndWorkingHourCountList; this.dayHoursSum = dayHoursSum; @@ -20,40 +23,16 @@ public ReportWrapper(List mergedReportList, List getDayAndWorkingHourCountList() { - return dayAndWorkingHourCountList; - } - - public List getMergedReportList() { - return mergedReportList; + return format(dayHoursDiff); } } diff --git a/src/main/java/org/tb/employee/AddEmployeeContractForm.java b/src/main/java/org/tb/employee/AddEmployeeContractForm.java index 31a91b451..3dca599b6 100644 --- a/src/main/java/org/tb/employee/AddEmployeeContractForm.java +++ b/src/main/java/org/tb/employee/AddEmployeeContractForm.java @@ -22,7 +22,7 @@ public class AddEmployeeContractForm extends ActionForm { private String validFrom; private String validUntil; private Boolean freelancer; - private Double dailyworkingtime; + private String dailyworkingtime; private Integer yearlyvacation; private long employee; private long supervisorid; @@ -45,10 +45,10 @@ public void reset(ActionMapping mapping, HttpServletRequest request) { validUntil = ""; freelancer = Boolean.FALSE; hide = Boolean.FALSE; - dailyworkingtime = 8.0; - initialOvertime = "0.0"; + dailyworkingtime = "8:00"; + initialOvertime = "0:00"; yearlyvacation = 30; - newOvertime = "0.0"; + newOvertime = "0:00"; } } diff --git a/src/main/java/org/tb/employee/EditEmployeecontractAction.java b/src/main/java/org/tb/employee/EditEmployeecontractAction.java index 559fe2cb0..b40d13891 100644 --- a/src/main/java/org/tb/employee/EditEmployeecontractAction.java +++ b/src/main/java/org/tb/employee/EditEmployeecontractAction.java @@ -2,6 +2,7 @@ import static org.tb.common.util.DateUtils.today; +import java.time.Duration; import java.time.LocalDate; import java.util.List; import javax.servlet.http.HttpServletRequest; @@ -13,6 +14,7 @@ import org.tb.common.GlobalConstants; import org.tb.common.struts.LoginRequiredAction; import org.tb.common.util.DateUtils; +import org.tb.common.util.DurationUtils; import org.tb.dailyreport.Vacation; /** @@ -45,13 +47,12 @@ public ActionForward executeAuthenticated(ActionMapping mapping, AddEmployeeCont // get overtime-entries List overtimes = overtimeDAO.getOvertimesByEmployeeContractId(ecId); - double totalOvertime = 0.0; + Duration totalOvertime = Duration.ZERO; for (Overtime overtime : overtimes) { - totalOvertime += overtime.getTime(); + totalOvertime = totalOvertime.plus(overtime.getTimeMinutes()); } - totalOvertime = Math.rint(totalOvertime * 100) / 100; request.getSession().setAttribute("overtimes", overtimes); - request.getSession().setAttribute("totalovertime", totalOvertime); + request.getSession().setAttribute("totalovertime", DurationUtils.format(totalOvertime)); // set day string for overime LocalDate now = today(); @@ -85,8 +86,8 @@ private void setFormEntries(HttpServletRequest request, AddEmployeeContractForm ecForm.setTaskdescription(ec.getTaskDescription()); ecForm.setFreelancer(ec.getFreelancer()); ecForm.setHide(ec.getHide()); - ecForm.setDailyworkingtime(ec.getDailyWorkingTime()); - if (ec.getVacations().size() > 0) { + ecForm.setDailyworkingtime(DurationUtils.format(ec.getDailyWorkingTime())); + if (!ec.getVacations().isEmpty()) { // actually, vacation entitlement is a constant value // for an employee (not year-dependent), so just take the // first vacation entry to set the form value diff --git a/src/main/java/org/tb/employee/Employeecontract.java b/src/main/java/org/tb/employee/Employeecontract.java index 54b9606f9..cbf6ce348 100644 --- a/src/main/java/org/tb/employee/Employeecontract.java +++ b/src/main/java/org/tb/employee/Employeecontract.java @@ -3,13 +3,16 @@ import static org.tb.common.util.DateUtils.format; import java.io.Serializable; +import java.time.Duration; import java.time.LocalDate; import java.util.List; +import javax.persistence.Convert; import javax.persistence.Entity; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.OneToOne; +import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; import org.hibernate.annotations.Cache; @@ -19,13 +22,19 @@ import org.hibernate.annotations.Fetch; import org.hibernate.annotations.FetchMode; import org.tb.common.AuditedEntity; +import org.tb.common.DurationMinutesConverter; import org.tb.common.GlobalConstants; import org.tb.common.util.DateUtils; import org.tb.dailyreport.Timereport; import org.tb.dailyreport.Vacation; import org.tb.order.Employeeorder; -@Getter +/** + * The duration fields have their entity attribute names with minutes to indicate the value in the database. + * In the Java object world, their getters/setter are named without the minutes ending, because Duration + * objects are not minutes in reality. + */ +@Getter() @Setter @Entity @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) @@ -41,21 +50,24 @@ public class Employeecontract extends AuditedEntity implements Serializable { private LocalDate validFrom; private LocalDate validUntil; - private Double dailyWorkingTime; + + @Convert(converter = DurationMinutesConverter.class) + @Getter(AccessLevel.NONE) + @Setter(AccessLevel.NONE) + private Duration dailyWorkingTimeMinutes; + private Boolean freelancer; private String taskDescription; private LocalDate fixedUntil; private LocalDate reportAcceptanceDate; private LocalDate reportReleaseDate; private Boolean hide; - /** - * static overtime from begin of employeecontract to reportAcceptanceDate - */ - private double overtimeStatic; - /** - * boolean for new overtime computation: if true, overtimeStatic has not been set before - */ - private Boolean useOvertimeOld; + + /** static overtime ranging from begin of employeecontract to reportAcceptanceDate */ + @Convert(converter = DurationMinutesConverter.class) + @Getter(AccessLevel.NONE) + @Setter(AccessLevel.NONE) + private Duration overtimeStaticMinutes; @OneToOne // FIXME check if ManyToOne? @@ -88,6 +100,8 @@ public class Employeecontract extends AuditedEntity implements Serializable { @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) private List vacations; + + public Boolean getFreelancer() { if (freelancer == null) { freelancer = false; @@ -127,7 +141,7 @@ public boolean isValidAt(LocalDate date) { } public Integer getVacationEntitlement() { - if (vacations != null && vacations.size() > 0) { + if (vacations != null && !vacations.isEmpty()) { // actually, vacation entitlement is a constant value // for an employee (not year-dependent), so just take the // first vacation entry to get the value @@ -211,4 +225,20 @@ public boolean getAcceptanceWarningByDate(LocalDate date) { return acceptanceWarning; } + public Duration getDailyWorkingTime() { + return dailyWorkingTimeMinutes; + } + + public void setDailyWorkingTime(Duration value) { + this.dailyWorkingTimeMinutes = value; + } + + public Duration getOvertimeStatic() { + return overtimeStaticMinutes; + } + + public void setOvertimeStatic(Duration overtimeStaticMinutes) { + this.overtimeStaticMinutes = overtimeStaticMinutes; + } + } diff --git a/src/main/java/org/tb/employee/Overtime.java b/src/main/java/org/tb/employee/Overtime.java index e97ddf392..ec36ad11a 100644 --- a/src/main/java/org/tb/employee/Overtime.java +++ b/src/main/java/org/tb/employee/Overtime.java @@ -1,6 +1,12 @@ package org.tb.employee; +import static org.tb.common.GlobalConstants.MINUTES_PER_HOUR; + import java.io.Serializable; +import java.math.BigDecimal; +import java.time.Duration; +import javax.persistence.Column; +import javax.persistence.Convert; import javax.persistence.Entity; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; @@ -13,6 +19,7 @@ import org.hibernate.annotations.Fetch; import org.hibernate.annotations.FetchMode; import org.tb.common.AuditedEntity; +import org.tb.common.DurationMinutesConverter; import org.tb.common.util.DateUtils; @Getter @@ -30,10 +37,13 @@ public class Overtime extends AuditedEntity implements Serializable { private Employeecontract employeecontract; private String comment; - private Double time; + + @Convert(converter = DurationMinutesConverter.class) + private Duration timeMinutes; public String getCreatedString() { return DateUtils.formatDateTime(getCreated(), "yyyy-MM-dd HH:mm"); } } + diff --git a/src/main/java/org/tb/employee/StoreEmployeecontractAction.java b/src/main/java/org/tb/employee/StoreEmployeecontractAction.java index 827226d3c..4caa01a97 100644 --- a/src/main/java/org/tb/employee/StoreEmployeecontractAction.java +++ b/src/main/java/org/tb/employee/StoreEmployeecontractAction.java @@ -4,6 +4,7 @@ import static org.tb.common.util.DateUtils.today; import java.text.ParseException; +import java.time.Duration; import java.time.LocalDate; import java.util.ArrayList; import java.util.HashSet; @@ -23,6 +24,7 @@ import org.tb.common.GlobalConstants; import org.tb.common.struts.LoginRequiredAction; import org.tb.common.util.DateUtils; +import org.tb.common.util.DurationUtils; import org.tb.dailyreport.Timereport; import org.tb.dailyreport.TimereportDAO; import org.tb.dailyreport.Vacation; @@ -61,7 +63,7 @@ public ActionForward executeAuthenticated(ActionMapping mapping, AddEmployeeCont LocalDate newValue; if (howMuch != 0) { ActionMessages errorMessages = validateDate(request, ecForm, which); - if (errorMessages.size() > 0) { + if (!errorMessages.isEmpty()) { return mapping.getInputForward(); } @@ -95,72 +97,38 @@ public ActionForward executeAuthenticated(ActionMapping mapping, AddEmployeeCont } // new overtime - double overtimeDouble = 0.0; if (ecForm.getNewOvertime() != null) { String overtimeString = ecForm.getNewOvertime(); - try { - // test wether there are too many numbers after point-seperator - if (overtimeString.contains(".") && overtimeString.length() - overtimeString.indexOf(".") > 2) { - //if yes, cut off - overtimeDouble = Double.parseDouble(overtimeString.substring(0, overtimeString.indexOf('.') + 3)); - } else { - overtimeDouble = Double.parseDouble(overtimeString); - } - - if (overtimeDouble == 0) { - errors.add("newOvertime", new ActionMessage("form.employeecontract.error.initialovertime.wrongformat2")); - } - - if (!GenericValidator.isDouble(overtimeString) || - !GenericValidator.isInRange(overtimeDouble, - GlobalConstants.MIN_OVERTIME, GlobalConstants.MAX_OVERTIME)) { + // validate comment + if (ecForm.getNewOvertimeComment().length() > GlobalConstants.EMPLOYEECONTRACT_OVERTIME_COMMENT_MAX_LENGTH) { + errors.add("newOvertimeComment", new ActionMessage("form.employeecontract.error.overtimecomment.toolong")); + } else if (ecForm.getNewOvertimeComment().trim().isEmpty()) { + errors.add("newOvertimeComment", new ActionMessage("form.employeecontract.error.overtimecomment.missing")); + } + if(!DurationUtils.validateDuration(overtimeString)) { + errors.add("newOvertime", new ActionMessage("form.employeecontract.error.initialovertime.wrongformat")); + } else { + Duration overtimeMinutes = DurationUtils.parseDuration(overtimeString); + if(overtimeMinutes.isZero()) { errors.add("newOvertime", new ActionMessage("form.employeecontract.error.initialovertime.wrongformat")); } - - ecForm.setNewOvertime("" + overtimeDouble); - - double time = overtimeDouble * 100000; - - if (time >= 0) { - time += 0.5; - } else { - time -= 0.5; - } - int time2 = (int) time; - int modulo = time2 % 5000; - - if (modulo != 0) { - errors.add("newOvertime", new ActionMessage("form.employeecontract.error.initialovertime.wrongformat2")); - } - } catch (NumberFormatException e) { - errors.add("newOvertime", new ActionMessage("form.employeecontract.error.initialovertime.wrongformat")); + } + if (!errors.isEmpty()) { + saveErrors(request, errors); + //setFormEntries(request, ecForm, ec); // warum???? + return mapping.getInputForward(); } } - // new comment - if (ecForm.getNewOvertimeComment().length() > GlobalConstants.EMPLOYEECONTRACT_OVERTIME_COMMENT_MAX_LENGTH) { - errors.add("newOvertimeComment", new ActionMessage("form.employeecontract.error.overtimecomment.toolong")); - } else if (ecForm.getNewOvertimeComment().trim().length() == 0) { - errors.add("newOvertimeComment", new ActionMessage("form.employeecontract.error.overtimecomment.missing")); - } - - saveErrors(request, errors); - - // get employeecontract - long ecId; - ecId = Long.parseLong(request.getSession().getAttribute("ecId").toString()); - Employeecontract ec = employeecontractDAO.getEmployeeContractByIdInitializeEager(ecId); - - if (errors.size() > 0) { - setFormEntries(request, ecForm, ec); - return mapping.getInputForward(); - } + // validation completed -> create overtime entity and store it + long ecId = Long.parseLong(request.getSession().getAttribute("ecId").toString()); + Employeecontract ec = employeecontractDAO.getEmployeeContractById(ecId); Overtime overtime = new Overtime(); overtime.setComment(ecForm.getNewOvertimeComment()); overtime.setEmployeecontract(ec); - overtime.setTime(overtimeDouble); + overtime.setTimeMinutes(DurationUtils.parseDuration(ecForm.getNewOvertime())); Employee loginEmployee = (Employee) request.getSession().getAttribute("loginEmployee"); @@ -168,23 +136,16 @@ public ActionForward executeAuthenticated(ActionMapping mapping, AddEmployeeCont // refresh list of overtime adjustments List overtimes = overtimeDAO.getOvertimesByEmployeeContractId(ecId); - Double totalOvertime = 0.0; + Duration totalOvertime = Duration.ZERO; for (Overtime ot : overtimes) { - totalOvertime += ot.getTime(); + totalOvertime = totalOvertime.plus(ot.getTimeMinutes()); } - totalOvertime = Math.rint(totalOvertime * 100) / 100; - // optimizing totalOvertime - String tOString = totalOvertime.toString(); - if (tOString.length() - tOString.indexOf(".") > 2) { - tOString = tOString.substring(0, tOString.indexOf(".") + 3); - totalOvertime = Double.parseDouble(tOString); - } request.getSession().setAttribute("overtimes", overtimes); - request.getSession().setAttribute("totalovertime", totalOvertime); + request.getSession().setAttribute("totalovertime", DurationUtils.format(totalOvertime)); // reset form - ecForm.setNewOvertime("0.0"); + ecForm.setNewOvertime("0:00"); ecForm.setNewOvertimeComment(""); setFormEntries(request, ecForm, ec); @@ -217,13 +178,10 @@ public ActionForward executeAuthenticated(ActionMapping mapping, AddEmployeeCont } Employee theEmployee = employeeDAO.getEmployeeById(employeeId); - - // EmployeeHelper eh = new EmployeeHelper(); - ec.setEmployee(theEmployee); ActionMessages errorMessages = validateFormData(request, ecForm, theEmployee, ec); - if (errorMessages.size() > 0) { + if (!errorMessages.isEmpty()) { return mapping.getInputForward(); } @@ -318,7 +276,7 @@ public ActionForward executeAuthenticated(ActionMapping mapping, AddEmployeeCont ec.setTaskDescription(ecForm.getTaskdescription()); ec.setFreelancer(ecForm.getFreelancer()); ec.setHide(ecForm.getHide()); - ec.setDailyWorkingTime(ecForm.getDailyworkingtime()); + ec.setDailyWorkingTime(DurationUtils.parseDuration(ecForm.getDailyworkingtime())); // if necessary, add new vacation for current year Vacation va = null; @@ -335,12 +293,6 @@ public ActionForward executeAuthenticated(ActionMapping mapping, AddEmployeeCont } } - if (newContract) { - // default-value for useOvertimeOld in new employeecontract: False - // useOvertimeOld is only needed at start of Release 1.83, because of the new overtime computation - ec.setUseOvertimeOld(false); - } - employeecontractDAO.save(ec, loginEmployee); if (newContract) { @@ -349,10 +301,10 @@ public ActionForward executeAuthenticated(ActionMapping mapping, AddEmployeeCont overtime.setEmployeecontract(ec); // if no value is selected, set 0.0 if (ecForm.getInitialOvertime() == null) { - ecForm.setInitialOvertime("0.0"); + ecForm.setInitialOvertime("0:00"); } // the ecForm entry is checked before - overtime.setTime(Double.valueOf(ecForm.getInitialOvertime())); + overtime.setTimeMinutes(DurationUtils.parseDuration(ecForm.getInitialOvertime())); overtimeDAO.save(overtime, loginEmployee); } @@ -423,23 +375,12 @@ private ActionMessages validateDate(HttpServletRequest request, AddEmployeeContr errors = new ActionMessages(); } - String dateString = ""; if (which.equals("from")) { - dateString = ecForm.getValidFrom().trim(); - } else { - dateString = ecForm.getValidUntil().trim(); - } - - int minus = 0; - for (int i = 0; i < dateString.length(); i++) { - if (dateString.charAt(i) == '-') { - minus++; - } - } - if (dateString.length() != 10 || minus != 2) { - if (which.equals("from")) { + if(!DateUtils.validateDate(ecForm.getValidFrom())) { errors.add("validFrom", new ActionMessage("form.timereport.error.date.wrongformat")); - } else { + } + } else { + if(!DateUtils.validateDate(ecForm.getValidUntil())) { errors.add("validUntil", new ActionMessage("form.timereport.error.date.wrongformat")); } } @@ -461,15 +402,15 @@ private ActionMessages validateFormData(HttpServletRequest request, AddEmployeeC // check date formats (must now be 'yyyy-MM-dd') String dateFromString = ecForm.getValidFrom().trim(); - boolean dateError = DateUtils.validateDate(dateFromString); - if (dateError) { + boolean dateValid = DateUtils.validateDate(dateFromString); + if (!dateValid) { errors.add("validFrom", new ActionMessage("form.timereport.error.date.wrongformat")); } String dateUntilString = ecForm.getValidUntil().trim(); if (!dateUntilString.equals("")) { - dateError = DateUtils.validateDate(dateUntilString); - if (dateError) { + dateValid = DateUtils.validateDate(dateUntilString); + if (!dateValid) { errors.add("validUntil", new ActionMessage( "form.timereport.error.date.wrongformat")); } @@ -545,43 +486,13 @@ private ActionMessages validateFormData(HttpServletRequest request, AddEmployeeC } // check dailyworkingtime format - if (!GenericValidator.isDouble(ecForm.getDailyworkingtime().toString()) || - !GenericValidator.isInRange(ecForm.getDailyworkingtime(), - 0.0, GlobalConstants.MAX_DEBITHOURS)) { + if (!DurationUtils.validateDuration(ecForm.getDailyworkingtime())) { errors.add("dailyworkingtime", new ActionMessage("form.employeecontract.error.dailyworkingtime.wrongformat")); } - double time = ecForm.getDailyworkingtime() * 100000; - time += 0.5; - int time2 = (int) time; - int modulo = time2 % 5000; - ecForm.setDailyworkingtime(time2 / 100000.0); - - if (modulo != 0) { - errors.add("dailyworkingtime", new ActionMessage("form.employeecontract.error.dailyworkingtime.wrongformat2")); - } // check initial overtime if (ecForm.getInitialOvertime() != null) { - String initialOvertimeString = ecForm.getInitialOvertime(); - try { - double initialOvertimeDouble = Double.parseDouble(initialOvertimeString); - - if (!GenericValidator.isDouble(initialOvertimeString) || - !GenericValidator.isInRange(initialOvertimeDouble, - GlobalConstants.MIN_OVERTIME, GlobalConstants.MAX_OVERTIME)) { - errors.add("initialOvertime", new ActionMessage("form.employeecontract.error.initialovertime.wrongformat")); - } - - time = initialOvertimeDouble * 100000; - time += 0.5; - time2 = (int) time; - modulo = time2 % 5000; - ecForm.setInitialOvertime("" + time2 / 100000.0); - - if (modulo != 0) { - errors.add("initialOvertime", new ActionMessage("form.employeecontract.error.initialovertime.wrongformat2")); - } - } catch (NumberFormatException e) { + if (!DurationUtils.validateDuration(ecForm.getInitialOvertime())) { errors.add("initialOvertime", new ActionMessage("form.employeecontract.error.initialovertime.wrongformat")); } } @@ -637,8 +548,8 @@ private void setFormEntries(HttpServletRequest request, AddEmployeeContractForm ecForm.setTaskdescription(ec.getTaskDescription()); ecForm.setFreelancer(ec.getFreelancer()); ecForm.setHide(ec.getHide()); - ecForm.setDailyworkingtime(ec.getDailyWorkingTime()); - if (ec.getVacations().size() > 0) { + ecForm.setDailyworkingtime(DurationUtils.format(ec.getDailyWorkingTime())); + if (!ec.getVacations().isEmpty()) { // actually, vacation entitlement is a constant value // for an employee (not year-dependent), so just take the // first vacation entry to set the form value diff --git a/src/main/java/org/tb/invoice/InvoiceSuborderHelper.java b/src/main/java/org/tb/invoice/InvoiceSuborderHelper.java index 988f80b00..bb7ff6fc8 100644 --- a/src/main/java/org/tb/invoice/InvoiceSuborderHelper.java +++ b/src/main/java/org/tb/invoice/InvoiceSuborderHelper.java @@ -1,13 +1,14 @@ package org.tb.invoice; -import static org.tb.common.util.TimeFormatUtils.decimalFormatHours; import static org.tb.common.util.TimeFormatUtils.decimalFormatMinutes; -import static org.tb.common.util.TimeFormatUtils.timeFormatHours; import static org.tb.common.util.TimeFormatUtils.timeFormatMinutes; +import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.List; +import org.springframework.boot.convert.DurationFormat; +import org.tb.common.util.DurationUtils; import org.tb.dailyreport.Timereport; import org.tb.dailyreport.TimereportDAO; import org.tb.employee.Employee; @@ -104,17 +105,11 @@ public long getTotalActualminutesPrint() { } private long getTotalActualminutesHelper(boolean print) { - long actualminutes = 0; - for (InvoiceTimereportHelper invoiceTimereportViewHelper : invoiceTimereportViewHelperList) { - if (!print) { - actualminutes += invoiceTimereportViewHelper.getDurationminutes(); - actualminutes += invoiceTimereportViewHelper.getDurationhours() * 60; - } else if (invoiceTimereportViewHelper.isVisible()) { - actualminutes += invoiceTimereportViewHelper.getDurationminutes(); - actualminutes += invoiceTimereportViewHelper.getDurationhours() * 60; - } - } - return actualminutes; + return invoiceTimereportViewHelperList.stream() + .filter(v -> !print || v.isVisible()) + .map(v -> Duration.ofHours(v.getDurationhours()).plusMinutes(v.getDurationminutes())) + .reduce(Duration.ZERO, Duration::plus) + .toMinutes(); } public List getInvoiceTimereportViewHelperList() { @@ -177,20 +172,20 @@ public void setCustomerorder(Customerorder order) { suborder.setCustomerorder(order); } - public Double getDebithours() { + public Duration getDebithours() { return suborder.getDebithours(); } - public void setDebithours(Double debithours) { + public void setDebithours(Duration debithours) { suborder.setDebithours(debithours); } public String getDebithoursString() { String result = ""; - if (suborder.getDebithours() != null && suborder.getDebithours() != 0.0) { - result = timeFormatHours(suborder.getDebithours()); + if (suborder.getDebithours() != null && !suborder.getDebithours().isZero()) { + result = DurationUtils.format(suborder.getDebithours()); // add decimal value - helps the backoffice - result += " (" + decimalFormatHours(suborder.getDebithours()) + ")"; + result += " (" + DurationUtils.decimalFormat((suborder.getDebithours())) + ")"; } return result; } diff --git a/src/main/java/org/tb/invoice/ShowInvoiceAction.java b/src/main/java/org/tb/invoice/ShowInvoiceAction.java index 5123667cc..b2e4f4547 100644 --- a/src/main/java/org/tb/invoice/ShowInvoiceAction.java +++ b/src/main/java/org/tb/invoice/ShowInvoiceAction.java @@ -4,6 +4,7 @@ import static org.tb.common.util.TimeFormatUtils.decimalFormatMinutes; import static org.tb.common.util.TimeFormatUtils.timeFormatMinutes; +import java.time.Duration; import java.time.LocalDate; import java.time.YearMonth; import java.util.ArrayList; @@ -22,6 +23,7 @@ import org.springframework.stereotype.Component; import org.tb.common.GlobalConstants; import org.tb.common.util.DateUtils; +import org.tb.common.util.DurationUtils; import org.tb.common.util.ExcelArchivierer; import org.tb.dailyreport.DailyReportAction; import org.tb.dailyreport.Timereport; @@ -266,7 +268,7 @@ public ActionForward executeAuthenticated(ActionMapping mapping, ShowInvoiceForm } } } - long actualMinutesSum = 0; + Duration actualMinutesSum = Duration.ZERO; int layerlimit = Integer.parseInt(showInvoiceForm.getLayerlimit()); for (InvoiceSuborderHelper invoiceSuborderViewHelper : suborderViewhelperList) { if (invoiceSuborderViewHelper.getLayer() <= layerlimit @@ -274,15 +276,15 @@ public ActionForward executeAuthenticated(ActionMapping mapping, ShowInvoiceForm if (invoiceSuborderViewHelper.isVisible()) { if (invoiceSuborderViewHelper.getLayer() < layerlimit || showInvoiceForm.getLayerlimit().equals("-1")) { - actualMinutesSum += invoiceSuborderViewHelper.getTotalActualminutesPrint(); + actualMinutesSum = actualMinutesSum.plusMinutes(invoiceSuborderViewHelper.getTotalActualminutesPrint()); } else { - actualMinutesSum += invoiceSuborderViewHelper.getDurationInMinutes(); + actualMinutesSum = actualMinutesSum.plusMinutes(invoiceSuborderViewHelper.getDurationInMinutes()); } } } } - request.getSession().setAttribute("actualminutessum", (double) actualMinutesSum); - request.getSession().setAttribute("printactualhourssum", timeFormatMinutes(actualMinutesSum) + " (" + decimalFormatMinutes(actualMinutesSum) + ")"); + request.getSession().setAttribute("actualminutessum", actualMinutesSum); + request.getSession().setAttribute("printactualhourssum", DurationUtils.format(actualMinutesSum) + " (" + DurationUtils.decimalFormat(actualMinutesSum) + ")"); request.getSession().setAttribute("titleactualhourstext", showInvoiceForm.getTitleactualhourstext()); request.getSession().setAttribute("titlecustomersigntext", showInvoiceForm.getTitlecustomersigntext()); request.getSession().setAttribute("titleinvoiceattachment", showInvoiceForm.getTitleinvoiceattachment()); diff --git a/src/main/java/org/tb/order/AddCustomerorderForm.java b/src/main/java/org/tb/order/AddCustomerorderForm.java index becb5157a..6adfb877b 100644 --- a/src/main/java/org/tb/order/AddCustomerorderForm.java +++ b/src/main/java/org/tb/order/AddCustomerorderForm.java @@ -31,7 +31,7 @@ public class AddCustomerorderForm extends ActionForm { private String responsibleCustomerContractually; private String orderCustomer; - private Double debithours; + private String debithours; private Byte debithoursunit; private int statusreport; diff --git a/src/main/java/org/tb/order/AddEmployeeOrderForm.java b/src/main/java/org/tb/order/AddEmployeeOrderForm.java index a11e6cd29..36502654c 100644 --- a/src/main/java/org/tb/order/AddEmployeeOrderForm.java +++ b/src/main/java/org/tb/order/AddEmployeeOrderForm.java @@ -1,5 +1,6 @@ package org.tb.order; +import java.time.Duration; import java.time.LocalDate; import javax.annotation.Nonnull; import javax.servlet.http.HttpServletRequest; @@ -24,7 +25,7 @@ public class AddEmployeeOrderForm extends ActionForm { private String sign; private String validFrom; private String validUntil; - private Double debithours; + private String debithours; private Byte debithoursunit; private String status; private String order; diff --git a/src/main/java/org/tb/order/AddSuborderForm.java b/src/main/java/org/tb/order/AddSuborderForm.java index 964ed25f0..e2f1018a7 100644 --- a/src/main/java/org/tb/order/AddSuborderForm.java +++ b/src/main/java/org/tb/order/AddSuborderForm.java @@ -32,7 +32,7 @@ public class AddSuborderForm extends ActionForm { private Boolean trainingFlag; private String validFrom; private String validUntil; - private Double debithours; + private String debithours; private Byte debithoursunit; private Boolean hide; private Long parentId; diff --git a/src/main/java/org/tb/order/CreateEmployeeorderAction.java b/src/main/java/org/tb/order/CreateEmployeeorderAction.java index b27386ebd..ebf92551b 100644 --- a/src/main/java/org/tb/order/CreateEmployeeorderAction.java +++ b/src/main/java/org/tb/order/CreateEmployeeorderAction.java @@ -11,6 +11,7 @@ import org.apache.struts.action.ActionMapping; import org.springframework.stereotype.Component; import org.tb.common.GlobalConstants; +import org.tb.common.util.DurationUtils; import org.tb.employee.Employee; import org.tb.employee.Employeecontract; import org.tb.employee.EmployeecontractDAO; @@ -83,7 +84,7 @@ public ActionForward executeAuthenticated(final ActionMapping mapping, // init form with first order and corresponding suborders final List theSuborders = new ArrayList<>(); request.getSession().setAttribute("suborders", theSuborders); - if (orderswithsuborders.size() > 0) { + if (!orderswithsuborders.isEmpty()) { Customerorder selectedCustomerorder; final Long orderId = (Long) request.getSession().getAttribute("currentOrderId"); @@ -121,24 +122,19 @@ public ActionForward executeAuthenticated(final ActionMapping mapping, if (!suborders.isEmpty()) { request.getSession().setAttribute("selectedsuborder", suborders.get(0)); } - if ((selectedCustomerorder.getSuborders() != null) && (selectedCustomerorder.getSuborders().size() > 0)) { + if ((selectedCustomerorder.getSuborders() != null) && (!selectedCustomerorder.getSuborders().isEmpty())) { employeeOrderForm.setSuborder(selectedCustomerorder.getSuborders().get(0).getSign()); employeeOrderForm.setSuborderId(selectedCustomerorder.getSuborders().get(0).getId()); } - /* suggest value */ - if (Objects.requireNonNull(selectedCustomerorder.getSuborders()).size() > 0) { - employeeOrderForm.setDebithours(selectedCustomerorder.getSuborders().get(0).getDebithours()); - } else { - employeeOrderForm.setDebithours(0.0); - } - - employeeOrderForm.setDebithoursunit((byte) -1); // default: no unit set - if (selectedCustomerorder.getSuborders().size() > 0 - && selectedCustomerorder.getSuborders().get(0).getDebithours() != null - && selectedCustomerorder.getSuborders().get(0).getDebithours() > 0.0) { + if (!selectedCustomerorder.getSuborders().isEmpty() + && selectedCustomerorder.getSuborders().get(0).getDebithours() != null + && !selectedCustomerorder.getSuborders().get(0).getDebithours().isZero()) { + employeeOrderForm.setDebithours(DurationUtils.format(selectedCustomerorder.getSuborders().get(0).getDebithours())); /* set unit if applicable */ employeeOrderForm.setDebithoursunit(selectedCustomerorder.getSuborders().get(0).getDebithoursunit()); + } else { + employeeOrderForm.setDebithoursunit(null); } } diff --git a/src/main/java/org/tb/order/CustomerOrderViewDecorator.java b/src/main/java/org/tb/order/CustomerOrderViewDecorator.java index 4ed297451..5926274a7 100644 --- a/src/main/java/org/tb/order/CustomerOrderViewDecorator.java +++ b/src/main/java/org/tb/order/CustomerOrderViewDecorator.java @@ -1,5 +1,8 @@ package org.tb.order; +import static org.tb.common.GlobalConstants.DEBITHOURS_UNIT_TOTALTIME; + +import java.time.Duration; import lombok.RequiredArgsConstructor; import lombok.experimental.Delegate; import org.tb.common.GlobalConstants; @@ -13,31 +16,19 @@ public class CustomerOrderViewDecorator extends Customerorder { @Delegate private final Customerorder customerOrder; - public Double getDifference() { - if ((this.customerOrder.getDebithours() != null && this.customerOrder.getDebithours() > 0.0) - && (this.customerOrder.getDebithoursunit() == null || this.customerOrder.getDebithoursunit() == GlobalConstants.DEBITHOURS_UNIT_TOTALTIME)) { - double rounded, notRounded; - notRounded = (this.customerOrder.getDebithours() - getDuration()); - rounded = Math.round(notRounded * 100) / 100.0; - - return rounded; + public Duration getDifference() { + if (this.customerOrder.getDebithours() != null + && !this.customerOrder.getDebithours().isZero() + && (this.customerOrder.getDebithoursunit() == null || this.customerOrder.getDebithoursunit() == DEBITHOURS_UNIT_TOTALTIME)) { + return this.customerOrder.getDebithours().minus(getDuration()); } else { return null; } } - public double getDuration() { + public Duration getDuration() { long durationMinutes = timereportDAO.getTotalDurationMinutesForCustomerOrder(customerOrder.getId()); - - double totalTime = (double) durationMinutes / GlobalConstants.MINUTES_PER_HOUR; - - /* round totalTime */ - totalTime *= 100.0; - long roundedTime = Math.round(totalTime); - totalTime = roundedTime / 100.0; - - /* return result */ - return totalTime; + return Duration.ofMinutes(durationMinutes); } @Override diff --git a/src/main/java/org/tb/order/Customerorder.java b/src/main/java/org/tb/order/Customerorder.java index 0fff20c54..d6b60c0a1 100644 --- a/src/main/java/org/tb/order/Customerorder.java +++ b/src/main/java/org/tb/order/Customerorder.java @@ -1,14 +1,19 @@ package org.tb.order; +import static org.tb.common.GlobalConstants.MINUTES_PER_HOUR; import static org.tb.common.util.DateUtils.format; import java.io.Serializable; +import java.math.BigDecimal; +import java.time.Duration; import java.time.LocalDate; import java.util.List; +import javax.persistence.Convert; import javax.persistence.Entity; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; +import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; import org.hibernate.annotations.Cache; @@ -18,6 +23,7 @@ import org.hibernate.annotations.Fetch; import org.hibernate.annotations.FetchMode; import org.tb.common.AuditedEntity; +import org.tb.common.DurationMinutesConverter; import org.tb.common.util.DateUtils; import org.tb.customer.Customer; import org.tb.employee.Employee; @@ -82,7 +88,12 @@ public class Customerorder extends AuditedEntity implements Serializable { private String sign; private String description; private String shortdescription; - private Double debithours; + + @Convert(converter = DurationMinutesConverter.class) + @Getter(AccessLevel.NONE) + @Setter(AccessLevel.NONE) + private Duration debitMinutes; + private Byte debithoursunit; private Integer statusreport; /** @@ -146,4 +157,12 @@ public boolean isValidAt(LocalDate date) { return !date.isBefore(getFromDate()) && (getUntilDate() == null || !date.isAfter(getUntilDate())); } + public Duration getDebithours() { + return debitMinutes; // its a Duration - hours or minutes make no difference + } + + public void setDebithours(Duration value) { + debitMinutes = value; // its a Duration - hours or minutes make no difference + } + } diff --git a/src/main/java/org/tb/order/CustomerorderHelper.java b/src/main/java/org/tb/order/CustomerorderHelper.java index a1d784c6b..07a7c53e5 100644 --- a/src/main/java/org/tb/order/CustomerorderHelper.java +++ b/src/main/java/org/tb/order/CustomerorderHelper.java @@ -24,7 +24,7 @@ */ @Component @Slf4j -@RequiredArgsConstructor(onConstructor_ = { @Autowired}) +@RequiredArgsConstructor public class CustomerorderHelper { private final CustomerorderDAO customerorderDAO; diff --git a/src/main/java/org/tb/order/EditCustomerorderAction.java b/src/main/java/org/tb/order/EditCustomerorderAction.java index 5789cce20..f6cb0a44a 100644 --- a/src/main/java/org/tb/order/EditCustomerorderAction.java +++ b/src/main/java/org/tb/order/EditCustomerorderAction.java @@ -10,6 +10,7 @@ import org.springframework.stereotype.Component; import org.tb.common.struts.LoginRequiredAction; import org.tb.common.util.DateUtils; +import org.tb.common.util.DurationUtils; import org.tb.customer.Customer; import org.tb.customer.CustomerDAO; import org.tb.employee.Employee; @@ -90,8 +91,8 @@ private void setFormEntries(HttpServletRequest request, AddCustomerorderForm coF coForm.setValidUntil(""); } - if (co.getDebithours() != null) { - coForm.setDebithours(co.getDebithours()); + if (co.getDebithours() != null && !co.getDebithours().isZero()) { + coForm.setDebithours(DurationUtils.format(co.getDebithours())); coForm.setDebithoursunit(co.getDebithoursunit()); } else { coForm.setDebithours(null); diff --git a/src/main/java/org/tb/order/EditEmployeeOrderContentAction.java b/src/main/java/org/tb/order/EditEmployeeOrderContentAction.java index 2bea9a863..e45df2cea 100644 --- a/src/main/java/org/tb/order/EditEmployeeOrderContentAction.java +++ b/src/main/java/org/tb/order/EditEmployeeOrderContentAction.java @@ -36,7 +36,7 @@ protected ActionForward executeAuthenticated(ActionMapping mapping, mapping.findForward("error"); } String eoIdString = request.getParameter("eoId"); - Long eoId = new Long(eoIdString); + Long eoId = Long.valueOf(eoIdString); // get associated employee order and content from db, if present Employeeorder employeeorder = employeeorderDAO diff --git a/src/main/java/org/tb/order/EditEmployeeorderAction.java b/src/main/java/org/tb/order/EditEmployeeorderAction.java index 4ad132d83..518a237f1 100644 --- a/src/main/java/org/tb/order/EditEmployeeorderAction.java +++ b/src/main/java/org/tb/order/EditEmployeeorderAction.java @@ -10,6 +10,7 @@ import org.springframework.stereotype.Component; import org.tb.common.GlobalConstants; import org.tb.common.util.DateUtils; +import org.tb.common.util.DurationUtils; import org.tb.employee.Employee; import org.tb.employee.Employeecontract; import org.tb.employee.EmployeecontractDAO; @@ -105,9 +106,8 @@ private void setFormEntries(HttpServletRequest request, AddEmployeeOrderForm eoF eoForm.setOrderId(eo.getSuborder().getCustomerorder().getId()); eoForm.setSuborderId(eo.getSuborder().getId()); - eoForm.setDebithours(eo.getDebithours()); - if (eo.getDebithours() != null) { - eoForm.setDebithours(eo.getDebithours()); + if (eo.getDebithours() != null && !eo.getDebithours().isZero()) { + eoForm.setDebithours(DurationUtils.format(eo.getDebithours())); eoForm.setDebithoursunit(eo.getDebithoursunit()); } else { eoForm.setDebithours(null); diff --git a/src/main/java/org/tb/order/EditSuborderAction.java b/src/main/java/org/tb/order/EditSuborderAction.java index 6576d1f68..4fe3a0a57 100644 --- a/src/main/java/org/tb/order/EditSuborderAction.java +++ b/src/main/java/org/tb/order/EditSuborderAction.java @@ -11,6 +11,7 @@ import org.tb.common.GlobalConstants; import org.tb.common.struts.LoginRequiredAction; import org.tb.common.util.DateUtils; +import org.tb.common.util.DurationUtils; import org.tb.employee.Employee; /** @@ -90,8 +91,8 @@ private void setFormEntries(HttpServletRequest request, AddSuborderForm soForm, soForm.setValidUntil(""); } - if (so.getDebithours() != null) { - soForm.setDebithours(so.getDebithours()); + if (so.getDebithours() != null && !so.getDebithours().isZero()) { + soForm.setDebithours(DurationUtils.format(so.getDebithours())); soForm.setDebithoursunit(so.getDebithoursunit()); } else { soForm.setDebithours(null); diff --git a/src/main/java/org/tb/order/EmployeeOrderViewDecorator.java b/src/main/java/org/tb/order/EmployeeOrderViewDecorator.java index 4abfb32ad..f5e912d01 100644 --- a/src/main/java/org/tb/order/EmployeeOrderViewDecorator.java +++ b/src/main/java/org/tb/order/EmployeeOrderViewDecorator.java @@ -1,5 +1,6 @@ package org.tb.order; +import java.time.Duration; import lombok.RequiredArgsConstructor; import lombok.experimental.Delegate; import org.tb.common.GlobalConstants; @@ -13,28 +14,15 @@ public class EmployeeOrderViewDecorator extends Employeeorder { @Delegate private final Employeeorder employeeOrder; - public double getDuration() { + public Duration getDuration() { long durationMinutes = timereportDAO.getTotalDurationMinutesForEmployeeOrder(employeeOrder.getId()); - - double totalTime = (double) durationMinutes / GlobalConstants.MINUTES_PER_HOUR; - - /* round totalTime */ - totalTime *= 100.0; - long roundedTime = Math.round(totalTime); - totalTime = roundedTime / 100.0; - - /* return result */ - return totalTime; + return Duration.ofMinutes(durationMinutes); } - public Double getDifference() { - if ((this.employeeOrder.getDebithours() != null && this.employeeOrder.getDebithours() > 0.0) + public Duration getDifference() { + if ((this.employeeOrder.getDebithours() != null && this.employeeOrder.getDebithours().toMinutes() > 0) && (this.employeeOrder.getDebithoursunit() == null || this.employeeOrder.getDebithoursunit() == GlobalConstants.DEBITHOURS_UNIT_TOTALTIME)) { - double rounded, notRounded; - notRounded = (this.employeeOrder.getDebithours() - getDuration()); - rounded = Math.round(notRounded * 100) / 100.0; - - return rounded; + return this.employeeOrder.getDebithours().minus(getDuration()); } else { return null; } diff --git a/src/main/java/org/tb/order/Employeeorder.java b/src/main/java/org/tb/order/Employeeorder.java index c6af9e62d..6b76ece7b 100644 --- a/src/main/java/org/tb/order/Employeeorder.java +++ b/src/main/java/org/tb/order/Employeeorder.java @@ -1,13 +1,18 @@ package org.tb.order; +import static org.tb.common.GlobalConstants.MINUTES_PER_HOUR; import static org.tb.common.util.DateUtils.format; import java.io.Serializable; +import java.math.BigDecimal; +import java.time.Duration; import java.time.LocalDate; +import javax.persistence.Convert; import javax.persistence.Entity; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.OneToOne; +import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; import org.hibernate.annotations.Cache; @@ -17,6 +22,7 @@ import org.hibernate.annotations.Fetch; import org.hibernate.annotations.FetchMode; import org.tb.common.AuditedEntity; +import org.tb.common.DurationMinutesConverter; import org.tb.common.util.DateUtils; import org.tb.employee.Employeecontract; @@ -50,7 +56,12 @@ public class Employeeorder extends AuditedEntity implements Serializable { * sign of the employee order */ private String sign; - private Double debithours; + + @Convert(converter = DurationMinutesConverter.class) + @Getter(AccessLevel.NONE) + @Setter(AccessLevel.NONE) + private Duration debitMinutes; + private Byte debithoursunit; private LocalDate fromDate; private LocalDate untilDate; @@ -113,4 +124,13 @@ public boolean getFitsToSuperiorObjects() { !getUntilDate().isAfter(suborder.getUntilDate()))); } + public Duration getDebithours() { + return debitMinutes; // its a Duration - hours or minutes make no difference + } + + public void setDebithours(Duration value) { + // its a Duration - hours or minutes make no difference + debitMinutes = value; + } + } diff --git a/src/main/java/org/tb/order/ShowEmployeeOrderForm.java b/src/main/java/org/tb/order/ShowEmployeeOrderForm.java index 3e628a450..02b419290 100644 --- a/src/main/java/org/tb/order/ShowEmployeeOrderForm.java +++ b/src/main/java/org/tb/order/ShowEmployeeOrderForm.java @@ -24,7 +24,7 @@ public class ShowEmployeeOrderForm extends ActionForm { private long orderId; private long suborderId; private String filter; - private Boolean show; + private Boolean show = false; private Boolean showActualHours = false; @Nonnull @@ -48,6 +48,9 @@ public void reset(ActionMapping mapping, HttpServletRequest request) { filter = ""; show = false; + showActualHours = false; } + + } diff --git a/src/main/java/org/tb/order/StoreCustomerorderAction.java b/src/main/java/org/tb/order/StoreCustomerorderAction.java index 30a65a814..9569e0508 100644 --- a/src/main/java/org/tb/order/StoreCustomerorderAction.java +++ b/src/main/java/org/tb/order/StoreCustomerorderAction.java @@ -20,6 +20,7 @@ import org.tb.common.GlobalConstants; import org.tb.common.struts.LoginRequiredAction; import org.tb.common.util.DateUtils; +import org.tb.common.util.DurationUtils; import org.tb.customer.CustomerDAO; import org.tb.dailyreport.Timereport; import org.tb.dailyreport.TimereportDAO; @@ -60,7 +61,7 @@ public ActionForward executeAuthenticated(ActionMapping mapping, AddCustomerorde LocalDate newValue; if (howMuch != 0) { ActionMessages errorMessages = valiDate(request, coForm, which); - if (errorMessages.size() > 0) { + if (!errorMessages.isEmpty()) { return mapping.getInputForward(); } @@ -88,7 +89,7 @@ public ActionForward executeAuthenticated(ActionMapping mapping, AddCustomerorde request.getParameter("coId") != null) { ActionMessages errorMessages = validateFormData(request, coForm); - if (errorMessages.size() > 0) { + if (!errorMessages.isEmpty()) { return mapping.getInputForward(); } @@ -195,11 +196,13 @@ public ActionForward executeAuthenticated(ActionMapping mapping, AddCustomerorde co.setResponsible_hbt(employeeDAO.getEmployeeById(coForm.getEmployeeId())); co.setRespEmpHbtContract(employeeDAO.getEmployeeById(coForm.getRespContrEmployeeId())); - if (coForm.getDebithours() == null || coForm.getDebithours() == 0.0) { + if (coForm.getDebithours() == null + || coForm.getDebithours().isEmpty() + || DurationUtils.parseDuration(coForm.getDebithours()).isZero()) { co.setDebithours(null); co.setDebithoursunit(null); } else { - co.setDebithours(coForm.getDebithours()); + co.setDebithours(DurationUtils.parseDuration(coForm.getDebithours())); co.setDebithoursunit(coForm.getDebithoursunit()); } @@ -279,23 +282,12 @@ private ActionMessages valiDate(HttpServletRequest request, AddCustomerorderForm errors = new ActionMessages(); } - String dateString = ""; if (which.equals("from")) { - dateString = coForm.getValidFrom().trim(); - } else { - dateString = coForm.getValidUntil().trim(); - } - - int minus = 0; - for (int i = 0; i < dateString.length(); i++) { - if (dateString.charAt(i) == '-') { - minus++; - } - } - if (dateString.length() != 10 || minus != 2) { - if (which.equals("from")) { + if(!DateUtils.validateDate(coForm.getValidFrom())) { errors.add("validFrom", new ActionMessage("form.timereport.error.date.wrongformat")); - } else { + } + } else { + if(!DateUtils.validateDate(coForm.getValidUntil())) { errors.add("validUntil", new ActionMessage("form.timereport.error.date.wrongformat")); } } @@ -316,14 +308,14 @@ private ActionMessages validateFormData(HttpServletRequest request, AddCustomero // check date formats (must now be 'yyyy-MM-dd') String dateFromString = coForm.getValidFrom().trim(); - boolean dateError = DateUtils.validateDate(dateFromString); + boolean dateError = !DateUtils.validateDate(dateFromString); if (dateError) { errors.add("validFrom", new ActionMessage("form.timereport.error.date.wrongformat")); } if (coForm.getValidUntil() != null && !coForm.getValidUntil().trim().equals("")) { String dateUntilString = coForm.getValidUntil().trim(); - dateError = DateUtils.validateDate(dateUntilString); + dateError = !DateUtils.validateDate(dateUntilString); if (dateError) { errors.add("validUntil", new ActionMessage("form.timereport.error.date.wrongformat")); } @@ -378,24 +370,13 @@ private ActionMessages validateFormData(HttpServletRequest request, AddCustomero errors.add("responsibleCustomerTechnical", new ActionMessage("form.customerorder.error.responsiblecustomer.required")); } - if (!GenericValidator.isDouble(coForm.getDebithours().toString()) || - !GenericValidator.isInRange(coForm.getDebithours(), - 0.0, GlobalConstants.MAX_DEBITHOURS)) { + if (!DurationUtils.validateDuration(coForm.getDebithours())) { errors.add("debithours", new ActionMessage("form.customerorder.error.debithours.wrongformat")); - } else if (coForm.getDebithours() != null && coForm.getDebithours() != 0.0) { - double debithours = coForm.getDebithours() * 100000; - debithours += 0.5; - - int debithours2 = (int) debithours; - int modulo = debithours2 % 5000; - coForm.setDebithours(debithours2 / 100000.0); - - if (modulo != 0) { - errors.add("debithours", new ActionMessage("form.customerorder.error.debithours.wrongformat2")); - } } - if (coForm.getDebithours() != 0.0) { + if (coForm.getDebithours() != null + && coForm.getDebithours().isEmpty() + && !DurationUtils.parseDuration(coForm.getDebithours()).isZero()) { if (coForm.getDebithoursunit() == null || !(coForm.getDebithoursunit() == GlobalConstants.DEBITHOURS_UNIT_MONTH || coForm.getDebithoursunit() == GlobalConstants.DEBITHOURS_UNIT_YEAR || coForm.getDebithoursunit() == GlobalConstants.DEBITHOURS_UNIT_TOTALTIME)) { errors.add("debithours", new ActionMessage("form.customerorder.error.debithours.nounit")); diff --git a/src/main/java/org/tb/order/StoreEmployeeorderAction.java b/src/main/java/org/tb/order/StoreEmployeeorderAction.java index 0f2755255..664c340c5 100644 --- a/src/main/java/org/tb/order/StoreEmployeeorderAction.java +++ b/src/main/java/org/tb/order/StoreEmployeeorderAction.java @@ -1,5 +1,6 @@ package org.tb.order; +import static org.apache.struts.action.ActionMessages.GLOBAL_MESSAGE; import static org.tb.common.util.DateUtils.addDays; import static org.tb.common.util.DateUtils.parse; import static org.tb.common.util.DateUtils.today; @@ -13,7 +14,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; -import org.apache.commons.validator.GenericValidator; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionMessage; @@ -21,6 +21,7 @@ import org.springframework.stereotype.Component; import org.tb.common.GlobalConstants; import org.tb.common.util.DateUtils; +import org.tb.common.util.DurationUtils; import org.tb.dailyreport.Timereport; import org.tb.dailyreport.TimereportDAO; import org.tb.employee.Employee; @@ -72,7 +73,7 @@ public ActionForward executeAuthenticated(ActionMapping mapping, LocalDate newValue; if (howMuch != 0) { ActionMessages errorMessages = valiDate(request, eoForm, which); - if (errorMessages.size() > 0) { + if (!errorMessages.isEmpty()) { return mapping.getInputForward(); } @@ -126,10 +127,13 @@ public ActionForward executeAuthenticated(ActionMapping mapping, Suborder suborder = so.get(); eoForm.setSuborderId(suborder.getId()); request.getSession().setAttribute("selectedsuborder", suborder); - eoForm.setDebithours(suborder.getDebithours()); - if (suborder.getDebithours() != null && suborder.getDebithours() > 0.0) { + if (suborder.getDebithours() != null && suborder.getDebithours().toMinutes() > 0) { + eoForm.setDebithours(DurationUtils.format(suborder.getDebithours())); /* set unit if applicable */ eoForm.setDebithoursunit(suborder.getDebithoursunit()); + } else { + eoForm.setDebithours(null); + eoForm.setDebithoursunit(null); } } @@ -153,13 +157,13 @@ public ActionForward executeAuthenticated(ActionMapping mapping, request.getSession().setAttribute("selectedsuborder", so); eoForm.setSuborderId(so.getId()); - /* suggest value */ - eoForm.setDebithours(so.getDebithours()); - - eoForm.setDebithoursunit((byte) -1); // default: no unit set - if (so.getDebithours() != null && so.getDebithours() > 0.0) { + if (so.getDebithours() != null && so.getDebithours().toMinutes() > 0) { + eoForm.setDebithours(DurationUtils.format(so.getDebithours())); /* set unit if applicable */ eoForm.setDebithoursunit(so.getDebithoursunit()); + } else { + eoForm.setDebithours(null); + eoForm.setDebithoursunit(null); } } // checkDatabaseForEmployeeOrder(request, eoForm, @@ -188,7 +192,7 @@ public ActionForward executeAuthenticated(ActionMapping mapping, } ActionMessages errorMessages = validateFormData(request, eoForm, employeeorderDAO, employeecontractDAO, suborderDAO, eo.getId()); - if (errorMessages.size() > 0) { + if (!errorMessages.isEmpty()) { return mapping.getInputForward(); } @@ -214,22 +218,21 @@ public ActionForward executeAuthenticated(ActionMapping mapping, GlobalConstants.CUSTOMERORDER_SIGN_VACATION) && !eo.getSuborder().getSign().equalsIgnoreCase(GlobalConstants.SUBORDER_SIGN_OVERTIME_COMPENSATION)) { - if ("adm".equals(loginEmployee.getSign())) { + if (authorizedUser.isAdmin()) { if (eoForm.getDebithours() == null - || eoForm.getDebithours() == 0.0) { + || eoForm.getDebithours().isEmpty() + || DurationUtils.parseDuration(eoForm.getDebithours()).isZero()) { eo.setDebithours(null); eo.setDebithoursunit(null); } else { - eo.setDebithours(eoForm.getDebithours()); - eo.setDebithoursunit(eoForm.getDebithoursunit()); + eo.setDebithours(DurationUtils.parseDuration(eoForm.getDebithours())); + eo.setDebithoursunit(GlobalConstants.DEBITHOURS_UNIT_YEAR); } - } else { - // TODO: code unreachable? - eo.setDebithours(eo.getEmployeecontract() - .getVacationEntitlement() - * eo.getEmployeecontract().getDailyWorkingTime()); - eo.setDebithoursunit(GlobalConstants.DEBITHOURS_UNIT_YEAR); + ActionMessages errors = new ActionMessages(); + errors.add(GLOBAL_MESSAGE, new ActionMessage("common.error.admin.required")); + saveErrors(request, errors); + return mapping.getInputForward(); } } else if (eo.getSuborder().getCustomerorder().getSign().equals( @@ -238,11 +241,12 @@ public ActionForward executeAuthenticated(ActionMapping mapping, eo.setDebithoursunit(GlobalConstants.DEBITHOURS_UNIT_YEAR); } else { if (eoForm.getDebithours() == null - || eoForm.getDebithours() == 0.0) { + || eoForm.getDebithours().isEmpty() + || DurationUtils.parseDuration(eoForm.getDebithours()).isZero()) { eo.setDebithours(null); eo.setDebithoursunit(null); } else { - eo.setDebithours(eoForm.getDebithours()); + eo.setDebithours(DurationUtils.parseDuration(eoForm.getDebithours())); eo.setDebithoursunit(eoForm.getDebithoursunit()); } } @@ -368,8 +372,8 @@ private ActionMessages validateFormData(HttpServletRequest request, errors = new ActionMessages(); } - java.time.LocalDate validFromDate = null; - java.time.LocalDate validUntilDate = null; + LocalDate validFromDate = null; + LocalDate validUntilDate = null; try { validFromDate = parse(eoForm.getValidFrom()); } catch (ParseException e) { @@ -403,24 +407,14 @@ private ActionMessages validateFormData(HttpServletRequest request, Customerorder co = (Customerorder) request.getSession().getAttribute("selectedcustomerorder"); if (co != null && !co.getSign().equals(GlobalConstants.CUSTOMERORDER_SIGN_VACATION) && !co.getSign().equals(GlobalConstants.CUSTOMERORDER_SIGN_ILL)) { - if (!GenericValidator.isDouble(eoForm.getDebithours().toString()) - || !GenericValidator.isInRange(eoForm.getDebithours(), 0.0, GlobalConstants.MAX_DEBITHOURS)) { + if (!DurationUtils.validateDuration(eoForm.getDebithours())) { errors.add("debithours", new ActionMessage("form.employeeorder.error.debithours.wrongformat")); - } else if (eoForm.getDebithours() != null && eoForm.getDebithours() != 0.0) { - double debithours = eoForm.getDebithours() * 100000; - debithours += 0.5; - - int debithours2 = (int) debithours; - int modulo = debithours2 % 5000; - eoForm.setDebithours(debithours2 / 100000.0); - - if (modulo != 0) { - errors.add("debithours", new ActionMessage("form.customerorder.error.debithours.wrongformat2")); - } } } - if (eoForm.getDebithours() != null && eoForm.getDebithours() != 0.0) { + if (eoForm.getDebithours() != null + && eoForm.getDebithours().isEmpty() + && !DurationUtils.parseDuration(eoForm.getDebithours()).isZero()) { if (eoForm.getDebithoursunit() == null || !(eoForm.getDebithoursunit() == GlobalConstants.DEBITHOURS_UNIT_MONTH || eoForm.getDebithoursunit() == GlobalConstants.DEBITHOURS_UNIT_YEAR || eoForm diff --git a/src/main/java/org/tb/order/StoreSuborderAction.java b/src/main/java/org/tb/order/StoreSuborderAction.java index c36287104..f7d63afd7 100644 --- a/src/main/java/org/tb/order/StoreSuborderAction.java +++ b/src/main/java/org/tb/order/StoreSuborderAction.java @@ -24,6 +24,7 @@ import org.tb.common.GlobalConstants; import org.tb.common.struts.LoginRequiredAction; import org.tb.common.util.DateUtils; +import org.tb.common.util.DurationUtils; import org.tb.dailyreport.Timereport; import org.tb.dailyreport.TimereportDAO; import org.tb.employee.Employee; @@ -61,7 +62,7 @@ public ActionForward executeAuthenticated(ActionMapping mapping, LocalDate newValue; if (howMuch != 0) { ActionMessages errorMessages = valiDate(request, addSuborderForm, which); - if (errorMessages.size() > 0) { + if (!errorMessages.isEmpty()) { return mapping.getInputForward(); } @@ -222,7 +223,7 @@ public ActionForward executeAuthenticated(ActionMapping mapping, if (request.getParameter("task") != null && request.getParameter("task").equals("save") || request.getParameter("soId") != null) { //*** task for saving new suborder ActionMessages errorMessages = validateFormData(request, addSuborderForm); - if (errorMessages.size() > 0) { + if (!errorMessages.isEmpty()) { return mapping.getInputForward(); } @@ -306,11 +307,13 @@ public ActionForward executeAuthenticated(ActionMapping mapping, } } - if (addSuborderForm.getDebithours() == null || addSuborderForm.getDebithours() == 0.0) { + if (addSuborderForm.getDebithours() == null + || addSuborderForm.getDebithours().isEmpty() + || DurationUtils.parseDuration(addSuborderForm.getDebithours()).isZero()) { so.setDebithours(null); so.setDebithoursunit(null); } else { - so.setDebithours(addSuborderForm.getDebithours()); + so.setDebithours(DurationUtils.parseDuration(addSuborderForm.getDebithours())); so.setDebithoursunit(addSuborderForm.getDebithoursunit()); } @@ -379,23 +382,12 @@ private ActionMessages valiDate(HttpServletRequest request, AddSuborderForm soFo errors = new ActionMessages(); } - String dateString = ""; if (which.equals("from")) { - dateString = soForm.getValidFrom().trim(); - } else { - dateString = soForm.getValidUntil().trim(); - } - - int minus = 0; - for (int i = 0; i < dateString.length(); i++) { - if (dateString.charAt(i) == '-') { - minus++; - } - } - if (dateString.length() != 10 || minus != 2) { - if (which.equals("from")) { + if(!DateUtils.validateDate(soForm.getValidFrom())) { errors.add("validFrom", new ActionMessage("form.timereport.error.date.wrongformat")); - } else { + } + } else { + if(!DateUtils.validateDate(soForm.getValidFrom())) { errors.add("validUntil", new ActionMessage("form.timereport.error.date.wrongformat")); } } @@ -499,23 +491,13 @@ private ActionMessages validateFormData(HttpServletRequest request, AddSuborderF } } // check debit hours - if (!GenericValidator.isDouble(addSuborderForm.getDebithours().toString()) || - !GenericValidator.isInRange(addSuborderForm.getDebithours(), 0.0, GlobalConstants.MAX_DEBITHOURS)) { - + if (!DurationUtils.validateDuration(addSuborderForm.getDebithours())) { errors.add("debithours", new ActionMessage("form.customerorder.error.debithours.wrongformat")); - } else if (addSuborderForm.getDebithours() != null && addSuborderForm.getDebithours() != 0.0) { - double debithours = addSuborderForm.getDebithours() * 100000; - debithours += 0.5; - int debithours2 = (int) debithours; - int modulo = debithours2 % 5000; - addSuborderForm.setDebithours(debithours2 / 100000.0); - - if (modulo != 0) { - errors.add("debithours", new ActionMessage("form.customerorder.error.debithours.wrongformat2")); - } } - if (addSuborderForm.getDebithours() != 0.0) { + if (addSuborderForm.getDebithours() != null + && addSuborderForm.getDebithours().isEmpty() + && !DurationUtils.parseDuration(addSuborderForm.getDebithours()).isZero()) { if (addSuborderForm.getDebithoursunit() == null || !(addSuborderForm.getDebithoursunit() == GlobalConstants.DEBITHOURS_UNIT_MONTH || addSuborderForm.getDebithoursunit() == GlobalConstants.DEBITHOURS_UNIT_YEAR || diff --git a/src/main/java/org/tb/order/Suborder.java b/src/main/java/org/tb/order/Suborder.java index 5c018b3ef..a25357b87 100644 --- a/src/main/java/org/tb/order/Suborder.java +++ b/src/main/java/org/tb/order/Suborder.java @@ -1,17 +1,23 @@ package org.tb.order; +import static org.tb.common.GlobalConstants.MINUTES_PER_HOUR; + import java.io.Serializable; +import java.math.BigDecimal; +import java.time.Duration; import java.time.LocalDate; import java.util.LinkedList; import java.util.List; import java.util.Objects; import javax.persistence.Column; +import javax.persistence.Convert; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.JoinColumn; import javax.persistence.Lob; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; +import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; import org.hibernate.annotations.Cache; @@ -21,6 +27,7 @@ import org.hibernate.annotations.Fetch; import org.hibernate.annotations.FetchMode; import org.tb.common.AuditedEntity; +import org.tb.common.DurationMinutesConverter; import org.tb.common.util.DateUtils; import org.tb.dailyreport.Timereport; import org.tb.dailyreport.TimereportDAO; @@ -82,7 +89,12 @@ public class Suborder extends AuditedEntity implements Serializable { private Boolean commentnecessary; private LocalDate fromDate; private LocalDate untilDate; - private Double debithours; + + @Convert(converter = DurationMinutesConverter.class) + @Getter(AccessLevel.NONE) + @Setter(AccessLevel.NONE) + private Duration debitMinutes; + private Byte debithoursunit; /** * Hide in select boxes @@ -351,7 +363,7 @@ public Suborder copy(boolean copyroot, String creator) { copy.setCreated(DateUtils.now()); copy.setCreatedby(creator + "_treecopy"); copy.setCustomerorder(customerorder); - copy.setDebithours(debithours); + copy.setDebithours(getDebithours()); // see #getDebithours copy.setDebithoursunit(debithoursunit); copy.setDescription(description); copy.setFromDate(fromDate); @@ -378,4 +390,12 @@ public Suborder copy(boolean copyroot, String creator) { return copy; } + public Duration getDebithours() { + return debitMinutes; // its a Duration - hours or minutes make no difference + } + + public void setDebithours(Duration value) { + debitMinutes = value; // its a Duration - hours or minutes make no difference + } + } diff --git a/src/main/java/org/tb/order/SuborderHelper.java b/src/main/java/org/tb/order/SuborderHelper.java index a06f2ee24..745e005f0 100644 --- a/src/main/java/org/tb/order/SuborderHelper.java +++ b/src/main/java/org/tb/order/SuborderHelper.java @@ -25,7 +25,7 @@ */ @Component @Slf4j -@RequiredArgsConstructor(onConstructor_ = { @Autowired}) +@RequiredArgsConstructor public class SuborderHelper { private final SuborderDAO suborderDAO; diff --git a/src/main/java/org/tb/order/SuborderViewDecorator.java b/src/main/java/org/tb/order/SuborderViewDecorator.java index 9ee82bc45..03b5068aa 100644 --- a/src/main/java/org/tb/order/SuborderViewDecorator.java +++ b/src/main/java/org/tb/order/SuborderViewDecorator.java @@ -1,8 +1,10 @@ package org.tb.order; +import static org.tb.common.GlobalConstants.DEBITHOURS_UNIT_TOTALTIME; import static org.tb.common.GlobalConstants.SUBORDER_INVOICE_NO; import static org.tb.common.GlobalConstants.SUBORDER_INVOICE_YES; +import java.time.Duration; import java.util.ArrayList; import java.util.List; import lombok.RequiredArgsConstructor; @@ -17,8 +19,8 @@ public class SuborderViewDecorator extends Suborder { private final TimereportDAO timereportDAO; @Delegate private final Suborder suborder; - private Double duration; - private Double durationNotInvoiceable; + private Duration duration; + private Duration durationNotInvoiceable; private static void generateListOfDescendants(Suborder so, boolean isInvoiceable, List listOfDescendents) { if (isInvoiceable != (so.getInvoice() == SUBORDER_INVOICE_YES)) { @@ -32,45 +34,44 @@ private static void generateListOfDescendants(Suborder so, boolean isInvoiceable } } - public Double getDifference() { - if (this.suborder.getDebithours() != null && this.suborder.getDebithours() > 0.0 - && (this.suborder.getDebithoursunit() == null || this.suborder.getDebithoursunit() == GlobalConstants.DEBITHOURS_UNIT_TOTALTIME)) { - double rounded, notRounded; - notRounded = this.suborder.getDebithours() - getDuration(); - rounded = Math.round(notRounded * 100) / 100.0; - - return rounded; + public Duration getDifference() { + if (suborder.getDebithours() != null + && suborder.getDebithours().toMinutes() > 0 + && (suborder.getDebithoursunit() == null || suborder.getDebithoursunit() == DEBITHOURS_UNIT_TOTALTIME)) { + return suborder.getDebithours().minus(getDuration()); } else { return null; } } - public double getDuration() { - if (this.duration == null) { + public Duration getDuration() { + if (duration == null) { if (suborder.getInvoice() == SUBORDER_INVOICE_NO) { - return 0; + return Duration.ZERO; } List descendants = new ArrayList<>(); generateListOfDescendants(suborder, true, descendants); - this.duration = (double) (timereportDAO.getTotalDurationMinutesForSuborders(descendants) * 100 / GlobalConstants.MINUTES_PER_HOUR) / 100; + long durationMinutes = timereportDAO.getTotalDurationMinutesForSuborders(descendants); + duration = Duration.ofMinutes(durationMinutes); } - return this.duration; + return duration; } - public double getDurationNotInvoiceable() { - if (this.durationNotInvoiceable == null) { + public Duration getDurationNotInvoiceable() { + if (durationNotInvoiceable == null) { if (suborder.getInvoice() == SUBORDER_INVOICE_YES) { - return 0; + return Duration.ZERO; } List descendants = new ArrayList<>(); generateListOfDescendants(suborder, false, descendants); - this.durationNotInvoiceable = (double) (timereportDAO.getTotalDurationMinutesForSuborders(descendants) * 100 / GlobalConstants.MINUTES_PER_HOUR) / 100; + long durationMinutes = timereportDAO.getTotalDurationMinutesForSuborders(descendants); + duration = Duration.ofMinutes(durationMinutes); } - return this.durationNotInvoiceable; + return durationNotInvoiceable; } @Override diff --git a/src/main/java/org/tb/statusreport/StoreStatusReportAction.java b/src/main/java/org/tb/statusreport/StoreStatusReportAction.java index d447e9ebc..683317325 100644 --- a/src/main/java/org/tb/statusreport/StoreStatusReportAction.java +++ b/src/main/java/org/tb/statusreport/StoreStatusReportAction.java @@ -473,23 +473,12 @@ private ActionMessages valiDate(HttpServletRequest request, AddStatusReportForm errors = new ActionMessages(); } - String dateString = ""; if (which.equals("from")) { - dateString = reportForm.getValidFrom().trim(); - } else { - dateString = reportForm.getValidUntil().trim(); - } - - int minus = 0; - for (int i = 0; i < dateString.length(); i++) { - if (dateString.charAt(i) == '-') { - minus++; - } - } - if (dateString.length() != 10 || minus != 2) { - if (which.equals("from")) { + if(!DateUtils.validateDate(reportForm.getValidFrom())) { errors.add("validFrom", new ActionMessage("form.timereport.error.date.wrongformat")); - } else { + } + } else { + if(!DateUtils.validateDate(reportForm.getValidFrom())) { errors.add("validUntil", new ActionMessage("form.timereport.error.date.wrongformat")); } } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 0a336f8a1..b7425b710 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -3,6 +3,7 @@ server: session: persistent: false timeout: 660m + forward-headers-strategy: native # ensure correct handling of X-Forwarded-Host and X-Forwarded-Proto headers spring: datasource: url: jdbc:mysql://localhost:3306/salat?useUnicode=true&useJDBCCompliantTimezoneShift=true&serverTimezone=Europe/Berlin&useLegacyDatetimeCode=false&autoReconnect=true @@ -23,7 +24,7 @@ spring: naming: physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl - ddl-auto: none + ddl-auto: validate open-in-view: true database: mysql management: diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 6bab24cd3..c8c393797 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -183,97 +183,360 @@ databaseChangeLog: columns: - column: name: updatecounter - value: 0 + valueNumeric: 0 tableName: customer where: updatecounter is null - update: columns: - column: name: updatecounter - value: 0 + valueNumeric: 0 tableName: customerorder where: updatecounter is null - update: columns: - column: name: updatecounter - value: 0 + valueNumeric: 0 tableName: employee where: updatecounter is null - update: columns: - column: name: updatecounter - value: 0 + valueNumeric: 0 tableName: employeecontract where: updatecounter is null - update: columns: - column: name: updatecounter - value: 0 + valueNumeric: 0 tableName: employeeorder where: updatecounter is null - update: columns: - column: name: updatecounter - value: 0 + valueNumeric: 0 tableName: employeeordercontent where: updatecounter is null - update: columns: - column: name: updatecounter - value: 0 + valueNumeric: 0 tableName: overtime where: updatecounter is null - update: columns: - column: name: updatecounter - value: 0 + valueNumeric: 0 tableName: publicholiday where: updatecounter is null - update: columns: - column: name: updatecounter - value: 0 + valueNumeric: 0 tableName: referenceday where: updatecounter is null - update: columns: - column: name: updatecounter - value: 0 + valueNumeric: 0 tableName: statusreport where: updatecounter is null - update: columns: - column: name: updatecounter - value: 0 + valueNumeric: 0 tableName: suborder where: updatecounter is null - update: columns: - column: name: updatecounter - value: 0 + valueNumeric: 0 tableName: timereport where: updatecounter is null - update: columns: - column: name: updatecounter - value: 0 + valueNumeric: 0 tableName: vacation where: updatecounter is null - update: columns: - column: name: updatecounter - value: 0 + valueNumeric: 0 tableName: workingday where: updatecounter is null + - changeSet: + id: 7 + author: kr + comment: Introduce daily working time in minutes + preConditions: + - onFail: MARK_RAN + - columnExists: + tableName: employeecontract + columnName: dailyWorkingTime + changes: + - addColumn: + tableName: employeecontract + columns: + - column: + name: dailyWorkingTimeMinutes + type: int + - update: + columns: + - column: + name: dailyWorkingTimeMinutes + valueComputed: ROUND(dailyWorkingTime * 60) + tableName: employeecontract + where: dailyWorkingTimeMinutes is null + - addNotNullConstraint: + tableName: employeecontract + columnName: dailyWorkingTimeMinutes + columnDataType: int + - dropColumn: + tableName: employeecontract + columnName: dailyWorkingTime + - changeSet: + id: 8 + author: kr + comment: Introduce overtime static in minutes + preConditions: + - onFail: MARK_RAN + - columnExists: + tableName: employeecontract + columnName: overtimeStatic + changes: + - addColumn: + tableName: employeecontract + columns: + - column: + name: overtimeStaticMinutes + type: int + - update: + columns: + - column: + name: overtimeStaticMinutes + valueComputed: ROUND(overtimeStatic * 60) + tableName: employeecontract + where: overtimeStaticMinutes is null + - addNotNullConstraint: + tableName: employeecontract + columnName: overtimeStaticMinutes + columnDataType: int + - dropColumn: + tableName: employeecontract + columnName: overtimeStatic + - changeSet: + id: 9 + author: kr + comment: Introduce customer order debit hours in minutes + preConditions: + - onFail: MARK_RAN + - columnExists: + tableName: customerorder + columnName: debithours + - not: + - columnExists: + tableName: customerorder + columnName: debitMinutes + changes: + - addColumn: + tableName: customerorder + columns: + - column: + name: debitMinutes + type: int + - update: + columns: + - column: + name: debitMinutes + valueComputed: ROUND(debithours * 60) + tableName: customerorder + where: debitMinutes is null + - update: + columns: + - column: + name: debitMinutes + valueNumeric: 0 + tableName: customerorder + where: debitMinutes is null + - addNotNullConstraint: + tableName: customerorder + columnName: debitMinutes + columnDataType: int + - dropColumn: + tableName: customerorder + columnName: debithours + - changeSet: + id: 10 + author: kr + comment: Introduce suborder debit hours in minutes + preConditions: + - onFail: MARK_RAN + - columnExists: + tableName: suborder + columnName: debithours + - not: + - columnExists: + tableName: suborder + columnName: debitMinutes + changes: + - addColumn: + tableName: suborder + columns: + - column: + name: debitMinutes + type: int + - update: + columns: + - column: + name: debitMinutes + valueComputed: ROUND(debithours * 60) + tableName: suborder + where: debitMinutes is null + - update: + columns: + - column: + name: debitMinutes + valueNumeric: 0 + tableName: suborder + where: debitMinutes is null + - addNotNullConstraint: + tableName: suborder + columnName: debitMinutes + columnDataType: int + - dropColumn: + tableName: suborder + columnName: debithours + - changeSet: + id: 11 + author: kr + comment: Introduce overtime in minutes + preConditions: + - onFail: MARK_RAN + - columnExists: + tableName: overtime + columnName: time + - not: + - columnExists: + tableName: overtime + columnName: timeMinutes + changes: + - addColumn: + tableName: overtime + columns: + - column: + name: timeMinutes + type: int + - update: + columns: + - column: + name: timeMinutes + valueComputed: ROUND(time * 60) + tableName: overtime + where: timeMinutes is null + - update: + columns: + - column: + name: timeMinutes + valueNumeric: 0 + tableName: overtime + where: timeMinutes is null + - addNotNullConstraint: + tableName: overtime + columnName: timeMinutes + columnDataType: int + - dropColumn: + tableName: overtime + columnName: time + - changeSet: + id: 12 + author: kr + comment: Introduce employee order debit hours in minutes + preConditions: + - onFail: MARK_RAN + - columnExists: + tableName: employeeorder + columnName: debithours + - not: + - columnExists: + tableName: employeeorder + columnName: debitMinutes + changes: + - addColumn: + tableName: employeeorder + columns: + - column: + name: debitMinutes + type: int + - update: + columns: + - column: + name: debitMinutes + valueComputed: ROUND(debithours * 60) + tableName: employeeorder + where: debitMinutes is null + - update: + columns: + - column: + name: debitMinutes + valueNumeric: 0 + tableName: employeeorder + where: debitMinutes is null + - addNotNullConstraint: + tableName: employeeorder + columnName: debitMinutes + columnDataType: int + - dropColumn: + tableName: employeeorder + columnName: debithours + - changeSet: + id: 13 + author: kr + comment: Remove timereport costs + preConditions: + - onFail: MARK_RAN + - columnExists: + tableName: timereport + columnName: costs + changes: + - dropColumn: + tableName: timereport + columnName: costs + - changeSet: + id: 14 + author: kr + comment: Minutes columns must be 0 at least + changes: + - update: + columns: + - column: + name: debitMinutes + valueNumeric: 0 + tableName: customerorder + where: debitMinutes is null + - update: + columns: + - column: + name: debitMinutes + valueNumeric: 0 + tableName: employeeorder + where: debitMinutes is null + - update: + columns: + - column: + name: debitMinutes + valueNumeric: 0 + tableName: suborder + where: debitMinutes is null diff --git a/src/main/resources/org/tb/web/MessageResources_de.properties b/src/main/resources/org/tb/web/MessageResources_de.properties index eda7e008f..2df080f5b 100644 --- a/src/main/resources/org/tb/web/MessageResources_de.properties +++ b/src/main/resources/org/tb/web/MessageResources_de.properties @@ -25,6 +25,8 @@ errorcode.tr.0021=Datum passt nicht zum Mitarbeitervertrag errorcode.tr.0022=Buchungen können nur im vergangenen, aktuellen oder nächsten Jahr vorgenommen bzw. geändert werden errorcode.tr.0023=Überstundenausgleich kann nur mit einer Zeit von 00:00 gebucht werden +common.error.admin.required=Für diese Aktion sind Adminrechte erforderlich. + form.login.error.loginname.empty=Bitte User eingeben. form.login.error.password.empty=Bitte Kennwort eingeben. form.login.error.unknownuser=Benutzer unbekannt oder Password falsch. diff --git a/src/main/resources/org/tb/web/MessageResources_en.properties b/src/main/resources/org/tb/web/MessageResources_en.properties index 3307a503e..96125a62c 100644 --- a/src/main/resources/org/tb/web/MessageResources_en.properties +++ b/src/main/resources/org/tb/web/MessageResources_en.properties @@ -25,6 +25,8 @@ errorcode.tr.0021=Date does not match the employee contract errorcode.tr.0022=Bookings can only be modified in the last, current or next year errorcode.tr.0023=Overtime compensations must always be booked with 00:00 time +common.error.admin.required=This action requires admin priveleges. + form.login.error.loginname.empty=Please enter a loginname. form.login.error.password.empty=Please enter a password. form.login.error.unknownuser=Unknown user or wrong password. diff --git a/src/main/webapp/WEB-INF/java8DateFormatting.tld b/src/main/webapp/WEB-INF/java8DateFormatting.tld index 5d19eb4a2..7713efdde 100644 --- a/src/main/webapp/WEB-INF/java8DateFormatting.tld +++ b/src/main/webapp/WEB-INF/java8DateFormatting.tld @@ -1,21 +1,17 @@ - - + - - - 1.0 - 1.1 - java8-date-formatting-taglib - - + 1.1 + java8-date-formatting-taglib + http://hbt.de/jsp/taglib/java8-date-formatting formatLocalDate - org.tb.common.jsptags.FormatLocalDateTag - empty - Formats a given LocalDate using DateUtils + org.tb.common.jsptags.FormatLocalDateTag + empty + Formats a given LocalDate using DateUtils value true @@ -25,9 +21,21 @@ formatLocalDateTime - org.tb.common.jsptags.FormatLocalDateTimeTag - empty - Formats a given LocalDateTime using DateUtils + org.tb.common.jsptags.FormatLocalDateTimeTag + empty + Formats a given LocalDateTime using DateUtils + + value + true + true + + + + + formatDuration + org.tb.common.jsptags.FormatDurationTag + empty + Formats a given Duration using DurationUtils value true diff --git a/src/main/webapp/WEB-INF/treeTag.tld b/src/main/webapp/WEB-INF/treeTag.tld index 0abc39bef..2457c2b44 100644 --- a/src/main/webapp/WEB-INF/treeTag.tld +++ b/src/main/webapp/WEB-INF/treeTag.tld @@ -1,38 +1,65 @@ - - + - + 1.1 + davisjsp + http://hbt.de/jsp/taglib/tree -1.0 -1.1 -davisjsp - - - - - - - -tree -org.tb.common.jsptags.TreeTag -JSP -Outputs node in a HTML menu tree - - mainProject false true - subProjects false true - browser false true - changeFunctionString false true - deleteFunctionString false true - onlySuborders false true - defaultString false true - currentSuborderID false true - endlessDate false true - - - + + + tree + org.tb.common.jsptags.TreeTag + JSP + Outputs nodes in a HTML menu tree + + mainProject + false + true + + + subProjects + false + true + + + browser + false + true + + + changeFunctionString + false + true + + + deleteFunctionString + false + true + + + onlySuborders + false + true + + + defaultString + false + true + + + currentSuborderID + false + true + + + endlessDate + false + true + + diff --git a/src/main/webapp/dailyreport/showMatrix.jsp b/src/main/webapp/dailyreport/showMatrix.jsp index 08689ee50..fd826f64a 100644 --- a/src/main/webapp/dailyreport/showMatrix.jsp +++ b/src/main/webapp/dailyreport/showMatrix.jsp @@ -448,15 +448,15 @@ - + - + - +
color:#FF0000;">color:#FF0000;">
diff --git a/src/main/webapp/employee/addEmployeeContract.jsp b/src/main/webapp/employee/addEmployeeContract.jsp index 309af6184..67ca60df2 100644 --- a/src/main/webapp/employee/addEmployeeContract.jsp +++ b/src/main/webapp/employee/addEmployeeContract.jsp @@ -7,6 +7,7 @@ <%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> +<%@ taglib uri="/WEB-INF/java8DateFormatting.tld" prefix="java8"%> @@ -454,7 +455,7 @@ - +

@@ -463,10 +464,10 @@
- - @@ -493,26 +494,26 @@ - - - - - - - diff --git a/src/main/webapp/employee/showEmployeeContract.jsp b/src/main/webapp/employee/showEmployeeContract.jsp index bc7180e00..fd30a1437 100644 --- a/src/main/webapp/employee/showEmployeeContract.jsp +++ b/src/main/webapp/employee/showEmployeeContract.jsp @@ -4,6 +4,7 @@ <%@taglib uri="http://struts.apache.org/tags-html-el" prefix="html"%> <%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%> <%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic"%> +<%@ taglib uri="http://hbt.de/jsp/taglib/java8-date-formatting" prefix="java8"%> @@ -229,8 +230,11 @@ - + @@ -250,10 +254,14 @@ - - + + diff --git a/src/main/webapp/order/addEmployeeOrder.jsp b/src/main/webapp/order/addEmployeeOrder.jsp index 010a754a8..2fa7dda58 100644 --- a/src/main/webapp/order/addEmployeeOrder.jsp +++ b/src/main/webapp/order/addEmployeeOrder.jsp @@ -59,6 +59,7 @@ + diff --git a/src/main/webapp/order/addEmployeeOrderContent.jsp b/src/main/webapp/order/addEmployeeOrderContent.jsp index 3344f5217..9db016598 100644 --- a/src/main/webapp/order/addEmployeeOrderContent.jsp +++ b/src/main/webapp/order/addEmployeeOrderContent.jsp @@ -7,7 +7,7 @@ <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%> - +<%@ taglib uri="/WEB-INF/java8DateFormatting.tld" prefix="java8"%> @@ -127,11 +127,11 @@ @@ -372,11 +370,11 @@ value="${customerorder.order_customer}" /> @@ -508,11 +506,11 @@ diff --git a/src/main/webapp/order/showSuborder.jsp b/src/main/webapp/order/showSuborder.jsp index ae12a2d12..998e947d5 100644 --- a/src/main/webapp/order/showSuborder.jsp +++ b/src/main/webapp/order/showSuborder.jsp @@ -4,8 +4,9 @@ <%@taglib uri="http://struts.apache.org/tags-html-el" prefix="html"%> <%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%> <%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic"%> -<%@ taglib uri="/WEB-INF/treeTag.tld" prefix="myjsp"%> +<%@ taglib uri="http://hbt.de/jsp/taglib/tree" prefix="tree"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> +<%@ taglib uri="http://hbt.de/jsp/taglib/java8-date-formatting" prefix="java8"%> @@ -237,7 +238,7 @@ - - @@ -522,12 +523,11 @@ - + - + @@ -638,12 +636,11 @@ - + - + diff --git a/src/main/webapp/welcome/showWelcome.jsp b/src/main/webapp/welcome/showWelcome.jsp index 2cbbe008c..f0e32c715 100644 --- a/src/main/webapp/welcome/showWelcome.jsp +++ b/src/main/webapp/welcome/showWelcome.jsp @@ -20,7 +20,7 @@
+ : +
+ - + + +
+ - + + - + @@ -521,12 +522,12 @@
+ : + - +
+ + + + + + + + + + - + ./. - + / diff --git a/src/main/webapp/order/showCustomerOrder.jsp b/src/main/webapp/order/showCustomerOrder.jsp index 7ee08c7df..3c1409fa2 100644 --- a/src/main/webapp/order/showCustomerOrder.jsp +++ b/src/main/webapp/order/showCustomerOrder.jsp @@ -5,6 +5,7 @@ <%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%> <%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> +<%@ taglib uri="/WEB-INF/java8DateFormatting.tld" prefix="java8"%> @@ -279,11 +280,11 @@ - +   - + / @@ -303,22 +304,19 @@ - + - - + + - - + + - - + + - -   - - +   - + / @@ -396,18 +394,18 @@ - + - - + + - - + + - - + +   diff --git a/src/main/webapp/order/showEmployeeOrder.jsp b/src/main/webapp/order/showEmployeeOrder.jsp index 9ae20bf89..1e3e5271a 100644 --- a/src/main/webapp/order/showEmployeeOrder.jsp +++ b/src/main/webapp/order/showEmployeeOrder.jsp @@ -6,6 +6,7 @@ <%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> +<%@ taglib uri="/WEB-INF/java8DateFormatting.tld" prefix="java8"%> @@ -406,11 +407,11 @@ + test="${employeeorder.debithours == null || employeeorder.debithours.zero}">   - + / @@ -431,14 +432,14 @@ - + - + - + @@ -446,19 +447,16 @@ - - + + - - + + - - + + - -   - + test="${employeeorder.debithours == null || employeeorder.debithours.zero}">   - + / @@ -533,32 +531,29 @@ - + - + - + - - + + - - + + - - + + - -   - - +   - + / @@ -546,30 +546,28 @@ + + - - + + - + test="${suborder.difference != null && suborder.difference.negative}"> + - + test="${suborder.difference != null && !suborder.difference.negative}"> + - -   - + + - +   - + / @@ -663,30 +660,29 @@ - + test="${suborder.difference != null && suborder.debithoursunit != 0 && suborder.debithoursunit != 1 && suborder.debithoursunit != 12}"> + - + test="${suborder.difference != null && suborder.difference.negative}"> + - + test="${suborder.difference != null && !suborder.difference.negative}"> +