Pflichtenhefte: PDFs zu Arbeitskopie und Versionen erzeugen
[kivitendo-erp.git] / SL / DB / RequirementSpecItem.pm
1 package SL::DB::RequirementSpecItem;
2
3 use strict;
4
5 use Carp;
6 use List::MoreUtils qw(any);
7 use Rose::DB::Object::Helpers;
8 use Rose::DB::Object::Util;
9
10 use SL::DB::MetaSetup::RequirementSpecItem;
11 use SL::DB::Manager::RequirementSpecItem;
12 use SL::DB::Helper::ActsAsList;
13 use SL::DB::Helper::AttrDuration;
14 use SL::DB::Default;
15 use SL::Locale::String;
16 use SL::PrefixedNumber;
17
18 __PACKAGE__->meta->add_relationship(
19   children     => {
20     type       => 'one to many',
21     class      => 'SL::DB::RequirementSpecItem',
22     column_map => { id => 'parent_id' },
23   },
24   dependencies => {
25     map_class  => 'SL::DB::RequirementSpecDependency',
26     map_from   => 'depending_item',
27     map_to     => 'depended_item',
28     type       => 'many to many',
29   },
30   dependents   => {
31     map_class  => 'SL::DB::RequirementSpecDependency',
32     map_from   => 'depended_item',
33     map_to     => 'depending_item',
34     type       => 'many to many',
35   },
36 );
37
38 __PACKAGE__->meta->initialize;
39
40 __PACKAGE__->configure_acts_as_list(group_by => [qw(requirement_spec_id parent_id)]);
41 __PACKAGE__->attr_duration(qw(time_estimation));
42
43 __PACKAGE__->before_save(\&_before_save_create_fb_number);
44 __PACKAGE__->before_save(\  &_before_save_invalidate_requirement_spec_version);
45 __PACKAGE__->before_delete(\&_before_delete_invalidate_requirement_spec_version);
46
47 sub _before_save_create_fb_number {
48   my ($self) = @_;
49
50   return 1 if  $self->fb_number;
51   return 0 if !$self->requirement_spec_id;
52
53   my $method      = 'previous_' . ($self->parent_id ? 'fb' : 'section') . '_number';
54   my $next_number = $self->requirement_spec->$method + 1;
55
56   $self->requirement_spec->update_attributes($method => $next_number) || return 0;
57
58   $method    = 'requirement_spec_' . ($self->parent_id ? 'function_block' : 'section') . '_number_format';
59   my $format = SL::DB::Default->get->$method;
60
61   $self->fb_number(SL::PrefixedNumber->new(number => $format || 0)->set_to($next_number));
62
63   return 1;
64 }
65
66 sub _before_save_invalidate_requirement_spec_version {
67   my ($self, %params) = @_;
68
69   return 1 if !$self->requirement_spec_id;
70
71   my %changed_columns = map { $_ => 1 } (Rose::DB::Object::Helpers::dirty_columns($self));
72   my $has_changed     = !Rose::DB::Object::Util::is_in_db($self);
73   $has_changed      ||= any { $changed_columns{$_} } qw(requirement_spec_id parent_id position fb_number title description);
74
75   if (!$has_changed && $self->id) {
76     my $old_item = SL::DB::RequirementSpecItem->new(id => $self->id)->load;
77     $has_changed = join(':', sort map { $_->id } @{ $self->dependencies }) ne join(':', sort map { $_->id } @{ $old_item->dependencies });
78   }
79
80   $self->requirement_spec->invalidate_version if $has_changed;
81
82   return 1;
83 }
84
85 sub _before_delete_invalidate_requirement_spec_version {
86   my ($self, %params) = @_;
87
88   $self->requirement_spec->invalidate_version if $self->requirement_spec_id;
89
90   return 1;
91 }
92
93 sub validate {
94   my ($self) = @_;
95
96   my @errors;
97   push @errors, t8('The title is missing.') if !$self->parent_id && !$self->title;
98
99   return @errors;
100 }
101
102 sub children_sorted {
103   my ($self, @args) = @_;
104
105   croak "Not a writer" if @args;
106
107   my @children = sort { $a->position <=> $b->position } $self->children;
108   return wantarray ? @children : \@children;
109 }
110
111 sub section {
112   my ($self, @args) = @_;
113
114   croak "Not a writer" if @args;
115   $self = $self->parent while $self->parent_id;
116
117   return $self;
118 }
119
120 sub child_type {
121   my ($self, @args) = @_;
122
123   croak "Not a writer" if @args;
124
125   return $self->item_type eq 'section' ? 'function-block' : 'sub-function-block';
126 }
127
128 1;