2 require_once($path_to_root.'/'.'includes/date_functions.inc');
5 function __construct($set=null) {
6 $this->pairs = $set ? array_merge($set->pairs) : array();
9 function add($value, $field, $quote=true) {
11 array_push($this->pairs, $quote ? "$field = '$value'" : "$field = $value");
17 function addDate($date, $field) {
18 return $this->add(date2sql($date), $field);
22 return implode(', ', $this->pairs);
30 public $quantity_dispatched=0;
33 function __construct($start_date, $period=null) {
34 $this->start_date = $start_date;
35 $this->end_date = $start_date;
36 if($period) $this->extend($period);
39 function extend($days) {
40 $this->end_date = add_days($this->end_date, $days);
45 public $detail_ids = array() ;
53 public function __construct(array $data) {
54 $this->detail_ids = array();
55 foreach($data['detail'] as $detail_id => $detail) {
56 array_push($this->detail_ids, $detail_id);
58 $this->start_date = $data['start_date'];
59 $this->end_date = $data['end_date'];
60 $this->start_offset = $data['start_offset'];
61 $this->end_offset = $data['end_offset'];
62 $this->days = date_diff2($this->end_date, $this->start_date, 'd');
64 $this->max_quantity = $data['max_quantity'];
67 protected function loadDetail($detail_id) {
69 FROM ".TB_PREF."sales_order_details
70 WHERE id = $detail_id";
71 $result = db_query($sql);
72 return db_fetch($result);
75 public function splitAll() {
77 foreach($this->detail_ids as $detail_id) {
78 display_warning("processing $detail_id");
79 $detail = $this->loadDetail($detail_id);
80 $splits = $this->split($detail);
81 foreach($splits as $split) $this->alterSplit($split);
82 $ok &= $this->saveSplits($detail, $splits);
88 public function days() {
94 /* This function splits on order detail in bits of a specified size.
95 * Each split starting at the end time of the previous one.
96 * the first split starts at the start_date and ends at the end_date.
97 * The 'splitting' split the whole quantity not only the quantity left to dispatch
98 * However, fully dispatched split won't be split in real, but merged with the next one
100 public function split($row) {
102 $quantity = $row['quantity'];
103 $quantity_sent = $row['qty_sent'];
105 /* Check if the item has been fully dispatched.
106 * If so, there is no need to do anything.
108 if($quantity_sent >= $quantity) return $splits;
110 // determine the number of split needed. This will give us the lenght of a split.
111 $nsplit = ceil($quantity/$this->max_quantity);
113 $period = $this->days/$nsplit;
115 array_push($splits, $split = new Split($this->start_date, $period));
116 $split->quantity_dispatched = $quantity_sent;
117 $split_quantity = min($quantity, $this->max_quantity);
118 while($split_quantity > 0) {
119 $split->quantity += $split_quantity;
120 // Check if the split has been entirely dispatch or not.
121 if($split->quantity_dispatched > $split->quantity) {
123 $split->extend($period);
126 // create a new split
127 array_push($splits, $split = new Split($split->end_date, $period));
130 $quantity -= $split_quantity;
131 $split_quantity = min($quantity, $this->max_quantity);
134 // We need to remove the last split if it's empty
135 if($split->quantity == 0) array_pop($splits);
139 function alterSplit($split) {
140 foreach(explode(' ', 'start end') as $att) {
141 $date = "${att}_date";
142 $offset = "${att}_offset";
143 if($this->$offset === null || $this->$offset === "") {
144 $split->$date = null;
147 $split->$date = add_days($split->$date, $this->$offset);
152 public function saveSplits($detail, $splits) {
153 if(empty($splits)) return true;
155 $detail_id = $detail['id'];
156 $priority = $detail['priority'];
157 $priority_offset = 1;
158 $order_no = $detail['order_no'];
159 $trans_type = $detail['trans_type'];
161 /* We need to update the first one (as it exists already in the database)
162 * but insert the following one.
164 $first = array_shift($splits);
166 $set->addDate($first->start_date, 'hold_until_date')
167 ->addDate($first->end_date, 'expiry_date')
168 ->add($first->quantity, 'quantity', false);
169 display_warning($set->toString());
170 db_query("UPDATE ".TB_PREF."sales_order_details
171 SET {$set->toString()}
172 WHERE id = $detail_id", "Problem splitting order details $detail_id");
174 // Compute common field for each split
175 $common_set = new SqlSet();
176 $common_set->add($order_no, 'order_no', false)
177 ->add($trans_type, 'trans_type')
178 ->add($detail['required_date'], 'required_date')
179 ->add($detail['comment'], 'comment')
180 ->add($detail['stk_code'], 'stk_code')
181 ->add($detail['description'], 'description')
182 ->add($detail['unit_price'], 'unit_price', false)
183 ->add($detail['discount_percent'], 'discount_percent', false);
185 foreach($splits as $split) {
186 $set = new SqlSet($common_set);
187 $set->addDate($split->start_date, 'hold_until_date')
188 ->addDate($split->end_date, 'expiry_date')
189 ->add($split->quantity, 'quantity', false);
190 display_warning($set->toString());
191 db_query("INSERT INTO ".TB_PREF."sales_order_details
192 SET {$set->toString()}
193 , priority = '$priority' + INTERVAL ${priority_offset} second"
194 ,"Problem spliting order details $detail_id");