Can't create product variant through API - api

Cant seem to create new product variant using shopify api.
This is my code:
global $shopifyClient;
$config['shopify_api_product_price'] = "/admin/products/128671451/variants.json";
$variant = array
(
'variant' => array ('price' => '3.00', 'option1' => 'test')
);
if( $shopifyClient == null )
return;
try{
$postVariant = $shopifyClient->call('POST', $config['shopify_api_product_price'], $variant);
return $postVariant;
}catch( ShopifyApiException $e ){
$e->getMessage();
}
return false;
Thanks in advance!

Related

What I did wrong with Db::getInstance()->insert('product', $dimension)); not inserting data to database?

I am developing a module that would save a custom field from product admin.. but my code is not inserting data into database.. below is my code.
public function hookActionProductUpdate($params)
{
if(Tools::isSubmit('submitDimension'))
{
$name = Tools::getValue('name');
$length = Tools::getValue('custom_length');
$width = Tools::getValue('custom_width');
if(empty($name) || !Validate::isGenericName($name))
$this->errors[] = $this->module->l('Invalid name');
if(empty($length) || !Validate::isGenericName($length))
$this->errors[] = $this->module->l('Invalid length');
if(empty($width) || !Validate::isGenericName($width))
$this->errors[] = $this->module->l('Invalid width');
if(!$this->errors)
{
$dimension = array(
'name' => $name,
'custom_length' => $length,
'custom_width' => $width
);
if(!Db::getInstance()->insert('product', $dimension));
$this->errors[] = Tools::displayError('Error while updating database');
}
}
}
Anyone can help me please..
Here is my install function
function install()
{
if (!parent::install() ||
!$this->alterProductTable() ||
!$this->registerHook('extraright') ||
!$this->registerHook('displayAdminProductsExtra') ||
!$this->registerHook('actionProductSave') ||
!$this->registerHook('actionProductUpdate') ||
!$this->registerHook('header')
)
return false;
return true;
}
Here is my alter table function
private function alterProductTable($method = 'add')
{
if($method = 'add')
$sql = '
ALTER TABLE '._DB_PREFIX_.'product
ADD COLUMN `custom_length` decimal(20,6) NOT NULL,
ADD COLUMN `custom_width` decimal(20,6) NOT NULL,
ADD COLUMN `name` VARCHAR(64) NOT NULL';
if(!Db::getInstance()->Execute($sql))
return false;
return true;
}
.. the columns are there..
And here is my display admin hook
public function hookDisplayAdminProductsExtra($params)
{
$name = Db::getInstance()->getValue('SELECT `name` FROM '._DB_PREFIX_.'product WHERE id_product = '.Tools::getValue('id_product'));
$length = Db::getInstance()->getValue('SELECT custom_length FROM '._DB_PREFIX_.'product WHERE id_product = '.(int)Tools::getValue('id_product'));
$width = Db::getInstance()->getValue('SELECT custom_width FROM '._DB_PREFIX_.'product WHERE id_product = '.(int)Tools::getValue('id_product'));
$this->context->smarty->assign(array(
'name' => $name,
'length' => $length,
'width' => $width
));
return $this->display(__FILE__, 'views/templates/hook/adminProductsExtra.tpl');
}
I have been looking at this for 2 days.. and I cant seem to find what I did wrong.. I have gone to prestashop forum but no help so far.. I hope I can get something from good people here. thanks in advance!
Do you check the Prestashop db best practice guide if not than please check first.
This is not the correct way to insert data you also need to mention fields in which you want to insert data particular table.
Best Practices of the Db Class - Prestashop
All is wrong, you are trying to insert data in a table which have many other fields required, and you are trying also to insert data in columns that doesn't exist in that table. The best way to create new products by code is using their object, like this...
$product = new Product()
$product->id_tax_rules_group = 1;
$product->redirect_type = '404';
$product->name = array(
$id_lang => 'Product name in this lang',
$id_lang => 'Product name in this lang',
);
/*
* And so on all the mandatory fields
*/
$product->save();

Yii2-How to access a variable from model to a controller?

