Skip to content

Commit

Permalink
FIX: S:H:EmailProcessing: automatischer ZUGFeRD-Import
Browse files Browse the repository at this point in the history
  • Loading branch information
z4m1n0 committed Nov 30, 2023
1 parent b518d7b commit ef2af60
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 31 deletions.
71 changes: 45 additions & 26 deletions SL/DB/Helper/ZUGFeRD.pm
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use utf8;

use parent qw(Exporter);
our @EXPORT_CREATE = qw(create_zugferd_data create_zugferd_xmp_data);
our @EXPORT_IMPORT = qw(import_zugferd_xml);
our @EXPORT_IMPORT = qw(import_zugferd_data);
our @EXPORT_OK = (@EXPORT_CREATE, @EXPORT_IMPORT);
our %EXPORT_TAGS = (
ALL => (@EXPORT_CREATE, @EXPORT_IMPORT),
Expand All @@ -15,6 +15,7 @@ our %EXPORT_TAGS = (

use SL::DB::BankAccount;
use SL::DB::GenericTranslation;
use SL::DB::Chart;
use SL::DB::Tax;
use SL::DB::TaxKey;
use SL::DB::RecordTemplate;
Expand Down Expand Up @@ -719,7 +720,7 @@ sub import_zugferd_data {
my %metadata = %{$parser->metadata};
my @items = @{$parser->items};

my $notes = t8("ZUGFeRD Import. Type: #1", $metadata{'type'});
my $intnotes = t8("ZUGFeRD Import. Type: #1", $metadata{'type'})->translated;
my $iban = $metadata{'iban'};
my $invnumber = $metadata{'invnumber'};

Expand All @@ -739,12 +740,12 @@ sub import_zugferd_data {

# Check IBAN specified on bill matches the one we've got in
# the database for this vendor.
if ($iban) {
$notes .= "\nIBAN: ";
$notes .= $iban ne $vendor->iban ?
t8("Record IBAN #1 doesn't match vendor IBAN #2", $iban, $vendor->iban)
: $iban
}
if ($iban) {
$intnotes .= "\nIBAN: ";
$intnotes .= $iban ne $vendor->iban ?
t8("Record IBAN #1 doesn't match vendor IBAN #2", $iban, $vendor->iban)
: $iban
}

# Use invoice creation date as due date if there's no due date
$metadata{'duedate'} = $metadata{'transdate'} unless defined $metadata{'duedate'};
Expand All @@ -763,14 +764,15 @@ sub import_zugferd_data {

# Try to fill in AP account to book against
my $ap_chart_id = $::instance_conf->get_ap_chart_id;
my $ap_chart = SL::DB::Manager::Chart->find_by(id => $ap_chart_id);

unless ( defined $ap_chart_id ) {
unless ( defined $ap_chart ) {
# If no default account is configured, just use the first AP account found.
my $ap_chart = SL::DB::Manager::Chart->get_all(
my $ap_charts = SL::DB::Manager::Chart->get_all(
where => [ link => 'AP' ],
sort_by => [ 'accno' ],
);
$ap_chart_id = ${$ap_chart}[0]->id;
$ap_chart = ${$ap_charts}[0];
}

my $currency = SL::DB::Manager::Currency->find_by(
Expand All @@ -783,7 +785,7 @@ sub import_zugferd_data {
# Fallback if there's no default AP amount chart configured
$default_ap_amount_chart ||= SL::DB::Manager::Chart->find_by(charttype => 'A');

my $active_taxkey = $default_ap_amount_chart->taxkey_id;
my $active_taxkey = $default_ap_amount_chart->get_active_taxkey;
my $taxes = SL::DB::Manager::Tax->get_all(
where => [ chart_categories => {
like => '%' . $default_ap_amount_chart->category . '%'
Expand All @@ -794,6 +796,15 @@ sub import_zugferd_data {
"No tax found for chart #1", $default_ap_amount_chart->displayable_name
) unless scalar @{$taxes};

my %template_params;
my $template_ap = SL::DB::Manager::RecordTemplate->get_first(where => [vendor_id => $vendor->id]);
if ($template_ap) {
$template_params{globalproject_id} = $template_ap->globalproject_id;
$template_params{payment_id} = $template_ap->payment_id;
$template_params{department_id} = $template_ap->department_id;
$template_params{ordnumber} = $template_ap->ordnumber;
$template_params{transaction_description} = $template_ap->transaction_description;
}

my $today = DateTime->today_local;
my %params = (
Expand All @@ -802,17 +813,13 @@ sub import_zugferd_data {
taxzone_id => $vendor->taxzone_id,
currency_id => $currency->id,
direct_debit => $metadata{'direct_debit'},
# globalproject_id => $template_ap->project_id,
# payment_id => $template_ap->payment_id,
invnumber => $invnumber,
transdate => $metadata{transdate} || $today->to_kivitendo,
duedate => $metadata{duedate} || $today->to_kivitendo,
# department_id => $template_ap->department_id,
# ordnumber => $template_ap->ordnumber,
taxincluded => 0,
notes => $notes,
intnotes => $intnotes,
transactions => [],
# transaction_description => $template_ap->transaction_description,
%template_params,
);

$self->assign_attributes(%params);
Expand All @@ -821,26 +828,38 @@ sub import_zugferd_data {
foreach my $i (@items) {
my %item = %{$i};

my $net_total = $::form->format_amount(\%::myconfig, $item{'subtotal'}, 2);
my $net_total = $item{'subtotal'};

# set default values for items
my ($tax, $chart, $project_id);
if ($template_ap) {
my $template_item = $template_ap->items->[0];
$tax = SL::DB::Tax->new(id => $template_item->tax_id)->load();
$chart = SL::DB::Chart->new(id => $template_item->chart_id)->load();
$project_id = $template_item->project_id;
} else {

my $tax_rate = $item{'tax_rate'};
$tax_rate /= 100 if $tax_rate > 1; # XML data is usually in percent
my $tax_rate = $item{'tax_rate'};
$tax_rate /= 100 if $tax_rate > 1; # XML data is usually in percent

my $tax = first { $tax_rate == $_->rate } @{ $taxes };
$tax //= first { $active_taxkey->tax_id == $_->id } @{ $taxes };
$tax //= $taxes->[0];
$tax = first { $tax_rate == $_->rate } @{ $taxes };
$tax //= first { $active_taxkey->tax_id == $_->id } @{ $taxes };
$tax //= $taxes->[0];

$chart = $default_ap_amount_chart;
}

my %line_params = (
amount => $net_total,
tax_id => $tax->id,
chart => $default_ap_amount_chart->chart,
chart => $chart,
);

$self->add_ap_amount_row(%line_params);
}
$self->recalculate_amounts();

$self->create_ap_row(chart => $default_ap_amount_chart);
$self->create_ap_row(chart => $ap_chart);

return $self;
}
Expand Down
11 changes: 6 additions & 5 deletions SL/Helper/EmailProcessing.pm
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,15 @@ sub process_attachments_zugferd {

my $purchase_invoice;
eval {
$purchase_invoice = SL::DB::PurchaseInvoice->create_from_zugferd_xml(\%res)->save();
$purchase_invoice = SL::DB::PurchaseInvoice->create_from_zugferd_data(\%res)->save();
1;
} or do {
my $error = $@;
$email_journal->extended_status(
join "\n", $email_journal->extended_status,
"Error processing ZUGFeRD attachment $name: $error"
)->save;
$email_journal->update_attributes(
extended_status =>
join "\n", $email_journal->extended_status,
"Error processing ZUGFeRD attachment $name: $error"
);
return 0;
};

Expand Down

0 comments on commit ef2af60

Please sign in to comment.