Use hold_until_date in item_scheduler.
[order_line_extra.git] / hincludes / lib / ItemScheduler.class.php
1 <?php
2
3 class ItemScheduler {
4         public function __construct($stock_id, $startLocation, $parameters) {
5                 if(!php_Boot::$skip_constructor) {
6                 $this->stock_id = $stock_id;
7                 $this->startLocation = $startLocation;
8                 $this->parameters = $parameters;
9                 $this->qoh = get_qoh_on_date($this->stock_id, $startLocation);
10         }}
11         public function action() {
12                 if($this->parameters !== null && $this->parameters->mode == ScheduleMode::$Update) {
13                         $this->update();
14                 }
15         }
16         public function update() {
17                 $orders = $this->orders();
18                 $priorities = Lambda::harray(Lambda::map($orders, array(new _hx_lambda(array(&$orders), "ItemScheduler_0"), 'execute')));
19                 $priorities->sort(array(new _hx_lambda(array(&$orders, &$priorities), "ItemScheduler_1"), 'execute'));
20                 $iter = $priorities->iterator();
21                 $p = $iter->next();
22                 $position = 0 - $priorities->length;
23                 {
24                         $_g = 0;
25                         while($_g < $orders->length) {
26                                 $order = $orders[$_g];
27                                 ++$_g;
28                                 $new_priority = DateTools::delta($p, 1000 * $position);
29                                 update_order_detail_priority($order->id, $new_priority->toString());
30                                 $position += 1;
31                                 $p = $iter->next();
32                                 unset($order,$new_priority);
33                         }
34                 }
35                 update_queue_quantity_for_item($this->stock_id);
36         }
37         public function needsUpdate() {
38                 return $this->parameters !== null && $this->parameters->mode == ScheduleMode::$Move;
39         }
40         public function purcharseOrders() {
41                 $TB = FA::tb();
42                 $sql = "SELECT SUM(quantity_ordered - quantity_received) as quantity\x0A\x09\x09\x09into_stock_location AS location\x0A\x09\x09\x09FROM " . $TB . "purch_order_details\x0A\x09\x09\x09NATURAL JOIN " . $TB . "purch_orders\x0A\x09\x09\x09WHERE item_code = \"" . $this->stock_id . "\"\x0A\x09\x09\x09AND quantity_ordered > quantity_received\x0A\x09\x09\x09GROUP by item_code,delivery_date, into_stock_location\x0A\x09\x09\x09ORDER by delivery_date";
43                 return FA::query($sql);
44         }
45         public function locations() {
46                 $TB = FA::tb();
47                 $sql = "SELECT * \x0A\x09\x09FROM " . $TB . "locations";
48                 $_locs = new _hx_array(array());
49                 if(null == _hx_qtype("FA")) throw new HException('null iterable');
50                 $»it = FA::query($sql);
51                 while($»it->hasNext()) {
52                         $row = $»it->next();
53                         $location = new Location($row);
54                         if($location->code === $this->startLocation) {
55                                 $location->delivery = Date::fromTime(0);
56                         } else {
57                                 if($location->delivery === null) {
58                                         continue;
59                                 }
60                         }
61                         $_locs->push($location);
62                         unset($location);
63                 }
64                 return $_locs;
65         }
66         public function orders() {
67                 $_g = $this;
68                 $rows = $this->loadOrders();
69                 $orderList = new _hx_array(array());
70                 $»it = $rows;
71                 while($»it->hasNext()) {
72                         $row = $»it->next();
73                         $a = php_Lib::objectOfAssociativeArray($row);
74                         $order = $a;
75                         $order->priority = Date::fromString($a->pp);
76                         $order->quantity = $a->qty;
77                         $orderList->push($order);
78                         unset($order,$a);
79                 }
80                 if($this->parameters !== null) {
81                         $orderList->sort(array(new _hx_lambda(array(&$_g, &$orderList, &$rows), "ItemScheduler_2"), 'execute'));
82                 }
83                 {
84                         $_g1 = 0;
85                         while($_g1 < $orderList->length) {
86                                 $order = $orderList[$_g1];
87                                 ++$_g1;
88                                 unset($order);
89                         }
90                 }
91                 return $orderList;
92         }
93         public function loadOrders() {
94                 $tb = TB_PREF;
95                 $sql = "SELECT *  , d.quantity as qty,   d.priority AS pp\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\x09WHERE stock_id = '" . $this->stock_id . "'\x0A\x09\x09AND od.trans_type = 30\x0A\x09\x09ORDER by d.priority";
96                 return FA::query($sql);
97         }
98         public function formatLocation($location, $type, $left) {
99                 $cells = new _hx_array(array($type, $location->name, $location->quantityOnHand($this->stock_id, null), $left - $location->quantityOnHand($this->stock_id, null), $left, $location->code, ((_hx_equal($location->delivery->getTime(), 0)) ? "" : DateTools::format($location->delivery, "%F")), "", ""));
100                 $this->printRow($cells, new _hx_array(array("class = \"tableheader location\"", "id = \"loc_" . $location->code . "\"")));
101         }
102         public function formatOrder($order, $left, $date) {
103                 $row_id = ItemScheduler::orderId($order);
104                 $attributes = new _hx_array(array("id = \"" . $row_id . "\""));
105                 $classes = new _hx_array(array());
106                 $before = $left + $order->quantity;
107                 if($before < 0) {
108                         $classes->push("soldout");
109                 } else {
110                         if($left < 0) {
111                                 $classes->push("partial");
112                         } else {
113                                 $classes->push("full");
114                         }
115                 }
116                 $required_by = FA::sql2date($order->required_date);
117                 if($required_by === null) {
118                         $required_by = FA::sql2date($order->expiry_date);
119                 }
120                 if($required_by !== null && $required_by->getTime() < $date->getTime()) {
121                         $classes->push("late");
122                 } else {
123                         $hold_until = FA::sql2date($order->hold_until_date);
124                         php_Lib::hprint($hold_until);
125                         php_Lib::hprint($date);
126                         if($hold_until === null) {
127                                 $hold_until = FA::sql2date($order->delivery_date);
128                         }
129                         if($hold_until->getTime() > $date->getTime()) {
130                                 $classes->push("early");
131                         } else {
132                                 $classes->push("on_time");
133                         }
134                 }
135                 $cells = new _hx_array(array($order->order_id, "<a href=\"/modules/order_line_extra/order_lines_view.php?customer_id=" . Std::string($order->debtor_no) . "\">" . Std::string($order->deliver_to) . "</a>", "<input type=\"text\" name=\"" . $row_id . "[quantity]\" value=\"" . Std::string($order->quantity) . "\">", $before, $left, $order->from_stk_loc, $order->hold_until_date, $order->required_date, $order->comment));
136                 $attributes->push("class=\"" . $classes->join(" ") . "\"");
137                 $this->printRow($cells, $attributes);
138         }
139         public function printRow($tds, $attributes) {
140                 php_Lib::hprint("<tr " . $attributes->join(" ") . ">");
141                 $position = 1;
142                 {
143                         $_g = 0;
144                         while($_g < $tds->length) {
145                                 $td = $tds[$_g];
146                                 ++$_g;
147                                 php_Lib::hprint("<td class=\"cell_" . _hx_string_rec($position, "") . "\">");
148                                 if($td) {
149                                         php_Lib::hprint($td);
150                                 }
151                                 php_Lib::hprint("</td>");
152                                 $position++;
153                                 unset($td);
154                         }
155                 }
156                 php_Lib::hprint("</tr>");
157         }
158         public function generateTable() {
159                 $startDate = Date::fromTime(0);
160                 $locations = $this->locations();
161                 $locations->sort(array(new _hx_lambda(array(&$locations, &$startDate), "ItemScheduler_3"), 'execute'));
162                 $locationIter = $locations->iterator();
163                 $location = $locationIter->next();
164                 $qoh = $location->quantityOnHand($this->stock_id, null);
165                 $left = $qoh;
166                 $this->formatLocation($location, "Initial", $left);
167                 {
168                         $_g = 0; $_g1 = $this->orders();
169                         while($_g < $_g1->length) {
170                                 $order = $_g1[$_g];
171                                 ++$_g;
172                                 $quantity = Std::parseInt($order->quantity);
173                                 while(0 >= $left && $locationIter->hasNext()) {
174                                         $location = $locationIter->next();
175                                         $quantityForLocation = $location->quantityOnHand($this->stock_id, null) + $location->quantityOnOrder($this->stock_id);
176                                         if($quantityForLocation === null || $quantityForLocation === 0 || $location->delivery === null) {
177                                                 continue;
178                                         }
179                                         $left += $quantityForLocation;
180                                         $this->formatLocation($location, "Delivery", $left);
181                                         unset($quantityForLocation);
182                                 }
183                                 $left -= $quantity;
184                                 $now = Date::now();
185                                 $this->formatOrder($order, $left, ItemScheduler_4($this, $_g, $_g1, $left, $location, $locationIter, $locations, $now, $order, $qoh, $quantity, $startDate));
186                                 unset($quantity,$order,$now);
187                         }
188                 }
189                 while(0 >= $left && $locationIter->hasNext()) {
190                         $location = $locationIter->next();
191                         $quantityForLocation = $location->quantityOnHand($this->stock_id, null);
192                         if($quantityForLocation === null || $quantityForLocation === 0) {
193                                 continue;
194                         }
195                         $left += $quantityForLocation;
196                         $this->formatLocation($location, "Delivery", $left);
197                         unset($quantityForLocation);
198                 }
199         }
200         public function tableHeader() {
201                 return new _hx_array(array("Order", "Customer", "Quantity", "Before", "After", "Loc", "From", "Required Date", "Comment"));
202         }
203         public $qoh;
204         public $parameters;
205         public $startLocation;
206         public $stock_id;
207         public function __call($m, $a) {
208                 if(isset($this->$m) && is_callable($this->$m))
209                         return call_user_func_array($this->$m, $a);
210                 else if(isset($this->»dynamics[$m]) && is_callable($this->»dynamics[$m]))
211                         return call_user_func_array($this->»dynamics[$m], $a);
212                 else if('toString' == $m)
213                         return $this->__toString();
214                 else
215                         throw new HException('Unable to call «'.$m.'»');
216         }
217         static function orderId($order) {
218                 return "order_" . $order->id;
219         }
220         function __toString() { return 'ItemScheduler'; }
221 }
222 function ItemScheduler_0(&$orders, $o) {
223         {
224                 return $o->priority;
225         }
226 }
227 function ItemScheduler_1(&$orders, &$priorities, $a, $b) {
228         {
229                 $as = $a->toString();
230                 $bs = $b->toString();
231                 if($as < $bs) {
232                         return -1;
233                 }
234                 if($as > $bs) {
235                         return 1;
236                 }
237                 return 0;
238         }
239 }
240 function ItemScheduler_2(&$_g, &$orderList, &$rows, $a, $b) {
241         {
242                 return $_g->parameters->priority($a) - $_g->parameters->priority($b);
243         }
244 }
245 function ItemScheduler_3(&$locations, &$startDate, $a, $b) {
246         {
247                 $as = $a->delivery->getTime();
248                 $bs = $b->delivery->getTime();
249                 if($as < $bs) {
250                         return -1;
251                 } else {
252                         if($as > $bs) {
253                                 return 1;
254                         } else {
255                                 return 0;
256                         }
257                 }
258         }
259 }
260 function ItemScheduler_4(&$»this, &$_g, &$_g1, &$left, &$location, &$locationIter, &$locations, &$now, &$order, &$qoh, &$quantity, &$startDate) {
261         if($now->getTime() > $location->delivery->getTime()) {
262                 return $now;
263         } else {
264                 return $location->delivery;
265         }
266 }