Skip to content

Commit

Permalink
Merge pull request #269 from micromata/Release-8.1-SNAPSHOT
Browse files Browse the repository at this point in the history
Release 8.1 snapshot
ForecastExport/ForecastTemplate: Planning data fixed.
Mass update improved: description of which fields were changed to excel file in user's data transfer box.
Timesheets: ignores no ai fields for recent entries as well as for favorites (should be done manually).
Selection of User/Employee improved (without autocompletion), see vacation editing...
EmployeeService.selectAllActive returns now sorted list of employees.
  • Loading branch information
kreinhard authored Jan 28, 2025
2 parents f29fb79 + 080620f commit 735ef6d
Show file tree
Hide file tree
Showing 28 changed files with 657 additions and 541 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class AddressCampaignValueMultiSelectedPageRest : AbstractMultiSelectedPage<Addr
selectedIds: Collection<Serializable>,
massUpdateContext: MassUpdateContext<AddressCampaignValue>,
): ResponseEntity<*>? {
val params = massUpdateContext.massUpdateData
val params = massUpdateContext.massUpdateParams
val addressCampaign = addressCampaignValuePagesRest.getAddressCampaign(request)
params["value"]?.let { param ->
param.textValue?.let { value ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

package org.projectforge.business.user.service;

import jakarta.annotation.PostConstruct;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
Expand Down Expand Up @@ -58,6 +59,9 @@ public class UserService {
private static final String MESSAGE_KEY_OLD_PASSWORD_WRONG = "user.changePassword.error.oldPasswordWrong";

private static final String MESSAGE_KEY_LOGIN_PASSWORD_WRONG = "user.changeWlanPassword.error.loginPasswordWrong";

private static UserService instance;

private final UsersComparator usersComparator = new UsersComparator();
private UserGroupCache userGroupCache;
private ConfigurationService configurationService;
Expand All @@ -73,6 +77,11 @@ public class UserService {
public UserService() {
}

@PostConstruct
private void postConstruct() {
instance = this;
}

@Autowired
public UserService(AccessChecker accessChecker, ConfigurationService configurationService, PasswordQualityService passwordQualityService, UserDao userDao, UserPasswordDao userPasswordDao, UserGroupCache userGroupCache, PfPersistenceService persistenceService) {
this.accessChecker = accessChecker;
Expand Down Expand Up @@ -525,4 +534,8 @@ public String decrypt(String encrypted) {
public String decrypt(String encrypted, Long userId) {
return userDao.decrypt(encrypted, userId);
}

public static UserService getInstance() {
return instance;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class EmployeeService {

@PostConstruct
private fun postConstruct() {
instance = this
employeeDao.employeeService = this
historyFormatService.register(EmployeeValidSinceAttrDO::class.java, EmployeeValidSinceAttrHistoryAdapter())
}
Expand Down Expand Up @@ -100,7 +101,7 @@ class EmployeeService {
* Returns all active employees.
* An employee is active if the austrittsdatum is not set or if the austrittsdatum is in the future.
* If showRecentLeft is true, the employee is also active if the austrittsdatum is within the last 3 months.
* @param checkAccess If true, the logged in user must have access to the employee.
* @param checkAccess If true, the logged-in user must have access to the employee.
* @param showRecentLeft If true, the employee is also active if the austrittsdatum is within the last 3 months.
* @return List of active employees.
*/
Expand All @@ -111,6 +112,7 @@ class EmployeeService {
employeeDao.selectAll(checkAccess = false)
}
return employeeList.filter { employee -> isEmployeeActive(employee, showRecentLeft) }
.sortedBy { it.displayName }
}

fun findByStaffnumber(staffnumber: Int?): EmployeeDO? {
Expand Down Expand Up @@ -173,7 +175,11 @@ class EmployeeService {
return getWeeklyWorkingHours(employee, LocalDate.now())
}

fun getWeeklyWorkingHours(employee: EmployeeDO?, validAtDate: LocalDate?, checkAccess: Boolean = true): BigDecimal? {
fun getWeeklyWorkingHours(
employee: EmployeeDO?,
validAtDate: LocalDate?,
checkAccess: Boolean = true
): BigDecimal? {
return employeeServiceSupport.getWeeklyWorkingHours(employee, validAtDate, checkAccess = checkAccess)
}

Expand Down Expand Up @@ -431,4 +437,9 @@ class EmployeeService {
monthlyEmployeeReport.calculate()
return monthlyEmployeeReport
}

companion object {
lateinit var instance: EmployeeService
private set
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,12 @@

package org.projectforge.business.fibu

import de.micromata.merlin.excel.ExcelSheet
import mu.KotlinLogging
import org.projectforge.business.fibu.kost.ProjektCache
import org.projectforge.business.fibu.orderbooksnapshots.OrderbookSnapshotsService
import org.projectforge.framework.access.AccessChecker
import org.projectforge.framework.time.PFDay
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.ApplicationContext
import org.springframework.stereotype.Service
import java.util.*

private val log = KotlinLogging.logger {}

Expand Down Expand Up @@ -87,68 +84,92 @@ internal class ForecastExportInvoices { // open needed by Wicket.
if (monthIndex !in -12..11) {
return@forEach // continue
}
val sheet = if (monthIndex < 0) ctx.invoicesPrevYearSheet else ctx.invoicesSheet
if (monthIndex < 0) {
if (monthIndex >= 0) {
insertIntoSheet(ctx, ctx.invoicesSheet, invoice, pos, order, orderPosId, firstMonthCol, monthIndex)
ctx.planningDate?.let { planningDate ->
if (invoice.datum!! < planningDate) {
// Planning date is given, so add the invoice to the planning sheet.
insertIntoSheet(
ctx,
ctx.planningInvoicesSheet,
invoice,
pos,
order,
orderPosId,
firstMonthCol,
monthIndex
)
}
}
} else {
monthIndex += 12
insertIntoSheet(ctx, ctx.invoicesPrevYearSheet, invoice, pos, order, orderPosId, firstMonthCol, monthIndex)
}
val rowNumber = sheet.createRow().rowNum
sheet.setIntValue(rowNumber, ForecastExportContext.InvoicesCol.INVOICE_NR.header, invoice.nummer)
sheet.setStringValue(rowNumber, ForecastExportContext.InvoicesCol.POS_NR.header, "#${pos.number}")
sheet.setDateValue(
rowNumber,
ForecastExportContext.InvoicesCol.DATE.header,
PFDay(invoice.datum!!).localDate,
ctx.excelDateFormat
)
val projekt = projektCache.getProjektIfNotInitialized(invoice.projekt)
sheet.setStringValue(
rowNumber,
ForecastExportContext.InvoicesCol.CUSTOMER.header,
invoice.kundeAsString
)
sheet.setStringValue(rowNumber, ForecastExportContext.InvoicesCol.PROJECT.header, projekt?.name)
sheet.setStringValue(rowNumber, ForecastExportContext.InvoicesCol.SUBJECT.header, invoice.betreff)
sheet.setStringValue(rowNumber, ForecastExportContext.InvoicesCol.POS_TEXT.header, pos.text)
invoice.bezahlDatum?.let {
sheet.setDateValue(
rowNumber,
ForecastExportContext.InvoicesCol.DATE_OF_PAYMENT.header,
PFDay(it).localDate,
ctx.excelDateFormat
)
}
val leistungsZeitraumColDef =
sheet.getColumnDef(ForecastExportContext.InvoicesCol.LEISTUNGSZEITRAUM.header)
invoice.periodOfPerformanceBegin?.let {
sheet.setDateValue(rowNumber, leistungsZeitraumColDef, PFDay(it).localDate, ctx.excelDateFormat)
}
invoice.periodOfPerformanceEnd?.let {
sheet.setDateValue(
rowNumber,
leistungsZeitraumColDef!!.columnNumber + 1,
PFDay(it).localDate,
ctx.excelDateFormat
)
}
if (order != null && orderPosId != null) {
sheet.setStringValue(
rowNumber,
ForecastExportContext.InvoicesCol.ORDER.header,
"${order.nummer}.${pos.auftragsPositionNummer}"
)
}
sheet.setBigDecimalValue(
rowNumber,
ForecastExportContext.InvoicesCol.NETSUM.header,
pos.netSum
).cellStyle =
ctx.currencyCellStyle
sheet.setBigDecimalValue(rowNumber, firstMonthCol + monthIndex, pos.netSum).cellStyle =
ctx.currencyCellStyle
}
}
}

private fun insertIntoSheet(
ctx: ForecastExportContext, sheet: ExcelSheet, invoice: RechnungDO, pos: RechnungPosInfo,
order: OrderInfo?, orderPosId: Long?, firstMonthCol: Int, monthIndex: Int,
) {
val rowNumber = sheet.createRow().rowNum
sheet.setIntValue(rowNumber, ForecastExportContext.InvoicesCol.INVOICE_NR.header, invoice.nummer)
sheet.setStringValue(rowNumber, ForecastExportContext.InvoicesCol.POS_NR.header, "#${pos.number}")
sheet.setDateValue(
rowNumber,
ForecastExportContext.InvoicesCol.DATE.header,
PFDay(invoice.datum!!).localDate,
ctx.excelDateFormat
)
val projekt = projektCache.getProjektIfNotInitialized(invoice.projekt)
sheet.setStringValue(
rowNumber,
ForecastExportContext.InvoicesCol.CUSTOMER.header,
invoice.kundeAsString
)
sheet.setStringValue(rowNumber, ForecastExportContext.InvoicesCol.PROJECT.header, projekt?.name)
sheet.setStringValue(rowNumber, ForecastExportContext.InvoicesCol.SUBJECT.header, invoice.betreff)
sheet.setStringValue(rowNumber, ForecastExportContext.InvoicesCol.POS_TEXT.header, pos.text)
invoice.bezahlDatum?.let {
sheet.setDateValue(
rowNumber,
ForecastExportContext.InvoicesCol.DATE_OF_PAYMENT.header,
PFDay(it).localDate,
ctx.excelDateFormat
)
}
val leistungsZeitraumColDef =
sheet.getColumnDef(ForecastExportContext.InvoicesCol.LEISTUNGSZEITRAUM.header)
invoice.periodOfPerformanceBegin?.let {
sheet.setDateValue(rowNumber, leistungsZeitraumColDef, PFDay(it).localDate, ctx.excelDateFormat)
}
invoice.periodOfPerformanceEnd?.let {
sheet.setDateValue(
rowNumber,
leistungsZeitraumColDef!!.columnNumber + 1,
PFDay(it).localDate,
ctx.excelDateFormat
)
}
if (order != null && orderPosId != null) {
sheet.setStringValue(
rowNumber,
ForecastExportContext.InvoicesCol.ORDER.header,
"${order.nummer}.${pos.auftragsPositionNummer}"
)
}
sheet.setBigDecimalValue(
rowNumber,
ForecastExportContext.InvoicesCol.NETSUM.header,
pos.netSum
).cellStyle =
ctx.currencyCellStyle
sheet.setBigDecimalValue(rowNumber, firstMonthCol + monthIndex, pos.netSum).cellStyle =
ctx.currencyCellStyle

}

private fun getMonthIndex(ctx: ForecastExportContext, date: PFDay): Int {
val monthDate = date.year * 12 + date.monthValue
val monthBaseDate = ctx.startDate.year * 12 + ctx.startDate.monthValue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,58 +29,75 @@ import org.projectforge.favorites.AbstractFavorite
import org.projectforge.framework.persistence.user.entities.PFUserDO

class TimesheetFavorite(
name: String? = null,
id: Long = 0,
var taskId: Long? = null,
var userId: Long? = null,
var location: String? = null,
var tag: String? = null,
var reference: String? = null,
var description: String? = null,
var cost2Id: Long? = null
name: String? = null,
id: Long = 0,
var taskId: Long? = null,
var userId: Long? = null,
var location: String? = null,
var tag: String? = null,
var reference: String? = null,
var description: String? = null,
var cost2Id: Long? = null,
// Don't copy these values to the timesheet. The user should enter them manually.
// var timeSavedByAI: BigDecimal? = null,
// var timeSavedByAIUnit: TimesheetDO.TimeSavedByAIUnit? = null,
// var timeSavedByAIDescription: String? = null,
) : AbstractFavorite(name, id) {

fun fillFromTimesheet(timesheet: TimesheetDO) {
if (timesheet.taskId != null) {
taskId = timesheet.taskId
fun fillFromTimesheet(timesheet: TimesheetDO) {
if (timesheet.taskId != null) {
taskId = timesheet.taskId
}
if (timesheet.userId != null) {
userId = timesheet.userId
}
if (!timesheet.location.isNullOrBlank()) {
location = timesheet.location
}
tag = timesheet.tag
if (!timesheet.reference.isNullOrBlank()) {
reference = timesheet.reference
}
if (!timesheet.description.isNullOrBlank()) {
description = timesheet.description
}
if (timesheet.kost2Id != null) {
cost2Id = timesheet.kost2Id
}
// Don't copy these values to the timesheet. The user should enter them manually.
/*if (timesheet.timeSavedByAI != null) {
timeSavedByAI = timesheet.timeSavedByAI
}
if (timesheet.timeSavedByAIUnit != null) {
timeSavedByAIUnit = timesheet.timeSavedByAIUnit
}
if (!timesheet.timeSavedByAIDescription.isNullOrBlank()) {
timeSavedByAIDescription = timesheet.timeSavedByAIDescription
}*/
}
if (timesheet.userId != null) {
userId = timesheet.userId
}
if (!timesheet.location.isNullOrBlank()) {
location = timesheet.location
}
tag = timesheet.tag
if (!timesheet.reference.isNullOrBlank()) {
reference = timesheet.reference
}
if (!timesheet.description.isNullOrBlank()) {
description = timesheet.description
}
if (timesheet.kost2Id != null) {
cost2Id = timesheet.kost2Id
}
}

fun copyToTimesheet(timesheet: TimesheetDO) {
if (taskId != null) {
val task = TaskDO()
task.id = taskId
timesheet.task = task
}
if (userId != null) {
val user = PFUserDO()
user.id = userId
timesheet.user = user
}
timesheet.location = location ?: ""
timesheet.tag = tag ?: "" // Overwrite client's value.
timesheet.reference = reference ?: ""
timesheet.description = description ?: ""
if (cost2Id != null) {
val cost2 = Kost2DO()
cost2.id = cost2Id
timesheet.kost2 = cost2
fun copyToTimesheet(timesheet: TimesheetDO) {
if (taskId != null) {
val task = TaskDO()
task.id = taskId
timesheet.task = task
}
if (userId != null) {
val user = PFUserDO()
user.id = userId
timesheet.user = user
}
timesheet.location = location ?: ""
timesheet.tag = tag ?: "" // Overwrite client's value.
timesheet.reference = reference ?: ""
timesheet.description = description ?: ""
// timesheet.timeSavedByAI = timeSavedByAI
// timesheet.timeSavedByAIUnit = timeSavedByAIUnit
// timesheet.timeSavedByAIDescription = timeSavedByAIDescription ?: ""
if (cost2Id != null) {
val cost2 = Kost2DO()
cost2.id = cost2Id
timesheet.kost2 = cost2
}
}
}
}
Loading

0 comments on commit 735ef6d

Please sign in to comment.