/** * Convert serial quantities into tally quantities, and tally quantities into serials. * If you pass in an integer, it will allocate that many of your existing tally count into serials, * deleting from tally and adding serials. * if you pass in a list of serials, it will delete those serials from the inventory and convert them * into tally. */ public function convert($item_id, $quantity, $data = NULL) { Transaction::start(); try { if (Base::validatePositiveInteger($quantity)) { $this->subtract($item_id, $quantity, $data); $q = $this->quantity(); foreach ($this->newIds($quantity) as $serial) { $q->set($serial, array()); } $result = $this->add($item_id, $q, $data); } else { $this->subtract($item_id, $quantity, $data); $result = $this->add($item_id, Base::quantify($quantity), $data); } if (!Transaction::commit()) { throw new Exception('database error'); } return $result; } catch (\Exception $e) { if (Transaction::inProgress()) { Transaction::rollback(); } $e = new Exception('cannot convert: ' . $e->getMessage(), $e->__toString()); throw $e; } }
/** * @see Stockpile_Interface::add(); * on insert, set the pos column of the sort table to match current time. * on dupe key violation, update the pos column to match current time */ public function add($item_id, $quantity = 1, array $data = NULL) { $res = $this->core->add($item_id, $quantity, $data); try { $this->storage('sorter')->sort(Base::time(), array($item_id)); } catch (Exception $e) { throw $this->handle($e); } if ($this->cacher) { $this->cacher->set($item_id, $now, $this->cacheTimeout()); Transaction::onRollback(array($this->cacher, 'delete'), array($item_id)); } return $res; }
/** * @see Stockpile_Interface::subtract(); * do we need this function? if it turned into zero quantity, it already disappears. * do we need to clean up the sorting? */ public function subtract($item_id, $quantity = 1, array $data = NULL) { $res = $this->core->subtract($item_id, $quantity, $data); if (Base::quantify($res) > 0) { return $res; } try { $this->storage('sorter')->remove($item_id); } catch (Exception $e) { throw $this->handle($e); } if ($this->cacher) { $this->cacher->delete($item_id); } return $res; }
/** * @see Stockpile_Interface::add(); * only bump up to the top the first time we add this item id to the inventory. * after that, just let it slide. */ public function add($item_id, $quantity = 1, array $data = NULL) { $res = $this->core->add($item_id, $quantity, $data); $now = Base::time(); try { $ct = $this->storage('sorter')->sort($now, array($item_id), $ignore = TRUE); } catch (\Exception $e) { throw $this->handle($e); } if ($ct < 1 || !$this->cacher) { return $res; } $this->cacher->set($item_id, $now, 0, $this->cacheTimeout()); if ($this->inTran()) { Transaction::onRollback(array($cache, 'delete'), array($item_id)); } return $res; }
/** * @see Stockpile_Interface::set(); */ public function set($item_id, $quantity, array $data = NULL) { Transaction::start(); try { $current = $this->get($item_id); if (Base::quantify($current) > 0) { $this->subtract($item_id, $current, $data); } if (Base::quantify($quantity) == 0) { $result = $quantity; } else { $result = $this->add($item_id, $quantity, $data); } if (!Transaction::commit()) { throw new \Gaia\Exception('database error'); } return $result; } catch (\Exception $e) { $this->handle($e); throw $e; } }
/** * Write the item_id => total quantity pairing into the cache. * @param int item id * @param int total count, after db write * if the total is less than zero, write it in as undefined in the cache so it doesn't hit the * db again. With tally, the total is a number, but the serial total will be a quantity object. * no matter. we can get it's total value easily enough by just getting strval of it. * if there is a transaction attached, set up a callback to delete this key if the transaction doesn't work. * can't delete the cache key for history since variations are endless, but we can bust the key * using last touch. if we aren't in a transaction, just bust last touch right away. * check the id index so we can update it in the cache. * if nothing left of a given item, remove it from the index. * if the item id is in the index, no more work needed. * make sure the index is sorted the way it is supposed to be. * always sorted in numeric order of item id. */ protected function writeToCache($item_id, $total) { $cache = $this->cacher; $timeout = $this->cacheTimeout(); $cache->set($item_id, Base::quantify($total) > 0 ? $total : Store\Callback::UNDEF, $timeout); if ($this->inTran()) { Transaction::onRollback(array($cache, 'delete'), array($item_id)); Transaction::onRollback(array($this, 'lastTouch'), array(TRUE)); Transaction::onCommit(array($this, 'lastTouch'), array(TRUE)); } else { $this->lastTouch(TRUE); } $index = $cache->get(self::INDEX_CACHEKEY); if (!is_array($index)) { return; } if (Base::quantify($total) > 0) { if (in_array($item_id, $index)) { return; } $index[] = $item_id; sort($index, SORT_NUMERIC); } else { $found = array_keys($index, $item_id); if (count($found) < 1) { return; } foreach ($found as $k) { unset($index[$k]); } } $cache->set(self::INDEX_CACHEKEY, $index, $timeout); }