Use picked quantity in available Q&A on order summary
[order_line_extra.git] / includes / order_lines.inc
1 <?php
2 include_once('order_xtra_config.inc');
3 include_once('picking.inc');
4 include_once($path_to_root."/includes/ui/ui_input.inc");
5 /* This utility function remove beginning <td> and </td> from a string
6  * generated by the above *_cell function.
7  * This is usefull to use the result of the function within a pager
8  * which already include the <td>...</td>
9  * However, for function which doesn't return a string
10  * but echo, we need to capture the output of the echo first.
11  */
12 function start_extract_cell() {
13         // We need 
14         ob_start();
15 }
16
17 function end_extract_cell() {
18         $content = ob_get_contents();
19         ob_end_clean();
20         return extract_cell($content);
21 }
22
23 function extract_cell($td) {
24         if(preg_match('/\s*<td>(.*)<\/td>\s*/s', $td, $matches)) {
25                 return $matches[1];
26         }
27         else {
28                 return $td;
29         }
30 }
31
32 /* remove unchecked data so each
33  * funcion doesn't to check what's been checked or not. 
34  */
35 function filter_data(&$data) {
36         if(!isset($data['detail'])) return;
37         $new_details = array();
38         foreach(@$data['detail'] as $detail_id => $values) {
39                 if(@$values['check'] === 'on') $new_details[$detail_id]=$values;
40         }
41         $data['detail'] = $new_details;
42 }
43
44 function post_to_detail_ids() {
45         if(!isset($_POST['detail'])) return;
46         $detail_ids = array();
47         foreach($_POST['detail'] as $detail_id => $values) {
48                 array_push($detail_ids, $detail_id);
49         }
50
51         return $detail_ids;
52 }
53
54 function update_extra_order_details() {
55         if(!isset($_POST['Update']) || $_POST['Update'] != 'Update')  return;
56
57         $cart = post_to_detail_ids();
58         if($cart === null) return;
59 begin_transaction();
60         hook_db_prewrite($cart, 'order_xtra');
61         // update in database all field
62         $date_fields = array('hold_until_date', 'required_date', 'expiry_date', 'priority');
63         foreach($_POST['detail'] as $detail_id => $values) {
64                 $set = array();
65                 $comment=$values['comment'];
66           array_push($set, " comment='$comment' "); // erase comment if needed.
67                 foreach($date_fields as $date_field) {
68                         if(isset($values[$date_field])) {
69                                 $input_date = trim($values[$date_field]);
70                                 if($input_date == "")  {
71                                         // Only the priority field can be set to null.
72                                         if($date_field == 'priority') array_push($set," $date_field = NULL");
73                                 } else {
74                                         $date = date2sql($input_date);
75                                         array_push($set," $date_field='$date' ");
76                                 }
77                         }
78                 }
79
80                 if(!empty($set))  {
81                         $sql = "UPDATE ".TB_PREF."sales_order_details  SET ".implode($set,', ')."  WHERE id = $detail_id ";
82
83                         if(!db_query($sql)) {
84                                 display_error('Problem while updating order details. Try again');
85                                 cancel_transaction();
86                                 return;
87                         }
88                 }
89         }
90         hook_db_postwrite($cart, 'order_xtra');
91         commit_transaction();
92
93
94         display_notification('Order details updated');
95
96 }
97
98 function split_order_details() {
99         if(!isset($_POST['Split']) || $_POST['Split'] != 'Split')  return;
100         $splitter = new Splitter($_POST);
101         begin_transaction();
102         $cart = post_to_detail_ids();
103         if($cart === null) return;
104         hook_db_prewrite($cart, 'order_xtra');
105                 if($splitter->splitAll()) display_warning("Items have been split.");
106         hook_db_postwrite($cart, 'order_xtra');
107         commit_transaction();
108 }
109
110 function bulk_update_order_details() {
111         if(!isset($_POST['Bulk']) || $_POST['Bulk'] != 'Bulk')  return;
112         $bulk_updater = new BulkUpdater($_POST);
113         begin_transaction();
114         $cart = post_to_detail_ids();
115         if($cart === null) return;
116         hook_db_prewrite($cart, 'order_xtra');
117         $bulk_updater->update();
118         hook_db_postwrite($cart, 'order_xtra');
119         commit_transaction();
120 }
121
122
123
124 function compute_input_name($row, $field) {
125         $row_id = $row['id'];
126         return "detail[$row_id][$field]";
127 }
128
129 function view_link($dummy, $order_no)
130 {
131         return  get_customer_trans_view_str(ST_SALESORDER, $order_no);
132 }
133
134 function edit_link($row, $order_no) {
135         return pager_link( _("# $order_no"),
136         "/sales/sales_order_entry.php?ModifyOrderNumber=" .$row['order_no']);
137 }
138
139 function item_link($dummy, $stock_id)
140 {
141         return pager_link( _($stock_id),
142         "/modules/order_line_extra/item_schedule.php?stock_id=" .$stock_id);
143 }
144
145 function order_link($row)
146 {
147         return pager_link( _("Sales Order"),
148         "/sales/sales_order_entry.php?NewQuoteToSalesOrder=" .$row['order_no'], ICON_DOC);
149 }
150
151 function customer_link($row) {
152         return customer_link2($row['debtor_ref'], $row['debtor_no']);
153 }
154
155 function customer_link2($name, $id) {
156         return pager_link(_($name), "/modules/order_line_extra/order_lines_view.php?customer_id=${id}");
157
158 }
159
160 function aggregate_comment($row) {
161         $comment =  $row['order_comment'].";".$row['detail_comment'];
162         if($comment) {
163                 $comments = array_map('trim', explode(';', $comment));
164                 $comments = array_filter($comments);
165                 $first = array_shift($comments);
166                 if(count($comments) == 0)
167                         return $first;
168                 else {
169                         $tooltip = implode('<br> - ', $comments);
170                         return "$first <span class='before-tooltip'>more<span class='tooltip'>&nbsp$tooltip</span><span>";
171                 }
172         }
173         return '';
174 }
175
176 function available_quantity($row, $available) {
177         $quantity = $row['quantity'];
178         $class = '';
179         if($available== 0) $class = $row['qoh'] == 0 ? 'stockmankobg' : 'limited';
180         else if($quantity > $available)  $class = 'partial';
181         else if(OrderXtraConfig::early(sql2date($row['hold_until_date']))) $class = 'early';
182
183         return "<span class='$class'>$available<span>";
184 }
185
186 function input_date_details($row, $field_name, $date) {
187 $row_id = $row['id'];
188         $name = compute_input_name($row, $field_name);
189
190 $_POST[$name] = sql2date($date);
191
192         start_extract_cell();
193                 date_cells (null, $name, 'title', null, 0,0,1001);
194         return end_extract_cell();
195
196
197         return "
198 <input type='text' value='$date' name='$name'>
199 ";
200 }
201
202 function input_priority_date_details($row, $date) {
203         return input_date_details($row, 'priority', $date);
204 }
205
206 function input_hold_until_date_details($row, $date) {
207         return input_date_details($row, 'hold_until_date', $date);
208 }
209
210 function input_required_date_details($row, $date) {
211         return input_date_details($row, 'required_date', $date);
212 }
213
214 function input_expiry_date_details($row, $date) {
215         return input_date_details($row, 'expiry_date', $date);
216 }
217
218 function input_comment_details($row, $comment) {
219 $row_id = $row['id'];
220         return "
221 <input type='text' value='$comment' name='detail[$row_id][comment]'>
222 ";
223 }
224
225 function input_check_details($row, $dummy) {
226         $row_id = $row['id'];
227                 return "
228                 <input type='checkbox' class='check_detail' name='detail[$row_id][check]'>";
229 }
230
231 function pick_checkbox($row)
232 {
233         $id = $row['debtor_no']."_".$row['branch_code'];
234         $name = "chgpck" .$id;
235         $value = $row['quantity_to_pick'] !== null;
236
237 // save also in hidden field for testing during 'Update'
238  return checkbox(null, $name, $value, true,
239         _('Pick all possible item for this branch.'))
240         . hidden('pick['.$id.']', $value, false);
241 }
242
243 function get_order_details_extra($customer_id, $location, $item_like, $order_id) {
244         $select = "sod.id
245         , so.order_no
246         , stk_code
247         , sod.quantity - qty_sent quantity
248         , GREATEST(0, LEAST(qoh.quantity  - quantity_before - COALESCE(tp.quantity,0) + COALESCE(p.quantity, 0) , sod.quantity - qty_sent)) AS available
249         , quantity_before
250         , qoh.quantity AS qoh
251         , p.quantity AS quantity_to_pick
252         , sod.`priority`
253         , hold_until_date
254         , required_date
255         , expiry_date
256         ,comment";
257         $from =  TB_PREF."sales_order_details sod
258         JOIN ".TB_PREF."sales_orders so ON (so.order_no = sod.order_no
259                 AND so.trans_type = sod.trans_type
260                 AND so.trans_type = ".ST_SALESORDER."
261                 AND so.debtor_no = $customer_id
262         )
263         JOIN ".TB_PREF."denorm_qoh qoh ON (stock_id = stk_code AND loc_code = '$location')
264         LEFT JOIN ".TB_PREF."denorm_order_details_queue  d ON (d.id = sod.id)
265         LEFT JOIN (".pick_query().") p ON (detail_id = sod.id)
266         LEFT JOIN (".totalpick_query().") tp ON (tp.stock_id = sod.stk_code)
267         ";
268         $where = " sod.quantity > qty_sent
269         ";
270
271         if($item_like) {
272                         if($item_like[0]=='/')  {
273                                 $regexp = substr($item_like, 1);
274                                 $where .= " AND stk_code RLIKE '$regexp'";
275                         }
276                         else 
277                                 $where .= " AND stk_code LIKE '$item_like'";
278         }
279
280         if($order_id) {
281                 $where .= " AND so.order_no = $order_id";
282         }
283
284         return array('select' => $select, 'from' => $from, 'where' => $where);
285 }
286
287 function get_order_summary($location) {
288         $held_condition = OrderXtraConfig::sql_held_condition();
289
290         $pick = pick_query();
291
292         $sub = "SELECT debtor_no, debtor_ref, branch_code, branch_ref, stk_code
293         , MIN(delivery_date)
294         , SUM(d.quantity) AS quantity
295         , SUM((d.quantity)*unit_price*(1-discount_percent/100)) AS amount
296         , MIN(required_date)
297         , GROUP_CONCAT(distinct comments separator ';') AS order_comment
298         , GROUP_CONCAT(distinct comment separator ';') AS detail_comment
299         , MAX(quantity_before) AS quantity_before
300         , @available := GREATEST(LEAST(d.quantity, COALESCE(qoh.quantity,0) - COALESCE(tp.quantity,0) + COALESCE(p.quantity,0) - quantity_before), 0)
301         , SUM(IF($held_condition, @available , 0)) AS quantity_held
302         , SUM(IF($held_condition, 0,  @available)) AS available_quantity
303         , SUM(IF($held_condition, 0,  @available*unit_price*(1-discount_percent/100))) AS available_amount
304         , SUM(p.quantity) AS quantity_to_pick
305         , SUM(p.quantity*unit_price) AS amount_to_pick
306         FROM ".TB_PREF."sales_order_details sod
307         JOIN ".TB_PREF."sales_orders so ON (so.order_no = sod.order_no
308                 AND so.trans_type = sod.trans_type
309                 AND so.trans_type = ".ST_SALESORDER."
310         )
311         JOIN ".TB_PREF."debtors_master USING (debtor_no)
312         JOIN ".TB_PREF."cust_branch USING (debtor_no, branch_code)
313         LEFT JOIN ($pick) p ON (detail_id = sod.id)
314         JOIN ".TB_PREF."denorm_order_details_queue  d ON (d.id = sod.id)
315         LEFT JOIN ".TB_PREF."denorm_qoh qoh ON (qoh.stock_id = stk_code AND loc_code = '$location')
316         LEFT JOIN (".totalpick_query().") tp ON (tp.stock_id = sod.stk_code)
317         WHERE sod.quantity > qty_sent AND ".ST_SALESORDER."
318         GROUP BY debtor_no, branch_code, stk_code
319         ";
320
321         //$sub = TB_PREF."order_summary_view";
322         //
323
324         $sql = array( "select" => "debtor_no, branch_code, debtor_ref, branch_ref
325         , `min(delivery_date)` as delivery_date
326         , sum(sub.quantity) as quantity
327         , sum(sub.amount) as amount
328         , sum(sub.available_quantity)
329         , sum(sub.available_amount)
330         , sum(quantity_held) as quantity_help
331         ,  min(`min(required_date)`) as required_date
332         , group_concat(distinct order_comment separator ';') as order_comment
333         , group_concat(distinct detail_comment separator ';') as detail_comment
334         , sum(quantity_to_pick) as quantity_to_pick
335         , sum(amount_to_pick) as amount_to_pick
336         ", "from" => " ($sub) sub
337                         LEFT JOIN ".TB_PREF."denorm_qoh qoh ON (stock_id = stk_code AND loc_code = '$location')
338
339         ", "group" => " debtor_no, branch_code
340         ");
341
342         return $sql;
343 }
344 ?>