stock_id = $stock_id; $this->startLocation = $startLocation; $this->parameters = $parameters; $this->qoh = get_qoh_on_date($this->stock_id, $startLocation); }} public function toPick($order) { $picked = Std::parseInt($order->to_pick); $user_picked = null; if($this->parameters !== null) { $user_picked = $this->parameters->toPick($order); } return (($user_picked === null) ? $picked : $user_picked); } public function action() { if($this->parameters !== null) { $»t = ($this->parameters->mode); switch($»t->index) { case 0: { $this->update(); }break; case 1: { $this->cancel(); }break; case 2: { }break; } } } public function cancel() { $this->parameters = null; } public function update() { $orders = $this->orders(); $priorities = Lambda::harray(Lambda::map($orders, array(new _hx_lambda(array(&$orders), "ItemScheduler_0"), 'execute'))); $priorities->sort(array(new _hx_lambda(array(&$orders, &$priorities), "ItemScheduler_1"), 'execute')); $iter = $priorities->iterator(); $p = $iter->next(); $position = 0 - $priorities->length; { $_g = 0; while($_g < $orders->length) { $order = $orders[$_g]; ++$_g; $new_priority = DateTools::delta($p, 1000 * $position); update_order_detail_priority($order->id, $new_priority->toString()); if(Std::parseInt($order->to_pick) !== $this->toPick($order)) { update_pick($order->id, $this->toPick($order)); } $position += 1; $p = $iter->next(); unset($order,$new_priority); } } update_queue_quantity_for_item($this->stock_id); } public function needsUpdate() { return $this->parameters !== null && $this->parameters->mode == ScheduleMode::$Move; } public function purcharseOrders() { $TB = FA::tb(); $sql = "SELECT SUM(quantity_ordered - quantity_received) as quantity\x0A\x09\x09into_stock_location AS location\x0A\x09\x09FROM " . $TB . "purch_order_details\x0A\x09\x09NATURAL JOIN " . $TB . "purch_orders\x0A\x09\x09WHERE item_code = \"" . $this->stock_id . "\"\x0A\x09\x09AND quantity_ordered > quantity_received\x0A\x09\x09GROUP by item_code,delivery_date, into_stock_location\x0A\x09\x09ORDER by delivery_date"; return FA::query($sql); } public function locations() { $TB = FA::tb(); $sql = "SELECT * \x0A\x09\x09FROM " . $TB . "locations"; $_locs = new _hx_array(array()); if(null == _hx_qtype("FA")) throw new HException('null iterable'); $»it = FA::query($sql); while($»it->hasNext()) { $row = $»it->next(); $location = new Location($row); if($location->code === $this->startLocation) { $location->delivery = Date::fromTime(0); } else { if($location->delivery === null) { continue; } } $_locs->push($location); unset($location); } return $_locs; } public function orders() { $_g = $this; $rows = $this->loadOrders(); $orderList = new _hx_array(array()); $»it = $rows; while($»it->hasNext()) { $row = $»it->next(); $a = php_Lib::objectOfAssociativeArray($row); $order = $a; $order->priority = Date::fromString($a->pp); $order->quantity = $a->qty; $orderList->push($order); unset($order,$a); } if($this->parameters !== null) { $orderList->sort(array(new _hx_lambda(array(&$_g, &$orderList, &$rows), "ItemScheduler_2"), 'execute')); } { $_g1 = 0; while($_g1 < $orderList->length) { $order = $orderList[$_g1]; ++$_g1; unset($order); } } return $orderList; } public function loadOrders() { $tb = TB_PREF; $sql = "SELECT * , d.quantity as qty, d.priority AS pp, p.quantity AS to_pick\x0A\x09\x09FROM " . $tb . "denorm_order_details_queue d\x0A\x09\x09JOIN " . $tb . "sales_order_details od ON (od.id = d.id)\x0A\x09\x09JOIN " . $tb . "sales_orders so ON (so.order_no = d.order_id)\x0A\x09\x09LEFT JOIN (" . FA::pick_query() . ") p ON (p.detail_id = od.id)\x0A\x09\x09WHERE stock_id = '" . $this->stock_id . "'\x0A\x09\x09AND od.trans_type = 30\x0A\x09\x09ORDER by quantity_before, d.priority"; return FA::query($sql); } public function formatLocation($location, $type, $left) { $cells = new _hx_array(array($type, $location->name, $location->quantityOnHand($this->stock_id, null), $left - $location->quantityOnHand($this->stock_id, null), "" . _hx_string_rec($left, "") . "", $location->code, ((_hx_equal($location->delivery->getTime(), 0)) ? "" : DateTools::format($location->delivery, "%F")), "", "", "")); $this->printRow($cells, new _hx_array(array("class = \"tableheader location\"", "id = \"loc_" . $location->code . "\""))); } public function quantity_box($row_id, $order, $left) { $maxQuantity = $order->quantity; $quantity = $order->to_pick; $available = ItemScheduler_3($this, $left, $maxQuantity, $order, $quantity, $row_id); $user_pick = (($this->parameters === null) ? $quantity : $this->parameters->toPick($order)); if($user_pick === null) { $user_pick = 0; } $inputs = new _hx_array(array()); if($maxQuantity > 12) { $inputs->push("" . _hx_string_rec(((($quantity === null) ? 0 : $quantity)), "") . " "); $inputs->push(""); } else { $inputs->push(""); { $_g1 = 0; $_g = $maxQuantity + 1; while($_g1 < $_g) { $q = $_g1++; $last_available = $q == $available ? true: false; $current_pick = $q == $user_pick ? true:false; $picked = $q == $quantity; $differs = $user_pick != $quantity; $checked = (($current_pick) ? "checked" : ""); $klass = (($q > $available) ? "early" : ""); $inputs->push(""); $inputs->push(ItemScheduler_4($this, $_g, $_g1, $available, $checked, $current_pick, $differs, $inputs, $klass, $last_available, $left, $maxQuantity, $order, $picked, $q, $quantity, $row_id, $user_pick)); $inputs->push(""); if($last_available) { $inputs->push(""); $inputs->push(""); } unset($q,$picked,$last_available,$klass,$differs,$current_pick,$checked); } } $inputs->push(""); } return $inputs->join(""); } public function formatOrder($order, $left, $date, $now) { $row_id = ItemScheduler::orderId($order); $attributes = new _hx_array(array("id = \"" . $row_id . "\"")); $classes = new _hx_array(array()); $to_pick = $this->toPick($order); $before = $left + $order->quantity - $to_pick; if($before < 0) { $classes->push("soldout"); } else { if($left < 0) { $classes->push("partial"); } else { $classes->push("full"); } } $required_by = FA::sql2date($order->required_date); if($required_by === null) { $required_by = FA::sql2date($order->expiry_date); } if($to_pick > 0) { $classes->push("picked"); } else { if($required_by !== null && $required_by->getTime() < $date->getTime()) { $classes->push("late"); } else { $hold_until = FA::sql2date($order->hold_until_date); if($hold_until === null) { $hold_until = FA::sql2date($order->delivery_date); } if($hold_until->getTime() - FA::preHoldOffset() > $date->getTime()) { $classes->push("early"); } else { $classes->push("on_time"); } } } $expiry_date = FA::sql2date($order->expiry_date); if($expiry_date !== null && $now->getTime() > $expiry_date->getTime()) { $classes->push("expired"); } $cells = new _hx_array(array("debtor_no) . "&order_id=" . Std::string($order->order_id) . "\">" . Std::string($order->order_id) . "", "debtor_no) . "\">" . Std::string($order->deliver_to) . "", $order->quantity, $before, $left, $order->from_stk_loc, $order->hold_until_date, $order->required_date, $order->comment, $this->quantity_box($row_id, $order, $left))); $attributes->push("class=\"" . $classes->join(" ") . "\""); $this->printRow($cells, $attributes); } public function printRow($tds, $attributes) { php_Lib::hprint("join(" ") . ">"); $position = 1; { $_g = 0; while($_g < $tds->length) { $td = $tds[$_g]; ++$_g; php_Lib::hprint(""); if($td) { php_Lib::hprint($td); } php_Lib::hprint(""); $position++; unset($td); } } php_Lib::hprint(""); } public function generateTable() { $startDate = Date::fromTime(0); $locations = $this->locations(); $locations->sort(array(new _hx_lambda(array(&$locations, &$startDate), "ItemScheduler_5"), 'execute')); $locationIter = $locations->iterator(); $location = $locationIter->next(); $qoh = $location->quantityOnHand($this->stock_id, null); $left = $qoh; $orders = $this->orders(); $total_picked = 0; { $_g = 0; while($_g < $orders->length) { $order = $orders[$_g]; ++$_g; $total_picked += $this->toPick($order); unset($order); } } $left -= $total_picked; if($left < 0) { FA::error("There is more items to pick than in stock"); } $this->formatLocation($location, "Initial", $left); { $_g = 0; while($_g < $orders->length) { $order = $orders[$_g]; ++$_g; $quantity = Std::parseInt($order->quantity); $to_pick = $this->toPick($order); while(0 >= $left && $locationIter->hasNext()) { $location = $locationIter->next(); $quantityForLocation = $location->quantityOnHand($this->stock_id, null) + $location->quantityOnOrder($this->stock_id); if($quantityForLocation === null || $quantityForLocation === 0 || $location->delivery === null) { continue; } $left += $quantityForLocation; $this->formatLocation($location, "Delivery", $left); unset($quantityForLocation); } if($to_pick > 0) { $qoh -= $quantity; } else { $left -= $quantity; } $now = Date::now(); $this->formatOrder($order, (($to_pick > 0) ? $qoh : $left), ItemScheduler_6($this, $_g, $left, $location, $locationIter, $locations, $now, $order, $orders, $qoh, $quantity, $startDate, $to_pick, $total_picked), $now); unset($to_pick,$quantity,$order,$now); } } while(0 >= $left && $locationIter->hasNext()) { $location = $locationIter->next(); $quantityForLocation = $location->quantityOnHand($this->stock_id, null); if($quantityForLocation === null || $quantityForLocation === 0) { continue; } $left += $quantityForLocation; $this->formatLocation($location, "Delivery", $left); unset($quantityForLocation); } } public function tableHeader() { return new _hx_array(array("Order", "Customer", "Quantity", "Before", "After", "Loc", "From", "Required Date", "Comment", "To Pick")); } public $qoh; public $parameters; public $startLocation; public $stock_id; public function __call($m, $a) { if(isset($this->$m) && is_callable($this->$m)) return call_user_func_array($this->$m, $a); else if(isset($this->»dynamics[$m]) && is_callable($this->»dynamics[$m])) return call_user_func_array($this->»dynamics[$m], $a); else if('toString' == $m) return $this->__toString(); else throw new HException('Unable to call «'.$m.'»'); } static function orderId($order) { return "order_" . $order->id; } function __toString() { return 'ItemScheduler'; } } function ItemScheduler_0(&$orders, $o) { { return $o->priority; } } function ItemScheduler_1(&$orders, &$priorities, $a, $b) { { $as = $a->toString(); $bs = $b->toString(); if($as < $bs) { return -1; } if($as > $bs) { return 1; } return 0; } } function ItemScheduler_2(&$_g, &$orderList, &$rows, $a, $b) { { return $_g->parameters->priority($a) - $_g->parameters->priority($b); } } function ItemScheduler_3(&$»this, &$left, &$maxQuantity, &$order, &$quantity, &$row_id) { if($order->quantity > $left) { return $left; } else { return $order->quantity; } } function ItemScheduler_4(&$»this, &$_g, &$_g1, &$available, &$checked, &$current_pick, &$differs, &$inputs, &$klass, &$last_available, &$left, &$maxQuantity, &$order, &$picked, &$q, &$quantity, &$row_id, &$user_pick) { if($picked) { return "" . _hx_string_rec($q, "") . ""; } else { return "" . _hx_string_rec($q, ""); } } function ItemScheduler_5(&$locations, &$startDate, $a, $b) { { $as = $a->delivery->getTime(); $bs = $b->delivery->getTime(); if($as < $bs) { return -1; } else { if($as > $bs) { return 1; } else { return 0; } } } } function ItemScheduler_6(&$»this, &$_g, &$left, &$location, &$locationIter, &$locations, &$now, &$order, &$orders, &$qoh, &$quantity, &$startDate, &$to_pick, &$total_picked) { if($now->getTime() > $location->delivery->getTime()) { return $now; } else { return $location->delivery; } }