Revision ba929776
Von Johannes Grassler vor etwa 1 Jahr hinzugefügt
bin/mozilla/ap.pl | ||
---|---|---|
56 | 56 |
use SL::DB::ValidityToken; |
57 | 57 |
use SL::Presenter::ItemsList; |
58 | 58 |
use SL::Webdav; |
59 |
use SL::ZUGFeRD; |
|
59 | 60 |
use SL::Locale::String qw(t8); |
60 | 61 |
|
61 | 62 |
require "bin/mozilla/common.pl"; |
... | ... | |
109 | 110 |
$::form->show_generic_error($::locale->text("You do not have the permissions to access this function.")) if ! $cache->{_may_view_or_edit_this_invoice}; |
110 | 111 |
} |
111 | 112 |
|
113 |
sub load_zugferd { |
|
114 |
$::auth->assert('ap_transactions'); |
|
115 |
|
|
116 |
my $data; # buffer for holding file contents |
|
117 |
|
|
118 |
my $form_defaults = $::form->{form_defaults}; |
|
119 |
my $file = SL::SessionFile->new($form_defaults->{zugferd_session_file}, mode => '<'); |
|
120 |
my $file_name = $file->file_name; |
|
121 |
|
|
122 |
$::form->{$_} = $form_defaults->{$_} for keys %{ $form_defaults // {} }; |
|
123 |
|
|
124 |
# Defaults |
|
125 |
$::form->{title} = "Add"; |
|
126 |
$::form->{paidaccounts} = 1; |
|
127 |
|
|
128 |
$file->open('<'); |
|
129 |
if ( ! defined($file->fh->read($data, -s $file->fh)) ) { |
|
130 |
SL::Helper::Flash::flash_later('error', |
|
131 |
t8('Could not open ZUGFeRD file for reading: #1', $!)); |
|
132 |
} else { |
|
133 |
|
|
134 |
my %res; # result data structure returned by SL::ZUGFeRD->extract_from_{pdf,xml}() |
|
135 |
my $parser; # SL::XMLInvoice object created by SL::ZUGFeRD->extract_from_{pdf,xml}() |
|
136 |
my $template_ap; # SL::DB::RecordTemplate object |
|
137 |
my $vendor; # SL::DB::Vendor object |
|
138 |
my %metadata; # structured data extracted from XML payload |
|
139 |
my @items; # list of invoice items |
|
140 |
my $default_ap_amount_chart; |
|
141 |
|
|
142 |
if ( $data =~ m/^%PDF/ ) { |
|
143 |
%res = %{SL::ZUGFeRD->extract_from_pdf($data)}; |
|
144 |
} else { |
|
145 |
%res = %{SL::ZUGFeRD->extract_from_xml($data)}; |
|
146 |
} |
|
147 |
|
|
148 |
|
|
149 |
$parser = $res{'invoice_xml'}; |
|
150 |
%metadata = %{$parser->metadata}; |
|
151 |
@items = @{$parser->items}; |
|
152 |
|
|
153 |
$default_ap_amount_chart = SL::DB::Manager::Chart->find_by(charttype => 'A'); |
|
154 |
|
|
155 |
my $row = 0; |
|
156 |
foreach my $i (@items) { |
|
157 |
$row++; |
|
158 |
|
|
159 |
my %item = %{$i}; |
|
160 |
|
|
161 |
my $net_total = $::form->format_amount(\%::myconfig, $item{'subtotal'}, 2); |
|
162 |
my $desc = $item{'description'}; |
|
163 |
my $tax_rate = $item{'tax_rate'} / 100; # XML data is usually in percent |
|
164 |
|
|
165 |
my $taxes = SL::DB::Manager::Tax->get_all( |
|
166 |
where => [ |
|
167 |
chart_categories => { like => '%' . $default_ap_amount_chart->category . '%' }, |
|
168 |
rate => $tax_rate, |
|
169 |
], |
|
170 |
); |
|
171 |
|
|
172 |
# If we really can't find any tax definition (a simple rounding error may |
|
173 |
# be sufficient for that to happen), grab the first tax fitting the default |
|
174 |
# AP amount chart, just like the AP form would do it for manual entry. |
|
175 |
if ( scalar @{$taxes} == 0 ) { |
|
176 |
$taxes = SL::DB::Manager::Tax->get_all( |
|
177 |
where => [ chart_categories => { like => '%' . $default_ap_amount_chart->category . '%' } ], |
|
178 |
); |
|
179 |
} |
|
180 |
|
|
181 |
my $tax = ${$taxes}[0]; |
|
182 |
|
|
183 |
if (!$tax) { |
|
184 |
$row--; |
|
185 |
next; |
|
186 |
} |
|
187 |
|
|
188 |
$::form->{"AP_amount_chart_id_${row}"} = $default_ap_amount_chart->id; # FIXME: add heuristic for picking a better one |
|
189 |
$::form->{"previous_AP_amount_chart_id_${row}"} = $default_ap_amount_chart->id; # FIXME: add heuristic for picking a better one |
|
190 |
$::form->{"amount_${row}"} = $net_total; |
|
191 |
$::form->{"taxchart_${row}"} = $tax->id . '--' . $tax->rate; |
|
192 |
} |
|
193 |
|
|
194 |
flash('info', $::locale->text("The ZUGFeRD/Factur-X invoice '#1' has been loaded.", $file_name)); |
|
195 |
|
|
196 |
$::form->{form_validity_token} = SL::DB::ValidityToken->create(scope => SL::DB::ValidityToken::SCOPE_PURCHASE_INVOICE_POST())->token; |
|
197 |
$::form->{rowcount} = $row; |
|
198 |
|
|
199 |
update( |
|
200 |
keep_rows_without_amount => 1, |
|
201 |
dont_add_new_row => 1, |
|
202 |
); |
|
203 |
} |
|
204 |
} |
|
205 |
|
|
112 | 206 |
sub load_record_template { |
113 | 207 |
$::auth->assert('ap_transactions'); |
114 | 208 |
|
Auch abrufbar als: Unified diff
ZUGFeRD: Importiere via SessionFile
Benutze das SessionFile aus
um die strukturierten Daten der ZUGFeRD/Faktur-X-Rechnung in
das Formular fuer die Kreditorenbuchung zu uebertragen. Diese
Loesung ist deutlich eleganter als die bisherige, die fuer
jeden Import ein RecordTemplate erzeugte und es nach dem
Import in der Datenbank beliess.