3 * Table Definition for shiphead
7 * shipdate = filled in..
10 * shipdate : filled in
13 * shipdate : filled in
22 require_once 'DB/DataObject.php';
24 class Pman_Xtuple_DataObjects_Shiphead extends DB_DataObject
27 /* the code below is auto generated do not remove the above tag */
29 public $__table = 'shiphead'; // table name
30 public $shiphead_id; // int4(4) not_null default_nextval%28shiphead_shiphead_id_seq%29 primary_key
31 public $shiphead_order_id; // int4(4) not_null
32 public $shiphead_order_type; // text(-1) not_null
33 public $shiphead_number; // text(-1) not_null unique_key
34 public $shiphead_shipvia; // text(-1)
35 public $shiphead_freight; // numeric(-1) not_null default_0.0
36 public $shiphead_freight_curr_id; // int4(4) not_null default_basecurrid%28%29
37 public $shiphead_notes; // text(-1)
38 public $shiphead_shipped; // bool(1) not_null default_false
39 public $shiphead_shipdate; // date(4)
40 public $shiphead_shipchrg_id; // int4(4)
41 public $shiphead_shipform_id; // int4(4)
42 public $shiphead_sfstatus; // bpchar(-1) not_null
43 public $shiphead_tracknum; // text(-1)
44 public $shiphead_location_id; // text(-1)
45 public $shiphead_shipto_id; // text(-1)
46 public $shiphead_delivery_note; // TEXT
50 * Getter / Setter for $shiphead_freight_curr_id
52 * @param mixed (optional) value to assign
55 public function freight_curr() {
56 return func_num_args() ? $this->link('shiphead_freight_curr_id', func_get_arg(0)) : $this->link('shiphead_freight_curr_id');
60 * Getter / Setter for $shiphead_shipchrg_id
62 * @param mixed (optional) value to assign
65 public function shipchrg() {
66 return func_num_args() ? $this->link('shiphead_shipchrg_id', func_get_arg(0)) : $this->link('shiphead_shipchrg_id');
70 * Getter / Setter for $shiphead_shipform_id
72 * @param mixed (optional) value to assign
75 public function shipform() {
76 return func_num_args() ? $this->link('shiphead_shipform_id', func_get_arg(0)) : $this->link('shiphead_shipform_id');
80 /* the code above is auto generated do not remove the tag below */
85 public function location() {
86 if (func_num_args()) {
87 $obj = func_get_args(0);
88 $this->shiphead_location_id = is_object($obj) ? $obj->pid() : $obj;
91 //echo '<PRE>';print_r($this);exit;
92 $l = DB_DataObject::Factory('location');
93 $l->get($this->shiphead_location_id);
98 public function shipto() {
99 if (func_num_args()) {
100 $obj = func_get_args(0);
101 $this->shiphead_shipto_id = is_object($obj) ? $obj->pid() : $obj;
104 $l = DB_DataObject::Factory('shiptoinfo');
105 $l->get($this->shiphead_shipto_id);
113 if (func_num_args()) {
114 $ar = func_get_arg(0);
115 $this->shiphead_order_id = is_object($ar) ? $ar->pid() : $ar;
116 return $this->shiphead_order_id;
118 // no arguemnts - fetch..
119 static $cache = array();
120 if (isset($cache[$this->shiphead_order_id])) {
121 return $cache[$this->shiphead_order_id];
123 // technically check --- shiphead_order_type
124 $d = $this->factory('cohead');
125 if (!$d->get($this->shiphead_order_id)) {
126 $d = $this->factory('cohead');
127 $cache[$this->shiphead_order_id] = $d;
130 $cache[$this->shiphead_order_id] = $d;
134 // returns a map of orderitemid-> shipitem.
135 // it assumes that a order item does not have multiple lines referenced..
139 $ids = $o->items('coitem_id');
140 $i = $this->factory('shipitem');
141 $i->shipitem_shiphead_id = $this->shiphead_id;
142 $i->whereAddIn('shipitem_orderitem_id', $ids, 'int');
147 $ret[$i->shipitem_orderitem_id] = clone($i);
157 function applyFilters($q, $au, $roo)
160 if (!empty($q['_download'])) {
161 if (!$this->get($q['_download'])) {
162 $roo->jerr("invalid id");
164 return $this->download($roo);
166 if (!empty($q['_stash'])) {
167 return $this->stashList($q['_stash'],$roo);
172 if (!empty($q['_status'])) {
173 switch($q['_status']) {
174 case 'S': // [ 'S', "Shipped"],
175 $this->whereAdd('shiphead_shipdate IS NOT NULL');
180 case 'R' : // , "Reserved"],
181 $this->whereAdd('shiphead_shipdate IS NULL AND NOT shiphead_shipped');
184 case 'V' : // , "Void Only"],
185 $this->whereAdd('shiphead_shipdate IS NULL AND shiphead_shipped');
194 if (!empty($q['search']['fromDate'])) {
195 $v = $this->escape($q['search']['fromDate']);
196 $this->whereAdd("shiphead_shipdate >= '$v'");
198 if (!empty($q['search']['toDate'])) {
199 $v = $this->escape($q['search']['toDate']);
200 $this->whereAdd("shiphead_shipdate <= '$v'");
210 (SELECT count(shipitem_qty) FROM shipitem WHERE shipitem_shiphead_id = shiphead_id) AS shipqty
212 //DB_DataObject::debugLevel(1);
214 $cohead = $this->factory('cohead');
215 $cohead->joinAdd($this->factory('custinfo'), 'LEFT');
217 $this->joinAdd(array('shiphead_order_id', $cohead, 'cohead_id'), 'LEFT');
220 $this->selectAs($this->factory('cohead'), 'shiphead_order_id_%s');
221 $this->selectAs($this->factory('custinfo'), 'shiphead_custinfo_%s');
222 $this->_extra_cols = array ( 'shiphead_order_id_cohead_number', ); // sortable
224 if (!empty($q['shiphead_custinfo_cust_id'])) {
225 $this->whereAdd('custinfo.cust_id = ' . ((int) $q['shiphead_custinfo_cust_id']));
236 function beforeInsert($q, $roo)
239 //check to see if there are any other 'draft' shipments...
241 $sh = DB_DataObject::Factory('shiphead');
242 $sh->shiphead_order_id = $this->shiphead_order_id;
243 $sh->shiphead_shipped = false;
244 $sh->whereAdd('shiphead_shipdate IS NOT NULL');
246 $roo->jerr("Order already contains a draft shipment");
250 * check to see if the delivery notes is allow blank
251 * if the shiphead location id is same as the default_location, then all blank, otherwise, MUST fill it in...
253 if(empty($this->shiphead_delivery_note)){
254 $l = DB_DataObject::factory('location');
255 $l = $l->defaultConfigLocation();
257 if($this->shiphead_location_id != $l->pid()){
258 $roo->jerr("You must fill in the delivery notes!");
265 if (empty($q['shiphead_number'] ) || $q['shiphead_number'] == 'Automatic') {
266 $this->shiphead_number = $this->genNumber();
269 if (empty($this->shiphead_order_type)) {
270 $this->shiphead_order_type = 'SO';
277 function beforeUpdate($old,$q,$roo)
279 if(!empty($q['_send_delivery'])){
280 $this->setDelivery($roo);
284 if (!empty($q['_void'])) {
286 $this->factory('cohead')->lockTables();
287 if ($this->shiphead_shipped) {
289 $res = $this->unconfirm($roo);
292 $roo->jerr("You need to unpost the invoice for this sales order");
294 $roo->jerr("recall returned ". serialize($res));
297 $roo->jok("unconfirmed");
303 $ret = $this->void($roo);
304 $ret === true ? $roo->jok("Voided") : $roo->jerr($ret);
308 * check to see if the delivery notes is allow blank
309 * if the shiphead location id is same as the default_location, then all blank, otherwise, MUST fill it in...
311 if(empty($this->shiphead_delivery_note)){
312 $l = DB_DataObject::factory('location');
313 $l = $l->defaultConfigLocation();
315 if($this->shiphead_location_id != $l->pid()){
316 $roo->jerr("You must fill in the delivery notes!");
321 if ($this->shiphead_shipped) {
322 $roo->jerr("You can not modified confirmed shipments - void it");
331 $sh = DB_DataObject::factory('shiphead');
332 $sh->shiphead_order_id = $this->shiphead_order_id;
334 $sh->whereAdd("shiphead_number like '" . $this->escape($o->cohead_number) . "-%'");
335 $sh->selectAdd('substr(shiphead_number, ' . strlen($o->cohead_number.'--') .')::numeric as shiphead_number_seq');
336 $sh->orderBy('shiphead_number_seq DESC');
338 return $o->cohead_number .'-1';
342 $n = array_pop(explode('-',$sh->shiphead_number)) * 1;
343 return $o->cohead_number .'-' . ($n+1);
348 function unconfirm($roo)
352 $s = $this->factory('shiphead');
353 if (empty($roo->transObj)) {
356 //DB_DataObject::debugLevel(1);
358 $items = $this->items();
360 // increase our revision.
361 $this->query("UPDATE shiphead
363 shiphead_rev = shiphead_rev +1,
364 shiphead_shipped=FALSE
366 shiphead_id = {$this->shiphead_id}
372 $gl= DB_DataObject::Factory('gltrans');
374 $gl->selectAdd('max(gltrans_id) as gltrans_id');
376 $glbefore = $gl->gltrans_id;
377 // now do the actuall recall..
378 $dt = date('Y-m-d', strtotime( $this->shiphead_shipdate));
379 $s->query("SELECT recallShipment({$this->pid()}, '$dt') as res");
383 // recall shipment returns null if it's a sales order...
384 if (!empty($s->res) && $s->res < 0) {
386 if (empty($roo->transObj)) {
387 $s->query("ROLLBACK");
393 $gl= DB_DataObject::Factory('gltrans');
395 $gl->selectAdd('max(gltrans_id) as gltrans_id');
398 if ($glbefore == $gl->gltrans_id) {
399 $roo->jerr("no gltrans was commited for recal shipment?");
404 // hopefully the fact that we have recalled this shipment will not break this..
406 $our_site = substr($this->database(), -2);
409 // where are we transfering to...
410 $loc = DB_DataObject::Factory('location');
411 if (!$this->shiphead_location_id || !$loc->get($this->shiphead_location_id)) {
412 $roo->jerr("no location specified");
416 if ($loc->location_cust_id) {
417 $cust = $loc->customer();
419 $roo->jerr("the location specified does not have a customer associated with it. X");
422 $target = $cust->char('INTERNALCOMPANY');
423 if (empty($target)) {
428 // who owns the target location
432 // migration process can not transfer.
433 if (HTML_FlexyFramework::get()->cli && $target != $our_site) {
434 $roo->jerr("invalid transfer via cli");
440 // transfer if necessary..
441 if ($target != $our_site) {
442 $res = $this->revertStockTransfer($roo);
444 // rollback handled by top level..
445 //$s->query("ROLLBACK");
452 // checck for transfer - it should really look up customers with that remote, and see how many there are..
456 // increase our revision.
457 $this->query("UPDATE shiphead
459 shiphead_rev = shiphead_rev +1
461 shiphead_id = {$this->shiphead_id}
464 if (empty($roo->transObj)) {
470 function confirm($roo)
472 $items = $this->items();
474 // increase our revision.
475 $roo->jerr("shipment does not have any items");
480 $s = $this->factory('shiphead');
481 if (empty($roo->transObj)) {
484 $dt = date('Y-m-d', strtotime( $this->shiphead_shipdate));
485 $s->query("SELECT shipShipment({$this->pid()}, '$dt') as res");
488 if (!is_null($s->res)) {
489 if (empty($roo->transObj)) {
490 $s->query("ROLLBACK");
493 $roo->jerr("ship returned ". serialize($s->res));
496 $thisdb = substr($this->database(), -2);
498 // migration process can not transfer.
501 // determine the location.
502 $loc = DB_DataObject::Factory('location');
503 if (!$loc->get($this->shiphead_location_id)) {
504 $roo->jerr("no location specified");
508 $cust = $loc->customer();
511 $roo->jerr("the location specified does not have a customer associated with it. X");
513 $location_db = $cust->char('INTERNALCOMPANY');
514 $location_db = empty($location_db ) ? $thisdb : $location_db ;
517 $is_cli = HTML_FlexyFramework::get()->cli;
519 if (HTML_FlexyFramework::get()->cli && ($thisdb != $location_db)) {
520 $roo->jerr("cli can not do a transfer");
523 // transfer if necessary..
524 if ($thisdb != $location_db) {
526 //$roo->jerr("Stock transfer disabled at present $thisdb to $location_db");
527 $res = $this->doStockTransfer($roo);
529 // rollback handled by top level..
530 //$s->query("ROLLBACK");
541 if (empty($roo->transObj)) {
551 function onInsert($q, $roo)
554 if (isset($q['shipitems'])) {
555 $this->factory('cohead')->lockTables();
556 $this->updateItems(json_decode($q['shipitems']),$roo);
561 function onUpdate($old, $q, $roo)
563 if (isset($q['shipitems'])) {
564 $this->factory('cohead')->lockTables();
565 $this->updateItems(json_decode($q['shipitems']), $roo);
567 if (isset($q['_confirm'])) {
568 $this->factory('cohead')->lockTables();
569 $res = $this->confirm($roo);
580 // shiphead_shipped = true and shipdate is empty..
581 if (!empty($this->shiphead_shipped) && empty($this->shiphead_shipdate) ) {
582 $roo->jerr("the shipment is already void");
584 $this->stashShipment();
586 $old = $this->items();
588 // always attempt to reverse it..
589 // the reverse code should delete the shipitem line - causing this to
590 // do nothing the next time round..
591 foreach($old as $id => $ol) {
596 if (!$old && empty($this->shiphead_shipdate)) {
597 return "Already void";
601 $this->shiphead_shipdate = $this->sqlValue('NULL');
602 $this->shiphead_shipped = true;
605 // we have to flag it as shipped..
614 * update Items in a shipment
616 * order_item_id => qty
620 * shipitem_orderitem_id => order_item_id
629 function updateItems($ar, $roo)
632 //DB_DataObject::debugLevel(1);
634 //$o->shipitem_orderitem_id,
638 $old = $this->items();
640 $bar = array(); //$ar;
642 // check stdcost of item to make sure it's not $0
645 foreach ($ar as $order_item => $qty){
646 if (is_object($qty)) {
647 $order_item = $qty->shipitem_orderitem_id;
648 $qty = $qty->shipitem_qty;
651 $oi = DB_DataObject::factory('coitem');
652 $oi->get($order_item);
653 $item = $oi->itemsite()->item();
655 $i = DB_DataObject::factory('item');
656 $i->query("SELECT stdCost({$item->pid()}) AS cost");
660 $badItems[] = $item->item_number;
664 if(count($badItems)){
665 $roo->jerr("These items have 0 stdCost " . implode(', ', $badItems));
669 foreach($ar as $order_item=>$qty) {
671 if (is_object($qty)) {
672 $order_item = $qty->shipitem_orderitem_id;
673 $qty = $qty->shipitem_qty;
675 // in theory what happens to kit parts being updated to zero quantity
676 // I'm not sure it's even allowed..
677 //if (empty($qty )) {
678 // $bar[$order_item] = $qty;
682 $oi = DB_DataObject::factory('coitem');
683 $oi->get($order_item);
684 if ($oi->itemsite()->item()->item_type != 'K') {
685 $bar[$order_item] = $qty;
689 // find all the child elements..
690 $si = DB_DataObject::factory('coitem');
691 $si->coitem_linenumber = $oi->coitem_linenumber;
692 $si->coitem_cohead_id = $oi->coitem_cohead_id;
693 $si->whereAdd('coitem_subnumber != 0 ');
695 //echo "CONVERTING kit : {$oi->pid()}\n";
696 while ($si->fetch()) {
697 //echo "ADDING kit : {$si->coitem_id}\n";
698 $bar[$si->coitem_id] = floor($si->coitem_qtyord / $oi->coitem_qtyord) * $qty;
700 //$roo->jerr("fixing kit of parts at present");
707 if(!empty($roo->bootLoader->Xtuple['prevent_negative'])){
709 foreach ($ar as $order_item => $qty){
710 if (is_object($qty)) {
711 $order_item = $qty->shipitem_orderitem_id;
712 $qty = $qty->shipitem_qty;
718 $coitem = DB_DataObject::factory('coitem');
719 $coitem->get($order_item);
721 $balance = $coitem->itemsite()->checkLocationStock($this->shiphead_location_id);
723 if(empty($balance) || $balance < $qty){
724 $stock[] = $coitem->itemsite()->item()->item_number;
729 $roo->jerr("These items have negative stock " . implode(', ', $stock));
734 foreach($ar as $order_item=>$qty) {
735 if (is_object($qty)) {
736 $order_item = $qty->shipitem_orderitem_id;
737 $qty = $qty->shipitem_qty;
740 if (!isset($old[$order_item])) {
742 continue; // skip empty lines..
744 $this->addShipitem($order_item, $qty );
747 $ol = $old[$order_item];
751 if ($ol->shipitem_qty == $qty) {
752 unset($old[$order_item]);
755 //$roo->jerr("REVERSING");
758 unset($old[$order_item]);
762 $this->addShipItem($order_item, $qty );
763 unset($old[$order_item]);
765 // $ar - should contain all the order items.. if it does not...
766 // then we should update the quatities.
767 foreach($old as $id => $ol) {
776 * - this mimic's issueToshipping
778 * @param int|Object $oid the orderitem id or orderitem dataobject
779 * @param number $qty the quantity to add.. - there should only be one per order..
782 function addShipItem($oid, $qty)
784 $si = $this->factory('shipitem');
787 if (is_object($oid)) {
791 $oi = $this->factory('coitem');
796 $itemsite = DB_DataObject::factory('itemsite');
797 $itemsite->get('itemsite_id', $oi->coitem_itemsite_id);
798 if ($itemsite->itemsite_controlmethod !='R') {
799 // it will not get created..
803 $roo = HTML_FlexyFramework::get()->page;
804 if (!$itemsite->itemsite_stocked) {
805 $roo->jerr("Item ". $itemsite->item()->item_number . " is not marked as stocked, so can not be fullfilled.");
808 if (!$itemsite->itemsite_loccntrl) {
809 $roo->jerr("Item ". $itemsite->item()->item_number . " is not marked as location controlled, so can not be fullfilled.");
813 $d = $this->factory($this->tablename());
816 if (empty($roo->transObj)) {
820 // verify the product is stocked...
827 /// issue to shipping can not handle multiple shipments for the same
829 $ci = $this->factory('coitem');
830 $ci->query("SELECT NEXTVAL('itemloc_series_seq')::integer as itemlocseries ");
832 $itemlocSeries = $ci->itemlocseries;
834 $ci = $this->factory('coitem');
835 $q = "SELECT postInvTrans(
841 formatSoNumber(coitem_id),
843 ('Issue ' || item_number || ' to Shipping for customer ' || cohead_billtoname),
844 getPrjAccntId(cohead_prj_id, costcat_shipasset_accnt_id), costcat_asset_accnt_id,
846 CAST('{$this->shiphead_shipdate}' AS timestamp with time zone)
848 FROM coitem, cohead, itemsite, item, costcat, shiphead
849 WHERE ( (coitem_cohead_id=cohead_id)
850 AND (coitem_itemsite_id=itemsite_id)
851 AND (itemsite_item_id=item_id)
852 AND (itemsite_costcat_id=costcat_id)
853 AND (coitem_id={$oid})
854 AND (shiphead_id={$this->shiphead_id}) )";
860 if (empty($ci->invhistid) || $ci->invhistid < 0) {
862 $roo->jerr("post inv trans failed " . @$ci->invhistid );
868 'shipitem_orderitem_id' => $oid,
869 'shipitem_shiphead_id' => $this->shiphead_id,
870 'shipitem_qty'=> $qty,
871 'shipitem_shipped' =>false,
872 'shipitem_shipdate' => $this->shiphead_shipdate,
873 'shipitem_transdate' => $this->shiphead_shipdate, // $this->sqlValue('NOW()'),
874 //'shipitem_trans_username' text,
875 'shipitem_invoiced' => false,
876 //'shipitem_invcitem_id' =>
877 //'shipitem_value' => $oi->coitem_custprice * $qty,
878 'shipitem_invhist_id' => $ci->invhistid
883 // $si->shipitem_value = $si->sqlValue("
884 // currtobase({$o->cohead_curr_id}, {$oi->coitem_custprice} * {$qty}, '{ $this->shiphead_shipdate}')
886 $si->shipitem_value = $si->sqlValue("
887 (SELECT invhist_value_before - invhist_value_after FROM invhist where invhist_id = {$ci->invhistid} )
893 $d = $this->factory($this->tablename());
898 itemlocdist_reqlotserial,
899 itemlocdist_distlotserial,
902 itemsite_controlmethod,
905 COALESCE(itemsite_lsseq_id,-1) AS itemsite_lsseq_id,
906 COALESCE(itemlocdist_source_id,-1) AS itemlocdist_source_id
908 itemlocdist, itemsite
910 ( (itemlocdist_itemsite_id=itemsite_id)
912 (itemlocdist_series=$itemlocSeries) )
913 ORDER BY itemlocdist_id;
920 if (empty($d->itemlocdist_id)) {
921 $ssi = DB_DataObject::factory('shipitem');
922 $ssi->get($si->pid());
923 $roo->jerr("FAILED TO ADD ITEM " . $itemlocSeries. "\n".
924 print_r($ssi->toArray(), true)
928 $itemlocdist_id = $d->itemlocdist_id;
930 while ($d->fetch()) {
931 print_r($d->toArray('%s', true));
934 //print_r($ildist->toArray('%s', true));exit;
937 // why grab from the line item...
938 // it should grab from the shiphead?!?
940 $location = $this->shiphead_location_id; /// where.... from..
943 $d = $this->factory($this->tablename());
948 itemlocdist_itemlocdist_id, itemlocdist_source_type,
949 itemlocdist_source_id, itemlocdist_qty,
950 itemlocdist_ls_id, itemlocdist_expiration
954 {$location}, {$qty} * -1,
955 itemlocdist_ls_id, endOfTime()
958 WHERE (itemlocdist_id= $itemlocdist_id);
966 // this generates an additional itemlocdist record..
968 $d = $this->factory($this->tablename());
969 $d->query("SELECT distributeToLocations({$itemlocdist_id}) AS result");
970 $d = $this->factory($this->tablename());
971 $d->query("SELECT postItemlocseries({$itemlocSeries}) AS result");
973 $d = $this->factory($this->tablename());
975 if (empty($roo->transObj)) {
985 return $si->pid(); //we could return insert()...
988 // dumping old versions..
989 function stashItems()
991 $i = $this->factory('shipitem');
993 $i->shipitem_shiphead_id = $this->pid();
995 (SELECT coitem_itemsite_id FROM coitem where coitem_id = shipitem_orderitem_id) AS itemsite_id,
998 return $i->fetchAll('itemsite_id','shipitem_qty');
1003 function stashShipment()
1006 $old = $this->stashItems();
1008 return; // no point in stashing empty..
1010 // we should stash based on id.. - so old ones can be deleted.
1011 // group into 100's.. eg.
1012 // /shipstash/{floor(id/100)00/{id}/... versions..
1013 $ff = HTML_FlexyFramework::get();
1015 if (empty($ff->Xtuple['storedir'])) {
1016 $ff->page->jerr("Xtuple['storedir'] is not configured");
1019 $fd = $ff->Xtuple['storedir'] .
1021 floor($this->shiphead_order_id /100) .
1022 '/' . $this->shiphead_order_id .'/';
1025 if (!is_writable( $ff->Xtuple['storedir'])) {
1026 $ff->page->jerr("Xtuple['storedir'] is not writable");
1030 if (!file_exists($fd)) {
1031 mkdir($fd,0700, true);
1036 $fn = $fd. $this->shiphead_number . '_' . date('Y-m-d h:i:s',$d). '.json';
1037 if (file_exists($fn)) {
1046 file_put_contents($fn, json_encode( $old ));
1047 //$ff->page->jok("wrote stash");
1050 function stashList($id, $roo)
1052 $ff = HTML_FlexyFramework::get();
1058 if (empty($ff->Xtuple['storedir'])) {
1059 $roo>jerr("Xtuple['storedir'] is not configured");
1061 $fd = $ff->Xtuple['storedir'] .
1066 if (!file_exists($fd)) {
1067 $roo->jerr("no data available " . $fd);
1068 $roo->jdata(array());
1074 foreach(scandir($fd) as $d) {
1075 if (!preg_match('/\.json$/', $d)) {
1078 $n = preg_replace('/\.json$/', '', $d);
1079 $n = explode('_', $n);
1080 $n = $n[0] . ' voided on ' . $n[1];
1085 'data' => json_decode(file_get_contents($fd.'/'. $d))
1088 return $roo->jdata($ret);
1093 * return a list of what should be transfered.
1097 function transferItems()
1099 $i = $this->factory('shipitem');
1101 $i->shipitem_shiphead_id = $this->pid();
1105 LEFT JOIN itemsite ON coitem_itemsite_id = itemsite_id
1106 LEFT JOIN item ON itemsite_item_id = item_id
1107 WHERE coitem_id = shipitem_orderitem_id
1111 // only transfer products... ?? should be default... - code should not generate shipments for kits etc..
1113 'P' = (SELECT item_type
1115 LEFT JOIN itemsite ON coitem_itemsite_id = itemsite_id
1116 LEFT JOIN item ON itemsite_item_id = item_id
1117 WHERE coitem_id = shipitem_orderitem_id
1122 return $i->fetchAll('item_number','shipitem_qty');
1126 * return a list of source locations for this shipment - it should
1127 * only return 1 in our system...
1132 function sourceLocations()
1134 // this is based on the location listed in the coitem
1135 $i = $this->factory('shipitem');
1137 $i->shipitem_shiphead_id = $this->pid();
1139 (SELECT coitem_location_src
1141 WHERE coitem_id = shipitem_orderitem_id
1144 $src = array_unique($i->fetchAll('location_src'));
1148 function doStockTransfer($roo)
1150 $roo->sessionState(0); // non-locking!?
1151 $roo->jerr("stock transfer is disabled at present");
1155 //if ($this->order()->cust()->cust_name == 'Bloom and Grow HK') {
1156 // return $this->creditHK($roo);
1160 $srcs = $this->sourceLocations();
1161 if (count($srcs) != 1) {
1162 return "Shipment contains multiple source locations - this should not be allowed";
1166 $loc = DB_DataObject::Factory('location');
1167 $loc->get($srcs[0]);
1168 $cust = $loc->customer();
1170 $our_db = substr($this->database(),-2);
1171 $remote_db = $cust->char('INTERNALCOMPANY');
1172 if ($our_db == $remote_db) {
1173 $roo->jerr("stock transfer between same company - something is set up wrong.");
1180 // create a purchase order...
1182 $po = DB_DataObject::factory('pohead');
1183 //Create purchase order + reciept + voucher.
1184 //createAllFromShipment($roo, $shiphead, $remote_db, $cust, $loc)
1185 $prices = $po->createAllFromShipment($roo, $this, $remote_db, $cust, $loc);
1189 // ensure we have a price list???
1193 $order = $this->order();
1194 $tx_items = $this->transferItems();
1197 foreach($tx_items as $item=>$qty) {
1202 'linenumber' => $line,
1204 'unitprice' => $prices[$item],
1205 'item_number' => $item,
1215 // find the location it is comming from...
1224 // Order number (so it can be voided later..)
1225 // list of items (and the source location)
1227 // UnitPrice?? - this should be the FIFO cost..
1230 // on the signapore site
1232 $rev = $this->shiphead_rev ? '-rev' . $this->shiphead_rev : '';
1233 //$roo->jerr($this->shiphead_rev);
1236 require_once 'HTTP/Request.php';
1238 $req = new HTTP_Request( "{http://localhost/$roo->rootURL/{$remote_db}.php/Roo/Invchead" );
1239 $req->setMethod(HTTP_REQUEST_METHOD_POST);
1240 $req->addPostData( array(
1241 '_is_xfer' => $our_db,
1242 'invchead_invcnumber' => 'XF-'.$this->shiphead_number . $rev, // invoice should match number...
1243 'invchead_orderdate' => $this->shiphead_shipdate,
1244 'invchead_invcdate' => $this->shiphead_shipdate,
1245 //'cust_number' => $ff->Xtuple['main_remote_cust_number'] , // $roo->jerr("Old code using remote_customer - disabled");
1246 'invchead_posted' => false,
1247 'invchead_printed' => false,
1248 'invchead_commission' => 0,
1249 'invchead_freight' => 0,
1250 'invchead_misc_amount' => 0,
1251 'invchead_shipchrg_id' => -1,
1253 'src_location' => $loc->location_name
1257 $res = $req->sendRequest();
1258 if (is_a($res,'PEAR_Error')) {
1259 return "MAIN REQUEST RETURNED: ". $res->toString();
1261 $res = json_decode($req->getResponseBody());
1265 if (!is_object($res)) {
1266 return "MAIN REQUEST RETURNED: ". $req->getResponseBody();
1269 if (!$res->success) {
1270 return "MAIN REQUEST RETURNED: ". $res->errorMsg;
1277 // invoicing HK for stock..
1280 function creditHK($roo)
1283 $this->jerr("creditHK code - creates a credit memo on remote site? - why?");
1284 $ff = HTML_FlexyFramework::get();
1286 if (empty($ff->Xtuple['main_url'])) {
1287 $roo->jerr("Xtuple['main_url'] is not configured");
1289 if (empty($ff->Xtuple['main_remote_cust_number'])) {
1290 //$roo->jerr( "Xtuple['main_remote_cust_number'] is not configured");
1291 $roo->jerr("Old code using remote_customer - disabled");
1298 $order = $this->order();
1299 $tx_items = $this->transferItems();
1300 $po = DB_DataObject::factory('pohead');
1301 $prices = $po->fetchXferPrices($roo, $tx_items);
1306 foreach($tx_items as $item=>$qty) {
1310 'linenumber' => $line,
1312 'unitprice' => $prices[$item],
1313 'item_number' => $item,
1319 $srcs = $this->sourceLocations();
1320 if (count($srcs) != 1) {
1321 return "Shipment contains multiple source locations - this should not be allowed";
1324 $loc = DB_DataObject::Factory('location');
1325 $loc->get($srcs[0]);
1333 // Order number (so it can be voided later..)
1334 // list of items (and the source location)
1336 // UnitPrice?? - this should be the FIFO cost..
1339 // on the signapore site
1341 $full = DB_DataObject::Factory('cmhead');
1343 $full->get($this->pid());
1345 $roo->jerr("Old code using remote_customer - disabled");
1347 require_once 'HTTP/Request.php';
1349 $req = new HTTP_Request( $ff->Xtuple['main_url'] . '/Roo/Cmhead' );
1350 $req->setMethod(HTTP_REQUEST_METHOD_POST);
1352 $req->addPostData( array(
1356 'cmhead_number' => 'XF-INV-' . $this->shiphead_number,
1357 'cust_number' => $ff->Xtuple['main_remote_cust_number'], // $roo->jerr("Old code using remote_customer - disabled");
1358 'cmhead_docdate' => $this->shiphead_shipdate,
1361 'cmhead_freight' => 0 , //$full->cmhead_freight ,
1362 'cmhead_misc' => 0, //$full->cmhead_misc,
1364 'cmhead_comments' => $full->cmhead_comments,
1365 //'cmhead_misc_descrip'=> '', //$full->cmhead_misc_descrip,
1367 'location_name' => $loc->location_name,
1368 //'cmhead_misc_accnt_id_accnt_number' => $full->cmhead_misc_accnt_id_accnt_number,
1371 //'cmhead_curr_id; // int4(4) default_basecurrid%28%29
1372 //cmhead_freighttaxtype_id; // int4(4)
1373 //public $cmhead_salesrep_id; // int4(4)
1375 //cmhead_taxzone_id; // int4(4)
1382 $res = $req->sendRequest();
1383 if (is_a($res,'PEAR_Error')) {
1384 $roo->jerr( "MAIN REQUEST RETURNED: ". $res->toString());
1386 $res = json_decode($req->getResponseBody());
1390 if (!is_object($res)) {
1391 $roo->jerr("MAIN REQUEST RETURNED: ". $req->getResponseBody());
1394 if (!$res->success) {
1395 $roo->jerr("MAIN REQUEST RETURNED: ". $res->errorMsg);
1403 function revertStockTransfer($roo)
1405 $roo->jerr("stock transfer is disabled at present");
1406 if ($this->order()->cust()->cust_name == 'Bloom and Grow HK') {
1407 $roo->jerr("You can not reverse transfers to HK - you need to create
1408 a credit memo for HK - which will move the stock back");
1412 if (preg_match('/-d$/', $this->shiphead_number)) {
1413 // it's a migrated record.. no need to track stuff..
1417 $po = DB_DataObject::factory('pohead');
1418 //Create purchase order + reciept + voucher.
1419 $po->revertAllFromShipment($roo, $this);
1421 $ff = HTML_FlexyFramework::get();
1423 if (empty($ff->Xtuple['main_url'])) {
1424 return "Xtuple['main_url'] is not configured";
1426 //if (empty($ff->Xtuple['main_remote_cust_number'])) {
1427 // return "Xtuple['main_remote_cust_number'] is not configured";
1431 $order = $this->order();
1437 // Order number (so it can be voided later..)
1438 // list of items (and the source location)
1440 // UnitPrice?? - this should be the FIFO cost..
1443 // on the signapore site
1445 $rev = $this->shiphead_rev ? '-rev' . $this->shiphead_rev : '';
1447 require_once 'HTTP/Request.php';
1449 $req = new HTTP_Request( $ff->Xtuple['main_url'] . '/Roo/Invchead' );
1450 $req->setMethod(HTTP_REQUEST_METHOD_POST);
1451 $req->addPostData( array(
1452 '_is_xfer_void' => 1,
1453 'invchead_invcnumber' => 'XF-'.$this->shiphead_number . $rev
1456 $res = $req->sendRequest();
1457 if (is_a($res,'PEAR_Error')) {
1458 return "MAIN REQUEST RETURNED: ". $res->toString();
1460 $res = json_decode($req->getResponseBody());
1464 if (!is_object($res)) {
1465 return "MAIN REQUEST RETURNED: ". $req->getResponseBody();
1468 if (!$res->success) {
1469 return "MAIN REQUEST RETURNED: ". $res->errorMsg;
1481 function download($roo)
1484 //DB_DAtaObject::debugLevel(1);
1486 $r= DB_DataObject::Factory('shipitem');
1487 $r->shiphead($this);
1490 $r->joinAddCoitem();
1491 //$r->applyFilters(array(), $roo->authUser, $roo);
1493 $r->orderBy('coitem_linenumber ASC, coitem_subnumber ASC');
1495 $order = $this->order();
1496 $loc = $this->location();
1497 $shipto = $this->shipto();
1499 require_once 'Pman/Core/SimpleExcel.php';
1500 $s = new Pman_Core_SimpleExcel(
1501 $r->fetchAll(false,false,'toArray'),
1505 array( "Ship Date:", date('Y-m-d', strtotime($this->shiphead_shipdate))),
1506 array( "Order ID:", $order->cohead_number),
1507 array( "From:", $loc->location_name),
1508 array( "To:", implode("\n", $shipto->address())),
1513 'header'=> "Item Code",
1514 'dataIndex'=> 'item_number',
1516 //'renderer' => array($this, 'getThumb')
1519 'header'=> "Description",
1520 'dataIndex'=> 'item_descrip1',
1522 //'renderer' => array($this, 'getThumb')
1525 'header'=> "Quantity",
1526 'dataIndex'=> 'shipitem_qty',
1528 //'renderer' => array($this, 'getThumb')
1532 'workbook' => 'Shipment'
1536 $s->send($this->shiphead_number.date("-d-M-Y").'.xls');
1542 function setDelivery($roo)
1544 if(empty($this->shiphead_shipdate) || empty($this->shiphead_shipped)){
1545 $roo->jerr('Shipment has not been confirmed');
1548 if(empty($this->shiphead_delivery_note)){
1549 $roo->jerr('Delivery note has not been filled in');
1551 $order = $this->order();
1553 $order->shipment = clone($this);
1555 $order->sendShipment($roo);