Author Archives: markn

About markn

Mark is the owner and founder of Timesheets MTS Software, an mISV that develops and markets employee timesheet and time clock software. He's also a mechanical engineer, father of four, and a lifelong lover of gadgets.

    Find more about me on:
  • googleplus
  • linkedin

WooCommerce – Receive Copies of Customer Emails

If a user is new to WooCommerce it can be a little confusing what emails a customer is receiving and exactly what events are triggering the delivery of emails. To help alleviate the problem it can be useful to deliver copies of all customer emails (see the WooCommerce Email Notifications screen below) to another email address so they can be monitored.

WooCommerce Email Notifications Screen

In this case the woocommerce_email_headers() filter is useful. It allows you to intercept the email header and inject your own custom headers of the same form used by the PHP mail function. In my case I was happy to include a CC email address so I used this code:

//
//Send copies of customer emails to someone@somewhere.com
//
add_filter( 'woocommerce_email_headers', 'copy_customer_emails_headers_filter_function', 10, 2);

function copy_customer_emails_headers_filter_function( $headers, $object ) 
{
    if ($object == 'customer_completed_order' || $object == 'customer_invoice' || $object == 'customer_note' || $object == 'customer_on_hold_order' || $object == 'customer_processing_order' || $object == 'customer_refunded_order') 
    {
        $headers .= "CC: Someone <someone@somewhere.com>" . "\r\n";
    }

    return $headers;
}

The code itself is fairly self explanatory. It checks the passed object and if it’s one of the customer notification emails then the “CC: Someone <someone@somewhere.com>” . “\r\n” string is appended to the email headers. That email address will now receive a copy of all the emails sent to a customer. Of course the customer will see the CC address in their emails so you could include a BCC address with something like “Bcc: Someone<someone@somewhere.com>\r\n”.

WooCommerce – Default Manage Stock and Sold Invidually Values

I’ve had the somewhat dubious pleasure of launching a new WordPress / WooCommerce site for an established collectables business. The site replaced an aging cart system, that was frankly a steaming pile. Almost every item sold by this business is unique so they wanted to default the values for Manage Stock to true and Sold Individually to true.

The WooCommerce Inventory Screen

It turns out the easiest way to do this is to add some javascript to the admin_enqueue_scripts action that checks the form elements we need checked. Poking about with the Chrome element inspector at the WooCommerce stock handling form told me we needed the _manage_stock and _sold_individually checkboxes ticked and to set a value in the _stock text field. Here’s the code I put in my child theme’s functions.php file.

//
//set default stock handling values
//

    add_action('admin_enqueue_scripts', 'wc_default_variation_stock_quantity');

    function wc_default_variation_stock_quantity()
    {
        global $pagenow, $woocommerce;

        $default_stock_quantity = 1;
        $screen = get_current_screen();

        if ( $pagenow == 'post-new.php' && $screen->post_type == 'product')
        {
            ?>
            <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
            <script type="text/javascript">
                jQuery(document).ready(function () {
                    if (!jQuery('#_manage_stock').attr('checked')) {
                        jQuery('#_manage_stock').attr('checked', 'checked');
                    }
                    if ('0' === jQuery('#_stock').val()) {
                        jQuery('#_stock').val(<?php echo $default_stock_quantity; ?>);
                    }
                    if (!jQuery('#_sold_individually').attr('checked')) {
                        jQuery('#_sold_individually').attr('checked', 'checked');
                    }

                });
            </script>
            <?php
        }
    }

The code itself is fairly simple. The javascript is injected into the document.ready function but only if we’re adding a new post and the post type is WooCommerce’s product post type. The appropriate checkboxes have their checked attribute set to true and the _stock field is set to a value of 1 if it’s currently zero. Simples!

Munich Dunkel

With summer coming to an end I am looking for a darker winter beer to drink that is an easy quaff. Sticking with my recent history of German styles I bought a couple of commercial Dunkels and liked what I tasted. So Dunkel it is. The Dunkel is a dark, transparent lager brewed with darker Munich malts and sometimes some pilsner malt. It is supposed to have a sweeter dark malt profile with a moderate spicy hop aroma. I surfed around various beer recipe sites before settling on a simple recipe that I thought would suit my palate. I adapted the recipe using the trusty BIAB recipe spreadsheet tweaking it for my usual no chill / 30 minute technique.

