Difference between revisions of "Invoice"

From ConTeXt wiki
m (add link to Letter)
(adaptions to current letter module)
 
Line 1: Line 1:
 
< [[Sample documents]] | [[Letter]]
 
< [[Sample documents]] | [[Letter]]
  
This is my invoice setup, it works with MkIV as of 2011-12.
+
This is my invoice setup, it works with MkIV as of 2014-01.
  
 
It’s an application of Wolfgang’s letter module with a lot of tweaks that I could never think of on my own.
 
It’s an application of Wolfgang’s letter module with a lot of tweaks that I could never think of on my own.
Line 134: Line 134:
 
\setuplanguage [de] [date={year, –, mm, –, dd}] % ISO 8601 date
 
\setuplanguage [de] [date={year, –, mm, –, dd}] % ISO 8601 date
  
\usemodule[simplefonts]
+
\setupbodyfont[rm,10pt]
\setmainfont[Gentium Basic][expansion=quality,protrusion=quality]
 
\setsansfont[Delicious][scale=0.9]
 
\setupbodyfont[rm,9.5pt]
 
 
\setupinterlinespace[3.0ex] % default: 2.8ex
 
\setupinterlinespace[3.0ex] % default: 2.8ex
 +
\setbreakpoints[compound] % break at / and -
 +
 +
\setupletteroptions
 +
  [language=german, % de
 +
  bodyfont={rm,10pt},
 +
  whitespace=1.5ex, %3ex
 +
  ]
  
 
\setuptabulate[distance=0pt]
 
\setuptabulate[distance=0pt]
Line 149: Line 153:
 
% Sender address in envelope window
 
% Sender address in envelope window
 
backaddress={\MyCompany\ · My Name · Samplestr.\,11 · CH-1234 Village}
 
backaddress={\MyCompany\ · My Name · Samplestr.\,11 · CH-1234 Village}
]
 
 
% Use the sender address line, but not the default subject line
 
\setupletterstyle[backaddress=yes,reference=no]
 
 
% We put our logo in the head
 
\setupletterstyle[head,nexthead][
 
hoffset=128mm,
 
voffset=0pt,
 
alternative=fiee,
 
 
]
 
]
  
 
% Define logo for the first page
 
% Define logo for the first page
\defineletterelement[head][fiee]{%
+
\defineletterelement[layer][head][fiee]%
\framed[background=logo,height=35mm,frame=off]{\vbox{
+
{\framed[background=logo,height=35mm,frame=off,align=right]%
\par\blank[15mm]\par
+
{\externalfigure[schriftzug]}}
\externalfigure[schriftzug]}}
 
 
 
}
 
  
 
% Other logo for subsequent (right) pages
 
% Other logo for subsequent (right) pages
\defineletterelement[nexthead][fiee]{%
+
\defineletterelement[layer][nexthead][fiee]%
\externalfigure[logo][height=2cm, width=6cm]}
+
{\externalfigure[logo][height=2cm, width=6cm]}
  
\setupletterstyle[nexthead][
+
% We put our logo in the head
state=right,
+
\setupletterlayer[head,nexthead][
 +
x=128mm,
 +
y=15mm,
 +
alternative=fiee,
 
]
 
]
  
% We don't really use this
+
\setupletterlayer[nexthead][state=right]
\copyletterelement[location][fiee][reference][d]
 
 
 
\setupletterstyle[location][
 
hoffset=128mm,
 
voffset=3cm,
 
alternative=fiee,
 
list={name,street,city,phone,email,web,skype}
 
]
 
  
 