I am working on yii2. I have came across a point in which I have to send an email to a person when a meter is installed and it's images are uploaded to the server. Fro this I have already configured the swift mailer.
There is a model named Installations which have a function which saves all the installation data.
public static function saveAll($inputs){
$coutner = 0;
$arr_status = [];
foreach ($inputs as $input) {
$s = new Installations;
foreach ((array)$input as $key => $value) {
if($key != 'image_names') {
if ($s->hasAttribute($key)) {
$s->$key = $value;
}
}
}
$user = Yii::$app->user;
if (isset($input->auth_key) && Users::find()->where(['auth_key' => $input->auth_key])->exists()) {
$user = Users::find()->where(['auth_key' => $input->auth_key])->one();
}
$s->created_by = $user->id;
if (Installations::find()->where(['ref_no' => $input->ref_no])->exists()) {
$arr_status[] = ['install_id' => $input->install_id, 'status' => 2, 'messages' => "Ref # Already exists"];
continue;
}
$s->sync_date = date('Y-m-d H:i:sā€Šā€Š');
if($s->save()){
if ($s->istallation_status == 'Installed') {
Meters::change_status_byinstall($s->meter_msn, Meters::$status_titles[4]);
}
else if ($s->istallation_status != 'Installed' && $s->comm_status =='Failed')
{
Meters::change_status_byinstall($s->meter_msn, Meters::$status_titles[5]);
}
$arr_status[] = ['install_id' => $input->install_id, 'status' => 1];
$coutner++;
if (isset($input->doc_images_name)) {
foreach ($input->doc_images_name as $img) {
$image = new InstallationImages;
$image->image_name = $img->image_name;
$image->installation_id = $s->id;
$image->save();
}
}
if (isset($input->site_images_name)) {
foreach ($input->site_images_name as $img2) {
$image2 = new InstallationImagesSite;
$image2->image_name = $img2->image_name;
$image2->installation_id = $s->id;
$image2->save();
}
}
}else{
$arr_status[] = ['install_id' => $input->install_id, 'status' => 0, 'messages' => $s->errors];
}
$status = $s->istallation_status;
$msn = $s->meter_msn;
$com = $s->comm_status;
// want to pass these variables to the controller function
}
return ['status' => 'OK', 'details' => $arr_status, 'records_saved' => $coutner];
}
Now There Is a Controller name InstallationController. This controller contains all the APIs for my mobile application. Below are two main functions in it
public function actionAddnew()
{
$fp = fopen('debugeeeeeee.txt', 'w+');
fwrite($fp, file_get_contents('php://input'));
fclose($fp);
$inputs = json_decode(file_get_contents('php://input'));
return Installations::saveAll($inputs);
}
public function actionSavephoto()
{
try {
$count = 0;
foreach ($_FILES as $f) {
$dd = pathinfo($f['name']);
if (!isset($dd['extension']) || !in_array($dd['extension'], array('jpg', 'png', 'gif'))) {
return ['status' => 'ERROR', 'uploaded_files' => $count, 'message' => 'Invalid File'];
break;
}
if (move_uploaded_file($f['tmp_name'], Installations::UPLOAD_FOLDER . $f['name'])) {
$count++;
return ['status' => 'OK', 'uploaded_files' => $count];
break;
} else {
return ['status' => 'ERROR', 'uploaded_files' => $count];
break;
}
}
} catch (Exception $x) {
return ['status' => 'ERROR', 'message' => $x->getMessage()];
}
}
The mobile application will call the Addnew() api and after that it will call the savephoto. Now I want to pass $msn,$status and $com values from the Model to the controller function Savephoto.
For this I have tried to use session variables but still I am unable to get by desired result(s).
I have also checked the question Yii, how to pass variables to model from controller?
but it didn't worked for me.
How can I achieve it?
Any help would be highly appreciated.
The only way to get those values out of saveAll() is to return them. Presently, they are defined on an object in $s that is overwritten each loop. The best way to do that seems to be creating an array outside of your foreach ($inputs... loop and appending each created Installations object.
Return that at the end, and pass it (or just the relevant element from it) into actionSavephoto() as a parameter. Then, those values will be accessible of properties of that passed object. This handling will occur in the code that is not pictured which calls actionAddNew() and then actionSavephoto()

Disable WooCommerce email notification for specific product

I can refer to this function to disable email notification:
https://docs.woocommerce.com/document/unhookremove-woocommerce-emails/
But I would like to disable it only for a specific product or, if it can be more simple, for a specific product category.
Thanks for your help
Thanks to #vidish-purohit for the help!
Here is my code to use if you need to disable admin email notification for a specific product:
function change_email_recipient_depending_of_product_id( $recipient, $order ) {
global $woocommerce;
$items = $order->get_items();
foreach ( $items as $item ) {
$product_id = $item['product_id'];
if ( $product_id == xxx ) {
$recipient = '';
}
return $recipient;
}
}
add_filter( 'woocommerce_email_recipient_new_order', 'change_email_recipient_depending_of_product_id', 10, 2 );
And if you need to disable customer email notification for a specific product:
function change_email_recipient_depending_of_product_id( $recipient, $order ) {
global $woocommerce;
$items = $order->get_items();
foreach ( $items as $item ) {
$product_id = $item['product_id'];
if ( $product_id == xxx ) {
$recipient = '';
}
return $recipient;
}
}
add_filter( 'woocommerce_email_recipient_customer_processing_order', 'change_email_recipient_depending_of_product_id', 10, 2 );
I think when you try to hook email notification from template, where you can find order, at that time emails are already sent.
You can try one thing - using recipient's hook you can remove recipient email and return empty string. Or if empty string triggers error, then you can give some dummy email.
Use this code for this:
// Change new order email recipient for registered customers
function wc_change_admin_new_order_email_recipient( $recipient, $order ) {
global $woocommerce;
// check if product in order
if ( true ) ) {
$recipient = "";
} else {
$recipient = "newbusiness#yourdomain.com";
}
return $recipient;
}
add_filter('woocommerce_email_recipient_new_order', 'wc_change_admin_new_order_email_recipient', 1, 2);
// Change new order email recipient for registered customers
function wc_change_admin_new_order_email_recipient( $recipient, $order ) {
$flagHasProduct = false;
// Get items in order
$items = $order->get_items();
// Loop for all items
foreach ( $items as $item ) {
$product_id = $item['product_id'];
// check if specific product is in order
if ( $product_id == 102 ) {
$flagHasProduct = true;
}
}
// if product is found then remove recipient
if ($flagHasProduct) {
$recipient = "";
} else {
$recipient = "newbusiness#yourdomain.com";
}
return $recipient;
}
add_filter('woocommerce_email_recipient_new_order', 'wc_change_admin_new_order_email_recipient', 1, 2);
The above code will disable the email option in the Woocommerce email setting option page.
/**
* Disable Admin email Notification for Specific Product
*/
function cstm_change_email_recipient_for_giftcard_product($recipient, $order)
{
// Bail on WC settings pages since the order object isn't yet set yet
// Not sure why this is even a thing, but shikata ga nai
$page = $_GET['page'] = isset($_GET['page']) ? $_GET['page'] : '';
if ('wc-settings' === $page) {
return $recipient;
}
// just in case
if (!$order instanceof WC_Order) {
return $recipient;
}
$items = $order->get_items();
foreach ($items as $item) {
$product_id = $item['product_id'];
if ($product_id == xxxx) {
$recipient = '';
}
return $recipient;
}
}
add_filter('woocommerce_email_recipient_new_order', 'cstm_change_email_recipient_for_giftcard_product', 10, 2);
this code works fine in latest version of Woocommerce.

