]> wagnertech.de Git - mfinanz.git/blob - SL/Controller/Invoice.pm
kivitendo 3.9.2-0.2
[mfinanz.git] / SL / Controller / Invoice.pm
1 package SL::Controller::Invoice;
2
3 use strict;
4
5 use parent qw(SL::Controller::Base);
6
7 use Archive::Zip;
8 use Params::Validate qw(:all);
9
10 use SL::DB::File;
11 use SL::DB::Invoice;
12 use SL::DB::Employee;
13
14 use SL::Webdav;
15 use SL::File;
16 use SL::Locale::String qw(t8);
17 use SL::MoreCommon qw(listify);
18
19 __PACKAGE__->run_before('check_auth');
20
21 sub check_auth {
22   my ($self) = validate_pos(@_, { isa => 'SL::Controller::Invoice' }, 1);
23
24   return 1 if  $::auth->assert('ar_transactions', 1); # may edit all invoices
25   my @ids = listify($::form->{id});
26   $::auth->assert() unless has_rights_through_projects(\@ids);
27   return 1;
28 }
29
30 sub has_rights_through_projects {
31   my ($ids) = validate_pos(@_, {
32     type => ARRAYREF,
33   });
34   return 0 unless scalar @{$ids}; # creating new invoices isn't allowed without invoice_edit
35   my $current_employee = SL::DB::Manager::Employee->current;
36   my $id_placeholder = join(', ', ('?') x @{$ids});
37   # Count of ids where the use has no access to
38   my $query = <<SQL;
39   SELECT count(id) FROM ar
40   WHERE NOT EXISTS (
41     SELECT * from employee_project_invoices WHERE project_id = ar.globalproject_id and employee_id = ?
42   ) AND id IN ($id_placeholder)
43 SQL
44   my ($no_access_count) = SL::DB->client->dbh->selectrow_array($query, undef, $current_employee->id, @{$ids});
45   return !$no_access_count;
46 }
47
48 sub action_webdav_pdf_export {
49   my ($self) = @_;
50   my $ids  = $::form->{id};
51
52   my $invoices = SL::DB::Manager::Invoice->get_all(where => [ id => $ids ]);
53
54   my @file_names_and_file_paths;
55   my @errors;
56   foreach my $invoice (@{$invoices}) {
57     my $record_type = $invoice->record_type;
58     $record_type = 'invoice' if $record_type eq 'ar_transaction';
59     $record_type = 'invoice' if $record_type eq 'invoice_storno';
60     my $webdav = SL::Webdav->new(
61       type     => $record_type,
62       number   => $invoice->record_number,
63     );
64     my @latest_object = $webdav->get_all_latest();
65     unless (scalar @latest_object) {
66       push @errors, t8(
67         "No Dokument found for record '#1'. Please deselect it or create a document it.",
68         $invoice->displayable_name()
69       );
70       next;
71     }
72     push @file_names_and_file_paths, {
73       file_name => $latest_object[0]->basename . "." . $latest_object[0]->extension,
74       file_path => $latest_object[0]->full_filedescriptor(),
75     }
76   }
77
78   if (scalar @errors) {
79     die join("\n", @errors);
80   }
81   $self->_create_and_send_zip(\@file_names_and_file_paths);
82 }
83
84 sub action_files_pdf_export {
85   my ($self) = @_;
86
87   my $ids  = $::form->{id};
88
89   my $invoices = SL::DB::Manager::Invoice->get_all(where => [ id => $ids ]);
90
91   my @file_names_and_file_paths;
92   my @errors;
93   foreach my $invoice (@{$invoices}) {
94     my $record_type = $invoice->record_type;
95     $record_type = 'invoice' if $record_type eq 'ar_transaction';
96     $record_type = 'invoice' if $record_type eq 'invoice_storno';
97     my @file_objects = SL::File->get_all(
98       object_type => $record_type,
99       object_id   => $invoice->id,
100       file_type   => 'document',
101       source      => 'created',
102     );
103
104     unless (scalar @file_objects) {
105       push @errors, t8(
106         "No Dokument found for record '#1'. Please deselect it or create a document it.",
107         $invoice->displayable_name()
108       );
109       next;
110     }
111     foreach my $file_object (@file_objects) {
112       eval {
113         push @file_names_and_file_paths, {
114           file_name => $file_object->file_name,
115           file_path => $file_object->get_file(),
116         };
117       } or do {
118         push @errors, $@,
119       };
120     }
121   }
122
123   if (scalar @errors) {
124     die join("\n", @errors);
125   }
126   $self->_create_and_send_zip(\@file_names_and_file_paths);
127 }
128
129 sub _create_and_send_zip {
130   my ($self, $file_names_and_file_paths) = validate_pos(@_,
131     { isa => 'SL::Controller::Invoice' },
132     {
133       type => ARRAYREF,
134       callbacks => {
135         "has 'file_name' and 'file_path'" => sub {
136           foreach my $file_entry (@{$_[0]}) {
137             return 0 unless defined $file_entry->{file_name}
138                          && defined $file_entry->{file_path};
139           }
140           return 1;
141         }
142       }
143     });
144
145   my ($fh, $zipfile) = File::Temp::tempfile();
146   my $zip = Archive::Zip->new();
147   foreach my $file (@{$file_names_and_file_paths}) {
148     $zip->addFile($file->{file_path}, $file->{file_name});
149   }
150   $zip->writeToFileHandle($fh) == Archive::Zip::AZ_OK() or die 'error writing zip file';
151   close($fh);
152
153   $self->send_file(
154     $zipfile,
155     name => t8('pdf_records.zip'), unlink => 1,
156     type => 'application/zip',
157   );
158 }
159
160 1;