Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 51fec310

Von Moritz Bunkus vor mehr als 10 Jahren hinzugefügt

  • ID 51fec3106e49e1ffc7d6a0a2c577bea8641efbff
  • Vorgänger 48aa4607
  • Nachfolger d90408d8

Pflichtenheftversionen anlegen und auflisten

Unterschiede anzeigen:

SL/Controller/RequirementSpec.pm
4 4

  
5 5
use parent qw(SL::Controller::Base);
6 6

  
7
use Rose::DB::Object::Helpers;
8

  
9 7
use SL::ClientJS;
10 8
use SL::Controller::Helper::GetModels;
11 9
use SL::Controller::Helper::Paginated;
......
52 50
  type          => t8('Requirement Spec Type'),
53 51
  status        => t8('Requirement Spec Status'),
54 52
  projectnumber => t8('Project Number'),
53
  version       => t8('Version'),
54
  mtime         => t8('Last modification'),
55 55
);
56 56

  
57 57
#
......
191 191
sub setup {
192 192
  my ($self) = @_;
193 193

  
194
  $::auth->assert('config');
194
  $::auth->assert('sales_quotation_edit');
195 195
  $::request->{layout}->use_stylesheet("${_}.css") for qw(jquery.contextMenu requirement_spec);
196 196
  $::request->{layout}->use_javascript("${_}.js") for qw(jquery.jstree jquery/jquery.contextMenu client_js requirement_spec);
197 197
  $self->is_template($::form->{is_template} ? 1 : 0);
......
267 267
    }
268 268
  })) {
269 269
    $::lxdebug->message(LXDebug::WARN(), "Error: " . $db->error);
270
    @errors = ($::locale->text('Saving failed. Erro message from the database: #1'), $db->error);
270
    @errors = ($::locale->text('Saving failed. Error message from the database: #1'), $db->error);
271 271
    return SL::ClientJS->new->error(@errors)->render($self) if $::request->is_ajax;
272 272

  
273 273
    $self->requirement_spec->id(undef) if $is_new;
......
300 300
  $args{where} = [
301 301
    and => [
302 302
      @{ $args{where} || [] },
303
      is_template => $self->is_template
303
      working_copy_id => undef,
304
      is_template     => $self->is_template
304 305
    ]];
305 306

  
306 307
  $self->db_args(\%args);
......
314 315
  my $report      = SL::ReportGenerator->new(\%::myconfig, $::form);
315 316
  $self->{report} = $report;
316 317

  
317
  my @columns     = qw(title customer status type projectnumber);
318
  my @sortable    = qw(title customer status type projectnumber);
318
  my @columns     = qw(title customer status type projectnumber mtime version);
319
  my @sortable    = qw(title customer status type projectnumber mtime);
319 320

  
320 321
  my %column_defs = (
321 322
    title         => { obj_link => sub { $self->url_for(action => 'show', id => $_[0]->id, callback => $callback) } },
......
325 326
                       sub      => sub { $_[0]->project_id ? $_[0]->project->projectnumber : '' } },
326 327
    status        => { sub      => sub { $_[0]->status->description } },
327 328
    type          => { sub      => sub { $_[0]->type->description } },
329
    version       => { sub      => sub { $_[0]->version_id ? $_[0]->version->version_number : t8('Working copy without version') } },
330
    mtime         => { sub      => sub { $_[0]->mtime->to_kivitendo(precision => 'minute') } },
328 331
  );
329 332

  
330 333
  map { $column_defs{$_}->{text} ||= $::locale->text( $self->get_sort_spec->{$_}->{title} ) } keys %column_defs;
SL/Controller/RequirementSpecItem.pm
25 25
  'scalar --get_set_init' => [ qw(complexities risks) ],
