Fix #7123 - getting abra ready to test
[Pman.Xtuple] / Import / Magento.php
1 <?php
2
3 require_once 'Pman/Roo.php';
4
5 class Pman_Xtuple_Import_Magento extends Pman_Roo
6 {
7     
8     function getAuth()
9     {
10         if (HTML_FlexyFramework::get()->cli) {
11             $this->authUser = DB_DataObject::Factory('Person');
12             $this->authUser->get('email','brian@bloomandgrowdirect.com');
13             return true;
14         }
15         return parent::getAuth();
16     }
17     
18     var $timer = false;
19     
20     function get()
21     { 
22         ini_set('memory_limit', '1024M'); 
23         $this->sessionState(0); // turn off session..
24        //$this->transObj = DB_DataObject::Factory('coitem');
25         
26 //        $this->transObj->query('BEGIN');
27         
28         PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($this, 'onPearError'));
29         
30         $this->timer = microtime(true);
31         
32         require_once 'File/Convert.php';
33         
34         $this->debugLog('reading /tmp/magento.csv');
35         $fc = new File_Convert('/tmp/magento.csv', 'text/csv');
36         $csv = $fc->convert('text/csv');
37         $this->debugLog('running import CSV');
38         $this->importCsv($csv);
39         
40     }
41     
42     
43     function debugLog($str)
44     {
45         if (!HTML_FlexyFramework::get()->cli) {
46             return;
47         }
48         static $start = false;
49         if (!$start) {
50             
51             $start = microtime(true);
52         }
53         $timed = microtime(true) - $start;
54         
55     
56         echo number_format($timed/60 ,2, '.',','). 'm MEM:' . number_format(memory_get_usage() /1000000,0, '.',','). 'M : '. $str . "\n";
57
58     }
59     
60     
61     function post()
62     {
63         ini_set('memory_limit', '512M'); 
64         set_time_limit(0);
65         $this->timer = microtime(true);
66         
67         $this->sessionState(0); // turn off session..
68         //$this->transObj = DB_DataObject::Factory('coitem');
69       
70 //        $this->transObj->query('BEGIN');
71                 
72         PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($this, 'onPearError'));
73         
74         $img = DB_DataObject::Factory('images');
75         $img->setFrom(array(
76             'onid' => 0,
77             'ontable' => 'ipshead'
78         ));
79         $img->onUpload(false);
80         
81         require_once 'File/Convert.php';
82         $fc = new File_Convert($img->getStoreName(), $img->mimetype );
83         $csv = $fc->convert('text/csv');
84         $this->importCsv($csv);
85     }
86     
87     function importCsv($content)
88     {
89         ini_set("auto_detect_line_endings", true);
90         
91         $this->debugLog('reading file');
92         
93         $fh = fopen($content, 'r');
94         
95         if (!$fh) {
96             $this->jerr("invalid content file");
97         }
98         // new format header
99         $reqs = array(
100             'ORDER ID', 'CREATION DATE', 'BILLING NAME', 
101             'CUSTOMER EMAIL', 'SHIPPING NAME', 'SHIPPING ADDRESS',
102             'SHIPPING CITY', 'SHIPPING STATE', 'SHIPPING POSTCODE', 
103             'SHIPPING COUNTRY', 'SHIPPING TELEPHONE', 'SHIPPING METHOD', 
104             'DELIVERY NOTE', 'SIGNATURE REQUIRED?', 'TOTAL WEIGHT', 
105             'CUSTOMER BALANCE', 'SHIPPING', 'GRAND TOTAL', 'GIFT CARD',
106             'TAX AMOUNT', 'SKU', 'PRODUCT NAME', 
107             'QTY', 'UNIT PRICE', 'SUBTOTAL', 
108             'DISCOUNT', 'DISCOUNTED TOTAL', 'PAYMENT METHOD', 
109             'GIFT WRAP ID', 'COUPON CODE', 'CUSTOMER GROUP'
110         );
111         
112         $cols = false;
113         $rows = array();
114         
115         
116         // load customers..
117         
118         $c = DB_DataObject::factory('custinfo');
119         $c->whereAdd("
120             cust_number = 'MGCREDITCARD'
121             OR
122             cust_number= 'MGPAYPAL'
123             OR
124             cust_number = 'MGDEPOSIT'
125         ");
126         
127         $customers = $c->fetchAll('cust_id', 'cust_number');
128         
129         if(count(array_values($customers)) != 3){
130             $this->jerr("error occur on getting MGCREDITCARD, MGPAYPAL and MGDEPOSIT customers". print_R($customers,true));
131         }
132         
133         foreach($customers as $id=>$n) {
134             $rows[$n] = array();
135         }
136         
137         $this->errmsg = array();
138         
139         $no_lines_in_file= count(file($content)) ;
140         
141         $no_split = $no_lines_in_file > 500 ? false : true; // small file just group by customers.. big file group by the first two char of the order number!
142         
143         if (!HTML_FlexyFramework::get()->cli && !$no_split && $no_lines_in_file > 2500) {
144             $this->jerr("file is too large to upload - please send to admin to import ($no_lines_in_file)");
145         }
146         
147         $ln = '';
148         $lnum=  0;
149         $od = false;
150         
151         while(false !== ($n = fgetcsv($fh,10000, ',', '"'))) {
152             $lnum++;
153             if (!strlen(implode('', $n))) {
154                 continue;
155             }
156             if (!$cols) {
157                 $cols = array();
158                 foreach($n as $k) {
159                     $cols[] = strtoupper(trim($k));
160                 }
161                 
162                 if (empty($cols)) {
163                     continue;
164                 }
165                 foreach($reqs as $req) {
166                     if (!in_array($req,$cols)) {
167                         $cols = false;
168                         break;
169                     }
170                 }
171                 continue;
172             }
173             
174             foreach ($cols as $k => $c){
175                 $c = strtoupper($c);
176                 if (empty($c) || !strlen(trim($c))) {
177                     continue;
178                 }
179                 
180                 if($c == 'ORDER ID'){
181                     if($ln != $n[$k]){
182                         $ln = $n[$k];
183                         $row = 1;
184                     }
185                     $r[$c] = substr($n[$k], -4) * 10000 + $row;
186                     
187                     continue;
188                 }
189                 if($c == 'CREATION DATE'){
190                    $r[$c] = date('Y-m-d',strtotime(str_replace('/', '-', $n[$k]))); 
191                    continue;
192                 }
193                 if (!isset($n[$k])) {
194                     $this->jerr("Error on line $lnum - missing data in column $c");
195                 }
196                 $r[$c] = $n[$k];
197             }
198             
199             if ($od === false) {
200                 $od = $r['CREATION DATE'];
201             } 
202             if ($od != $r['CREATION DATE']) {
203                 $this->jerr("the file contains orders for multiple days first was $od, found {$r['CREATION DATE']}
204                             - either download again, or remove the extra lines");
205             }
206             
207             if (empty($r['QTY']) || (floor($r['QTY']) != $r['QTY'])) {
208                 $this->jerr("Error on line $lnum - {$r['QTY']} is not a valid quantity");
209             }
210             
211             
212             $row++;
213             $index = $no_split ? 1 : floor($r['ORDER ID'] / 1000000);
214             
215             if($r['PAYMENT METHOD'] == 'creditcard' || $r['PAYMENT METHOD'] == 'free' || $r['PAYMENT METHOD'] == 'secureframe'){
216                 $rows['MGCREDITCARD'][$index][] = $r;
217                 continue;
218                 
219             }
220             
221             if($r['PAYMENT METHOD'] == 'paypal_express'){
222                 $rows['MGPAYPAL'][$index][] = $r;
223                 continue;
224             }
225             if($r['PAYMENT METHOD'] == 'paypal_standard'){
226                 $rows['MGPAYPAL'][$index][] = $r;
227                 continue;
228             }
229             if($r['PAYMENT METHOD'] == 'directdeposit_au'){
230                 $rows['MGDEPOSIT'][$index][] = $r;
231                 continue;
232             }
233             $this->jerr("invalid payment type: {$r['PAYMENT METHOD']} on   line $lnum");
234             
235         }
236         
237         fclose($fh);
238         
239         if (empty($cols)) {
240             $this->jerr("could not find a row with " . implode(' / ', $req));
241         }
242         
243         $total   = 0.0;
244         $billed = 0.0;
245         
246         foreach($customers as $cid => $cname) {
247             
248             
249             if (empty($rows[$cname])) {
250                 continue;
251             }
252             
253             foreach ($rows[$cname] as $k => $v){
254                 $this->transObj = DB_DataObject::Factory('cohead');
255                 $this->transObj->query('BEGIN');
256                 $this->transObj->lockTables();
257                 list( $ltotal, $lbilled)  = $this->createOrder($cid, $cname, $v, ($no_split) ? '' : ($k));
258                 
259                 if (!empty($this->errmsg)) {
260                     $this->jerr(implode("\n", $this->errmsg));
261                 }
262                 
263                 $this->transObj->query('COMMIT');
264                 $this->transObj = false;
265                 
266                 $GLOBALS['_DB_DATAOBJECT']['RESULTS']   = array();
267                 $GLOBALS['_DB_DATAOBJECT']['RESULTFIELDS'] = array();
268                 
269                 
270                 $total += $ltotal;
271                 $billed += $lbilled;
272             }
273             
274         }
275         
276         $msg = empty($this->ok_message) ? 'data imported successfully' : $this->ok_message;
277
278         $this->addEvent('MAGENTO', false, $msg);
279         
280         $this->jok($msg . ' TOTAL: '. number_format($total,2) . ' BILLED: ' .number_format($billed, 2) . ' Time:' . (microtime(true) - $this->timer) . ' seconds' );
281        
282     }
283     
284     function createOrder($cust_id, $cust_name, $rows, $suffix = '')
285     {
286         
287         $this->debugLog("creating order $cust_name - $suffix");
288         $customer = DB_DataObject::Factory('custinfo');
289         $customer->get($cust_id);
290         $location_id = DB_DataObject::Factory('location')->defaultByItemsite()->itemsite_location_id;
291         
292         if(empty($rows)){
293             $this->warning[] = "No products sold for " . $cust_name;
294             return;
295         }
296         
297         $order_date = $rows[0]['CREATION DATE'];
298         
299         $prefix = array(
300             'MGCREDITCARD' => 'MGC',
301             'MGPAYPAL' => 'MGP',
302             'MGDEPOSIT' => 'MGD',
303             
304         );
305         
306         if(!empty($suffix)){
307             static $oldvoid = array();
308             $nox = $prefix[$cust_name] . str_replace('-', '', $order_date);
309             if (!in_array($nox, $oldvoid)) {
310                 $this->debugLog('void the non-x sales order');
311                 
312                 $co = DB_DataObject::factory('cohead');
313                 if($co->get('cohead_number',$nox)){
314                     $this->voidInvAndShipments($co);
315                     $co->void();
316                 }
317                 
318                 $oldvoid[] = $nox;
319             }
320             $suffix = 'x'.$suffix;
321         }
322         
323         $cohead_number = $prefix[$cust_name] . str_replace('-', '', $order_date) . $suffix;
324         
325         $co = DB_DataObject::factory('cohead');
326         
327         if($co->get('cohead_number',$cohead_number)){
328             
329             $this->voidInvAndShipments($co);
330         
331         } else {
332             
333             $this->debugLog('creating new head');
334             // create cntct if not exists
335             $cntct = array(
336                 'cntct_first_name' => $customer->cust_name,
337                 'cust_id'  =>        $cust_id,
338                 'cntct_active'     => 1,
339                 'cntct_name'       => $customer->cust_name
340             );
341             // simple address for customer..
342             $addr = array(
343                 'addr_active' => 1,
344                 'addr_line1'  => 'Address for ' . $customer->cust_name . ' account'
345             );
346             $cn = $this->checkcntctAndaddr($cntct, $addr);
347
348             if(!$cn->cntct_id){
349                 $this->jerr('error occur on getting the contact of ' . $customer->cust_name);
350             }
351             $sr = $this->authUser->salesrep();
352             
353             $co = DB_DataObject::factory('cohead');
354
355             $co->setFrom(array(
356                 'cohead_cust_id'           => $cust_id,
357                 'cohead_number'            => $cohead_number,
358                 'cohead_cust_id_cust_name' => $cust_name,
359                 'cohead_orderdate'         => $order_date,
360                 'cohead_targetdate'        => $order_date,
361                 'cohead_location_src'      => $location_id,
362                 'cohead_terms_id'          => $customer->cust_terms_id,
363                 'cohead_salesrep_id'       => empty($sr->salesrep_id) ? $customer->cust_salesrep_id : $sr->salesrep_id,
364                 'cohead_billto_cntct_id'   => $cn->pid(),
365                 'cohead_shipto_cntct_id'   => $cn->pid(),
366                 'cohead_curr_id'           => $customer->cust_curr_id,
367                 'cohead_taxzone_id'        => $customer->cust_taxzone_id
368                 
369             ));
370
371             foreach($co->defaults() as $k=>$v) {
372                 if (!isset($co->$k)) {
373                     $co->$k = $v;
374                 }
375             }
376
377             $co->insert();
378             $oldco = clone($co);
379             $co->updateAddress();
380             $co->fixMisc();
381             $co->update($oldco);
382             
383         }
384         
385         $this->debugLog('adding lines');
386         
387         $total = 0.0;
388         $delivery = 0.0;
389         $billitems = array();
390         $invoice_total = 0.0;
391         $toShipment = array();
392         $gift = 0.0;
393         
394         $this->debugLog("number of items " . count($rows));
395        
396         foreach ($rows  as $r){
397             
398             // do we have the itme??
399             $i = DB_DataObject::factory('item')->lookupSKU($r['SKU']);
400             if (!$i) {
401                 $this->errmsg[] = $r['SKU'] . ' not found';
402                 continue;
403             }
404             
405             // delete the old line numbers.. AGHH !!! = this has been destroying data!!! (it did not have coitem_cohead_id before..)
406             $coitem = DB_DataObject::factory('coitem');
407             $coitem->coitem_cohead_id = $co->pid();
408             
409             if($coitem->get('coitem_linenumber', $r['ORDER ID'])){ // coitem not exist
410                $coitem->delete();    
411             }
412             
413             $coitem = DB_DataObject::factory('coitem');
414             // create the coitem
415             
416             $itemsite = $i->itemsite();
417             if (!$itemsite) {
418                 $this->jerr("product {$i->item_number} has not been created correctly - missing itemsite");
419             }
420             
421             $coitem_custprice = round(($r['UNIT PRICE']) * (10 / 11) ,3); // take out the tax
422             
423             // grand total = unit price + discount + shipping -customer balance - gift card
424             
425             $discount_rate = round((abs(
426                                     $r['DISCOUNT']) /
427                                     ($r['GRAND TOTAL'] - $r['SHIPPING'] - $r['DISCOUNT'] +
428                                             $r['CUSTOMER BALANCE'] + $r['GIFT CARD'])
429                                 ), 3); // discount rate
430             
431             $coitem_price = round(($coitem_custprice * (1 - $discount_rate)), 3);
432             
433              
434             $coitem->setFrom(array(
435                 'coitem_cohead_id'    => $co->pid(),
436                 'coitem_linenumber'   => $r['ORDER ID'],
437                 'coitem_itemsite_id'  => $itemsite->pid(),
438                 'coitem_qtyord'       => $r['QTY'],
439                 'coitem_price'        => $coitem_price,
440                 'coitem_custprice'    => $coitem_custprice, 
441                 'coitem_qtyshipped'   => 0,
442                 'coitem_location_src' => $co->cohead_location_src,
443                 'coitem_shipto_id'    => $co->cohead_shipto_id, // $shipto, 
444                 'coitem_scheddate'    => $r['CREATION DATE']
445             ));
446             foreach($coitem->defaults() as $k=>$v) {
447                 if (empty($coitem->$k)) {
448                     $coitem->$k = $v;
449                 }
450             }
451             
452             $coitem->insert();
453             
454             if(!$coitem->coitem_id){
455                 $this->errmsg[] = $r['SKU'] . ' error occur on insert';
456                 continue;
457             }
458             
459             $toShipment[$coitem->pid()] = $coitem;
460             
461             if(substr($r['ORDER ID'],-4,4) == 1){ 
462                 
463                 $total +=  ($r['GRAND TOTAL'] + $r['CUSTOMER BALANCE'] + $r['GIFT CARD']) ; // with tax
464                 
465 //                if ( $r['PAYMENT METHOD'] == 'free' ) {
466 //                    $r['SHIPPING']  = 0.0;
467 //                }
468                 
469                 $delivery += round(($r['SHIPPING'] * (10 / 11)), 3); // without tax
470                 
471                 $gift += round((($r['CUSTOMER BALANCE'] + $r['GIFT CARD']) * (10 / 11)), 3); // without tax
472             }
473             
474             $x = array(
475                 'cobill_coitem_id'  => $coitem->pid(),
476                 'cobill_qty'        => $coitem->coitem_qtyord
477             );
478             
479             $billitems[] = (object)$x;
480             
481             $invoice_total += round($coitem->coitem_qtyord * $coitem->coitem_price, 3);
482             
483             
484             
485         }
486         
487         if (!empty($this->errmsg)) {
488             return false;
489         }
490         
491         // last row - create shipment...
492         
493         if(count($toShipment)){
494             $d = array(
495                 'curr'    => $co->cohead_curr_id
496             );
497             $this->orderShipments($toShipment,$d);
498             
499         }
500         
501         $this->debugLog('sorting out discounts');
502         
503         $coitem = DB_DataObject::factory('coitem');
504         $coitem->get('coitem_cohead_id', $co->pid());
505         if($coitem->find(true)){
506             $coitem->updatePretaxDiscount($this); 
507         }
508         
509         if ($delivery > 0) {
510             $this->debugLog('sorting out delivery');
511             
512             $i = dB_DataObject::Factory('item');
513             if (!$i->get('item_number', 'Z-DELIVERY CHARGE')) { 
514                 $this->jerr("delivery charge not found");
515             }
516             $itemsite = $i->itemsite();
517             
518             // add z-Delivery Charge coz it's taxable
519             $coitem = DB_DataObject::factory('coitem');
520             $coitem->coitem_cohead_id = $co->pid();
521             $coitem->coitem_itemsite_id = $itemsite->pid();
522             $coitem->coitem_linenumber = 9999998;
523             if (!$coitem->find(true)) {
524             
525                     $coitem->setFrom(array(
526                         'coitem_cohead_id'    => $co->pid(),
527                         'coitem_linenumber'   => 9999998, // need a line number..
528                         'coitem_itemsite_id'  => $coitem->coitem_itemsite_id,
529                         'coitem_qtyord'       => 1,
530                         'coitem_price'        => round($delivery,3),
531                         'coitem_custprice'    => round($delivery,3),
532                         'coitem_qtyshipped'   => 0,
533                         'coitem_location_src' => $co->cohead_location_src,
534                         'coitem_shipto_id'    => $co->cohead_shipto_id, // $shipto, 
535                         'coitem_scheddate'    => $order_date
536                     ));
537                 
538                 foreach($coitem->defaults() as $k=>$v) {
539                     if (empty($coitem->$k)) {
540                         $coitem->$k = $v;
541                     }
542                 }
543                 $coitem->insert();
544             } else {
545                 $co_old = clone($coitem);
546                 $coitem->setFrom(array(
547                     'coitem_price'        => round($delivery,3),
548                     'coitem_custprice'    => round($delivery,3),
549                     'coitem_location_src' => $co->cohead_location_src,
550                     'coitem_shipto_id'    => $co->cohead_shipto_id, // $shipto, 
551                     'coitem_scheddate'    => $order_date
552                 ));
553                 $coitem->update($co_old);
554                 
555                 
556             }
557             // add freigth total to invoice..
558             $invoice_total +=  round($delivery,3) ;
559             
560             $x = array(
561                 'cobill_coitem_id'  => $coitem->pid(),
562                 'cobill_qty'        => $coitem->coitem_qtyord
563             );
564             
565             $billitems[] = (object)$x;
566             
567             
568         }
569        
570         
571         $i = DB_DataObject::Factory('item');
572         if (!$i->get('item_number', 'Z-LIST-DISCOUNT')) { 
573             $this->jerr("Z-LIST-DISCOUNT not found");
574         }
575         $itemsite = $i->itemsite();
576         
577         $coitem = DB_DataObject::factory('coitem');
578         $coitem->coitem_cohead_id = $co->pid();
579         $coitem->coitem_itemsite_id = $itemsite->pid();
580         if($coitem->find(true)){
581             $x = array(
582                 'cobill_coitem_id'  => $coitem->pid(),
583                 'cobill_qty'        => $coitem->coitem_qtyord
584             );
585             
586             $billitems[] = (object)$x;
587             $invoice_total = $invoice_total + round(($coitem->coitem_qtyord * $coitem->coitem_price), 3);
588             
589             $co_old = clone ($co);
590             $co->setFrom(array(
591                 'cohead_misc' => $coitem->coitem_qtyord * $coitem->coitem_price * -1,
592                 'cohead_misc_descript' => 'DISCOUNT'
593             ));
594             $co->update($co_old);
595         }
596         
597         
598         $cobapply_list = array();
599         
600         if($gift > 0){ // check credit memo
601             
602             $cmhead = DB_DataObject::factory('cmhead');
603             $cmhead->setFrom(array(
604                 'cmhead_number'          => $cmhead->nextNumber(),
605                 'cmhead_cust_id'         => $co->cohead_cust_id,
606                 'cmhead_billto_cntct_id' => $co->cohead_billto_cntct_id,
607                 'cmhead_taxzone_id'      => $co->cohead_taxzone_id,
608                 'cmhead_curr_id'         => $co->cohead_curr_id,
609                 'cmhead_salesrep_id'     => $co->cohead_salesrep_id,
610                 'cmhead_docdate'         => $co->cohead_targetdate,
611                 'cmhead_location_id'     => $co->cohead_location_src
612             ));
613             
614             foreach($cmhead->defaults() as $k=>$v) {
615                 if (empty($cmhead->$k)) {
616                     $cmhead->$k = $v;
617                 }
618             }
619             
620             $cmhead->insert();
621             
622             if(!$cmhead->pid()){
623                 $this->jerr('error occur on insert a credit memo');
624             }
625             
626             $i = dB_DataObject::Factory('item');
627             if (!$i->get('item_number', 'Z-DISCOUNT-VOUCHER')) { 
628                 $this->jerr("Z-DISCOUNT-VOUCHER not found");
629             }
630             $itemsite = $i->itemsite();
631             
632             $cmitem = DB_DataObject::factory('cmitem');
633             $cmitem->setFrom(array(
634                 'cmitem_cmhead_id' => $cmhead->pid(),
635                 'cmitem_linenumber' => 999997,
636                 'cmitem_itemsite_id' => $itemsite->pid(),
637                 'cmitem_qtycredit' => 1,
638                 'cmitem_qtyreturned' => 1,
639                 'cmitem_unitprice' => $gift,
640                 'cmitem_taxtype_id' => $cmitem->sqlValue("gettaxtypeid('Taxable'::text)"),
641                 'cmitem_comments' => $i->item_descrip1,
642             ));
643             
644             foreach($cmitem->defaults() as $k=>$v) {
645                 if (empty($cmitem->$k)) {
646                     $cmitem->$k = $v;
647                 }
648             }
649             $cmitem->insert();
650             
651             if(!$cmitem->pid()){
652                 $this->jerr('error occur on insert Z-DISCOUNT-VOUCHER to credit memo');
653             }
654             
655             $cmhead->post($this);
656             
657             $aropen = DB_DataObject::factory('aropen');
658             $aropen->aropen_cust_id = $customer->pid();
659             $aropen->aropen_doctype = 'C';
660             $aropen->aropen_docnumber = $cmhead->cmhead_number;
661             $cobapply_list = $aropen->fetchAll('aropen_id');
662             if(count($cobapply_list) != 1){
663                 $this->jerr('error occur on getting cmhead aropen');
664             }
665              
666         }
667         
668         $this->debugLog('creating bill');
669         
670         // create the invoice for each magento order
671         $cobmisc = DB_DataObject::factory('cobmisc');
672         
673         $cobmisc->setFrom(array(
674             'cobmisc_cohead_id' => $co->pid(),
675             'cobmisc_invcdate'  => $order_date,
676             'cobmisc_shipdate'  => $order_date
677         ));
678         
679         $cobmisc->cobmisc_taxtype_id = $cobmisc->sqlValue("gettaxtypeid('Taxable'::text)");
680         $cobmisc->fixMisc();
681         
682         $t = $cobmisc->factory('cobmisc');
683         $t->query("SELECT createBillingHeader({$co->pid()}) AS cobmisc_id");
684         $t->fetch();
685         
686         $cobmisc->cobmisc_id = $t->cobmisc_id;
687         $cobmisc->updateItems($billitems);
688         
689         // apply the credit memo..
690         if (!empty($cobapply_list)) {
691            $cobmisc->updateCobApply($this,$cobapply_list);
692         }
693         
694         // post the bill.
695         
696         $t = $cobmisc->factory('cobmisc');
697         $t->get($cobmisc->cobmisc_id);
698         $t->post($this);
699         
700         // fetch again so it should have invoice..
701         $t = $cobmisc->factory('cobmisc');
702         $t->get($cobmisc->cobmisc_id);
703         
704         $invoice = $t->invchead();
705         
706         $aropen = $invoice->aropen();
707         
708         return array( $total, $aropen->aropen_amount);
709         
710     }
711     
712     function checkcntctAndaddr($cntct,$addrs)
713     {
714         $cn = DB_DataObject::factory('cntct');
715
716         if(!$cn->get('cntct_first_name', $cntct['cntct_first_name'])){ // contact not exists
717             $cn->setFrom($cntct);
718             $cn->cntct_crmacct_id = $cn->sqlValue("(SELECT crmacct_id FROM crmacct WHERE crmacct_cust_id = {$cntct['cust_id']})");
719             $cn->genNumber();
720             $cn->insert();
721         }
722
723         if(!$cn->cntct_addr_id){ // addr not exists
724             $addr = DB_DataObject::Factory('addr');
725             $addr->setFrom($addrs);
726             $addr->genNumber();
727             $addr->insert();
728
729             $oldcn = clone($cn);
730             $cn->cntct_addr_id = $addr->pid();
731             $cn->update($oldcn);
732
733         }
734         
735         return $cn;
736     }
737     
738     function checkshiptoinfo($customer, $cntct)
739     {
740         $sh = DB_DataObject::Factory('shiptoinfo');
741         $sh->shipto_cntct_id = $cntct->pid();
742         $sh->shipto_addr_id = $cntct->cntct_addr_id;
743         if ($sh->find(true)) {
744             return $sh->pid();
745         }
746         
747         $sh->setFrom(array(
748             'shipto_cust_id' => $cust_id,
749             'shipto_name' => $cntct->cntct_name,
750             'shipto_salesrep_id'=> $customer->cust_salesrep_id,
751             'shipto_active' => true,
752             'shipto_adefault' => false,
753             'shipto_shipchrg_id' => $customer->cust_shipchrg_id,
754             'shipto_taxzone_id' => $customer->cust_taxzone_id,
755             'shipto_shipform_id' => $customer->cust_shipform_id,
756             'shipto_commission' => 0,
757             'shipto_shipzone_id' => $customer->cust_taxzone_id
758
759         ));
760         $sh->genNum();
761         $sh->insert();
762         
763         return $sh->pid();
764         
765     }
766     
767     function orderShipments($toShipments,$d)
768     {
769         $this->debugLog('creating shipments');
770         
771         $ids = array_keys($toShipments);
772         $c = array_pop($toShipments);
773         
774         $cc = DB_DataObject::factory('coitem');
775         $cc->coitem_cohead_id = $c->coitem_cohead_id;
776         $cc->find();
777         
778         $x = array();
779         $shipitems = array();
780         while ($cc->fetch()){ // this query will take about 6 secs...
781             
782             $itemsite = $cc->itemsite();
783             // skip non-stock items..
784             if (!$itemsite->itemsite_stocked) {
785                 continue;
786             }
787             
788             $x['shipitem_orderitem_id'] = $cc->pid();
789             $x['shipitem_qty'] = 0;
790             if(in_array($cc->pid(), $ids)){
791                 $x['shipitem_qty'] = $cc->coitem_qtyord;
792             }
793             $shipitems[] = (object)$x;
794         }
795         
796         $sh = DB_DataObject::factory('shiphead');
797         
798         
799         
800         $sh->setFrom(array(
801             'shiphead_shipdate'        => $c->coitem_scheddate,
802             'shiphead_order_id'        => $c->coitem_cohead_id,
803             'shiphead_sfstatus'        => 'N',
804             'shiphead_location_id'     => $c->coitem_location_src,
805             'shiphead_shipto_id'       => $c->coitem_shipto_id,
806             //'shiphead_number'          => $cohead->cohead_number . substr($c->coitem_linenumber, 0, 4),
807             'shiphead_order_type'      => 'SO',
808             'shiphead_freight'         => 0, //$d['freight'],
809             'shiphead_freight_curr_id' => $d['curr'],
810             'shiphead_notes'           => '' // $r['SHIP NOTE']
811         ));
812         $sh->beforeInsert(array('shiphead_number' => 'Automatic'),$this);
813         //$this->jerr("about to create shipment: " . $sh->shiphead_number);
814         
815         $sh->insert();
816         
817         $sh->updateItems($shipitems, $this); 
818         
819         $sh->confirm($this); 
820     }
821     
822     function voidInvAndShipments($co)
823     {
824         $this->debugLog('deelting old invoices / shipments');
825         $invoices  = $co->cobmiscs();
826         
827         foreach($invoices as $i) {
828             $i->void($this, true);
829         }
830
831         // do it twice..
832         $invoices  = $co->cobmiscs();
833         foreach($invoices as $i) {
834             $i->void($this,true);
835         }
836         // delete the shipments...
837         $shipheads = $co->shipheads();
838
839         foreach($shipheads  as $s) {
840
841             if (!empty($s->shiphead_shipped) && !empty($s->shiphead_shipdate)) {
842                 $res = $s->unconfirm($this,true);
843
844                 if ($res !== true) {
845                     $this->jerr("ship unconfirm failed:" . $res);
846                 }
847             }
848
849             if (!empty($s->shiphead_shipdate)) { // 395.43042492867 secs...
850                 $res = $s->void($this,true);    // void shipitem will take 0.1 sec for each... a little bit long time...
851
852                 if ($res !== true) {
853                     $this->jerr("ship voiding failed" . $res)  ;
854                 }
855             }
856         }
857     }
858     //B_45 not found
859     //B_12 not found
860     //B_1 not found
861     //B_11 not found
862     
863     // 210203 not found
864     // 212103 not found
865     // Gift Wrapping not found
866     // Gift Wrapping not found
867     // 212204 not found
868     // Gift Wrapping not found
869     
870     
871 }