How to fix integration issue Magento store with POS system after site migration? - api

We migrated our Magento site (Magento 1.8.1.0) from old server to a new server.
But, we can't use the Winepos integration extension any more.
Our site is connected with Winepos system, and this Magento extension had been operated before migrating work.
This is Winepos API manual.
At this time, we think some PHP modules were not installed on our new server.
But, we don't know which PHP modules were not installed. It seems all PHP modules were installed on our new server.
The Magento extension to integrate with Winepos are as follow. This extension is consisted with two files.
Config.xml
<config>
<global>
<events>
<checkout_onepage_controller_success_action>
<observers>
<igor_winepos_order_success_observer>
<type>singleton</type>
<class>igor_Winepos_Model_Wineposobserver</class>
<method>checkoutSuccessObserve</method>
</igor_winepos_order_success_observer>
</observers>
</checkout_onepage_controller_success_action>
</events>
</global>
</config>
wineposobserver.php
class igor_Winepos_Model_Wineposobserver extends Varien_Event_Observer {
function customlog($obj) {
ob_start();
var_dump($obj);
$out1 = ob_get_contents();
ob_end_clean();
$f = fopen('/tmp/log.txt', 'ab');
fwrite($f, $out1);
fclose($f);
}
public function __construct() {
}
public function checkoutSuccessObserve($observer) {
// $event = $observer->getEvent();
$order_ids = $observer->getData('order_ids');
if(gettype($order_ids) == 'array' && count($order_ids) == 1) {
$the_order = Mage::getModel('sales/order')->load($order_ids[0]);
Mage::helper('globalfunc')->registerOrderWithWinePOSAsynchronousWithTimeout($the_order);
}
}
}
I am getting the following in the Apache log:
PHP Warning: PHP Startup: apc.shm_segments setting ignored in MMAP mode in Unknown on line 0 [Sun Apr 30 06:32:30 2017] [notice] Apache/2.2.22 (Ubuntu) mod_ssl/2.2.22 OpenSSL/1.0.1 configured -- resuming normal operations
285: function registerOrderWithWinePOSAsynchronousWithTimeout($the_order) {
286 try {
287 $items = $the_order->getAllItems();
...
426 $ordered_raw_item = $ordered_products_raw_items[$ordered_product_id];
428: $product_winepos_id = trim(strval($product->getResource()->getAttribute('winepos_id')->getFrontend()->getValue($product)));
429
430 $item_element = $doc->createElement('item');
432 $item_num_element = $doc->createElement('item-num');
433: $item_num_element->appendChild($doc->createTextNode(strval($product_winepos_id)));
434 $item_element->appendChild($item_num_element);
...
466 $the_xml = $doc->saveXML();
468: // $post_result = Mage::helper('globalfunc')->post_to_api_winepos('https://wines-in-november.vznlink.com/orders', $the_xml, 'admin276975', '8dc670fb943dc2c0a1415405cdf00e3ec579c4e6', 8, 10);
470: return Mage::helper('globalfunc')->delayed_post_to_winepos($the_xml);
471 } catch(Exception $e) {
472 $this->customlog($e);
...
475 }

I created a new module to integrate with POS system and implemented inventory synchronization successfully.
This work should be done by cron job. To do it, I created three individual script files.
Also, POS provider should provide ordered product information including inventory information as txt file via ftp in every time interval.
lftp -u [username],[password] -e'set ftp:passive-mode false; cd files; put data.txt; quit' [folder name]
The cron job operating blocks are as follow.
cron_file_mover.php
$start = microtime(true);
shell_exec('cp /home/files/data.txt /var/www/vhosts/magento/');
shell_exec('chown -R www-data:www-data /var/www/vhosts/magento/');
$end = microtime(true);
echo 'Run time: '.round($end-$start, 4).'s';
cron_pos_post_script.php
Utils::initMagento(); $MAX_RETRIES = 5;
$delayed_jobs = Utils::mageGetRows("select * from delayed_jobs where job_type = 'pos_order' and status = 'todo' order by created_at DESC");
$current_index = 0;
foreach($delayed_jobs as $delayed_job) {
$current_index += 1;
$retry_count = intval($delayed_job['retry_count']);
$retry_count += 1;
$post_result = Mage::helper('globalfunc')->post_to_api_pos('https://vznlink.com/orders', $delayed_job['job_details'], 'admin', 'fd93d2de58ab', 8, 10);
Utils::mageSqlExecute("update delayed_jobs set status = 'done' where id = " . $delayed_job['id']);
Utils::mageSqlExecute("update delayed_jobs set status = '" . $new_status . "', retry_count = " . $retry_count . " where id = " . $delayed_job['id']);
}
cron_pos_update_script.php
$PATH_TO_FILE = '/var/www/vhosts/magento/data.txt';
function read_pos_file($path_to_file) {
$min_count_required_for_product = 12;
$f = fopen($path_to_file, 'rb');
$text = trim(fread($f, 100000000));
fclose($f);
$lines = preg_split('/\r\n|\r|\n/i', $text);
$products = array();
foreach($lines as $line) {
$product = preg_split('/\t/i', trim($line));
if(count($product) >= $min_count_required_for_product) {
$product[0] = strval(trim($product[0]));
$product[1] = strval(trim($product[1]));
$product[2] = strval(trim($product[2]));
$product[11] = intval(strval(trim($product[11])));
$products []= $product;
}
}
return $products;
}
function update_stock_for_stock_item($product_id, $new_stock) {
$stock_item = Mage::getModel('cataloginventory/stock_item')->loadByProduct($product_id);
$stock_item->setData('qty', $new_stock);
if($new_stock > 0) {
$stock_item->setData('is_in_stock', 1);
}
$stock_item->save();
}
$products = read_pos_file($PATH_TO_FILE);
$total_count = 0; $processed_count = 0;
foreach($products as $product) {
$total_count += 1;
$item_number = $product[0];
$new_stock = $product[11];
if($new_stock < 0) {
$new_stock = 0;
}
$products_matching_item_number = Mage::getModel('catalog/product')->getCollection()->addAttributeToSelect('pos_id')->addFieldToFilter('pos_id', $item_number)->getItems();
if(count($products_matching_item_number) == 1) {
$products_matching_item_number = array_values($products_matching_item_number);
$matching_product = $products_matching_item_number[0];
$matching_product_id = $matching_product->getId();
update_stock_for_stock_item($matching_product_id, $new_stock);
$processed_count += 1;
}
}
The cron job settings are as follows.
10 * * * * /usr/bin/php /var/www/vhosts/magento/pos/cron_winepos_post_script.php &> /dev/null
10 * * * * /usr/bin/php /var/www/vhosts/magento/pos/cron_winepos_update_script.php &> /dev/null
20 * * * * /usr/bin/php /var/www/vhosts/magento/pos/cron_pos_file_mover.php &> /dev/null
Keep in mind, checking POS data provided from POS system, cron job setting, checking update script operations.

Related

How to automate synchronizing Windows 10 guest's time with the Linux host?

On Arch Linux I have a Windows 10 Guest on top of libvirt, kvm and virsh (still having some trouble to connect all these dots mentally together). Every time I suspend the laptop and a day is gone the Windows 10 host goes out of sync. I learned that with the following command I can force a time sync in the host:
➜ ~ virsh qemu-agent-command win10 '{"execute":"guest-set-time"}'
{"return":{}}
In order to make this work I modifed the clock XML block and added a kvm clock entry. This is how the block looks like now:
<clock offset="localtime">
<timer name="tsc" tickpolicy="delay"/>
<timer name="kvmclock"/>
<timer name="rtc" tickpolicy="delay" track="wall"/>
<timer name="pit" tickpolicy="delay"/>
<timer name="hpet" present="yes"/>
</clock>
I would like to know whether I can automate this step or trigger an update everytime I wake up the machine or log-in.
Thanks in advance
I was not able to get anywhere specifically using virsh. Here is how I fixed this issue in a Windows 11 guest on MacOS in UTM 3.6.4 and 4.1.5.
At first I tried many workarounds using w32tm - but this was always flaky.
This helped slightly:
disable "use local time for base clock" (otherwise you can't add a manual -rtc argument if using UTM)
add -rtc base=localtime,driftfix=slew
This wasn't great, because it won't recover a significant delta.
This is the solution I settled on (run in the Windows guest). It creates a scheduled task that runs every 5 minutes, gets the time from NTP, converts it to local time, measures the drift, and if the drift is >30 seconds in either direction it updates the system clock.
function Get-NtpTime
{
[OutputType([datetime])]
[CmdletBinding()]
param
(
[string]$Server = "time.nist.gov",
[int]$Port = 13
)
if (-not $PSBoundParameters.ContainsKey('ErrorAction'))
{
$ErrorActionPreference = 'Stop'
}
$Client = [Net.Sockets.TcpClient]::new($Server, $Port)
$Reader = [IO.StreamReader]::new($Client.GetStream())
try
{
$Response = $Reader.ReadToEnd()
$UtcString = $Response.Substring(7, 17)
$LocalTime = [datetime]::ParseExact(
$UtcString,
"yy-MM-dd HH:mm:ss",
[cultureinfo]::InvariantCulture,
[Globalization.DateTimeStyles]::AssumeUniversal
)
}
finally
{
$Reader.Dispose()
$Client.Dispose()
}
$LocalTime
}
function Register-TimeSync
{
[CmdletBinding()]
param
(
[Parameter()]
[timespan]$RepetitionInterval = (New-TimeSpan -Minutes 5),
[Parameter()]
[timespan]$ExecutionTimeLimit = (New-TimeSpan -Minutes 3)
)
$Invocation = {
$NtpTime = Get-NtpTime
$Delta = [datetime]::Now - $NtpTime
if ([Math]::Abs($Delta.TotalSeconds) -gt 30)
{
Set-Date $NtpTime
}
}
$PSName = if ($PSVersionTable.PSVersion.Major -le 5) {'powershell'} else {'pwsh'}
$Path = (Get-Command $PSName).Source
$Command = Get-Command Get-NtpTime
$Definition = "function Get-NtpTime`n{$($Command.Definition)}"
$Invocation = $Definition, $Invocation -join "`n"
$Bytes = [Text.Encoding]::Unicode.GetBytes($Invocation)
$Encoded = [Convert]::ToBase64String($Bytes)
$TriggerParams = #{
Once = $true
At = [datetime]::Today
RepetitionInterval = $RepetitionInterval
}
$Trigger = New-ScheduledTaskTrigger #TriggerParams
$Action = New-ScheduledTaskAction -Execute $Path -Argument "-NoProfile -EncodedCommand $Encoded"
$Settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit $ExecutionTimeLimit -MultipleInstances IgnoreNew
$Principal = New-ScheduledTaskPrincipal -UserID "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount -RunLevel Highest
$RegisterParams = #{
TaskName = "Update system time from NTP"
Trigger = $Trigger
Action = $Action
Settings = $Settings
Principal = $Principal
Force = $true
}
Register-ScheduledTask #RegisterParams
}
Usage (run as admin):
Register-TimeSync

