BulkUpdater work.
[order_line_extra.git] / haxe / ItemScheduler.hx
index c767bda6fd592e2b43a65c19251f81cddbcbb40a..fb2cd4746a38d0a36a87f5010630288bf56f2019 100644 (file)
@@ -1,4 +1,5 @@
 import php.Lib;
+using DateTools;
 
 typedef Detail = {
        id : String,
@@ -6,14 +7,30 @@ typedef Detail = {
        position : Int,
 }
 
+typedef Order = {
+               id:String
+               ,quantity:String
+               ,priority:Date
+               ,delivery_date:String
+
+}
+
+enum ScheduleMode {
+       Update;
+       Cancel;
+       Move;
+}
+
 class ScheduleParameters {
        var row_id : String;
        var rowDetails: Hash<Detail>;
+       public var mode:ScheduleMode;
 
        function new(rawData : Dynamic) {
                var data  = php.Lib.hashOfAssociativeArray(rawData);
                row_id = data.get('row_id');
                var raw_order : Dynamic = data.get('row_order');
+               mode = ScheduleMode.Move;
 
                var row_ids = php.Lib.toHaxeArray(raw_order);
                if (row_ids!= null) {
@@ -21,9 +38,6 @@ class ScheduleParameters {
                        var position = 1;
                        for(id in row_ids) {
                                var d : Dynamic = data.get(id);
-                               //var o = php.Lib.objectOfAssociativeArray(d);
-                               php.Lib.dump(d);
-                               php.Lib.print('<br>');
 
                                var quantity : Int = null;
                                if(d != null) {
@@ -35,28 +49,48 @@ class ScheduleParameters {
                                rowDetails.set(id, {
                                        id: id
                                        ,quantity: quantity
-                                       ,position: position++
+                                       ,position: position
                                        });
+                               position+=1;
                        }
                }
-               //php.Lib.dump(rowDetails);
        }
 
-public function position(id: String) : Int {
-       return rowDetails == null ? rowDetails.get(id).position : null;
+       public function setMode(action:String) {
+               mode = switch(action) {
+                       case "update" :
+                               ScheduleMode.Update;
+                       case "cancel" :
+                               ScheduleMode.Cancel;
+                       default:
+                               ScheduleMode.Move;
+               };
+       }
 
-}
+       public function position(id: String) : Null<Int> {
+               if(rowDetails == null) return null;
+               return rowDetails.get(id).position;
+
+       }
+
+       public function priority(order : {id: String, priority: Date})  : Int {
+               var orderId = ItemScheduler.orderId(order);
+               var orderPosition = position(orderId);
+               return orderPosition != null  ? orderPosition : cast(order.priority.getTime(), Int);
+       }
 }
 
 
 class ItemScheduler {
        var stock_id:String;
        var startLocation:String;
+       var parameters:ScheduleParameters; 
        var qoh: Int;
        function new(stock_id: String, startLocation, parameters : Null<ScheduleParameters>) {
                this.stock_id = stock_id;
                this.startLocation = startLocation;
-               qoh =  untyped __call__('get_qoh_on_date', this.stock_id, 'DEF');
+               this.parameters = parameters;
+               qoh =  untyped __call__('get_qoh_on_date', this.stock_id, startLocation);
        }
 
        function tableHeader() {
@@ -66,10 +100,16 @@ class ItemScheduler {
        function generateTable(): Void {
                var startDate = Date.fromTime(0);
 
-               // Sort location by datae
+               // Sort location by date
                var locations = this.locations();
                locations.sort(function(a, b) {
-                               return cast(a.delivery.getTime() - b.delivery.getTime(), Int );
+                       var as = a.delivery.getTime();
+                       var bs = b.delivery.getTime();
+                       if(as < bs) 
+                               return -1;
+                       else if(as > bs)
+                               return 1;
+                       else return 0;
                                });
 
                // Get the start location, it should be the first one
@@ -85,18 +125,28 @@ class ItemScheduler {
                for(order in orders()) {
                        var quantity : Int = Std.parseInt(order.quantity);
 
-                       while(0 > left && locationIter.hasNext()) {
+                       while(0 >= left && locationIter.hasNext()) {
                                location = locationIter.next();
-                               var quantityForLocation : Int = location.quantityOnHand(stock_id, null);
-                               if(quantityForLocation == null || quantityForLocation == 0) continue;
+                               var quantityForLocation : Int = location.quantityOnHand(stock_id, null) + location.quantityOnOrder(stock_id);
+                               if(quantityForLocation == null || quantityForLocation == 0 || location.delivery == null) continue;
                                left += quantityForLocation;
                                formatLocation(location, "Delivery", left);
                        }
                        left -= quantity;
 
-                       formatOrder(order, left, location.delivery);
+                       var now = Date.now();
+                       //formatOrder(order, left, location.delivery); // now.getTime() > location.delivery ? now : location.delivery);
+                       formatOrder(order, left, now.getTime() > location.delivery.getTime() ? now : location.delivery);
 
                }
+               // display the left locations
+                       while(0 >= left && locationIter.hasNext()) {
+                               location = locationIter.next();
+                               var quantityForLocation : Int = location.quantityOnHand(stock_id, null);
+                               if(quantityForLocation == null || quantityForLocation == 0) continue;
+                               left += quantityForLocation;
+                               formatLocation(location, "Delivery", left);
+                       }
 
        }
 
@@ -112,8 +162,12 @@ class ItemScheduler {
                php.Lib.print('</tr>');
        }
 
+       static public function orderId(order) {
+               return 'order_'+order.id;
+       }
+
        function formatOrder(order : Dynamic, left : Int, date : Date) {
-               var row_id = 'order_'+order.id;
+               var row_id = orderId(order);
                var attributes = ['id = "'+row_id+'"'];
                var classes = [];
                var before : Int = left + order.quantity;
@@ -134,14 +188,24 @@ class ItemScheduler {
 
                /* The order can also be late if we need
                 * to wait for a delivery to get it
+                * or early if the item is on hold.
                 */
                var required_by : Date = FA.sql2date(order.required_date);
-               if(required_by == null) required_by = FA.sql2date(order.delivery_date);
-               if(required_by.getTime() < date.getTime()) {
+               if(required_by == null) required_by = FA.sql2date(order.expiry_date);
+               if(required_by != null && required_by.getTime() < date.getTime()) {
                        classes.push('late');
                }
                else {
-                       classes.push('on_time');
+                       var hold_until : Date = FA.sql2date(order.hold_until_date);
+                       php.Lib.print(hold_until);
+                       php.Lib.print(date);
+                       if(hold_until == null) hold_until = FA.sql2date(order.delivery_date);
+                       if(hold_until.getTime() > date.getTime()) {
+                               classes.push('early');
+                       }
+                       else {
+                               classes.push('on_time');
+                       }
                }
                var cells : Array <Dynamic> = [
                        order.order_id
@@ -150,7 +214,7 @@ class ItemScheduler {
                        ,before
                        ,left
                        ,order.from_stk_loc
-                       ,order.delivery_date
+                       ,order.hold_until_date
                        ,order.required_date 
                        ,order.comment
                        ];
@@ -168,7 +232,7 @@ class ItemScheduler {
                        ,left-location.quantityOnHand(stock_id, null)
                        ,left
                        ,location.code
-                       ,location.delivery
+                       ,location.delivery.getTime() == 0 ? '' : location.delivery.format("%F")
                        ,""
                        ,""
                        ];
@@ -187,7 +251,7 @@ return cast(locations(), Array<Dynamic>);
 
 private function loadOrders() {
        var tb : String =  untyped __php__('TB_PREF');
-       var sql : String = "SELECT *  
+       var sql : String = "SELECT *  , d.quantity as qty,   d.priority AS pp
                FROM "+tb+"denorm_order_details_queue  d
                JOIN "+tb+"sales_order_details od ON (od.id = d.id)
                JOIN "+tb+"sales_orders so ON (so.order_no = d.order_id)
@@ -198,14 +262,26 @@ private function loadOrders() {
        return FA.query(sql);
 }
 
-function orders()  {
+function orders():Array<Order>  {
        var rows = loadOrders();
        var orderList = [];
        for(row in rows) {
-               var order = php.Lib.objectOfAssociativeArray(row);
+               // for some reason, priority is null
+               // so we use the pp field
+               var a:Dynamic = php.Lib.objectOfAssociativeArray(row);
+               var order:Order = a;
+               order.priority = Date.fromString(a.pp);
+               order.quantity = a.qty;
                orderList.push(order);
        };
 
+       if(parameters != null) {
+               orderList.sort(function(a, b) { return parameters.priority(a)-parameters.priority(b); });
+
+       }
+               for(order in orderList) {
+               }
+
        return orderList;
 }
 
@@ -221,6 +297,9 @@ function locations() {
                if(location.code == startLocation) {
                        location.delivery =  Date.fromTime(0);
                }
+               else if(location.delivery == null) {
+               continue;
+               }
                _locs.push(location);
        }
 
@@ -229,8 +308,54 @@ function locations() {
 }
 
 
-function purcharseOrders()  {
-}
+       function purcharseOrders()  {
+               var TB = FA.tb();
+               var sql = 'SELECT SUM(quantity_ordered - quantity_received) as quantity
+                       into_stock_location AS location
+                       FROM '+TB+'purch_order_details
+                       NATURAL JOIN '+TB+'purch_orders
+                       WHERE item_code = "'+this.stock_id+'"
+                       AND quantity_ordered > quantity_received
+                       GROUP by item_code,delivery_date, into_stock_location
+                       ORDER by delivery_date' ;
+
+               return  FA.query(sql);
+       }
+
+       public function needsUpdate():Bool {
+               return parameters != null && parameters.mode == ScheduleMode.Move;
+       }
+
+       function update() {
+               var orders = this.orders();
+               var priorities = Lambda.array(Lambda.map(orders, function(o) { return o.priority;}));
+               priorities.sort(function(a,b) {
+                       var as = a.toString();
+                       var bs = b.toString();
+                       if (as < bs) return -1;
+                       if( as > bs) return 1;
+                       return 0;
+                       });
+
+               var iter = priorities.iterator();
+               var p = iter.next();
+               var position:Int = 0-priorities.length;
+               for(order in orders) {
+                       var new_priority = DateTools.delta(p, 1000*position);
+                       untyped __call__ ('update_order_detail_priority', order.id, new_priority.toString());
+                       
+                       position +=1;
+                       p = iter.next();
+               }
+                       untyped __call__ ('update_queue_quantity_for_item', stock_id);
+               
+       }
+       
+       public function action() {
+               if(parameters != null && parameters.mode == ScheduleMode.Update) {
+                       update();
+               }
+       }
 
 
 }