# --
# Copyright (C) 2001-2019 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --
package Kernel::Modules::AgentAppointmentEdit;
use strict;
use warnings;
use Kernel::System::VariableCheck qw(:all);
use Kernel::Language qw(Translatable);
our $ObjectManagerDisabled = 1;
sub new {
my ( $Type, %Param ) = @_;
my $Self = {%Param};
bless( $Self, $Type );
$Self->{EmptyString} = '-';
return $Self;
}
sub Run {
my ( $Self, %Param ) = @_;
my $Output;
# get param object
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
# get names of all parameters
my @ParamNames = $ParamObject->GetParamNames();
# get params
my %GetParam;
PARAMNAME:
for my $Key (@ParamNames) {
# skip the Action parameter, it's giving BuildDateSelection problems for some reason
next PARAMNAME if $Key eq 'Action';
$GetParam{$Key} = $ParamObject->GetParam( Param => $Key );
}
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
my $CalendarObject = $Kernel::OM->Get('Kernel::System::Calendar');
my $AppointmentObject = $Kernel::OM->Get('Kernel::System::Calendar::Appointment');
my $PluginObject = $Kernel::OM->Get('Kernel::System::Calendar::Plugin');
my $JSON = $LayoutObject->JSONEncode( Data => [] );
my %PermissionLevel = (
'ro' => 1,
'move_into' => 2,
'create' => 3,
'note' => 4,
'owner' => 5,
'priority' => 6,
'rw' => 7,
);
my $Permissions = 'rw';
# challenge token check
$LayoutObject->ChallengeTokenCheck();
# ------------------------------------------------------------ #
# edit mask
# ------------------------------------------------------------ #
if ( $Self->{Subaction} eq 'EditMask' ) {
# get all user's valid calendars
my $ValidID = $Kernel::OM->Get('Kernel::System::Valid')->ValidLookup(
Valid => 'valid',
);
my @Calendars = $CalendarObject->CalendarList(
UserID => $Self->{UserID},
ValidID => $ValidID,
);
# transform data for select box
my @CalendarData = map {
{
Key => $_->{CalendarID},
Value => $_->{CalendarName},
}
} @Calendars;
# transform data for ID lookup
my %CalendarLookup = map {
$_->{CalendarID} => $_->{CalendarName}
} @Calendars;
for my $Calendar (@CalendarData) {
# check permissions
my $CalendarPermission = $CalendarObject->CalendarPermissionGet(
CalendarID => $Calendar->{Key},
UserID => $Self->{UserID},
);
if ( $PermissionLevel{$CalendarPermission} < 3 ) {
# permissions < create
$Calendar->{Disabled} = 1;
}
}
# define year boundaries
my ( %YearPeriodPast, %YearPeriodFuture );
for my $Field (qw (Start End RecurrenceUntil)) {
$YearPeriodPast{$Field} = $YearPeriodFuture{$Field} = 5;
}
# do not use date selection time zone calculation by default
my $OverrideTimeZone = 1;
my %Appointment;
if ( $GetParam{AppointmentID} ) {
%Appointment = $AppointmentObject->AppointmentGet(
AppointmentID => $GetParam{AppointmentID},
);
# non-existent appointment
if ( !$Appointment{AppointmentID} ) {
my $Output = $LayoutObject->Error(
Message => Translatable('Appointment not found!'),
);
return $LayoutObject->Attachment(
NoCache => 1,
ContentType => 'text/html',
Charset => $LayoutObject->{UserCharset},
Content => $Output,
Type => 'inline',
);
}
# use time zone calculation if editing existing appointments
# but only if not dealing with an all day appointment
else {
$OverrideTimeZone = $Appointment{AllDay} || 0;
}
# check permissions
$Permissions = $CalendarObject->CalendarPermissionGet(
CalendarID => $Appointment{CalendarID},
UserID => $Self->{UserID},
);
# Get start time components.
my $StartTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $Appointment{StartTime},
},
);
my $StartTimeSettings = $StartTimeObject->Get();
my $StartTimeComponents;
for my $Key ( sort keys %{$StartTimeSettings} ) {
$StartTimeComponents->{"Start$Key"} = $StartTimeSettings->{$Key};
}
# Get end time components.
my $EndTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $Appointment{EndTime},
},
);
# End times for all day appointments are inclusive, subtract whole day.
if ( $Appointment{AllDay} ) {
$EndTimeObject->Subtract(
Days => 1,
);
if ( $EndTimeObject < $StartTimeObject ) {
$EndTimeObject = $StartTimeObject->Clone();
}
}
my $EndTimeSettings = $EndTimeObject->Get();
my $EndTimeComponents;
for my $Key ( sort keys %{$EndTimeSettings} ) {
$EndTimeComponents->{"End$Key"} = $EndTimeSettings->{$Key};
}
%Appointment = ( %Appointment, %{$StartTimeComponents}, %{$EndTimeComponents} );
# Get recurrence until components.
if ( $Appointment{RecurrenceUntil} ) {
my $RecurrenceUntilTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $Appointment{RecurrenceUntil},
},
);
my $RecurrenceUntilSettings = $RecurrenceUntilTimeObject->Get();
my $RecurrenceUntilComponents;
for my $Key ( sort keys %{$EndTimeSettings} ) {
$RecurrenceUntilComponents->{"RecurrenceUntil$Key"} = $RecurrenceUntilSettings->{$Key};
}
%Appointment = ( %Appointment, %{$RecurrenceUntilComponents} );
}
# Recalculate year boundaries for build selection method.
my $DateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime');
my $DateTimeSettings = $DateTimeObject->Get();
for my $Field (qw(Start End RecurrenceUntil)) {
if ( $Appointment{"${Field}Year"} ) {
my $Diff = $Appointment{"${Field}Year"} - $DateTimeSettings->{Year};
if ( $Diff > 0 && abs $Diff > $YearPeriodFuture{$Field} ) {
$YearPeriodFuture{$Field} = abs $Diff;
}
elsif ( $Diff < 0 && abs $Diff > $YearPeriodPast{$Field} ) {
$YearPeriodPast{$Field} = abs $Diff;
}
}
}
if ( $Appointment{Recurring} ) {
my $RecurrenceType = $GetParam{RecurrenceType} || $Appointment{RecurrenceType};
if ( $RecurrenceType eq 'CustomWeekly' ) {
my $DayOffset = $Self->_DayOffsetGet(
Time => $Appointment{StartTime},
);
if ( defined $GetParam{Days} ) {
# check parameters
$Appointment{Days} = $GetParam{Days};
}
else {
my @Days = @{ $Appointment{RecurrenceFrequency} };
# display selected days according to user timezone
if ($DayOffset) {
for my $Day (@Days) {
$Day += $DayOffset;
if ( $Day == 8 ) {
$Day = 1;
}
}
}
$Appointment{Days} = join( ",", @Days );
}
}
elsif ( $RecurrenceType eq 'CustomMonthly' ) {
my $DayOffset = $Self->_DayOffsetGet(
Time => $Appointment{StartTime},
);
if ( defined $GetParam{MonthDays} ) {
# check parameters
$Appointment{MonthDays} = $GetParam{MonthDays};
}
else {
my @MonthDays = @{ $Appointment{RecurrenceFrequency} };
# display selected days according to user timezone
if ($DayOffset) {
for my $MonthDay (@MonthDays) {
$MonthDay += $DayOffset;
if ( $DateTimeSettings->{Day} == 32 ) {
$MonthDay = 1;
}
}
}
$Appointment{MonthDays} = join( ",", @MonthDays );
}
}
elsif ( $RecurrenceType eq 'CustomYearly' ) {
my $DayOffset = $Self->_DayOffsetGet(
Time => $Appointment{StartTime},
);
if ( defined $GetParam{Months} ) {
# check parameters
$Appointment{Months} = $GetParam{Months};
}
else {
my @Months = @{ $Appointment{RecurrenceFrequency} };
$Appointment{Months} = join( ",", @Months );
}
}
}
# Check if dealing with ticket appointment.
if ( $Appointment{TicketAppointmentRuleID} ) {
$GetParam{TicketID} = $CalendarObject->TicketAppointmentTicketID(
AppointmentID => $Appointment{AppointmentID},
);
my $Rule = $CalendarObject->TicketAppointmentRuleGet(
CalendarID => $Appointment{CalendarID},
RuleID => $Appointment{TicketAppointmentRuleID},
);
# Get date types from the ticket appointment rule.
if ( IsHashRefWithData($Rule) ) {
for my $Type (qw(StartDate EndDate)) {
if (
$Rule->{$Type} eq 'FirstResponseTime'
|| $Rule->{$Type} eq 'UpdateTime'
|| $Rule->{$Type} eq 'SolutionTime'
|| $Rule->{$Type} eq 'PendingTime'
)
{
$GetParam{ReadOnlyStart} = 1 if $Type eq 'StartDate';
$GetParam{ReadOnlyDuration} = 1 if $Type eq 'EndDate';
}
elsif ( $Rule->{$Type} =~ /^Plus_[0-9]+$/ ) {
$GetParam{ReadOnlyDuration} = 1;
}
}
}
}
}
# get selected timestamp
my $SelectedTimestamp = sprintf(
"%04d-%02d-%02d 00:00:00",
$Appointment{StartYear} // $GetParam{StartYear},
$Appointment{StartMonth} // $GetParam{StartMonth},
$Appointment{StartDay} // $GetParam{StartDay}
);
# Get current date components.
my $SelectedSystemTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $SelectedTimestamp,
},
);
my $SelectedSystemTimeSettings = $SelectedSystemTimeObject->Get();
# Set current date components if not defined.
$Appointment{Days} //= $SelectedSystemTimeSettings->{DayOfWeek};
$Appointment{MonthDays} //= $SelectedSystemTimeSettings->{Day};
$Appointment{Months} //= $SelectedSystemTimeSettings->{Month};
# calendar ID selection
my $CalendarID = $Appointment{CalendarID} // $GetParam{CalendarID};
# calendar name
if ($CalendarID) {
$Param{CalendarName} = $CalendarLookup{$CalendarID};
}
# calendar selection
$Param{CalendarIDStrg} = $LayoutObject->BuildSelection(
Data => \@CalendarData,
SelectedID => $CalendarID,
Name => 'CalendarID',
Multiple => 0,
Class => 'Modernize Validate_Required',
PossibleNone => 1,
);
# all day
if (
$GetParam{AllDay} ||
( $GetParam{AppointmentID} && $Appointment{AllDay} )
)
{
$Param{AllDayString} = Translatable('Yes');
$Param{AllDayChecked} = 'checked="checked"';
# start date
$Param{StartDate} = sprintf(
"%04d-%02d-%02d",
$Appointment{StartYear} // $GetParam{StartYear},
$Appointment{StartMonth} // $GetParam{StartMonth},
$Appointment{StartDay} // $GetParam{StartDay},
);
# end date
$Param{EndDate} = sprintf(
"%04d-%02d-%02d",
$Appointment{EndYear} // $GetParam{EndYear},
$Appointment{EndMonth} // $GetParam{EndMonth},
$Appointment{EndDay} // $GetParam{EndDay},
);
}
else {
$Param{AllDayString} = Translatable('No');
$Param{AllDayChecked} = '';
# start date
$Param{StartDate} = sprintf(
"%04d-%02d-%02d %02d:%02d:00",
$Appointment{StartYear} // $GetParam{StartYear},
$Appointment{StartMonth} // $GetParam{StartMonth},
$Appointment{StartDay} // $GetParam{StartDay},
$Appointment{StartHour} // $GetParam{StartHour},
$Appointment{StartMinute} // $GetParam{StartMinute},
);
# end date
$Param{EndDate} = sprintf(
"%04d-%02d-%02d %02d:%02d:00",
$Appointment{EndYear} // $GetParam{EndYear},
$Appointment{EndMonth} // $GetParam{EndMonth},
$Appointment{EndDay} // $GetParam{EndDay},
$Appointment{EndHour} // $GetParam{EndHour},
$Appointment{EndMinute} // $GetParam{EndMinute},
);
}
# start date string
$Param{StartDateString} = $LayoutObject->BuildDateSelection(
%GetParam,
%Appointment,
Prefix => 'Start',
StartHour => $Appointment{StartHour} // $GetParam{StartHour},
StartMinute => $Appointment{StartMinute} // $GetParam{StartMinute},
Format => 'DateInputFormatLong',
ValidateDateBeforePrefix => 'End',
Validate => $Appointment{TicketAppointmentRuleID} && $GetParam{ReadOnlyStart} ? 0 : 1,
YearPeriodPast => $YearPeriodPast{Start},
YearPeriodFuture => $YearPeriodFuture{Start},
OverrideTimeZone => $OverrideTimeZone,
);
# end date string
$Param{EndDateString} = $LayoutObject->BuildDateSelection(
%GetParam,
%Appointment,
Prefix => 'End',
EndHour => $Appointment{EndHour} // $GetParam{EndHour},
EndMinute => $Appointment{EndMinute} // $GetParam{EndMinute},
Format => 'DateInputFormatLong',
ValidateDateAfterPrefix => 'Start',
Validate => $Appointment{TicketAppointmentRuleID} && $GetParam{ReadOnlyDuration} ? 0 : 1,
YearPeriodPast => $YearPeriodPast{End},
YearPeriodFuture => $YearPeriodFuture{End},
OverrideTimeZone => $OverrideTimeZone,
);
# get main object
my $MainObject = $Kernel::OM->Get('Kernel::System::Main');
# check if team object is registered
if ( $MainObject->Require( 'Kernel::System::Calendar::Team', Silent => 1 ) ) {
my $TeamIDs = $Appointment{TeamID};
if ( !$TeamIDs ) {
my @TeamIDs = $ParamObject->GetArray( Param => 'TeamID[]' );
$TeamIDs = \@TeamIDs;
}
my $ResourceIDs = $Appointment{ResourceID};
if ( !$ResourceIDs ) {
my @ResourceIDs = $ParamObject->GetArray( Param => 'ResourceID[]' );
$ResourceIDs = \@ResourceIDs;
}
# get needed objects
my $TeamObject = $Kernel::OM->Get('Kernel::System::Calendar::Team');
my $UserObject = $Kernel::OM->Get('Kernel::System::User');
# get allowed team list for current user
my %TeamList = $TeamObject->AllowedTeamList(
PreventEmpty => 1,
UserID => $Self->{UserID},
);
# team names
my @TeamNames;
for my $TeamID ( @{$TeamIDs} ) {
push @TeamNames, $TeamList{$TeamID} if $TeamList{$TeamID};
}
if ( scalar @TeamNames ) {
$Param{TeamNames} = join( '
', @TeamNames );
}
else {
$Param{TeamNames} = $Self->{EmptyString};
}
# team list string
$Param{TeamIDStrg} = $LayoutObject->BuildSelection(
Data => \%TeamList,
SelectedID => $TeamIDs,
Name => 'TeamID',
Multiple => 1,
Class => 'Modernize',
PossibleNone => 1,
);
# iterate through selected teams
my %TeamUserListAll;
TEAMID:
for my $TeamID ( @{$TeamIDs} ) {
next TEAMID if !$TeamID;
# get list of team members
my %TeamUserList = $TeamObject->TeamUserList(
TeamID => $TeamID,
UserID => $Self->{UserID},
);
# get user data
for my $UserID ( sort keys %TeamUserList ) {
my %User = $UserObject->GetUserData(
UserID => $UserID,
);
$TeamUserList{$UserID} = $User{UserFullname};
}
%TeamUserListAll = ( %TeamUserListAll, %TeamUserList );
}
# resource names
my @ResourceNames;
for my $ResourceID ( @{$ResourceIDs} ) {
push @ResourceNames, $TeamUserListAll{$ResourceID} if $TeamUserListAll{$ResourceID};
}
if ( scalar @ResourceNames ) {
$Param{ResourceNames} = join( '
', @ResourceNames );
}
else {
$Param{ResourceNames} = $Self->{EmptyString};
}
# team user list string
$Param{ResourceIDStrg} = $LayoutObject->BuildSelection(
Data => \%TeamUserListAll,
SelectedID => $ResourceIDs,
Name => 'ResourceID',
Multiple => 1,
Class => 'Modernize',
PossibleNone => 1,
);
}
my $SelectedRecurrenceType = 0;
my $SelectedRecurrenceCustomType = 'CustomDaily'; # default
if ( $Appointment{Recurring} ) {
# from appointment
$SelectedRecurrenceType = $GetParam{RecurrenceType} || $Appointment{RecurrenceType};
if ( $SelectedRecurrenceType =~ /Custom/ ) {
$SelectedRecurrenceCustomType = $SelectedRecurrenceType;
$SelectedRecurrenceType = 'Custom';
}
}
# recurrence type
my @RecurrenceTypes = (
{
Key => '0',
Value => Translatable('Never'),
},
{
Key => 'Daily',
Value => Translatable('Every Day'),
},
{
Key => 'Weekly',
Value => Translatable('Every Week'),
},
{
Key => 'Monthly',
Value => Translatable('Every Month'),
},
{
Key => 'Yearly',
Value => Translatable('Every Year'),
},
{
Key => 'Custom',
Value => Translatable('Custom'),
},
);
my %RecurrenceTypeLookup = map {
$_->{Key} => $_->{Value}
} @RecurrenceTypes;
$Param{RecurrenceValue} = $LayoutObject->{LanguageObject}->Translate(
$RecurrenceTypeLookup{$SelectedRecurrenceType},
);
# recurrence type selection
$Param{RecurrenceTypeString} = $LayoutObject->BuildSelection(
Data => \@RecurrenceTypes,
SelectedID => $SelectedRecurrenceType,
Name => 'RecurrenceType',
Multiple => 0,
Class => 'Modernize',
PossibleNone => 0,
);
# recurrence custom type
my @RecurrenceCustomTypes = (
{
Key => 'CustomDaily',
Value => Translatable('Daily'),
},
{
Key => 'CustomWeekly',
Value => Translatable('Weekly'),
},
{
Key => 'CustomMonthly',
Value => Translatable('Monthly'),
},
{
Key => 'CustomYearly',
Value => Translatable('Yearly'),
},
);
my %RecurrenceCustomTypeLookup = map {
$_->{Key} => $_->{Value}
} @RecurrenceCustomTypes;
my $RecurrenceCustomType = $RecurrenceCustomTypeLookup{$SelectedRecurrenceCustomType};
$Param{RecurrenceValue} .= ', ' . $LayoutObject->{LanguageObject}->Translate(
lc $RecurrenceCustomType,
) if $RecurrenceCustomType && $SelectedRecurrenceType eq 'Custom';
# recurrence custom type selection
$Param{RecurrenceCustomTypeString} = $LayoutObject->BuildSelection(
Data => \@RecurrenceCustomTypes,
SelectedID => $SelectedRecurrenceCustomType,
Name => 'RecurrenceCustomType',
Class => 'Modernize',
);
# recurrence interval
my $SelectedInterval = $GetParam{RecurrenceInterval} || $Appointment{RecurrenceInterval} || 1;
if ( $Appointment{RecurrenceInterval} ) {
my %RecurrenceIntervalLookup = (
'CustomDaily' => $LayoutObject->{LanguageObject}->Translate(
'day(s)',
),
'CustomWeekly' => $LayoutObject->{LanguageObject}->Translate(
'week(s)',
),
'CustomMonthly' => $LayoutObject->{LanguageObject}->Translate(
'month(s)',
),
'CustomYearly' => $LayoutObject->{LanguageObject}->Translate(
'year(s)',
),
);
if ( $RecurrenceCustomType && $SelectedRecurrenceType eq 'Custom' ) {
$Param{RecurrenceValue} .= ', '
. $LayoutObject->{LanguageObject}->Translate('every')
. ' ' . $Appointment{RecurrenceInterval} . ' '
. $RecurrenceIntervalLookup{$SelectedRecurrenceCustomType};
}
}
# add interval selection (1-31)
my @RecurrenceCustomInterval;
for ( my $DayNumber = 1; $DayNumber < 32; $DayNumber++ ) {
push @RecurrenceCustomInterval, {
Key => $DayNumber,
Value => $DayNumber,
};
}
$Param{RecurrenceIntervalString} = $LayoutObject->BuildSelection(
Data => \@RecurrenceCustomInterval,
SelectedID => $SelectedInterval,
Name => 'RecurrenceInterval',
);
# recurrence limit
my $RecurrenceLimit = 1;
if ( $Appointment{RecurrenceCount} ) {
$RecurrenceLimit = 2;
if ($SelectedRecurrenceType) {
$Param{RecurrenceValue} .= ', ' . $LayoutObject->{LanguageObject}->Translate(
'for %s time(s)', $Appointment{RecurrenceCount},
);
}
}
# recurrence limit string
$Param{RecurrenceLimitString} = $LayoutObject->BuildSelection(
Data => [
{
Key => 1,
Value => Translatable('until ...'),
},
{
Key => 2,
Value => Translatable('for ... time(s)'),
},
],
SelectedID => $RecurrenceLimit,
Name => 'RecurrenceLimit',
Multiple => 0,
Class => 'Modernize',
PossibleNone => 0,
);
my $RecurrenceUntilDiffTime = 0;
if ( !$Appointment{RecurrenceUntil} ) {
# Get current and start time for difference.
my $SystemTime = $Kernel::OM->Create('Kernel::System::DateTime')->ToEpoch();
my $StartTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
Year => $Appointment{StartYear} // $GetParam{StartYear},
Month => $Appointment{StartMonth} // $GetParam{StartMonth},
Day => $Appointment{StartDay} // $GetParam{StartDay},
Hour => $Appointment{StartHour} // $GetParam{StartHour},
Minute => $Appointment{StartMinute} // $GetParam{StartMinute},
Second => 0,
},
);
my $StartTime = $StartTimeObject->ToEpoch();
$RecurrenceUntilDiffTime = $StartTime - $SystemTime + 60 * 60 * 24 * 3; # start +3 days
}
else {
$Param{RecurrenceUntil} = sprintf(
"%04d-%02d-%02d",
$Appointment{RecurrenceUntilYear},
$Appointment{RecurrenceUntilMonth},
$Appointment{RecurrenceUntilDay},
);
if ($SelectedRecurrenceType) {
$Param{RecurrenceValue} .= ', ' . $LayoutObject->{LanguageObject}->Translate(
'until %s', $Param{RecurrenceUntil},
);
}
}
# recurrence until date string
$Param{RecurrenceUntilString} = $LayoutObject->BuildDateSelection(
%Appointment,
%GetParam,
Prefix => 'RecurrenceUntil',
Format => 'DateInputFormat',
DiffTime => $RecurrenceUntilDiffTime,
ValidateDateAfterPrefix => 'Start',
Validate => 1,
YearPeriodPast => $YearPeriodPast{RecurrenceUntil},
YearPeriodFuture => $YearPeriodFuture{RecurrenceUntil},
OverrideTimeZone => $OverrideTimeZone,
);
# notification template
my @NotificationTemplates = (
{
Key => '0',
Value => $LayoutObject->{LanguageObject}->Translate('No notification'),
},
{
Key => 'Start',
Value => $LayoutObject->{LanguageObject}->Translate( '%s minute(s) before', 0 ),
},
{
Key => '300',
Value => $LayoutObject->{LanguageObject}->Translate( '%s minute(s) before', 5 ),
},
{
Key => '900',
Value => $LayoutObject->{LanguageObject}->Translate( '%s minute(s) before', 15 ),
},
{
Key => '1800',
Value => $LayoutObject->{LanguageObject}->Translate( '%s minute(s) before', 30 ),
},
{
Key => '3600',
Value => $LayoutObject->{LanguageObject}->Translate( '%s hour(s) before', 1 ),
},
{
Key => '7200',
Value => $LayoutObject->{LanguageObject}->Translate( '%s hour(s) before', 2 ),
},
{
Key => '43200',
Value => $LayoutObject->{LanguageObject}->Translate( '%s hour(s) before', 12 ),
},
{
Key => '86400',
Value => $LayoutObject->{LanguageObject}->Translate( '%s day(s) before', 1 ),
},
{
Key => '172800',
Value => $LayoutObject->{LanguageObject}->Translate( '%s day(s) before', 2 ),
},
{
Key => '604800',
Value => $LayoutObject->{LanguageObject}->Translate( '%s week before', 1 ),
},
{
Key => 'Custom',
Value => $LayoutObject->{LanguageObject}->Translate('Custom'),
},
);
my %NotificationTemplateLookup = map {
$_->{Key} => $_->{Value}
} @NotificationTemplates;
my $SelectedNotificationTemplate = $Appointment{NotificationTemplate} || '0';
$Param{NotificationValue} = $NotificationTemplateLookup{$SelectedNotificationTemplate};
# notification selection
$Param{NotificationStrg} = $LayoutObject->BuildSelection(
Data => \@NotificationTemplates,
SelectedID => $SelectedNotificationTemplate,
Name => 'NotificationTemplate',
Multiple => 0,
Class => 'Modernize',
PossibleNone => 0,
);
# notification custom units
my @NotificationCustomUnits = (
{
Key => 'minutes',
Value => $LayoutObject->{LanguageObject}->Translate('minute(s)'),
},
{
Key => 'hours',
Value => $LayoutObject->{LanguageObject}->Translate('hour(s)'),
},
{
Key => 'days',
Value => $LayoutObject->{LanguageObject}->Translate('day(s)'),
},
);
my %NotificationCustomUnitLookup = map {
$_->{Key} => $_->{Value}
} @NotificationCustomUnits;
my $SelectedNotificationCustomUnit = $Appointment{NotificationCustomRelativeUnit} || 'minutes';
# notification custom units selection
$Param{NotificationCustomUnitsStrg} = $LayoutObject->BuildSelection(
Data => \@NotificationCustomUnits,
SelectedID => $SelectedNotificationCustomUnit,
Name => 'NotificationCustomRelativeUnit',
Multiple => 0,
Class => 'Modernize',
PossibleNone => 0,
);
# notification custom units point of time
my @NotificationCustomUnitsPointOfTime = (
{
Key => 'beforestart',
Value => $LayoutObject->{LanguageObject}->Translate('before the appointment starts'),
},
{
Key => 'afterstart',
Value => $LayoutObject->{LanguageObject}->Translate('after the appointment has been started'),
},
{
Key => 'beforeend',
Value => $LayoutObject->{LanguageObject}->Translate('before the appointment ends'),
},
{
Key => 'afterend',
Value => $LayoutObject->{LanguageObject}->Translate('after the appointment has been ended'),
},
);
my %NotificationCustomUnitPointOfTimeLookup = map {
$_->{Key} => $_->{Value}
} @NotificationCustomUnitsPointOfTime;
my $SelectedNotificationCustomUnitPointOfTime = $Appointment{NotificationCustomRelativePointOfTime}
|| 'beforestart';
# notification custom units point of time selection
$Param{NotificationCustomUnitsPointOfTimeStrg} = $LayoutObject->BuildSelection(
Data => \@NotificationCustomUnitsPointOfTime,
SelectedID => $SelectedNotificationCustomUnitPointOfTime,
Name => 'NotificationCustomRelativePointOfTime',
Multiple => 0,
Class => 'Modernize',
PossibleNone => 0,
);
# Extract the date units for the custom date selection.
my $NotificationCustomDateTimeSettings = {};
if ( $Appointment{NotificationCustomDateTime} ) {
my $NotificationCustomDateTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $Appointment{NotificationCustomDateTime},
},
);
$NotificationCustomDateTimeSettings = $NotificationCustomDateTimeObject->Get();
}
# notification custom date selection
$Param{NotificationCustomDateTimeStrg} = $LayoutObject->BuildDateSelection(
Prefix => 'NotificationCustomDateTime',
NotificationCustomDateTimeYear => $NotificationCustomDateTimeSettings->{Year},
NotificationCustomDateTimeMonth => $NotificationCustomDateTimeSettings->{Month},
NotificationCustomDateTimeDay => $NotificationCustomDateTimeSettings->{Day},
NotificationCustomDateTimeHour => $NotificationCustomDateTimeSettings->{Hour},
NotificationCustomDateTimeMinute => $NotificationCustomDateTimeSettings->{Minute},
Format => 'DateInputFormatLong',
YearPeriodPast => $YearPeriodPast{Start},
YearPeriodFuture => $YearPeriodFuture{Start},
);
# prepare radio button for custom date time and relative input
$Appointment{NotificationCustom} ||= '';
if ( $Appointment{NotificationCustom} eq 'datetime' ) {
$Param{NotificationCustomDateTimeInputRadio} = 'checked="checked"';
}
elsif ( $Appointment{NotificationCustom} eq 'relative' ) {
$Param{NotificationCustomRelativeInputRadio} = 'checked="checked"';
}
else {
$Param{NotificationCustomRelativeInputRadio} = 'checked="checked"';
}
# notification custom string value
if ( $Appointment{NotificationCustom} eq 'datetime' ) {
$Param{NotificationValue} .= ', ' . $LayoutObject->{LanguageObject}->FormatTimeString(
$Appointment{NotificationCustomDateTime},
'DateFormat'
);
}
elsif ( $Appointment{NotificationCustom} eq 'relative' ) {
if (
$Appointment{NotificationCustomRelativeUnit}
&& $Appointment{NotificationCustomRelativePointOfTime}
)
{
$Appointment{NotificationCustomRelativeUnitCount} ||= 0;
$Param{NotificationValue} .= ', '
. $Appointment{NotificationCustomRelativeUnitCount}
. ' '
. $NotificationCustomUnitLookup{$SelectedNotificationCustomUnit}
. ' '
. $NotificationCustomUnitPointOfTimeLookup{$SelectedNotificationCustomUnitPointOfTime};
}
}
# get plugin list
$Param{PluginList} = $PluginObject->PluginList();
# new appointment plugin search
if ( $GetParam{PluginKey} && ( $GetParam{Search} || $GetParam{ObjectID} ) ) {
if ( grep { $_ eq $GetParam{PluginKey} } keys %{ $Param{PluginList} } ) {
# search using plugin
my $ResultList = $PluginObject->PluginSearch(
%GetParam,
UserID => $Self->{UserID},
);
$Param{PluginData}->{ $GetParam{PluginKey} } = [];
my @LinkArray = sort keys %{$ResultList};
# add possible links
for my $LinkID (@LinkArray) {
push @{ $Param{PluginData}->{ $GetParam{PluginKey} } }, {
LinkID => $LinkID,
LinkName => $ResultList->{$LinkID},
LinkURL => sprintf(
$Param{PluginList}->{ $GetParam{PluginKey} }->{PluginURL},
$LinkID
),
};
}
$Param{PluginList}->{ $GetParam{PluginKey} }->{LinkList} = $LayoutObject->JSONEncode(
Data => \@LinkArray,
);
}
}
# edit appointment plugin links
elsif ( $GetParam{AppointmentID} ) {
for my $PluginKey ( sort keys %{ $Param{PluginList} } ) {
my $LinkList = $PluginObject->PluginLinkList(
AppointmentID => $GetParam{AppointmentID},
PluginKey => $PluginKey,
UserID => $Self->{UserID},
);
my @LinkArray;
$Param{PluginData}->{$PluginKey} = [];
for my $LinkID ( sort keys %{$LinkList} ) {
push @{ $Param{PluginData}->{$PluginKey} }, $LinkList->{$LinkID};
push @LinkArray, $LinkList->{$LinkID}->{LinkID};
}
$Param{PluginList}->{$PluginKey}->{LinkList} = $LayoutObject->JSONEncode(
Data => \@LinkArray,
);
}
}
# html mask output
$LayoutObject->Block(
Name => 'EditMask',
Data => {
%Param,
%GetParam,
%Appointment,
PermissionLevel => $PermissionLevel{$Permissions},
},
);
$LayoutObject->AddJSData(
Key => 'CalendarPermissionLevel',
Value => $PermissionLevel{$Permissions},
);
$LayoutObject->AddJSData(
Key => 'EditAppointmentID',
Value => $Appointment{AppointmentID} // '',
);
$LayoutObject->AddJSData(
Key => 'EditParentID',
Value => $Appointment{ParentID} // '',
);
# get registered location links
my $LocationLinkConfig = $ConfigObject->Get('AgentAppointmentEdit::Location::Link') // {};
for my $ConfigKey ( sort keys %{$LocationLinkConfig} ) {
# show link icon
$LayoutObject->Block(
Name => 'LocationLink',
Data => {
Location => $Appointment{Location} // '',
%{ $LocationLinkConfig->{$ConfigKey} },
},
);
}
my $Output = $LayoutObject->Output(
TemplateFile => 'AgentAppointmentEdit',
Data => {
%Param,
%GetParam,
%Appointment,
},
AJAX => 1,
);
return $LayoutObject->Attachment(
NoCache => 1,
ContentType => 'text/html',
Charset => $LayoutObject->{UserCharset},
Content => $Output,
Type => 'inline',
);
}
# ------------------------------------------------------------ #
# add/edit appointment
# ------------------------------------------------------------ #
elsif ( $Self->{Subaction} eq 'EditAppointment' ) {
my %Appointment;
if ( $GetParam{AppointmentID} ) {
%Appointment = $AppointmentObject->AppointmentGet(
AppointmentID => $GetParam{AppointmentID},
);
# check permissions
$Permissions = $CalendarObject->CalendarPermissionGet(
CalendarID => $Appointment{CalendarID},
UserID => $Self->{UserID},
);
my $RequiredPermission = 2;
if ( $GetParam{CalendarID} && $GetParam{CalendarID} != $Appointment{CalendarID} ) {
# in order to move appointment to another calendar, user needs "create" permission
$RequiredPermission = 3;
}
if ( $PermissionLevel{$Permissions} < $RequiredPermission ) {
# no permission
# build JSON output
$JSON = $LayoutObject->JSONEncode(
Data => {
Success => 0,
Error => Translatable('No permission!'),
},
);
# send JSON response
return $LayoutObject->Attachment(
ContentType => 'application/json; charset=' . $LayoutObject->{Charset},
Content => $JSON,
Type => 'inline',
NoCache => 1,
);
}
}
if ( $GetParam{AllDay} ) {
$GetParam{StartTime} = sprintf(
"%04d-%02d-%02d 00:00:00",
$GetParam{StartYear}, $GetParam{StartMonth}, $GetParam{StartDay}
);
$GetParam{EndTime} = sprintf(
"%04d-%02d-%02d 00:00:00",
$GetParam{EndYear}, $GetParam{EndMonth}, $GetParam{EndDay}
);
my $StartTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $GetParam{StartTime},
},
);
my $EndTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $GetParam{EndTime},
},
);
# Prevent storing end time before start time.
if ( $EndTimeObject < $StartTimeObject ) {
$EndTimeObject = $StartTimeObject->Clone();
}
# Make end time inclusive, add whole day.
$EndTimeObject->Add(
Days => 1,
);
$GetParam{EndTime} = $EndTimeObject->ToString();
}
elsif ( $GetParam{Recurring} && $GetParam{UpdateType} && $GetParam{UpdateDelta} ) {
my $StartTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $Appointment{StartTime},
},
);
my $EndTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $Appointment{EndTime},
},
);
# Calculate new start/end times.
if ( $GetParam{UpdateType} eq 'StartTime' ) {
$StartTimeObject->Add(
Seconds => $GetParam{UpdateDelta},
);
$GetParam{StartTime} = $StartTimeObject->ToString();
}
elsif ( $GetParam{UpdateType} eq 'EndTime' ) {
$EndTimeObject->Add(
Seconds => $GetParam{UpdateDelta},
);
$GetParam{EndTime} = $EndTimeObject->ToString();
}
else {
$StartTimeObject->Add(
Seconds => $GetParam{UpdateDelta},
);
$EndTimeObject->Add(
Seconds => $GetParam{UpdateDelta},
);
$GetParam{StartTime} = $StartTimeObject->ToString();
$GetParam{EndTime} = $EndTimeObject->ToString();
}
}
else {
if (
defined $GetParam{StartYear}
&& defined $GetParam{StartMonth}
&& defined $GetParam{StartDay}
&& defined $GetParam{StartHour}
&& defined $GetParam{StartMinute}
)
{
$GetParam{StartTime} = sprintf(
"%04d-%02d-%02d %02d:%02d:00",
$GetParam{StartYear}, $GetParam{StartMonth}, $GetParam{StartDay},
$GetParam{StartHour}, $GetParam{StartMinute}
);
# Convert start time to local time.
my $StartTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $GetParam{StartTime},
TimeZone => $Self->{UserTimeZone},
},
);
if ( $Self->{UserTimeZone} ) {
$StartTimeObject->ToOTRSTimeZone();
}
$GetParam{StartTime} = $StartTimeObject->ToString();
}
else {
$GetParam{StartTime} = $Appointment{StartTime};
}
if (
defined $GetParam{EndYear}
&& defined $GetParam{EndMonth}
&& defined $GetParam{EndDay}
&& defined $GetParam{EndHour}
&& defined $GetParam{EndMinute}
)
{
$GetParam{EndTime} = sprintf(
"%04d-%02d-%02d %02d:%02d:00",
$GetParam{EndYear}, $GetParam{EndMonth}, $GetParam{EndDay},
$GetParam{EndHour}, $GetParam{EndMinute}
);
# Convert end time to local time.
my $EndTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $GetParam{EndTime},
TimeZone => $Self->{UserTimeZone},
},
);
if ( $Self->{UserTimeZone} ) {
$EndTimeObject->ToOTRSTimeZone();
}
# Get already calculated local start time.
my $StartTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $GetParam{StartTime},
},
);
# Prevent storing end time before start time.
if ( $EndTimeObject < $StartTimeObject ) {
$EndTimeObject = $StartTimeObject->Clone();
}
$GetParam{EndTime} = $EndTimeObject->ToString();
}
else {
$GetParam{EndTime} = $Appointment{EndTime};
}
}
# Prevent recurrence until dates before start time.
if ( $Appointment{Recurring} && $Appointment{RecurrenceUntil} ) {
my $StartTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $GetParam{StartTime},
},
);
my $RecurrenceUntilObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $Appointment{RecurrenceUntil},
},
);
if ( $RecurrenceUntilObject < $StartTimeObject ) {
$Appointment{RecurrenceUntil} = $GetParam{StartTime};
}
}
# recurring appointment
if ( $GetParam{Recurring} && $GetParam{RecurrenceType} ) {
if (
$GetParam{RecurrenceType} eq 'Daily'
|| $GetParam{RecurrenceType} eq 'Weekly'
|| $GetParam{RecurrenceType} eq 'Monthly'
|| $GetParam{RecurrenceType} eq 'Yearly'
)
{
$GetParam{RecurrenceInterval} = 1;
}
elsif ( $GetParam{RecurrenceType} eq 'Custom' ) {
if ( $GetParam{RecurrenceCustomType} eq 'CustomWeekly' ) {
if ( $GetParam{Days} ) {
my @Days = split( ",", $GetParam{Days} );
$GetParam{RecurrenceFrequency} = \@Days;
}
else {
my $StartTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $GetParam{StartTime},
},
);
my $StartTimeSettings = $StartTimeObject->Get();
$GetParam{RecurrenceFrequency} = [ $StartTimeSettings->{DayOfWeek} ];
}
}
elsif ( $GetParam{RecurrenceCustomType} eq 'CustomMonthly' ) {
if ( $GetParam{MonthDays} ) {
my @MonthDays = split( ",", $GetParam{MonthDays} );
$GetParam{RecurrenceFrequency} = \@MonthDays;
}
else {
my $StartTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $GetParam{StartTime},
},
);
my $StartTimeSettings = $StartTimeObject->Get();
$GetParam{RecurrenceFrequency} = [ $StartTimeSettings->{Day} ];
}
}
elsif ( $GetParam{RecurrenceCustomType} eq 'CustomYearly' ) {
if ( $GetParam{Months} ) {
my @Months = split( ",", $GetParam{Months} );
$GetParam{RecurrenceFrequency} = \@Months;
}
else {
my $StartTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $GetParam{StartTime},
},
);
my $StartTimeSettings = $StartTimeObject->Get();
$GetParam{RecurrenceFrequency} = [ $StartTimeSettings->{Month} ];
}
}
$GetParam{RecurrenceType} = $GetParam{RecurrenceCustomType};
}
# until ...
if (
$GetParam{RecurrenceLimit} eq '1'
&& $GetParam{RecurrenceUntilYear}
&& $GetParam{RecurrenceUntilMonth}
&& $GetParam{RecurrenceUntilDay}
)
{
$GetParam{RecurrenceUntil} = sprintf(
"%04d-%02d-%02d 00:00:00",
$GetParam{RecurrenceUntilYear}, $GetParam{RecurrenceUntilMonth},
$GetParam{RecurrenceUntilDay}
);
# Prevent recurrence until dates before start time.
my $StartTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $GetParam{StartTime},
},
);
my $RecurrenceUntilObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $GetParam{RecurrenceUntil},
},
);
if ( $RecurrenceUntilObject < $StartTimeObject ) {
$GetParam{RecurrenceUntil} = $GetParam{StartTime};
}
$GetParam{RecurrenceCount} = undef;
}
# for ... time(s)
elsif ( $GetParam{RecurrenceLimit} eq '2' ) {
$GetParam{RecurrenceUntil} = undef;
}
}
# Determine notification custom type, if supplied.
if ( defined $GetParam{NotificationTemplate} ) {
if ( $GetParam{NotificationTemplate} ne 'Custom' ) {
$GetParam{NotificationCustom} = '';
}
elsif ( $GetParam{NotificationCustomRelativeInput} ) {
$GetParam{NotificationCustom} = 'relative';
}
elsif ( $GetParam{NotificationCustomDateTimeInput} ) {
$GetParam{NotificationCustom} = 'datetime';
$GetParam{NotificationCustomDateTime} = sprintf(
"%04d-%02d-%02d %02d:%02d:00",
$GetParam{NotificationCustomDateTimeYear},
$GetParam{NotificationCustomDateTimeMonth},
$GetParam{NotificationCustomDateTimeDay},
$GetParam{NotificationCustomDateTimeHour},
$GetParam{NotificationCustomDateTimeMinute}
);
my $NotificationCustomDateTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $GetParam{NotificationCustomDateTime},
TimeZone => $Self->{UserTimeZone},
},
);
if ( $Self->{UserTimeZone} ) {
$NotificationCustomDateTimeObject->ToOTRSTimeZone();
}
$GetParam{NotificationCustomDateTime} = $NotificationCustomDateTimeObject->ToString();
}
}
# team
if ( $GetParam{'TeamID[]'} ) {
my @TeamIDs = $ParamObject->GetArray( Param => 'TeamID[]' );
$GetParam{TeamID} = \@TeamIDs;
}
else {
$GetParam{TeamID} = undef;
}
# resources
if ( $GetParam{'ResourceID[]'} ) {
my @ResourceID = $ParamObject->GetArray( Param => 'ResourceID[]' );
$GetParam{ResourceID} = \@ResourceID;
}
else {
$GetParam{ResourceID} = undef;
}
# Check if dealing with ticket appointment.
if ( $Appointment{TicketAppointmentRuleID} ) {
# Make sure readonly values stay unchanged.
$GetParam{Title} = $Appointment{Title};
$GetParam{CalendarID} = $Appointment{CalendarID};
$GetParam{AllDay} = undef;
$GetParam{Recurring} = undef;
my $Rule = $CalendarObject->TicketAppointmentRuleGet(
CalendarID => $Appointment{CalendarID},
RuleID => $Appointment{TicketAppointmentRuleID},
);
# Recalculate end time based on time preset.
if ( IsHashRefWithData($Rule) ) {
if ( $Rule->{EndDate} =~ /^Plus_([0-9]+)$/ && $GetParam{StartTime} ) {
my $Preset = int $1;
my $EndTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $GetParam{StartTime}, # base on start time
},
);
# Calculate end time using preset value.
$EndTimeObject->Add(
Minutes => $Preset,
);
$GetParam{EndTime} = $EndTimeObject->ToString();
}
}
}
my $Success;
# reset empty parameters
for my $Param ( sort keys %GetParam ) {
if ( !$GetParam{$Param} ) {
$GetParam{$Param} = undef;
}
}
# pass current user ID
$GetParam{UserID} = $Self->{UserID};
# Get passed plugin parameters.
my @PluginParams = grep { $_ =~ /^Plugin_/ } keys %GetParam;
if (%Appointment) {
# Continue only if coming from edit screen
# (there is at least one passed plugin parameter).
if (@PluginParams) {
# Get all related appointments before the update.
my @RelatedAppointments = ( $Appointment{AppointmentID} );
my @CalendarAppointments = $AppointmentObject->AppointmentList(
CalendarID => $Appointment{CalendarID},
);
# If we are dealing with a parent, include any child appointments.
push @RelatedAppointments,
map {
$_->{AppointmentID}
}
grep {
defined $_->{ParentID}
&& $_->{ParentID} eq $Appointment{AppointmentID}
} @CalendarAppointments;
# Remove all existing links.
for my $CurrentAppointmentID (@RelatedAppointments) {
my $Success = $PluginObject->PluginLinkDelete(
AppointmentID => $CurrentAppointmentID,
UserID => $Self->{UserID},
);
if ( !$Success ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Links could not be deleted for appointment $CurrentAppointmentID!",
);
}
}
}
$Success = $AppointmentObject->AppointmentUpdate(
%Appointment,
%GetParam,
);
}
else {
$Success = $AppointmentObject->AppointmentCreate(
%GetParam,
);
}
my $AppointmentID = $GetParam{AppointmentID} ? $GetParam{AppointmentID} : $Success;
if ($AppointmentID) {
# Continue only if coming from edit screen
# (there is at least one passed plugin parameter).
if (@PluginParams) {
# Get fresh appointment data.
%Appointment = $AppointmentObject->AppointmentGet(
AppointmentID => $AppointmentID,
);
# Process all related appointments.
my @RelatedAppointments = ($AppointmentID);
my @CalendarAppointments = $AppointmentObject->AppointmentList(
CalendarID => $Appointment{CalendarID},
);
# If we are dealing with a parent, include any child appointments as well.
push @RelatedAppointments,
map {
$_->{AppointmentID}
}
grep {
defined $_->{ParentID}
&& $_->{ParentID} eq $AppointmentID
} @CalendarAppointments;
# Process passed plugin parameters.
for my $PluginParam (@PluginParams) {
my $PluginData = $Kernel::OM->Get('Kernel::System::JSON')->Decode(
Data => $GetParam{$PluginParam},
);
my $PluginKey = $PluginParam;
$PluginKey =~ s/^Plugin_//;
# Execute link add method of the plugin.
if ( IsArrayRefWithData($PluginData) ) {
for my $LinkID ( @{$PluginData} ) {
for my $CurrentAppointmentID (@RelatedAppointments) {
my $Link = $PluginObject->PluginLinkAdd(
AppointmentID => $CurrentAppointmentID,
PluginKey => $PluginKey,
PluginData => $LinkID,
UserID => $Self->{UserID},
);
if ( !$Link ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Link could not be created for appointment $CurrentAppointmentID!",
);
}
}
}
}
}
}
}
# build JSON output
$JSON = $LayoutObject->JSONEncode(
Data => {
Success => $Success ? 1 : 0,
AppointmentID => $AppointmentID,
},
);
}
# ------------------------------------------------------------ #
# delete mask
# ------------------------------------------------------------ #
elsif ( $Self->{Subaction} eq 'DeleteAppointment' ) {
if ( $GetParam{AppointmentID} ) {
my %Appointment = $AppointmentObject->AppointmentGet(
AppointmentID => $GetParam{AppointmentID},
);
my $Success = 0;
my $Error = '';
# Prevent deleting ticket appointment.
if ( $Appointment{TicketAppointmentRuleID} ) {
$Error = Translatable('Cannot delete ticket appointment!');
}
else {
# Get all related appointments before the deletion.
my @RelatedAppointments = ( $Appointment{AppointmentID} );
my @CalendarAppointments = $AppointmentObject->AppointmentList(
CalendarID => $Appointment{CalendarID},
);
# If we are dealing with a parent, include any child appointments.
push @RelatedAppointments,
map {
$_->{AppointmentID}
}
grep {
defined $_->{ParentID}
&& $_->{ParentID} eq $Appointment{AppointmentID}
} @CalendarAppointments;
# Remove all existing links.
for my $CurrentAppointmentID (@RelatedAppointments) {
my $Success = $PluginObject->PluginLinkDelete(
AppointmentID => $CurrentAppointmentID,
UserID => $Self->{UserID},
);
if ( !$Success ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Links could not be deleted for appointment $CurrentAppointmentID!",
);
}
}
$Success = $AppointmentObject->AppointmentDelete(
%GetParam,
UserID => $Self->{UserID},
);
if ( !$Success ) {
$Error = Translatable('No permissions!');
}
}
# build JSON output
$JSON = $LayoutObject->JSONEncode(
Data => {
Success => $Success,
Error => $Error,
AppointmentID => $GetParam{AppointmentID},
},
);
}
}
# ------------------------------------------------------------ #
# update preferences
# ------------------------------------------------------------ #
elsif ( $Self->{Subaction} eq 'UpdatePreferences' ) {
my $Success = 0;
if (
$GetParam{OverviewScreen} && (
$GetParam{DefaultView} || $GetParam{CalendarSelection}
|| ( $GetParam{ShownResources} && $GetParam{TeamID} )
|| $GetParam{ShownAppointments}
)
)
{
my $PreferenceKey;
my $PreferenceKeySuffix = '';
if ( $GetParam{DefaultView} ) {
$PreferenceKey = 'DefaultView';
}
elsif ( $GetParam{CalendarSelection} ) {
$PreferenceKey = 'CalendarSelection';
}
elsif ( $GetParam{ShownResources} && $GetParam{TeamID} ) {
$PreferenceKey = 'ShownResources';
$PreferenceKeySuffix = "-$GetParam{TeamID}";
}
elsif ( $GetParam{ShownAppointments} ) {
$PreferenceKey = 'ShownAppointments';
}
# set user preferences
$Success = $Kernel::OM->Get('Kernel::System::User')->SetPreferences(
Key => 'User' . $GetParam{OverviewScreen} . $PreferenceKey . $PreferenceKeySuffix,
Value => $GetParam{$PreferenceKey},
UserID => $Self->{UserID},
);
}
elsif ( $GetParam{OverviewScreen} && $GetParam{RestoreDefaultSettings} ) {
my $PreferenceKey;
my $PreferenceKeySuffix = '';
if ( $GetParam{RestoreDefaultSettings} eq 'ShownResources' && $GetParam{TeamID} ) {
$PreferenceKey = 'ShownResources';
$PreferenceKeySuffix = "-$GetParam{TeamID}";
}
# blank user preferences
$Success = $Kernel::OM->Get('Kernel::System::User')->SetPreferences(
Key => 'User' . $GetParam{OverviewScreen} . $PreferenceKey . $PreferenceKeySuffix,
Value => '',
UserID => $Self->{UserID},
);
}
# build JSON output
$JSON = $LayoutObject->JSONEncode(
Data => {
Success => $Success,
},
);
}
# ------------------------------------------------------------ #
# team list selection update
# ------------------------------------------------------------ #
elsif ( $Self->{Subaction} eq 'TeamUserList' ) {
my @TeamIDs = $ParamObject->GetArray( Param => 'TeamID[]' );
my %TeamUserListAll;
# Check if team object is registered.
if ( $Kernel::OM->Get('Kernel::System::Main')->Require( 'Kernel::System::Calendar::Team', Silent => 1 ) ) {
my $TeamObject = $Kernel::OM->Get('Kernel::System::Calendar::Team');
my $UserObject = $Kernel::OM->Get('Kernel::System::User');
TEAMID:
for my $TeamID (@TeamIDs) {
next TEAMID if !$TeamID;
# get list of team members
my %TeamUserList = $TeamObject->TeamUserList(
TeamID => $TeamID,
UserID => $Self->{UserID},
);
# get user data
for my $UserID ( sort keys %TeamUserList ) {
my %User = $UserObject->GetUserData(
UserID => $UserID,
);
$TeamUserList{$UserID} = $User{UserFullname};
}
%TeamUserListAll = ( %TeamUserListAll, %TeamUserList );
}
}
# build JSON output
$JSON = $LayoutObject->JSONEncode(
Data => {
TeamUserList => \%TeamUserListAll,
},
);
}
# send JSON response
return $LayoutObject->Attachment(
ContentType => 'application/json; charset=' . $LayoutObject->{Charset},
Content => $JSON,
Type => 'inline',
NoCache => 1,
);
}
sub _DayOffsetGet {
my ( $Self, %Param ) = @_;
# check needed stuff
for my $Needed (qw(Time)) {
if ( !$Param{$Needed} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $Needed!",
);
return;
}
}
# Get original date components.
my $OriginalTimeObject = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
String => $Param{Time},
},
);
my $OriginalTimeSettings = $OriginalTimeObject->Get();
# Get destination time according to user timezone.
my $DestinationTimeObject = $OriginalTimeObject->Clone();
$DestinationTimeObject->ToTimeZone( TimeZone => $Self->{UserTimeZone} );
my $DestinationTimeSettings = $DestinationTimeObject->Get();
# Compare days of two times.
if ( $OriginalTimeSettings->{Day} == $DestinationTimeSettings->{Day} ) {
return 0; # same day
}
elsif ( $OriginalTimeObject > $DestinationTimeObject ) {
return -1;
}
return 1;
}
1;