Woocommerce and WPML: Creating and traducing products - wordpress

When I create a product with the methods of "WC_Product" with WPML enabled by default Woo creates it in the English language.
How can I determine the product creation language?
$product = new WC_Product;
$product->set_name('My test product');
$product->set_slug('test-product');
$product->set_description('This is my test product');
$product->set_sku('some_sku');
$product->save();
Thanks for your help!

I done it with the methods from $sitepress object:
global $sitepress;
// Create the product in defaul language
// First switch de language for the product to create
$language_code_default = 'es';
$sitepress->switch_lang($language_code_default);
// Create product with de Woo methods
$product_es = new WC_Product;
$product_es->set_name('PRODUCTO EN ESPAÑOL');
$product_es->set_slug('producto-wc');
$product_es->set_description('Este producto ha sido creado con WC_Product');
$product_es->set_short_description('Este producto ha sido creado con WC_Product');
$post_id_es = $product_es->save();
// Create the traduction
// Remember, switch the traduction language
$language_code_tr = 'en';
$sitepress->switch_lang($language_code_tr);
$product_en = new WC_Product;
$product_en->set_name('PRODUCT IN ENGLISH');
$product_en->set_slug('producto-wc-en');
$product_en->set_description('This product was made from spanish version');
$product_en->set_short_description('This product was made from spanish version');
$post_id_en = $product_en->save();
// And use the wpml methods to link de traduction with the original language
$element_type = 'post_product';
$trid = $sitepress->get_element_trid($post_id_es, $element_type);
$sitepress->set_element_language_details($post_id_en, $element_type, $trid, $language_code_tr, $language_code_default);
// And then copy de product meta from de original to the traduction
$sitepress->copy_custom_fields($post_id_es, $post_id_en);

Related

If statement inside Wordpress Contact Form 7 E-mail Template

I'm trying to edit E-mail 2 in Contact Form 7 Wordpress plugin. I have an Option tag [salutation](Mr, Mrs), in German Language – [anrede] (Herr, Frau) So, in E-mail 2 template I have to write 2 different texts like:
Sehr geehrter Herr
Sehr geehrte Frau
The first one is when the [anrede] option is 'Herr', and the other one is when the [anrede] option is 'Frau'.
if ([anrede] = "Herr"){
<p>Sehr geehrter Herr</p>
}
else if([anrede] = "Frau"){
<p>Sehr geehrte Frau</p>
}
Thank you in advance,
Jon Kraja
and if statement isn't needed, seems to me is much easier as follows and w/o plugin conditional fields.
Generate a select field with your values
--> [select anrede "Herr|geehrter" "Frau|geehrte"]
Take care, that a pipe symbol (|) is between the values as shown above.
Note: only the left side of the select field is shown on contact form!; the right side is NOT shown and always hidden. BUT you can choose both values with different codes on your Mail:
If you would put left side of value into your mail, use [_raw_anrede] - means "Herr" or "Frau" is given out.
If you would put right side of value into your mail, use [anrede] - means "geehrter" or "geehrte" is given out.
With this you may have a correct salutation depending on "Herr" or "Frau" is choosen at the select field.
You can use the hook 'wpcf7_before_send_mail'.
function hsc_cf7_submit_update_email($cf){
$formID = $cf->id();
$wpcf7 = WPCF7_ContactForm::get_current();
$submission = WPCF7_Submission::get_instance();
if (!$submission){
return;
}
if($formID == 'ENTER FORM ID'){
$submitData = $submission->get_posted_data();
$mail = $wpcf7->prop('mail_2');
$mailBody = $mail['body'];
if($submitData['anrede'][0] == 'Herr'){
$mail['body'] = "<p>Sehr geehrter Herr</p>";
$wpcf7->set_properties( array("mail_2" => $mail)) ;
}elseif($submitData['anrede'][0] == 'Frau'){
$mail['body'] = "<p>Sehr geehrte Frau</p>";
$wpcf7->set_properties( array("mail_2" => $mail)) ;
}
}else{
return;
}
}
add_action( 'wpcf7_before_send_mail', 'hsc_cf7_submit_update_email' );
That's not possible with contact form 7 alone, but you can do it with this plugin.

