Revision 9dffe94b
Von Moritz Bunkus vor mehr als 10 Jahren hinzugefügt
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
Pflichtenheftabschnittsvorlagen erzeugen, bearbeiten, löschen