Changes

Jump to navigation Jump to search
8,717 bytes added ,  22:48, 14 December 2011
new
< [[Sample documents]]

This is my invoice setup, it works with MkIV as of 2011-12.

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 <code>invoicefunctions.tex</code>
<texcode>
\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
</texcode>

== Letter setup ==
File <code>invoicesetup.tex</code>
<texcode>
\mainlanguage[de]
\usemodule[letter]

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

\usemodule[simplefonts]
\setmainfont[Gentium Basic][expansion=quality,protrusion=quality]
\setsansfont[Delicious][scale=0.9]
\setupbodyfont[rm,9.5pt]
\setupinterlinespace[3.0ex] % default: 2.8ex

\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}
]

% 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
\defineletterelement[head][fiee]{%
\framed[background=logo,height=35mm,frame=off]{\vbox{
\par\blank[15mm]\par
\externalfigure[schriftzug]}}

}

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

\setupletterstyle[nexthead][
state=right,
]

% We don't really use this
\copyletterelement[location][fiee][reference][d]

\setupletterstyle[location][
hoffset=128mm,
voffset=3cm,
alternative=fiee,
list={name,street,city,phone,email,web,skype}
]

\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 :
\startsetups letter:location
\tfx\it
\starttabulate[|rw(39mm)|p|]
\NC name \NC\lettervalue{name} \NC\NR
\NC location \NC\lettervalue{street}\\\lettervalue{city}\NC\NR
\NC phone \NC\lettervalue{phone}\\\lettervalue{mobile} \NC\NR
\NC internet \NC\lettervalue{email}\\\lettervalue{web} \NC\NR
\NC skype \NC\lettervalue{skype} \NC\NR
\stoptabulate
\stopsetups


\setupletterstyle[address][alternative=fiee]
% Our own recipient setup without too much space before the address
\defineletterelement[address][fiee]{
\setupinterlinespace
\blank
\lettervalue{toname}\\
\lettervalue{toaddress}
}

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

% account information at the foot, below the logo
\defineletterelement[foot][fiee]{
\tfx\it
% \starttabulate[|rw(5em)a{{\tf~:}}|p|]
\starttabulate[|rw(39mm)|p|]
\NC account \NC \NC\NR
\NC Swiss \NC 12-34567-89 \NC\NR
\NC IBAN \NC CH12\,1234\,5678\,0000\,1234\,X \NC\NR
\NC German \NC Kto. 111\,222\,333\\Fraudbank, BLZ 110\,110\,10 \NC\NR
\NC IBAN \NC DE11\,1234\,0000\,1234\,9999\,12 \NC\NR
\stoptabulate
\crlf
}

\setupletterstyle[foot][
preset=leftbottom,
hoffset=130mm,
voffset=3.4cm,
alternative=fiee,
]

% switch off reference line
\setupletterstyle[reference][alternative=none]

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

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

% Move marks to the paper rim (won't print on most printers)
\setupletterstyle[topmark,botmark,cutmark][
hoffset=-2mm
]
</texcode>

== Invoice ==
File <code>invoice.tex</code>
<texcode>
\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
]
\starttext

\startletter[subject={Invoice No.\,99/2011}]
%\startletter[subject={Reminder on invoice No.\,1/2011}]

Special services in December 2011:

{
\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.\2012. Earlier is nicer.

\blank[2*big]

\MyCompany\ bedankt sich für den Auftrag.
\blank[2*big]
Mit freundlichen Grüßen,

\externalfigure[signature]

My Name

\stopletter

\stoptext
</texcode>

Navigation menu