with 'software' tag
no identity crisis
i slipped in a bit to the item table in my nascent point-of-sale system that i introduced last time that i didn’t explain at all. it’s just a little thing, a column called id that is an auto-incrementing integer. we need a way to uniquely identify items, and that’s the fallback method for this broken-down php and mysql coder.*
on the other hand, dealing with ringing up customers and putting together orders from distributors, my experience has been that it is good to have a short-hand identifier for products that is not totally opaque like a bare number. you can see that the developers of php point of sale came to the same conclusion by their inclusion of a item_number field (which is not a number, but we won’t hold that against them). the point-of-sale system we are using currently has a unique identifier for items that they call the code, and the underlying numeric identifiers in the database are never actually exposed in the interface.
the codes we use to identify products are borrowed almost entirely from the way that our primary distributor identifies products. each code has a two letter prefix that identifies the brand of the product, and then the rest of the identifier is structured differently depending on the brand. another of our distributors uses a fairly similar system with the three-letter prefix separated by a dash. depending on the brand and product, this means that looking up similar products can be straightforward if you just remember a part of the code. for example, i have it baked into my brain that all art alternatives studio canvases have a code starting with 'AA55', so doing searches or reports on just those items means i can just type in that prefix instead of having to navigate a more complicated category system. not all of the brands have codes that are structured that conveniently — products from 3M, for example, have a prefix of 'MT' but the rest of the code is based on a portion of the UPC, and a line like all of the command hooks & clips doesn’t sit within the same numeric range so there’s no one prefix that will come up with just those.
another interesting thing to consider is that an identification scheme based on the brand isn’t stable. not too long ago, chartpak acquired the higgins brand from sanford, which meant in the language of the codes that our distributor uses (and we use), the prefix on the higgins items changed from 'SA' to 'CH'. how we track those sort of changes is something we’ll have to consider later, but it does demonstrate that relying on this code as our primary identifier would be unwise.
but i think the real bottom line is that these identifiers are just a unique opaque identifier for the users of the point-of-sale system, so the system doesn’t need to impose any structure on them. in fact, i’m not sure if i can come up with a reason why they shouldn’t be optional, so i’ve left it open to an item not having a code.
so here is the updated table with our newly-minted code field:
CREATE TABLE item (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
code VARCHAR(255),
retail_price DECIMAL(9,2) NOT NULL,
discount_type ENUM('percentage','relative','fixed'),
discount DECIMAL(9,2),
PRIMARY KEY(id),
UNIQUE (code)
);* so is an auto-incrementing integer really the best primary key to use? it may seem a little more grown-up to use something like a uuid, but while these identifiers may be intended to be hidden, as someone who will almost certainly be looking behind the curtain to run queries against these tables manually, relatively small integers are a whole lot easier to deal with than big hexadecimal ones.
the prices need to be right
i wasn’t entirely truthful when i said i wasn’t sure where to start when writing a point-of-sale system. clearly the place to start is with a model of the data you are going to be handling, and because we are retail store dealing mostly with items out of inventory, describing an item is probably the place to start with that.
php point of sale has a pretty simple item table:
CREATE TABLE `phppos_items` ( `name` varchar(255) NOT NULL, `category` varchar(255) NOT NULL, `supplier_id` int(11) DEFAULT NULL, `item_number` varchar(255) DEFAULT NULL, `description` varchar(255) NOT NULL, `cost_price` double(15,2) NOT NULL, `unit_price` double(15,2) NOT NULL, `quantity` int(10) NOT NULL DEFAULT '0', `reorder_level` int(10) NOT NULL DEFAULT '0', `item_id` int(10) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`item_id`), UNIQUE KEY `item_number` (`item_number`), KEY `phppos_items_ibfk_1` (`supplier_id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
it’s not a bad start, but it is very limited. the net cost of an item (cost_price in the table) is not a constant. prices change, different suppliers may charge different prices for the same item, and suppliers often have special deals based on quantity or time. and yes, suppliers with an 's', because we can get many items through more than one supplier.
even just two prices aren’t really enough: most of the items have net prices they are available to us at (depending on supplier and specials), the net price we actually paid for items in inventory, a retail price (also known as msrp), our every-day price (often a fixed percentage discount from msrp), limited-time sale prices, and even discounts based on a quantity of related items being purchased (buy six cans of spray paint, get them all at 25% off instead of 20% off). there’s also the price that someone actually paid for an item when they purchase it, which is usually derived from one of those others but could also be something that we further change or discount for a particular transaction. clearly, two fields in one table doesn’t quite capture this complexity.
if i were to really boil down the pricing in a primary item table, i think the only values that would be necessary are the retail price and our every-day price (expressed as a fixed price, relative price, or discount). even that retail price could arguably draw from the data that our suppliers provide, but we don’t always roll out changes to the suggested retail price at the same time our suppliers may update the pricing, and suppliers may not always agree on what the suggested retail price may be. so here’s my item table so far:
CREATE TABLE item (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
retail_price DECIMAL(9,2) NOT NULL,
discount_type ENUM('percentage','relative','fixed'),
discount DECIMAL(9,2),
PRIMARY KEY(id)
);obviously i haven’t yet captured all of the complexity that i’ve outlined above, but i’ll get there eventually.
piece of what?
i spend a lot of my day now dealing with a point-of-sale system that bothers me for the same reason that most software bothers me: it is broken and i can’t fix it. in this case, i can’t fix it because it is a closed-source application. one redeeming feature of the software is that it uses postgres as its back-end database, so it is relatively straightforward to get at the raw data and i’m not entirely hobbled by the slow, incomplete interfaces that the software itself offers. (instead i’m just hobbled by its baroque and undocumented schema and an inability to change or add to the data.)
so i have been poking around at the scant open source point-of-sale solutions, and they all generally look terrible, are complicated in directions that i don’t need complication, or are written in stupid languages like java.
php point of sale is way too simplistic, but it has helped me think about how i would (and likely will) build a point-of-sale system. unfortunately, i still haven’t figured out where to start.
so my hope is that if i start writing about it, i will find an entry point and i can eventually start building.
my mac essentials
whenever i see somebody’s list of essential mac applications, i am always a little surprised at how little overlap it has for me. now that i’ve mostly switched over the new macbook pro, here’s the list of applications that i have installed:
- acorn ($50): this is a nifty little image editing application. in the last few days, i have been using it to mock up shelving layouts for the store.
- bzr (free): this is the distributed version control system of choice at mysql these days.
- busysync: it would be nice to keep my google calender and ical in sync. after giving spanning sync a try for a bit, i am giving this a try as an alternative.
- delivery status: this dashboard widget is great for tracking the way-too-many packages that i get from amazon and other places.
- google notifier (no cost): now that i have switched almost entirely to using gmail, this is useful to let me know when i have new mail.
- linkinus ($20): i use this irc client for accessing the company chat server to connect with my mysql coworkers.
- menucalendarclock for ical (no cost or $20 for more features): i like this replacement for the date/time display in the upper-right of the menu bar, which drops down a full calendar, including upcoming ical events.
- myob accountedge ($300): this is for doing the books for the store and gallery.
- mysql (free): i have the standard mysql server package installed for testing.
- twitteriffic (ad-supported or $15): this is a not-too-obtrusive way of participating in twitter nonsense.
- virtualbox (free): i used parallels on my last machine, but i figured i would give sun’s own virtualization technology a spin. i use it to run a windows xp image for development using the microsoft toolchain and for accessing sun’s vpn.
- xcode (no cost): i don’t really use xcode itself, just many of the unix development tools that come along with it.
of the bundled software, i regularly use address book, ical, iphoto, itunes, mail (for my sun/mysql email), preview, safari, and terminal. and i use time machine, but i hope i don’t have to regularly use it.
must be something in the air
evan henshaw-plath coins the term coupleware — sites built for two, and brings up wesabe, the financial site i also had in mind when i wrote about services built for two.
how i work
dave rosenberg has been doing a series of “how i work” interviews and asked for more submissions. here is mine.
what is your role? i believe my title is still maintenance engineer, but i’m now actually a proper server developer at mysql. right now i’m doing some falcon-related work, but i hope to get back to working on pluggable authentication and authorization soon.
what is your computer setup? my desktop is a mac mini (powerpc), hooked up to a 20" apple cinema display. my development box, which runs headless and i just access with ssh, is an amd64 running ubuntu. i also have a 12" powerbook that i use when on the road (which isn’t often). my plan is to replace the mac mini and powerbook with a new macbook pro at some point down the line. this site also runs off a colo server.
what desktop software applications do you use daily? when i am working, i’m always running safari, terminal, itunes (plus synergy classic), colloquy (irc client), and the stickies application. i also have antirsi running to remind me to take breaks. i use mutt, running on my colo server, for all of my email.
what websites do you visit every day? i have my own rss aggregator that i use for reading various news feeds, and it has a blo.gs-based sidebar that lets me know when the various weblogs i am interested in get updated. i read planet apache, planet php, planet perl, planet mysql, and planet intertwingly regularly.
what mobile device or cell phone do you use? i have a motorola razr, and i sync my address book over bluetooth. i recently started using bluephoneelite, which lets me send sms from my computer, and also pops up caller information when i get a call on my cell.
do you use im? i went back to using ichat after dabbling with adium, but now that my fiancée celia is working from my couch, i haven’t even had a need to keep ichat running.
do you use a voip phone? every once in a while i’ll fire up sjphone to use the company’s internal voip network, and i’ll fire up skype once in a while.
do you have a personal organization/time management theory? not really. i use the stickies application to keep track of what i’ve done this week, and my short to-do list for work. my incoming email gets sorted into three folders: personal, work, and the mysql mailing lists (i’m subscribed to all of them). i try to keep the personal and work inbox to under thirty messages (generally successfully — they currently have nine and ten, respecitively), and i flush out the mailing list inbox regularly. we have a couple of monthly calendars on the fridge to keep track of upcoming events.
anything else? the whole cult of “gettings things done” creeps me out.
producing open source software by karl fogel (hardcopy) looks to be a very good book about the human side of producing open-source software.
don’t give up the fight
antirsi is a nice little application that sits in the mac os x dock and bothers you every so often to take short typing breaks and longer get-away-from-the-computer breaks. i’ve never had serious wrist problems, and i don’t really expect to have any since i am not much of a crank-code-out sort of programmer. i started using it to remind me to get up and give my back a break.
colloquy is a very slick open-source irc client for mac os x. after just a day of use, i think i may be ready to ditch snak.
one really slick feature is per-channel text encodings. so i can peek in the #russian channel on the internal irc server and see it in the right character set, even if i can’t read it.
mercurial is yet another version control system sparked by the no-more-free-bitkeeper kerfuffle.
the best part of matthew thomas’s review of usability problems with ubuntu is the punchline.
kragen sitaker wrote a great explanation of the meaning of “enterprise software”.
nobody tell ted turner
the examples from this paper about colorization using optimization (via wes felter) are really impressive. just dab some color on a black-and-white picture, feed it (and the original b&w image) through this process, and get colorized pictures out the other end. i wonder how long this will take to find its way into photoshop and the like.
the video clips are even more impressive.