26 26
);
27 27

  
28
__PACKAGE__->run_before('check_auth');
28 29
__PACKAGE__->run_before('load_requirement_spec_item', only => [ qw(dragged_and_dropped ajax_update ajax_edit ajax_delete ajax_flag ajax_copy) ]);
29 30
__PACKAGE__->run_before('init_visible_section');
30 31

  
......
469 470
# filters
470 471
#
471 472

  
473
sub check_auth {
474
  my ($self) = @_;
475
  $::auth->assert('sales_quotation_edit');
476
}
477

  
472 478
sub load_requirement_spec {
473 479
  my ($self) = @_;
474 480
  $self->requirement_spec(SL::DB::RequirementSpec->new(id => $::form->{requirement_spec_id})->load || die "No such requirement spec");
SL/Controller/RequirementSpecVersion.pm
1
package SL::Controller::RequirementSpecVersion;
2

  
3
use strict;
4

  
5
use parent qw(SL::Controller::Base);
6

  
7
use Carp;
8
use List::MoreUtils qw(any);
9

  
10
use SL::ClientJS;
11
use SL::DB::Customer;
12
use SL::DB::Project;
13
use SL::DB::RequirementSpec;
14
use SL::DB::RequirementSpecVersion;
15
use SL::Helper::Flash;
16
use SL::Locale::String;
17

  
18
use Rose::Object::MakeMethods::Generic
19
(
20
  'scalar --get_set_init' => [ qw(requirement_spec version js versioned_copies) ],
21
);
22

  
23
__PACKAGE__->run_before('check_auth');
24

  
25
#
26
# actions
27
#
28

  
29
sub action_list {
30
  my ($self, %params) = @_;
31

  
32
  $self->render('requirement_spec_version/list', { layout => 0 });
33
}
34

  
35
sub action_new {
36
  my ($self) = @_;
37

  
38
  $self->version(SL::DB::RequirementSpecVersion->new);
39

  
40
  my $previous_version = $self->requirement_spec->previous_version;
41
  my %differences      = $self->calculate_differences(current => $self->requirement_spec, previous => $previous_version);
42

  
43
  if (!$previous_version) {
44
    $self->version->description(t8('Initial version.'));
45

  
46
  } else {
47
    my @lines;
48

  
49
    my $fb_diff = $differences{function_blocks};
50
    push @lines, t8('Added sections and function blocks: #1',   $::locale->language_join([ map { $_->fb_number         } @{ $fb_diff->{additions} } ])) if @{ $fb_diff->{additions} };
51
    push @lines, t8('Changed sections and function blocks: #1', $::locale->language_join([ map { $_->fb_number         } @{ $fb_diff->{changes}   } ])) if @{ $fb_diff->{changes}   };
52
    push @lines, t8('Removed sections and function blocks: #1', $::locale->language_join([ map { $_->fb_number         } @{ $fb_diff->{removals}  } ])) if @{ $fb_diff->{removals}  };
53

  
54
    my $tb_diff = $differences{text_blocks};
55
    push @lines, t8('Added text blocks: #1',                    $::locale->language_join([ map { '"' . $_->title . '"' } @{ $tb_diff->{additions} } ])) if @{ $tb_diff->{additions} };
56
    push @lines, t8('Changed text blocks: #1',                  $::locale->language_join([ map { '"' . $_->title . '"' } @{ $tb_diff->{changes}   } ])) if @{ $tb_diff->{changes}   };
57
    push @lines, t8('Removed text blocks: #1',                  $::locale->language_join([ map { '"' . $_->title . '"' } @{ $tb_diff->{removals}  } ])) if @{ $tb_diff->{removals}  };
58

  
59
    $self->version->description(@lines ? join("\n", @lines) : t8('No changes since previous version.'));
60
  }
61

  
62
  $self->render('requirement_spec_version/new', { layout => 0 }, title => t8('Create a new version'));
63
}
64

  
65
sub action_create {
66
  my ($self, %params) = @_;
67

  
68
  my %attributes = %{ delete($::form->{rs_version}) || {} };
69
  my @errors     = SL::DB::RequirementSpecVersion->new(%attributes, version_number => 1)->validate;
70

  
71
  return $self->js->error(@errors)->render($self) if @errors;
72

  
73
  my $db     = $self->requirement_spec->db;
74
  my @result = $self->version($self->requirement_spec->create_version(%attributes));
75

  
76
  if (!@result) {
77
    $::lxdebug->message(LXDebug::WARN(), "Error: " . $db->error);
78
    return $self->js->error($::locale->text('Saving failed. Error message from the database: #1'), $db->error)->render($self);
79
  }
80

  
81
  my $html = $self->render('requirement_spec/_version', { output => 0 }, requirement_spec => $self->requirement_spec);
82

  
83
  $self->js
84
    ->html('#requirement_spec_version', $html)
85
    ->jqmClose('.jqmWindow')
86
    ->render($self);
87
}
88

  
89
#
90
# filters
91
#
92

  
93
sub check_auth {
94
  my ($self, %params) = @_;
95
  $::auth->assert('sales_quotation_edit');
96
}
97

  
98
#
99
# helpers
100
#
101

  
102
sub init_requirement_spec {
103
  my ($self) = @_;
104
  $self->requirement_spec(SL::DB::RequirementSpec->new(id => $::form->{requirement_spec_id})->load) if $::form->{requirement_spec_id};
105
}
106

  
107
sub init_version {
108
  my ($self) = @_;
109
  $self->version(SL::DB::RequirementSpecVersion->new(id => $::form->{id})->load) if $::form->{id};
110
}
111

  
112
sub init_js {
113
  my ($self, %params) = @_;
114
  $self->js(SL::ClientJS->new);
115
}
116

  
117
sub init_versioned_copies {
118
  my ($self) = @_;
119
  $self->versioned_copies([
120
    sort { $b->mtime <=> $a->mtime } @{ $self->requirement_spec->versioned_copies }
121
  ]);
122
}
123

  
124
sub has_item_changed {
125
  my ($previous, $current) = @_;
126
  croak "Missing previous/current" if !$previous || !$current;
127
  return any { ($previous->$_ || '') ne ($current->$_ || '') } qw(item_type parent_id fb_number title description complexity_id risk_id time_estimation net_sum);
128
}
129

  
130
sub has_text_block_changed {
131
  my ($previous, $current) = @_;
132
  croak "Missing previous/current" if !$previous || !$current;
133
  return any { ($previous->$_ || '') ne ($current->$_ || '') } qw(title text);
134
}
135

  
136
sub compare_items {
137
  return -1 if ($a->item_type eq 'section') && ($b->item_type ne 'section');
138
  return +1 if ($a->item_type ne 'section') && ($b->item_type eq 'section');
139
  return $a->fb_number cmp $b->fb_number;
140
}
141

  
142
sub calculate_differences {
143
  my ($self, %params) = @_;
144

  
145
  my %differences = (
146
    function_blocks => {
147
      additions => [],
148
      changes   => [],
149
      removals  => [],
150
    },
151
    text_blocks => {
152
      additions => [],
153
      changes   => [],
154
      removals  => [],
155
    },
156
  );
157

  
158
  return %differences if !$params{previous} || !$params{current};
159

  
160
  my @previous_items                         = sort compare_items @{ $params{previous}->items };
161
  my @current_items                          = sort compare_items @{ $params{current}->items  };
162

  
163
  my @previous_text_blocks                   = sort { lc $a->title cmp lc $b->title } @{ $params{previous}->text_blocks };
164
  my @current_text_blocks                    = sort { lc $a->title cmp lc $b->title } @{ $params{current}->text_blocks  };
165

  
166
  my %previous_items_map                     = map { $_->fb_number => $_ } @previous_items;
167
  my %current_items_map                      = map { $_->fb_number => $_ } @current_items;
168

  
169
  my %previous_text_blocks_map               = map { $_->title     => $_ } @previous_text_blocks;
170
  my %current_text_blocks_map                = map { $_->title     => $_ } @current_text_blocks;
171

  
172
  $differences{function_blocks}->{additions} = [ grep { !$previous_items_map{ $_->fb_number }                                                                         } @current_items        ];
173
  $differences{function_blocks}->{removals}  = [ grep { !$current_items_map{  $_->fb_number }                                                                         } @previous_items       ];
174
  $differences{function_blocks}->{changes}   = [ grep {  $previous_items_map{ $_->fb_number }       && has_item_changed($previous_items_map{ $_->fb_number }, $_)     } @current_items        ];
175

  
176
  $differences{text_blocks}->{additions}     = [ grep { !$previous_text_blocks_map{ $_->title }                                                                       } @current_text_blocks  ];
177
  $differences{text_blocks}->{removals}      = [ grep { !$current_text_blocks_map{  $_->title }                                                                       } @previous_text_blocks ];
178
  $differences{text_blocks}->{changes}       = [ grep {  $previous_text_blocks_map{ $_->title } && has_text_block_changed($previous_text_blocks_map{ $_->title }, $_) } @current_text_blocks  ];
179

  
180
  return %differences;
181
}
182

  
183
1;
SL/DB/RequirementSpec.pm
10 10
use SL::Locale::String;
11 11

  
12 12
__PACKAGE__->meta->add_relationship(
13
  items          => {
14
    type         => 'one to many',
15
    class        => 'SL::DB::RequirementSpecItem',
16
    column_map   => { id => 'requirement_spec_id' },
13
  items            => {
14
    type           => 'one to many',
15
    class          => 'SL::DB::RequirementSpecItem',
16
    column_map     => { id => 'requirement_spec_id' },
17 17
  },
18
  text_blocks    => {
19
    type         => 'one to many',
20
    class        => 'SL::DB::RequirementSpecTextBlock',
21
    column_map   => { id => 'requirement_spec_id' },
18
  text_blocks      => {
19
    type           => 'one to many',
20
    class          => 'SL::DB::RequirementSpecTextBlock',
21
    column_map     => { id => 'requirement_spec_id' },
22
  },
23
  versioned_copies => {
24
    type           => 'one to many',
25
    class          => 'SL::DB::RequirementSpec',
26
    column_map     => { id => 'working_copy_id' },
22 27
  },
23 28
);
24 29

  
......
119 124
  return $copy;
120 125
}
121 126

  
127
sub previous_version {
128
  my ($self) = @_;
129

  
130
  my $and    = $self->version_id ? " AND (version_id <> ?)" : "";
131
  my $id     = $self->db->dbh->selectrow_array(<<SQL, undef, $self->id, ($self->version_id) x !!$self->version_id);
132
   SELECT MAX(id)
133
   FROM requirement_specs
134
   WHERE (working_copy_id = ?) $and
135
SQL
136

  
137
  return $id ? SL::DB::RequirementSpec->new(id => $id)->load : undef;
138
}
139

  
140
sub is_working_copy {
141
  my ($self) = @_;
142

  
143
  return !$self->working_copy_id;
144
}
145

  
146
sub next_version_number {
147
  my ($self) = @_;
148
  my $max_number = $self->db->dbh->selectrow_array(<<SQL, undef, $self->id);
149
    SELECT COALESCE(MAX(ver.version_number), 0)
150
    FROM requirement_spec_versions ver
151
    JOIN requirement_specs rs ON (rs.version_id = ver.id)
152
    WHERE rs.working_copy_id = ?
153
SQL
154

  
155
  return $max_number + 1;
156
}
157

  
158
sub create_version {
159
  my ($self, %attributes) = @_;
160

  
161
  my ($copy, $version);
162
  my $ok = $self->db->do_transaction(sub {
163
    delete $attributes{version_number};
164

  
165
    $version = SL::DB::RequirementSpecVersion->new(%attributes, version_number => $self->next_version_number)->save;
166
    $copy    = $self->create_copy;
167
    $copy->update_attributes(version_id => $version->id, working_copy_id => $self->id);
168
    $self->update_attributes(version_id => $version->id);
169

  
170
    1;
171
  });
172

  
173
  return $ok ? ($copy, $version) : ();
174
}
175

  
122 176
1;
js/locale/de.js
7 7
"Are you sure?":"Sind Sie sicher?",
8 8
"Copy":"Kopieren",
9 9
"Copy requirement spec":"Pflichtenheft kopieren",
10
"Create new version":"Neue Version anlegen",
10 11
"Database Connection Test":"Test der Datenbankverbindung",
11 12
"Delete":"Löschen",
12 13
"Delete requirement spec":"Pflichtenheft löschen",
js/requirement_spec.js
313 313
  return true;
314 314
}
315 315

  
316
function disable_requirement_spec_commands(key, opt) {
317
  if (key === "create_version")
318
    return ($('#current_version_id').val() || '') == '' ? false : true;
319
  return false;
320
}
321

  
322
// -------------------------------------------------------------------------
323
// -------------------------------- versions -------------------------------
324
// -------------------------------------------------------------------------
325

  
326
function create_requirement_spec_version() {
327
  open_jqm_window({ url:  'controller.pl',
328
                    data: { action:              'RequirementSpecVersion/new',
329
                            requirement_spec_id: $('#requirement_spec_id').val() },
330
                    id:   'new_requirement_spec_version_window' });
331
  return true;
332
}
333

  
316 334
// -------------------------------------------------------------------------
317 335
// ----------------------------- context menus -----------------------------
318 336
// -------------------------------------------------------------------------
319 337

  
320 338
function create_requirement_spec_context_menus() {
321
  var events = {
322
    show: requirement_spec_text_block_popup_menu_shown,
323
    hide: requirement_spec_text_block_popup_menu_hidden
324
  };
325

  
326 339
  var general_actions = {
327 340
      sep98:           "---------"
328 341
    , general_actions: { name: kivi.t8('Requirement spec actions:') }
329 342
    , sep99:           "---------"
343
    , create_version:  { name: kivi.t8('Create new version'),      icon: "new",    callback: create_requirement_spec_version, disabled: disable_requirement_spec_commands }
330 344
    , copy_reqspec:    { name: kivi.t8('Copy requirement spec'),   icon: "copy",   callback: copy_reqspec   }
331 345
    , delete_reqspec:  { name: kivi.t8('Delete requirement spec'), icon: "delete", callback: delete_reqspec }
332 346
  };
......
336 350
    items:    general_actions
337 351
  });
