import php.Lib; enum Maybe { Nothing; Just(v : T); } class QueryIterator { var result : Dynamic; var nextValue : Maybe; public function new(result) { this.result= result; /* We fetch the first row , so we can answer hasNext */ fetch(); } private function fetch() { var next : Dynamic = untyped __call__('db_fetch', this.result); nextValue = if(next) Just(next) else Nothing; } public function hasNext() : Bool { return this.nextValue != Nothing; } public function next() : T { switch(this.nextValue) { case Nothing : throw 'Iterator exhausted'; case Just(v) : { this.fetch(); return v; }; } } } class FA { static public function query(sql: String) { var result = untyped __call__('db_query', sql, sql); return new QueryIterator(result); } static public function tb() : String { return untyped __php__('TB_PREF'); } static public function sql2date(sqlDate:Dynamic) : Null { return sqlDate == null ? null : Date.fromString(sqlDate); } } class ItemScheduler { var stock_id:String; var startLocation:String; var qoh: Int; function new(stock_id: String, startLocation) { this.stock_id = stock_id; this.startLocation = startLocation; 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 generateTablex(): Void { for(location in locations()) { formatLocation(location, null); } for(order in this.orders()) { this.formatRow(order); } } */ function generateTable(): Void { var startDate = Date.fromTime(0); for(order in orders()) { var obj = php.Lib.objectOfAssociativeArray(order); } // Sort location by datae 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(orderRow in orders()) { var order = php.Lib.objectOfAssociativeArray(orderRow); 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(''); for(td in tds) { php.Lib.print(''); if(td) php.Lib.print(td); php.Lib.print(''); } php.Lib.print(''); } function formatOrder(order : Dynamic, left : Int, date : Date) { var attributes = []; 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+'' ,order.quantity ,before ,left ,order.from_stk_loc ,order.delivery_date ,order.required_date ,order.comment ]; attributes.push('class="'+classes.join(' ')+'"'); printRow(cells, attributes); } function formatRow(row) { var array = php.Lib.hashOfAssociativeArray(row); var quantity_before : Int = array.get('quantity_before'); var quantity_available = qoh - quantity_before; var quantity: Int = array.get('quantity'); var status : String = if(quantity_available < quantity) 'overduebg'; var cells : Array = [ array.get('order_id') ,array.get('deliver_to') ,quantity ,quantity_available-quantity ,quantity_available ,array.get('from_stk_loc') ,array.get('delivery_date') ]; php.Lib.print(''); for(cell in cells) { php.Lib.print(''); php.Lib.print(cell); php.Lib.print(''); } php.Lib.print(''); } 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"']); } /* function schedules() { //return orders()+locations(); //return orders(); return cast(locations(), Array); } */ function orders() { 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 quantity_before"; return FA.query(sql); } 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() { } }