5 |
5 |
|
6 |
6 |
use parent qw(Exporter);
|
7 |
7 |
our @EXPORT_CREATE = qw(create_zugferd_data create_zugferd_xmp_data);
|
8 |
|
our @EXPORT_IMPORT = qw(import_zugferd_xml);
|
|
8 |
our @EXPORT_IMPORT = qw(import_zugferd_data);
|
9 |
9 |
our @EXPORT_OK = (@EXPORT_CREATE, @EXPORT_IMPORT);
|
10 |
10 |
our %EXPORT_TAGS = (
|
11 |
11 |
ALL => (@EXPORT_CREATE, @EXPORT_IMPORT),
|
... | ... | |
15 |
15 |
|
16 |
16 |
use SL::DB::BankAccount;
|
17 |
17 |
use SL::DB::GenericTranslation;
|
|
18 |
use SL::DB::Chart;
|
18 |
19 |
use SL::DB::Tax;
|
19 |
20 |
use SL::DB::TaxKey;
|
20 |
21 |
use SL::DB::RecordTemplate;
|
... | ... | |
719 |
720 |
my %metadata = %{$parser->metadata};
|
720 |
721 |
my @items = @{$parser->items};
|
721 |
722 |
|
722 |
|
my $notes = t8("ZUGFeRD Import. Type: #1", $metadata{'type'});
|
|
723 |
my $intnotes = t8("ZUGFeRD Import. Type: #1", $metadata{'type'})->translated;
|
723 |
724 |
my $iban = $metadata{'iban'};
|
724 |
725 |
my $invnumber = $metadata{'invnumber'};
|
725 |
726 |
|
... | ... | |
739 |
740 |
|
740 |
741 |
# Check IBAN specified on bill matches the one we've got in
|
741 |
742 |
# the database for this vendor.
|
742 |
|
if ($iban) {
|
743 |
|
$notes .= "\nIBAN: ";
|
744 |
|
$notes .= $iban ne $vendor->iban ?
|
745 |
|
t8("Record IBAN #1 doesn't match vendor IBAN #2", $iban, $vendor->iban)
|
746 |
|
: $iban
|
747 |
|
}
|
|
743 |
if ($iban) {
|
|
744 |
$intnotes .= "\nIBAN: ";
|
|
745 |
$intnotes .= $iban ne $vendor->iban ?
|
|
746 |
t8("Record IBAN #1 doesn't match vendor IBAN #2", $iban, $vendor->iban)
|
|
747 |
: $iban
|
|
748 |
}
|
748 |
749 |
|
749 |
750 |
# Use invoice creation date as due date if there's no due date
|
750 |
751 |
$metadata{'duedate'} = $metadata{'transdate'} unless defined $metadata{'duedate'};
|
... | ... | |
763 |
764 |
|
764 |
765 |
# Try to fill in AP account to book against
|
765 |
766 |
my $ap_chart_id = $::instance_conf->get_ap_chart_id;
|
|
767 |
my $ap_chart = SL::DB::Manager::Chart->find_by(id => $ap_chart_id);
|
766 |
768 |
|
767 |
|
unless ( defined $ap_chart_id ) {
|
|
769 |
unless ( defined $ap_chart ) {
|
768 |
770 |
# If no default account is configured, just use the first AP account found.
|
769 |
|
my $ap_chart = SL::DB::Manager::Chart->get_all(
|
|
771 |
my $ap_charts = SL::DB::Manager::Chart->get_all(
|
770 |
772 |
where => [ link => 'AP' ],
|
771 |
773 |
sort_by => [ 'accno' ],
|
772 |
774 |
);
|
773 |
|
$ap_chart_id = ${$ap_chart}[0]->id;
|
|
775 |
$ap_chart = ${$ap_charts}[0];
|
774 |
776 |
}
|
775 |
777 |
|
776 |
778 |
my $currency = SL::DB::Manager::Currency->find_by(
|
... | ... | |
783 |
785 |
# Fallback if there's no default AP amount chart configured
|
784 |
786 |
$default_ap_amount_chart ||= SL::DB::Manager::Chart->find_by(charttype => 'A');
|
785 |
787 |
|
786 |
|
my $active_taxkey = $default_ap_amount_chart->taxkey_id;
|
|
788 |
my $active_taxkey = $default_ap_amount_chart->get_active_taxkey;
|
787 |
789 |
my $taxes = SL::DB::Manager::Tax->get_all(
|
788 |
790 |
where => [ chart_categories => {
|
789 |
791 |
like => '%' . $default_ap_amount_chart->category . '%'
|
... | ... | |
794 |
796 |
"No tax found for chart #1", $default_ap_amount_chart->displayable_name
|
795 |
797 |
) unless scalar @{$taxes};
|
796 |
798 |
|
|
799 |
my %template_params;
|
|
800 |
my $template_ap = SL::DB::Manager::RecordTemplate->get_first(where => [vendor_id => $vendor->id]);
|
|
801 |
if ($template_ap) {
|
|
802 |
$template_params{globalproject_id} = $template_ap->globalproject_id;
|
|
803 |
$template_params{payment_id} = $template_ap->payment_id;
|
|
804 |
$template_params{department_id} = $template_ap->department_id;
|
|
805 |
$template_params{ordnumber} = $template_ap->ordnumber;
|
|
806 |
$template_params{transaction_description} = $template_ap->transaction_description;
|
|
807 |
}
|
797 |
808 |
|
798 |
809 |
my $today = DateTime->today_local;
|
799 |
810 |
my %params = (
|
... | ... | |
802 |
813 |
taxzone_id => $vendor->taxzone_id,
|
803 |
814 |
currency_id => $currency->id,
|
804 |
815 |
direct_debit => $metadata{'direct_debit'},
|
805 |
|
# globalproject_id => $template_ap->project_id,
|
806 |
|
# payment_id => $template_ap->payment_id,
|
807 |
816 |
invnumber => $invnumber,
|
808 |
817 |
transdate => $metadata{transdate} || $today->to_kivitendo,
|
809 |
818 |
duedate => $metadata{duedate} || $today->to_kivitendo,
|
810 |
|
# department_id => $template_ap->department_id,
|
811 |
|
# ordnumber => $template_ap->ordnumber,
|
812 |
819 |
taxincluded => 0,
|
813 |
|
notes => $notes,
|
|
820 |
intnotes => $intnotes,
|
814 |
821 |
transactions => [],
|
815 |
|
# transaction_description => $template_ap->transaction_description,
|
|
822 |
%template_params,
|
816 |
823 |
);
|
817 |
824 |
|
818 |
825 |
$self->assign_attributes(%params);
|
... | ... | |
821 |
828 |
foreach my $i (@items) {
|
822 |
829 |
my %item = %{$i};
|
823 |
830 |
|
824 |
|
my $net_total = $::form->format_amount(\%::myconfig, $item{'subtotal'}, 2);
|
|
831 |
my $net_total = $item{'subtotal'};
|
|
832 |
|
|
833 |
# set default values for items
|
|
834 |
my ($tax, $chart, $project_id);
|
|
835 |
if ($template_ap) {
|
|
836 |
my $template_item = $template_ap->items->[0];
|
|
837 |
$tax = SL::DB::Tax->new(id => $template_item->tax_id)->load();
|
|
838 |
$chart = SL::DB::Chart->new(id => $template_item->chart_id)->load();
|
|
839 |
$project_id = $template_item->project_id;
|
|
840 |
} else {
|
825 |
841 |
|
826 |
|
my $tax_rate = $item{'tax_rate'};
|
827 |
|
$tax_rate /= 100 if $tax_rate > 1; # XML data is usually in percent
|
|
842 |
my $tax_rate = $item{'tax_rate'};
|
|
843 |
$tax_rate /= 100 if $tax_rate > 1; # XML data is usually in percent
|
828 |
844 |
|
829 |
|
my $tax = first { $tax_rate == $_->rate } @{ $taxes };
|
830 |
|
$tax //= first { $active_taxkey->tax_id == $_->id } @{ $taxes };
|
831 |
|
$tax //= $taxes->[0];
|
|
845 |
$tax = first { $tax_rate == $_->rate } @{ $taxes };
|
|
846 |
$tax //= first { $active_taxkey->tax_id == $_->id } @{ $taxes };
|
|
847 |
$tax //= $taxes->[0];
|
|
848 |
|
|
849 |
$chart = $default_ap_amount_chart;
|
|
850 |
}
|
832 |
851 |
|
833 |
852 |
my %line_params = (
|
834 |
853 |
amount => $net_total,
|
835 |
854 |
tax_id => $tax->id,
|
836 |
|
chart => $default_ap_amount_chart->chart,
|
|
855 |
chart => $chart,
|
837 |
856 |
);
|
838 |
857 |
|
839 |
858 |
$self->add_ap_amount_row(%line_params);
|
840 |
859 |
}
|
841 |
860 |
$self->recalculate_amounts();
|
842 |
861 |
|
843 |
|
$self->create_ap_row(chart => $default_ap_amount_chart);
|
|
862 |
$self->create_ap_row(chart => $ap_chart);
|
844 |
863 |
|
845 |
864 |
return $self;
|
846 |
865 |
}
|
FIX: S:H:EmailProcessing: automatischer ZUGFeRD-Import