ffb74bdefd834fb1c43979fcfcf5118e1e1b4343
[Pman.Xtuple] / DataObjects / Cmhead.php
1 <?php
2 /**
3  * Table Definition for cmhead
4  */
5 require_once 'DB/DataObject.php';
6
7 class Pman_Xtuple_DataObjects_Cmhead extends DB_DataObject 
8 {
9     ###START_AUTOCODE
10     /* the code below is auto generated do not remove the above tag */
11
12     public $__table = 'cmhead';              // table name
13     public $cmhead_id;                       // int4(4)  not_null default_nextval%28%28cmhead_cmhead_id_seq%29%3A%3Aregclass%29 primary_key
14     public $cmhead_number;                   // text(-1)  
15     public $cmhead_posted;                   // bool(1)  
16     public $cmhead_invcnumber;               // text(-1)  
17     public $cmhead_custponumber;             // text(-1)  
18     public $cmhead_cust_id;                  // int4(4)  
19     public $cmhead_docdate;                  // date(4)  
20     public $cmhead_shipto_id;                // int4(4)  
21     public $cmhead_shipto_name;              // text(-1)  
22     public $cmhead_shipto_address1;          // text(-1)  
23     public $cmhead_shipto_address2;          // text(-1)  
24     public $cmhead_shipto_address3;          // text(-1)  
25     public $cmhead_shipto_city;              // text(-1)  
26     public $cmhead_shipto_state;             // text(-1)  
27     public $cmhead_shipto_zipcode;           // text(-1)  
28     public $cmhead_salesrep_id;              // int4(4)  
29     public $cmhead_freight;                  // numeric(-1)  
30     public $cmhead_misc;                     // numeric(-1)  
31     public $cmhead_comments;                 // text(-1)  
32     public $cmhead_printed;                  // bool(1)  
33     public $cmhead_billtoname;               // text(-1)  
34     public $cmhead_billtoaddress1;           // text(-1)  
35     public $cmhead_billtoaddress2;           // text(-1)  
36     public $cmhead_billtoaddress3;           // text(-1)  
37     public $cmhead_billtocity;               // text(-1)  
38     public $cmhead_billtostate;              // text(-1)  
39     public $cmhead_billtozip;                // text(-1)  
40     public $cmhead_hold;                     // bool(1)  
41     public $cmhead_commission;               // numeric(-1)  
42     public $cmhead_misc_accnt_id;            // int4(4)  
43     public $cmhead_misc_descrip;             // text(-1)  
44     public $cmhead_rsncode_id;               // int4(4)  
45     public $cmhead_curr_id;                  // int4(4)  default_basecurrid%28%29
46     public $cmhead_freighttaxtype_id;        // int4(4)  
47     public $cmhead_gldistdate;               // date(4)  
48     public $cmhead_billtocountry;            // text(-1)  
49     public $cmhead_shipto_country;           // text(-1)  
50     public $cmhead_rahead_id;                // int4(4)  
51     public $cmhead_taxzone_id;               // int4(4)  
52     public $cmhead_prj_id;                   // int4(4)  
53     public $cmhead_billto_cntct_id;          // int4(4)
54     public $cmhead_billto_addr_id;          // int4(4)
55     public $cmhead_location_id;  // extra...
56     
57     
58    /**
59     * Getter / Setter for $cmhead_freighttaxtype_id
60     *
61     * @param    mixed   (optional) value to assign
62     * @access   public
63     */
64     public function freighttaxtype() {
65         return func_num_args() ? $this->link('cmhead_freighttaxtype_id', func_get_arg(0)) : $this->link('cmhead_freighttaxtype_id');
66     }
67
68    /**
69     * Getter / Setter for $cmhead_prj_id
70     *
71     * @param    mixed   (optional) value to assign
72     * @access   public
73     */
74     public function prj() {
75         return func_num_args() ? $this->link('cmhead_prj_id', func_get_arg(0)) : $this->link('cmhead_prj_id');
76     }
77
78    /**
79     * Getter / Setter for $cmhead_taxzone_id
80     *
81     * @param    mixed   (optional) value to assign
82     * @access   public
83     */
84     public function taxzone() {
85         return func_num_args() ? $this->link('cmhead_taxzone_id', func_get_arg(0)) : $this->link('cmhead_taxzone_id');
86     }
87
88    /**
89     * Getter / Setter for $cmhead_curr_id
90     *
91     * @param    mixed   (optional) value to assign
92     * @access   public
93     */
94     public function curr() {
95         return func_num_args() ? $this->link('cmhead_curr_id', func_get_arg(0)) : $this->link('cmhead_curr_id');
96     }
97     
98     /**
99     * Getter / Setter for $cmhead_billto_cntct_id
100     *
101     * @param    mixed   (optional) value to assign
102     * @access   public
103     */
104     public function billto_cntct() {
105         return func_num_args() ? $this->link('cmhead_billto_cntct_id', func_get_arg(0)) : $this->link('cmhead_billto_cntct_id');
106     }
107     
108     /**
109     * Getter / Setter for $cohead_salesrep_id
110     *
111     * @param    mixed   (optional) value to assign
112     * @access   public
113     */
114     public function salesrep() {
115         return func_num_args() ? $this->link('cmhead_salesrep_id', func_get_arg(0)) : $this->link('cmhead_salesrep_id');
116     }
117     
118     /* the code above is auto generated do not remove the tag below */
119     ###END_AUTOCODE
120     
121     function defaults() {
122         
123         $sa =  DB_DataObject::Factory('salesaccnt');
124         $sa->salesaccnt_custtype ='.*';
125         $sa->salesaccnt_prodcat = '.*';
126         $sa->find(true);
127           
128         
129         return array(
130             'cmhead_printed'=>true,
131             'cmhead_rsncode_id'=> $this->sqlValue('NULL'),
132             'cmhead_posted'=>  false,
133             'cmhead_custponumber' => '',
134             'cmhead_freight' => 0.0,
135             'cmhead_misc' => 0.0,
136             'cmhead_hold' => false,
137             'cmhead_commission' => 0.0,
138             'cmhead_misc_accnt_id' =>  $sa->salesaccnt_credit_accnt_id,
139             'cmhead_misc_descrip' => '',
140             'cmhead_freighttaxtype_id' => $this->sqlValue('NULL'),
141             'cmhead_rahead_id' => $this->sqlValue('NULL'),
142             'cmhead_prj_id'=> $this->sqlValue('NULL'),
143         );
144         
145         //public $cmhead_invcnumber;               // text(-1)  
146         //public $cmhead_cust_id;                  // int4(4)  
147         //public $cmhead_docdate;                  // date(4)  
148         //public $cmhead_shipto_id;                // int4(4)  
149         //public $cmhead_salesrep_id;              // int4(4)  
150         //public $cmhead_freight;                  // numeric(-1)  
151         //public $cmhead_misc;                     // numeric(-1)  
152         //public $cmhead_comments;                 // text(-1)  
153         //public $cmhead_curr_id;                  // int4(4)  default_basecurrid%28%29
154         //public $cmhead_taxzone_id;               // int4(4)  
155         
156         //public $cmhead_billto_cntct_id;          // int4(4)
157         //public $cmhead_billto_addr_id;          // int4(4)
158         //public $cmhead_location_id;  // extra...
159             
160         
161     }
162     
163     
164     function applyFilters($q, $au, $roo)
165     {
166         //join the customer table
167         //DB_DataObject::debugLevel(1);
168         $tn=  $this->tableName();
169         
170         //$ci = DB_DataObject::Factory('custinfo');
171         //$this->selectAs($ci, 'cmhead_cust_id_%s');
172         //$this->_join .= " LEFT JOIN custinfo ON cmhead_cust_id=custinfo.cmhead_cust_id ";
173         
174         //join the value from cmitem table as cmhead_value
175         $this->selectAdd("
176             CASE WHEN
177                 cmhead_taxzone_id != gettaxzoneid('NO TAX')
178             THEN
179                 (SELECT SUM(cmitem_unitprice * cmitem_qtyreturned + 
180                             calculatetax(
181                                 cmhead_taxzone_id,
182                                 cmitem_taxtype_id,
183                                 cmhead_docdate,
184                                 cmhead_curr_id,
185                                 cmitem_unitprice * cmitem_qtyreturned
186                             )) 
187                  FROM 
188                     cmitem 
189                  WHERE 
190                     cmitem_cmhead_id = cmhead.cmhead_id
191                 ) 
192             ELSE
193                 (SELECT 
194                     SUM(cmitem_unitprice * cmitem_qtyreturned) 
195                  FROM 
196                     cmitem 
197                  WHERE 
198                     cmitem_cmhead_id = cmhead.cmhead_id
199                 ) 
200             END AS cmhead_value
201         "); 
202         
203         // tax...
204         $this->selectAdd("
205             CASE WHEN
206                 cmhead_taxzone_id != gettaxzoneid('NO TAX')
207             THEN
208                 (
209                     select COALESCE( sum(
210                         calculatetax(
211                             cmhead_taxzone_id,
212                             cmitem_taxtype_id,
213                             cmhead_docdate,
214                             cmhead_curr_id,
215                             cmitem_unitprice * cmitem_qtyreturned
216                         )
217                     ), 0.0)
218                         from 
219                             cmitem 
220                         where 
221                             cmitem_cmhead_id = cmhead.cmhead_id
222                             AND
223                             cmitem_taxtype_id = gettaxtypeid('Taxable')
224                 )
225                 ELSE
226                     0.0
227                 END as cmhead_tax_value,
228             
229                 CASE WHEN
230                     cmhead_taxzone_id != gettaxzoneid('NO TAX')
231                 THEN
232                     (
233                         select COALESCE( sum(
234                             cmitem_unitprice * cmitem_qtyreturned
235                           
236                         ), 0,0)
237                             from 
238                                 cmitem 
239                             where 
240                                 cmitem_cmhead_id = cmhead.cmhead_id
241                                 AND
242                                 cmitem_taxtype_id = gettaxtypeid('Taxable')
243                     )
244                 ELSE
245                     0.0
246                 END as cmhead_taxable_value,
247                 
248                 
249                 CASE WHEN
250                     cmhead_taxzone_id != gettaxzoneid('NO TAX')
251                 THEN
252                     (
253                         select COALESCE( sum(
254                             cmitem_unitprice * cmitem_qtyreturned
255                           
256                         ), 0,0)
257                             from 
258                                 cmitem 
259                             where 
260                                 cmitem_cmhead_id = cmhead.cmhead_id
261                                 AND
262                                 cmitem_taxtype_id != gettaxtypeid('Taxable')
263                     )
264                 ELSE
265                     0.0
266                 END as cmhead_taxfree_value
267             "); 
268         
269         
270         $this->selectAdd("gettaxtypeid('Taxable') AS default_taxtype_id");
271         
272         //join the bill contact and address
273         
274         $cntct = DB_DataObject::factory('cntct');
275         $this->_join .= '
276             LEFT JOIN cntct AS billcntct ON ( cmhead_billto_cntct_id = billcntct.cntct_id)
277         ';
278         $this->selectAs($cntct, 'cmhead_billto_cntct_id_%s', 'billcntct');
279         
280         $addr = DB_DataObject::Factory('addr');
281         $this->_join .= '
282             LEFT JOIN addr AS billaddr ON ( cmhead_billto_addr_id = billaddr.addr_id)
283         ';
284         $this->selectAs($addr, 'cmhead_billto_cntct_id_cntct_addr_id_%s', 'billaddr');
285         
286         
287         //get the location name
288         // this is not used?
289         /*$loc = DB_DataObject::factory('location');
290         $loc->selectAdd("
291             distinct(cmhead_location_id) as cmhead_location_id,
292             (SELECT location_name from location where location_id = cmhead_location_id) as cmhead_location_name
293             ");
294         */
295         
296         
297         $tax = DB_DataObject::factory('taxzone');
298         $d = date('Y-m-d');
299         //error_log($d);
300         $this->selectAdd("
301             COALESCE( (SELECT taxrate_percent FROM taxrate WHERE taxrate_tax_id IN 
302                 (SELECT taxass_tax_id FROM taxass WHERE
303                     taxass_taxzone_id = cmhead.cmhead_taxzone_id
304                     AND taxrate_effective < '$d' AND taxrate_expires > '$d'
305                 )
306             ), 0) as taxzone_rate
307         ");
308         
309         $this->selectAdd("
310              COALESCE(
311                 (SELECT aropen_amount - aropen_paid FROM
312                         aropen
313                     WHERE
314                             aropen_doctype ='C'
315                         AND
316                             aropen_ordernumber = cmhead.cmhead_number
317                         LIMIT 1
318                 ), 0
319             ) as cmhead_unpaid
320         ");
321         
322         
323         if (!empty($q['query']['cmhead_number'])) {
324             //DB_DataObject::DebugLevel(1);
325             $this->whereAdd("{$tn}.cmhead_number ilike '" . $this->escape($q['query']['cmhead_number']) . "%'");
326             
327
328         }
329         $this->joinAddCustSalesRep();
330         
331         if (!empty($q['query']['status']))
332         {
333             $ap = "(SELECT aropen_open FROM aropen WHERE aropen_doctype ='C' and aropen_ordernumber = cmhead.cmhead_number LIMIT 1)";
334            //DB_DataObject::DebugLevel(1);
335             // if it's been used..
336             switch($q['query']['status']) {
337                 case   'NOTCLOSED' :
338                     $this->whereAdd("
339                         {$tn}.cmhead_posted = false OR
340                         {$ap}
341                     ");
342                     break;
343                     
344                     
345                 case 'CLOSED' :
346                     $this->whereAdd("
347                         {$tn}.cmhead_posted = true AND
348                         {$ap} = false
349                     ");
350                     break;
351                 
352                 case 'UNPOSTED':
353                     $this->cmhead_posted = false;
354                     break;
355                 
356                 case 'UNUSED':
357                     $this->whereAdd("
358                         {$tn}.cmhead_posted = true
359                         AND
360                         {$ap}
361                     ");
362                     break;
363                 
364                 case 'VOIDED':
365                     $this->whereAdd(" NOT  {$ap} ");
366                     break;
367                 
368                  case 'NOTVOIDED':
369                     $this->whereAdd($ap);
370                     break;
371                 
372                 
373             }
374         }
375         
376         if(isset($q['_with_aropen'])){
377             $this->joinAddAropen();
378             
379             $this->selectAdd("
380                 (join_cmhead_aropen_id.aropen_amount - join_cmhead_aropen_id.aropen_paid - 
381                 (SELECT 
382                     COALESCE(SUM(checkhead_amount),0)  
383                 FROM 
384                     checkhead,checkitem  
385                 WHERE 
386                     ((checkhead_id=checkitem_checkhead_id)  
387                 AND 
388                     (NOT checkhead_posted)
389                 AND 
390                     (NOT checkhead_void)  
391                 AND 
392                     (checkitem_aropen_id=aropen_id)))
393                 ) AS checkhead_total
394             ");
395         }
396         
397     }
398     
399     
400     function joinAddCustSalesRep()
401     {
402         $this->_join .= '
403              LEFT JOIN salesrep AS join_cust_salesrep_id_salesrep_id
404                 ON ( join_cust_salesrep_id_salesrep_id.salesrep_id = join_cmhead_cust_id_cust_id.cust_salesrep_id)
405         ';
406         $this->selectAs(DB_DataObject::Factory('salesrep'), 'cust_salesrep_%s', 'join_cust_salesrep_id_salesrep_id');
407         
408         
409     }
410     
411     function beforeUpdate($old, $q,$roo){
412         
413       
414         $this->contact2bill($q);
415         if (isset($q['cmhead_posted']) && $q['cmhead_posted'] == 'false') {
416             $this->cmhead_posted = false;
417         }
418         if (!empty($q['_post'])) {
419             $this->post($roo); // should only return if it succeeds.
420             $roo->jok($this->pid());
421         }
422         if (!empty($q['_void'])) {
423             $this->void($roo); // should only return if it succeeds.
424             $roo->jok("VOIDED");
425         }
426         if (empty($this->cmhead_misc_accnt_id)) {
427             
428             
429             $sa =  DB_DataObject::Factory('salesaccnt');
430             $sa->salesaccnt_custtype ='.*';
431             $sa->salesaccnt_prodcat = '.*';
432             $sa->find(true);
433             $this->cmhead_misc_accnt_id = $sa->salesaccnt_credit_accnt_id;
434         }
435         
436     }
437     
438     function beforeInsert($request,$roo)
439     {
440         if(isset($request['_fix_stock'])){
441             $cmhead = DB_DataObject::factory('cmhead');
442             $cmhead->query("SELECT invfifo_apply_gl_cmhead_fix_stock()");
443             
444             $roo->jok("FIXED");
445         }
446         
447         if (isset($request['_is_xfer'])) {
448             $this->recieveXfer($roo, $request);
449             $this->jerr("no ok");
450         }
451         
452         // handle automatic numbering..
453         if ($this->cmhead_number == 'Automatic' || empty($this->cmhead_number)) {
454             $this->cmhead_number = $this->nextNumber();
455         }
456         $this->cmhead_posted = false;
457         $this->contact2bill($request);
458     }
459     
460     function beforeDelete()
461     {
462         $cmitem = DB_DataObject::factory('cmitem');
463         $cmitem->whereAdd("
464             cmitem_cmhead_id = {$this->pid()}
465         ");
466         $cmitem->delete(DB_DATAOBJECT_WHEREADD_ONLY);
467     }
468
469     function items($what=false)
470     {
471         $i = $this->factory('cmitem');
472         $i->cmitem_cmhead_id = $this->cmhead_id;
473         
474         //$i->orderBy('cmitem_linenumber ASC');
475         return $i->fetchAll($what);
476         
477     }
478      function relatedWhere()
479     {
480         return  array(
481             'cmitem' => $this->items('cmitem_id'),
482         );
483         
484         
485         
486         
487     }
488     
489     
490     
491     function contact2bill($request){
492         
493         $bill = $this->billto_cntct();
494         //print_r($bill);exit;
495         
496         if ($bill->cntct_id) {
497             $this->setFrom($bill->toArray('cmhead_billto_%s'));
498             $this->cmhead_billto_cntct_id = $bill->cntct_id;
499             
500             
501             $addr = $bill->addr();
502             //print_r($addr);exit;
503             $this->cmhead_billto_addr_id = $addr->addr_id;
504             $this->setFrom(array(
505                 'cmhead_billtoname' =>       $bill->cntct_name,
506                 'cmhead_billtoaddress1' =>   $addr->addr_line1,
507                 'cmhead_billtoaddress2' =>   $addr->addr_line2,
508                 'cmhead_billtoaddress3' =>   $addr->addr_line3,
509                 'cmhead_billtocity' =>       $addr->addr_city,
510                 'cmhead_billtostate' =>      $addr->addr_state,
511                 'cmhead_billtozipcode' =>    $addr->addr_postalcode,
512                 'cmhead_billtocountry'  =>   $addr->addr_country,
513             ));
514         }
515     }
516     
517     function toRooArray($req)
518     {
519         
520         $ret = $this->toArray();
521         // seaching for order id's does not include id..
522         if (!$this->cmhead_id) {
523             return $ret;
524         }
525         
526         $l = $this->factory('cmhead');
527         $l->selectAdd();
528         $l->selectAdd("
529               calcsalesordersubtotal(cmhead_id::integer) as cmhead_subtotal,
530               calcsalesordertax(cmhead_id::integer) as cmhead_tax
531         ");
532         $l->get($this->pid());
533         $x = $l->toArray('%s', true);
534         $ret = $ret + $x;
535         return $ret;
536     }
537     
538     function nextNumber()
539     {
540         //DB_DataObject::debugLevel(1);
541         $cp = DB_DataObject::factory('cmhead');
542         $date = substr(date('Y'), -2);
543         
544         $pr = "CM-". strtoupper(substr($this->database(), -2)).$date."-";
545         $cp->whereAdd("cmhead_number LIKE '$pr%'");
546         
547
548         $cp->orderBy('cmhead_number DESC');
549         $cp->limit(1);
550         $res = $cp->fetchAll('cmhead_number');
551         
552         if (empty($res)) {
553             $np = '9999';
554         } else {
555             $last = $res[0];
556             $np = substr($last,strlen($pr)) *1;
557         }
558         
559         return $pr . sprintf('%04d', ($np+1));
560     }
561     
562     function post($roo)
563     {
564         $tn = $this->tableName();
565         // check we are ready to go..
566         if (empty($this->cmhead_location_id)) {
567             $roo->jerr("no location provided");
568         }
569         if (!empty($this->cmhead_posted)) {
570             $roo->jerr("credit memo is already posted");
571         }
572         
573         // we have created a cmhead..
574         $ret = $this->pid();
575         $db = DB_DataObject::factory($tn);
576         $db->query("SELECT postCreditMemo({$ret}, 0) as result");
577         $db->fetch();
578         if (empty($db->result) || $db->result < 0) {
579             $roo->jerr("postCreditMemo failed with result being {$db->result}! " .
580                         print_r($ret,true) );
581         }
582        
583         $itemlocdist_series = $db->result;
584
585         // print_r("\nDEBUG: {$itemlocdist_series} \n");
586
587         $db = DB_DataObject::factory($tn);
588         $db->query("SELECT itemlocdist_id,
589                 itemlocdist_reqlotserial,
590                 itemlocdist_distlotserial,
591                 itemlocdist_qty,
592                 itemsite_loccntrl,
593                 itemsite_controlmethod,
594                 itemsite_perishable,
595                 itemsite_warrpurc,
596                 COALESCE(itemsite_lsseq_id,-1) AS itemsite_lsseq_id,
597                 COALESCE(itemlocdist_source_id,-1) AS itemlocdist_source_id
598                 FROM itemlocdist, itemsite
599                 WHERE ( (itemlocdist_itemsite_id=itemsite_id) 
600                         AND (itemlocdist_series={$itemlocdist_series}) ) 
601                 ORDER BY itemlocdist_id
602         ");
603
604         while ($db->fetch()) {
605             if (empty($db->itemlocdist_id) || $db->itemlocdist_id < 0) {
606                 die("itemlocdist_id isn't found! \n");
607             }
608             $itemlocdist_id = $db->itemlocdist_id;
609
610             $sdb = DB_DataObject::factory($tn);
611             $sdb->query("INSERT INTO itemlocdist (itemlocdist_itemlocdist_id,
612                             itemlocdist_source_type,
613                             itemlocdist_source_id,
614                             itemlocdist_qty,
615                             itemlocdist_ls_id, itemlocdist_expiration
616                     )
617                     SELECT itemlocdist_id, 
618                             'L', 
619                             {$this->cmhead_location_id}, 
620                             itemlocdist_qty, 
621                             itemlocdist_ls_id,
622                             endOfTime()
623                     FROM itemlocdist
624                     WHERE (itemlocdist_id={$itemlocdist_id})
625             ");
626
627
628             $sdb = DB_DataObject::factory($tn);
629             $sdb->query("SELECT distributeToLocations({$itemlocdist_id}) AS result");
630             $sdb->fetch();
631         }
632
633         $db = DB_DataObject::factory($tn);                    
634         $db->query("SELECT postItemlocseries({$itemlocdist_series}) AS result");
635         $db->fetch();
636         
637         
638         
639         $loc = DB_DataObject::Factory('location');
640         if (!$loc->get($this->cmhead_location_id)) {
641             $roo->jerr("no location specified");
642         }
643         
644         $cust = $loc->customer();
645         if (!$cust) {
646             $roo->jerr("the location specified does not have a customer associated with it.");
647         }
648         $our_db = substr($this->database(),-2);
649         
650         
651         $loc_db = $cust->char('INTERNALCOMPANY');
652         
653         $loc_db = empty($loc_db) ? $our_db : $loc_db ;
654         
655         // this now needs to create a credit memo in HK to transfer the stock back to HK..
656          
657         // transfer if necessary..
658         if ($our_db != $loc_db) {
659             if (HTML_FlexyFramework::get()->cli) {  
660                 $roo->jerr("CLI can not be used to do transfer");
661             }
662             
663             $res  = $this->doStockTransfer($roo);
664             if (true !== $res) {
665                 // rollback handled by top level..
666                 //$s->query("ROLLBACK");
667                 
668                 return $res;
669             }
670             
671             
672         }
673         
674         
675         
676         
677         
678         return true;
679         // end handling items being posted..
680     }
681     // SG ONLY ... - creates a matching credit memo in HK..
682     
683     /*
684      *  this is for voiding a un-apply credit memo
685      *  voidcreditmemo(integer)
686      *  pCmheadid ALIAS FOR $1;
687      * 
688      */
689     function void($roo)
690     {   
691         $tn = $this->tableName();
692         
693         if (empty($this->cmhead_posted)) {
694             $roo->jerr("credit memo is not posted");
695         }
696         
697         
698         // check who can do this..
699         $admin = DB_DataObject::factory('groups')->lookup('name', 'Administrators' );
700         if (
701                 ($this->cmhead_salesrep_id != $roo->authUser->salesrep()->pid())
702                 &&
703                 (!in_array($roo->authUser->pid() , $admin->memberIds()))
704            )
705         {
706             $roo->jerr("you may not void this credit memo - you must be the sales rep or an administrator");
707             
708         }
709         
710         
711         
712         // check apply??
713         $aropen = DB_DataObject::factory('aropen');
714         $aropen->aropen_docnumber = $this->cmhead_number;
715         $aropen->doctype = 'C';
716         if(!$aropen->find(true)){
717             $roo->jerr("Error occur on finding aropen id for {$this->cmhead_number}");
718         }
719         
720         $arapply = DB_DataObject::factory('arapply');
721         $arapply->whereAdd("
722             arapply_target_aropen_id = {$aropen->pid()}
723             OR
724             arapply_source_aropen_id = {$aropen->pid()}
725         ");
726         
727         if($arapply->find(true)){
728             $roo->jerr("Can not void {$this->cmhead_number} since it has applied to application");
729         }
730         
731         $this->checkLocationStock($roo);
732         
733         $ret = $this->pid();
734         
735         $db = DB_DataObject::factory($tn);
736         $db->query("SELECT voidCreditMemo({$ret}) as result");
737         $db->fetch();
738         if (empty($db->result) || $db->result < 0) {
739             $roo->jerr("voidCreditMemo failed with result being {$db->result}! " .  print_r($ret,true) );
740         }
741        
742         $itemlocdist_series = $db->result;
743          //$roo->jerr("$itemlocdist_series");
744          
745          
746          
747         
748         
749          
750         $db = DB_DataObject::factory($tn);
751         $db->query("SELECT itemlocdist_id,
752                 itemlocdist_reqlotserial,
753                 itemlocdist_distlotserial,
754                 itemlocdist_qty,
755                 itemsite_loccntrl,
756                 itemsite_controlmethod,
757                 itemsite_perishable,
758                 itemsite_warrpurc,
759                 COALESCE(itemsite_lsseq_id,-1) AS itemsite_lsseq_id,
760                 COALESCE(itemlocdist_source_id,-1) AS itemlocdist_source_id
761                 FROM itemlocdist, itemsite
762                 WHERE ( (itemlocdist_itemsite_id=itemsite_id) 
763                         AND (itemlocdist_series={$itemlocdist_series}) ) 
764                 ORDER BY itemlocdist_id
765         ");
766
767         while ($db->fetch()) {
768             if (empty($db->itemlocdist_id) || $db->itemlocdist_id < 0) {
769                 die("itemlocdist_id isn't found! \n");
770             }
771             $itemlocdist_id = $db->itemlocdist_id;
772
773             $sdb = DB_DataObject::factory($tn);
774             $sdb->query("INSERT INTO itemlocdist (itemlocdist_itemlocdist_id,
775                             itemlocdist_source_type,
776                             itemlocdist_source_id,
777                             itemlocdist_qty,
778                             itemlocdist_ls_id, itemlocdist_expiration
779                     )
780                     SELECT itemlocdist_id, 
781                             'L', 
782                             {$this->cmhead_location_id}, 
783                             itemlocdist_qty, 
784                             itemlocdist_ls_id,
785                             endOfTime()
786                     FROM itemlocdist
787                     WHERE (itemlocdist_id={$itemlocdist_id})
788             ");
789
790
791             $sdb = DB_DataObject::factory($tn);
792             $sdb->query("SELECT distributeToLocations({$itemlocdist_id}) AS result");
793             $sdb->fetch();
794         }
795
796                
797         
798         // this generates an additional itemlocdist record..
799          
800         
801         
802         
803         $db = DB_DataObject::factory($tn);                    
804         $db->query("SELECT postItemlocseries({$itemlocdist_series}) AS result");
805         $db->fetch();
806         
807         return true;
808         
809     }
810     
811     
812     function fixCmvoid()
813     {
814        $query = " select * from invhist where invhist_comments like 'Credit Voided%' and not invhist_hasdetail ";
815        
816        // fetch the CM-head based on ordnumber
817        // 
818        // look up in itemloc -> what the current qty is..
819        
820        // search for invdetail - with same doc number invdetail_qty > 0 - distinct locatoin_id 
821        //if more than 1.. error out.. and let's check them;
822        
823 $query = " 
824          INSERT INTO invdetail
825             ( invdetail_invhist_id, invdetail_location_id, invdetail_ls_id,
826               invdetail_qty, invdetail_qty_before, invdetail_qty_after, invdetail_expiration, 
827               invdetail_warrpurc )
828               
829
830
831             SELECT _itemlocdist.invhistid, itemloc_location_id, itemloc_ls_id,
832                    _itemlocdist.qty, itemloc_qty, (itemloc_qty + _itemlocdist.qty),
833                    itemloc_expiration,_itemlocdist.warranty
834             FROM itemloc
835             WHERE (itemloc_id=_itemlocid)
836             
837
838 ";
839 $query = " 
840         --  Update the parent invhist to indicate that it has invdetail records
841             UPDATE invhist
842             SET invhist_hasdetail=TRUE
843             WHERE ((invhist_hasdetail=FALSE)
844              AND (invhist_id=_itemlocdist.invhistid));
845              ";
846
847     }
848     
849     
850     function doStockTransfer($roo)
851     {
852         $roo->jerr("cross company transfer disabled");
853         $items =  $this->items();
854         
855         
856         $items = $this->sellToHK($roo, $items); // remove the stock so that HK can have it..
857         
858
859         $ff = HTML_FlexyFramework::get();
860         
861         if (empty($ff->Xtuple['main_url'])) {
862             $roo->jerr("Xtuple['main_url'] is not configured");
863         }
864         if (empty($ff->Xtuple['main_remote_cust_number'])) {
865             //$roo->jerr( "Xtuple['main_remote_cust_number'] is not configured");
866             $roo->jerr("Old code using remote_customer - disabled");
867         }
868         
869         
870         
871         
872         $loc = DB_DataObject::Factory('location');
873         $loc->get($this->cmhead_location_id); 
874         
875         
876         
877         
878         
879         // on hk side..
880         //Needs to know 
881         //  Order number (so it can be voided later..)
882         //  list of items (and the source location)
883         //  Qty
884         //  UnitPrice?? - this should be the FIFO cost..
885         
886         
887         // on the signapore site
888         
889         $full = DB_DataObject::Factory('cmhead');
890         $full->autoJoin();
891         $full->get($this->pid());
892         
893         $roo->jerr("Old code using remote_customer - disabled");
894         
895         require_once 'HTTP/Request.php';
896         
897         $req = new HTTP_Request( $ff->Xtuple['main_url'] . '/Roo/Cmhead' );
898         $req->setMethod(HTTP_REQUEST_METHOD_POST);
899      
900         
901         $base = $this->toArray();
902         unset($base['cmhead_id']);
903         unset($base['cmhead_id']);
904                     
905         $req->addPostData( array(
906                 '_is_xfer' => 1,
907                 
908                 
909                 'cmhead_number' => 'XF-' . $full->cmhead_number,
910                 'cust_number' => $ff->Xtuple['main_remote_cust_number'], // $roo->jerr("Old code using remote_customer - disabled");
911                 'cmhead_docdate' => $full->cmhead_docdate,
912     
913                 
914                 'cmhead_freight' => 0 , //$full->cmhead_freight ,
915                 'cmhead_misc' => 0, //$full->cmhead_misc,
916             
917                 'cmhead_comments' => $full->cmhead_comments,
918                 //'cmhead_misc_descrip'=> '', //$full->cmhead_misc_descrip,
919                 
920                 'location_name' => $full->cmhead_location_id_location_name,
921                 //'cmhead_misc_accnt_id_accnt_number' => $full->cmhead_misc_accnt_id_accnt_number,
922                 
923     
924                 //'cmhead_curr_id;                  // int4(4)  default_basecurrid%28%29
925                 //cmhead_freighttaxtype_id;        // int4(4)  
926                 //public $cmhead_salesrep_id;              // int4(4)  
927     
928                 //cmhead_taxzone_id;               // int4(4)  
929     
930                  
931                 'items' => $items,
932                 
933         ));
934         
935         $res = $req->sendRequest();
936         if (is_a($res,'PEAR_Error')) {
937             $roo->jerr( "MAIN REQUEST RETURNED: ". $res->toString());
938         }
939         $res = json_decode($req->getResponseBody());
940         
941         
942         
943         if (!is_object($res)) {
944             $roo->jerr("MAIN REQUEST RETURNED: ". $req->getResponseBody());
945         }
946         
947         if (!$res->success) {
948             $roo->jerr("MAIN REQUEST RETURNED: ". $res->errorMsg);
949         }
950          
951         return true;
952          
953         
954     }
955          
956     function sellToHK($roo,$items)
957     {
958         
959         $ff = HTML_FlexyFramework::get();
960
961         $out = array();
962         foreach($items as $item) {
963             
964             $xitem = $item->itemsite()->item();
965             if (!isset($item_req[$xitem ->item_number])) {
966                 $item_req[$xitem ->item_number] = 0;
967             }
968             $item_req[$xitem->item_number] += $item->cmitem_qtycredit;
969             
970             $out[] = array(
971                 
972                 'linenumber'=> $item->cmitem_linenumber,
973                 'item_number'=> $xitem->item_number,
974                 'qty' => $item->cmitem_qtycredit    
975             );
976             
977             
978         }
979         
980         
981         $po = DB_DataObject::factory('pohead');
982         
983         //print_R($item_req);exit;
984         
985         $prices = $po->fetchXferPrices($roo, $item_req);
986        
987         // now read the data and fill in the values..
988         foreach($out as $i=>$item) {
989             
990             if (!isset($prices[$item['item_number']])) {
991                 $roo->jerr( "ERROR MAIN REQUEST FAILED TO RETURN PRICE FOR {$item['item_number']}");
992             }
993             $out[$i]['unitprice'] = $prices[$item['item_number']];
994         }
995        
996         $loc = DB_DataObject::Factory('location');
997         $loc->get($this->cmhead_location_id); 
998         
999         //print_R($out);exit;
1000         
1001         $cust = DB_DataObject::Factory('custinfo');
1002         $cust ->get('cust_number', $ff->Xtuple['main_vendor_number']);
1003         
1004         $curr= DB_DataObject::Factory('curr_symbol');
1005         $curr->get('curr_abbr', 'HKD');
1006         
1007         // now make a debit memo... for the transaction..
1008         $d = DB_DataObject::Factory('invchead');
1009         $d->handleXfer($roo, array(
1010         
1011          
1012                 'invchead_invcnumber' => 'XF-'.$this->cmhead_number,  // invoice should match number...
1013                 'invchead_orderdate' => $this->cmhead_docdate,
1014                 'invchead_invcdate' => $this->cmhead_docdate,
1015                 'cust_number' => $cust->cust_number,
1016                 'invchead_curr_id' => $curr->pid(),
1017                 'invchead_posted' => false,
1018                 'invchead_printed' => false,
1019                 'invchead_commission' => 0,
1020                 'invchead_freight' => 0,
1021                 'invchead_misc_amount' => 0,
1022                 'invchead_shipchrg_id' => -1,
1023                 
1024                 'src_location' => $loc->location_name,
1025                 
1026                 'items' => $out,
1027           
1028         ));
1029         
1030         return $out;
1031         
1032         
1033         
1034     }
1035     
1036     // in HK... we recieved a  transfer CM..
1037     function recieveXfer($roo, $r)
1038     {
1039         
1040         //$roo->jerr("xfer testing");
1041         $cm = DB_DataObject::factory('cmhead');
1042         $cm->setFrom($r);
1043         
1044         foreach($cm->defaults() as $k=>$v) {
1045             if (!isset($r[$k])) {
1046                 $cm->$k  = $v;
1047             }
1048         }
1049         
1050         if (empty($r['location_name'])) {
1051             $roo->jerr("no location name recieved.");
1052         }
1053         $loc = DB_DataObject::Factory('location');
1054         if (!$loc->get('location_name', $r['location_name'])) {
1055             $roo->jerr("could not find lcoation {$r['location_name']}");
1056         }
1057         $cm->cmhead_location_id = $loc->pid();
1058         
1059         
1060         if (empty($r['cust_number'])) {
1061             $roo->jerr("no cust_number   recieved.");
1062         }
1063         $cust = DB_DataObject::Factory('custinfo');
1064         if (!$cust->get('cust_number', $r['cust_number'])) {
1065             $roo->jerr("could not find customer number : {$r['cust_number']}");
1066            
1067         }
1068         $cm->cmhead_cust_id = $cust->pid();
1069         
1070          
1071         $cm->insert();
1072         
1073         foreach($r['items'] as $item) {
1074             $i = DB_DataObject::Factory('cmitem');
1075             $i->recieveXfer($roo,$cm, $item);
1076             
1077         }
1078         
1079         $cm->post($roo);
1080         
1081         // fill in our varous data...
1082         
1083         
1084         $roo->jok("transfered");
1085         
1086         
1087         
1088     }
1089     
1090     function joinAddAropen()
1091     {
1092         $aropen = DB_DataObject::factory('aropen');
1093         $this->_join .= "
1094             LEFT JOIN aropen join_cmhead_aropen_id
1095             ON
1096             join_cmhead_aropen_id.aropen_doctype = 'C'
1097             AND
1098             join_cmhead_aropen_id.aropen_docnumber = cmhead_number
1099             AND
1100             join_cmhead_aropen_id.aropen_cust_id = cmhead_cust_id
1101             AND
1102             aropen_open
1103         ";
1104         
1105         $this->selectAs($aropen, 'cmhead_aropen_id_%s', 'join_cmhead_aropen_id');
1106     }
1107     
1108     function checkLocationStock($roo)
1109     {
1110         if(empty($roo->bootLoader->Xtuple['prevent_negative'])){
1111             return;
1112         }
1113         
1114         $items = $this->items();
1115         
1116         $stock = array();
1117         
1118         foreach ($items as $item){
1119             if(empty($item->cmitem_qtycredit)){
1120                 continue;
1121             }
1122             
1123             $balance = $item->itemsite()->checkLocationStock($this->cmhead_location_id);
1124             
1125             if(empty($balance) || $balance < $item->cmitem_qtycredit){
1126                 $stock[] = $item->itemsite()->item()->item_number;
1127             }
1128         }
1129
1130         if(count($stock)){
1131             $roo->jerr("These items have negative stock " . implode(', ', $stock));
1132         }
1133     }
1134     
1135 }