Vegetables are driving me crazy!

Ever since the last typhoon, the vegetable situation here has been absolutely crazy. This is not an unusual phenomenon; after any typhoon prices usually jump up, but usually just for a few days. But here we are weeks later and still having problems. Previously our problem was related to price. Tomatoes were the worst, tripling in price to TW$180/kg. We had been product testing using pre-shredded lettuce instead of shredding it in-store but they announced they’d be going to TW$200/kg for that so we switched back to shredding it ourselves.

Today our main vegetable supplier only delivered half our vegetable order to each of our stores. They cited market shortage as the reason for the cut in our order. But that leaves us kinda stuck. We order based on our sales level, so having our order suddenly cut means we don’t have enough. On the other hand, Subway specifies how much of each vegetable goes in a sub and that we can only buy from authorized vendors.

All this means we are stuck with no good choice on how to resolve the problem.

One Hour: 312 Free Hot Subs Given Away


http://www.youtube.com/watch?v=TcosWu-qzBE

To celebrate the 10th Anniversary of SUBWAYâ„¢ in Taiwan, participating restaurants had a free hot sub giveaway for one hour on 2007-10-26. This is a time-lapse video from SUBWAYâ„¢ Qingcheng Restaurant where we gave away 312 free hot subs in one hour.

SUBWAYâ„¢: http://www.subway.com/

SUBWAYâ„¢ Qingcheng Restaurant: http://jimmys.tw/subway/36096/

The SUBWAYâ„¢ trademarks are owned by Doctor’s Associates Inc. and the independent franchised operator of this restaurant is a licensed user of such trademarks.

Media Coverage of Free Sub Giveaway

We’re getting some nice news coverage of the free sub giveaway. There was a news segment on ERA TV News (Channel 50) covering the event at the Neihu Ruiguang store. Lots of happy customers trying out the found, some great shots of the subs being made, and a short interview with Brendon, the store owner. It is nice to get a good event like this covered by the media.

Wow! 546 free subs in one hour!

We gave away 312 free subs at Qingcheng Restaurant and 234 free subs at Xingtian Temple Restaurant in just one hour today. One of the other owners gave away even more than that and also had two TV news crews covering the event at his restaurant. We also gave away buy one get one free coupons with every free sub in the hopes that we can get some new customers out of the event. All in all I’m very happy we got to give a lot of potential customers a taste of our food and service.

On Board

Every year each Subway market elects an board of franchisees in the market who will decide how to spend the advertising contributions in the market. Our election for the Taiwan board was in September and I ran for a seat (last year I didn’t qualify as I hadn’t been open long enough). Unfortunately I did not earn a seat in the election and was tied as second runner up. Today I found out that one of the board members resigned. The first runner up passed on the seat and the person I was tied with deferred to me, so I’m now on the Subway Taiwan ad board.

Web application development (part 4)

Et voila! My first application is complete. Since the last post I extended the edit module so that it would put in blank boxes for hours the store is open but for which there isn’t data already stored. (Actually I just have it put in entry boxes for everything from 8a to 11pm for every day, even though my Xingtian Temple restaurant is only open 10a-10p and Qingcheng restaurant is only open from 10a-10:30p on Saturday & Sunday. I’ll have to add in more smarts later so it will look at what hours the store is actually supposed to be open for.)

I encountered another couple of difficulties here, namely that when you add new inputs you have to also have a hidden form value for the foreign key id for the main table. So in my case since the main table is Daily and the multiple data fields are hourly, I have to have a hidden form value for data[Hourly][index][daily_id].

When it was editing existing fields this wasn’t a problem since it would figure out the missing values based on data[Hourly][index][id]. However when you are adding new stuff it is unable to make the connection and so the data gets stored without the foreign key and doesn’t get associated correctly. You also have to do the correct magic to create a new object when saving new (as opposed to updated) data, but that’s straightforward from the add example I referenced in part 3.

I also completed the add controller and add view with the ability to add the daily and hourly data all on one screen. This was actually quite straightforward once the edit stuff was done. Again, the main hitch is making sure you get the hidden field for the foreign key id in there or it won’t go in the db correctly.

The final piece was to give me a scheduling view. Basically I set up a scheduler controller and view under dailies which would take a store number, number of weeks and ending date of the schedule analysis. The last two are optional and default to 1 week and the date of the latest daily in the db for the store, respectively. It then will make up an average of units sold for each hour on each day (i.e. each of the Tuesday’s 8:00 sales averaged, etc.) and based on that would give a number of hours to schedule each employee.

