Magic Smoke ODF Templates

This text describes how ODF templates are generated and which ones exist. ODT templates always use the suffix ".odtt" for text templates and ".odst" for spreadsheet templates.

Creating a Template

Open Document Files (*.od?, usually *.odt) are basically zipped XML files. Magic Smoke ODF Templates are ODF files in which the "content.xml" file contains some special markup that is replaced by Magic Smoke before the file is used as a normal OD file.

This process needs some knowledge in XML.

  1. Write an OD file that meets your expectations for what you want to template. It is recommended that you already put all variables (@VAR@, see below) or at least some markers into the file to make it easier to find each location. Alternatively you can go through the "Edit Templates" dialog to retrieve an existing template.
  2. Open MagicSmoke and log into your system (this is necessary to test localization and to have data available for testing the template).
  3. Go to the menu "Actions" - "Templates" - "ODF Editor", then go to "File" - "Import ODF File" and load your file.
  4. Enter all missing variables and loops. See below.
  5. Test the template:
    1. Go to "Test" - "Test with..."; depending on what kind of template you are constructing chose the correct type.
    2. MagicSmoke asks for the Order ID or Event to use as a template - it is best if you check beforehand to have a few examples handy that fulfill your requirements for testing a template (e.g. one order with multiple different tickets, one with vouchers, one paid, one partly paid...)
    3. A window opens that contains the example information - it behaves just the same as in normal mode except that it always uses the template you just created for printing. Warning: if you make changes to an order in this window, they WILL end up in the system!
    4. Go to the print or save function and test the template, it is recommended to use a virtual PDF printer or to just save as ODF file for testing to avoid wasting paper.
    5. Close the window, continue to change the file or save it.
  6. Save the template locally. It is recommended to keep this saved file around to have a backup for later reference.
  7. Upload the template file to the server: "Templates" - "Edit Templates", use the "Upload new Variant" button to upload your file.

Syntax

ODF templates use a pure XML syntax, they are actually ODF files that have been enhanced with some XML tags that allow to create special behavior.

You have the following syntactic elements at your disposal:

Variables and Formulas

Variables and Formulas can be added to any text element by enclosing them in two "@" signs. Predefined variables contain only upper-case letters, you can assign variables with any combination of upper- and lower-case. The parser is case sensitive. Any syntax violation results in empty text. To create a single "@" you can simply enter "@@".

If a variable exists it is replaced by the value that Magic Smoke intended for it.

If a value contains special characters they are replaced by the correct XML sequences (eg. < by &lt;).

You can use the usual mathematical operations to add, subtract, multiply or divide. There are a number of functions available to convert values.

Operators and functions:
@123@literal integer value 123 - rendered as number 123
@"hello"@literal string value rendered as hello (without "quotes")
@VAR@tries to find the variable VAR and replaces it by its value
@VAR1 + VAR2@add the value of two variables VAR1 and VAR2, or if one of them is string: concatenate them
@VAR1 + 9@add 9 to the value of the variable VAR1 and display the result
@VAR1 - VAR2@subtract the value of VAR2 from VAR1
@VAR1 * VAR2@multiply two values
@VAR1 / VAR2@divide two values
@VAR1 == 12@compare two values for equality, yields a boolean usable in if(...), other operators are != (non-equality), < (less than), <= (less or equal), > (greater), >= (greater or equal)
@VAR1 || true@logical OR of the value of VAR1 and the literal boolean true, other logical operators are: && (AND), and ^^ (XOR)
@VAR = 123@assign a value to variable VAR and also print this value
@int(VAR)@try to convert the value of VAR into a numeric value, succeeds for integers, floats and all strings that contain digits only
@float(VAR)@try to convert to a floating point number
@bool(VAR)@try to convert to a boolean (succeeds for numbers: zero is false, anything else is true)
@string(VAR)@converts a value to string (after this numbers can be concatenated, but not multiplied anymore)
@strlen(VAR)@returns the number of characters of the variable
@concat(VAR1,VAR2,...)@concatenate multiple values into one string
@null@a literal value for "invalid value", cannot be used as variable name
@true@, @false@literal truth values
@!true@inverts a boolean value
@if(BOOL, IFTRUEEXPR [,IFFALSEEXPR])@if the first parameters evaluates to true, the result is the second parameter, otherwise the (optional) third parameter (if omitted: null)
@isNull(EXPR)@evaluates to true if the parameter is null (invalid)
@isException(EXPR)@evaluates to true if the parameter yields an exception (i.e. the operation is not permitted on those values or a variable or function is unknown)
@isExceptionOrNull(EXPR)evaluates to true if the parameter is null or yields an exception
@catch(EXPR [, IFEXC [, IFOK]] )@if the EXPR yields and exception returns the second paramter (IFEXC) or true, otherwise the third parameter or false
@toMoney(INTVAL)@converts a value in cents to a normal monetary value, including currency sign
@toMoneyLocal(INTVAL)@converts a value in cents to a normal monetary value, including currency sign in its localized form
@toMoneyNL(INTVAL)@converts a value in cents to a normal monetary value, including currency sign in its non-localized form
@fromMoney(STRVAL)@converts a string representing a monetary value to a number in cents (inverse of toMoney(..); also: fromMoneyLocal(..), fromMoneyNL(..))
@unix2date(INTVAL [,LOCAL])@converts a numeric Unix time to a human readable date value, per default localized, the optional parameter means: true=localized, false=non-localized
@unix2time(INTVAL [,LOCAL])@converts a numeric Unix time to a human readable time (without date) value
@unix2dateTime(INTVAL [,LOCAL])@converts a numeric Unix time to a human readable date and time value
@cent2str(INTVAL)@, @str2cent(STRVAL)@aliases for toMoney() and fromMoney()

