import php.Lib; typedef Detail = { id : String, quantity : Int, position : Int, } typedef Order = { id:String ,quantity:String ,priority:Int ,delivery_date:String } class ScheduleParameters { var row_id : String; var rowDetails: Hash; function new(rawData : Dynamic) { var data = php.Lib.hashOfAssociativeArray(rawData); row_id = data.get('row_id'); var raw_order : Dynamic = data.get('row_order'); var row_ids = php.Lib.toHaxeArray(raw_order); if (row_ids!= null) { rowDetails = new Hash(); var position = 1; for(id in row_ids) { var d : Dynamic = data.get(id); var quantity : Int = null; if(d != null) { var o = php.Lib.objectOfAssociativeArray(d); quantity = Std.parseInt(o.quantity); } rowDetails.set(id, { id: id ,quantity: quantity ,position: position }); position+=1; } } } public function position(id: String) : Null { if(rowDetails == null) return null; return rowDetails.get(id).position; } public function priority(order : {id: String, priority: Int}) : Int { var orderId = ItemScheduler.orderId(order); var orderPosition = position(orderId); return orderPosition != null ? orderPosition : order.priority; } } class ItemScheduler { var stock_id:String; var startLocation:String; var parameters:ScheduleParameters; var qoh: Int; function new(stock_id: String, startLocation, parameters : Null) { this.stock_id = stock_id; this.startLocation = startLocation; this.parameters = parameters; qoh = untyped __call__('get_qoh_on_date', this.stock_id, 'DEF'); } function tableHeader() { return ["Order", "Customer", "Quantity", "Before", "After", "Loc", "From", "Required Date", "Comment"]; } function generateTable(): Void { var startDate = Date.fromTime(0); // Sort location by date var locations = this.locations(); locations.sort(function(a, b) { return cast(a.delivery.getTime() - b.delivery.getTime(), Int ); }); // Get the start location, it should be the first one var locationIter = locations.iterator(); var location = locationIter.next(); var qoh : Int = location.quantityOnHand(stock_id, null); var left = qoh; formatLocation(location, "Initial", left); // We display the order ordered by priority // But insert the location when needed (meaning // when we run out of item available for(order in orders()) { var quantity : Int = Std.parseInt(order.quantity); 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); } left -= quantity; formatOrder(order, left, location.delivery); } } function printRow(tds : Array, attributes : Array) { php.Lib.print(''); var position : Int = 1; for(td in tds) { php.Lib.print(''); if(td) php.Lib.print(td); php.Lib.print(''); position++; } php.Lib.print(''); } static public function orderId(order) { return 'order_'+order.id; } function formatOrder(order : Dynamic, left : Int, date : Date) { var row_id = orderId(order); var attributes = ['id = "'+row_id+'"']; var classes = []; var before : Int = left + order.quantity; /* We have basically 3 different cases; * - the order can be fullfilled * - the order can be partially * - not at all */ if (before < 0 ) { classes.push('soldout'); } else if(left < 0) { classes.push('partial'); } else { classes.push('full'); } /* The order can also be late if we need * to wait for a delivery to get it */ 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()) { classes.push('late'); } else { classes.push('on_time'); } var cells : Array = [ order.order_id , ''+order.deliver_to+'' ,'' ,before ,left ,order.from_stk_loc ,order.delivery_date ,order.required_date ,order.comment ]; attributes.push('class="'+classes.join(' ')+'"'); printRow(cells, attributes); } function formatLocation(location : Location, type: String, left : Int) { var cells = [ type ,location.name ,location.quantityOnHand(stock_id, null) ,left-location.quantityOnHand(stock_id, null) ,left ,location.code ,location.delivery ,"" ,"" ]; printRow(cells, ['class = "tableheader location"', 'id = "loc_'+location.code+'"']); } /* function schedules() { //return orders()+locations(); //return orders(); return cast(locations(), Array); } */ private function loadOrders() { var tb : String = untyped __php__('TB_PREF'); var sql : String = "SELECT * 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) WHERE stock_id = '"+this.stock_id+"' AND od.trans_type = 30 ORDER by d.priority"; return FA.query(sql); } function orders():Array { var rows = loadOrders(); var orderList = []; for(row in rows) { var order:Order = php.Lib.objectOfAssociativeArray(row); orderList.push(order); }; if(parameters != null) { orderList.sort(function(a, b) { return parameters.priority(a)-parameters.priority(b); }); } for(order in orderList) { } return orderList; } function locations() { var TB = FA.tb(); var sql = 'SELECT * FROM '+TB+'locations'; var _locs = []; for(row in FA.query(sql)) { var location = new Location(row); if(location.code == startLocation) { location.delivery = Date.fromTime(0); } _locs.push(location); } return _locs; } function purcharseOrders() { } }