13 February 2017

Munich Dunkel

12.5L BIAB
1.052OG
1.014FG
44.3BC
18.6IBU

Munich 1 Malt 1.4kg (11.29EBC)
Pilsner Malt 1.4kg (4.56EBC)
CaraAmber 0.25kg (9.96EBC)
Carafa 2 0.1kg (35.15EBC)

Pitch onto Fermentis SAFLAGER 34/70 yeast cake from a previous Bohemian Pilsner brew.

15L strike water at 72C with 69C target mash temp. Stir every 20 minutes of mash. The temperature at the start of the mash was 67.6C and at the end of the mash the temperature was 65.2C. At that point I squeezed the bag and sparged it with 4L of cold water. This resulted in 17.5L of pre-boil wort with an SG of 1.036 at 50C. Temperature corrected to 1.045.

30 minute boil

6g Nugget 15.5%AA @ 30 minutes
20g Saaz 4.4%AA @ 10 minutes
1/4 of a Whirlfloc tablet @ 10 minutes.

This hop schedule gave a projected bitterness right at the bottom limit of the style. Because I no chill I’ve perceived that a lot of my beers have been too bitter even when counting flameout and 5 minute additions as 10 minute additions. So when devising this recipe I used those allowances AND aimed for IBU’s at the bottom limit of the style hoping it would end up right on target.

As usual when the boil was done I stuck the whole pot in a my fermentation fridge and allowed it to get the wort down to 12.5C. The next day when it was at the correct temperature I tipped the lot onto the yeast cake of my last brew and aerated it vigorously with my giant brew spoon. Original gravity was finalised at 1.050. There was 14.5L of wort in the fermenter. I’ll be using the usual fast lagering method for this beer before bulk priming and bottling.

Fermentation Log

14-2-17 – Into fridge at 12C
27-2-17 – ramp temp up to 20C over three days
2-3-17 – Cold crash to 3C
4-3-17 – Bottle with 130g of priming sugar to get 18.5 740mL bottles. FG measured at 1.019 which was too high. Perhaps due to not leaving at 20C long enough?

Tasting

Well I couldn’t wait with this one and opened a bottle just 8 days after bottling and surprisingly it was reasonably carbonated and poured fairly clear. It had a lovely creamy tan head which didn’t hang around too long most likely due to it not being in the bottle long enough. It was super easy to drink and very toasty with just a hint of the dark malt burnt flavor which is not really appropriate for the style. To my palate the bitterness was spot on and it went down just a bit too quickly! I don’t see this brew hanging around too long and can’t wait to try it again to iron out a couple of wrinkles in the process and perhaps tone down the impact of the Carafa 2 specialty malt a little bit.

Munich Dunkel

Bohemian Pilsner with Flameout Hop Addition

This is the third time I’ve brewed this particular Bohemian Pilsner recipe with the only variation being a flameout hop addition of Czech Saaz. Last time I brewed it the hop flavour was a bit grassy and overpowering, so I’ve dropped the addition to 25g down from 35g last time.

29 January 2017

Bohemian Pilsner

12.5L BIAB
1.055OG
1.015FG
8.6EBC
32.3IBU

3kg Gladfield Pilsner Malt (3.8EBC)
0.26kg Weyermann Vienna Malt (7.5EBC)
Fermentis SAFLAGER 34/70

15L strike water at 72C with 69C target mash temp. Stir every 20 minutes of mash. At the end of the mash the temperature was 67C. At that point I squeezed the bag and rinsed it with 4L of cold water. This resulted in 17.5L of pre-boil wort with an SG of 1.037 at 51C. Temperature corrected to 1.046.

30 minute boil

7g of Warrior 15.5%AA @ 30 minutes
17g Saaz (4.4%AA) @ 15 minutes
15g Saaz (4.4%AA) @ 10 minutes
1/2 whirlfloc @ 10 minutes
25g Saaz (4.4%AA) @ Flameout.

