Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 9dffe94b

Von Moritz Bunkus vor mehr als 10 Jahren hinzugefügt

  • ID 9dffe94b2b63322be723ad557ba1e1222185bf1c
  • Vorgänger 82c10c28
  • Nachfolger 6af6a67b

Pflichtenheftabschnittsvorlagen erzeugen, bearbeiten, löschen

Unterschiede anzeigen:

SL/Controller/RequirementSpec.pm
25 25

  
26 26
use Rose::Object::MakeMethods::Generic
27 27
(
28
  scalar                  => [ qw(requirement_spec_item customers types statuses db_args flat_filter is_template visible_item visible_section) ],
28
  scalar                  => [ qw(requirement_spec_item customers types statuses db_args flat_filter visible_item visible_section) ],
29 29
  'scalar --get_set_init' => [ qw(requirement_spec complexities risks projects copy_source js) ],
30 30
);
31 31

  
......
77 77
sub action_new {
78 78
  my ($self) = @_;
79 79

  
80
  $self->requirement_spec(SL::DB::RequirementSpec->new);
80
  $self->requirement_spec(SL::DB::RequirementSpec->new(is_template => $::form->{is_template}));
81 81

  
82 82
  if ($self->copy_source) {
83 83
    $self->requirement_spec->$_($self->copy_source->$_) for qw(type_id status_id customer_id title hourly_rate)
84 84
  }
85 85

  
86
  $self->render('requirement_spec/new', title => t8('Create a new requirement spec'));
86
  $self->render('requirement_spec/new', title => $self->requirement_spec->is_template ? t8('Create a new requirement spec section template') : t8('Create a new requirement spec'));
87 87
}
88 88

  
89 89
sub action_ajax_edit {
......
220 220
  $::auth->assert('sales_quotation_edit');
221 221
  $::request->{layout}->use_stylesheet("${_}.css") for qw(jquery.contextMenu requirement_spec);
222 222
  $::request->{layout}->use_javascript("${_}.js") for qw(jquery.jstree jquery/jquery.contextMenu client_js requirement_spec);
223
  $self->is_template($::form->{is_template} ? 1 : 0);
224 223
  $self->init_visible_section;
225 224

  
226 225
  return 1;
......
275 274
  my $self   = shift;
276 275
  my $is_new = !$self->requirement_spec->id;
277 276
  my $params = delete($::form->{requirement_spec}) || { };
278
  my $title  = $is_new ? t8('Create a new requirement spec') : t8('Edit requirement spec');
279 277

  
280 278
  $self->requirement_spec->assign_attributes(%{ $params });
281 279

  
280
  my $title  = $is_new && $self->requirement_spec->is_template ? t8('Create a new requirement spec section template')
281
             : $is_new                                         ? t8('Create a new requirement spec')
282
             :            $self->requirement_spec->is_template ? t8('Edit section template')
283
             :                                                   t8('Edit requirement spec');
284

  
282 285
  my @errors = $self->requirement_spec->validate;
283 286

  
284 287
  if (@errors) {
......
306 309
    return $self->render('requirement_spec/new', title => $title);
307 310
  }
308 311

  
312
  my $info = $self->requirement_spec->is_template ? t8('The section template has been saved.') : t8('The requirement spec has been saved.');
313

  
309 314
  if ($::request->is_ajax) {
310 315
    my $html = $self->render('requirement_spec/_header', { output => 0 });
311 316
    return $self->invalidate_version
312 317
      ->replaceWith('#requirement-spec-header', $html)
313
      ->flash('info', t8('The requirement spec has been saved.'))
318
      ->flash('info', $info)
314 319
      ->render($self);
315 320
  }
316 321

  
317
  flash_later('info', $is_new ? t8('The requirement spec has been created.') : t8('The requirement spec has been saved.'));
322
  flash_later('info', $info);
318 323
  $self->redirect_to(action => 'show', id => $self->requirement_spec->id);
319 324
}
320 325

  
......
332 337
    and => [
333 338
      @{ $args{where} || [] },
334 339
      working_copy_id => undef,
335
      is_template     => $self->is_template
340
      is_template     => $::form->{is_template} ? 1 : 0,
336 341
    ]];
337 342

  
338 343
  $self->db_args(\%args);
......
343 348

  
344 349
  my $callback    = $self->get_callback;
345 350

  
351
  my $is_template = $::form->{is_template};
346 352
  my $report      = SL::ReportGenerator->new(\%::myconfig, $::form);
347 353
  $self->{report} = $report;
348 354

  
349
  my @columns     = qw(title customer status type projectnumber mtime version);
350
  my @sortable    = qw(title customer status type projectnumber mtime);
355
  my @columns     = $is_template ? qw(title mtime) : qw(title customer status type projectnumber mtime version);
356
  my @sortable    = $is_template ? qw(title mtime) : qw(title customer status type projectnumber mtime);