338 352

  
353
  var events = {
354
    show: requirement_spec_text_block_popup_menu_shown,
355
    hide: requirement_spec_text_block_popup_menu_hidden
356
  };
357

  
339 358
  $.contextMenu({
340 359
    selector: '.text-block-context-menu',
341 360
    events:   {
locale/de/all
179 179
  'Add sub function block'      => 'Unterfunktionsblock hinzufügen',
180 180
  'Add text block'              => 'Textblock erfassen',
181 181
  'Add unit'                    => 'Einheit hinzuf&uuml;gen',
182
  'Added sections and function blocks: #1' => 'Hinzugefügte Abschnitte und Funktionsblöcke: #1',
183
  'Added text blocks: #1'       => 'Hinzugefügte Textblöcke: #1',
182 184
  'Address'                     => 'Adresse',
183 185
  'Admin'                       => 'Administration',
184 186
  'Administration'              => 'Administration',
......
436 438
  'Cc E-mail'                   => 'CC (E-Mail)',
437 439
  'Change default bin for this parts' => 'Standardlagerplatz für diese Waren ändern',
438 440
  'Change kivitendo installation settings (most entries in the \'System\' menu)' => 'Verändern der kivitendo-Installationseinstellungen (die meisten Menüpunkte unterhalb von \'System\')',
441
  'Change representative to'    => 'Vertreter ändern in',
442
  'Changed sections and function blocks: #1' => 'Geänderte Abschnitte und Funktionsblöcke: #1',
443
  'Changed text blocks: #1'     => 'Geänderte Textblöcke: #1',
439 444
  'Changes in this block are only sensible if the account is NOT a summary account AND there exists one valid taxkey. To select both Receivables and Payables only make sense for Payment / Receipt (i.e. account cash).' => 'Es ist nur sinnvoll Änderungen vorzunehmen, wenn das Konto KEIN Sammelkonto ist und wenn ein gültiger Steuerschlüssel für das Konto existiert. Gleichzeitig Haken bei Forderungen und Verbindlichkeiten zu setzen, macht auch NUR für den Zahlungsein- und Ausgang (bspw. Bank oder Kasse) Sinn.',
440 445
  'Changes to Receivables and Payables are only possible if no transactions to this account are posted yet.' => 'Änderungen bei Forderungen oder Verbindlichkeiten sind nur möglich, wenn dieses Konto noch nicht bebucht wurde.',
441 446
  'Charge Number'               => 'Chargennummer',
......
549 554
  'Create a new section'        => 'Neuen Abschnitt erstellen',
550 555
  'Create a new user'           => 'Einen neuen Benutzer anlegen',
551 556
  'Create a new user group'     => 'Eine neue Benutzergruppe erfassen',
557
  'Create a new version'        => 'Eine neue Version anlegen',
558
  'Create a standard group'     => 'Eine Standard-Benutzergruppe anlegen',
552 559
  'Create and edit RFQs'        => 'Lieferantenanfragen erfassen und bearbeiten',
553 560
  'Create and edit dunnings'    => 'Mahnungen erfassen und bearbeiten',
554 561
  'Create and edit invoices and credit notes' => 'Rechnungen und Gutschriften erfassen und bearbeiten',
......
576 583
  'Create new payment term'     => 'Neue Zahlungsbedingung anlegen',
577 584
  'Create new project type'     => 'Neuen Projekttypen anlegen',
578 585
  'Create new templates from master templates' => 'Neue Druckvorlagen aus Vorlagensatz erstellen',
586
  'Create new version'          => 'Neue Version anlegen',
579 587
  'Create one from the context menu by right-clicking on this text.' => 'Erstellen Sie einen aus dem Kontextmenü, indem Sie auf diesen Text rechtsklicken.',
580 588
  'Create tables'               => 'Tabellen anlegen',
581 589
  'Created by'                  => 'Erstellt von',
......
1183 1191
  'Increase'                    => 'Erhöhen',
1184 1192
  'Individual Items'            => 'Einzelteile',
1185 1193
  'Information'                 => 'Information',
1194
  'Initial version.'            => 'Initiale Version.',
1186 1195
  'Insert'                      => 'Einfügen',
1187 1196
  'Insert with new customer/vendor number' => 'Mit neuer Kunden-/Lieferantennummer anlegen',
1188 1197
  'Insert with new database ID' => 'Neu anlegen mit neuer Datenbank-ID',
......
1190 1199
  'Interest'                    => 'Zinsen',
1191 1200
  'Interest Rate'               => 'Zinssatz',
1192 1201
  'Internal Notes'              => 'Interne Bemerkungen',
1202
  'Internal comment'            => 'Interne Bemerkungen',
1203
  'International'               => 'Ausland',
1193 1204
  'Internet'                    => 'Internet',
1194 1205
  'Introduction of clients'     => 'Einführung von Mandanten',
1195 1206
  'Inv. Duedate'                => 'Rg. Fälligkeit',
......
1282 1293
  'Last Transaction'            => 'Letzte Buchung',
1283 1294
  'Last Vendor Number'          => 'Letzte Lieferantennummer',
1284 1295
  'Last command output'         => 'Ausgabe des letzten Befehls',
1296
  'Last modification'           => 'Letzte Änderung',
1285 1297
  'Last opening balance or all transactions' => 'Letzte Eröffnungsbuchung oder alle Buchungen',
1286 1298
  'Last opening balance or start of year' => 'Letzte Eröffnungsbuchung oder Jahresanfang',
1287 1299
  'Last run at'                 => 'Letzte Ausführung um',
......
1439 1451
  'No bins have been added to this warehouse yet.' => 'Es wurden zu diesem Lager noch keine Lagerpl&auml;tze angelegt.',
1440 1452
  'No business has been created yet.' => 'Es wurden noch kein Kunden-/Lieferantentyp erfasst.',
1441 1453
  'No clients have been created yet.' => 'Es wurden noch keine Mandanten angelegt.',
1454
  'No changes since previous version.' => 'Keine Änderungen seit der letzten Version.',
1442 1455
  'No complexities has been created yet.' => 'Es wurden noch keine Komplexitätsgrade angelegt.',
1443 1456
  'No contact selected to delete' => 'Keine Ansprechperson zum Löschen ausgewählt',
1444 1457
  'No customer has been selected yet.' => 'Es wurde noch kein Kunde ausgewählt.',
......
1821 1834
  'Remove'                      => 'Entfernen',
1822 1835
  'Remove Draft'                => 'Entwurf l&ouml;schen',
1823 1836
  'Remove draft when posting'   => 'Entwurf beim Buchen l&ouml;schen',
1837
  'Removed sections and function blocks: #1' => 'Entfernte Abschnitte und Funktionsblöcke: #1',
1824 1838
  'Removed spoolfiles!'         => 'Druckdateien entfernt!',
1839
  'Removed text blocks: #1'     => 'Entfernte Textblöcke: #1',
1825 1840
  'Removing marked entries from queue ...' => 'Markierte Einträge werden von der Warteschlange entfernt ...',
1826 1841
  'Replace the orphaned currencies by other not orphaned currencies. To do so, please delete the currency in the textfields above and replace it by another currency. You could loose or change unintentionally exchangerates. Go on very carefully since you could destroy transactions.' => 'Ersetze die Währungen durch andere gültige Währungen. Wenn Sie sich hierfür entscheiden, ersetzen Sie bitte alle Währungen, die oben angegeben sind, durch Währungen, die in Ihrem System ordnungsgemäß eingetragen sind. Alle eingetragenen Wechselkurse für die verwaiste Währung werden dabei gelöscht. Bitte gehen Sie sehr vorsichtig vor, denn die betroffenen Buchungen können unter Umständen kaputt gehen.',
1827 1842
  'Report Positions'            => 'Berichte',
......
1928 1943
  'Save draft'                  => 'Entwurf speichern',
1929 1944
  'Save profile'                => 'Profil speichern',
1930 1945
  'Save settings as'            => 'Einstellungen speichern unter',
1931
  'Saving failed. Erro message from the database: #1' => 'Speichern schlug fehl. Fehlermeldung der Datenbank: #1',
1946
  'Saving failed. Error message from the database: #1' => 'Speichern schlug fehl. Fehlermeldung der Datenbank: #1',
1932 1947
  'Saving the file \'%s\' failed. OS error message: %s' => 'Das Speichern der Datei \'%s\' schlug fehl. Fehlermeldung des Betriebssystems: %s',
1933 1948
  'Screen'                      => 'Bildschirm',
1934 1949
  'Search'                      => 'Suchen',
......
2610 2625
  'Vendor missing!'             => 'Lieferant fehlt!',
2611 2626
  'Vendor not on file or locked!' => 'Dieser Lieferant existiert nicht oder ist gesperrt.',
2612 2627
  'Vendor not on file!'         => 'Lieferant ist nicht in der Datenbank!',
2613
  'Vendor saved'                => 'Lieferant gespeichert',
2614 2628
  'Vendor saved!'               => 'Lieferant gespeichert!',
2629
  'Vendor saved'                => 'Lieferant gespeichert',
2615 2630
  'Vendor type'                 => 'Lieferantentyp',
2616 2631
  'Vendors'                     => 'Lieferanten',
2617 2632
  'Verrechnungseinheit'         => 'Verrechnungseinheit',
2633
  'Version number'              => 'Versionsnummer',
2618 2634
  'Version'                     => 'Version',
2635
  'Versions'                    => 'Versionen',
2636
  'Vertreter'                   => 'Vertreter',
2619 2637
  'View SEPA export'            => 'SEPA-Export-Details ansehen',
2620 2638
  'View background job execution result' => 'Verlauf der Hintergrund-Job-Ausführungen anzeigen',
2621 2639
  'View background job history' => 'Hintergrund-Job-Verlauf anzeigen',
......
2652 2670
  'Workflow request_quotation'  => 'Workflow Preisanfrage',
2653 2671
  'Workflow sales_order'        => 'Workflow Auftrag',
2654 2672
  'Workflow sales_quotation'    => 'Workflow Angebot',
2673
  'Working copy identical to version number #1' => 'Mit Versionsnummer #1 identische Arbeitskopie',
2655 2674
  'Working copy without version' => 'Arbeitskopie ohne Version',
2675
  'Working copy; no description yet' => 'Arbeitskopie; noch keine Beschreibung',
2656 2676
  'Write bin to default bin in part?' => 'Diesen Lagerplatz als Standardlagerplatz im Artikel setzen?',
2657 2677
  'Wrong tax keys recorded'     => 'Gespeicherte Steuerschlüssel sind falsch',
2658 2678
  'Wrong taxes recorded'        => 'Gespeicherte Steuern passen nicht zum Steuerschlüssel',
templates/webpages/requirement_spec/_version.html
1 1
[%- USE L -%][%- USE LxERP -%][%- USE HTML -%]
2
[% L.stuff %]
2
[% L.hidden_tag('current_version_id', requirement_spec.version_id) %]
3 3
[% LxERP.t8("Current version") %]:
4 4
[% IF !requirement_spec.version_id %]
5 5
 [% LxERP.t8("Working copy without version") %]
6 6
[% ELSE %]
7 7
 [% LxERP.t8("Version") %] [% HTML.escape(requirement_spec.version.version_number) %]
8
 [% LxERP.t8("dated") %] [% HTML.escape(requirement_spec.version.itime.displayable_date) %]
8
 [% LxERP.t8("dated") %] [% HTML.escape(requirement_spec.version.itime.to_kivitendo(precision='minute')) %]
9 9
[%- END -%]
templates/webpages/requirement_spec/show.html
11 11
  <li><a href="#function-blocks-tab">[%- LxERP.t8("Content") %]</a></li>
12 12
  <li><a href="controller.pl?action=RequirementSpec/ajax_edit&id=[% HTML.url(SELF.requirement_spec.id) %]">[%- LxERP.t8("Basic settings") %]</a></li>
13 13
  <li><a href="controller.pl?action=RequirementSpec/ajax_show_time_and_cost_estimate&id=[% HTML.url(SELF.requirement_spec.id) %]">[%- LxERP.t8("Time and cost estimate") %]</a></li>
14
  <li><a href="controller.pl?action=RequirementSpecVersion/list&requirement_spec_id=[% HTML.url(SELF.requirement_spec.id) %]">[%- LxERP.t8("Versions") %]</a></li>
14 15
 </ul>
15 16

  
16 17
 <div id="function-blocks-tab">
templates/webpages/requirement_spec_version/_form.html
1
[%- USE LxERP -%][%- USE L -%]
2
[%- DEFAULT id_prefix = 'edit_version_form'
3
            submit_as = 'post'
4
%]
5
<form method="post" action="controller.pl" id="[% id_prefix %]">
6
 [% L.hidden_tag("requirement_spec_id", SELF.requirement_spec.id, id=id_prefix _ '_id') %]
7
 [% L.hidden_tag("id", SELF.version.id, id=id_prefix _ '_id') %]
8

  
9
 <table class="rs_input_field">
10
  <tr>
11
   <td>[% LxERP.t8("Version") %]</td>
12
   <td>[% SELF.requirement_spec.next_version_number %]</td>
13
  </tr>
14

  
15
  <tr>
16
   <td>[% LxERP.t8("Description") %]</td>
17
   <td>[% L.textarea_tag("rs_version.description",  SELF.version.description, cols=80, rows=8, id=id_prefix _ '_description') %]</td>
18
  </tr>
19

  
20
  <tr>
21
   <td>[% LxERP.t8("Internal comment") %]</td>
22
   <td>[% L.textarea_tag("rs_version.comment",  SELF.version.comment, cols=80, rows=8, id=id_prefix _ '_comment') %]</td>
23
  </tr>
24

  
25
 </table>
26

  
27
 <p>
28
[%- IF SELF.version.id %]
29
  [% L.ajax_submit_tag("controller.pl?action=RequirementSpecVersion/update",  "#" _ id_prefix, LxERP.t8("Save")) %]
30
  <a href="[% SELF.url_for(action='list') %]">[%- LxERP.t8("Cancel") %]</a>
31
[%- ELSE %]
32
  [% L.ajax_submit_tag("controller.pl?action=RequirementSpecVersion/create",  "#" _ id_prefix, LxERP.t8("Save")) %]
33
  <a href="#" onclick="$('.jqmWindow').jqmClose();">[% LxERP.t8("Cancel") %]</a>
34
[%- END %]
35
 </p>
36
</form>
37

  
38
<script type="text/javascript">
39
<!--
40
$(function() {
41
  $('#[% id_prefix %]_description').focus();
42
});
43
 -->
44
</script>
templates/webpages/requirement_spec_version/list.html
1
[% USE HTML %][% USE L %][% USE LxERP %][%- USE P -%]
2

  
3
<table>
4
 <thead>
5
  <tr class="listheading">
6
   <th>[%- LxERP.t8("Version number") %]</th>
7
   <th>[%- LxERP.t8("Description") %]</th>
8
   <th>[%- LxERP.t8("Internal comment") %]</th>
9
   <th>[%- LxERP.t8("Last modification") %]</th>
10
  </tr>
11
 </thead>
12

  
13
 <tbody>
14
  <tr class="listrow">
15
   <td>
16
    [%- IF SELF.requirement_spec.version_id %]
17
     [%- LxERP.t8("Working copy identical to version number #1", SELF.requirement_spec.version.version_number) %]
18
    [%- ELSE %]
19
     [%- LxERP.t8("Working copy without version") %]
20
    [%- END -%]
21
   </td>
22
   <td>[%- LxERP.t8("Working copy; no description yet") %]</td>
23
   <td>&nbsp;</td>
24
   <td>[% SELF.requirement_spec.mtime.to_kivitendo(precision='minute') %]</td>
25
  </tr>
26

  
27
  [%- FOREACH versioned = SELF.versioned_copies %]
28
   <tr class="listrow versioned_copy_context_menu">
29
    <td>[% HTML.escape(versioned.version.version_number) %]</td>
30
    <td>[% HTML.escape(P.truncate(versioned.description)) %]</td>
31
    <td>[% HTML.escape(P.truncate(versioned.comment)) %]</td>
32
    <td>[% versioned.mtime.to_kivitendo(precision='minute') %]</td>
33
   </tr>
34
  [%- END %]
35
 </tbody>
36
</table>
templates/webpages/requirement_spec_version/new.html
1
<h1>[% title %]</h1>
2

  
3
[%- INCLUDE 'common/flash.html' %]
4

  
5
[%- INCLUDE 'requirement_spec_version/_form.html' %]

Auch abrufbar als: Unified diff