2 require_once('includes/sql_set.inc');
8 public $quantity_dispatched=0;
11 function __construct($start_date, $period=null) {
12 $this->start_date = $start_date;
13 $this->end_date = $start_date;
14 if($period) $this->extend($period);
17 function extend($days) {
18 $this->end_date = add_days($this->end_date, $days);
22 class Splitter extends OrderAction {
30 public function __construct(array $data) {
31 parent::__construct($data);
32 $this->start_date = $data['start_date'];
33 $this->end_date = $data['end_date'];
34 $this->start_offset = $data['start_offset'];
35 $this->end_offset = $data['end_offset'];
36 $this->days = date_diff2($this->end_date, $this->start_date, 'd');
38 $this->max_quantity = $data['max_quantity'];
41 protected function loadDetail($detail_id) {
43 FROM ".TB_PREF."sales_order_details
44 WHERE id = $detail_id";
45 $result = db_query($sql);
46 return db_fetch($result);
49 public function splitAll() {
51 foreach($this->detail_ids as $detail_id) {
52 $detail = $this->loadDetail($detail_id);
53 $splits = $this->split($detail);
54 foreach($splits as $split) $this->alterSplit($split);
55 $ok &= $this->saveSplits($detail, $splits);
61 public function days() {
67 /* This function splits on order detail in bits of a specified size.
68 * Each split starting at the end time of the previous one.
69 * the first split starts at the start_date and ends at the end_date.
70 * The 'splitting' split the whole quantity not only the quantity left to dispatch
71 * However, fully dispatched split won't be split in real, but merged with the next one
73 public function split($row) {
75 $quantity = $row['quantity'];
76 $quantity_sent = $row['qty_sent'];
78 /* Check if the item has been fully dispatched.
79 * If so, there is no need to do anything.
81 if($quantity_sent >= $quantity) return $splits;
83 // determine the number of split needed. This will give us the lenght of a split.
84 $nsplit = ceil($quantity/$this->max_quantity);
86 $period = $this->days/$nsplit;
88 array_push($splits, $split = new Split($this->start_date, $period));
89 $split->quantity_dispatched = $quantity_sent;
90 $split_quantity = min($quantity, $this->max_quantity);
91 while($split_quantity > 0) {
92 $split->quantity += $split_quantity;
93 // Check if the split has been entirely dispatch or not.
94 if($split->quantity_dispatched > $split->quantity) {
96 $split->extend($period);
100 array_push($splits, $split = new Split($split->end_date, $period));
103 $quantity -= $split_quantity;
104 $split_quantity = min($quantity, $this->max_quantity);
107 // We need to remove the last split if it's empty
108 if($split->quantity == 0) array_pop($splits);
112 function alterSplit($split) {
113 foreach(explode(' ', 'start end') as $att) {
114 $date = "${att}_date";
115 $offset = "${att}_offset";
116 if($this->$offset === null || $this->$offset === "") {
117 $split->$date = null;
120 $split->$date = add_days($split->$date, $this->$offset);
125 public function saveSplits($detail, $splits) {
126 if(empty($splits)) return true;
128 $detail_id = $detail['id'];
129 $priority = $detail['priority'];
130 $priority_offset = 1;
131 $order_no = $detail['order_no'];
132 $trans_type = $detail['trans_type'];
134 /* We need to update the first one (as it exists already in the database)
135 * but insert the following one.
137 $first = array_shift($splits);
139 $set->addDate($first->start_date, 'hold_until_date')
140 ->addDate($first->end_date, 'expiry_date')
141 ->add($first->quantity, 'quantity', false);
142 db_query("UPDATE ".TB_PREF."sales_order_details
143 SET {$set->toString()}
144 WHERE id = $detail_id", "Problem splitting order details $detail_id");
146 // Compute common field for each split
147 $common_set = new SqlSet();
148 $common_set->add($order_no, 'order_no', false)
149 ->add($trans_type, 'trans_type')
150 ->add($detail['required_date'], 'required_date')
151 ->add($detail['comment'], 'comment')
152 ->add($detail['stk_code'], 'stk_code')
153 ->add($detail['description'], 'description')
154 ->add($detail['unit_price'], 'unit_price', false)
155 ->add($detail['discount_percent'], 'discount_percent', false)
156 ->add($detail['ref'].":split:".$detail['id'], 'ref')
159 foreach($splits as $split) {
160 $set = new SqlSet($common_set);
161 $set->addDate($split->start_date, 'hold_until_date')
162 ->addDate($split->end_date, 'expiry_date')
163 ->add($split->quantity, 'quantity', false);
164 db_query("INSERT INTO ".TB_PREF."sales_order_details
165 SET {$set->toString()}
166 , priority = '$priority' + INTERVAL ${priority_offset} second"
167 ,"Problem spliting order details $detail_id");