Cant create new entry. PHPLDAPADMIN

I just installed LDAP and PHPLDAPADMIN.Its work fine but when I want Create new entry page just refresh and nothing happend.There are a few errors:
Unrecognized error number: 8192: Function create_function() is deprecated
Errors in phpldapadmin
Thank you.
Try this code working fine.
/usr/share/phpldapadmin/lib/functions.php on line 54
change line 54 to
function my_autoload($className) {
Add this code on line 777
spl_autoload_register("my_autoload");
change line 1083 to
$CACHE[$sortby] = __create_function('$a, $b',$code);
add the code below on line 1091 from the
function __create_function($arg, $body) {
static $cache = array();
static $maxCacheSize = 64;
static $sorter;
if ($sorter === NULL) {
$sorter = function($a, $b) {
if ($a->hits == $b->hits) {
return 0;
}
return ($a->hits < $b->hits) ? 1 : -1;
};
}
$crc = crc32($arg . "\\x00" . $body);
if (isset($cache[$crc])) {
++$cache[$crc][1];
return $cache[$crc][0];
}
if (sizeof($cache) >= $maxCacheSize) {
uasort($cache, $sorter);
array_pop($cache);
}
$cache[$crc] = array($cb = eval('return
function('.$arg.'){'.$body.'};'), 0);
return $cb;
}
finally restart your apache server sudo service apache2 restart
PhpLdapAdmin uses a few functions which are deprecated in PHP 7.2. Take a look at this fix:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=890127

Puppet: Syntax error with '$x.each...'

I have the code below:
define keepalived::vrrp_instance(
$state,
$interface,
$virtual_addresses,
$virtual_router_id,
$priority = $::keepalived::params::priority,
$advert_int = $::keepalived::params::advert_int,
$password = $::keepalived::params::password,
$notify_master = $::keepalived::params::notify_master,
$notify_backup = $::keepalived::params::notify_backup,
$notify_fault = $::keepalived::params::notify_fault,
$notify_all = $::keepalived::params::notify_all,
$smtp_alert = $::keepalived::params::smtp_alert,
) {
...
$virtual_addresses.each |$address| {
$splitted_address = split($address,' ')
if !is_ip_address($splitted_address[0]) {
fail("Error virtual_address Value: \"${address}\" not an ip address!")
}
}
...
}
$virtual_addresses is something like ['127.0.0.1 dev eth0','fd00::1 dev eth0']
Running the code I get the following error:
Syntax error at '.'; expected '}' at /etc/puppet/environments/ip6_dev/modules_custom/keepalived/manifests/vrrp_instance.pp:136 on node
Line 136 is "$virtual_addresses.each |$address| {"
I can't find a mistake (https://docs.puppetlabs.com/references/3.stable/function.html#each)
I am using Puppet 3.3.2
"note requires parser = future"
Ensure you are using future parser in puppet.
Set parser = future in your puppet.conf file or add the command line switch --parser=future
UPDATE:
Wrap your verification function:
define verify::wrapper ()
{
$ip_address = split($name,' ')
if !is_ip_address("${ip_address[0]}") {
fail("Error virtual_address Value: \"${ip_address[0]}\" not an ip address!")
}
}
Next use it:
define keepalived::vrrp_instance(...)
{
...
verify::wrapper{ $virtual_addresses : }
...
}

Efficient Way to do batch import XMI in Enterprise Architect

Our team are using Enterprise Architect version 10 and SVN for the repository.
Because the EAP file size is quite big (e.g. 80 MB), we exports each packages into separate XMI and stored it into SVN. The EAP file itself is committed after some milestone. The problem is to synchronize the EAP file with work from co worker during development, we need to import lots of XMI (e.g. total can be 500 files).
I know that once the EAP file is updated, we can use Package Control -> Get All Latest. Therefore this problem occurs only during parallel development.
We have used keyboard shorcuts to do the import as follow:
Ctrl+Alt+I (Import package from XMI file)
Select the file name to import
Alt+I (Import)
Enter (Yes)
Repeat step number 2 to 4 until module finished
But still, importing hundreds of file is inefficient.
I've checked that the Control Package has Batch Import/Export. The batch import/export are working when I explicitly hard-coded the XMI Filename, but the options are not available if using version control (batch import/export options are greyed).
Is there any better ways to synchronize EAP and XMI files?
There is a scripting interface in EA. You might be able to automate the import using that. I've not used it but its probably quite good.
I'm not sure I fully understand your working environment, but I have some general points that may be of interest. It might be that if you use EA in a different way (especially my first point below), the need to batch import might go away.
Multiworker
First, multiple people can work on the same EAP file at a time. The EAP file is nothing more than an Access database file, and EA uses locking to stop multiple people editing the same package at the same time. But you can comfortably have multiple people editing different packages in one EAP file at the same time. Putting the EAP file on a file share somewhere is a good way of doing it.
Inbuilt Revision Control
Secondly, EA can interact directly with SVN (and other revision control systems). See this. In short, you can setup your EAP file so that individual packages (and everything below them) is SVN controlled. You can then check out an individual package, edit it, check it back in. Or indeed you can check out the whole branch below a package (including sub packages that are themselves SVN controlled).
Underneath the hood EA is importing and exporting XMI files and checking them in and out of SVN, whilst the EAP file is always the head revision. Just like what you're doing by hand, but automated. It makes sense given that you can all use the one single EAP file. You do have to be a bit careful rolling back - links originating from objects in older versions of one package might be pointing at objects that no longer exist (but you can look at the import log errors to see if this is the case). It takes a bit of getting used to, but it works pretty well.
There's also the built in package baselining functionality - that might be all you need anyway, and works quite well especially if you're all using the same EAP file.
Bigger Database Engine
Thirdly, you don't have to have an EAP file at all. The model's database can be in any suitable database system (MySQL, SQL Server, Oracle, etc). So that gives you all sorts of options for scaling up how its used, what its like over a WAN/Internet, etc.
In short Sparx have been quite sensible about how EA can be used in a multi-worker environment, and its worth exploiting that.
I have created the EA script using JScript for the automation
Here is the script to do the export:
!INC Local Scripts.EAConstants-JScript
/*
* Script Name : Export List of SVN Packages
* Author : SDK
* Purpose : Export a package and all of its subpackages information related to version
* controlled. The exported file then can be used to automatically import
* the XMIs
* Date : 30 July 2013
* HOW TO USE : 1. Select the package that you would like to export in the Project Browser
* 2. Change the output filepath in this script if necessary.
* By default it is "D:\\EAOutput.txt"
* 3. Send the output file to your colleague who wanted to import the XMIs
*/
var f;
function main()
{
// UPDATE THE FOLLOWING OUTPUT FILE PATH IF NECESSARY
var filename = "D:\\EAOutput.txt";
var ForReading = 1, ForWriting = 2, ForAppending = 8;
Repository.EnsureOutputVisible( "Script" );
Repository.ClearOutput( "Script" );
Session.Output("Start generating output...please wait...");
var treeSelectedType = Repository.GetTreeSelectedItemType();
switch ( treeSelectedType )
{
case otPackage:
{
var fso = new ActiveXObject("Scripting.FileSystemObject");
f = fso.OpenTextFile(filename, ForWriting, true);
var selectedObject as EA.Package;
selectedObject = Repository.GetContextObject();
reportPackage(selectedObject);
loopChildPackages(selectedObject);
f.Close();
Session.Output( "Done! Check your output at " + filename);
break;
}
default:
{
Session.Prompt( "This script does not support items of this type.", promptOK );
}
}
}
function loopChildPackages(thePackage)
{
for (var j = 0 ; j < thePackage.Packages.Count; j++)
{
var child as EA.Package;
child = thePackage.Packages.GetAt(j);
reportPackage(child);
loopChildPackages(child);
}
}
function getParentPath(childPackage)
{
if (childPackage.ParentID != 0)
{
var parentPackage as EA.Package;
parentPackage = Repository.GetPackageByID(childPackage.ParentID);
return getParentPath(parentPackage) + "/" + parentPackage.Name;
}
return "";
}
function reportPackage(thePackage)
{
f.WriteLine("GUID=" + thePackage.PackageGUID + ";"
+ "NAME=" + thePackage.Name + ";"
+ "VCCFG=" + getVCCFG(thePackage) + ";"
+ "XML=" + thePackage.XMLPath + ";"
+ "PARENT=" + getParentPath(thePackage).substring(1) + ";"
);
}
function getVCCFG(thePackage)
{
if (thePackage.IsVersionControlled)
{
var array = new Array();
array = (thePackage.Flags).split(";");
for (var z = 0 ; z < array.length; z++)
{
var pos = array[z].indexOf('=');
if (pos > 0)
{
var key = array[z].substring(0, pos);
var value = array[z].substring(pos + 1);
if (key=="VCCFG")
{
return (value);
}
}
}
}
return "";
}
main();
And the script to do the import:
!INC Local Scripts.EAConstants-JScript
/*
* Script Name : Import List Of SVN Packages
* Author : SDK
* Purpose : Imports a package with all of its sub packages generated from
* "Export List Of SVN Packages" script
* Date : 01 Aug 2013
* HOW TO USE : 1. Get the output file generated by "Export List Of SVN Packages" script
* from your colleague
* 2. Get the XMIs in the SVN local copy
* 3. Change the path to the output file in this script if necessary (var filename).
* By default it is "D:\\EAOutput.txt"
* 4. Change the path to local SVN
* 5. Run the script
*/
var f;
var svnPath;
function main()
{
// CHANGE THE FOLLOWING TWO LINES ACCORDING TO YOUR INPUT AND LOCAL SVN COPY
var filename = "D:\\EAOutput.txt";
svnPath = "D:\\svn.xxx.com\\yyy\\docs\\design\\";
var ForReading = 1, ForWriting = 2, ForAppending = 8;
Repository.EnsureOutputVisible( "Script" );
Repository.ClearOutput( "Script" );
Session.Output("[INFO] Start importing packages from " + filename + ". Please wait...");
var fso = new ActiveXObject("Scripting.FileSystemObject");
f = fso.OpenTextFile(filename, ForReading);
// Read from the file and display the results.
while (!f.AtEndOfStream)
{
var r = f.ReadLine();
parseLine(r);
Session.Output("--------------------------------------------------------------------------------");
}
f.Close();
Session.Output("[INFO] Finished");
}
function parseLine(line)
{
Session.Output("[INFO] Parsing " + line);
var array = new Array();
array = (line).split(";");
var guid;
var name;
var isVersionControlled;
var xmlPath;
var parentPath;
isVersionControlled = false;
xmlPath = "";
for (var z = 0 ; z < array.length; z++)
{
var pos = array[z].indexOf('=');
if (pos > 0)
{
var key = array[z].substring(0, pos);
var value = array[z].substring(pos + 1);
if (key=="GUID") {
guid = value;
} else if (key=="NAME") {
name = value;
} else if (key=="VCCFG") {
if (value != "") {
isVersionControlled = true;
}
} else if (key=="XML") {
if (isVersionControlled) {
xmlPath = value;
}
} else if (key=="PARENT") {
parentPath = value;
}
}
}
// Quick check for target if already exist to speed up process
var targetPackage as EA.Package;
targetPackage = Repository.GetPackageByGuid(guid);
if (targetPackage != null)
{
// target exists, do not do anything
Session.Output("[DEBUG] Target package \"" + name + "\" already exist");
return;
}
var paths = new Array();
var packages = new Array(paths.Count);
for (var i = 0; i < paths.Count; i++)
{
packages[i] = null;
}
paths = (parentPath).split("/");
if (paths.Count < 2)
{
Session.Output("[INFO] Skipped root or level1");
return;
}
packages[0] = selectRoot(paths[0]);
packages[1] = selectPackage(packages[0], paths[1]);
if (packages[1] == null)
{
Session.Output("[ERROR] Cannot find " + paths[0] + "/" + paths[1] + "in Project Browser");
return;
}
for (var j = 2; j < paths.length; j++)
{
packages[j] = selectPackage(packages[j - 1], paths[j]);
if (packages[j] == null)
{
Session.Output("[DEBUG] Creating " + packages[j].Name);
// create the parent package
var parent as EA.Package;
parent = Repository.GetPackageByGuid(packages[j-1].PackageGUID);
packages[j] = parent.Packages.AddNew(paths[j], "");
packages[j].Update();
parent.Update();
parent.Packages.Refresh();
break;
}
}
// Check if name (package to import) already exist or not
var targetPackage = selectPackage(packages[paths.length - 1], name);
if (targetPackage == null)
{
if (xmlPath == "")
{
Session.Output("[DEBUG] Creating " + name);
// The package is not SVN controlled
var newPackage as EA.Package;
newPackage = packages[paths.length - 1].Packages.AddNew(name,"");
Session.Output("New GUID = " + newPackage.PackageGUID);
newPackage.Update();
packages[paths.length - 1].Update();
packages[paths.length - 1].Packages.Refresh();
}
else
{
// The package is not SVN controlled
Session.Output("[DEBUG] Need to import: " + svnPath + xmlPath);
var project as EA.Project;
project = Repository.GetProjectInterface;
var result;
Session.Output("GUID = " + packages[paths.length - 1].PackageGUID);
Session.Output("GUID XML = " + project.GUIDtoXML(packages[paths.length - 1].PackageGUID));
Session.Output("XMI file = " + svnPath + xmlPath);
result = project.ImportPackageXMI(project.GUIDtoXML(packages[paths.length - 1].PackageGUID), svnPath + xmlPath, 1, 0);
Session.Output(result);
packages[paths.length - 1].Update();
packages[paths.length - 1].Packages.Refresh();
}
}
else
{
// target exists, do not do anything
Session.Output("[DEBUG] Target package \"" + name + "\" already exist");
}
}
function selectPackage(thePackage, childName)
{
var childPackage as EA.Package;
childPackage = null;
if (thePackage == null)
return null;
for (var i = 0; i < thePackage.Packages.Count; i++)
{
childPackage = thePackage.Packages.GetAt(i);
if (childPackage.Name == childName)
{
Session.Output("[DEBUG] Found " + childName);
return childPackage;
}
}
Session.Output("[DEBUG] Cannot find " + childName);
return null;
}
function selectRoot(rootName)
{
for (var y = 0; y < Repository.Models.Count; y++)
{
root = Repository.Models.GetAt(y);
if (root.Name == rootName)
{
return root;
}
}
return null;
}
main();

Magento 1.6, Google Shopping / Products / Content

Magento 1.6 was out at the beginning of this week but upgrading from 1.5.1 with the mage_googleshopping extension (http://www.magentocommerce.com/magento-connect/Magento+Core/extension/6887/mage_googleshopping) up to v.1.6 was not something feasible.
mage_googleshopping remained compatible only with 1.5. Any working alternative to have the mage_googleshopping extension available on a clean Magento 1.6 installation or we have to wait for a stable extension release which goes with v.1.6?
Cheers,
Bogdan
I have browsed the Internet and searched for a problem to this, eventually I've turned into this script which runes separately but it connects to the Magento DB. The scripts generates the file, which can be uploaded following a schedule to Google.
Besides the fact that the script is totally editable, you can fully monitor all the processes behind it. The Magento script still can't be removed from a 1.6 Magento version.
The script wasn't developed by me but I did update it according with the latest rules enforced from 22/9/2011 by Google.
<code>
<?php
define('SAVE_FEED_LOCATION','google_base_feed.txt');
set_time_limit(1800);
require_once '../app/Mage.php';
Mage::app('default');
try{
$handle = fopen(SAVE_FEED_LOCATION, 'w');
$heading = array('id','mpn','title','description','link','image_link','price','brand','product_type','condition', 'google_product_category', 'manufacturer', 'availability');
$feed_line=implode("\t", $heading)."\r\n";
fwrite($handle, $feed_line);
$products = Mage::getModel('catalog/product')->getCollection();
$products->addAttributeToFilter('status', 1);
$products->addAttributeToFilter('visibility', 4);
$products->addAttributeToSelect('*');
$prodIds=$products->getAllIds();
$product = Mage::getModel('catalog/product');
$counter_test = 0;
foreach($prodIds as $productId) {
if (++$counter_test < 30000){
$product->load($productId);
$product_data = array();
$product_data['sku'] = $product->getSku();
$product_data['mpn'] = $product->getSku();
$title_temp = $product->getName();
if (strlen($title_temp) > 70){
$title_temp = str_replace("Supply", "", $title_temp);
$title_temp = str_replace(" ", " ", $title_temp);
}
$product_data['title'] = $title_temp;
$product_data['description'] = substr(iconv("UTF-8","UTF-8//IGNORE",$product->getDescription()), 0, 900);
$product_data['Deeplink'] = "http://www.directmall.co.uk/".$product->getUrlPath();
$product_data['image_link'] = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA).'catalog/product'.$product->getImage();
$price_temp = round($product->getPrice(),2);
$product_data['price'] = round($product->getPrice(),2) + 5;
$product_data['brand'] = $product->getData('brand');
$product_data['product_type'] = 'Laptop Chargers & Adapters';
$product_data['condition'] = "new";
$product_data['category'] = $product_data['brand'];
$product_data['manufacturer'] = $product_data['brand'];
$product_data['availability'] = "in stock";
foreach($product_data as $k=>$val){
$bad=array('"',"\r\n","\n","\r","\t");
$good=array(""," "," "," ","");
$product_data[$k] = '"'.str_replace($bad,$good,$val).'"';
}
echo $counter_test . " ";
$feed_line = implode("\t", $product_data)."\r\n";
fwrite($handle, $feed_line);
fflush($handle);
}
}
fclose($handle);
}
catch(Exception $e){
die($e->getMessage());
}</code>
Change www.directmall.co.uk into what you need.
Assign the proper permissions.
Fully updated according with Google's requirements.