Filtering imageCollection from an inicial date to the latest one

I'm working on a google earth engine app. In order to let it run without code changing, i need to specify a date range to filter an ImageCollection. The inicial date should be an arbitrary one, but the last date should be the "latest" available.
It would be nice also if anybody knows how to open a dialogue to let the user specify the inicial date.
var app = function (image)
{
//NDVI
var ndvi = image.normalizedDifference(['B8', 'B4']);
image = image.addBands(ndvi.rename('NDVI'));
return image;
}
var OLI = ee.ImageCollection("COPERNICUS/S2")
.filterDate('2016-10-01','2019-01-29')
.filterMetadata('CLOUDY_PIXEL_PERCENTAGE','less_than',10)
//.map aplica la funcion "app" definida previamente a la ImageCollection
.filterBounds(table)
.map(app);

Custom item prices change in WooC

Have situation with custom price for item line in WooC.
Now find solution to change subtotal in Edit of order this way:
add_action( 'woocommerce_update_order_item', function ($_item_id, $_item, $_order_id) {
if( $arr_item_meta = wc_get_order_item_meta($_item_id) )
{
$prc = wooc_item1_price( $arr_item_meta["_a1"][0], $arr_item_meta["_a2"][0], $arr_item_meta["_a3"][0], $_item->get_product()->get_id() );
$_item -> set_total( $prc );
$_item -> set_subtotal( $prc );
$_item -> save();
}
},10,3);
This only works on edit. I.e. while updated - it set up price i make with function
wooc_item1_price with few argumens from cart (quantities of each type of product)
Problem is:
howto make same after product just added to cart.
So new subtotal+total will be available in order before any edit/updater.
Please help me!
add_action ('woocommerce_calculate_totals', function( $_cart )
{
foreach ($_cart->cart_contents as $cart_key => $cart_item)
{
$prc = function_to_make_item_custom_price(
$_cart->cart_contents[$cart_key]["_param1"],
$_cart->cart_contents[$cart_key]["_param2"],
$_cart->cart_contents[$cart_key]["_param3"],
$_cart->cart_contents[$cart_key]["product_id"]
);
$_cart->cart_contents[$cart_key]['line_subtotal'] = $prc;
$_cart->cart_contents[$cart_key]['line_total'] = $prc;
}
}, 10,1);
this is right way - make price on adding item to cart.
is need have price function function_to_make_item_custom_price to make custom price, based on parameters. In my case - this is quantites of product parts (tour adult&child&infants param1,param2,param3)
Its simplifed idea, is need also recal taxes, coupons ...

Sylius - How to assign a Channel to a Product programmatically?

