Calculations in Lua

From ConTeXt wiki

I tried to use Wolfgang’s letter module for my invoices and came up with this Lua code:


\startluacode
userdata = userdata or {}

userdata.invoice = { amount = 0, hours = 0, perhour = 100, items = {} }

function userdata.RegisterTimeItem(text, hours)
-- register a time dependent invoice item
	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)
-- register a invoice item with fixed 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.numberformat(amount)
-- replace decimal point with comma (= German format)
	return string.gsub(string.format("\%.2f", amount), "%.", ",")
end

function userdata.InvoiceTimeLine(text, hours, printperhour)
-- print an invoice line for time dependent items
	context.NC(text)
	context.NC(userdata.numberformat(hours) .. "\\,h")
	if printperhour then
		context.NC("à " .. userdata.numberformat(userdata.invoice.perhour) .. "\\,€/h")
	else
		context.NC()
	end
	context.NC(userdata.numberformat(hours * userdata.invoice.perhour) .. "\\,€")
	context.NC()
	context.NR()
end

function userdata.InvoiceAmountLine(text, amount)
-- print a lump sum item
	context.NC(text)
	context.NC()
	context.NC()
	context.NC(userdata.numberformat(amount) .. "\\,€")
	context.NC()
	context.NR()
end

function userdata.InvoiceTextLine(text)
-- print a free invoice item (just text)
	context.NC(text)
	context.NC()
	context.NC()
	context.NC()
	context.NC()
	context.NR()
end

function userdata.InvoiceSumLine(text, printperhour)
-- print invoice sum line
	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) .. "\\,€/h")
	else
		context.NC()
	end
	context.NC("\\bf " .. userdata.numberformat(userdata.invoice.amount) .. "\\,€")
	context.NC()
	context.NR()
end

function userdata.Invoice()
-- print the whole invoice
	local amountsum, hoursum = 0,0
	local printperhour = true
	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 = (amountsum == (hoursum * userdata.invoice.perhour))
	--userdata.invoice.hours = hoursum
	--userdata.invoice.amount = amountsum
	userdata.InvoiceSumLine("gesamt", printperhour)
	context.stoptabulate()
end

-- register invoice items

userdata.RegisterAmountItem("Some introductional text", 0) -- just text

userdata.RegisterTimeItem("Learn \\LUATEX", 2.5)
userdata.RegisterTimeItem("Do some calculations in \\CONTEXT", 3.5 + 7)

userdata.RegisterAmountItem("Donations to Open Source projects", 99) -- lump sum

-- output

userdata.Invoice()

\stopluacode

I know, the code is quite horrible, but easy enough to customize it for your needs. There’s too much hardcoded to use it as a general module, of course. E.g. it can’t cope with quantity dependent items or with page breaks.

The whole thing becomes obsolete with the preliminary spreadsheet module by Hans in 2011-02 (I guess it will end up in the distribution soon).