I can’t describe it in much more detail than that because while this sort of calculation is common in food & beverage operations, the details of the method SUBWAYâ„¢ uses is proprietary. I’m still tweaking the algorithm on how to do the scheduling, but right now it’s roughly based on the Subway method with a few tweaks to make it look better to me. I also need to make the tweak parameters configurable in the database instead of hard coded in the code, but that’ll have to wait a bit.

It looks like I can cut down my morning and afternoon scheduling a bit and actually could use a bit more people at lunchtime than I had thought. But also overall it looks like I should be able to save quite a bit on labor costs with a more efficient schedule while at the same time improving service levels during busy times.

There’s a few other things I need to do. For example, there’s a fair amount of code that I probably should have put in the controller that I put in the view instead. I think I reverted to non-MVC programming practices quite a bit. I think from the MVC philosophy you shouldn’t be doing much more than displaying stuff in the view. Anything where it is calculating stuff should be in the controller. I also need to figure out how to modularize the code better.

But, hey, it works. Woo woo!

Web application development (part 3)

Well I didn’t quite get my first webapp done in time for last week’s meeting. Actually I got it mostly working, but the interface was not to my liking and I wasted a lot of time flailing about trying to figure out how to do what I wanted. I finally figured out how to do that so it shouldn’t be much longer before I have things completed.

Basically the issue is that I want to enter sales data for each day and each store. Each day has some data associated with the day over all, and then it also has breakdowns of specific data on an hourly basis. Or in CakePHP model lingo, stores hasMany dailies hasMany hourlies. The problem is that I want to view (index), add and edit the daily AND hourly data together on one form. The alternative is to enter the daily data, then add an hour, enter than data, add an hour… ad nauseum. There’s a limited and known amount of hourly data to enter, so it would be much easier to get it all over and done with in one form.

Getting the view to show dailies and hourlies together was straightforward. The scaffolding did a decent job of that by default so I was able to bake the scaffold view and modify it to my preference. The default data structure will automatically load the daily and related hourly data together when using the appropriate data loaders on properly associated models.

The editing/adding was a bit stickier. CakePHP’s form helper doesn’t handle this kind of thing at all currently. Basically if you aren’t editing a single row in a single table, you’re on your own, bub. The breakthrough was in finding this post on cake.php. It’s not exactly what I wanted, but it set me on the right track. The difference is they are editing multiple records from the same table together while I want to edit a single record from one table and multiple records from a related table together.

Fortunately the principle in both cases is similar. In my case I started with modifying the edit controller/view first. All the records I want to modify already were getting loaded automatically since the models had the proper associations set up. In my view I had to just loop over individual hours and set up form entries for each of them. Hour and id are hidden since those should not be changed.

The core of the edit view code to do this is as follows:

<?php foreach (array_keys($this->data['Hourly']) as $key):?>
<tr>

        <input type="hidden" name="data[Hourly][<?php echo $key; ?>][id]"
        value="<?php echo $this->data['Hourly'][$key]['id']; ?>" />

        <input type="hidden" name="data[Hourly][<?php echo $key; ?>][hour]"
        value="<?php echo $this->data['Hourly'][$key]['hour']; ?>" />

        <td><?php echo $pretty->hour($this->data['Hourly'][$key]['hour']);
                ?></td>

        <td>
        <input type="text" name="data[Hourly][<?php echo $key; ?>][hrtickets]"
        value="<?php echo $this->data['Hourly'][$key]['hrtickets']; ?>" />
        </td>

        <td>
        <input type="text" name="data[Hourly][<?php echo $key; ?>][hrgross]"
        value="<?php echo $this->data['Hourly'][$key]['hrgross']; ?>" />
        </td>

</tr>
<?php endforeach; ?>

It’s actually pretty straightforward conceptually, it was just getting the right incantation for it that was the problem, as this kind of thing is not covered in manual at all, and as mentioned, the forms helper doesn’t have code to do this kind of thing for you.

Then in the edit controller for dailies I originally had this (standard) code to save the modified data:

$this->Daily->save($this->data)

That will only save updates to the ‘Daily’ entries but not the ‘Hourly’ entries so I had to add:

foreach ($this->data['Hourly'] as $hourly) { $this->Hourly->save($hourly); }

This is a little bit simpler than the example in the above post. That’s because this is saving edits to existing data, so the ‘id’ field of each record is populated. In the add controller you need to do like the example in the post because the ‘id’ fields are empty in an add, so if you don’t create separate objects then the saves will just keep overwriting the first record over and over.

Anyways, the edit view and controller is already all set and working mostly the way I want it now. Getting the add view and controller working should be fairly simple at this point as that one is closer to the cake.php post I referenced. I might want to do something a bit fancy later by adding in forms for ‘missing’ hours in the edit, but that’s just spit and polish.

I’d be curious to know if the other MVC frameworks handle the case of adding/editing associated hasMany tables together in a more elegant manner?