351 357

  
352 358
  my %column_defs = (
353 359
    title         => { obj_link => sub { $self->url_for(action => 'show', id => $_[0]->id, callback => $callback) } },
354
    customer      => { raw_data => sub { $self->presenter->customer($_[0]->customer, display => 'table-cell', callback => $callback) },
355
                       sub      => sub { $_[0]->customer->name } },
356
    projectnumber => { raw_data => sub { $self->presenter->project($_[0]->project, display => 'table-cell', callback => $callback) },
357
                       sub      => sub { $_[0]->project_id ? $_[0]->project->projectnumber : '' } },
358
    status        => { sub      => sub { $_[0]->status->description } },
359
    type          => { sub      => sub { $_[0]->type->description } },
360
    version       => { sub      => sub { $_[0]->version_id ? $_[0]->version->version_number : t8('Working copy without version') } },
361 360
    mtime         => { sub      => sub { ($_[0]->mtime || $_[0]->itime)->to_kivitendo(precision => 'minute') } },
362 361
  );
363 362

  
363
  if (!$is_template) {
364
    %column_defs = (
365
      %column_defs,
366
      customer      => { raw_data => sub { $self->presenter->customer($_[0]->customer, display => 'table-cell', callback => $callback) },
367
                         sub      => sub { $_[0]->customer->name } },
368
      projectnumber => { raw_data => sub { $self->presenter->project($_[0]->project, display => 'table-cell', callback => $callback) },
369
                         sub      => sub { $_[0]->project_id ? $_[0]->project->projectnumber : '' } },
370
      status        => { sub      => sub { $_[0]->status->description } },
371
      type          => { sub      => sub { $_[0]->type->description } },
372
      version       => { sub      => sub { $_[0]->version_id ? $_[0]->version->version_number : t8('Working copy without version') } },
373
    );
374
  }
375

  
364 376
  map { $column_defs{$_}->{text} ||= $::locale->text( $self->get_sort_spec->{$_}->{title} ) } keys %column_defs;
365 377

  
366 378
  $report->set_options(
367 379
    std_column_visibility => 1,
368 380
    controller_class      => 'RequirementSpec',
369 381
    output_format         => 'HTML',
370
    raw_top_info_text     => $self->render('requirement_spec/report_top',    { output => 0 }),
382
    raw_top_info_text     => $self->render('requirement_spec/report_top',    { output => 0 }, is_template => $is_template),
371 383
    raw_bottom_info_text  => $self->render('requirement_spec/report_bottom', { output => 0 }),
372
    title                 => $::locale->text('Requirement Specs'),
384
    title                 => $is_template ? t8('Requirement Spec Section Templates') : t8('Requirement Specs'),
373 385
    allow_pdf_export      => 1,
374 386
    allow_csv_export      => 1,
375 387
  );
......
386 398
  my ($self) = @_;
387 399

  
388 400
  my $rspec  = SL::DB::RequirementSpec->new(id => $self->requirement_spec->id)->load;
401
  return $self->js if $rspec->is_template;
402

  
389 403
  $rspec->invalidate_version;
390 404

  
391 405
  my $html = $self->render('requirement_spec/_version', { output => 0 }, requirement_spec => $rspec);
392 406
  return $self->js->html('#requirement_spec_version', $html);
