X-Git-Url: https://delta.frontaccounting.com/gitweb/?a=blobdiff_plain;f=haxe%2FItemScheduler.hx;h=fb2cd4746a38d0a36a87f5010630288bf56f2019;hb=ee3469d3ffd74d2a6be87d3dd0a9541a14bcdfde;hp=0446983596a2f12764dfdbf93fc2745addcc8557;hpb=d4657264166ab67353e9d787d5f8449aa7b997c5;p=order_line_extra.git diff --git a/haxe/ItemScheduler.hx b/haxe/ItemScheduler.hx index 0446983..fb2cd47 100644 --- a/haxe/ItemScheduler.hx +++ b/haxe/ItemScheduler.hx @@ -1,84 +1,115 @@ import php.Lib; +using DateTools; -enum Maybe { - Nothing; - Just(v : T); +typedef Detail = { + id : String, + quantity : Int, + position : Int, } -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(); - } +typedef Order = { + id:String + ,quantity:String + ,priority:Date + ,delivery_date:String - 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; +enum ScheduleMode { + Update; + Cancel; + Move; +} + +class ScheduleParameters { + var row_id : String; + var rowDetails: Hash; + 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) { + 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 next() : T { - switch(this.nextValue) { - case Nothing : throw 'Iterator exhausted'; - case Just(v) : { - this.fetch(); - return v; + public function setMode(action:String) { + mode = switch(action) { + case "update" : + ScheduleMode.Update; + case "cancel" : + ScheduleMode.Cancel; + default: + ScheduleMode.Move; }; - } } -} -class FA { - static public function query(sql: String) { - var result = untyped __call__('db_query', sql, sql); - return new QueryIterator(result); + + public function position(id: String) : Null { + if(rowDetails == null) return null; + return rowDetails.get(id).position; + } - static public function tb() : String { - return untyped __php__('TB_PREF'); + 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) { + function new(stock_id: String, startLocation, parameters : Null) { 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() { - return ["Order", "Customer", "Quantity", "Before", "After", "Loc", "Required Date"]; - } - -/* - function generateTablex(): Void { - for(location in locations()) { - formatLocation(location, null); - } - for(order in this.orders()) { - this.formatRow(order); - } + return ["Order", "Customer", "Quantity", "Before", "After", "Loc", "From", "Required Date", "Comment"]; } -*/ 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 ); + var startDate = Date.fromTime(0); + + // Sort location by date + var locations = this.locations(); + locations.sort(function(a, b) { + 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 @@ -91,77 +122,106 @@ class ItemScheduler { // 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); + for(order in orders()) { var quantity : Int = Std.parseInt(order.quantity); - while(quantity > 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); - + 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); + } + } function printRow(tds : Array, attributes : Array) { - php.Lib.print(''); + php.Lib.print(''); + var position : Int = 1; for(td in tds) { - php.Lib.print(''); - php.Lib.print(td); + php.Lib.print(''); + if(td) php.Lib.print(td); php.Lib.print(''); + position++; } php.Lib.print(''); } - function formatOrder(order : Dynamic, left : Int) { - var attributes = []; - var cells : Array = [ - order.order_id - ,order.deliver_to - ,order.quantity - ,left - ,left+order.quantity - ,order.from_stk_code - ,order.delivery_date - ]; - printRow(cells, attributes); - + static public function orderId(order) { + return 'order_'+order.id; } - 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'); + 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'); + } - var status : String = if(quantity_available < quantity) 'overduebg'; + /* 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.expiry_date); + if(required_by != null && required_by.getTime() < date.getTime()) { + classes.push('late'); + } + else { + 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 = [ + order.order_id + , ''+order.deliver_to+'' + ,'' + ,before + ,left + ,order.from_stk_loc + ,order.hold_until_date + ,order.required_date + ,order.comment + ]; - 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') - ]; + attributes.push('class="'+classes.join(' ')+'"'); + printRow(cells, attributes); - 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) { @@ -172,58 +232,131 @@ class ItemScheduler { ,left-location.quantityOnHand(stock_id, null) ,left ,location.code - ,location.delivery - ]; - var status = 'header'; - php.Lib.print(''); - for(cell in cells) { - php.Lib.print(''); - php.Lib.print(cell); - php.Lib.print(''); - } - php.Lib.print(''); + ,location.delivery.getTime() == 0 ? '' : location.delivery.format("%F") + ,"" + ,"" + ]; + + printRow(cells, ['class = "tableheader location"', 'id = "loc_'+location.code+'"']); } -/* - function schedules() { - //return orders()+locations(); - //return orders(); - return cast(locations(), Array); + /* + 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 * , 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) + WHERE stock_id = '"+this.stock_id+"' + AND od.trans_type = 30 + ORDER by d.priority"; + + return FA.query(sql); +} - function orders() { - var tb : String = untyped __php__('TB_PREF'); - var sql : String = "SELECT * - FROM "+tb+"denorm_order_details_queue - JOIN "+tb+"sales_orders ON (order_no = order_id) - WHERE stock_id = '"+this.stock_id+"' - ORDER by quantity_before"; - - return FA.query(sql); - } +function orders():Array { + var rows = loadOrders(); + var orderList = []; + for(row in rows) { + // 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); }); - 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); + } + for(order in orderList) { } - return _locs; - + 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); + } + else if(location.delivery == null) { + continue; + } + _locs.push(location); } + return _locs; + +} + 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(); + } + } + }