06f62213c089f5d94e7abe1afb053edf4a4301bc
[kivitendo-erp.git] / SL / Controller / DownloadZip.pm
1 package SL::Controller::DownloadZip;
2
3 use strict;
4
5 use parent qw(SL::Controller::Base);
6
7 use List::Util qw(first max);
8
9 use utf8;
10 use Encode qw(decode encode);
11 use Archive::Zip;
12 use SL::File;
13 use SL::SessionFile::Random;
14
15 sub action_download_orderitems_files {
16   my ($self) = @_;
17
18   #
19   # special case for customer which want to have not all
20   # in kivitendo.conf some regex may be defined:
21   # For no values just let it commented out
22   # PA = Produktionsauftrag, L = Lieferschein, ML = Materialliste
23   # If you want several options, please seperate the letter with '|'. Example: '^(PA|L).*'
24   #set_sales_documenttype_for_delivered_quantity = '^(LS).*'
25   #set_purchase_documenttype_for_delivered_quantity = '^(EL).*'
26   #
27   # enbale this perl code:
28   #  my $doctype = $::lx_office_conf{system}->{"set_documenttype_for_part_zip_download"};
29   #  if ( $doctype ) {
30   #    # eliminate first and last char (are quotes)
31   #    $doctype =~ s/^.//;
32   #    $doctype =~ s/.$//;
33   #  }
34
35   #$Archive::Zip::UNICODE = 1;
36
37   my $object_id    = $::form->{object_id};
38   my $object_type  = $::form->{object_type};
39   my $element_type = $::form->{element_type};
40   my $sfile = SL::SessionFile::Random->new(mode => "w");
41   my $zip = Archive::Zip->new();
42   #TODO Check client encoding !!
43   #my $name_encoding = 'cp850';
44   my $name_encoding = 'UTF-8';
45
46   # today only sales_order implementation !
47   if ( $object_id && $object_type eq 'sales_order' && $element_type eq 'part' ) {
48     my $orderitems = SL::DB::Manager::OrderItem->get_all(query => ['order.id' => $object_id ],
49                                                          with_objects => [ 'order', 'part' ],
50                                                          sort_by => 'part.partnumber ASC');
51     my $part_id = 0;
52     foreach my $item ( @{$orderitems} ) {
53       next if $part_id == $item->parts_id;
54
55       my @files = SL::File->get_all(object_id   => $item->parts_id,
56                                     object_type => $element_type,
57                                   );
58       my @wanted_files;
59       ## also for filtering if needed:
60       # if ( $doctype ) {
61       #   @wanted_files = grep { $_->{file_name} =~ /$doctype/ } @files;
62       # } else {
63       @wanted_files = @files;
64       # }
65       if ( scalar (@wanted_files) > 0 ) {
66         $zip->addDirectory($item->part->partnumber);
67         $zip->addFile($_->get_file ), Encode::encode($name_encoding,$item->part->partnumber.'/'.$_->file_name)) for @wanted_files;
68       }
69     }
70   }
71   unless ( $zip->writeToFileNamed($sfile->file_name) == Archive::Zip::AZ_OK ) {
72     die 'zipfile write error';
73   }
74   $sfile->fh->close;
75
76   return $self->send_file(
77     $sfile->file_name,
78     type => 'application/zip',
79     name => $::form->{zipname}.'.zip',
80   );
81 }
82
83 1;
84
85 __END__
86
87 =pod
88
89 =encoding utf-8
90
91 =head1 NAME
92
93 SL::Controller::DownloadZip - controller for download all files from parts of an order in one zip file
94
95 =head2  C<action_download_zip FORMPARAMS>
96
97 Some customer want all attached files for the parts of an sales order or sales delivery order in one zip to download.
98 This is a special method for one customer, so it is moved into an extra controller.
99 The $Archive::Zip::UNICODE = 1; doesnt work ok
100 So today the filenames in cp850/DOS format for legacy windows.
101 To ues it for Linux Clients an additinal effort must be done,
102 for ex. a link to the same file with an utf-8 name.
103
104 There is also a special javascript method necessary which calles this controller method.
105 THis method must be inserted into the customer branch:
106
107 =begin text
108
109   ns.downloadOrderitemsAtt = function(type,id) {
110     var rowcount  = $('input[name=rowcount]').val() - 1;
111           var data = {
112         action:     'FileManagement/download_zip',
113         type:       type,
114         object_id:  id,
115         rowcount:   rowcount
116     };
117     if ( rowcount == 0 ) {
118         kivi.display_flash('error', kivi.t8('No articles have been added yet.'));
119         return false;
120     }
121     for (var i = 1; i <= rowcount; i++) {
122         data['parts_id_'+i] =  $('#id_' + i).val();
123     };
124     $.download("controller.pl", data);
125     return false;
126   }
127
128 =end text
129
130 See also L<SL::Controller::FileManagement>
131
132 =head1 DISCUSSION
133
134 Is this method needed in the master branch ?
135
136 =head1 AUTHOR
137
138 Martin Helmling E<lt>martin.helmling@opendynamic.deE<gt>
139
140 =cut