Skip to content

Commit

Permalink
MonthlyEmployeeReport: show weekly net and gross hours.
Browse files Browse the repository at this point in the history
Fix select in AuftragDao.positionen.status
Scripting: Add PFCaches as variable.
GlobalDefaultExceptionHandling: Exception handling improved.
  • Loading branch information
kreinhard committed Jan 2, 2025
1 parent 1bd5072 commit 4550ccc
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 166 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ public void calculate() {
taskTotal.addMillis(entry.getMillis());
}
totalGrossDuration += entry.getMillis();
totalNetDuration += entry.getMillis();
totalNetDuration += entry.getWorkFractionMillis();
}
}
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ public class MonthlyEmployeeReportWeek implements Serializable {

private long totalDuration = 0;

private long totalGrossDuration = 0;

/**
* Key is kost2 id.
*/
Expand Down Expand Up @@ -110,19 +112,14 @@ void addEntry(TimesheetDO sheet, final boolean hasSelectAccess) {
}
long duration = sheet.getDuration();
entry.addMillis(duration);
totalDuration += duration;
totalDuration += entry.getWorkFractionMillis();
totalGrossDuration += duration;
}

/**
* @see StringHelper#format2DigitNumber(int)
*/
public String getFormattedFromDayOfMonth() {
return StringHelper.format2DigitNumber(fromDate.getDayOfMonth());
}

/**
* @see StringHelper#format2DigitNumber(int)
*/
public String getFormattedToDayOfMonth() {
return StringHelper.format2DigitNumber(toDate.getDayOfMonth());
}
Expand All @@ -138,6 +135,10 @@ public String getFormattedTotalDuration() {
return MonthlyEmployeeReport.getFormattedDuration(totalDuration);
}

public String getFormattedGrossDuration() {
return MonthlyEmployeeReport.getFormattedDuration(totalGrossDuration);
}