393 407
}
394 408

  
395

  
396 409
1;
SL/DB/MetaSetup/RequirementSpec.pm
11 11

  
12 12
  columns => [
13 13
    id                      => { type => 'serial', not_null => 1 },
14
    type_id                 => { type => 'integer', not_null => 1 },
15
    status_id               => { type => 'integer', not_null => 1 },
14
    type_id                 => { type => 'integer' },
15
    status_id               => { type => 'integer' },
16 16
    version_id              => { type => 'integer' },
17
    customer_id             => { type => 'integer', not_null => 1 },
17
    customer_id             => { type => 'integer' },
18 18
    project_id              => { type => 'integer' },
19 19
    title                   => { type => 'text', not_null => 1 },
20 20
    hourly_rate             => { type => 'numeric', default => '0', not_null => 1, precision => 2, scale => 8 },
js/locale/de.js
7 7
"Are you sure?":"Sind Sie sicher?",
8 8
"Copy":"Kopieren",
9 9
"Copy requirement spec":"Pflichtenheft kopieren",
10
"Copy section template":"Abschnittsvorlage kopieren",
10 11
"Create PDF":"PDF erzeugen",
11 12
"Create new version":"Neue Version anlegen",
12 13
"Database Connection Test":"Test der Datenbankverbindung",
13 14
"Delete":"Löschen",
14 15
"Delete requirement spec":"Pflichtenheft löschen",
16
"Delete section template":"Abschnittsvorlage löschen",
15 17
"Delete text block":"Textblock löschen",
16 18
"Do you really want to cancel?":"Wollen Sie wirklich abbrechen?",
17 19
"Do you really want to revert to this version?":"Wollen Sie wirklich auf diese Version zurücksetzen?",
......
26 28
"Requirement spec actions":"Pflichtenheftaktionen",
27 29
"Revert to version":"Auf Version zurücksetzen",
28 30
"Save":"Speichern",
31
"Section template actions":"Abschnittsvorlagen-Aktionen",
29 32
"Section/Function block actions":"Abschnitts-/Funktionsblockaktionen",
30 33
"Text block actions":"Textblockaktionen",
31 34
"The description is missing.":"Die Beschreibung fehlt.",
js/requirement_spec.js
372 372
// ----------------------------- context menus -----------------------------
373 373
// -------------------------------------------------------------------------
374 374

  
375
ns.create_context_menus = function() {
376
  var general_actions = {
377
      sep98:           "---------"
378
    , general_actions: { name: kivi.t8('Requirement spec actions'), className: 'context-menu-heading' }
379
    // , sep99:           "---------"
380
    , create_pdf:      { name: kivi.t8('Create PDF'),              icon: "pdf",    callback: kivi.requirement_spec.create_reqspec_pdf }
381
    , create_version:  { name: kivi.t8('Create new version'),      icon: "new",    callback: kivi.requirement_spec.create_version, disabled: kivi.requirement_spec.disable_commands }
382
    , copy_reqspec:    { name: kivi.t8('Copy requirement spec'),   icon: "copy",   callback: kivi.requirement_spec.copy_reqspec   }
383
    , delete_reqspec:  { name: kivi.t8('Delete requirement spec'), icon: "delete", callback: kivi.requirement_spec.delete_reqspec }
384
  };
375
ns.create_context_menus = function(is_template) {
376
  if (is_template) {
377
    var general_actions = {
378
        sep98:           "---------"
379
      , general_actions: { name: kivi.t8('Section template actions'), className: 'context-menu-heading' }
380
      // , sep99:           "---------"
381
      , copy_reqspec:    { name: kivi.t8('Copy section template'),   icon: "copy",   callback: kivi.requirement_spec.copy_reqspec   }
382
      , delete_reqspec:  { name: kivi.t8('Delete section template'), icon: "delete", callback: kivi.requirement_spec.delete_reqspec }
383
    };
384
    var events = {};
385

  
386
  } else {                      // if (is_template)
387
    var general_actions = {
388
        sep98:           "---------"
389
      , general_actions: { name: kivi.t8('Requirement spec actions'), className: 'context-menu-heading' }
390
      // , sep99:           "---------"
391
      , create_pdf:      { name: kivi.t8('Create PDF'),              icon: "pdf",    callback: kivi.requirement_spec.create_reqspec_pdf }
392
      , create_version:  { name: kivi.t8('Create new version'),      icon: "new",    callback: kivi.requirement_spec.create_version, disabled: kivi.requirement_spec.disable_commands }
393
      , copy_reqspec:    { name: kivi.t8('Copy requirement spec'),   icon: "copy",   callback: kivi.requirement_spec.copy_reqspec   }
394
      , delete_reqspec:  { name: kivi.t8('Delete requirement spec'), icon: "delete", callback: kivi.requirement_spec.delete_reqspec }
395
    };
396

  
397
    var events = {
398
        show: kivi.requirement_spec.text_block_popup_menu_shown
399
      , hide: kivi.requirement_spec.text_block_popup_menu_hidden
400
    };
401

  
402
    $.contextMenu({
403
      selector: '.text-block-context-menu',
404
      events:   {
405
          show: kivi.requirement_spec.text_block_popup_menu_shown
406
        , hide: kivi.requirement_spec.text_block_popup_menu_hidden
407
      },
408
      items:    $.extend({
409
          heading: { name: kivi.t8('Text block actions'),    className: 'context-menu-heading' }
410
        , add:     { name: kivi.t8('Add text block'),        icon: "add",    callback: kivi.requirement_spec.standard_text_block_ajax_call }
411
        , edit:    { name: kivi.t8('Edit text block'),       icon: "edit",   callback: kivi.requirement_spec.standard_text_block_ajax_call, disabled: kivi.requirement_spec.disable_edit_text_block_commands }
412
        , delete:  { name: kivi.t8('Delete text block'),     icon: "delete", callback: kivi.requirement_spec.ask_delete_text_block,         disabled: kivi.requirement_spec.disable_edit_text_block_commands }
413
        , sep1:    "---------"
414
        , flag:    { name: kivi.t8('Toggle marker'),         icon: "flag",   callback: kivi.requirement_spec.standard_text_block_ajax_call, disabled: kivi.requirement_spec.disable_edit_text_block_commands }
415
        , sep2:    "---------"
416
        , copy:    { name: kivi.t8('Copy'),                  icon: "copy",   callback: kivi.requirement_spec.standard_text_block_ajax_call, disabled: kivi.requirement_spec.disable_edit_text_block_commands }
417
        , paste:   { name: kivi.t8('Paste'),                 icon: "paste",  callback: kivi.requirement_spec.standard_text_block_ajax_call  }
418
      }, general_actions)
419
    });
420

  
421
    $.contextMenu({
422
      selector: '.time-cost-estimate-context-menu',
423
      items:    $.extend({
424
          heading: { name: kivi.t8('Time/cost estimate actions'), className: 'context-menu-heading' }
425
        , edit:    { name: kivi.t8('Edit'), icon: "edit", callback: kivi.requirement_spec.standard_time_cost_estimate_ajax_call }
426
      }, general_actions)
427
    });
428

  
429
    $.contextMenu({
430
      selector: '.edit-time-cost-estimate-context-menu',
431
      items:    $.extend({
432
          heading: { name: kivi.t8('Time/cost estimate actions'), className: 'context-menu-heading' }
433
        , save:    { name: kivi.t8('Save'),   icon: "save",  callback: kivi.requirement_spec.standard_time_cost_estimate_ajax_call }
434
        , cancel:  { name: kivi.t8('Cancel'), icon: "close", callback: kivi.requirement_spec.standard_time_cost_estimate_ajax_call }
435
      }, general_actions)
436
    });
437

  
438
    $.contextMenu({
439
      selector: '.versioned-copy-context-menu',
440
      items:    $.extend({
441
          heading:            { name: kivi.t8('Version actions'), className: 'context-menu-heading' }
442
        , create_version_pdf: { name: kivi.t8('Create PDF'),        icon: "pdf",    callback: kivi.requirement_spec.create_pdf_for_versioned_copy_ajax_call                                                                      }
443
        , revert_to_version:  { name: kivi.t8('Revert to version'), icon: "revert", callback: kivi.requirement_spec.revert_to_versioned_copy_ajax_call,     disabled: kivi.requirement_spec.disable_versioned_copy_item_commands }
444
      }, general_actions)
445
    });
446
  }                             // if (is_template) ... else ...
385 447

  
386 448
  $.contextMenu({
387 449
    selector: '#content',
388 450
    items:    general_actions
389 451
  });
390 452

  
391
  var events = {
392
      show: kivi.requirement_spec.text_block_popup_menu_shown
393
    , hide: kivi.requirement_spec.text_block_popup_menu_hidden
394
  };
395

  
396
  $.contextMenu({
397
    selector: '.text-block-context-menu',
398
    events:   {
399
        show: kivi.requirement_spec.text_block_popup_menu_shown
400
      , hide: kivi.requirement_spec.text_block_popup_menu_hidden
401
    },
402
    items:    $.extend({
403
        heading: { name: kivi.t8('Text block actions'),    className: 'context-menu-heading' }
404
      , add:     { name: kivi.t8('Add text block'),        icon: "add",    callback: kivi.requirement_spec.standard_text_block_ajax_call }
405
      , edit:    { name: kivi.t8('Edit text block'),       icon: "edit",   callback: kivi.requirement_spec.standard_text_block_ajax_call, disabled: kivi.requirement_spec.disable_edit_text_block_commands }
406
      , delete:  { name: kivi.t8('Delete text block'),     icon: "delete", callback: kivi.requirement_spec.ask_delete_text_block,         disabled: kivi.requirement_spec.disable_edit_text_block_commands }
407
      , sep1:    "---------"
408
      , flag:    { name: kivi.t8('Toggle marker'),         icon: "flag",   callback: kivi.requirement_spec.standard_text_block_ajax_call, disabled: kivi.requirement_spec.disable_edit_text_block_commands }
409
      , sep2:    "---------"
410
      , copy:    { name: kivi.t8('Copy'),                  icon: "copy",   callback: kivi.requirement_spec.standard_text_block_ajax_call, disabled: kivi.requirement_spec.disable_edit_text_block_commands }
411
      , paste:   { name: kivi.t8('Paste'),                 icon: "paste",  callback: kivi.requirement_spec.standard_text_block_ajax_call  }
412
    }, general_actions)
413
  });
414

  
415 453
  events = {
416 454
      show: kivi.requirement_spec.item_popup_menu_shown
417 455
    , hide: kivi.requirement_spec.item_popup_menu_hidden
......
452 490
      , paste:                  { name: kivi.t8('Paste'),                  icon: "paste",  callback: kivi.requirement_spec.standard_item_ajax_call }
453 491
    }, general_actions)
454 492
  });
