import php.Lib;
-enum Maybe<T> {
- Nothing;
- Just(v : T);
+typedef Detail = {
+ id : String,
+ quantity : Int,
+ position : Int,
}
-class QueryIterator<T> {
- var result : Dynamic;
- var nextValue : Maybe<T>;
- 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;
+class ScheduleParameters {
+ var row_id : String;
+ var rowDetails: Hash<Detail>;
+
+ 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<Detail>();
+ var position = 1;
+ for(id in row_ids) {
+ rowDetails.set(id, {
+ id: id
+ ,quantity: null
+ ,position: position++
+ });
+ }
+ }
+ php.Lib.dump(rowDetails);
}
- public function hasNext() : Bool {
- return this.nextValue != Nothing;
- }
+public function position(id: String) : Int {
+ return rowDetails == null ? rowDetails.get(id).position : null;
- 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');
- }
}
+
+
class ItemScheduler {
var stock_id:String;
+ var startLocation:String;
var qoh: Int;
- function new(stock_id: String) {
+ 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');
}
function tableHeader() {
- return ["Order", "Customer", "Quantity", "Left", "On Hand", "Loc", "Required Date"];
+ return ["Order", "Customer", "Quantity", "Before", "After", "Loc", "From", "Required Date", "Comment"];
}
function generateTable(): Void {
- for(location in locations()) {
- formatLocation(location);
- }
- for(order in this.orders()) {
- this.formatRow(order);
+ var startDate = Date.fromTime(0);
+
+ // 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(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 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<Dynamic> = [
- 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('<tr class="'+status+'">');
- for(cell in cells) {
- php.Lib.print('<td>');
- php.Lib.print(cell);
+ function printRow(tds : Array<Dynamic>, attributes : Array<String>) {
+ php.Lib.print('<tr '+attributes.join(' ')+'>');
+ var position : Int = 1;
+ for(td in tds) {
+ php.Lib.print('<td class="cell_'+position+'">');
+ if(td) php.Lib.print(td);
php.Lib.print('</td>');
+ position++;
}
php.Lib.print('</tr>');
-
-
}
- function formatLocation(location : Location) {
- var cells = [
- location.code
- ,location.name
- ];
- var status = 'header';
- php.Lib.print('<tr class="'+status+'">');
- for(cell in cells) {
- php.Lib.print('<td>');
- php.Lib.print(cell);
- php.Lib.print('</td>');
+ function formatOrder(order : Dynamic, left : Int, date : Date) {
+ var row_id = 'order_'+order.id;
+ 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');
}
- php.Lib.print('</tr>');
- }
- function schedules() {
- //return orders()+locations();
- //return orders();
- return cast(locations(), Array<Dynamic>);
+ /* 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 <Dynamic> = [
+ order.order_id
+ , '<a href="/modules/order_line_extra/order_lines_view.php?customer_id='+Std.string(order.debtor_no)+'">'+order.deliver_to+'</a>'
+ ,'<input type="text" name="'+row_id+'[quantity]" value="'+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 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 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 locations() {
- var TB = FA.tb();
- var sql = 'SELECT *
- FROM '+TB+'locations';
- var _locs = [];
- for(row in FA.query(sql)) {
- _locs.push(new Location(row));
- }
+ /*
+ function schedules() {
+//return orders()+locations();
+//return orders();
+return cast(locations(), Array<Dynamic>);
+
+}
+ */
+
+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() {
+ var rows = loadOrders();
+ var orderList = [];
+ for(row in rows) {
+ var order = php.Lib.objectOfAssociativeArray(row);
+ orderList.push(order);
+ };
+
+ return orderList;
+}
- return _locs;
-
- }
- function purcharseOrders() {
+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() {
+}
+
+
}