How can I access the names of variant products in Shopware 6? - shopware

How can I get the name of a variant product via the product repository? So for example t-shirt L. Or only the option.
This is my code:
$cri2 = new Criteria();
$cri2->addFilter(new EqualsFilter('parentId', $itemProductId));
$cri2->addFilter(new EqualsFilter("active", 1));
$cri2->addFilter(new RangeFilter('stock', [ 'gt' => 0 ]));
I need the name of this option:

I believe the confusion is here:
Just note that this is not the name of the variant, it's just it's options concatenated as preview.
You can see inn the picture below that the actual name is null & therefore inherits the parents' name:
If you change the name from the variant product, then it will not be null anymore.
To create an actual name you will have to manually pull its options using associations. Here is an example of a query you might be looking for. After you get the data, just create the name yourself out of the variation data. High chance that this is how Shopware6 does it in the picture provided.
$criteria = (new Criteria()
// loads non-child products
->addFilter(new EqualsFilter('product.parentId', null))
->addAssociations([
'options',
'variation',
'children',
'children.options',
'children.properties',
'children.properties.group'
])

When you want to search for a specific name you can use
$cri2->addFilter(new EqualsFilter('name', 't-shirt L'));
When you want to search for the option name instead you can use
$cri2->addFilter(new EqualsFilter('options.option.name', 't-shirt L'));
When you don't want to search by name, but only what to get the name of a given product:
$product = $this->productRepository->search($cri2, $context)->getFirst();
echo $product->getName();

The finished code is:
$cri = new Criteria();
$cri->addFilter(new EqualsFilter('parentId', "[YOUR PARENT ID]"));
// Add options to associations
$cri->addAssociations([
'options'
]);
// Loop through variant products
foreach ($productRepository->search($cri, $context)->getElements() as &$variantRawItem) {
// Map all options to array
$options = array_map(function ($n) {
return $n->get('translated')['name'];
}, $variantRawItem->get('options')->getElements());
// Create the options title
$optionsTitle = implode(', ', $options);
// $optionsTitle is now e.g.: L, Lila
}

Related

setting context with list of objects as prameters in dialogflow

I have a list of values each having another KEY value corresponding to it, when i present this list to user, user has to select a value and agent has to call an external api with selected value's KEY. how can i achieve this in dialogflow?
I tried to send the entire key value pair in the context and access it in the next intent but for some reason when i set a list(array) to context parameters dialogflow simply ignoring the fulfillment response.
What is happening here and is there any good way to achieve this? I am trying to develop a food ordering chatbot where the category of items in menu is presented and list items in that menu will fetched when user selects a category, this menu is not static thats why i am using api calls to get the dynamic menu.
function newOrder(agent)
{
var categories = []
var cat_parameters = {}
var catarray = []
const conv = agent.conv();
//conv.ask('sure, select a category to order');
agent.add('select a category to order');
return getAllCategories().then((result)=>{
for(let i=0; i< result.restuarantMenuList.length; i++)
{
try{
var name = result.restuarantMenuList[i].Name;
var catid = result.restuarantMenuList[i].Id;
categories.push(name)
//categories.name = catid
cat_parameters['id'] = catid;
cat_parameters['name'] = name
catarray.push(cat_parameters)
}catch(ex)
{
agent.add('trouble getting the list please try again later')
}
}
agent.context.set({
name: 'categorynames',
lifespan: 5,
parameters: catarray, // if i omit this line, the reponse is the fultillment response with categories names, if i keep this line the reponse is fetching from default static console one.
})
return agent.add('\n'+categories.toString())
})
function selectedCategory(agent)
{
//agent.add('category items should be fetched and displayed here');
var cat = agent.parameters.category
const categories = agent.context.get('categorynames')
const cat_ob = categories.parameters.cat_parameters
// use the key in the catarray with the parameter cat to call the external API
agent.add('you have selected '+ cat );
}
}
The primary issue is that the context parameters must be an object, it cannot be an array.
So when you save it, you can do something like
parameters: {
"cat_parameters": catarray
}
and when you deal with it when you get the reply, you can get the array back with
let catarray = categories.parameters.cat_parameters;
(There are some other syntax and scoping issues with your code, but this seems like it is the data availability issue you're having.)

Magento admin, short by position and name

I want to, in the admin, sort by position and, when some products share the same, sort them by name.
catalog > manage categories > "Select categorie" > Category Products > sort by position
But I can't find the method that do the work. Any idea?
More or less all the sorting stuff are in:
app/code/core/Mage/Adminhtml/Block/Widget/Grid.php
And the function I was looking for (already modified to fit my pourpouse):
protected function _setCollectionOrder($column)
{
$collection = $this->getCollection();
if ($collection) {
$columnIndex = $column->getFilterIndex() ?
$column->getFilterIndex() : $column->getIndex();
$collection->setOrder($columnIndex, strtoupper($column->getDir()))
->setOrder('entity_id', 'asc'); // new line
}
return $this;
}

How to access 'Abbreviation' field of a custom list in NetSuite custom lists

I have a custom list that is used as a matrix option of Inventory item. Its 'Color'. This custom list has an abbreviation column. I am creating a saved search on item and using Color field(join) and trying to access 'Abbreviation' field of color.
Abbreviation on custom list is available on when 'Matrix Option List' is checked.
Can someone please help me achieve this? I tried to do this through script and it seems like we cannot access 'Abbreviation' column through script. I also tried to use script to write a search directly on 'Color' - custom list and get the 'abbreviation' through search columns. It did not work. Is there a way to access 'Abbreviation' from custom lists?
Thanks in Advance
You can access it via suitescript by using the record type "customlist" and the internal id of the list like so:
var rec = nlapiLoadRecord('customlist', 5);
var abbreviation = rec.getLineItemValue('customvalue', 'abbreviation', 1);
nlapiLogExecution('DEBUG', 'abbreviation', abbreviation);
Keep in mind that the third argument of getLineItemValue is the line number, not the internal ID of the item in the list. If you want to find a specifc line item, you may want to use rec.findLineItemValue(group, fldnam, value).
Unfortunately, it doesn't look like this translates to saved searches. The suiteanswer at https://netsuite.custhelp.com/app/answers/detail/a_id/10653 has the following code:
var col = new Array();
col[0] = new nlobjSearchColumn('name');
col[1] = new nlobjSearchColumn('internalid');
var results = nlapiSearchRecord('customlist25', null, null, col);
for ( var i = 0; results != null && i < results.length; i++ )
{
var res = results[i];
var listValue = (res.getValue('name'));
var listID = (res.getValue('internalid'));
nlapiLogExecution('DEBUG', (listValue + ", " + listID));
}
However, whatever part of the application layer translates this into a query doesn't handle the abbreviation field. One thing to keep in mind is that the 'custom list' record is basically a header record, and each individual entry is it's own record that ties to it. You can see some of the underlying structure here, but the takeaway is that you'd need some way to drill-down into the list entries, and the saved search interface doesn't really support it.
I could be wrong, but I don't think there's any way to get it to execute in a saved search as-is. I thought the first part of my answer might help you find a workaround though.
Here is a NetSuite SuiteScript 2.0 search I use to find the internalId for a given abbreviation in a custom list.
/**
* look up the internal id value for an abbreviation in a custom list
* #param string custom_list_name
* #param string abbreviation
* #return int
* */
function lookupNetsuiteCustomListInternalId( custom_list_name, abbreviation ){
var internal_id = -1;
var custom_list_search = search.create({
type: custom_list_name,
columns: [ { name:'internalId' }, { name:'abbreviation' } ]
});
var filters = [];
filters.push(
search.createFilter({
name: 'formulatext',
formula: "{abbreviation}",
operator: search.Operator.IS,
values: abbreviation
})
);
custom_list_search.filters = filters;
var result_set = custom_list_search.run();
var results = result_set.getRange( { start:0, end:1 } );
for( var i in results ){
log.debug( 'found custom list record', results[i] );
internal_id = results[i].getValue( { name:'internalId' } );
}
return internal_id;
}
Currently NetSuite does not allows using join on matrix option field. But as you mentioned, you can use an extra search to get the result, you could first fetch color id from item and then use search.lookupFields as follows
search.lookupFields({ type: MATRIX_COLOR_LIST_ID, id: COLOR_ID, columns: ['abbreviation'] });
Note: Once you have internalid of the color its better to use search.lookupFields rather than creating a new search with search.create.

Using CSOM in C# to Dynamically Load Project Server Columns From Selected Rows

I use CSOM .NET to load task objects from Project Server 2013, and I need to
filter tasks so that only a subset of them is returned, and
load only a subset of task columns, specified at runtime by the user.
I found this post that shows how to load a dynamic set of columns, and it works nicely for my second requirement. However, I cannot figure out a workable LINQ syntax to combine both column selection and row filtering.
In the example below, I need to load only those "rows" for summary tasks (where t.IsSummary is true), and I want to load only the Name, Start, and Finish columns.
The following code from the referenced post loads just the three columns that I need:
foreach (string fieldName in new List<string>(){"Name","Start","Finish"});
{
ctx.Load(ctx.Tasks,c => c.Include(t => t[fieldName]));
}
ctx.ExecuteQuery();
But when I try to combine where() and include() in the only syntax that makes sense to me, I get InvalidQueryExpressionException on second iteration through the foreach loop: "The query expression is not supported."
foreach (string fieldName in new List<string>(){"Name","Start","Finish"});
{
ctx.Load(ctx.Tasks,
c => c.Where(t => t.IsSummary),
c => c.Include(t => t[fieldName])
);
}
ctx.ExecuteQuery();
I get the same error if I reverse the order of where and include clauses. If I pull the where clause outside of the loop over field names and make it a separate Load call, the summary-task row filtering works, but I lose the dynamic selection of tasks fields. There must be a syntax in LINQ for CSOM that meets both requirements. What is the correct syntax to do this type of query?
The following example demonstrates how to apply select and filter operators in SharePoint CSOM API:
var list = ctx.Web.Lists.GetByTitle(listTitle);
var items = list.GetItems(CamlQuery.CreateAllItemsQuery());
var result = ctx.LoadQuery(items.Where(i => (bool)i["IsSummary"]).Include(i => i["Name"], i => i["Start"], i => i["Finish"]));
ctx.ExecuteQuery();
foreach (var item in result)
{
Console.WriteLine(item["Name"]);
}
So, i believe the following expression is supported in Project Server CSOM API:
var result = ctx.LoadQuery(ctx.Tasks.Where(t => (bool)t["IsSummary"]).Include(t => i["Name"], t => t["Start"], t => t["Finish"]));
ctx.ExecuteQuery();
I answered this myself by using expression trees, which let you filter a set of rows and select a set of columns based on parameters that are only known at runtime. In the example below, I simulate finding out at runtime that I need to filter the tasks on the IsSummary column and that I should retrieve only the five columns Id, Name, Start, IsSubProject, and Finish. Here's the code:
using System.Linq.Expressions;
// Input parms discovered at runtime
string filterColumnName = "IsSummary";
List<string> columnNames = new List<string>(
new[] { "Id", "Name", "Start", "IsSubProject", "Finish" });
// Get the client object for the Published Project matching projGuid
ctx.Load(ctx.Projects, c => c.Where(p => p.Id == projGuid));
ctx.ExecuteQuery();
PublishedProject proj = ctx.Projects.Single();
// Compute the expression tree for filtering the task rows
var taskParm = Expression.Parameter(typeof(PublishedTask), "t");
var predicate = Expression.PropertyOrField(taskParm, filterColumnName);
var filterExpression = Expression.Lambda<
Func<PublishedTask, bool>>(predicate, taskParm);
// Dynamically generate expression tree for each column to be included
var colSelectionList = new List<Expression<
Func<PublishedTask, object>>>();
foreach (var colName in columnNames)
{
var fldExpr = Expression.PropertyOrField(taskParm, colName);
var fldAsObjExpr = Expression.Convert(fldExpr, typeof(object));
var colSelectorExpr = Expression.Lambda<
Func<PublishedTask, object>>(fldAsObjExpr, taskParm);
colSelectionList.Add(colSelectorExpr);
}
// Create query using LoadQuery (Load does not work here)
var taskList = ctx.LoadQuery(proj.Tasks
.Where(filterExpression)
.Include(colSelectionList.ToArray())
);
// Execute the query
ctx.ExecuteQuery();
// taskList now contains just the filtered rows and selected columns
I hope this helps someone else who is stuck on using CSOM to do this for Project Server. I found these two references helpful:
At MSDN
and at Second Life of a Hungarian SharePoint Geek
..Jim

Is there any way to create matrix items using suite script?

Basically my requirement is to create a matrix item through the script. I'm wondering if is there any way to create a matrix item through Restlet or any Workflow. I succeeded creating the parent item with some specific attributes but it seems after submitting the record there is no child items getting created.
Bellow is the code snippet what I'm using right now.
var record= nlapiCreateRecord('serviceitem');
record.setFieldValue('name', 'Matrix Parent Record');
record.setFieldValue('matrixtype', 'PARENT');
record.setFieldValue('custitem_matrix_op1', '2');
record.setFieldValue('custitem_matrix_op2', '3');
var id=nlapiSubmitRecord(record);
Any help or suggestions would be appreciated.
Thank You.
Little example:
var parent = nlapiCreateRecord('noninventoryitem');
parent.setFieldValue('matrixtype', 'PARENT');
parent.setFieldValue('itemid', 'zzz ttt');
parent.setFieldValue('subsidiary', 2);// internalid for subs.
parent.setFieldValue('taxschedule', 4);// internalid for N/A in my account
parent.setFieldValues('itemoptions', ['CUSTCOL_LLL_EVENTLOCATION_OPT']);//option to be shown at PDP
parent.setFieldValue('custitem_event_location', 11);// particular option id (see in your list)
var parentid = nlapiSubmitRecord(parent);
var child = nlapiCreateRecord('noninventoryitem');
child.setFieldValue('matrixtype', 'CHILD');
child.setFieldValue('parent', parentid);
child.setFieldValue('itemid', 'zzz ttt child');
child.setFieldValue('taxschedule', 4);// internalid for N/A in my account
child.setFieldValues('itemoptions', ['CUSTCOL_LLL_EVENTLOCATION_OPT']);// same as in parent record
child.setFieldValue('matrixoptioncustitem_event_location', 11);// same as in parent record
var childid = nlapiSubmitRecord(child );
It will create a matrix with one child item.
Do not forget to set up additional fields like price and "display in web store" (isonline field).
After creating the parent item, you need to create child item as well,In the child item set the parent item internal ID & submit the record.
but here there is a drawback. because of static sub list, am not able to append the child items to parent in the Matrix sub list.
Using Suite Talk you could do something like this
/** Create Sweaters as matrix items.
* First create the parent - no matrix properties except "Matrix Type" is Parent
* Second create the matrix children with a combination of sizes and colors.
* This can be done in a single addList (as shown).
*/
//Define mrr method
public static RecordRef mrr(String internalId)
{
RecordRef toRet = new RecordRef();
toRet.setInternalId(internalId);
return toRet;
}
// Define makeListOrRecordRef method
public static ListOrRecordRef makeListOrRecordRef(String sTypeId, String internalId, String sName)
{
ListOrRecordRef toRet = new ListOrRecordRef();
toRet.setInternalId(internalId);
toRet.setName(sName);
toRet.setTypeId(sTypeId);
return toRet;
}
public void testMatrixSample() throws Exception
{
// Color is a Custom List of TypeId/RecType 1 that has already been created. 1,2,3 represent the
// internalIds of Red, Green, Blue
ListOrRecordRef[] colorArray = new
ListOrRecordRef[] {makeListOrRecordRef("1","1","Red"), makeListOrRecordRef("1","2","Green"),
makeListOrRecordRef("1","3","Blue")}; // Representing red, green and blue
// Size is a CustomList of TypeId/RecType 2 that has already been created
ListOrRecordRef[] sizeArray = new ListOrRecordRef[]{makeListOrRecordRef("2","2","Large"),makeListOrRecordRef("2","3","Small")};
//Representing large and small
InventoryItem[] toSubmit = new InventoryItem[1+colorArray.length*sizeArray.length];
toSubmit[0] = new InventoryItem();
toSubmit[0].setExternalId("parentSweater");
toSubmit[0].setItemId("sweater");
toSubmit[0].setMatrixType(ItemMatrixType._parent);
// set other fields on the Parent
for (int i=0;i<colorArray.length*sizeArray.length;i++)
{
toSubmit[i+1] = new InventoryItem();
toSubmit[i+1].setMatrixType(ItemMatrixType._child);
// mrr Creates a recordRef given an internal and externalId, the latter of which we specify.
// This makes it so we can submit all the records at once
toSubmit[i+1].setParent(mrr((String)null,"parentSweater"));
// "sweater-large-red","sweater-large-green"...
toSubmit[i+1].setItemId("sweater-"+colorArray[i%3].getName() + "-" +
sizeArray[i % 2].getName());
// set externalId so it's easier to find later
toSubmit[i+1].setExternalId(toSubmit[i+1].getItemId());
// CUSTITEM_COLOR,SIZE are the names of the Item Custom Fields, applied to
//InventoryItem that were setup as a Matrix types.
SelectCustomFieldRef colorRef = new SelectCustomFieldRef();
colorRef.setInternalId("CUSTITEM_COLOR");
colorRef.setValue(colorArray[i%3]);
SelectCustomFieldRef sizeRef = new SelectCustomFieldRef();
sizeRef.setInternalId("CUSTITEM_SIZE");
sizeRef.setValue(sizeArray[i%2]);
toSubmit[i+1].setMatrixOptionList(new MatrixOptionList(new
SelectCustomFieldRef[]{colorRef,sizeRef}));
// Set other matrix item child files
//....
}
WriteResponseList wr = c.getPort().addList(toSubmit);
}

Resources