455

  
456
  $.contextMenu({
457
    selector: '.time-cost-estimate-context-menu',
458
    items:    $.extend({
459
        heading: { name: kivi.t8('Time/cost estimate actions'), className: 'context-menu-heading' }
460
      , edit:    { name: kivi.t8('Edit'), icon: "edit", callback: kivi.requirement_spec.standard_time_cost_estimate_ajax_call }
461
    }, general_actions)
462
  });
463

  
464
  $.contextMenu({
465
    selector: '.edit-time-cost-estimate-context-menu',
466
    items:    $.extend({
467
        heading: { name: kivi.t8('Time/cost estimate actions'), className: 'context-menu-heading' }
468
      , save:    { name: kivi.t8('Save'),   icon: "save",  callback: kivi.requirement_spec.standard_time_cost_estimate_ajax_call }
469
      , cancel:  { name: kivi.t8('Cancel'), icon: "close", callback: kivi.requirement_spec.standard_time_cost_estimate_ajax_call }
470
    }, general_actions)
471
  });
472

  
473
  $.contextMenu({
474
    selector: '.versioned-copy-context-menu',
475
    items:    $.extend({
476
        heading:            { name: kivi.t8('Version actions'), className: 'context-menu-heading' }
477
      , create_version_pdf: { name: kivi.t8('Create PDF'),        icon: "pdf",    callback: kivi.requirement_spec.create_pdf_for_versioned_copy_ajax_call                                                                      }
478
      , revert_to_version:  { name: kivi.t8('Revert to version'), icon: "revert", callback: kivi.requirement_spec.revert_to_versioned_copy_ajax_call,     disabled: kivi.requirement_spec.disable_versioned_copy_item_commands }
479
    }, general_actions)
480
  });