\setupletter[
 
\setupletter[
Line 199: Line 185:
  
 
% center around the :
 
% center around the :
\startsetups letter:location
+
\defineletterelement[layer][location][fiee]%
\tfx\it
+
{\setuptabulate[bodyfont=small]
\starttabulate[|rw(39mm)|p|]
+
\starttabulate[|Irw(5em)|Ip|]
\NC name \NC\lettervalue{name} \NC\NR
+
\NC person \NC\correspondenceparameter{name} \NC\NR
\NC location \NC\lettervalue{street}\\\lettervalue{city}\NC\NR
+
\NC address \NC\correspondenceparameter{street}\\\correspondenceparameter{city}\NC\NR
\NC phone \NC\lettervalue{phone}\\\lettervalue{mobile} \NC\NR
+
\NC phone \NC\correspondenceparameter{phone}\\\correspondenceparameter{mobile} \NC\NR
\NC internet \NC\lettervalue{email}\\\lettervalue{web} \NC\NR
+
\NC internet \NC\correspondenceparameter{email}\\\correspondenceparameter{web} \NC\NR
\NC skype \NC\lettervalue{skype} \NC\NR
+
\NC skype \NC\correspondenceparameter{skype} \NC\NR
\stoptabulate
+
\stoptabulate}
\stopsetups
 
  
 +
\setupletterlayer[location]
 +
[alternative=fiee,
 +
x=152mm,
 +
y=30mm
 +
]
  
\setupletterstyle[address][alternative=fiee]
 
 
% Our own recipient setup without too much space before the address
 
% Our own recipient setup without too much space before the address
\defineletterelement[address][fiee]{
+
\defineletterelement[layer][address][fiee]%
\setupinterlinespace
+
{\correspondenceparameter{toname}\\
\blank
+
\correspondenceparameter{toaddress}
\lettervalue{toname}\\
+
\par}
\lettervalue{toaddress}
+
}
+
\setupletterlayer[address][alternative=fiee]
  
 
% Subject and date on the same line, date below logo
 
% Subject and date on the same line, date below logo
\startsetups letter:subject
+
\startsetups[letter:section:subject]
\bTABLE[frame=off]
+
  \bTABLE[frame=off]
\bTR
+
    \bTR
\bTD[width=\dimexpr169mm-\backspace\relax]\lettervalue{subject}\eTD
+
      \bTD[width=\dimexpr169mm-\backspace\relax]\correspondenceparameter{subject}\eTD
\bTD{\tf\lettervalue{date}}\eTD % auto date
+
    \bTD{\tf\correspondenceparameter{date}}\eTD
%\bTD{\tf 2011-11-14}\eTD % manual date
+
    \eTR
\eTR
+
  \eTABLE
\eTABLE
 
 
\stopsetups
 
\stopsetups
 +
 +
\setuplettersection[subject][alternative=setups]
  
 
% account information at the foot, below the logo
 
% account information at the foot, below the logo
\defineletterelement[foot][fiee]{
+
\defineletterelement[layer][foot][fiee]%
\tfx\it
+
  {\setuptabulate[bodyfont=small]
% \starttabulate[|rw(5em)a{{\tf~:}}|p|]
+
  \starttabulate[|Irw(39mm)|Ip|]
\starttabulate[|rw(39mm)|p|]
+
\NC accounts \NC \NC\NR
\NC account \NC \NC\NR
+
\NC account \NC 123\,456\,789\\Postbank, BLZ 360\,100\,00 \NC\NR
\NC Swiss \NC 12-34567-89 \NC\NR
+
\NC IBAN \NC DE00\,3601\,0000\,0123\,4567\,89 \NC\NR
\NC IBAN \NC CH12\,1234\,5678\,0000\,1234\,X \NC\NR
+
\NC BIC \NC PBNKDEFF \NC\NR
\NC German \NC Kto. 111\,222\,333\\Fraudbank, BLZ 110\,110\,10 \NC\NR
+
\stoptabulate}
\NC IBAN \NC DE11\,1234\,0000\,1234\,9999\,12 \NC\NR
 
\stoptabulate
 
\crlf
 
}
 
  
\setupletterstyle[foot][
+
\setupletterlayer[foot][
 
preset=leftbottom,
 
preset=leftbottom,
hoffset=130mm,
+
x=127mm,
voffset=3.4cm,
+
y=34mm,
alternative=fiee,
+
alternative=fiee]
]
 
  
 
% switch off reference line
 
% switch off reference line
\setupletterstyle[reference][alternative=none]
+
\setupletterlayer[reference][state=stop]
  
 
% Move the text a bit up
 
% Move the text a bit up
\setupletterstyle[firstpage][
+
\setupletterlayout[firstpage][topspace=10cm]
topspace=10cm
 
]
 
  
 
% Adjust text start on subsequent pages
 
% Adjust text start on subsequent pages
\setupletterstyle[secondpage][
+
\setupletterlayout[secondpage][topspace=3cm]
topspace=3cm,
 
]
 
  
 
% Move marks to the paper rim (won't print on most printers)
 
% Move marks to the paper rim (won't print on most printers)
\setupletterstyle[topmark,botmark,cutmark][
+
\setupletterlayer[topmark,botmark,cutmark][x=-2mm]
hoffset=-2mm
 
]
 
 
</texcode>
 
</texcode>
  
Line 279: Line 258:
 
\setupletter[
 
\setupletter[
 
% Recipient
 
% Recipient
%toname={Pragma ADE\\Mr.\\,Hans Hagen},toaddress={Ridderstraat 27\\8061GH Hasselt NL},
+
toname={Pragma ADE\\Mr.\\,Hans Hagen},toaddress={Ridderstraat 27\\8061GH Hasselt NL},
 
% here I keep commented all of my few customers
 
% here I keep commented all of my few customers
 +
subject={Invoice No.\,99/2014}
 +
%subject={Reminder on invoice No.\,1/2014}
 
]
 
]
\starttext
 
  
\startletter[subject={Invoice No.\,99/2011}]
+
\startletter
%\startletter[subject={Reminder on invoice No.\,1/2011}]
 
  
Special services in December 2011:
+
Special services in December 2013:
  
 
{
 
{
Line 305: Line 284:
 
}
 
}
  
Due on 1.\,1.\2012. Earlier is nicer.
+
Due on 1.\,1.\2014. Earlier is nicer.
  
 
\blank[2*big]
 
\blank[2*big]
  
\MyCompany\ bedankt sich für den Auftrag.
+
\MyCompany\ thanks for your order.
 
\blank[2*big]
 
\blank[2*big]
Mit freundlichen Grüßen,
+
Best regards,
  
 
\externalfigure[signature]
 
\externalfigure[signature]
Line 318: Line 297:
  
 
\stopletter
 
\stopletter
 
\stoptext
 
 
</texcode>
 
</texcode>

Latest revision as of 07:35, 13 January 2014

< Sample documents | Letter

This is my invoice setup, it works with MkIV as of 2014-01.

It’s an application of Wolfgang’s letter module with a lot of tweaks that I could never think of on my own.

The code isn’t pretty or modular or readily usable for you, but works for me and might get you over some hurds.

As you see, I need my invoices in Euros or Swiss Francs. And I need to charge some work by time and some by fixed amounts. If you need number of pieces etc., it should be easy to adapt.

Big thanks to Wolfgang and all the other helpful power users on NTG-ConTeXt!

Lua functions

File invoicefunctions.tex

\startluacode
userdata = userdata or {}

userdata.invoice = { amount = 0, hours = 0, perhour = 50, currency1 = "€", currency2 = "SFr", exchangerate=1.22, items = {} }

function userdata.RegisterTimeItem(text, hours)
	if tex.systemmodes.trialtypesetting then return end
	table.insert(userdata.invoice.items, {text=text, hours=hours, amount=0})
	userdata.invoice.hours = userdata.invoice.hours + hours
	userdata.invoice.amount = userdata.invoice.amount + hours * userdata.invoice.perhour
end

function userdata.RegisterAmountItem(text, amount)
	if tex.systemmodes.trialtypesetting then return end
	table.insert(userdata.invoice.items, {text=text, hours=0, amount=amount})
	userdata.invoice.amount = userdata.invoice.amount + amount
end

function userdata.RegisterTextItem(text)
	if tex.systemmodes.trialtypesetting then return end
	table.insert(userdata.invoice.items, {text=text, hours=0, amount=0})
end

function userdata.numberformat(amount)
	-- replace decimal point with comma (= German format)
	return string.gsub(string.format("\%.2f", amount), "%.", ",")
end

function userdata.InvoiceTimeLine(text, hours, printperhour)
	context.NC(text)
	context.NC(userdata.numberformat(hours) .. "\\,h")
	if printperhour then
		context.NC("à " .. userdata.numberformat(userdata.invoice.perhour) .. "\\," .. userdata.invoice.currency1 .. "/h")
	else
		context.NC()
	end
	context.NC(userdata.numberformat(hours * userdata.invoice.perhour) .. "\\," .. userdata.invoice.currency1)
	context.NC()
	context.NR()
end

function userdata.InvoiceAmountLine(text, amount)
	context.NC(text)
	context.NC()
	context.NC()
	context.NC(userdata.numberformat(amount) .. "\\," .. userdata.invoice.currency1)
	context.NC()
	context.NR()
end

function userdata.InvoiceTextLine(text)
	context.NC(text)
	context.NC()
	context.NC()
	context.NC()
	context.NC()
	context.NR()
end

function userdata.InvoiceSumLine(text, printperhour)
	context.HL()
	context.NC("\\bf " .. text)
	if userdata.invoice.hours > 0 then
		context.NC(userdata.numberformat(userdata.invoice.hours) .. "\\,h")
	else
		context.NC()
	end
	if printperhour then
		context.NC("à " .. userdata.numberformat(userdata.invoice.perhour) .. "\\," .. userdata.invoice.currency1 .. "/h")
	else
		context.NC()
	end
	context.NC("\\bf " .. userdata.numberformat(userdata.invoice.amount) .. "\\," .. userdata.invoice.currency1)
	context.NC()
	context.NR()
	if userdata.invoice.currency1 ~= userdata.invoice.currency2 then
		context.NC()
		context.NC()
		context.NC()
		context.NC("(" .. userdata.numberformat(userdata.invoice.amount * userdata.invoice.exchangerate) .. "\\," .. userdata.invoice.currency2 .. ")")
		context.NC()
		context.NR()
	end
end

function userdata.Invoice()
	local amountsum, hoursum = 0,0
	local printperhour
	printperhour = (userdata.invoice.amount ~= (userdata.invoice.hours * userdata.invoice.perhour))
	context.starttabulate({"|lw(8cm)|rg(,)w(2cm)|rg(,)w(2cm)|rg(,)w(3cm)|"})
	for no, item in ipairs(userdata.invoice.items) do
		if item.hours ~= 0 and item.amount == 0 then
			userdata.InvoiceTimeLine(item.text, item.hours, printperhour)
			hoursum = hoursum + item.hours
			amountsum = amountsum + item.hours * userdata.invoice.perhour
		elseif item.amount ~= 0 and item.hours == 0 then
			userdata.InvoiceAmountLine(item.text, item.amount)
			amountsum = amountsum + item.amount
		else
			userdata.InvoiceTextLine(item.text)
		end
	end
	printperhour = (hoursum > 0) and (amountsum == (hoursum * userdata.invoice.perhour))
	--userdata.invoice.hours = hoursum
	--userdata.invoice.amount = amountsum
	userdata.InvoiceSumLine("gesamt", printperhour)
	context.stoptabulate()
end

\stopluacode

Letter setup

File invoicesetup.tex

\mainlanguage[de]
\usemodule[letter]

\setuplanguage [de] [date={year, –, mm, –, dd}] % ISO 8601 date

\setupbodyfont[rm,10pt]
\setupinterlinespace[3.0ex] % default: 2.8ex
\setbreakpoints[compound] % break at / and -

\setupletteroptions
  [language=german, % de
   bodyfont={rm,10pt},
   whitespace=1.5ex, %3ex
   ]

\setuptabulate[distance=0pt]

\def\MyCompany{{\it MyCompany}}
\useexternalfigure[logo][logo-head]
\useexternalfigure[schriftzug][logo-type]

\setupletter[
	% Sender address in envelope window
	backaddress={\MyCompany\ · My Name · Samplestr.\,11 · CH-1234 Village}
]

% Define logo for the first page
\defineletterelement[layer][head][fiee]%
{\framed[background=logo,height=35mm,frame=off,align=right]%
{\externalfigure[schriftzug]}}

% Other logo for subsequent (right) pages
\defineletterelement[layer][nexthead][fiee]%
{\externalfigure[logo][height=2cm, width=6cm]}

% We put our logo in the head
\setupletterlayer[head,nexthead][
	x=128mm,
	y=15mm,
	alternative=fiee,
]

\setupletterlayer[nexthead][state=right]

\setupletter[
	name={My Name},
	street={Samplestrasse 11},
	city={CH-1234 Village},
	phone={+41 11 23\,45\,67},
	mobile={+41 00 99\,88\,88\,88},
	email={me@mycompany.com},
	web={www.example.com},
	skype={example}
]

% center around the :
\defineletterelement[layer][location][fiee]%
	{\setuptabulate[bodyfont=small]
	\starttabulate[|Irw(5em)|Ip|]
	\NC person 	\NC\correspondenceparameter{name} \NC\NR
	\NC address 		\NC\correspondenceparameter{street}\\\correspondenceparameter{city}\NC\NR
	\NC phone 	\NC\correspondenceparameter{phone}\\\correspondenceparameter{mobile} \NC\NR
	\NC internet 	\NC\correspondenceparameter{email}\\\correspondenceparameter{web} \NC\NR
	\NC skype 		\NC\correspondenceparameter{skype} \NC\NR
\stoptabulate}

\setupletterlayer[location]
	[alternative=fiee,
	x=152mm,
	y=30mm
	]

% Our own recipient setup without too much space before the address
\defineletterelement[layer][address][fiee]%
	{\correspondenceparameter{toname}\\
	\correspondenceparameter{toaddress}
	\par}
	
\setupletterlayer[address][alternative=fiee]

% Subject and date on the same line, date below logo
\startsetups[letter:section:subject]
  \bTABLE[frame=off]
    \bTR
      \bTD[width=\dimexpr169mm-\backspace\relax]\correspondenceparameter{subject}\eTD
     \bTD{\tf\correspondenceparameter{date}}\eTD
    \eTR
  \eTABLE
\stopsetups

\setuplettersection[subject][alternative=setups]

% account information at the foot, below the logo
\defineletterelement[layer][foot][fiee]%
  {\setuptabulate[bodyfont=small]
  \starttabulate[|Irw(39mm)|Ip|]
		\NC accounts \NC \NC\NR
		\NC account \NC 123\,456\,789\\Postbank, BLZ 360\,100\,00 \NC\NR
		\NC IBAN \NC DE00\,3601\,0000\,0123\,4567\,89 \NC\NR
		\NC BIC \NC PBNKDEFF \NC\NR
	\stoptabulate}

\setupletterlayer[foot][
	preset=leftbottom,
	x=127mm,
	y=34mm,
	alternative=fiee]

% switch off reference line
\setupletterlayer[reference][state=stop]

% Move the text a bit up
\setupletterlayout[firstpage][topspace=10cm]

% Adjust text start on subsequent pages
\setupletterlayout[secondpage][topspace=3cm]

% Move marks to the paper rim (won't print on most printers)
\setupletterlayer[topmark,botmark,cutmark][x=-2mm]

Invoice

File invoice.tex

\input invoicesetup.tex
\input invoicefunctions.tex

\setupletter[
	% Recipient
	toname={Pragma ADE\\Mr.\\,Hans Hagen},toaddress={Ridderstraat 27\\8061GH Hasselt NL},
	% here I keep commented all of my few customers
	subject={Invoice No.\,99/2014}
	%subject={Reminder on invoice No.\,1/2014}
]

\startletter

Special services in December 2013:

{
\setuptabulate[distance=.25em]
\startluacode
userdata.invoice.perhour = 111
--userdata.invoice.currency1 = "SFr"

userdata.RegisterTextItem("Some project description")

userdata.RegisterAmountItem("Data handling, flat-rate", 500)

userdata.RegisterTimeItem("Design of issue 1 of Some magazine", 42.5)

userdata.Invoice()
\stopluacode
}

Due on 1.\,1.\2014. Earlier is nicer.

\blank[2*big]

\MyCompany\ thanks for your order.
\blank[2*big]
Best regards,

\externalfigure[signature]

My Name

\stopletter