I am trying to assign a Channel to my products created programmatically, so they will be displayed on shop. Unfortunately, there is no documentation for this use case.
Here is how I create my products:
$productFactory = $this->container->get('sylius.factory.product');
$productManager = $this->container->get('sylius.manager.product');
$productRepository = $this->get('sylius.repository.product');
$productVariantFactory = $this->get('sylius.factory.product_variant');
$productVariantRepository = $this->get('sylius.repository.product_variant');
$channelPricingFactory = $this->get('sylius.factory.channel_pricing');
$channelPricingRepository = $this->get('sylius.repository.channel_pricing');
//CREATE PRODUCT
$product = $factory->createNew();
$product->setName('TEST 2 - '.$title);
$product->setCode($this->generateRandomString());
$product->setSlug($this->generateRandomString());
$productRepository->add($product);
//CREATE VARIANT & ATTACH IT TO PRODUCT
$variant = $productVariantFactory->createNew();
$variant->setName('TEST 2 - '.$title);
$variant->setCode($this->generateRandomString());
$variant->setProduct($product);
$productVariantRepository->add($variant);
//CREATE PRICE & ATTACH IT TO VARIANT
$channelPricing = $channelPricingFactory->createNew();
$channelPricing->setPrice(999);
$channelPricing->setOriginalPrice(999);
$channelPricing->setChannelCode('US_WEB');
$channelPricing->setProductVariant($variant);
$channelPricingRepository->add($channelPricing);
Unfortunately, the products are not linked to a Channel:
The answer to your question:
You have one product variant, but Product variant implements ProductVariantInterface which extends TranslatableInterface. So we need one translation to make it appear and work. To add the translation:
$productVariant->setCurrentLocale('fr_FR');
$productVariantTranslation = $productVariant->getTranslation();
or
$productVariantTranslation = $productVariant->getTranslation($locale);
after you can add a name or not:
$productVariantTranslation->setName('What a product variant!');
after:
$product->addVariant($productVariant);
$this->entityManager->persist($product);
You will have your product variant on line.
Another thing is that:
$channelPricingRepository = $this->get('sylius.repository.channel_pricing');
$channelPricingRepository->add($entity);
it's going to flush directly data to DB in each call. In the example you are going to flush 3 times instead only one. In bigger proccess with many "add" this can be a lack of performance. You can simply;
$this->entityManager->persist($entity); //Many times
$this->entityManager->flush();
Here is how I managed to create my products (to attach them then to my entities):
function createProduct($livre,$options){
$title = $livre['title'];
$prix = $livre['prix'];
// SYLIUS REPOSITORIES LOAD
$productFactory = $options['sylius_factory_product'];
$productRepository = $options['sylius_repository_product'];
$productVariantFactory = $options['sylius_factory_product_variant'];
$productVariantRepository = $options['sylius_repository_product_variant'];
$channelPricingFactory = $options['sylius_factory_channel_pricing'];
$channelPricingRepository = $options['sylius_repository_channel_pricing'];
//CREATE PRODUCT
$product = $productFactory->createNew();
$product->setName($title);
$product->setCode($title.'_'.$this->generateRandomString());
$product->setSlug($title.'_'.$this->generateRandomString());
$productRepository->add($product);
//CREATE VARIANT & ATTACH IT TO PRODUCT
$variant = $productVariantFactory->createNew();
$variant->setName($title. 'Variant');
$variant->setCode($title.'_'.$this->generateRandomString());
$variant->setProduct($product);
$productVariantRepository->add($variant);
//CREATE PRICE & ATTACH IT TO VARIANT
$channelPricing = $channelPricingFactory->createNew();
$channelPricing->setPrice($prix*100);
$channelPricing->setOriginalPrice($prix*100);
$channelPricing->setChannelCode('CH');
$channelPricing->setProductVariant($variant);
$channelPricingRepository->add($channelPricing);
$productId = $product->getId();
return $productId;
}
I added the channel to the product like this:
$channelCode = 'US_WEB'
$channelRepository = $this->get('sylius.repository.channel');
$channel = $channelRepository->findOneBy(array('code' => $channelCode));
$product->addChannel($channel);

Programmatically add an invoice to Dynamics AX 2009