481 493
};
482 494

  
483 495
});                             // end of namespace(...., function() {...
locale/de/all
152 152
  'Add RFQ'                     => 'Preisanfrage erfassen',
153 153
  'Add Request for Quotation'   => 'Anfrage erfassen',
154 154
  'Add Requirement Spec'        => 'Pflichtenheft erfassen',
155
  'Add Requirement Spec Section Template' => 'Pflichtenheft-Abschnittsvorlage erfassen',
155 156
  'Add Sales Delivery Order'    => 'Lieferschein (Verkauf) erfassen',
156 157
  'Add Sales Invoice'           => 'Rechnung erfassen',
157 158
  'Add Sales Order'             => 'Auftrag erfassen',
......
521 522
  'Copy file from #1 to #2 failed: #3' => 'Kopieren der Datei von #1 nach #2 schlug fehl: #3',
522 523
  'Copy'                        => 'Kopieren',
523 524
  'Copy requirement spec'       => 'Pflichtenheft kopieren',
525
  'Copy section template'       => 'Abschnittsvorlage kopieren',
524 526
  'Correct taxkey'              => 'Richtiger Steuerschlüssel',
525 527
  'Cost'                        => 'Kosten',
526 528
  'Costs'                       => 'Kosten',
......
551 553
  'Create a new project'        => 'Neues Projekt anlegen',
552 554
  'Create a new project type'   => 'Einen neuen Projekttypen anlegen',
553 555
  'Create a new requirement spec' => 'Ein neues Pflichtenheft anlegen',
556
  'Create a new requirement spec section template' => 'Eine neue Pflichtenheft-Abschnittsvorlage erfassen',
554 557
  'Create a new requirement spec status' => 'Einen neuen Pflichtenheftstatus anlegen',
555 558
  'Create a new requirement spec type' => 'Einen neuen Pflichtenhefttypen anlegen',
556 559
  'Create a new risk level'     => 'Einen neuen Risikograd anlegen',
......
727 730
  'Delete links'                => 'Verknüpfungen löschen',
728 731
  'Delete profile'              => 'Profil löschen',
729 732
  'Delete requirement spec'     => 'Pflichtenheft löschen',
733
  'Delete section template'     => 'Abschnittsvorlage löschen',
730 734
  'Delete text block'           => 'Textblock löschen',
731 735
  'Delete transaction'          => 'Buchung löschen',
732 736
  'Deleted'                     => 'Gelöscht',
......
910 914
  'Edit requirement spec type'  => 'Pflichtenhefttypen bearbeiten',
911 915
  'Edit risk level'             => 'Risikograd bearbeiten',
912 916
  'Edit section #1'             => 'Abschnitt #1 bearbeiten',
917
  'Edit section template'       => 'Abschnittsvorlage bearbeiten',
913 918
  'Edit templates'              => 'Vorlagen bearbeiten',
914 919
  'Edit text block'             => 'Textblock bearbeiten',
915 920
  'Edit text block \'#1\''      => 'Textblock \'#1\' bearbeiten',
......
1865 1870
  'Requested execution date to' => 'Gewünschtes Ausführungsdatum bis',
1866 1871
  'Requests for Quotation'      => 'Preisanfragen',
1867 1872
  'Required by'                 => 'Lieferdatum',
1873
  'Requirement Spec Section Templates' => 'Pflichtenheft-Abschnittsvorlagen',
