Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some enhancements to gc2latex #1

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
47fb45d
Added third address line from Gnucash's customer fields if available
susi-wunsch Jul 20, 2012
6618ec1
Changed handling of second address line of a customer to avoid a perl…
susi-wunsch Jul 20, 2012
f508c64
Integrate gunzip into the perl script enabling to use the Gnucash fil…
susi-wunsch Jul 20, 2012
b2bdf18
Duplicate the table header on each page if the table spreads over sev…
susi-wunsch Jul 20, 2012
d77bd56
Introduced new field for use in LaTeXs invoice template: "__GNUCASH-I…
susi-wunsch Jul 23, 2012
b4e978e
! add rounding for 0.01€ from http://github.com/Cougar/gc2latex/
Cougar Apr 4, 2011
a6670e3
Removed rounding from 'getNetPrice' but applied to 'getNetSum' and 'g…
susi-wunsch Jul 25, 2012
e70ecdc
Treat invoice ID as number or string
trefzer Apr 23, 2013
1c2b1b6
avoid undefined value for $entry->child("entry:invoice")
trefzer Apr 23, 2013
9fc873c
avoid undefined value for $entry->child("entry:action")
trefzer Apr 23, 2013
30b7b9f
get replacement variables not in while
trefzer Apr 25, 2013
18c23b3
add invoice items as parameters to avoid latex code in perl script
trefzer Apr 25, 2013
616588e
add parameter in sub definition of l_enc
trefzer Apr 27, 2013
465ba36
remove sub createLaTeXTable, use createLaTexParams is more flexible
trefzer Apr 27, 2013
c2da0c6
add some more parameters for invoice
trefzer Apr 27, 2013
bd76822
fill in some more fields in the parameters
trefzer Apr 27, 2013
aeb8ed9
New functions for amount calculation:
trefzer Apr 27, 2013
9a324cd
use new sub getAmount to caculate all amounts. This includes now disc…
trefzer Apr 27, 2013
b1e377b
remove unused functions
trefzer Apr 27, 2013
e6a193f
replace multiple occurences of GNUCASH variable in one line
trefzer Apr 27, 2013
f52bfc5
fix example template to not use gc2latex generated table but pameters
trefzer Apr 27, 2013
256afe0
add all address fields, alow empty lines in address
trefzer May 3, 2013
4f6fb05
Distinction for Credit-Notes added, works since GnuCash 2.6
susi-wunsch Feb 21, 2014
e714b6a
Billing terms added
susi-wunsch Feb 21, 2014
8db196e
Applied LaTex::Encode to invoice notes and billing terms, path to perl
susi-wunsch Feb 21, 2014
f0d1b8b
More robust for empty strings in case of LaTeX::Encode usage
susi-wunsch Feb 27, 2014
41b0104
Sub 'translateNewlines' moved into sub 'l_enc' in order to use it for
susi-wunsch Mar 2, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 93 additions & 41 deletions bin/gc2latex
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#!/opt/local/bin/perl
# use the following line as default, the above line had to be
# changed for Mac OSX perl installed with MacPorts/CPAN
#!/usr/bin/perl

# gc2latex by Stefan Tomanek <[email protected]>
Expand All @@ -7,6 +10,7 @@ use Gnucash::Business::InvoiceEntry;
use Gnucash::Business::Customer;
use IO::File;
use Date::Format;
use IO::Zlib;

use strict;

Expand All @@ -19,16 +23,27 @@ sub main($$$) {
}

my $parser = new XML::Parser (ErrorContext => 2, Style => "Tree");
my $xmlobj = new XML::SimpleObject( $parser->parsefile($gnucash) ) || die "Unable to open Gnucash file";


my $zhandle = new IO::Zlib;
$zhandle->open($gnucash, "rb") || die "Unable to zopen Gnucash file\n";

my $xmlobj = new XML::SimpleObject( $parser->parse($zhandle) ) || die "Unable to open Gnucash file";

my $invoice = new Invoice( $xmlobj, $id);

replace($template, $invoice);
}

sub translateNewlines($) {
my ($value) = @_;
$value =~ s/\n/\\\\/g;
return $value;
}

