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