1868 1874
  'Requirement Spec Status'     => 'Pflichtenheftstatus',
1869 1875
  'Requirement Spec Statuses'   => 'Pflichtenheftstatus',
1870 1876
  'Requirement Spec Type'       => 'Pflichtenhefttyp',
......
1873 1879
  'Requirement spec actions'    => 'Pflichtenheftaktionen',
1874 1880
  'Requirement spec function block #1 with #2 sub function blocks; description: "#3"' => 'Pflichtenheft-Funktionsblock #1 mit #2 Unterfunktionsblöcken; Beschreibung: "#3"',
1875 1881
  'Requirement spec section #1 "#2" with #3 function blocks and a total of #4 sub function blocks; preamble: "#5"' => 'Pflichtenheftabschnitt #1 "#2" mit #3 Funktionsblöcken und insgesamt #4 Unterfunktionsblöcken; Einleitung: "#5"',
1882
  'Requirement spec section template \'#1\'' => 'Pflichtenheft_Abschnittsvorlage \'#1\'',
1876 1883
  'Requirement spec sub function block #1; description: "#2"' => 'Pflichtenheft-Unterfunktionsblock #1; Beschreibung: "#2"',
1877 1884
  'Requirement spec text block "#1"; content: "#2"' => 'Pflichtenheft-Textblock "1"; Inhalt: "#2"',
1878 1885
  'Requirement specs'           => 'Pflichtenhefte',
......
1962 1969
  'Searchable'                  => 'Durchsuchbar',
1963 1970
  'Secondary sorting'           => 'Untersortierung',
1964 1971
  'Section "#1"'                => 'Abschnitt "#1"',
1972
  'Section template actions'    => 'Abschnittsvorlagen-Aktionen',
1965 1973
  'Section/Function block actions' => 'Abschnitts-/Funktionsblockaktionen',
1966 1974
  'Sections'                    => 'Abschnitte',
1967 1975
  'Select'                      => 'auswählen',
......
2389 2397
  'The risk level is in use and cannot be deleted.' => 'Der Risikograd wird verwendet und kann nicht gelöscht werden.',
2390 2398
  'The second reason is that kivitendo allowed the user to enter the tax amount manually regardless of the taxkey used.' => 'Der zweite Grund war, dass kivitendo zuließ, dass die Benutzer beliebige, von den tatsächlichen Steuerschlüsseln unabhängige Steuerbeträge eintrugen.',
2391 2399
  'The second way is to use Perl\'s CPAN module and let it download and install the module for you.' => 'Die zweite Variante besteht darin, Perls CPAN-Modul zu benutzen und es das Modul für Sie installieren zu lassen.',
2400
  'The section template has been saved.' => 'Die Abschnittsvorlage wurde gespeichert.',
2392 2401
  'The selected bank account does not exist anymore.' => 'Das ausgewählte Bankkonto existiert nicht mehr.',
2393 2402
  'The selected bin does not exist.' => 'Der ausgewählte Lagerplatz existiert nicht.',
2394 2403
  'The selected currency'       => 'Die ausgewählte Währung',
menus/erp.ini
35 35
module=controller.pl
36 36
action=Project/new
37 37

  
38
[Master Data--Add Requirement Spec Section Template]
39
ACCESS=project_edit
40
module=controller.pl
41
action=RequirementSpec/new
42
is_template=1
43

  
38 44
[Master Data--Update Prices]
39 45
ACCESS=part_service_assembly_edit
40 46
module=ic.pl
......
89 95
filter.active=active
90 96
filter.valid=valid
91 97

  
98
[Master Data--Reports--Requirement Spec Section Templates]
99
module=controller.pl
100
action=RequirementSpec/list
101
is_template=1
102

  
92 103
[AR]
93 104

  
94 105
[AR--Add Quotation]
sql/Pg-upgrade2/requirement_specs_section_templates.sql
1
-- @tag: requirement_specs_section_templates
2
-- @description: requirement_specs_section_templates
3
-- @depends: release_3_0_0 requirement_specs
4
-- @charset: utf-8
5

  
6
ALTER TABLE requirement_specs ALTER COLUMN type_id     DROP NOT NULL;
7
ALTER TABLE requirement_specs ALTER COLUMN status_id   DROP NOT NULL;
8
ALTER TABLE requirement_specs ALTER COLUMN customer_id DROP NOT NULL;
9

  
10
ALTER TABLE requirement_specs
11
ADD CONSTRAINT requirement_specs_is_template_or_has_customer_status_type
12
CHECK (
13
    is_template
14
 OR (    (type_id     IS NOT NULL)
15
     AND (status_id   IS NOT NULL)
16
     AND (customer_id IS NOT NULL))
17
);
templates/webpages/requirement_spec/_filter.html
8 8
 <a href="#" onClick="javascript:$('.filter_toggle').toggle()">[% LxERP.t8("Hide Filter") %]</a>