I followed my usual no chill routine to get the wort down to 12.5C. At that point I poured it into my sterilised fermenter and took at gravity reading of 1.053. There was 13.75L of wort in the fermenter which I aerated and then sprinkled the yeast on top. This will be using the Brulosopy Fast Lager method which means leaving it at 12.5C for 5 days before allowing the temperature to ramp up to 20C over 2 days, holding at 20C for a week or so before fining with gelatin and cold crashing.

Fermentation Log

30/1/17 – Set temp of 12.5C.
6/2/17 – +3C each day until 20C
8/2/17->11/2/17 – 20C
11/2/17 – Fine with gelatin
11/2/17->13/2/17 – Cold crash to 1C

13/2/17 bottled after bulk priming w/130g of sugar. Forgot to take final gravity reading before bulk priming, gravity after bulk priming was 1.019.

Australian Pale Ale with Stella / Ella Hops

I haven’t been posting much here recently about my home brewing activities. Actually I haven’t been posting much here about anything. But nevermind. I’m posting now because I just filled up my good old pen and paper notebook and the last half dozen or so brew days are about to be consigned to an archive box so I figured I should really start logging things online again so I can look back at my brew logs more easily.

26 November 2016

Australian Pale ale with Stella / Ella Hops

This was a leftover/bitsa brew. I had a whole packet of Stella / Ella hops (14.6% AA) I wanted to use up. A goal was to keep the grain bill simple, use a single hop, and produce an easy drinking ale.

12.5L BIAB
1.046OG
1.012FG
13.4EBC
32.6IBU

2.6kg Barret Burston 2 Row Ale
0.14kg Crystal Pale 100
US05 SAFALE yeast

15L strike water at 70C with 68C target mash temp. Stir every 20 minutes of mash. At the end of the mash the temperature was 66C. At that point I squeezed the bag and rinsed it with 4L of cold water. This resulted in 18L of pre-boil wort with an SG of 1.027 at 48C. Temperature corected to 1.035.

45 minute boil

5g Ella @ 30 minutes
5g Ella @ 15 minutes
15g Ella @ 5 minutes
1/2 whirlflow @ 5 minutes
20g Ella @ Flameout

No Chill. As usual for my no chill brews I’ve considered all additions later than 10 minutes as 10 minute additions. At the end of the boil I put the wort, boil pot and all into my fridge and let it cool for 18 hours down to my target fermentation temperature of 18C. I cleaned and sterilised my trusty fermenter, dumped the cooled wort into it, at this point I had 14.5L of wort with a measured gravity of 1.046. I aerated the wort with my big old spoon, sprinkled my yeast, put the lid on and put the fermenter back in the fridge to do it’s think for a couple of weeks. I plan to let it ferment out for a week, fine with gelatin, chill for a few days and then bottle.

Fermentation Log

27/11/16 – Set temp of 18C.
28/11/16 – Fermentation appears to have started.
7/12/16 – Fined with Gelatin
9/12/16 – Cold crash to 3C.
11/11/16 – Bottled, bulk primed with 130g of sugar and total yield was 12.2L of beer.

Opened a bottle 7 days later and it was almost fully carbonated with a creamy pale cream head that last nicely and gave good lacing. Aroma was slightly fruity, and colour was a dark amber, quite a bit darker than I expected. The beer was also quite bitter, perhaps slightly out of balance with the malt character. There’s a couple of reasons why it might have seemed bitter, firstly it might be because it actually was, my no chill method sometimes leads to overly bitter beer especially with lots of late hop additions like this one. Alternatively I might have just perceived it as being more bitter because I’ve been drinking beers with lower IBU’s like Munich Helles (IBU 14.2) and Bohemian Pilsner (25 IBU) while this Ale had a predicted IBU of 33. Anyway, I only noticed the bitterness for the first glass, by the second glass my palate had adjusted and I enjoyed it immensely.

Ella Pale Ale

Ella Pale Ale

If I was to make this beer again I’d probably drop the late hob additions by 5g each.

Managing Bulk URL Exclusions in Adwords