/**
* Return the hours assigned to the different Kost2's. The key of the map is the kost2 id.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ import org.projectforge.framework.DisplayNameCapable
import org.projectforge.framework.i18n.I18nHelper
import org.projectforge.framework.jcr.AttachmentsInfo
import org.projectforge.framework.json.IdOnlySerializer
import org.projectforge.framework.json.IdsOnlySerializer
import org.projectforge.framework.persistence.candh.CandHIgnore
import org.projectforge.framework.persistence.entities.DefaultBaseDO
import org.projectforge.framework.persistence.history.NoHistory
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,9 +236,6 @@ open class AuftragDao : BaseDao<AuftragDO>(AuftragDO::class.java) {
eq("paymentSchedules.reached", true)
)
)
} else {
addCriterionForAuftragsStatuses(myFilter, queryFilter)
positionStatusAlreadyFilterd = true
}

if (myFilter.user != null) {
Expand Down Expand Up @@ -271,30 +268,13 @@ open class AuftragDao : BaseDao<AuftragDO>(AuftragDO::class.java) {
// Don't use filter for orders to be invoiced.
list = list.toMutableList() // Make mutable list of Kotlin's immutable list.
filterPositionsArten(myFilter, list)
if (!positionStatusAlreadyFilterd) { // Don't filter position status' again.
filterPositionsStatus(myFilter, list)
}
list = filterPositionsStatus(myFilter, list)
filterPositionsPaymentTypes(myFilter, list)
}

return list
}

private fun addCriterionForAuftragsStatuses(myFilter: AuftragFilter, queryFilter: QueryFilter) {
val auftragsStatuses = myFilter.auftragsStatuses
if (auftragsStatuses.isNotEmpty()) {
val orCriterions: MutableList<DBPredicate> = ArrayList()
orCriterions.add(isIn<Any>("status", auftragsStatuses))
orCriterions.add(isIn<Any>("positionen.status", myFilter.auftragsStatuses))
queryFilter.add(or(*orCriterions.toTypedArray<DBPredicate>()))
}

// check deleted
if (!myFilter.ignoreDeleted) {
queryFilter.add(eq("positionen.deleted", myFilter.deleted))
}
}

private fun createCriterionForErfassungsDatum(myFilter: AuftragFilter): Optional<DBPredicate> {
val startDate = myFilter.startDate
val endDate = myFilter.endDate
Expand Down Expand Up @@ -335,19 +315,12 @@ open class AuftragDao : BaseDao<AuftragDO>(AuftragDO::class.java) {
}
}

private fun filterPositionsStatus(myFilter: AuftragFilter, list: List<AuftragDO>) {
if (CollectionUtils.isEmpty(myFilter.auftragsStatuses)) {
return
}
val statusFilter = AuftragsPositionsStatusFilter(myFilter.auftragsStatuses)
CollectionUtils.filter(
list
) { `object`: AuftragDO? ->
statusFilter.match(
list.toMutableList(),
`object`!!
)
private fun filterPositionsStatus(myFilter: AuftragFilter, list: List<AuftragDO>): List<AuftragDO> {
val auftragsStatuses: List<AuftragsStatus> = myFilter.auftragsStatuses
if (auftragsStatuses.isEmpty()) {
return list
}
return list.filter { auftrag -> auftrag.positionenExcludingDeleted.any { pos -> auftragsStatuses.contains(pos.status) } }
}

private fun filterPositionsPaymentTypes(myFilter: AuftragFilter, list: List<AuftragDO>) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
////////////////////////////////////////////////////////////////////////////
// Project ProjectForge Community Edition
// www.projectforge.org
//
// Copyright (C) 2001-2025 Micromata GmbH, Germany (www.micromata.com)
//
// ProjectForge is dual-licensed.
//
// This community edition is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation; version 3 of the License.
//
// This community edition is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see http://www.gnu.org/licenses/.
//
//////////////////////////////////////////////////////////////////////////

package org.projectforge.business.fibu

import org.projectforge.business.PfCaches.Companion.instance
import org.projectforge.business.fibu.kost.Kost2DO
import org.projectforge.business.task.TaskDO
import java.io.Serializable
import java.math.BigDecimal

/**
* Repräsentiert einen Eintrag innerhalb eines Wochenberichts eines Mitarbeiters zu einem Kostenträger (Anzahl Stunden).
* @author Kai Reinhard ([email protected])
*/
class MonthlyEmployeeReportEntry : Serializable {
/**
* Only given, if task is not given and vice versa.
*/
var kost2: Kost2DO? = null
private set

/**
* Only given, if kost2 is not given and vice versa.
*/
var task: TaskDO? = null
private set

var millis: Long = 0
private set

constructor(kost2: Kost2DO?) {
this.kost2 = kost2
}

constructor(task: TaskDO?) {
this.task = task
}

fun addMillis(millis: Long) {
this.millis += millis
}

/**
* If this entry has a kost2 with a working time fraction set or a kost2art with a working time fraction set then the fraction of millis
* will be returned.
*/
val workFractionMillis: Long
get() = workFraction.multiply(millis.toBigDecimal()).toLong()

val workFraction: BigDecimal
get() {
val useKost2 = instance.getKost2IfNotInitialized(kost2) ?: return BigDecimal.ONE
useKost2.workFraction?.let {
return it
}
return instance.getKost2ArtIfNotInitialized(useKost2.kost2Art)?.workFraction ?: BigDecimal.ONE
}

val formattedDuration: String
get() = MonthlyEmployeeReport.getFormattedDuration(millis)

companion object {
private const val serialVersionUID = 7290000602224467755L
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ package org.projectforge.business.scripting
import mu.KotlinLogging
import org.apache.commons.lang3.StringUtils
import org.projectforge.ProjectForgeVersion
import org.projectforge.business.PfCaches
import org.projectforge.business.fibu.ForecastExport
import org.projectforge.business.fibu.kost.reporting.ReportGeneratorList
import org.projectforge.business.task.ScriptingTaskTree
Expand Down Expand Up @@ -94,6 +95,7 @@ abstract class ScriptExecutor(
variables["log"] = scriptLogger
variables["reportList"] = ReportGeneratorList()
variables["i18n"] = I18n()
variables["caches"] = PfCaches.instance
variables["forecastExport"] =
ApplicationContextProvider.getApplicationContext().getBean(ForecastExport::class.java)
for (entry in Registry.getInstance().orderedList) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,6 @@ class TimesheetPagesRest : AbstractDTOPagesRest<TimesheetDO, Timesheet, Timeshee
table.add(lc, "tag", width = 100)
}
table.add(lc, "description", width = 1000)
layout.add(UILabel("'${translate("timesheet.totalDuration")}: tbd.")) // See TimesheetListForm
}

/**
Expand Down
Loading

0 comments on commit 4550ccc

Please sign in to comment.