9 9

  
10 10
 <form method="post" action="controller.pl">
11
  [%- L.hidden_tag("is_template", is_template) %]
11 12

  
12 13
  <p>
13 14
   <table class="rs_input_field">
......
16 17
     <td>[% L.input_tag('filter.title:substr::ilike', filter.title_substr__ilike) %]</td>
17 18
    </tr>
18 19

  
20
[%- UNLESS is_template %]
19 21
    <tr>
20 22
     <th align="right">[% LxERP.t8("Customer") %]</th>
21 23
     <td>[% L.input_tag('filter.customer.name:substr::ilike', filter.customer.name_substr__ilike) %]</td>
......
40 42
     <th align="right">[% LxERP.t8("Project") %]</th>
41 43
     <td>[% L.select_tag('filter.project_id', SELF.projects, default=filter.project_id, title_key="full_description", with_empty=1) %]</td>
42 44
    </tr>
45
[%- END %]
43 46
   </table>
44 47
  </p>
45 48

  
templates/webpages/requirement_spec/_form.html
4 4
%]
5 5
<form method="post" action="controller.pl" id="[% id_prefix %]">
6 6
 [% L.hidden_tag("id", SELF.requirement_spec.id, id=id_prefix _ '_id') %]
7
 [% L.hidden_tag("requirement_spec.is_template", SELF.requirement_spec.is_template, id=id_prefix _ '_is_template') %]
7 8

  
8 9
 <table class="rs_input_field">
9 10
  <tr>
......
11 12
   <td>[% L.input_tag("requirement_spec.title", SELF.requirement_spec.title, id=id_prefix _ '_title') %]</td>
12 13
  </tr>
13 14

  
15
[%- UNLESS SELF.requirement_spec.is_template %]
16

  
14 17
  <tr>
15 18
   <td>[% LxERP.t8("Requirement Spec Type") %]</td>
16 19
   <td>[% L.select_tag("requirement_spec.type_id",  SELF.types, default=SELF.requirement_spec.type_id, title_key="description", id=id_prefix _ '_type_id') %]</td>
......
32 35
   <td>[% L.input_tag("requirement_spec.hourly_rate_as_number", SELF.requirement_spec.hourly_rate_as_number, id=id_prefix _ '_hourly_rate_as_number') %]</td>
33 36
  </tr>
34 37

  
38
[%- END %]
39

  
35 40
 </table>
36 41

  
37 42
[%- IF SELF.copy_source %]
......
46 51
[% IF submit_as == 'post' %]
47 52
  [% L.hidden_tag("action", "RequirementSpec/dispatch", id=id_prefix _ '_action') %]
48 53
  [% L.submit_tag("action_" _ (SELF.requirement_spec.id ? "update" : "create"), LxERP.t8('Save'), id=id_prefix _ '_action_update') %]
49
  <a href="[% SELF.url_for(action="list") %]">[% LxERP.t8('Abort') %]</a>
54
  <a href="[% SELF.url_for(action="list", is_template=SELF.requirement_spec.is_template) %]">[% LxERP.t8('Abort') %]</a>
50 55
[% ELSE %]
51 56
  [% L.ajax_submit_tag("controller.pl?action=RequirementSpec/update",  "#" _ id_prefix, LxERP.t8("Save")) %]
52 57
[% END %]
templates/webpages/requirement_spec/_header.html
1 1
[%- USE HTML -%][%- USE LxERP -%]
2 2
<div id="requirement-spec-header">
3 3
 <h1>
4
  [%- HTML.escape(SELF.requirement_spec.displayable_name('format', 'with_customer')) %]
5
  [% LxERP.t8("for") %]
6
  [% HTML.escape(SELF.requirement_spec.customer.displayable_name) -%]
4
  [%- IF SELF.requirement_spec.is_template %]
5
   [%- HTML.escape(LxERP.t8("Requirement spec section template '#1'", SELF.requirement_spec.title)) %]
6
  [%- ELSE %]
7
   [%- HTML.escape(SELF.requirement_spec.displayable_name('format', 'with_customer')) %]
8
   [% LxERP.t8("for") %]
9
   [% HTML.escape(SELF.requirement_spec.customer.displayable_name) -%]
10
  [%- END %]
7 11
 </h1>
8 12
</div>
templates/webpages/requirement_spec/show.html
4 4

  
5 5
[%- INCLUDE 'requirement_spec/_header.html' %]
6 6

  
7
[%- L.hidden_tag('requirement_spec_id', SELF.requirement_spec.id) -%]
7
[%- L.hidden_tag('requirement_spec_id', SELF.requirement_spec.id, 'data-is-template'=(SELF.requirement_spec.is_template ? 1 : 0)) -%]
8 8

  
9 9
<div class="tabwidget">
10 10
 <ul>
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
  <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>
