Force quantity column header on sales invoice to always show as “Qty”

Apologies if this has been addressed before. I seem to recall reading a similar topic, but I haven’t been able to find it.

I have inventory and non-inventory items denoted in various units of measurement, including metres, litres, hours, and just units. If I create a sales invoice with items of mixed units of measurement, the quantity column header displays as “Qty”. If I only have items of one unit type, the column header changes to that unit name (such as “Hours”). Is there a way I can force the template to use “Qty” in all scenarios?

I am in the process of setting up an electronic signature device to comply with local fiscalisation requirements. The software that communicates with our tax authority’s servers reads my PDF sales invoices and parses the data. The technician who has been helping me says that the quantity column header needs to be fixed, as the software will be trained to search for a single given string and cannot allow for all the possibilities I might use (“Hours”, “M”, “L”, etc).

You’ve already given the answer yourself: delete all units of measurement. (Or replace the technician).

Add a bogus line to each invoice with a different UOM and zero value so that every invoice has at least two UOM?

Change the technician is probably the better option :slight_smile:

@GrahamvdR, you do not mention what the software is searching. If it is the completed transaction, as displayed via a theme, you could use a substitution filter in the theme code that loops through column labels to check for any heading besides Qty and substitute your desired heading.

You could also eliminate all units of measure in item definitions and incorporate them into item descriptions.

1 Like

Thanks @Mark and @Joe91. I did consider those options. The units of measurement are useful, so I would prefer to keep them if possible, but that might be my most likely fall-back option. If I do that I will just be careful to name the items to include the unit (such as “labour per hour”, “cable per metre”, etc). Unfortunately I don’t think I’ll get any better help from the service provider, and they’ve already wasted far too much of my time, so I’m not going to try changing the technician.

I was considering seeing if I can accomplish what I need within the custom theme. Perhaps I can insert an “if” statement that checks the column header for all the possibilities and replaces it with “Qty”. I realise I’m on my own if I start playing with the theme code, but I was hoping that maybe someone else had been through this before and had written the necessary code. Or perhaps the developer would consider it a valid enough use case to build in the option to standardise the column header.

Thanks @Tut. It is searching the PDF of the sales invoice which I generate as soon as the invoice is finalised. It may or may not have a receipt allocated to it, so it could be partially or fully paid up, or not at all. I was thinking along much the same lines as you were, as seen in my text above which I composed before you posted your reply.

This issue has been discussed before, but for different reasons since most users just didn’t like the format.

Your case is different and your technician is probably correct since he will have to somehow id this shifty column.

Maybe if @lubos can add a name property to the columns so that:

  • column.name is always Qty
  • column.label can be “ml”, “kg” or whatever.

This way users will be able to tweak their themes to display fixed Qty column without the need for any serious changes to the program.

1 Like

It seems to me this is already possible with a single substitution filter. As long as you have decided to use a custom theme, adding such a filter would involve no change to the program at all.

But the column labels could be absolutely anything, which makes things tricky.

Then please let us know what that single substitution filter is.

The quantity column label will only be “Qty” or one of the units used for inventory or non-inventory items, so there are only about four possibilities in my case. Obviously I’d need to update my code if I add a new unit at a later stage, and anyone using the same code would need to check that all units they are using are included in the substitution. So it wouldn’t be a perfect solution, but certainly workable.

You only need to check whether the column label is not “Qty”, and if it is not substitute “Qty”. You do not need to test for all the other things it might be. In other words, make the substitution only if the test is failed, not if one of a list of other tests is passed.

The column labels are placed within a loop that iterates across all the columns, so changing anything that’s not “Qty” would also change the “Code”, “Description”, “Unit price”, and “Amount” column headers. I guess you could check for two conditions:

  1. Column is third in array
  2. Column label is not “Qty”

then perform the substitute if those two conditions are met. I was reluctant to do this because it is possible to add extra columns like “Discount” that might change the length of the array. I also have a custom line field that would come before the quantity column if it has a value, so in that case quantity would be the fourth column, not the third.

I have managed to get the header substitute working by checking to see if the column label is any of my units, but I’ve encountered another problem: When Manager replaces “Qty” in the column header with the unit, it removes the unit from the row. So, I now want to try to find a way to reinstate it there.

Sorry, I didn’t think about that. But you’re right.

That shouldn’t be a problem.

Capture column.label for third column.

Then run a condition for when the Qty column has a different name. In that case, insert two <td>s, one with the captured column.label and the other with cell.text. Else the code runs as-is.

But you should definitely mind any item custom fields, because they might change the column order.

1 Like

I seem to have got it working. I did the following:

  1. At the top of the table, create variables to hold values for the column index (a number) and the unit (a string): {% assign myUnitIndex = 0 %}{% assign myUnit = "" %}
  2. In the column heading, remove {{ column.label }} and replace with {% if column.label == "M" or column.label == "L" or column.label == "Hours" %}{{ "Qty" }}{% assign myUnit = column.label %}{% assign myUnitIndex = forloop.index %}{% else %}{{ column.label }}{% endif %}
  3. In the cell text, after {{ cell.text | newline_to_br }} add the following: {% if forloop.index == myUnitIndex %}{{ " " }}{{ myUnit | downcase }}{% endif %}

Step 2 checks to see if the column header matches any of my units, so I’ll need to update this if I create any new units. If there’s a match, it places the text “Qty” in the column header, assigns the matching unit to the variable myUnit, and assigns the column index to the variable myUnitIndex.

Step 3 checks to see if the column index for the cell matches the column index saved to the variable in step 2. If it does (ie if it’s in the quantity column), it adds a space followed by the unit converted to lowercase. This hopefully avoids any problems arising from item custom fields or anything else that might change the number of columns or column order.

So, it’s a slightly cumbersome workaround, but after initial tests the result seems to be exactly what I wanted.