txRecords($_REQUEST['loc'], explode(',',$_REQUEST['prods'])); echo json_encode($data);exit; } if (isset($_REQUEST['prod'])) { $data = $this->txRecordsAll($_REQUEST['loc'], $_REQUEST['prod'],isset($_REQUEST['day']) ? $_REQUEST['day'] : false); echo json_encode($data);exit; } $sd = strtoupper(array_pop(explode('xtuple', HTML_FlexyFramework::get()->database))); $lprefix = preg_match('/(lsg\.php|lhk.php)$/', $this->baseURL) ? 'l' : ''; //DB_DataObject::debugLevel(1); // we need to // A) grab the stock levels from the old database. // B) grab the stock levels from the new database // compare the values.. // for comparison: // use "Location: XXXX Product : XXXX" = $n // we might even be able to use array_diff between the two.. $il = DB_DataObject::Factory('itemloc'); $il->autoJoin(array( 'links' => array( 'itemloc_location_id' => 'location:location_id', 'itemloc_itemsite_id' => 'itemsite:itemsite_id', ) )); $il->selectAdd(); $il->selectAdd(" 'Location : ' || join_itemloc_location_id_location_id.location_name || ' Product : ' || (SELECT item_number FROM item WHERE item_id = join_itemloc_itemsite_id_itemsite_id.itemsite_item_id LIMIT 1) as pn, itemloc_qty "); $il->whereAdd('itemloc_qty <> 0.0'); $data = $il->fetchAll('pn', 'itemloc_qty'); ksort($data); if ($sd != 'HK') { // we only report on HK data.. echo json_encode($data); exit; } // hard codE? $har = explode('/', realpath(__FILE__)); $home = '/home/'. $har[2]; $fn = "$home/Dropbox/xtuple_working/old_database_snapshot/stock.json"; // var_dump($fn);exit; $base_data = (array)json_decode(file_get_contents($fn)); //echo '
'; print_r($base_data);exit; //var_dump($base_data['Location : Dymocks-CB Product : DM05001']); //exit; //print_r($base_data);exit; // run all the child processes... // //echo $cmd;exit; $other_data = (array) json_decode(file_get_contents( "http://localhost/xtuple/{$lprefix}sg.php/Xtuple/VerifyMigrate")); $core = array_merge($data,$base_data, $other_data); ksort($core); $out = array(); $out[] = array("location / sku", "OLD", "HK", "SG", "difference"); // merge the data and produce a sensible report.. $errors = array(); foreach($core as $k=>$blah) { $row = array( $k, isset($base_data[$k]) ? $base_data[$k] : 0, isset($data[$k]) ? $data[$k] : 0, isset($other_data[$k]) ? $other_data[$k] : 0, ); $row[4] = $row[1] - ($row[2] + $row[3]); if ($row[4] != 0 ) { $out[] = $row; $errors[$row[0]] = $row[1]; } } $error_ar = array(); foreach($errors as $r=>$qty) { $exp = explode(' Product : ', preg_replace('/^Location :/', '', $r)); //print_R( $exp); list($loc, $prod) = $exp; $loc = trim($loc); if (!isset($error_ar[$loc])) { $error_ar[$loc] = array(); } $error_ar[$loc][] = $prod; } // echo '';print_R($error_ar);exit; //echo ''; foreach($error_ar as $loc => $prods) { if ($loc != 'OLL') { // continue; } $out = array_merge($out,$this->processMismatch($loc, $prods)); } //die("got this far"); foreach($out as $o) { if (!is_array($o)) { var_dump($o);exit; } } header('Content-type: text/csv'); header( 'Content-Disposition: attachment;filename=stock_report-'.date('Y-m-d').'.csv'); $fh = fopen('php://output','w'); foreach($out as $o) { fputcsv($fh, $o); } exit; /* $el = array(); $eltot = 0; $locmax = 0; $totmax = 0; foreach($errors as $r=>$qty) { $exp = explode(' Product : ', preg_replace('/^Location :/', '', $r)); //print_R( $exp); list($loc, $prod) = $exp; $loc = trim($loc); $prod = trim($prod); $el[$loc] = isset($el[$loc]) ? $el[$loc] : 0; if ($locmax && $el[$loc] > $locmax) { continue; } if ($totmax && $eltot > $totmax) { break; } $el[$loc]++; $eltot++; $url = 'http://localhost/xtuple/hk.php/Roo/invdetail'; $args = $this->toParams(array( 'query[item_number]'=> trim($prod), 'query[location_name]'=> trim($loc), '_with_item'=>'1', 'sort'=>'invhist_transdate,invdetail_id', 'dir'=>'ASC', 'csvCols[0]' => 'invhist_transdate', 'csvCols[1]' => 'invhist_docnumber', 'csvCols[2]' => 'invhist_ordnumber', 'csvCols[3]' => 'invdetail_qty', 'csvCols[4]' => 'invdetail_bydate_qty', 'csvCols[5]' => 'invhist_comments', 'csvTitles[0]' => 'Date', 'csvTitles[1]' => 'Doc number', 'csvTitles[2]' => 'Order no.', 'csvTitles[3]' => 'Qty', 'csvTitles[4]' => 'Qty After', 'csvTitles[5]' => 'comments', 'start' => 0, 'limit' => 9999 )); fwrite($fh, "\n\n-- ". $r ." ,,Expecting:, $qty\n"); fwrite($fh, file_get_contents("http://localhost/xtuple/{$lprefix}hk.php/Roo/invdetail?$args")); fwrite($fh, file_get_contents("http://localhost/xtuple/{$lprefix}sg.php/Roo/invdetail?$args")); */ /* $rows = $this->fcsv("http://localhost/xtuple/{$lprefix}hk.php/Roo/invdetail?$args"); $head = array_shift($rows); fputcsv($fh, $head); $add = $this->fcsv("http://localhost/xtuple/{$lprefix}sg.php/Roo/invdetail?$args"); array_shift($add); $rows += $add; usort($rows, function($a, $b) { $aa =strtotime($a[0]); $bb = strtotime($b[0]); if ($aa == $bb) return 0; return $a < $b ? -1 : 1; }); $ltot = 0; foreach($rows as $row) { $ltot += $row[3]; $row[4] = $ltot; fputcsv($fh, $row); } */ /* } */ exit; echo '';print_r($data); exit; } function fcsv($fn) { $handle = fopen($fn, "r"); while (($data = fgetcsv($handle)) !== false) { $ret[] = $data; } return $ret; } function fullTx($loc,$pods) { // old style lists.. return array(array('old style tx log')); } /* process: we have a list of location / products that do not match 1. load the full tx list from the database. (grouping by day) from both databases. 2. load the csv for that. 3. compare the day change totals 4. any day that does not match - output the tx records from our system - output the tx records from netsuite (csv) */ function processMismatch($loc, $prods) { // we need to cache the results from this.. $cache = '/tmp/stock-'. $loc . '-' . date('Y-m-d'); if (file_exists($cache)) { return unserialize(file_get_contents($cache)); } $loc_data = $this->loadCSV($loc ); if (empty($loc_data)) { //echo "SKIP - not data for $loc\n"; $ret = array(array("LOCATION: $loc")); foreach($prods as $prod) { $ret[] = array("-- ONLY XT DATA: $prod"); $data =$this->xtData($loc, $prod,false); $head = false; foreach($data as $tx) { if (!$head) { $ret[] = array_keys($tx); $head = true; } $ret[] = array_values($tx); } } file_put_contents($cache,serialize($ret)); exit(' Processing more data...... ('. $loc .') '); exit; echo "DONE CACHE $loc\n";exit; return $ret; } $ourtx = $this->txRecords($loc, $prods); $sd = strtoupper(array_pop(explode('xtuple', HTML_FlexyFramework::get()->database))); $lprefix = preg_match('/(lsg\.php|lhk.php)$/', $this->baseURL) ? 'l' : ''; $other = (array) json_decode(file_get_contents( "http://localhost/xtuple/{$lprefix}sg.php/Xtuple/VerifyMigrate?loc=".urlencode($loc).'&prods='.implode(',', $prods))); // merge them.. foreach($other as $prod=>$data) { $data = (array) $data; foreach($data as $day=>$qty) { if (isset($ourtx[$prod][$day])) { $ourtx[$prod][$day] += $qty; continue; } $ourtx[$prod][$day] = $qty; } } $ret = array(); //print_R($ourtx);exit; // we should now have day summaries for them all.. compare it to the data in the database. foreach($ourtx as $prod=>$data) { if (!isset($loc_data[$prod])) { // $ret[] = array("NO location data for $loc / $prod"); // continue; } $prod_data = isset($loc_data[$prod]) ? $loc_data[$prod] : array(); // echo "$prod\n"; $bad_day = array(); $prod_changes = $this->dayChanges($prod_data); //echo "XTUPLE:\n"; //print_R($data); //echo "NS:\n"; //print_R($prod_changes); foreach($prod_changes as $day =>$qty) { if (!isset($data[$day]) || $data[$day] != $qty) { $ns = isset($data[$day] ) ? $data[$day] : 0 ; //echo "$day : XTUPLE: $qty : NS $ns\n"; $bad_day[] = $day; } } foreach($data as $day =>$qty) { if (!isset($prod_changes [$day]) || $prod_changes [$day] != $qty) { $xt = isset($prod_changes [$day] ) ? $prod_changes [$day] : 0 ; //echo "$day : XTUPLE: $xt : NS $qty\n"; $bad_day[] = $day; } } $bad_day = array_unique($bad_day); $bad_days[$prod] = $bad_day; //print_R($bad_day);exit; } // we now have a list of bad days for that product.. // print_r($bad_days); foreach($bad_days as $prod => $days) { $prod_data = isset($loc_data[$prod]) ? $loc_data[$prod] : array(); $ret[] = array(); $ret[] = array('LOCATION : ' . $loc . ' Product : ' . $prod); $ret[] = array("--- NETSUITE: "); $head =false; foreach($days as $day) { $day_data = isset($prod_data[$day]) ? $prod_data[$day] : array(); foreach($day_data as $tx) { if (!$head) { $ret[] = array_keys($tx); $head = true; } $ret[] = array_values($tx); } // now dump the data from } $ret[] = array(); $ret[] = array("--- MIGRATED: "); $head =false; foreach($days as $day) { $day_data = isset($prod_data[$day]) ? $prod_data[$day] : array(); $data = $this->xtData($loc, $prod, $day); foreach($data as $tx) { if (!$head) { $ret[] = array_slice(array_keys($tx), 0,7); $head = true; } $ret[] = array_values($tx); } // now dump the data from } $ret[] = array(); $ret[] = array(); } file_put_contents($cache,serialize($ret)); exit(''); echo "DONE CACHE $loc\n";exit; return $ret; print_R($ret); exit; exit; } function xtData($loc, $prod,$day) { //var_dump($loc); $locs = $this->txRecordsAll($loc,$prod,$day); $sd = strtoupper(array_pop(explode('xtuple', HTML_FlexyFramework::get()->database))); $lprefix = preg_match('/(lsg\.php|lhk.php)$/', $this->baseURL) ? 'l' : ''; //echo "http://localhost/xtuple/{$lprefix}sg.php/Xtuple/VerifyMigrate?loc=".urlencode($loc).'&prod='.$prod.'&day='.$day; //print_r($loc);exit; $remote = (array) json_decode(file_get_contents( "http://localhost/xtuple/{$lprefix}sg.php/Xtuple/VerifyMigrate?loc=".urlencode($loc).'&prod='.$prod . ($day !== false ? ('&day='.$day) : ''))); foreach($remote as $line) { $locs[] = (array)$line; } //print_r($locs);exit; $GLOBALS['_DB_DATAOBJECT']['RESULTFIELDS'] = array(); $GLOBALS['_DB_DATAOBJECT']['RESULTS'] = array(); return $locs; } function txRecordsAll($loc, $prod, $day) { $ret = array(); //DB_DataObject::debugLevel(1); $d = DB_DataObject::factory('invdetail'); $d->autoJoin(); $d->applyFilters(array( 'query' => array( 'item_number'=> trim($prod), 'location_name'=> trim($loc), ), '_with_item'=>'1', ),$this->authUser, $this); if ($day !== false) { $d->whereAdd("invhist_transdate::date = '$day'"); } $d->selectAdd(); $d->selectAdd(' join_invhist.invhist_transdate, join_invhist.invhist_docnumber, join_invhist.invhist_ordnumber, invdetail_qty , invdetail_bydate(invdetail_id) AS invdetail_bydate_qty , join_invhist.invhist_comments '); $d->orderBy('invdetail_id ASC'); return $d->fetchAll(false,false, 'toArray'); } function txRecords($loc, $prods) { $ret = array(); foreach($prods as $prod) { // DB_DataObject::debugLevel(1); $d = DB_DataObject::factory('invdetail'); $d->autoJoin(); $d->applyFilters(array( 'query' => array( 'item_number'=> trim($prod), 'location_name'=> trim($loc), ), '_with_item'=>'1', ),$this->authUser, $this); $d->orderBy('invhist_transdate ASC'); $d->selectAdd(); $d->selectAdd('distinct(invhist_transdate::date) as invhist_transdate, sum(invdetail_qty) as invdetail_qty'); $d->groupBy('invhist_transdate'); $ret[$prod] = $d->fetchAll('invhist_transdate', 'invdetail_qty'); //exit; } return $ret; } function dayChanges($cvsdata) { foreach($cvsdata as $day => $rows) { $qty = 0; foreach($rows as $row) { $qty += $row['Qty.']; } $ret[$day] = $qty; } return $ret; } // returns array of day -> [ tx, tx, tx ] function loadCSV($loc) { $file = '/home/alan/netsuite_accounts/iad-'. $loc. '.csv'; if (!file_exists($file)) { // echo "NO FILE: $file\n"; $files[$loc]= array(); return array(); } $fh = fopen($file ,'r'); if (!$fh) { die("failed to open $file\n"); } $head = false; $out = array(); $product = false; while (false !== ($row = fgetcsv($fh, 4000))) { if ($head === false) { if (trim($row[0]) != 'Item') { continue; } $head = array(); foreach($row as $v) { $head[] = trim($v); } continue; } // print_R($head);exit; $line = array(); // skip the intro line. if ($row[0] == 'Inventory Item') { continue; } if (preg_match('/^Total /', $row[0])) { continue; } if (!strlen(trim($row[1]))) { // then it's a new product. $product = $row[0]; $out[$product] = array( ); continue; } if (empty($product)) { continue; } // got a normal line. $day = date('Y-m-d', strtotime(implode('-', array_reverse(explode('/', $row[1]))))); if (!isset($out[$product][$day])) { $out[$product][$day] = array(); } foreach($head as $i=>$k) { if ($k == 'Date') { $line[$k] = date('Y-m-d', strtotime(implode('-', array_reverse(explode('/', $row[$i]))))); continue; } $line[$k] = trim($row[$i]); } $out[$product][$day][] = $line; } //print_R($out);exit; return $out; } }