# LaTeX encode: use LaTeX::Encode if available
sub l_enc {
sub l_enc ($) {
my ($data) = @_;
return "" unless $data;
my $result = $data;
eval {
# try to load LaTeX::Encode and encode the supplied data
Expand All @@ -37,58 +52,95 @@ sub l_enc {
require LaTeX::Encode;
$result = LaTeX::Encode::latex_encode( $data, {iquotes=>1} );
};
$result = translateNewlines( $result );
return $result;
}

sub createLaTeXTable($) {
my ($invoice) = @_;

my $cur = $invoice->getCurrency();

my $text = '\begin{longtable}{l|p{150pt}|l|l|r|r}'."\n";
$text .= 'Datum&Beschreibung&Einheit&Anzahl&St�ckpreis&Betrag\\\\'."\n";
$text .= '\hline\hline'."\n";
foreach my $e (@{ $invoice->getEntries() }) {
$text .= time2str("%e.%L.%Y", $e->getDate())."&";
$text .= l_enc( $e->getDescription() )."&";
$text .= l_enc( $e->getAction() )."&";
$text .= $e->getQuantity()."&";
$text .= sprintf("%0.2f", $e->getNetPrice())." $cur&";
$text .= sprintf("%0.2f", $e->getNetSum())." ".$cur.'\\\\'."\n";
$text .= '\hline'."\n";
}
$text .= '\hline'."\n";
$text .= '\multicolumn{5}{r|}{Summe} &'.sprintf("%0.2f", $invoice->getNetSum()).' '.$cur.'\\\\'."\n";
## FIXME
## * Retrieve the right percentage from gnucash file
## * Support multiple taxes
$text .= '\multicolumn{5}{r|}{zuz�glich 19\% Umsatzsteuer} &'.sprintf("%0.2f", $invoice->getTaxes()).' '.$cur.'\\\\'."\n";
$text .= '\hline\hline'."\n";
$text .= '\multicolumn{5}{r|}{Gesamtsumme} &'.sprintf("%0.2f", $invoice->getNetSum()+$invoice->getTaxes()).' '.$cur.'\\\\'."\n";
$text .= '\end{longtable}'."\n";
return $text;
sub createLaTexMacros() {

my $text= '%\usepackage{etoolbox}'."\n";

$text .= '\newcommand\gclsetline[3]{%' ."\n";
$text .= ' \csdef{gcl#1#2}{#3}}%' ."\n";

$text .= '\newcommand\gclgetline[2]{%' ."\n";
$text .= ' \csuse{gcl#1#2}}' ."\n";

return $text;
}

sub createLaTexParams($) {
my ($invoice) = @_;

my $text = '';

my $i=0;
foreach my $e (@{ $invoice->getEntries() }) {
$text .= "\\gclsetline{Date}{$i}{" . time2str("%e.%L.%Y", $e->getDate()) . "}\n" ;
$text .= "\\gclsetline{Description}{$i}{" . l_enc( $e->getDescription() ) . "}\n" ;
$text .= "\\gclsetline{Action}{$i}{" . l_enc( $e->getAction() ) . "}\n" ;
$text .= "\\gclsetline{Quantity}{$i}{" . $e->getQuantity() . "}\n" ;
$text .= "\\gclsetline{UnitPrice}{$i}{" . sprintf("%0.2f", $e->getPrice()) . "}\n" ;
$text .= "\\gclsetline{DiscType}{$i}{" . l_enc($e->getDiscountType()) . "}\n" ;
$text .= "\\gclsetline{DiscHow}{$i}{" . l_enc($e->getDiscountHow()) . "}\n" ;
$text .= "\\gclsetline{Disc}{$i}{" . sprintf("%0.2f", round($e->getDiscount())) . "}\n" ;
$text .= "\\gclsetline{isTaxable}{$i}{" . l_enc($e->isTaxable()) . "}\n" ;
$text .= "\\gclsetline{TaxTable}{$i}{" . l_enc($e->getTaxTable()) . "}\n" ;
$text .= "\\gclsetline{isTaxIncluded}{$i}{" . l_enc($e->isTaxIncluded()) . "}\n" ;
$text .= "\\gclsetline{Subtotal}{$i}{" . sprintf("%0.2f", round($e->getAmount('SubTotal'))). "}\n" ;
$text .= "\\gclsetline{Tax}{$i}{" . sprintf("%0.2f", round($e->getAmount('Tax'))) . "}\n" ;
$text .= "\\gclsetline{Total}{$i}{" . sprintf("%0.2f", round($e->getAmount('Total'))) . "}\n" ;
$text .= "\n";
$i=$i+1;
}
$text .= '\csdef{gclinvoicelines}{' . $i . "}\n";
return $text;
}

sub replace($$) {
my ($template, $invoice) = @_;

my $file = new IO::File "< $template" || die "Unable to open template";

my $id = $invoice->getID();
my $postingdate = l_enc( time2str("%e.%L.%Y", $invoice->getPostingDate()) );
my $address = l_enc( $invoice->getCustomer()->getAddress() );
my $notes = l_enc($invoice->getNotes());
my $terms = l_enc($invoice->getTerms());
my $creditNoteType = $invoice->getCreditNoteType();
my $currency = $invoice->getCurrency();
my $total = sprintf("%0.2f", $invoice->getNetSum()+$invoice->getTaxes());
my $subtotal = sprintf("%0.2f", $invoice->getNetSum());
my $taxes = sprintf("%0.2f", $invoice->getTaxes());

# invoice items (mutliple lines)
my $parameters = createLaTexParams($invoice);
my $macros = createLaTexMacros();

my $file = new IO::File "< $template" || die "Unable to open template";
while ( my $l = $file->getline() ) {
my $id = $invoice->getID();
my $date = l_enc( time2str("%e.%L.%Y", $invoice->getPostingDate()) );
my $address = l_enc( $invoice->getCustomer()->getAddress() );
$address =~ s/\n/\\\\/g;
my $table = createLaTeXTable($invoice);

$l =~ s/__GNUCASH-INVOICE-ID__/$id/;
$l =~ s/__GNUCASH-POSTING-DATE__/$date/;
$l =~ s/__GNUCASH-CUSTOMER__/$address/;
$l =~ s/__GNUCASH-TABLE__/$table/;
$l =~ s/__GNUCASH-INVOICE-ID__/$id/g;
$l =~ s/__GNUCASH-POSTING-DATE__/$postingdate/g;
$l =~ s/__GNUCASH-CUSTOMER__/$address/g;
$l =~ s/__GNUCASH-INVOICE-NOTES__/$notes/g;
$l =~ s/__GNUCASH-BILLING-TERMS__/$terms/g;
$l =~ s/__GNUCASH-CURRENCY__/$currency/g;
$l =~ s/__GNUCASH-TOTAL__/$total/g;
$l =~ s/__GNUCASH-SUBTOTAL__/$subtotal/g;
$l =~ s/__GNUCASH-TAXES__/$taxes/g;
$l =~ s/__GNUCASH-CREDIT-NOTE-TYPE__/$creditNoteType/g;

# invoice items (multiple lines)
$l =~ s/__GNUCASH-MACROS__/$macros/;
$l =~ s/__GNUCASH-PARAMETERS__/$parameters/;

print $l;
}
$file->close();
}

sub round($) {
my ($value) = @_;
return int($value * 100 + 0.5) / 100;
}

main($ARGV[0], $ARGV[1], $ARGV[2]);
101 changes: 76 additions & 25 deletions examples/template.tex
Original file line number Diff line number Diff line change
@@ -1,53 +1,104 @@
% Template for gc2latex
% by Stefan Tomanek <[email protected]>
% http://stefans.datenbruch.de/gnucash/gc2latex.shtml
%
% adapted to use parameters and not directly generated
% latex input from gc2latex by Benedikt Trefzer <[email protected]>
%
% enhanced for appropriate titles (invoice vs. credit-note), works
% since GnuCash 2.6 by Susanne Wunsch <[email protected]>

\documentclass[DIN, pagenumber=false, parskip=half,%
fromalign=left, fromphone=true,%
fromemail=true, fromurl=false, %
fromlogo=true, fromrule=false]{scrlttr2}

\usepackage[latin1]{inputenc}
\usepackage{german}
\RequirePackage{graphicx}
\usepackage[ngerman]{babel}
\usepackage{etoolbox}
\usepackage{ifthen}
\usepackage{tabularx}
\usepackage{booktabs}

\setkomavar{fromname}{Max Mustermann}
\setkomavar{fromaddress}{Musterstra�e 34\\12345 Musterstadt}
\setkomavar{fromaddress}{Musterstr. 34\\12345 Musterstadt}
\setkomavar{fromphone}{01234/123456}
\setkomavar{fromemail}{[email protected]}
\setkomavar{fromurl}{}
\setkomavar{signature}{Max Mustermann}
\setkomavar{fromlogo}{\includegraphics*[width=6cm]{musterfirma.eps}}
\setkomavar{frombank}{Musterbank\\BLZ: 12345678\\Kontonummer: 0123456}
\setkomavar{subject}{Rechnung Nr. __GNUCASH-INVOICE-ID__}

% Werte: DIN, DINmtext, SN, SNleft, KOMAold.
\LoadLetterOption{DIN}

__GNUCASH-MACROS__

__GNUCASH-PARAMETERS__

\setkomavar{yourref}{}
\setkomavar{yourmail}{}
\setkomavar{myref}{}
\setkomavar{customer}{}

\setkomavar{invoice}{__GNUCASH-INVOICE-ID__}
\setkomavar{date}{__GNUCASH-POSTING-DATE__}

\begin{document}
% Change the titles for your language needs
\csdef{gclcreditnotetype1}{Gutschrift} % credit-note
\csdef{gclcreditnotetype0}{Rechnung} % invoice/bill
\setkomavar{title}{\csuse{__GNUCASH-CREDIT-NOTE-TYPE__}}

\newcommand{\amp}{&}

\newcommand{\printQuantity}[1]{
\gclgetline{Quantity}{#1}%
\ifthenelse{\equal{\gclgetline{Action}{#1}}{Hours}}{h}{}
\ifthenelse{\equal{\gclgetline{Action}{#1}}{Material}}{Stk.}{}
}

\firstfoot{ {\hrulefill\\}%
\fontsize{9}{10.5}\selectfont%
\parbox[t]{0.4\textwidth}{%
Musterfirma\\
\usekomavar{fromname}\\
\usekomavar{fromaddress}}%
\hfill%
\parbox[t]{0.3\textwidth}{\usekomavar{fromname}\\\usekomavar{frombank}}%
\hfill%
\parbox[t]{0.3\textwidth}{%
Steuernummer: 111/22222/3333\\
Finanzamt Musterstadt-S�d\par }
\newcommand{\printDiscount}[1]{
\gclgetline{Disc}{#1}%
\ifthenelse{\equal{\gclgetline{DiscType}{#1}}{PERCENT}}{\%}{}
\ifthenelse{\equal{\gclgetline{DiscType}{#1}}{VALUE}}{__GNUCASH-CURRENCY__}{}
}



\newcommand{\printline}[5]{
#1\amp#2\amp#3\amp#4\amp#5\\
}


\newcounter{i}
\newcommand{\printtab}[1]{%
\setcounter{i}{0}
\whiledo {\value{i} < #1}{
\printline{\printQuantity{\arabic{i}}}
{\gclgetline{Description}{\arabic{i}}}
{\hfill\gclgetline{UnitPrice}{\arabic{i}}}
{\printDiscount{\arabic{i}}}
{\hfill\gclgetline{Subtotal}{\arabic{i}}}
\stepcounter{i}
}
}


\begin{document}
\begin{letter}{__GNUCASH-CUSTOMER__}
\opening{}

\opening{Sehr geehrte Damen und Herren,}
hiermit erlaube ich ich mir zu berechnen:
\fontsize{10pt}{1em}\selectfont
\begin{tabularx}{\linewidth}{lXlll}
Menge & Text & Preis (__GNUCASH-CURRENCY__) & Rabatt & Total (__GNUCASH-CURRENCY__) \\\toprule
\printtab{\csuse{gclinvoicelines}}\\[-2ex]
\midrule
&Taxes&\hfill__GNUCASH-SUBTOTAL__&&\hfill__GNUCASH-TAXES__\\
&\multicolumn{3}{l}{Total}&\hfill__GNUCASH-TOTAL__\\
\bottomrule
\end{tabularx}

__GNUCASH-TABLE__
__GNUCASH-BILLING-TERMS__

\closing{Mit freundlichem Gru�}
\closing{}

\end{letter}

\end{document}

35 changes: 35 additions & 0 deletions lib/Gnucash/Business/BillTerm.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package BillTerm;

use XML::SimpleObject;

use strict;

## By Susanne Wunsch <[email protected]>
## Adapted from Stefan Tomanek <[email protected]>

sub new($$$) {
my ($proto, $gc, $guid) = @_;

my $self = {};
$self->{guid} = $guid;
fillInfos($self, $gc);

bless($self);
return $self;
}

sub fillInfos($) {
my ($self, $xml) = @_;

my $gc = $xml->child("gnc-v2")->child("gnc:book");

my @terms = $gc->children("gnc:GncBillTerm");
return if ($terms[0] eq "");
foreach my $tm (@terms) {
next unless ($self->{guid} eq $tm->child("billterm:guid")->value());
$self->{info}{description} = $tm->child("billterm:desc")->value();
last;
}
}

1;
Loading