Loops and Loop Variables

Some templates use repeating elements. These are expressed as loops. Loops are sections of XML that are repeated for every iteration of the internal loop.

If you want to repeat some XML elements multiple times mark them all (using Shift + Click) and then select "Edit" - "Wrap in Loop" from the menu. The loop element will be placed where those wrapped elements were and the wrapped elements will be placed inside the loop. This can be used to loop through text, table rows, or other XML elements.

You have to select a loop variable. See below for valid choices. The elements of the loop will be repeated for each iteration of the loop variable, this can be zero, one or multiple times.

Loops can be nested, but nesting the same loop variable may lead to undesired results.

Conditional Output

You can wrap elements in a condition. The condition can be any expression described above, excluding the "@" signs - the expression must yield a value that can be converted to boolean (bool, or numeric result).

To wrap some elements in a conditional mark them with Shift + Click, then go to the menu and select "Edit" - "Wrap in condition". All elements inside this new condition element will now only appear in the document if the condition expression yields boolean "true".

You can make some elements appear on "true" and some on "false" if you insert an "else" tag: mark the element directly before the position where you want to insert the "else" tag and then select "Edit" - "Insert else behind current". It is permissible to insert several "else" tag - each one inverting the one that came before it, but this is not recommended, since it can become quite confusing.

Calculations

You can insert calculations anywhere in the document. Calculations are formulas that are evaluated, but whose result is not displayed. It makes sense to use them for calculating values that you want to use later on or to split up complex calculations into simpler steps. The syntax is the same as for formulas above, but without the enclosing "@" signs.

Calculations inside conditionals are only executed if visible tags inside the conditional would be displayed (i.e. the condition is "true", or if behind an "else" tag: the condition is "false"). Calculations inside loops are executed for each iteration of the loop.


Event Summary

File name: eventsummary.odtt

Loops:
TICKETS - this loop iterates over the ticket price categories.
ORDERS - this loop iterates over all orders that contain tickets for this event.

