start_date = $start_date; $this->end_date = $start_date; if($period) $this->extend($period); } function extend($days) { $this->end_date = add_days($this->end_date, $days); } } class Splitter extends OrderAction { public $start_date; public $end_date; public $start_offset; public $end_offset; protected $days; public $max_quantity; public function __construct(array $data) { parent::__construct($data); $this->start_date = $data['start_date']; $this->end_date = $data['end_date']; $this->start_offset = $data['start_offset']; $this->end_offset = $data['end_offset']; $this->days = date_diff2($this->end_date, $this->start_date, 'd'); $this->max_quantity = $data['max_quantity']; } protected function loadDetail($detail_id) { $sql = "SELECT * FROM ".TB_PREF."sales_order_details WHERE id = $detail_id"; $result = db_query($sql); return db_fetch($result); } public function splitAll() { $ok = true; foreach($this->detail_ids as $detail_id) { display_warning("processing $detail_id"); $detail = $this->loadDetail($detail_id); $splits = $this->split($detail); foreach($splits as $split) $this->alterSplit($split); $ok &= $this->saveSplits($detail, $splits); } return $ok; } public function days() { return $this->days; } /* This function splits on order detail in bits of a specified size. * Each split starting at the end time of the previous one. * the first split starts at the start_date and ends at the end_date. * The 'splitting' split the whole quantity not only the quantity left to dispatch * However, fully dispatched split won't be split in real, but merged with the next one */ public function split($row) { $splits = array(); $quantity = $row['quantity']; $quantity_sent = $row['qty_sent']; /* Check if the item has been fully dispatched. * If so, there is no need to do anything. */ if($quantity_sent >= $quantity) return $splits; // determine the number of split needed. This will give us the lenght of a split. $nsplit = ceil($quantity/$this->max_quantity); $period = $this->days/$nsplit; array_push($splits, $split = new Split($this->start_date, $period)); $split->quantity_dispatched = $quantity_sent; $split_quantity = min($quantity, $this->max_quantity); while($split_quantity > 0) { $split->quantity += $split_quantity; // Check if the split has been entirely dispatch or not. if($split->quantity_dispatched > $split->quantity) { //extend the split $split->extend($period); } else { // create a new split array_push($splits, $split = new Split($split->end_date, $period)); } $quantity -= $split_quantity; $split_quantity = min($quantity, $this->max_quantity); } // We need to remove the last split if it's empty if($split->quantity == 0) array_pop($splits); return $splits; } function alterSplit($split) { foreach(explode(' ', 'start end') as $att) { $date = "${att}_date"; $offset = "${att}_offset"; if($this->$offset === null || $this->$offset === "") { $split->$date = null; } else { $split->$date = add_days($split->$date, $this->$offset); } } } public function saveSplits($detail, $splits) { if(empty($splits)) return true; $detail_id = $detail['id']; $priority = $detail['priority']; $priority_offset = 1; $order_no = $detail['order_no']; $trans_type = $detail['trans_type']; /* We need to update the first one (as it exists already in the database) * but insert the following one. */ $first = array_shift($splits); $set = new SqlSet(); $set->addDate($first->start_date, 'hold_until_date') ->addDate($first->end_date, 'expiry_date') ->add($first->quantity, 'quantity', false); display_warning($set->toString()); db_query("UPDATE ".TB_PREF."sales_order_details SET {$set->toString()} WHERE id = $detail_id", "Problem splitting order details $detail_id"); // Compute common field for each split $common_set = new SqlSet(); $common_set->add($order_no, 'order_no', false) ->add($trans_type, 'trans_type') ->add($detail['required_date'], 'required_date') ->add($detail['comment'], 'comment') ->add($detail['stk_code'], 'stk_code') ->add($detail['description'], 'description') ->add($detail['unit_price'], 'unit_price', false) ->add($detail['discount_percent'], 'discount_percent', false); foreach($splits as $split) { $set = new SqlSet($common_set); $set->addDate($split->start_date, 'hold_until_date') ->addDate($split->end_date, 'expiry_date') ->add($split->quantity, 'quantity', false); display_warning($set->toString()); db_query("INSERT INTO ".TB_PREF."sales_order_details SET {$set->toString()} , priority = '$priority' + INTERVAL ${priority_offset} second" ,"Problem spliting order details $detail_id"); $priority_offset++; } return true; } } ?>