The Google Adwords online interface is horrid. Just abominable. I am sure they all went to iOS UI design school and said, well Apple’s UI is shit but I am sure we can make our stuff shitter. And so they did. Anyway, I manage a very long list of URL exclusions for one of my Display Network campaigns and there’s (apparently) some limit to the number of URL’s you can exclude directly from the campaign placement report. When you exceed the limit (whatever that is) and you try to exclude a URL (using the Edit->Exclude (campaign) option) you get this (fucking) useless error message:

useless-message

Thanks. A. Lot. You useless pack of dickheads.

Anyway after trying Google’s live support (useless), and their online forums (which only dream of one day being merely useless) I finally worked out that my list of exclusions had gotten too long. So, now I got to dig around in the online Adwords UI looking for a way of having a longer list. There is a way, but oh my goodness, finding it makes Indiana Jones’s quest for the Lost Ark of the Covenant look like a stroll to the local shop for a carton of milk by comparison. Again. Fuck. You. Google. Anyway, you manage the list from within the Campaign->Display Network tab of the Adwords system. Click on the TARGETING button, then look in the PLACEMENTS box (second from the top) and click the stupid little pencil icon to edit the placement list.

useless-message-2

Once you’ve done that you’ll see something like that below. Click the LISTS button

useless-message-3

Once you’ve done that you’ll be given an option to CREATE AND MANAGE LISTS. Once you’ve clicked on that option you can create a new URL exclusion list which can contain a very large number of exclusions. What is the very large number? I have no clue as the Adwords documentation sucks seven different types of ass. But my list is several thousand URL’s long and it seems to still be working OK.

Anyway, after spending several hours working this out you can probably sense my frustration with the Adwords management system. I get similar levels of frustration when I am forced to use iTunes but I have to say that the Adwords UI has taken it to a whole new level. Congratulations you asshats.

Running a PHP Script on a QNAP TS-431

I needed to setup a persistent cron job on my QNAP TS-431 that would run a PHP script (actually the script that let’s me always know what the IP address of my home router is from anywhere in the world). However, the QNAP has the php executable buried and the directory is not in the $PATH environment variable. It’s not too hard to find though, if you need to run a PHP script just do this:

mnt/ext/opt/apache/bin/php /path/to/some-php-script.php

Specify a SSH Key for rsync

If you use rsync with the -rsh=ssh option it looks for a private key called id_rsa in the ~/.ssh folder. If (for whatever reason) you want to specify a different private key from the default then you can do it with:

-e ‘ssh -i /some/path/some_key’

This can be useful if want a key per host. Or, if like me, you idiotically created the keys with a different name than the default.

Persist crontab Entries on QNAP TS-431

QNAP helpfully explains how to add items to crontab on one of the NAS machines on their wiki here. Less helpfully they don’t explain that adding jobs with crontab -e and then restarting the cron daemon won’t persist through a reboot. Yay. However, you get around this by adding jobs directly to /etc/config/crontab. Once you’ve done that reload the crontab file and restart the CRON daemon with:

crontab /etc/config/crontab && /etc/init.d/crond.sh restart

Thanks fellas.

Brew Day 14 – Sweet Stout

It seems counter-intuitive to be brewing a stout on only the fifth day of Autumn in southern Australia as the weather is still hot, not exactly the best weather for a stout. Stouts, I am told, do benefit from a month or two in a secondary so if I want one to drink during the cooler weather now is the time to be be brewing it. Last year I brewed a “two can” stout using a can of Cooper’s Dark Ale and Cooper’s Stout and some dark malt extract and it turned out very nice but the ABV was above 8%, too much for a two pot screamer like myself. I’ll brew one of these again this year but I wanted something a bit easier to drink as well, something along the lines of a Guinness Irish Stout. The recipe on this page looked interesting so I decided to give it a go. I had to scale it down to 3 gallons (12L),to account for my BIAB efficiency (65%) and for the 5.7%AA East Kent Goldings hops I had on hand. I also wanted to add some flaked oats to the recipe for a bit of a silkier mouth feel. My trusty BIAB spreadsheet was given a workout and I arrived at the following:

Ale Maris Otter 2.4kg
Roasted Barley 0.24kg
Flaked Barley 0.16kg
CaraPils 0.16kg
Acidulated Malt 0.16kg
Flaked Oats 0.16kg

EKG 23g (5.7%AA) @ 90 minutes
EKG 8g (5.7% AA) @ 45 minutes
1/2 Whirlfloc @ 5 minutes

Nottingham Ale Yeast

Brew Type : 12L All Grain (BIAB)

OG: 1.049
FG: 1.013
ABV: 4.7%
IBU: 37.7
EBC: 76.5

I am doing no-chill again here and seeing that the hops additions are very early I am not making any hop adjustments to allow for the no chill. Given the cascading series of errors I made in the last brew I took some more care with this brew with regards to the mash volume and sparge volume. Working from my previous brews I allowed for a mash absorption of 0.7L/kg of grain. Given I wanted 12L of beer I allowed for 0.25L of fermenter loss and 0.5L of kettle loss meaning I wanted a post boil volume of 12.75L. My typical boil losses are 3L/hr so I wanted a post mash volume of 17.75L which meant a pre mash volume of 20L, split into a 15L mash and 5L sparge.

Mashing In

Mashing In

The Mash

The target mash temp was 68C and I heated 15L of strike water to 71C in my bag lined pot. Once I’d reached the temperature I poured in my crushed grains and mixed it thoroughly for a few minutes. The lid went on the pot and I wrapped it all in a thick doona. At this point the mash temperature was 68.9C. Last brew I had an awful mash efficiency which I suspected was due to not mixing the mash enough. I resolved to mix this mash every 20 minutes which I went ahead and did at 20 minutes and 40 minutes into the saccharification process. At the 40 minute point I returned the pot to my gas burner for a few minutes to bring the temperature back up to 68C. At the same time I heated 5L of sparge water to 70C.

When 60 minutes was up I collected up the edges of my brew bag and holding it with rubber gloves spun it tight to extract as much of the sweet wort as possible. Once that was done I topped my pot with a holed pizza tray that happens to fit perfectly into the opening and pressed down on the bag to extract more wort. I then put the bag straight into the 5L of sparge water and pressed down on it again to rinse off the remaining sugars before squeezing the bag again on my pizza tray topped pot and tipping in the sparge water.

Expended Grain Bag

Expended Grain Bag

Hop Additions

Hop Additions

Boiling Wort

Boiling Wort

The Boil

At this point I had 19L of wort in my pot, 1.25L more than I had expected. I took at gravity reading (1.031 at 53C) and brought the wort to the boil (which took about 45 minutes) before making my first 23g East Kent Goldings hop addition. The second 8g addition was made at 45 minutes and finally half a Whirlfloc tablet went in with 5 minutes remaining. At the end of the boil there was 14L of wort in the pot. The pot with lid in place was then put into my temperature controlled refrigerator to cool to pitching temperature overnight.

Taking a Gravity Reading

Taking a Gravity Reading

Fermentation

At 10AM the next day (6 March 2016) the wort was sitting at a steady 18.5C. I sterilised my fermenter and poured the wort into the vessel, took a gravity reading (1.051) and aerated thoroughly with a large sterilised plastic spoon. I pitched the Nottingham yeast, put the airlock in place on the fermenter and put it into my fermentation chamber with a set temperature of 18.5C. Funnily enough just two hours later I saw signs of fermentation in the airlock and the next morning it was bubbling vigorously.

Yeast Pitched

Yeast Pitched

Taking another SG Reading

Taking another SG Reading

Mash Efficiency

It appears that the steps I took to improve mash efficiency worked as I managed 75% on this brew. I did my usual calculations in Excel to arrive at the mash efficiency:

Kg Potential Pounds Potential Points
Ale Maris Otter 2.40 1.038 5.28 41.8
Barley Roasted 0.24 1.025 0.528 2.7
Barley Flaked 0.16 1.032 0.352 2.3
CaraPils 0.16 1.033 0.352 2.4
Acidulated Malt 0.16 1.038 0.352 2.8
Oats Flaked 0.16 1.037 0.352 2.7
Potential 54.82
Actual 41.00
Efficiency 74.8%