All tests pass.
[order_line_extra.git] / includes / splitter.inc
1 <?php
2 require_once($path_to_root.'/'.'includes/date_functions.inc');
3 class Split {
4         public $start_date;
5         public $end_date;
6         public $quantity=0;
7         public $quantity_dispatched=0;
8         
9
10         function __construct($start_date, $period=null) {
11                         $this->start_date = $start_date;
12                         $this->end_date = $start_date;
13                         if($period) $this->extend($period);
14         }
15
16         function extend($days) {
17                         $this->end_date = add_days($this->end_date, $days);
18         }
19 }
20
21 class Splitter {
22         public $detail_ids = array() ;
23         public $start_date;
24         public $end_date;
25         protected $days;
26         public $max_quantity;
27
28         public function __construct(array $data) {
29                 $this->details_id = array();
30                 foreach($data['detail'] as $detail_id => $detail) {
31                         array_push($this->details_id, $detail_id);
32                 }
33                 $this->start_date = $data['start_date'];
34                 $this->end_date = $data['end_date'];
35                 $this->days = date_diff2($this->end_date, $this->start_date, 'd');
36
37                 $this->max_quantity = $data['max_quantity'];
38         }
39
40         protected function loadDetail($detail_id) {
41                 $sql = "SELECT *
42                                                 FROM ".TB_PREF."sales_order_details
43                                                 WHERE id = $detail_id";
44                 $result = db_query($sql);
45                 return db_fetch($result);
46         }
47
48         public function splitAll() {
49                 foreach($this->detail_ids as $detail_id) {
50                                 $detail = $this->loadDetail($detail_id);
51                                 $splits = $this->split($detail);
52                                 $this->saveSplits($detail, $splits);
53                 }
54         }
55
56         public function days() {
57                 return $this->days;
58         }
59
60
61         
62         /* This function splits on order detail in bits of a specified size.
63  * Each split  starting at the end time of the previous one.
64  * the first split starts at the start_date and ends at the end_date.
65  * The 'splitting' split the whole quantity not only the quantity left to dispatch
66  * However, fully dispatched split won't be split in real, but merged with the next one
67  */
68         public function split($row) {
69                 $splits = array();
70                 $quantity = $row['quantity'];
71                 $quantity_sent = $row['qty_sent'];
72
73                 /* Check if the item has been fully dispatched.
74                  * If so,  there is no need to do anything.
75                  */
76                 if($quantity_sent >= $quantity) return $splits;
77                 
78                 // determine the number of split needed. This will give us the lenght of a split.
79                 $nsplit = ceil($quantity/$this->max_quantity);
80
81                 $period = $this->days/$nsplit;
82
83                 array_push($splits, $split = new Split($this->start_date, $period));
84                 $split->quantity_dispatched = $quantity_sent;
85                 $split_quantity = min($quantity, $this->max_quantity);
86                 while($split_quantity > 0) {
87                                         $split->quantity += $split_quantity;
88                                 // Check if the split has been entirely dispatch or not.
89                                 if($split->quantity_dispatched > $split->quantity) {
90                                         //extend the split
91                                         $split->extend($period);
92                                 }
93                                 else {
94                                         // create a new split
95                                         array_push($splits, $split = new Split($split->end_date, $period));
96                                         
97                                 }
98                                 $quantity -= $split_quantity;
99                                 $split_quantity = min($quantity, $this->max_quantity);
100                 }
101
102                 // We need to remove the last split if it's empty
103                 if($split->quantity == 0) array_pop($splits);
104                 return $splits;
105         }
106
107 }
108 ?>