Revision 6aa3c3ea
Von Tamino Steinert vor 11 Monaten hinzugefügt
SL/Controller/EmailJournal.pm | ||
---|---|---|
265 | 265 |
$cv_type_found = 'vendor' if $self->entry->record_type eq 'ap_transaction'; |
266 | 266 |
$self->render( |
267 | 267 |
'email_journal/show', |
268 |
title => $::locale->text('View email'), |
|
269 |
CUSTOMER_VENDOR => , $customer_vendor,
|
|
270 |
CV_TYPE_FOUND => $cv_type_found, |
|
268 |
title => $::locale->text('View email'),
|
|
269 |
CUSTOMER_VENDOR => $customer_vendor,
|
|
270 |
CV_TYPE_FOUND => $cv_type_found,
|
|
271 | 271 |
RECORD_TYPES_WITH_INFO => \@record_types_with_info, |
272 | 272 |
RECORD_TYPES_TO_TEXT => \%record_types_to_text, |
273 | 273 |
back_to => $back_to, |
... | ... | |
399 | 399 |
|
400 | 400 |
sub action_zugferd_import_with_attachment { |
401 | 401 |
my ($self) = @_; |
402 |
|
|
403 |
my $email_journal_id = $::form->{email_journal_id}; |
|
404 |
my $attachment_id = $::form->{attachment_id}; |
|
405 |
|
|
402 |
my $email_journal_id = $::form->{email_journal_id}; |
|
403 |
my $attachment_id = $::form->{attachment_id}; |
|
406 | 404 |
die "no 'email_journal_id' was given" unless $email_journal_id; |
407 |
die "no 'attachment_id' was given" unless $attachment_id;
|
|
405 |
die t8("No attachment is selected") unless $attachment_id;
|
|
408 | 406 |
|
407 |
my $record_id = $::form->{"record_id"}; |
|
408 |
my $record_type = $::form->{"record_type"}; |
|
409 |
die "ZUGFeRD-Import only implemented for ap transaction templates" unless $record_type == 'ap_transaction'; |
|
409 | 410 |
my $attachment = SL::DB::EmailJournalAttachment->new(id => $attachment_id)->load(); |
410 | 411 |
|
411 | 412 |
my $content = $attachment->content; # scalar ref |
... | ... | |
423 | 424 |
die(t8("Could not extract Factur-X/ZUGFeRD data, data and error message:") . " $res{'message'}"); |
424 | 425 |
} |
425 | 426 |
|
426 |
my $form_defaults = SL::Controller::ZUGFeRD->build_ap_transaction_form_defaults(\%res); |
|
427 |
my $vendor; |
|
428 |
if ($record_id) { |
|
429 |
my $ap_template = SL::DB::RecordTemplate->new(id => $record_id)->load(); |
|
430 |
$vendor = $ap_template->vendor; |
|
431 |
} |
|
432 |
|
|
433 |
my $form_defaults = SL::Controller::ZUGFeRD->build_ap_transaction_form_defaults(\%res, vendor => $vendor); |
|
427 | 434 |
$form_defaults->{email_journal_id} = $email_journal_id; |
428 | 435 |
$form_defaults->{email_attachment_id} = $attachment_id; |
429 | 436 |
$form_defaults->{callback} = $::form->{back_to}; |
... | ... | |
431 | 438 |
flash_later('info', |
432 | 439 |
t8("The ZUGFeRD/Factur-X invoice '#1' has been loaded.", $attachment->name)); |
433 | 440 |
$self->redirect_to( |
434 |
controller => 'ap.pl', |
|
435 |
action => 'load_zugferd', |
|
436 |
form_defaults => $form_defaults, |
|
441 |
controller => 'ap.pl', |
|
442 |
action => 'load_zugferd', |
|
443 |
record_template_id => $record_id, |
|
444 |
form_defaults => $form_defaults, |
|
437 | 445 |
); |
438 | 446 |
} |
439 | 447 |
|
... | ... | |
447 | 455 |
id => $attachment_id, |
448 | 456 |
)->load if $attachment_id; |
449 | 457 |
|
450 |
$self->js->hide('#zugferd_import_div'); |
|
451 |
if ($attachment && $attachment->content =~ m/^%PDF|<\?xml/) { |
|
452 |
my $content = $attachment->content; |
|
453 |
my %res; |
|
454 |
if ( $content =~ m/^%PDF/ ) { |
|
455 |
%res = %{SL::ZUGFeRD->extract_from_pdf($content)}; |
|
456 |
} else { |
|
457 |
%res = %{SL::ZUGFeRD->extract_from_xml($content)}; |
|
458 |
} |
|
459 |
if ($res{'result'} == SL::ZUGFeRD::RES_OK()) { |
|
460 |
$self->js->show('#zugferd_import_div'); |
|
461 |
} |
|
462 |
} |
|
463 |
|
|
464 | 458 |
$self->js |
465 | 459 |
->replaceWith('#attachment_preview', |
466 | 460 |
SL::Presenter::EmailJournal::attachment_preview( |
SL/Controller/ZUGFeRD.pm | ||
---|---|---|
161 | 161 |
} |
162 | 162 |
|
163 | 163 |
sub build_ap_transaction_form_defaults { |
164 |
my ($self, $data) = @_; |
|
164 |
my ($self, $data, %params) = @_; |
|
165 |
my $vendor = $params{vendor}; |
|
165 | 166 |
|
166 | 167 |
my $parser = $data->{'invoice_xml'}; |
167 | 168 |
|
... | ... | |
172 | 173 |
my $iban = $metadata{'iban'}; |
173 | 174 |
my $invnumber = $metadata{'invnumber'}; |
174 | 175 |
|
175 |
if ( ! ($metadata{'ustid'} or $metadata{'taxnumber'}) ) { |
|
176 |
die t8("Cannot process this invoice: neither VAT ID nor tax ID present."); |
|
177 |
} |
|
176 |
if ($vendor) { |
|
177 |
if ($metadata{'ustid'} && $vendor->ustid && ($metadata{'ustid'} ne $vendor->ustid)) { |
|
178 |
$intnotes .= "\n" . t8('USt-IdNr.') . ': ' |
|
179 |
. t8("Record VAT ID #1 doesn't match vendor VAT ID #2", $metadata{'ustid'}, $vendor->ustid); |
|
180 |
} |
|
181 |
if ($metadata{'taxnumber'} && $vendor->taxnumber && ($metadata{'taxnumber'} ne $vendor->taxnumber)) { |
|
182 |
$intnotes .= "\n" . t8("Tax Number") . ': ' |
|
183 |
. t8("Record tax ID #1 doesn't match vendor tax ID #2", $metadata{'taxnumber'}, $vendor->taxnumber); |
|
184 |
} |
|
185 |
} else { |
|
186 |
if ( ! ($metadata{'ustid'} or $metadata{'taxnumber'}) ) { |
|
187 |
die t8("Cannot process this invoice: neither VAT ID nor tax ID present."); |
|
188 |
} |
|
178 | 189 |
|
179 |
my $vendor = find_vendor($metadata{'ustid'}, $metadata{'taxnumber'});
|
|
190 |
$vendor = find_vendor($metadata{'ustid'}, $metadata{'taxnumber'});
|
|
180 | 191 |
|
181 |
die t8("Vendor with VAT ID (#1) and/or tax ID (#2) not found. Please check if the vendor " . |
|
182 |
"#3 exists and whether it has the correct tax ID/VAT ID." , |
|
183 |
$metadata{'ustid'}, |
|
184 |
$metadata{'taxnumber'}, |
|
185 |
$metadata{'vendor_name'}, |
|
186 |
) unless $vendor; |
|
192 |
die t8("Vendor with VAT ID (#1) and/or tax ID (#2) not found. Please check if the vendor " . |
|
193 |
"#3 exists and whether it has the correct tax ID/VAT ID." , |
|
194 |
$metadata{'ustid'}, |
|
195 |
$metadata{'taxnumber'}, |
|
196 |
$metadata{'vendor_name'}, |
|
197 |
) unless $vendor; |
|
198 |
} |
|
187 | 199 |
|
188 | 200 |
|
189 | 201 |
# Check IBAN specified on bill matches the one we've got in |
SL/Presenter/Record.pm | ||
---|---|---|
651 | 651 |
data => sub { |
652 | 652 |
my $id = $_[0]->id; |
653 | 653 |
my $record_type = $_[0]->record_type; |
654 |
is_escaped(button_tag( |
|
655 |
"kivi.EmailJournal.apply_action_with_attachment( |
|
656 |
'$id', '$record_type');", |
|
657 |
$::locale->text('Select'), |
|
658 |
)) |
|
654 |
if ($record_type eq 'ap_transaction' && ref $_[0] eq 'SL::DB::RecordTemplate') { |
|
655 |
return is_escaped( |
|
656 |
button_tag( |
|
657 |
"kivi.EmailJournal.apply_action_with_attachment( |
|
658 |
'$id', '$record_type');", |
|
659 |
$::locale->text('Select'), |
|
660 |
) |
|
661 |
. " " . |
|
662 |
button_tag( |
|
663 |
"kivi.EmailJournal.zugferd_import_with_attachment( |
|
664 |
'$id', '$record_type');", |
|
665 |
$::locale->text('Factur-X/ZUGFeRD import'), |
|
666 |
) |
|
667 |
); |
|
668 |
} else { |
|
669 |
return is_escaped(button_tag( |
|
670 |
"kivi.EmailJournal.apply_action_with_attachment( |
|
671 |
'$id', '$record_type');", |
|
672 |
$::locale->text('Select'), |
|
673 |
)); |
|
674 |
} |
|
659 | 675 |
}, |
660 | 676 |
}; |
661 | 677 |
} |
bin/mozilla/ap.pl | ||
---|---|---|
120 | 120 |
"The ZUGFeRD/Factur-X invoice '#1' has been loaded.", $file_name)); |
121 | 121 |
} |
122 | 122 |
|
123 |
my $template_ap = SL::DB::Manager::RecordTemplate->get_first(where => [vendor_id => $::form->{form_defaults}->{vendor_id}]); |
|
123 |
my $template_ap; |
|
124 |
$template_ap ||= SL::DB::RecordTemplate->new(id => $::form->{record_template_id})->load() |
|
125 |
if $::form->{record_template_id}; |
|
126 |
$template_ap ||= SL::DB::Manager::RecordTemplate->get_first(where => [vendor_id => $::form->{form_defaults}->{vendor_id}]) |
|
127 |
if $::form->{form_defaults}->{vendor_id}; |
|
124 | 128 |
if ($template_ap) { |
125 | 129 |
$::form->{id} = $template_ap->id; |
126 | 130 |
# set default values for items |
js/kivi.EmailJournal.js | ||
---|---|---|
56 | 56 |
$.post("controller.pl", data, kivi.eval_json_result); |
57 | 57 |
} |
58 | 58 |
|
59 |
ns.zugferd_import_with_attachment = function() { |
|
59 |
ns.zugferd_import_with_attachment = function(record_id, record_type) {
|
|
60 | 60 |
let data = $('#record_action_form').serializeArray(); |
61 | 61 |
data.push({ name: 'action', value: 'EmailJournal/zugferd_import_with_attachment' }); |
62 |
data.push({ name: 'record_id', value: record_id }); |
|
63 |
data.push({ name: 'record_type', value: record_type }); |
|
64 |
|
|
62 | 65 |
$.post("controller.pl", data, kivi.eval_json_result); |
63 | 66 |
} |
64 | 67 |
|
locale/de/all | ||
---|---|---|
2482 | 2482 |
'No articles have been added yet.' => 'Es wurden noch keine Artikel hinzugefügt.', |
2483 | 2483 |
'No assembly has been selected yet.' => 'Es wurde noch kein Erzeugnis ausgewahlt.', |
2484 | 2484 |
'No attachment' => 'Kein Anhang', |
2485 |
'No attachment is selected' => 'Kein Anhang ausgewählt', |
|
2485 | 2486 |
'No background job has been created yet.' => 'Es wurden noch keine Hintergrund-Jobs angelegt.', |
2486 | 2487 |
'No bank account chosen!' => 'Kein Bankkonto ausgewählt!', |
2487 | 2488 |
'No bank account configured for bank code/BIC #1, account number/IBAN #2.' => 'Kein Bankkonto für BLZ/BIC #1, Kontonummer/IBAN #2 konfiguriert.', |
... | ... | |
3195 | 3196 |
'Reconciliation with bank' => 'Kontenabgleich mit Bank', |
3196 | 3197 |
'Record IBAN #1 doesn\'t match vendor IBAN #2' => 'Beleg IBAN #1 stimmt nicht mit Lieferanten IBAN #2 überein', |
3197 | 3198 |
'Record Type' => 'Belegtyp', |
3199 |
'Record VAT ID #1 doesn\'t match vendor VAT ID #2' => 'Beleg USt-IdNr. #1 stimmt nicht mit Lieferanten USt-IdNr. #2 überein', |
|
3198 | 3200 |
'Record Vendor Invoice' => 'Einkaufsrechnung erfassen', |
3199 | 3201 |
'Record in' => 'Buchen auf', |
3200 | 3202 |
'Record number' => 'Belegnummer', |
3201 | 3203 |
'Record numbers and dates' => 'Belegnummern & Datum', |
3202 | 3204 |
'Record numbers changeable' => 'Änderbarkeit von Belegnummern', |
3205 |
'Record tax ID #1 doesn\'t match vendor tax ID #2' => 'Beleg Steuernummer #1 stimmt nicht mit Lieferanten Steuernummer #2 überein', |
|
3203 | 3206 |
'Record templates' => 'Belegvorlagen', |
3204 | 3207 |
'Record type to create' => 'Anzulegender Belegtyp', |
3205 | 3208 |
'Record\'s files' => 'Belegdateien', |
locale/en/all | ||
---|---|---|
2481 | 2481 |
'No articles have been added yet.' => '', |
2482 | 2482 |
'No assembly has been selected yet.' => '', |
2483 | 2483 |
'No attachment' => '', |
2484 |
'No attachment is selected' => '', |
|
2484 | 2485 |
'No background job has been created yet.' => '', |
2485 | 2486 |
'No bank account chosen!' => '', |
2486 | 2487 |
'No bank account configured for bank code/BIC #1, account number/IBAN #2.' => '', |
... | ... | |
3194 | 3195 |
'Reconciliation with bank' => '', |
3195 | 3196 |
'Record IBAN #1 doesn\'t match vendor IBAN #2' => '', |
3196 | 3197 |
'Record Type' => '', |
3198 |
'Record VAT ID #1 doesn\'t match vendor VAT ID #2' => '', |
|
3197 | 3199 |
'Record Vendor Invoice' => '', |
3198 | 3200 |
'Record in' => '', |
3199 | 3201 |
'Record number' => '', |
3200 | 3202 |
'Record numbers and dates' => '', |
3201 | 3203 |
'Record numbers changeable' => '', |
3204 |
'Record tax ID #1 doesn\'t match vendor tax ID #2' => '', |
|
3202 | 3205 |
'Record templates' => '', |
3203 | 3206 |
'Record type to create' => '', |
3204 | 3207 |
'Record\'s files' => '', |
templates/design40_webpages/email_journal/show.html | ||
---|---|---|
173 | 173 |
</div> |
174 | 174 |
[% END %] |
175 | 175 |
|
176 |
<div id="zugferd_import_div" style="display:none"> |
|
177 |
<!-- get shown if the attachment is valid zugferd --> |
|
178 |
[% L.button_tag('kivi.EmailJournal.zugferd_import_with_attachment();', |
|
179 |
LxERP.t8('Factur-X/ZUGFeRD import'), |
|
180 |
style="margin-top:5px" |
|
181 |
) |
|
182 |
%] |
|
183 |
</div> |
|
184 |
|
|
185 | 176 |
</div></div> <!-- action_div --> |
186 | 177 |
|
187 | 178 |
<div id="record_selection_div"> |
... | ... | |
241 | 232 |
[% LxERP.t8('Hide Records') %] |
242 | 233 |
</a> |
243 | 234 |
<div class="toggle_panel_block"> |
244 |
<div id="record_list">LxERP.t8("Loading...")</div>
|
|
235 |
<div id="record_list">[% LxERP.t8("Loading...") %]</div>
|
|
245 | 236 |
</div> |
246 | 237 |
</div><!-- /.record_toggle --> |
247 | 238 |
</div><!-- record_div --> |
templates/webpages/email_journal/show.html | ||
---|---|---|
165 | 165 |
</div> |
166 | 166 |
</div> |
167 | 167 |
|
168 |
<div id="zugferd_import_div" style="display:none"> |
|
169 |
<!-- get shown if the attachment is valid zugferd --> |
|
170 |
[% L.button_tag('kivi.EmailJournal.zugferd_import_with_attachment();', |
|
171 |
LxERP.t8('Factur-X/ZUGFeRD import'), |
|
172 |
style="margin-top:5px" |
|
173 |
) |
|
174 |
%] |
|
175 |
</div> |
|
176 |
|
|
177 | 168 |
</tr> <tr> |
178 | 169 |
<td> |
179 | 170 |
<div id="record_selection_div"> |
... | ... | |
232 | 223 |
[% LxERP.t8('Hide Records') %] |
233 | 224 |
</a> |
234 | 225 |
<div class="toggle_panel_block"> |
235 |
<div id="record_list">LxERP.t8("Loading...")</div>
|
|
226 |
<div id="record_list">[% LxERP.t8("Loading...") %]</div>
|
|
236 | 227 |
</div> |
237 | 228 |
</div><!-- /.record_toggle --> |
238 | 229 |
</div><!-- record_div --> |
Auch abrufbar als: Unified diff
EmailJournal: ZUGFeRD-Import mit ausgewähter Buchungsvorlage