Magento observer (sales_order_grid_collection_load_before), filter collection by a product attribute - magento-1.5

So I'm working with sales_order_grid_collection_load_before observer event at the moment, where I can get the collection being used through $collection = $observer->getEvent()->getOrderGridCollection();, I'm just wondering, if it is possible to filter this collection by a product from the order attribute.
What I mean with that is the order grid collection has sub products related to that order, I need to only show orders if at least one of the products match a specific criteria (in my case, I've given the products an admin_id attribute, which is set to the administrator who added the product).
Thanks!

I've done a very similar thing by doing the following:
Override the sales order grid block. To do this you will need to set up your own extension (it looks like you might already be doing this, but just in case, there is some handy doco in the Magento wiki)
<config>
<modules>
<Company_Module>
<version>0.1.0</version>
</Company_Module>
</modules>
<global>
<blocks>
<company_module>
<class>Company_Module_Block</class>
</company_module>
<adminhtml>
<rewrite>
<sales_order_grid>Company_Module_Block_Sales_Order_Grid</sales_order_grid>
</rewrite>
</adminhtml>
</blocks>
</global>
</config>
I then copied the /app/code/core/Mage/Adminhtml/Block/Sales/Order/Grid.php into my extensions folder at /app/code/local/Company/Module/Block/Sales/Order
In the copied file I changed the class name to class Company_Module_Block_Sales_Order_Grid extends Mage_Adminhtml_Block_Widget_Grid
I then changed the _prepareCollection function. In this case I was interested in grabbing the customer_group_id and customer_email from the sales_flat_order table
protected function _prepareCollection() {
$collection = Mage::getResourceModel($this->_getCollectionClass());
// left join onto the sales_flat_order table, retrieving the customer_group_id and customer_email columns -< this can be expanded
$collection->getSelect()->join('sales_flat_order', 'main_table.entity_id=sales_flat_order.entity_id', array('customer_group_id'=>'customer_group_id', 'customer_email'=>'customer_email'), null, 'left');
// grab the current user and get their associated customer groups (additional coding required to associate the customer groups to an admin user
$user = Mage::getSingleton('admin/session')->getUser();
$roleId = implode('', $user->getRoles());
$customerGroupIds = Mage::getModel('admin/roles')->load($roleId)->getCustomerGroupIds();
$orders = Mage::getResourceModel('sales/order_collection');
// if the admin user has associated customer group ids then find the orders associated with those
// this would be where you would do your filtering of the products
if (count($customerGroupIds)) {
$orders->addAttributeToFilter('customer_group_id', array('in' => $customerGroupIds));
}
$orderIds = $orders->getAllIds();
$collection->addAttributeToFilter('entity_id', array('in' => $orderIds));
$this->setCollection($collection);
return parent::_prepareCollection();
}
You may not need the join to the sales_flat_order table...you might be able to do it just by doing the filtering in the second part of the _prepareCollection function shown above. In my case, I was displaying the customer_group_id and the customer_email in the grid so that the user could manually filter, if required.

I am not sure if you can access directly the product from the order_grid_collection (I don't think so) but you can join this collection with sales_flat_order_item and then filter as you wish.
HTH

Related

How to get source list types of particular list/record field?

Here is I have two entity custom fields with list/record type,
custom_dev_j15 entity field has a custom source list (eg: one, two, three, four, etc)
custom_qa_v93 entity field has a standard source list as an object (eg: customer )
I've two vendor entity custom fields as stated in screenshots of question,
custentity473 --> customer is selected as list source
custentity474 --> custom_dev_j15_m_list as selected as list source ( which is custom list)
Here is snippet that i used to get the options of these fields,
// Snippet
var fieldDetails = {};
var record = nlapiCreateRecord("Vendor");
var field = record.getField("custentity473");
var selectoptions = field.getSelectOptions();
for ( var i in selectOptions) {
var Option = {
id : selectOptions[i].getId(),
label : selectOptions[i].getText()
}
Options.push(Option);
}
fieldDetail["options"] = Options;
But my need is to get source list information like name of the list source (customer or custom_dev_j15_m_list) via suitescript
any idea on how to get this information?
Thanks in advance
I'm not sure I understand this question for what you're trying to do.
In NetSuite almost always, you accommodate to the source list types because you know that's the type, and if you need something else (e.g. a selection which is a combination/or custom selection you'll use a scripted field)
Perhaps you can expand on your use case, and then we can help you further?

How do I do a joined lookup with search.lookupFields()?

I'm trying to get some information about an item, including the item's subsidiary's logo, which naturally requires joining the item to the subsidiary.
The documentation for search.lookupFields says:
You can use joined-field lookups with this method, with the following syntax:
join_id.field_name
So, I duly request the fields I want, including a join on subsidiary:
require(['N/search'], function(search) {
var item = search.lookupFields({
type: search.Type.ITEM,
id: 2086,
columns: ['itemid', 'displayname', 'subsidiary.logo'],
});
log.debug(item);
});
itemid and displayname are fine, but when I try to join another record I get this error:
{
"type":"error.SuiteScriptError",
"name":"SSS_INVALID_SRCH_COLUMN_JOIN",
"message":"An nlobjSearchColumn contains an invalid column join ID, or is not in proper syntax: logo.",
"stack":["doLookupFields(N/search/searchUtil.js)","<anonymous>(adhoc$-1$debugger.user:2)","<anonymous>(adhoc$-1$debugger.user:1)"],
"cause":{
"type":"internal error",
"code":"SSS_INVALID_SRCH_COLUMN_JOIN",
"details":"An nlobjSearchColumn contains an invalid column join ID, or is not in proper syntax: logo.",
"userEvent":null,
"stackTrace":["doLookupFields(N/search/searchUtil.js)","<anonymous>(adhoc$-1$debugger.user:2)","<anonymous>(adhoc$-1$debugger.user:1)"],
"notifyOff":false
},
"id":"",
"notifyOff":false,
"userFacing":false
}
This seems to happen no matter which record and field I try to join. What am I missing?
Although you can return results from multi-select fields, you cannot join to fields on records referenced by multi-select fields (which the subsidiary field on the item record is). Also, you cannot search the logo field on the subsidiary record (not listed in Search Columns under Subsidiary in the NetSuite Records Browser).
This means you have to load the Subsidiary record to get the logo field. In other words:
require(['N/record', 'N/search'], function(record, search) {
var item = search.lookupFields({
type: search.Type.ITEM,
id: 2086,
columns: ['itemid', 'displayname', 'subsidiary'],
});
var subID = item.subsidiary[0].value; //internal id of *first* subsidiary
var subRec = record.load({
type: record.Type.SUBSIDIARY,
id: subID
});
var logo = subRec.getText('logo'); //gets the file name - use getValue to get its ID instead
});
Note that if multiple subsidiaries are set on the item, this only gets the values for the first one. You could iterate through the item.subsidiary result to handle values for multiple subsidiaries if required.
I believe you can't access to the subsidiary record from a lookupfield, you should do a proper search.
https://system.netsuite.com/help/helpcenter/en_US/srbrowser/Browser2018_2/script/record/item.html
You can only join to tables allowed in the Item search object. Try looking for "Subsidiary..." in the Search Results tab within the UI. It's not there. Use the Schema Browser to determine what fields and joins are available.
You cannot think of a NetSuite search as you would any regular SQL search. You have to be cognizant of which fields and which joins can be utilized via the search object.
As people have mentioned, the subsidiary is not a join field available from the item record, one way to achieve what you are trying to do is:
Make a lookup to get the internal id of the subsidiary belonging to the desired item.
Then make a lookup to get the internal id of the logo image (file cabinet image) belonging to the previous subsidiary.
Make another lookup/load the image file to get the URL of the image/logo
You can try to combine the above steps in a single saved search but I think you might need to load the image file to get the URL.
This won't answer your question, but this may help out in the future. The records browser shows everything that you can search and join on, columns and filters, and field IDs. Very useful when building out searches.
NetSuite Records Browser - 2018.2

loopback relational database hasManyThrough pivot table

I seem to be stuck on a classic ORM issue and don't know really how to handle it, so at this point any help is welcome.
Is there a way to get the pivot table on a hasManyThrough query? Better yet, apply some filter or sort to it. A typical example
Table products
id,title
Table categories
id,title
table products_categories
productsId, categoriesId, orderBy, main
So, in the above scenario, say you want to get all categories of product X that are (main = true) or you want to sort the the product categories by orderBy.
What happens now is a first SELECT on products to get the product data, a second SELECT on products_categories to get the categoriesId and a final SELECT on categories to get the actual categories. Ideally, filters and sort should be applied to the 2nd SELECT like
SELECT `id`,`productsId`,`categoriesId`,`orderBy`,`main` FROM `products_categories` WHERE `productsId` IN (180) WHERE main = 1 ORDER BY `orderBy` DESC
Another typical example would be wanting to order the product images based on the order the user wants them to
so you would have a products_images table
id,image,productsID,orderBy
and you would want to
SELECT from products_images WHERE productsId In (180) ORDER BY orderBy ASC
Is that even possible?
EDIT : Here is the relationship needed for an intermediate table to get what I need based on my schema.
Products.hasMany(Images,
{
as: "Images",
"foreignKey": "productsId",
"through": ProductsImagesItems,
scope: function (inst, filter) {
return {active: 1};
}
});
Thing is the scope function is giving me access to the final result and not to the intermediate table.
I am not sure to fully understand your problem(s), but for sure you need to move away from the table concept and express your problem in terms of Models and Relations.
The way I see it, you have two models Product(properties: title) and Category (properties: main).
Then, you can have relations between the two, potentially
Product belongsTo Category
Category hasMany Product
This means a product will belong to a single category, while a category may contain many products. There are other relations available
Then, using the generated REST API, you can filter GET requests to get items in function of their properties (like main in your case), or use custom GET requests (automatically generated when you add relations) to get for instance all products belonging to a specific category.
Does this helps ?
Based on what you have here I'd probably recommend using the scope option when defining the relationship. The LoopBack docs show a very similar example of the "product - category" scenario:
Product.hasMany(Category, {
as: 'categories',
scope: function(instance, filter) {
return { type: instance.type };
}
});
In the example above, instance is a category that is being matched, and each product would have a new categories property that would contain the matching Category entities for that Product. Note that this does not follow your exact data scheme, so you may need to play around with it. Also, I think your API query would have to specify that you want the categories related data loaded (those are not included by default):
/api/Products/13?filter{"include":["categories"]}
I suggest you define a custom / remote method in Product.js that does the work for you.
Product.getCategories(_productId){
// if you are taking product title as param instead of _productId,
// you will first need to find product ID
// then execute a find query on products_categories with
// 1. where filter to get only main categoris and productId = _productId
// 2. include filter to include product and category objects
// 3. orderBy filter to sort items based on orderBy column
// now you will get an array of products_categories.
// Each item / object in the array will have nested objects of Product and Category.
}

Updating sharepoint item multi lookup field via odata

I need some help sorting out some syntax for an update to a list item in sharepoint from an application. Here's a rundown on the situation :
There are two lists within this sp site. One list is a products list, and the second list is a pricing. The way these lists are setup however are a 1 to many scheme. One product can have many pricing records. The product then has a column against it that is a look up field that supports multiple values.
Using REST and oData I can query and get the pricing information easily enough now, but my problem is when I need to update the products record to add a price.
with regular lookup fields I normally just set the ID property for the object, then call the update and savechanges methods for that list. With the pricing column however supporting multiple records there is no ID to set, and the field is an array of sorts. Adding the pricing object (list item) and updating and savechanges doesn't actually save. No errors are thrown but the then when viewing the list it isn't actually saving.
How can I add a price lookup to my Product?
I wrote a small method to query through each price and add it's initial price to the product below for testing :
InventoryCatalogDataContext dc = new InventoryCatalogDataContext(_pushinTinSvc);
dc.Credentials = CredentialCache.DefaultCredentials;
List<PricingItem> pricing = (from q in dc.Pricing
select q).ToList<PricingItem>();
foreach (PricingItem price in pricing)
{
var query = (DataServiceQuery<ProductsItem>)
dc.Products
.Expand("Pricing")
.Where(p => p.Id.Equals(price.StockCodeId));
List<ProductsItem> prods = query.ToList<ProductsItem>();
ProductsItem product = prods[0];
product.Pricing.Add(price);
dc.UpdateObject(product);
}
try
{
dc.SaveChanges();
}
catch (Exception ex)
{
string stopHere = ex.Message;
}
I'm not sure if I'm doing something wrong or if this is a bug. If I inspect the item after the SaveChanges, the item still has the pricing item lookup attached, showing a count of 1. At the end of the code block, if I re-query for the product, at that point it even still has the pricing attached. But once the method finishes and returns to the UI, the pricing is no longer attached, the fields are empty when you look at the list in sharepoint, but the version does increment. So I'm a little lost...

Query Trac for all tickets related to a user

How do I query for all trac tickets related to a user. i.e. all tickets for which the tickets were once assigned, assigned now, created , etc etc
Create custom queries to the ticket_change table. Some SQL required. For assigned once/now, look for rows where field='owner', newvalue column contains the user name the ticket was assigned to. For created tickets, just query by reporter in the ticket table.
Example:
SELECT p.value AS __color__,
id AS ticket, summary, component, version, milestone,
t.type AS type, priority, t.time AS created,
changetime AS _changetime, description AS _description,
reporter AS _reporter
FROM ticket t, enum p, ticket_change c
WHERE p.name = t.priority AND p.type = 'priority'
AND c.field = 'owner'
AND c.newvalue = '$USER'
AND c.ticket = t.id
ORDER BY p.value, milestone, t.type, t.time
You can express this with a TraqQuery expression. E.g. if you want the columns id, summary and status to show up and query all the tickets for the currently logged in user ($USER) then use the following query.
query:?col=id
&
col=summary
&
col=status
&
owner=$USER
However this query assumes that the owner hasn't been the same during the lifetime of a ticket (since ownership can be changed).
If you want a specific user then replace $USER with the actual username. Also if you're using the Agilo plugin you can easily create new queries on the fly via the web-UI. This is done by looking at a report and adding filters to the report.

Resources