Pflichtenhefversion nach Ă„nderung an Items invalidieren
[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_delete_children);
46 __PACKAGE__->before_delete(\&_before_delete_invalidate_requirement_spec_version);
47
48 sub _before_delete_delete_children {
49   my ($self) = @_;
50
51   foreach my $child (@{ SL::DB::Manager::RequirementSpecItem->get_all(where => [ parent_id => $self->id ]) }) {
52     my $result = $child->delete;
53     return $result if !$result;
54   }
55
56   1;
57 }
58
59 sub _before_save_create_fb_number {
60   my ($self) = @_;
61
62   return 1 if  $self->fb_number;
63   return 0 if !$self->requirement_spec_id;
64
65   my $method      = 'previous_' . ($self->parent_id ? 'fb' : 'section') . '_number';
66   my $next_number = $self->requirement_spec->$method + 1;
67
68   $self->requirement_spec->update_attributes($method => $next_number) || return 0;
69
70   $method    = 'requirement_spec_' . ($self->parent_id ? 'function_block' : 'section') . '_number_format';
71   my $format = SL::DB::Default->get->$method;
72
73   $self->fb_number(SL::PrefixedNumber->new(number => $format || 0)->set_to($next_number));
74
75   return 1;
76 }
77
78 sub _before_save_invalidate_requirement_spec_version {
79   my ($self, %params) = @_;
80
81   return 1 if !$self->requirement_spec_id;
82
83   my %changed_columns = map { $_ => 1 } (Rose::DB::Object::Helpers::dirty_columns($self));
84   my $has_changed     = !Rose::DB::Object::Util::is_in_db($self);
85   $has_changed      ||= any { $changed_columns{$_} } qw(requirement_spec_id parent_id position fb_number title description);
86
87   if (!$has_changed && $self->id) {
88     my $old_item = SL::DB::RequirementSpecItem->new(id => $self->id)->load;
89     $has_changed = join(':', sort map { $_->id } @{ $self->dependencies }) ne join(':', sort map { $_->id } @{ $old_item->dependencies });
90   }
91
92   $self->requirement_spec->invalidate_version if $has_changed;
93
94   return 1;
95 }
96
97 sub _before_delete_invalidate_requirement_spec_version {
98   my ($self, %params) = @_;
99
100   $self->requirement_spec->invalidate_version if $self->requirement_spec_id;
101
102   return 1;
103 }
104
105 sub validate {
106   my ($self) = @_;
107
108   my @errors;
109   push @errors, t8('The title is missing.') if !$self->parent_id && !$self->title;
110
111   return @errors;
112 }
113
114 sub sorted_children {
115   my ($self, @args) = @_;
116
117   croak "Not a writer" if @args;
118
119   return [ sort { $a->position <=> $b->position } @{ $self->children } ];
120 }
121
122 sub section {
123   my ($self, @args) = @_;
124
125   croak "Not a writer" if @args;
126   $self = $self->parent while $self->parent_id;
127
128   return $self;
129 }
130
131 sub child_type {
132   my ($self, @args) = @_;
133
134   croak "Not a writer" if @args;
135
136   return $self->item_type eq 'section' ? 'function-block' : 'sub-function-block';
137 }
138
139 1;