I'm am pretty new to Dynamics AX 2009 and since I haven't really found the way to solve what I'm doing I decided to ask here.
I have a requirement to post(?) an invoice through X++.
I already found this HOWTO: Facturación selectiva de líneas en Dynamics AX and even though it's in Spanish I think you will get the idea.
Here is the code I modified from the link:
static void JAEE_PurchFormLetter(Args _args)
{
Num _invoiceNum; // Núm. factura
TransDate _invoiceDate; // Fecha factura
MyPurchFormLetter purchFormLetter = PurchFormLetter::construct(DocumentStatus::Invoice);
PurchParmUpdate purchParmUpdate;
PurchParmTable purchParmTable;
PurchParmLine purchParmLine;
TradeLineRefId tableRefId;
PurchTable purchTable;
PurchLine purchLine;
;
ttsbegin;
_invoiceNum = 'Facbyjob';
_invoiceDate = str2date('14-01-2013', 123);
purchTable = PurchTable::find('00000019_062'); // Primer pedido
// Inizializar purchFormLetter con el primer pedido
purchFormLetter.parmCallerTable(purchTable);
purchFormLetter.callInitParmPurchTable(purchTable);
purchFormLetter.proforma(false); // Proforma: NO (Registrar: SI)
purchFormLetter.enableUpdateNowField(true); // Actualizar ahora: SI
purchFormLetter.printFormLetter(false); // Imprimir: NO
purchFormLetter.transDate(_invoiceDate); // Fecha de factura
// Inizializar purchParmUpdate con el primer pedido
purchParmUpdate.clear();
purchParmUpdate.initValue();
purchParmUpdate.ParmId = purchFormLetter.parmId();
purchParmUpdate.SumBy = AccountOrder::Account; // Agrupar por cliente
purchParmUpdate.SumNum = _invoiceNum; // Núm. Factura
purchParmUpdate.SpecQty = PurchUpdate::All; // Actualizar: Todo
purchParmUpdate.DocumentStatus = DocumentStatus::Invoice; // Tipo documento: Factura
purchParmUpdate.Proforma = NoYes::No; // Proforma: NO
purchParmUpdate.SumIncludePending = NoYes::No; // Incluir pendiente: NO
if (purchParmUpdate.validateWrite())
purchParmUpdate.insert();
else
throw Exception::Error;
purchFormLetter.purchParmUpdate(purchParmUpdate);
purchFormLetter.parmParmTableNum(purchParmUpdate.SumNum);
// Tabla temporal, se crea un registro de cabecera del primer pedido (sólo uno)
purchParmTable.clear();
purchParmTable.TableRefId = FormLetter::getTableRef();
purchFormLetter.createParmTable(purchParmTable, purchTable);
if (purchParmTable.validateWrite())
purchParmTable.insert();
else
throw Exception::Error;
tableRefId = purchParmTable.TableRefId;
// BEGIN - LINEAS
// - Repetir para cada línea que se quiera facturar y para cada una y
// - asignar las variabies purchTable y purchLine según proceda
purchParmLine.clear();
purchParmLine.initValue();
// Ajustar cantidades según necesidades
// Catnidades de compra
[purchParmLine.ReceiveNow,
purchParmLine.RemainBefore,
purchParmLine.RemainAfter] = purchFormLetter.qtyPurch(purchLine, naReal());
// Cantidades de inventario
[purchParmLine.InventNow,
purchParmLine.RemainBeforeInvent,
purchParmLine.RemainAfterInvent] = purchFormLetter.qtyInvent(purchLine, naReal());
if (purchParmLine.ReceiveNow)
{
purchParmLine.ParmId = purchParmUpdate.ParmId;
purchParmLine.initFromPurchLine(purchLine);
purchParmLine.setLineAmount();
purchParmLine.TableRefId = tableRefId;
if (purchParmLine.validateWrite())
purchParmLine.insert();
else
throw Exception::Error;
}
// END - LINEAS
// Registrar!
purchFormLetter.reArrangeNow(false); // No organizar
purchFormLetter.run();
ttscommit;
}
My question is in this line: purchFormLetter.callInitParmPurchTable(purchTable);.
Why should initParmPurchTable() be called from within a derived class of PurchFormLetter?
And also, how to accomplish this? I tried declaring my own class MyPurchFormLetter which extends PurchFormLetter, adding the callInitParmPurchTable() method but compiler tells me that the object does not have the method when I try to run the code.
It reads:
Error al ejecutar código: Object objeto no tiene el método 'callInitParmPurchTable'.
EDIT:
What I have done is add the method into the class, in such a way that callInitParmPurchTable() is part of the object. But I am leaving the question open since I don't think this is the right approach.
Have you modified PurchFormLetter::construct(DocumentStatus::Invoice); to return a MyPurchFormLetter?
Also look into the "compile forward" feature
I have found out the following:
It is correct to make a class that inherits from PurchFormLetter and implement there the method callInitParmPurchTable() which obviously is the one that executes initParmPurchTable().
Most likely the one part that I had been missing was to compile MyPurchFormLetter so that the compiler could tell the method existed.

Resources