Revision 079067ee
Von Tamino Steinert vor 9 Monaten hinzugefügt
- ID 079067eea085ae3bc45d07fc3c7aba0f2ea083e4
- Vorgänger 86ec4349
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 |
# _check_access_right_for_ids($ids); |
|
53 |
|
|
54 |
my $invoices = SL::DB::Manager::Invoice->get_all(where => [ id => $ids ]); |
|
55 |
|
|
56 |
my @file_names_and_file_paths; |
|
57 |
my @errors; |
|
58 |
foreach my $invoice (@{$invoices}) { |
|
59 |
my $record_type = $invoice->record_type; |
|
60 |
$record_type = 'general_ledger' if $record_type eq 'ar_transaction'; |
|
61 |
$record_type = 'invoice' if $record_type eq 'invoice_storno'; |
|
62 |
my $webdav = SL::Webdav->new( |
|
63 |
type => $record_type, |
|
64 |
number => $invoice->record_number, |
|
65 |
); |
|
66 |
my @latest_object = $webdav->get_all_latest(); |
|
67 |
unless (scalar @latest_object) { |
|
68 |
push @errors, t8( |
|
69 |
"No Dokument found for record '#1'. Please deselect it or create a document it.", |
|
70 |
$invoice->displayable_name() |
|
71 |
); |
|
72 |
next; |
|
73 |
} |
|
74 |
push @file_names_and_file_paths, { |
|
75 |
file_name => $latest_object[0]->basename . "." . $latest_object[0]->extension, |
|
76 |
file_path => $latest_object[0]->full_filedescriptor(), |
|
77 |
} |
|
78 |
} |
|
79 |
|
|
80 |
if (scalar @errors) { |
|
81 |
die join("\n", @errors); |
|
82 |
} |
|
83 |
$self->_create_and_send_zip(\@file_names_and_file_paths); |
|
84 |
} |
|
85 |
|
|
86 |
sub action_files_pdf_export { |
|
87 |
my ($self) = @_; |
|
88 |
|
|
89 |
my $ids = $::form->{id}; |
|
90 |
|
|
91 |
# _check_access_right_for_ids($ids); |
|
92 |
|
|
93 |
my $invoices = SL::DB::Manager::Invoice->get_all(where => [ id => $ids ]); |
|
94 |
|
|
95 |
my @file_names_and_file_paths; |
|
96 |
my @errors; |
|
97 |
foreach my $invoice (@{$invoices}) { |
|
98 |
my $record_type = $invoice->record_type; |
|
99 |
$record_type = 'invoice' if $record_type eq 'ar_transaction'; |
|
100 |
$record_type = 'invoice' if $record_type eq 'invoice_storno'; |
|
101 |
my @file_objects = SL::File->get_all( |
|
102 |
object_type => $record_type, |
|
103 |
object_id => $invoice->id, |
|
104 |
file_type => 'document', |
|
105 |
source => 'created', |
|
106 |
); |
|
107 |
|
|
108 |
unless (scalar @file_objects) { |
|
109 |
push @errors, t8( |
|
110 |
"No Dokument found for record '#1'. Please deselect it or create a document it.", |
|
111 |
$invoice->displayable_name() |
|
112 |
); |
|
113 |
next; |
|
114 |
} |
|
115 |
foreach my $file_object (@file_objects) { |
|
116 |
eval { |
|
117 |
push @file_names_and_file_paths, { |
|
118 |
file_name => $file_object->file_name, |
|
119 |
file_path => $file_object->get_file(), |
|
120 |
}; |
|
121 |
} or do { |
|
122 |
push @errors, $@, |
|
123 |
}; |
|
124 |
} |
|
125 |
} |
|
126 |
|
|
127 |
if (scalar @errors) { |
|
128 |
die join("\n", @errors); |
|
129 |
} |
|
130 |
$self->_create_and_send_zip(\@file_names_and_file_paths); |
|
131 |
} |
|
132 |
|
|
133 |
sub _create_and_send_zip { |
|
134 |
my ($self, $file_names_and_file_paths) = validate_pos(@_, |
|
135 |
{ isa => 'SL::Controller::Invoice' }, |
|
136 |
{ |
|
137 |
type => ARRAYREF, |
|
138 |
callbacks => { |
|
139 |
"has 'file_name' and 'file_path'" => sub { |
|
140 |
foreach my $file_entry (@{$_[0]}) { |
|
141 |
return 0 unless defined $file_entry->{file_name} |
|
142 |
&& defined $file_entry->{file_path}; |
|
143 |
} |
|
144 |
return 1; |
|
145 |
} |
|
146 |
} |
|
147 |
}); |
|
148 |
|
|
149 |
my ($fh, $zipfile) = File::Temp::tempfile(); |
|
150 |
my $zip = Archive::Zip->new(); |
|
151 |
foreach my $file (@{$file_names_and_file_paths}) { |
|
152 |
$zip->addFile($file->{file_path}, $file->{file_name}); |
|
153 |
} |
|
154 |
$zip->writeToFileHandle($fh) == Archive::Zip::AZ_OK() or die 'error writing zip file'; |
|
155 |
close($fh); |
|
156 |
|
|
157 |
$self->send_file( |
|
158 |
$zipfile, |
|
159 |
name => t8('pdf_records.zip'), unlink => 1, |
|
160 |
type => 'application/zip', |
|
161 |
); |
|
162 |
} |
|
163 |
|
|
164 |
1; |
bin/mozilla/ar.pl | ||
---|---|---|
35 | 35 |
use POSIX qw(strftime); |
36 | 36 |
use List::Util qw(sum first max); |
37 | 37 |
use List::UtilsBy qw(sort_by); |
38 |
use Archive::Zip; |
|
39 |
use Params::Validate qw(:all); |
|
40 | 38 |
|
41 | 39 |
use SL::AR; |
42 | 40 |
use SL::Controller::Base; |
... | ... | |
49 | 47 |
use SL::DB::Currency; |
50 | 48 |
use SL::DB::Default; |
51 | 49 |
use SL::DB::Employee; |
52 |
use SL::DB::Invoice; |
|
53 | 50 |
use SL::DB::Manager::Invoice; |
54 | 51 |
use SL::DB::InvoiceItem; |
55 | 52 |
use SL::DB::RecordTemplate; |
... | ... | |
62 | 59 |
use SL::Presenter::Chart; |
63 | 60 |
use SL::Presenter::ItemsList; |
64 | 61 |
use SL::ReportGenerator; |
65 |
use SL::File::Object; |
|
66 |
use SL::DB::Manager::File; |
|
67 |
use SL::File::Backend::Filesystem; |
|
68 |
use SL::Webdav; |
|
69 |
use SL::File::Backend::Webdav; |
|
70 | 62 |
|
71 | 63 |
require "bin/mozilla/common.pl"; |
72 | 64 |
require "bin/mozilla/reportgenerator.pl"; |
... | ... | |
1032 | 1024 |
action => [ $::locale->text('PDF-Export') ], |
1033 | 1025 |
action => [ |
1034 | 1026 |
t8('WebDAV'), |
1035 |
submit => [ '#report_form', { action => 'webdav_pdf_export' } ], |
|
1027 |
submit => [ '#report_form', { action => 'Invoice/webdav_pdf_export' } ],
|
|
1036 | 1028 |
checks => [ ['kivi.check_if_entries_selected', '[name="id[]"]'] ], |
1037 | 1029 |
disabled => !$webdav_enabled ? t8('WebDAV is not enabled.') |
1038 | 1030 |
: undef, |
1039 | 1031 |
], |
1040 | 1032 |
action => [ |
1041 | 1033 |
t8('Documents'), |
1042 |
submit => [ '#report_form', { action => 'files_pdf_export' } ], |
|
1034 |
submit => [ '#report_form', { action => 'Invoice/files_pdf_export' } ],
|
|
1043 | 1035 |
checks => [ ['kivi.check_if_entries_selected', '[name="id[]"]'] ], |
1044 | 1036 |
disabled => !$files_enabled ? t8('No File Management enabled.') |
1045 | 1037 |
: undef, |
... | ... | |
1656 | 1648 |
$::request->layout->add_javascripts('kivi.Validator.js'); |
1657 | 1649 |
} |
1658 | 1650 |
|
1659 |
sub _check_access_right_for_ids { |
|
1660 |
my ($ids) = @_; |
|
1661 |
$main::lxdebug->enter_sub(); |
|
1662 |
|
|
1663 |
my $form = Form->new; |
|
1664 |
AR->ar_transactions(\%::myconfig, \%$form); |
|
1665 |
my %allowed_ids = (); |
|
1666 |
|
|
1667 |
my @allowed_ar_ids = map {$_->{id}} @{$form->{AR}}; |
|
1668 |
foreach my $ar_id (@allowed_ar_ids) { |
|
1669 |
$allowed_ids{$ar_id} = 1 ; |
|
1670 |
} |
|
1671 |
foreach my $id (@$ids) { |
|
1672 |
unless ($allowed_ids{$id}) { |
|
1673 |
$::auth->deny_access(); |
|
1674 |
} |
|
1675 |
} |
|
1676 |
|
|
1677 |
$main::lxdebug->leave_sub(); |
|
1678 |
} |
|
1679 |
|
|
1680 |
sub webdav_pdf_export { |
|
1681 |
$main::lxdebug->enter_sub(); |
|
1682 |
|
|
1683 |
my $form = $main::form; |
|
1684 |
my $ids = $form->{id}; |
|
1685 |
|
|
1686 |
_check_access_right_for_ids($ids); |
|
1687 |
|
|
1688 |
my $invoices = SL::DB::Manager::Invoice->get_all(where => [ id => $ids ]); |
|
1689 |
|
|
1690 |
my @file_names_and_file_paths; |
|
1691 |
my @errors; |
|
1692 |
foreach my $invoice (@{$invoices}) { |
|
1693 |
my $record_type = $invoice->record_type; |
|
1694 |
$record_type = 'general_ledger' if $record_type eq 'ar_transaction'; |
|
1695 |
$record_type = 'invoice' if $record_type eq 'invoice_storno'; |
|
1696 |
my $webdav = SL::Webdav->new( |
|
1697 |
type => $record_type, |
|
1698 |
number => $invoice->record_number, |
|
1699 |
); |
|
1700 |
my @latest_object = $webdav->get_all_latest(); |
|
1701 |
unless (scalar @latest_object) { |
|
1702 |
push @errors, t8( |
|
1703 |
"No Dokument found for record '#1'. Please deselect it or create a document it.", |
|
1704 |
$invoice->displayable_name() |
|
1705 |
); |
|
1706 |
next; |
|
1707 |
} |
|
1708 |
push @file_names_and_file_paths, { |
|
1709 |
file_name => $latest_object[0]->basename . "." . $latest_object[0]->extension, |
|
1710 |
file_path => $latest_object[0]->full_filedescriptor(), |
|
1711 |
} |
|
1712 |
} |
|
1713 |
|
|
1714 |
if (scalar @errors) { |
|
1715 |
die join("\n", @errors); |
|
1716 |
} |
|
1717 |
_create_and_send_zip(\@file_names_and_file_paths); |
|
1718 |
|
|
1719 |
$main::lxdebug->leave_sub(); |
|
1720 |
} |
|
1721 |
|
|
1722 |
sub files_pdf_export { |
|
1723 |
$main::lxdebug->enter_sub(); |
|
1724 |
|
|
1725 |
my $form = $main::form; |
|
1726 |
my $ids = $form->{id}; |
|
1727 |
|
|
1728 |
_check_access_right_for_ids($ids); |
|
1729 |
|
|
1730 |
my $invoices = SL::DB::Manager::Invoice->get_all(where => [ id => $ids ]); |
|
1731 |
|
|
1732 |
my @file_names_and_file_paths; |
|
1733 |
my @errors; |
|
1734 |
foreach my $invoice (@{$invoices}) { |
|
1735 |
my $record_type = $invoice->record_type; |
|
1736 |
$record_type = 'invoice' if $record_type eq 'ar_transaction'; |
|
1737 |
$record_type = 'invoice' if $record_type eq 'invoice_storno'; |
|
1738 |
my @file_entries = @{SL::DB::Manager::File->get_all( |
|
1739 |
where => [ |
|
1740 |
object_type => $record_type, |
|
1741 |
object_id => $invoice->id, |
|
1742 |
file_type => 'document', |
|
1743 |
source => 'created', |
|
1744 |
], |
|
1745 |
)}; |
|
1746 |
|
|
1747 |
unless (scalar @file_entries) { |
|
1748 |
push @errors, t8( |
|
1749 |
"No Dokument found for record '#1'. Please deselect it or create a document it.", |
|
1750 |
$invoice->displayable_name() |
|
1751 |
); |
|
1752 |
next; |
|
1753 |
} |
|
1754 |
foreach my $file_entry (@file_entries) { |
|
1755 |
my $file = SL::File::Object->new( |
|
1756 |
db_file => $file_entry, |
|
1757 |
id => $file_entry->id, |
|
1758 |
loaded => 1, |
|
1759 |
); |
|
1760 |
eval { |
|
1761 |
push @file_names_and_file_paths, { |
|
1762 |
file_name => $file->file_name, |
|
1763 |
file_path => $file->get_file(), |
|
1764 |
}; |
|
1765 |
} or do { |
|
1766 |
push @errors, $@, |
|
1767 |
}; |
|
1768 |
} |
|
1769 |
} |
|
1770 |
|
|
1771 |
if (scalar @errors) { |
|
1772 |
die join("\n", @errors); |
|
1773 |
} |
|
1774 |
_create_and_send_zip(\@file_names_and_file_paths); |
|
1775 |
|
|
1776 |
$main::lxdebug->leave_sub(); |
|
1777 |
} |
|
1778 |
|
|
1779 |
sub _create_and_send_zip { |
|
1780 |
$main::lxdebug->enter_sub(); |
|
1781 |
my ($file_names_and_file_paths) = validate_pos(@_, { |
|
1782 |
type => ARRAYREF, |
|
1783 |
callbacks => { |
|
1784 |
"has 'file_name' and 'file_path'" => sub { |
|
1785 |
foreach my $file_entry (@{$_[0]}) { |
|
1786 |
return 0 unless defined $file_entry->{file_name} |
|
1787 |
&& defined $file_entry->{file_path}; |
|
1788 |
} |
|
1789 |
return 1; |
|
1790 |
} |
|
1791 |
} |
|
1792 |
}); |
|
1793 |
|
|
1794 |
my ($fh, $zipfile) = File::Temp::tempfile(); |
|
1795 |
my $zip = Archive::Zip->new(); |
|
1796 |
foreach my $file (@{$file_names_and_file_paths}) { |
|
1797 |
$zip->addFile($file->{file_path}, $file->{file_name}); |
|
1798 |
} |
|
1799 |
$zip->writeToFileHandle($fh) == Archive::Zip::AZ_OK() or die 'error writing zip file'; |
|
1800 |
close($fh); |
|
1801 |
|
|
1802 |
my $controller = SL::Controller::Base->new; |
|
1803 |
|
|
1804 |
$controller->send_file( |
|
1805 |
$zipfile, |
|
1806 |
name => t8('pdf_records.zip'), unlink => 1, |
|
1807 |
type => 'application/zip', |
|
1808 |
); |
|
1809 |
|
|
1810 |
$main::lxdebug->leave_sub(); |
|
1811 |
} |
|
1812 |
|
|
1813 |
|
|
1814 | 1651 |
1; |
templates/design40_webpages/ar/ar_transactions_header.html | ||
---|---|---|
1 |
<form method="post" action="ar.pl" id="report_form"> |
|
1 |
<form method="post" action="controller.pl" id="report_form"> |
templates/webpages/ar/ar_transactions_header.html | ||
---|---|---|
1 |
<form method="post" action="ar.pl" id="report_form"> |
|
1 |
<form method="post" action="controller.pl" id="report_form"> |
Auch abrufbar als: Unified diff
FIX: Verschiebe PDF-Export für VK-Rechnungen in neuen Controller