bc763e9618ef4b1b0e46a69a924efeedcaf3b90e
[order_line_extra.git] / haxe / ItemScheduler.hx
1 import php.Lib;
2
3 typedef Detail = {
4         id : String,
5         quantity : Int,
6         position : Int,
7 }
8
9 typedef Order = {
10                 id:String
11                 ,quantity:String
12                 ,priority:Int
13                 ,delivery_date:String
14
15 }
16
17 class ScheduleParameters {
18         var row_id : String;
19         var rowDetails: Hash<Detail>;
20
21         function new(rawData : Dynamic) {
22                 var data  = php.Lib.hashOfAssociativeArray(rawData);
23                 row_id = data.get('row_id');
24                 var raw_order : Dynamic = data.get('row_order');
25
26                 var row_ids = php.Lib.toHaxeArray(raw_order);
27                 if (row_ids!= null) {
28                         rowDetails = new Hash<Detail>();
29                         var position = 1;
30                         for(id in row_ids) {
31                                 var d : Dynamic = data.get(id);
32
33                                 var quantity : Int = null;
34                                 if(d != null) {
35                                                 var o = php.Lib.objectOfAssociativeArray(d);
36                                                 quantity = Std.parseInt(o.quantity);
37                                 }
38                                 
39
40                                 rowDetails.set(id, {
41                                         id: id
42                                         ,quantity: quantity
43                                         ,position: position
44                                         });
45                                 position+=1;
46                         }
47                 }
48         }
49
50         public function position(id: String) : Null<Int> {
51                 if(rowDetails == null) return null;
52                 return rowDetails.get(id).position;
53
54         }
55
56         public function priority(order : {id: String, priority: Int})  : Int {
57                 var orderId = ItemScheduler.orderId(order);
58                 var orderPosition = position(orderId);
59                 return orderPosition != null  ? orderPosition : order.priority;
60         }
61 }
62
63
64 class ItemScheduler {
65         var stock_id:String;
66         var startLocation:String;
67         var parameters:ScheduleParameters; 
68         var qoh: Int;
69         function new(stock_id: String, startLocation, parameters : Null<ScheduleParameters>) {
70                 this.stock_id = stock_id;
71                 this.startLocation = startLocation;
72                 this.parameters = parameters;
73                 qoh =  untyped __call__('get_qoh_on_date', this.stock_id, 'DEF');
74         }
75
76         function tableHeader() {
77                 return ["Order", "Customer", "Quantity", "Before", "After", "Loc", "From",  "Required Date", "Comment"];
78         }
79
80         function generateTable(): Void {
81                 var startDate = Date.fromTime(0);
82
83                 // Sort location by date
84                 var locations = this.locations();
85                 locations.sort(function(a, b) {
86                                 return cast(a.delivery.getTime() - b.delivery.getTime(), Int );
87                                 });
88
89                 // Get the start location, it should be the first one
90                 var locationIter = locations.iterator();
91                 var location  = locationIter.next();
92                 var qoh : Int = location.quantityOnHand(stock_id, null);
93                 var left = qoh;
94                 formatLocation(location, "Initial", left);
95
96                 // We display the order ordered by priority 
97                 // But insert the location when needed (meaning
98                 // when we run out of item available
99                 for(order in orders()) {
100                         var quantity : Int = Std.parseInt(order.quantity);
101
102                         while(0 > left && locationIter.hasNext()) {
103                                 location = locationIter.next();
104                                 var quantityForLocation : Int = location.quantityOnHand(stock_id, null);
105                                 if(quantityForLocation == null || quantityForLocation == 0) continue;
106                                 left += quantityForLocation;
107                                 formatLocation(location, "Delivery", left);
108                         }
109                         left -= quantity;
110
111                         formatOrder(order, left, location.delivery);
112
113                 }
114
115         }
116
117         function printRow(tds : Array<Dynamic>, attributes : Array<String>) {
118                 php.Lib.print('<tr '+attributes.join(' ')+'>');
119                 var position : Int = 1;
120                 for(td in tds) {
121                         php.Lib.print('<td class="cell_'+position+'">');
122                         if(td) php.Lib.print(td);
123                         php.Lib.print('</td>');
124                         position++;
125                 }
126                 php.Lib.print('</tr>');
127         }
128
129         static public function orderId(order) {
130                 return 'order_'+order.id;
131         }
132
133         function formatOrder(order : Dynamic, left : Int, date : Date) {
134                 var row_id = orderId(order);
135                 var attributes = ['id = "'+row_id+'"'];
136                 var classes = [];
137                 var before : Int = left + order.quantity;
138                 /* We have basically 3 different cases;
139                  * - the order can be fullfilled
140                  * - the order can be partially 
141                  * - not at all
142                  */
143                 if (before < 0 ) {
144                         classes.push('soldout');
145                 }
146                 else if(left < 0) {
147                         classes.push('partial');
148                 }
149                 else {
150                         classes.push('full');
151                 }
152
153                 /* The order can also be late if we need
154                  * to wait for a delivery to get it
155                  */
156                 var required_by : Date = FA.sql2date(order.required_date);
157                 if(required_by == null) required_by = FA.sql2date(order.delivery_date);
158                 if(required_by.getTime() < date.getTime()) {
159                         classes.push('late');
160                 }
161                 else {
162                         classes.push('on_time');
163                 }
164                 var cells : Array <Dynamic> = [
165                         order.order_id
166                         , '<a href="/modules/order_line_extra/order_lines_view.php?customer_id='+Std.string(order.debtor_no)+'">'+order.deliver_to+'</a>'
167                         ,'<input type="text" name="'+row_id+'[quantity]" value="'+order.quantity+'">'
168                         ,before
169                         ,left
170                         ,order.from_stk_loc
171                         ,order.delivery_date
172                         ,order.required_date 
173                         ,order.comment
174                         ];
175
176                 attributes.push('class="'+classes.join(' ')+'"');
177                 printRow(cells, attributes);
178
179         }
180
181         function formatLocation(location : Location, type: String,  left : Int) {
182                 var cells = [
183                         type
184                         ,location.name
185                         ,location.quantityOnHand(stock_id, null)
186                         ,left-location.quantityOnHand(stock_id, null)
187                         ,left
188                         ,location.code
189                         ,location.delivery
190                         ,""
191                         ,""
192                         ];
193
194                 printRow(cells, ['class = "tableheader location"', 'id = "loc_'+location.code+'"']);
195         }
196
197         /*
198                  function schedules() {
199 //return orders()+locations();
200 //return  orders();
201 return cast(locations(), Array<Dynamic>);
202
203 }
204          */
205
206 private function loadOrders() {
207         var tb : String =  untyped __php__('TB_PREF');
208         var sql : String = "SELECT *  
209                 FROM "+tb+"denorm_order_details_queue  d
210                 JOIN "+tb+"sales_order_details od ON (od.id = d.id)
211                 JOIN "+tb+"sales_orders so ON (so.order_no = d.order_id)
212                 WHERE stock_id = '"+this.stock_id+"'
213                 AND od.trans_type = 30
214                 ORDER by d.priority";
215
216         return FA.query(sql);
217 }
218
219 function orders():Array<Order>  {
220         var rows = loadOrders();
221         var orderList = [];
222         for(row in rows) {
223                 var order:Order = php.Lib.objectOfAssociativeArray(row);
224                 orderList.push(order);
225         };
226
227         if(parameters != null) {
228                 orderList.sort(function(a, b) { return parameters.priority(a)-parameters.priority(b); });
229
230         }
231                 for(order in orderList) {
232                 }
233
234         return orderList;
235 }
236
237
238
239 function locations() {
240         var TB = FA.tb();
241         var sql = 'SELECT * 
242                 FROM '+TB+'locations';
243         var _locs = [];
244         for(row in FA.query(sql)) {
245                 var location = new Location(row);
246                 if(location.code == startLocation) {
247                         location.delivery =  Date.fromTime(0);
248                 }
249                 _locs.push(location);
250         }
251
252         return _locs;
253
254 }
255
256
257 function purcharseOrders()  {
258 }
259
260
261 }
262
263