24 class ScheduleParameters {
26 var rowDetails: Hash<Detail>;
27 public var mode:ScheduleMode;
29 function new(rawData : Dynamic) {
30 var data = php.Lib.hashOfAssociativeArray(rawData);
31 row_id = data.get('row_id');
32 var raw_order : Dynamic = data.get('row_order');
33 mode = ScheduleMode.Move;
35 var row_ids = php.Lib.toHaxeArray(raw_order);
37 rowDetails = new Hash<Detail>();
40 var d : Dynamic = data.get(id);
42 var quantity : Int = null;
44 var o = php.Lib.objectOfAssociativeArray(d);
45 quantity = Std.parseInt(o.quantity);
59 public function setMode(action:String) {
60 mode = switch(action) {
70 public function position(id: String) : Null<Int> {
71 if(rowDetails == null) return null;
72 return rowDetails.get(id).position;
76 public function priority(order : {id: String, priority: Date}) : Int {
77 var orderId = ItemScheduler.orderId(order);
78 var orderPosition = position(orderId);
79 return orderPosition != null ? orderPosition : cast(order.priority.getTime(), Int);
86 var startLocation:String;
87 var parameters:ScheduleParameters;
89 function new(stock_id: String, startLocation, parameters : Null<ScheduleParameters>) {
90 this.stock_id = stock_id;
91 this.startLocation = startLocation;
92 this.parameters = parameters;
93 qoh = untyped __call__('get_qoh_on_date', this.stock_id, startLocation);
96 function tableHeader() {
97 return ["Order", "Customer", "Quantity", "Before", "After", "Loc", "From", "Required Date", "Comment"];
100 function generateTable(): Void {
101 var startDate = Date.fromTime(0);
103 // Sort location by date
104 var locations = this.locations();
105 locations.sort(function(a, b) {
106 var as = a.delivery.getTime();
107 var bs = b.delivery.getTime();
115 // Get the start location, it should be the first one
116 var locationIter = locations.iterator();
117 var location = locationIter.next();
118 var qoh : Int = location.quantityOnHand(stock_id, null);
120 formatLocation(location, "Initial", left);
122 // We display the order ordered by priority
123 // But insert the location when needed (meaning
124 // when we run out of item available
125 for(order in orders()) {
126 var quantity : Int = Std.parseInt(order.quantity);
128 while(0 >= left && locationIter.hasNext()) {
129 location = locationIter.next();
130 var quantityForLocation : Int = location.quantityOnHand(stock_id, null) + location.quantityOnOrder(stock_id);
131 if(quantityForLocation == null || quantityForLocation == 0 || location.delivery == null) continue;
132 left += quantityForLocation;
133 formatLocation(location, "Delivery", left);
137 var now = Date.now();
138 //formatOrder(order, left, location.delivery); // now.getTime() > location.delivery ? now : location.delivery);
139 formatOrder(order, left, now.getTime() > location.delivery.getTime() ? now : location.delivery);
142 // display the left locations
143 while(0 >= left && locationIter.hasNext()) {
144 location = locationIter.next();
145 var quantityForLocation : Int = location.quantityOnHand(stock_id, null);
146 if(quantityForLocation == null || quantityForLocation == 0) continue;
147 left += quantityForLocation;
148 formatLocation(location, "Delivery", left);
153 function printRow(tds : Array<Dynamic>, attributes : Array<String>) {
154 php.Lib.print('<tr '+attributes.join(' ')+'>');
155 var position : Int = 1;
157 php.Lib.print('<td class="cell_'+position+'">');
158 if(td) php.Lib.print(td);
159 php.Lib.print('</td>');
162 php.Lib.print('</tr>');
165 static public function orderId(order) {
166 return 'order_'+order.id;
169 function formatOrder(order : Dynamic, left : Int, date : Date) {
170 var row_id = orderId(order);
171 var attributes = ['id = "'+row_id+'"'];
173 var before : Int = left + order.quantity;
174 /* We have basically 3 different cases;
175 * - the order can be fullfilled
176 * - the order can be partially
180 classes.push('soldout');
183 classes.push('partial');
186 classes.push('full');
189 /* The order can also be late if we need
190 * to wait for a delivery to get it
191 * or early if the item is on hold.
193 var required_by : Date = FA.sql2date(order.required_date);
194 if(required_by == null) required_by = FA.sql2date(order.expiry_date);
195 if(required_by != null && required_by.getTime() < date.getTime()) {
196 classes.push('late');
199 var hold_until : Date = FA.sql2date(order.hold_until_date);
200 php.Lib.print(hold_until);
202 if(hold_until == null) hold_until = FA.sql2date(order.delivery_date);
203 if(hold_until.getTime() > date.getTime()) {
204 classes.push('early');
207 classes.push('on_time');
210 var cells : Array <Dynamic> = [
212 , '<a href="/modules/order_line_extra/order_lines_view.php?customer_id='+Std.string(order.debtor_no)+'">'+order.deliver_to+'</a>'
213 ,'<input type="text" name="'+row_id+'[quantity]" value="'+order.quantity+'">'
217 ,order.hold_until_date
222 attributes.push('class="'+classes.join(' ')+'"');
223 printRow(cells, attributes);
227 function formatLocation(location : Location, type: String, left : Int) {
231 ,location.quantityOnHand(stock_id, null)
232 ,left-location.quantityOnHand(stock_id, null)
235 ,location.delivery.getTime() == 0 ? '' : location.delivery.format("%F")
240 printRow(cells, ['class = "tableheader location"', 'id = "loc_'+location.code+'"']);
244 function schedules() {
245 //return orders()+locations();
247 return cast(locations(), Array<Dynamic>);
252 private function loadOrders() {
253 var tb : String = untyped __php__('TB_PREF');
254 var sql : String = "SELECT * , d.quantity as qty, d.priority AS pp
255 FROM "+tb+"denorm_order_details_queue d
256 JOIN "+tb+"sales_order_details od ON (od.id = d.id)
257 JOIN "+tb+"sales_orders so ON (so.order_no = d.order_id)
258 WHERE stock_id = '"+this.stock_id+"'
259 AND od.trans_type = 30
260 ORDER by d.priority";
262 return FA.query(sql);
265 function orders():Array<Order> {
266 var rows = loadOrders();
269 // for some reason, priority is null
270 // so we use the pp field
271 var a:Dynamic = php.Lib.objectOfAssociativeArray(row);
273 order.priority = Date.fromString(a.pp);
274 order.quantity = a.qty;
275 orderList.push(order);
278 if(parameters != null) {
279 orderList.sort(function(a, b) { return parameters.priority(a)-parameters.priority(b); });
282 for(order in orderList) {
290 function locations() {
293 FROM '+TB+'locations';
295 for(row in FA.query(sql)) {
296 var location = new Location(row);
297 if(location.code == startLocation) {
298 location.delivery = Date.fromTime(0);
300 else if(location.delivery == null) {
303 _locs.push(location);
311 function purcharseOrders() {
313 var sql = 'SELECT SUM(quantity_ordered - quantity_received) as quantity
314 into_stock_location AS location
315 FROM '+TB+'purch_order_details
316 NATURAL JOIN '+TB+'purch_orders
317 WHERE item_code = "'+this.stock_id+'"
318 AND quantity_ordered > quantity_received
319 GROUP by item_code,delivery_date, into_stock_location
320 ORDER by delivery_date' ;
322 return FA.query(sql);
325 public function needsUpdate():Bool {
326 return parameters != null && parameters.mode == ScheduleMode.Move;
330 var orders = this.orders();
331 var priorities = Lambda.array(Lambda.map(orders, function(o) { return o.priority;}));
332 priorities.sort(function(a,b) {
333 var as = a.toString();
334 var bs = b.toString();
335 if (as < bs) return -1;
336 if( as > bs) return 1;
340 var iter = priorities.iterator();
342 var position:Int = 0-priorities.length;
343 for(order in orders) {
344 var new_priority = DateTools.delta(p, 1000*position);
345 untyped __call__ ('update_order_detail_priority', order.id, new_priority.toString());
350 untyped __call__ ('update_queue_quantity_for_item', stock_id);
354 public function action() {
355 if(parameters != null && parameters.mode == ScheduleMode.Update) {