Pflichtenheft: Zugriff auf nicht vorhandenes »visible_item« verhindern
[kivitendo-erp.git] / SL / DB / Project.pm
1 package SL::DB::Project;
2
3 use strict;
4
5 use List::MoreUtils qw(any);
6
7 use SL::DB::MetaSetup::Project;
8 use SL::DB::Manager::Project;
9
10 use SL::DB::Helper::CustomVariables(
11   module      => 'Projects',
12   cvars_alias => 1,
13 );
14
15 __PACKAGE__->meta->initialize;
16
17 sub validate {
18   my ($self) = @_;
19
20   my @errors;
21   push @errors, $::locale->text('The project number is missing.')        if !$self->projectnumber;
22   push @errors, $::locale->text('The project number is already in use.') if !$self->is_projectnumber_unique;
23   push @errors, $::locale->text('The description is missing.')           if !$self->description;
24
25   return @errors;
26 }
27
28 sub is_used {
29   my ($self) = @_;
30
31   # Unsaved projects are never referenced.
32   return 0 unless $self->id;
33
34   return any {
35     my $column = $SL::DB::Manager::Project::project_id_column_prefixes{$_} . 'project_id';
36     $self->db->dbh->selectrow_arrayref(qq|SELECT EXISTS(SELECT * FROM ${_} WHERE ${column} = ?)|, undef, $self->id)->[0]
37   } @SL::DB::Manager::Project::tables_with_project_id_cols;
38 }
39
40 sub is_projectnumber_unique {
41   my ($self) = @_;
42
43   return 1 unless $self->projectnumber;
44
45   my @filter = (projectnumber => $self->projectnumber);
46   @filter    = (and => [ @filter, '!id' => $self->id ]) if $self->id;
47
48   return !SL::DB::Manager::Project->get_first(where => \@filter);
49 }
50
51 sub displayable_name {
52   my ($self) = @_;
53
54   return join ' ', grep $_, $self->projectnumber, $self->description;
55 }
56
57 sub full_description {
58   my ($self, %params) = @_;
59
60   $params{style} ||= 'both';
61   my $description;
62
63   if ($params{style} =~ m/number/) {
64     $description = $self->projectnumber;
65
66   } elsif ($params{style} =~ m/description/) {
67     $description = $self->description;
68
69   } elsif (($params{style} =~ m/full/) && $self->customer) {
70     $description = $self->projectnumber;
71     if ($self->description && do { my $desc = quotemeta $self->description; $self->projectnumber !~ m/$desc/ }) {
72       $description .= ' ' . $self->description;
73     }
74
75     $description = $self->customer->name . " (${description})";
76
77   } else {
78     $description = $self->projectnumber;
79     if ($self->description && do { my $desc = quotemeta $self->description; $self->projectnumber !~ m/$desc/ }) {
80       $description .= ' (' . $self->description . ')';
81     }
82   }
83
84   return $description;
85 }
86
87 1;
88
89 __END__
90
91 =pod
92
93 =head1 NAME
94
95 SL::DB::Project: Model for the 'project' table
96
97 =head1 SYNOPSIS
98
99 This is a standard Rose::DB::Object based model and can be used as one.
100
101 =head1 FUNCTIONS
102
103 =over 4
104
105 =item C<validate>
106
107 Checks whether or not all fields are set to valid values so that the
108 object can be saved. If valid returns an empty list. Returns an array
109 of translated error message otherwise.
110
111 =item C<is_used>
112
113 Checks whether or not the project is referenced from any other
114 database table. Returns a boolean value.
115
116 =item C<is_projectnumber_unique>
117
118 Returns trueish if the project number is not used for any other
119 project in the database. Also returns trueish if no project number has
120 been set yet.
121
122 =item C<displayable_name>
123
124 Returns a human-readable description of the project, consisting of projectnumber
125 and description.
126
127 =item C<full_description %params>
128
129 Returns a full description for the project which can consist of the
130 project number, its description or both. This is determined by the
131 parameter C<style> which defaults to C<both>:
132
133 =over 2
134
135 =item C<both>
136
137 Returns the project's number followed by its description in
138 parenthesis (e.g. "12345 (Secret Combinations)"). If the project's
139 description is already part of the project's number then it will not
140 be appended.
141
142 =item C<projectnumber> (or simply C<number>)
143
144 Returns only the project's number.
145
146 =item C<projectdescription> (or simply C<description>)
147
148 Returns only the project's description.
149
150 =item C<full>
151
152 Returns the customer name followed by the project number and project
153 description in parenthesis (e.g. "Evil Corp (12345 World
154 domination)"). If the project's description is already part of the
155 project's number then it will not be appended.
156
157 If this project isn't linked to a customer then the style C<both> is
158 used instead.
159
160 =back
161
162 =back
163
164 =head1 AUTHOR
165
166 Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
167
168 =cut