how to add an image to product in prestashop

i have a pragmatically added product in my code , the product is added to presta correctly but not about its image .
here is some part of my code that i used :
$url= "localhost\prestashop\admin7988\Hydrangeas.jpg" ;
$id_productt = $object->id;
$shops = Shop::getShops(true, null, true);
$image = new Image();
$image->id_product = $id_productt ;
$image->position = Image::getHighestPosition($id_productt) + 1 ;
$image->cover = true; // or false;echo($godyes[$dt][0]['image']);
if (($image->validateFields(false, true)) === true &&
($image->validateFieldsLang(false, true)) === true && $image->add())
{
$image->associateTo($shops);
if (! self::copyImg($id_productt, $image->id, $url, 'products', false))
{
$image->delete();
}
}
but my product have not any image yet
the problem is in copyImg method ...
here is my copyImg function :
function copyImg($id_entity, $id_image = null, $url, $entity = 'products')
{
$tmpfile = tempnam(_PS_TMP_IMG_DIR_, 'ps_import');
$watermark_types = explode(',', Configuration::get('WATERMARK_TYPES'));
switch ($entity)
{
default:
case 'products':
$image_obj = new Image($id_image);
$path = $image_obj->getPathForCreation();
break;
case 'categories':
$path = _PS_CAT_IMG_DIR_.(int)$id_entity;
break;
}
$url = str_replace(' ' , '%20', trim($url));
// Evaluate the memory required to resize the image: if it's too much, you can't resize it.
if (!ImageManager::checkImageMemoryLimit($url))
return false;
// 'file_exists' doesn't work on distant file, and getimagesize make the import slower.
// Just hide the warning, the traitment will be the same.
if (#copy($url, $tmpfile))
{
ImageManager::resize($tmpfile, $path.'.jpg');
$images_types = ImageType::getImagesTypes($entity);
foreach ($images_types as $image_type)
ImageManager::resize($tmpfile, $path.'-'.stripslashes($image_type['name']).'.jpg', $image_type['width'],
$image_type['height']);
if (in_array($image_type['id_image_type'], $watermark_types))
Hook::exec('actionWatermark', array('id_image' => $id_image, 'id_product' => $id_entity));
}
else
{
unlink($tmpfile);
return false;
}
unlink($tmpfile);
return true;
}
can anybody help me ?
You have 2 issues:
You are passing 5th parameter (with value) to copyImg, while the function does not have such.
Your foreach ($images_types as $image_type) loop must include the Hook as well (add open/close curly braces).
foreach ($images_types as $image_type)
{
ImageManager::resize($tmpfile, $path.'-'.stripslashes($image_type['name']).'.jpg', $image_type['width'], $image_type['height']);
if (in_array($image_type['id_image_type'], $watermark_types))
Hook::exec('actionWatermark', array('id_image' => $id_image, 'id_product' => $id_entity));
}
You should also check if the product is imported correctly, expecially the "link_rewrite" and if the image is phisically uploaded in the /img/ folder.

Magento API, Return Orders with NULL values

Using the magento api version 1 and soap.
Need to return all orders with 'coupon_code'=> NULL
The call I'm attempting:
$order_listAR = $proxy->call($sessionId, 'sales_order.list', array(array('coupon_code'=>array('null'=>'null'))));
The ouput I want returned is this:
array(237) {
["state"]=>
string(8) "complete"
["status"]=>
string(8) "complete"
["coupon_code"]=> NULL
So far this seems to work properly, but I'm not sure if ('null'=>'null') is the proper way to find NULL values in the array. Can someone explain why this works, and, or if this is the correct syntax? I don't have any margin for error on this.
Yes, the syntax you use is correct to filter against null.
array(
'coupon_code' => array(
'null' => 'this_value_doesnt_matter'
)
)
Magento maps* the API method sales_order.list to Mage_Sales_Model_Order_Api::items().
public function items($filters = null)
{
:
$collection = Mage::getModel("sales/order")->getCollection()
:
if (is_array($filters)) {
try {
foreach ($filters as $field => $value) {
if (isset($this->_attributesMap['order'][$field])) {
$field = $this->_attributesMap['order'][$field];
}
$collection->addFieldToFilter($field, $value);
}
} catch (Mage_Core_Exception $e) {
$this->_fault('filters_invalid', $e->getMessage());
}
}
:
}
The items() method uses a Mage_Sales_Model_Resource_Order_Collection to fetch the orders for the API call. That collection is based on Varien_Data_Collection_Db, so
$collection->addFieldToFilter($field, $value)
from above essentially does call
Varien_Data_Collection_Db::addFieldToFilter()
If you follow the latter, you'll hit Varien_Db_Adapter_Pdo_Mysql::prepareSqlCondition() in the end, params being
$fieldName = 'coupon_code'
$condition = array('null' => 'null')
Excerpt of that method:
public function prepareSqlCondition($fieldName, $condition)
{
$conditionKeyMap = array(
'eq' => "{{fieldName}} = ?",
:
'notnull' => "{{fieldName}} IS NOT NULL",
'null' => "{{fieldName}} IS NULL",
:
'sneq' => null
);
:
$query = '';
if (is_array($condition)) {
:
$key = key(array_intersect_key($condition, $conditionKeyMap));
if (isset($condition['from']) || isset($condition['to'])) {
:
} elseif (array_key_exists($key, $conditionKeyMap)) {
$value = $condition[$key];
if (($key == 'seq') || ($key == 'sneq')) {
:
}
$query = $this->_prepareQuotedSqlCondition($conditionKeyMap[$key], $value, $fieldName);
} else {
:
}
}
:
}
In your case _prepareQuotedSqlCondition() will be called with
$text = '{{fieldName}} IS NULL'
$value = 'null'
$fieldName = 'coupon_code'
which will result in $query = 'coupon_code IS NULL'.
If you take a closer look at the conversion method
protected function _prepareQuotedSqlCondition($text, $value, $fieldName)
{
$sql = $this->quoteInto($text, $value);
$sql = str_replace('{{fieldName}}', $fieldName, $sql);
return $sql;
}
you'll also see, why the value of the 'null' => 'null' key/value pair does not matter at all. That's because $text will be '{{fieldName}} IS NULL', i.e. not containing any binding ?.
Hence, there's nothing to replace for _quoteInto()^^
* see app/code/core/Mage/Sales/etc/api.xml