Variables:
VariableDescription
@TITLE@title of the event
@ARTIST@artist of the event
@ROOM@room of the event
@START@start date and time in the currently active locale
@CAPACITY@maximum amount of tickets that can be sold
@RESERVED@tickets that are currently reserved for a seller
@BOUGHT@tickets that have been bought (used+unused)
@USED@tickets that have been used
@UNUSED@tickets that are still unused
@CANCELLED@tickets that were cancelled
@TOTALMONEY@the total amount of income for this event
@EVENTPRICE@the default price for this event
@TICKETS@the amount of ticket lines in the overview
@TICKETS:PRICE@the price of this category
@TICKETS:BOUGHT@used+unused
@TICKETS:USED@tickets from this category that have been used
@TICKETS:UNUSED@tickets from this category that were not used
@COMMENTS@the amount of (non-empty) comments attached to this event
@COMMENTS:ORDERID@the order-ID of this comment
@COMMENTS:CUSTOMERID@the ID of the customer this comment is attached to
@COMMENTS:CUSTOMER@the name of the customer this comment is attached to
@COMMENTS:TEXT@the text of the comment
@ORDERS@the amount of orders connected to this event
@ORDERS:ORDERID@the order-ID of this comment
@ORDERS:CUSTOMERID@the ID of the customer this comment is attached to
@ORDERS:CUSTOMER@the name of the customer this comment is attached to
@ORDERS:NUMTICKETS@number of tickets in the order that are for this event
@ORDERS:TICKETPRICE@the accumulated price of all tickets in that order for this event
@ORDERS:FULLPRICE@the full price of this order
@ORDERS:SHIPPING@description of the shipping method of this order
@ORDERS:SHIPPINGCOST@the full shipping costs for this order
@ORDERS:SHIPPINGCOSTWEIGHTED@the weighted shipping costs of this order (costs * ticketsforthisevent / ticketsintotal) - Warning: this may not add up correctly!
@ORDERS:SHIPPINGCOSTIFFIRST@contains the shipping costs if this event is the earliest in the order, zero otherwise
@ORDERS:SHIPPINGCOSTIFLAST@contains the shipping costs if this event is the last in the order, zero otherwise

Order Bills

File name: bill.odtt

Loops:
TICKETS - this loop iterates over each ticket in the order.
ACCTICKETS - this loop iterates over ticket categories in the order. Each category contains tickets for the same event with the same price.
ADDRESSLINES - this loop iterates over the lines of the address. (obsolete)
VOUCHERS - this loop iterates over all vouchers of the order.

Variables:
VariableDescription
@ORDERDATE@the date when this order has been generated
@ORDERDATETIME@the date and time when this order has been generated
@SENTDATE@the date when this order has been shipped
@SENTDATETIME@the date and time when this order has been shipped
@CUSTOMERID@the ID of the customer
@ORDERID@the ID of the order
@ADDRESS@the address of the customer
@FULLADDRESS@the name and address of the customer
@NAME@the name of the customer
@DELIVERYADDRESS@the address it is shipped to, if different from the customers address
@FINALADDRESS@equals DELIVERYADDRESS if it is non-empty, otherwise FULLADDRESS
@TOTALPRICE@the total price of the order
@AMOUNTPAID@the amount that has already been paid
@SELLER@the login ID of the seller (it is not recommended to use this)
@COMMENT@the comment in the order (it is not recommended to use this)
@AMOUNTTOPAY@the amount that still needs to be paid
@AMOUNTTOREFUND@the amount that has to be refunded
@SHIPPING@description of the shipping method used or empty string
@SHIPPINGPRICE@the costs for shipping
@TICKETS@the amount of tickets in the order
@TICKETS:PRICE@the price of this ticket
@TICKETS:ID@the ID of this ticket (barcode-string)
@TICKETS:TITLE@the title of the event for this ticket
@TICKETS:ARTIST@the artist of the event for this ticket
@TICKETS:DATE@the date of the event for this ticket
@TICKETS:STARTTIME@the date and start time of the event for this ticket
@TICKETS:ENDTIME@the end date and time of the event for this ticket
@TICKETS:ROOM@the room/place of the event for this ticket
@ACCTICKETS@the amount of distinct ticket types in the order
@ACCTICKETS:PRICE@the price of one ticket of this type
@ACCTICKETS:FULLPRICE@the accumulated price of all tickets of this type (PRICE*AMOUNT)
@ACCTICKETS:AMOUNT@the amount of tickets in this type
@ACCTICKETS:TITLE@the title of the event for this ticket type
@ACCTICKETS:ARTIST@the artist of the event for this ticket type
@ACCTICKETS:DATE@the date of the event for this ticket type
@ACCTICKETS:STARTTIME@the date and start time of the event for this ticket type
@ACCTICKETS:ENDTIME@the end date and time of the event for this ticket type
@ACCTICKETS:ROOM@the room/place of the event for this ticket type
@ADDRESSLINES@amount of lines that the address has (obsolete)
@ADDRESSLINES:LINE@current line in the address loop (obsolete)
@VOUCHERS@the amount of vouchers in the order
@VOUCHERS:PRICE@the price of this voucher
@VOUCHERS:VALUE@the (remaining) value of this voucher
@VOUCHERS:ID@the ID of this voucher