Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision dbba5f4d

Von Bernd Bleßmann vor mehr als 3 Jahren hinzugefügt

  • ID dbba5f4d2510c7ad18a3637bdabdc2d62dcc5aaa
  • Vorgänger 5b3c65a4
  • Nachfolger 9deaed00

Zeiterfassung: Datum/Dauer statt Start/Ende wählbar (Benutzereinstellung)

Unterschiede anzeigen:

SL/AM.pm
54 54
use SL::GenericTranslations;
55 55
use SL::Helper::UserPreferences::PositionsScrollbar;
56 56
use SL::Helper::UserPreferences::PartPickerSearch;
57
use SL::Helper::UserPreferences::TimeRecording;
57 58
use SL::Helper::UserPreferences::UpdatePositions;
58 59

  
59 60
use strict;
......
546 547
  SL::Helper::UserPreferences::UpdatePositions->new()->get_show_update_button();
547 548
}
548 549

  
550
sub time_recording_use_duration {
551
  SL::Helper::UserPreferences::TimeRecording->new()->get_use_duration();
552
}
553

  
549 554
sub save_preferences {
550 555
  $main::lxdebug->enter_sub();
551 556

  
......
583 588
  if (exists $form->{positions_show_update_button}) {
584 589
    SL::Helper::UserPreferences::UpdatePositions->new()->store_show_update_button($form->{positions_show_update_button})
585 590
  }
591
  if (exists $form->{time_recording_use_duration}) {
592
    SL::Helper::UserPreferences::TimeRecording->new()->store_use_duration($form->{time_recording_use_duration})
593
  }
586 594

  
587 595
  $main::lxdebug->leave_sub();
588 596

  
SL/Controller/TimeRecording.pm
14 14
use SL::DB::Part;
15 15
use SL::DB::TimeRecording;
16 16
use SL::DB::TimeRecordingArticle;
17
use SL::Helper::Flash qw(flash);
18
use SL::Helper::UserPreferences::TimeRecording;
17 19
use SL::Locale::String qw(t8);
18 20
use SL::ReportGenerator;
19 21

  
20 22
use Rose::Object::MakeMethods::Generic
21 23
(
22 24
# scalar                  => [ qw() ],
23
 'scalar --get_set_init' => [ qw(time_recording models all_employees all_time_recording_articles can_view_all can_edit_all) ],
25
 'scalar --get_set_init' => [ qw(time_recording models all_employees all_time_recording_articles can_view_all can_edit_all use_duration) ],
24 26
);
25 27

  
26 28

  
......
65 67

  
66 68
  $::request->{layout}->use_javascript("${_}.js") for qw(kivi.TimeRecording ckeditor/ckeditor ckeditor/adapters/jquery kivi.Validator);
67 69

  
70
  if ($self->use_duration) {
71
    flash('warning', t8('This entry is using start and end time. This information will be overwritten on saving.')) if !$self->time_recording->is_duration_used;
72
  } else {
73
    flash('warning', t8('This entry is using date and duration. This information will be overwritten on saving.'))  if $self->time_recording->is_duration_used;
74
  }
75

  
68 76
  if ($self->time_recording->start_time) {
69 77
    $self->{start_date} = $self->time_recording->start_time->to_kivitendo;
70 78
    $self->{start_time} = $self->time_recording->start_time->to_kivitendo_time;
......
84 92
sub action_save {
85 93
  my ($self) = @_;
86 94

  
95
  if ($self->use_duration) {
96
    $self->time_recording->start_date(undef);
97
    $self->time_recording->end_date(undef);
98
  }
99

  
87 100
  my @errors = $self->time_recording->validate;
88 101
  if (@errors) {
89 102
    $::form->error(t8('Saving the time recording entry failed: #1', join '<br>', @errors));
......
107 120
}
108 121

  
109 122
sub init_time_recording {
123
  my ($self) = @_;
124

  
110 125
  my $is_new         = !$::form->{id};
111
  my $time_recording = $is_new ? SL::DB::TimeRecording->new(start_time => DateTime->now_local)
112
                               : SL::DB::TimeRecording->new(id => $::form->{id})->load;
126
  my $time_recording = !$is_new            ? SL::DB::TimeRecording->new(id => $::form->{id})->load
127
                     : $self->use_duration ? SL::DB::TimeRecording->new(date => DateTime->today_local)
128
                     :                       SL::DB::TimeRecording->new(start_time => DateTime->now_local);
113 129

  
114 130
  my %attributes = %{ $::form->{time_recording} || {} };
115 131

  
116
  foreach my $type (qw(start end)) {
117
    if ($::form->{$type . '_date'}) {
118
      my $date = DateTime->from_kivitendo($::form->{$type . '_date'});
119
      $attributes{$type . '_time'} = $date->clone;
120
      if ($::form->{$type . '_time'}) {
121
        my ($hour, $min) = split ':', $::form->{$type . '_time'};
122
        $attributes{$type . '_time'}->set_hour($hour)  if $hour;
123
        $attributes{$type . '_time'}->set_minute($min) if $min;
132
  if (!$self->use_duration) {
133
    foreach my $type (qw(start end)) {
134
      if ($::form->{$type . '_date'}) {
135
        my $date = DateTime->from_kivitendo($::form->{$type . '_date'});
136
        $attributes{$type . '_time'} = $date->clone;
137
        if ($::form->{$type . '_time'}) {
138
          my ($hour, $min) = split ':', $::form->{$type . '_time'};
139
          $attributes{$type . '_time'}->set_hour($hour)  if $hour;
140
          $attributes{$type . '_time'}->set_minute($min) if $min;
141
        }
124 142
      }
125 143
    }
126 144
  }
127 145

  
128
  # do not overwright staff member if you do not have the right
146
  # do not overwrite staff member if you do not have the right
129 147
  delete $attributes{staff_member_id} if !$_[0]->can_edit_all;
130 148
  $attributes{staff_member_id} = SL::DB::Manager::Employee->current->id if $is_new;
131 149

  
......
178 196
  return $res;
179 197
}
180 198

  
199
sub init_use_duration {
200
  return SL::Helper::UserPreferences::TimeRecording->new()->get_use_duration();
201
}
202

  
181 203
sub check_auth {
182 204
  $::auth->assert('time_recording');
183 205
}
......
255 277
  my $staff_member = $filter->{staff_member_id} ? SL::DB::Employee->new(id => $filter->{staff_member_id})->load->safe_name : '';
256 278

  
257 279
  my @filters = (
258
    [ $filter->{"start_time:date::ge"},                        t8('From Start')      ],
259
    [ $filter->{"start_time:date::le"},                        t8('To Start')        ],
280
    [ $filter->{"date:date::ge"},                              t8('From Date')      ],
281
    [ $filter->{"date:date::le"},                              t8('To Date')        ],
260 282
    [ $filter->{"customer"}->{"name:substr::ilike"},           t8('Customer')        ],
261 283
    [ $filter->{"customer"}->{"customernumber:substr::ilike"}, t8('Customer Number') ],
262 284
    [ $staff_member,                                           t8('Mitarbeiter')     ],
SL/DB/TimeRecording.pm
33 33

  
34 34
  my @errors;
35 35

  
36
  push @errors, t8('Start time must not be empty.')                            if !$self->start_time;
37 36
  push @errors, t8('Customer must not be empty.')                              if !$self->customer_id;
38 37
  push @errors, t8('Staff member must not be empty.')                          if !$self->staff_member_id;
39 38
  push @errors, t8('Employee must not be empty.')                              if !$self->employee_id;
......
109 108
  return;
110 109
}
111 110

  
111
sub is_duration_used {
112
  return !$_[0]->start_time;
113
}
114

  
112 115
sub displayable_times {
113 116
  my ($self) = @_;
114 117

  
SL/Helper/UserPreferences/TimeRecording.pm
1
package SL::Helper::UserPreferences::TimeRecording;
2

  
3
use strict;
4
use parent qw(Rose::Object);
5

  
6
use Carp;
7
use List::MoreUtils qw(none);
8

  
9
use SL::Helper::UserPreferences;
10

  
11
use Rose::Object::MakeMethods::Generic (
12
  'scalar --get_set_init' => [ qw(user_prefs) ],
13
);
14

  
15
sub get_use_duration {
16
  !!$_[0]->user_prefs->get('use_duration');
17
}
18

  
19
sub store_use_duration {
20
  $_[0]->user_prefs->store('use_duration', $_[1]);
21
}
22

  
23
sub init_user_prefs {
24
  SL::Helper::UserPreferences->new(
25
    namespace => $_[0]->namespace,
26
  )
27
}
28

  
29
# read only stuff
30
sub namespace     { 'TimeRecording' }
31
sub version       { 1 }
32

  
33
1;
34

  
35
__END__
36

  
37
=pod
38

  
39
=encoding utf-8
40

  
41
=head1 NAME
42

  
43
SL::Helper::UserPreferences::TimeRecording - preferences intended
44
to store user settings for using the time recording functionality.
45

  
46
=head1 SYNOPSIS
47

  
48
  use SL::Helper::UserPreferences::TimeRecording;
49
  my $prefs = SL::Helper::UserPreferences::TimeRecording->new();
50

  
51
  $prefs->store_use_duration(1);
52
  my $value = $prefs->get_use_duration;
53

  
54
=head1 DESCRIPTION
55

  
56
This module manages storing the user's choise for settings for
57
the time recording controller.
58
For now it can be choosen if an entry is done by entering start and
59
end time or a date and a duration.
60

  
61
=head1 BUGS
62

  
63
None yet :)
64

  
65
=head1 AUTHOR
66

  
67
Bernd Bleßmann E<lt>bernd@kivitendo-premium.deE<gt>
68

  
69
=cut
bin/mozilla/am.pl
664 664
  $form->{purchase_search_makemodel}        = AM->purchase_search_makemodel();
665 665
  $form->{sales_search_customer_partnumber} = AM->sales_search_customer_partnumber();
666 666
  $form->{positions_show_update_button}     = AM->positions_show_update_button();
667
  $form->{time_recording_use_duration}      = AM->time_recording_use_duration();
667 668

  
668 669
  $myconfig{show_form_details} = 1 unless (defined($myconfig{show_form_details}));
669 670
  $form->{CAN_CHANGE_PASSWORD} = $main::auth->can_change_password();
locale/de/all
1530 1530
  'Fristsetzung'                => 'Fristsetzung',
1531 1531
  'From'                        => 'Von',
1532 1532
  'From Date'                   => 'Von',
1533
  'From Start'                  => 'Ab Start',
1534 1533
  'From bin'                    => 'Ausgelagert',
1535 1534
  'From shop "#1" :  #2 '       => 'Shop #1 : #2',
1536 1535
  'From shop #1 :  #2 shoporders have been fetched.' => 'Es wurden #2 Bestellungen von #1 geholt.',
......
3105 3104
  'Start the correction assistant' => 'Korrekturassistenten starten',
3106 3105
  'Start time'                  => 'Startzeit',
3107 3106
  'Start time must be earlier than end time.' => 'Startzeit muss vor der Endzeit liegen.',
3108
  'Start time must not be empty.' => 'Startzeit darf nicht leer sein.',
3109 3107
  'Startdate method'            => 'Methode zur Ermittlung des Startdatums',
3110 3108
  'Startdate_coa'               => 'Gültig ab',
3111 3109
  'Starting Balance'            => 'Eröffnungsbilanzwerte',
......
3661 3659
  'This discount is only valid in purchase documents' => 'Dieser Rabatt ist nur in Einkaufsdokumenten gültig',
3662 3660
  'This discount is only valid in records with customer or vendor' => 'Dieser Rabatt ist nur in Dokumenten mit Kunde oder Lieferant gültig',
3663 3661
  'This discount is only valid in sales documents' => 'Dieser Rabatt ist nur in Verkaufsdokumenten gültig',
3662
  'This entry is using date and duration. This information will be overwritten on saving.' => 'Dieser Eintrag verwendet Datum und Dauer. Diese Information wird beim Speichern überschrieben.',
3663
  'This entry is using start and end time. This information will be overwritten on saving.' => 'Dieser Eintrag verwendet Start- und End-Zeit. Diese Information wird beim Speichern überschrieben.',
3664 3664
  'This export will include all records in the given time range and all supplicant information from checked entities. You will receive a single zip file. Please extract this file onto the data medium requested by your auditor.' => 'Dieser Export umfasst alle Belege im gewählten Zeitrahmen und die dazugehörgen Informationen aus den gewählten Blöcken. Sie erhalten eine einzelne Zip-Datei. Bitte entpacken Sie diese auf das Medium das Ihr Steuerprüfer wünscht.',
3665 3665
  'This feature especially prevents mistakes by mixing up prior tax and sales tax.' => 'Dieses Feature vermeidet insbesondere Verwechslungen von Umsatz- und Vorsteuer.',
3666 3666
  'This field must not be empty.' => 'Dieses Feld darf nicht leer sein.',
......
3737 3737
  'To (email)'                  => 'An',
3738 3738
  'To (time)'                   => 'Bis',
3739 3739
  'To Date'                     => 'Bis',
3740
  'To Start'                    => 'Bis Start',
3741 3740
  'To continue please change the taxkey 0 to another value.' => 'Um fortzufahren, ändern Sie bitte den Steuerschlüssel 0 auf einen anderen Wert.',
3742 3741
  'To import'                   => 'Zu importieren',
3743 3742
  'To upload images: Please create shoppart first' => 'Um Bilder hochzuladen bitte Shopartikel zuerst anlegen',
......
3910 3909
  'Use a text field to enter (new) contact titles if enabled. Otherwise, only a drop down box is offered.' => 'Textfeld zusätzlich zur Eingabe (neuer) Titel von Ansprechpersonen verwenden. Sonst wird nur eine Auswahlliste angezeigt.',
3911 3910
  'Use a text field to enter (new) greetings if enabled. Otherwise, only a drop down box is offered.' => 'Textfeld zusätzlich zur Eingabe (neuer) Anreden verwenden. Sonst wird nur eine Auswahlliste angezeigt.',
3912 3911
  'Use as new'                  => 'Als neu verwenden',
3912
  'Use date and duration for time recordings' => 'Datum und Dauer für Zeiterfassung verwenden',
3913 3913
  'Use default booking group because setting is \'all\'' => 'Standardbuchungsgruppe wird verwendet',
3914 3914
  'Use default booking group because wanted is missing' => 'Fehlende Buchungsgruppe, deshalb Standardbuchungsgruppe',
3915 3915
  'Use default warehouse for assembly transfer' => 'Zum Fertigen Standardlager des Bestandteils verwenden',
......
4232 4232
  'http'                        => 'http',
4233 4233
  'https'                       => 'https',
4234 4234
  'imported'                    => 'Importiert',
4235
  'in minutes'                  => 'in Minuten',
4235 4236
  'inactive'                    => 'inaktiv',
4236 4237
  'income'                      => 'Einnahmen-Überschuß-Rechnung',
4237 4238
  'internal error (see details)' => 'Interner Fehler (siehe Details)!',
locale/en/all
1530 1530
  'Fristsetzung'                => '',
1531 1531
  'From'                        => '',
1532 1532
  'From Date'                   => '',
1533
  'From Start'                  => '',
1534 1533
  'From bin'                    => '',
1535 1534
  'From shop "#1" :  #2 '       => '',
1536 1535
  'From shop #1 :  #2 shoporders have been fetched.' => '',
......
3105 3104
  'Start the correction assistant' => '',
3106 3105
  'Start time'                  => '',
3107 3106
  'Start time must be earlier than end time.' => '',
3108
  'Start time must not be empty.' => '',
3109 3107
  'Startdate method'            => '',
3110 3108
  'Startdate_coa'               => '',
3111 3109
  'Starting Balance'            => '',
......
3660 3658
  'This discount is only valid in purchase documents' => '',
3661 3659
  'This discount is only valid in records with customer or vendor' => '',
3662 3660
  'This discount is only valid in sales documents' => '',
3661
  'This entry is using date and duration. This information will be overwritten on saving.' => '',
3662
  'This entry is using start and end time. This information will be overwritten on saving.' => '',
3663 3663
  'This export will include all records in the given time range and all supplicant information from checked entities. You will receive a single zip file. Please extract this file onto the data medium requested by your auditor.' => '',
3664 3664
  'This feature especially prevents mistakes by mixing up prior tax and sales tax.' => '',
3665 3665
  'This field must not be empty.' => '',
......
3736 3736
  'To (email)'                  => '',
3737 3737
  'To (time)'                   => '',
3738 3738
  'To Date'                     => '',
3739
  'To Start'                    => '',
3740 3739
  'To continue please change the taxkey 0 to another value.' => '',
3741 3740
  'To import'                   => '',
3742 3741
  'To upload images: Please create shoppart first' => '',
......
3909 3908
  'Use a text field to enter (new) contact titles if enabled. Otherwise, only a drop down box is offered.' => '',
3910 3909
  'Use a text field to enter (new) greetings if enabled. Otherwise, only a drop down box is offered.' => '',
3911 3910
  'Use as new'                  => '',
3911
  'Use date and duration for time recordings' => '',
3912 3912
  'Use default booking group because setting is \'all\'' => '',
3913 3913
  'Use default booking group because wanted is missing' => '',
3914 3914
  'Use default warehouse for assembly transfer' => '',
......
4230 4230
  'http'                        => '',
4231 4231
  'https'                       => '',
4232 4232
  'imported'                    => '',
4233
  'in minutes'                  => '',
4233 4234
  'inactive'                    => '',
4234 4235
  'income'                      => 'GUV and BWA',
4235 4236
  'internal error (see details)' => '',
templates/webpages/am/config.html
87 87
        </td>
88 88
      </tr>
89 89

  
90
     <tr>
91
      <th align="right">[% 'Use date and duration for time recordings' | $T8 %]</th>
92
      <td>
93
        [% L.yes_no_tag('time_recording_use_duration', time_recording_use_duration) %]
94
      </td>
95
     </tr>
96

  
90 97
    </table>
91 98
   </div>
92 99

  
templates/webpages/time_recording/form.html
15 15
  <table>
16 16
    <thead class="listheading">
17 17
      <tr>
18
       [%- IF SELF.use_duration %]
19
        <th>[% 'Date'     | $T8 %]</th>
20
        <th>[% 'Duration' | $T8 %] ([% 'in minutes' | $T8 %])</th>
21
       [%- ELSE %]
18 22
        <th>[% 'Start' | $T8 %]</th>
19
        <th>[% 'End' | $T8 %]</th>
23
        <th>[% 'End'   | $T8 %]</th>
24
       [%- END %]
20 25
        <th>[% 'Customer' | $T8 %]</th>
21 26
        <th>[% 'Article' | $T8 %]</th>
22 27
        <th>[% 'Project' | $T8 %]</th>
......
26 31
    </thead>
27 32
    <tbody valign="top">
28 33
      <tr>
34
       [%- IF SELF.use_duration %]
35
        <td>
36
          [% P.date_tag('time_recording.date_as_date', SELF.time_recording.date_as_date, "data-validate"="required", "data-title"=LxERP.t8('Date')) %]<br>
37
        </td>
38
        <td>
39
          [% P.input_tag('time_recording.duration', SELF.time_recording.duration, size=15) %]
40
        </td>
41
       [%- ELSE %]
29 42
        <td>
30 43
          [% P.date_tag('start_date',  SELF.start_date, "data-validate"="required", "data-title"=LxERP.t8('Start date'), onchange='kivi.TimeRecording.set_end_date()') %]<br>
31 44
          [% P.input_tag('start_time', SELF.start_time, type="time", "data-validate"="required", "data-title"=LxERP.t8('Start time')) %]
......
36 49
          [% P.input_tag('end_time', SELF.end_time, type="time") %]
37 50
          [% P.button_tag('kivi.TimeRecording.set_current_date_time("end")', LxERP.t8('now')) %]
38 51
        </td>
52
       [%- END %]
39 53
        <td>[% P.customer_vendor.picker('time_recording.customer_id', SELF.time_recording.customer_id, type='customer', style='width: 300px', "data-validate"="required", "data-title"=LxERP.t8('Customer')) %]</td>
40 54
        <td>[% P.select_tag('time_recording.part_id', SELF.all_time_recording_articles, default=SELF.time_recording.part_id, with_empty=1, value_key='id', title_key='description') %]</td>
41 55
        <td>[% P.project.picker('time_recording.project_id', SELF.time_recording.project_id, style='width: 300px') %]</td>

Auch abrufbar als: Unified diff