13
  [%- UNLESS SELF.requirement_spec.is_template %]
14
   <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>
15
   <li><a href="controller.pl?action=RequirementSpecVersion/list&requirement_spec_id=[% HTML.url(SELF.requirement_spec.id) %]">[%- LxERP.t8("Versions") %]</a></li>
16
  [%- END %]
15 17
 </ul>
16 18

  
17 19
 <div id="function-blocks-tab">
18
  <div id="requirement_spec_version">
20
  [%- UNLESS SELF.requirement_spec.is_template %]
21
   <div id="requirement_spec_version">
19 22
    [%- INCLUDE 'requirement_spec/_version.html' requirement_spec=SELF.requirement_spec -%]
20
  </div>
23
   </div>
24
  [%- END %]
21 25

  
22 26
  <div id="column-container" class="clearfix">
23 27
   <div id="tree-column">
......
43 47
<script type="text/javascript">
44 48
 <!--
45 49
$(function() {
46
  var tree_data = [
47
    { data:     [% JSON.json(LxERP.t8("Text blocks front")) %],
48
      metadata: { type: "text-blocks-front" },
49
      attr:     { id: "tb-front", class: "text-block-context-menu" },
50
      children: [
51
[% FOREACH tb = SELF.requirement_spec.text_blocks_sorted(output_position=0) %]
52
 [% P.requirement_spec_text_block_jstree_data(tb).json %][% IF !loop.last %],[% END %]
53
[% END %]
54
      ]},
50
  var initially_open = ['sections'
51
[%- FOREACH section = SELF.requirement_spec.sections -%]
52
        , "fb-[% section.id %]"
53
 [%- FOREACH function_block = section.children -%]
54
        , "fb-[% function_block.id -%]"
55
 [%- END -%]
56
[%- END -%]
57
  ];
55 58

  
56
    { data:     [% JSON.json(LxERP.t8("Sections")) %],
59
  var tree_data = [{
60
      data:     [% JSON.json(LxERP.t8("Sections")) %],
57 61
      metadata: { type: "sections" },
58 62
      attr:     { id: "sections", class: "section-context-menu" },
59 63
      children: [
60 64
[% FOREACH section = SELF.requirement_spec.sections %]
61 65
 [% P.requirement_spec_item_jstree_data(section).json %][% IF !loop.last %],[% END %]
62 66
[% END %]
63
      ]},
67
      ]}];
68

  
69
[% UNLESS SELF.requirement_spec.is_template %]
70
  tree_data.unshift({
71
      data:     [% JSON.json(LxERP.t8("Text blocks front")) %],
72
      metadata: { type: "text-blocks-front" },
73
      attr:     { id: "tb-front", class: "text-block-context-menu" },
74
      children: [
75
[% FOREACH tb = SELF.requirement_spec.text_blocks_sorted(output_position=0) %]
76
 [% P.requirement_spec_text_block_jstree_data(tb).json %][% IF !loop.last %],[% END %]
77
[% END %]
78
      ]});
64 79

  
65
    { data:     [% JSON.json(LxERP.t8("Text blocks back")) %],
80
  tree_data.push({
81
      data:     [% JSON.json(LxERP.t8("Text blocks back")) %],
66 82
      metadata: { type: "text-blocks-back" },
67 83
      attr:     { id: "tb-back", class: "text-block-context-menu" },
68 84
      children: [
69 85
[% FOREACH tb = SELF.requirement_spec.text_blocks_sorted(output_position=1) %]
70 86
 [% P.requirement_spec_text_block_jstree_data(tb).json %][% IF !loop.last %],[% END %]
71 87
[% END %]
72
      ]}];
88
      ]});
89

  
90
  initially_open = initially_open.concat(['tb-front', 'tb-back']);
91
[% END %]
73 92

  
74 93
  $('#tree').jstree({
75 94
    core: {
76 95
      animation: 0,
77
      initially_open: [ "tb-front", "tb-back", "sections"
78
[%- FOREACH section = SELF.requirement_spec.sections -%]
79
        , "fb-[% section.id %]"
80
 [%- FOREACH function_block = section.children -%]
81
        , "fb-[% function_block.id -%]"
82
 [%- END -%]
83
[%- END -%]
84
    ]},
96
      initially_open: initially_open,
97
    },
85 98
    json_data: {
86 99
      data: tree_data
87 100
    },
......
102 115
  $.jstree._reference("#tree").select_node('#fb-[% SELF.requirement_spec_item.id %]', true);
103 116
[% END %]
104 117

  
105
  kivi.requirement_spec.create_context_menus();
118
  kivi.requirement_spec.create_context_menus([% SELF.requirement_spec.is_template ? 'true' : 'false' %]);
106 119
});
107 120

  
108 121
  -->

Auch abrufbar als: Unified diff