Kentico Ecommerce: getting top selling categories - e-commerce

I am using Kentico 7.0, ecommerce version.
I would like to create a sidebar menu that shows the eshop's top selling product categories. I am a kentico newbie so I am looking around for the correct terminology/guidance so that I can dig deeper.
The ideal approach in my opinion would be to be able to add a field on categories, which is used to filter categories for the menu. This way I can either have some kind of job that updates the fields automatically based on sales, OR provide a manual override for an admin to specify whether a category will show up on the menu. Of course some kind of weight would also be needed to specify menu item ordering.
Which way should I look?

HAve you tried using the "Top N products by sales" web part that is available? you can configure from which part of the content tree (products) it should pull the data - in the Path property you can use also a path expression or macro that is resolved dynamically so the web part can display different products in different sections.

There are many ways to code for Kentico. I personally find the API is a bit clunky and on quite a few occasions I was surprised that a method didn't exist requiring extra calls to get the required results. I do use the Kentico API more when putting data in to Kentico. Pulling it out I use the following.
STORED PROC
Write a SQL stored procedure to get the top X categories - GetTop5Categories.
Look at the COM_* tables, specifically COM_OrderItem, linking OrderItemSKUID back to COM_SKU (or View_COM_SKU_Joined if you need to get to the IA).
This will get you the top selling products with a group by, a count, a top X and an order by.
Then you can link to other tables such as CMS_Category or CMS_Document (depending on how you setup your categories). The bonus of this is that procs are compiled, you do all your data manipulation there (it's what MSSQL specialises in!) and you only send back what you need to in the result set.
DOMAIN (leveraging EF)
I usually create a separate class library project myproject.domain and put an Entity Framework edmx in there mapped back to the Kentico DB. Add the proc to the EDMX, then create a Function Import MyProject_GetTop5Categories from your newly imported proc.
WEB
add a reference to the domain project from your web project, and a 'using at the top of the codebehind of the control.
using myproject.domain;
then in Page_Load for the control:
...
if(!IsPostBack)
{
var entities = new MyProjectModelContainer();
var list = entities.MyProject_GetTop5Categories().ToList();
StringBuilder sb = new StringBuilder("<ul>");
foreach(var category in list)
{
sb.Append("<li><a href='"+category.Link+"'>" + category.Name + "</a></li>");
}
sb.Append("<ul>");
listPlaceHolder = sb.ToString();
}
handwritten so probably a typo or two in there :)
HTH

Related

How to store system-created to-do list items?

In a to-do list where users have both system-created items and their own items, how would you store the items?
A to-do list can have a mix of items. The system-created items can be modified and deleted just like user-created items. There difference is the titles and description text for the system-created items are initially pulled from a configuration. Many users can have the same system-created items. E.g. if two users want to paint rooms in their houses, they'd both get "buy paint" items.
Option 1
Save the full system-created items (including the title & text) with the user-created items.
Pros: Flexibility for user modifications since the items belong to the user and are not dependent on a central item configuration.
Cons: Lots of redundancy because there will be many users all with the same items.
Option 2
Save references to a configuration for system-created items with the user-created items.
Pros: Flexibility for system modifications since if we want to say "buy X-brand paint" instead of "buy paint", the change is easily reflected for all users with this item.
Cons: System-created items have to persist forever in the configuration even if the item is no longer relevant for new to-do lists because otherwise the user's reference will be broken.
Other options?
Thank you!
My initial thought is - what is your requirement? Your user-flows and project road-map might contain information to inform your design.
From your question "system-created items can be modified and deleted just like user-created items":
This indicates that you are going to have to have a way to track modifications to your 'system-created' templates per user or convert them to 'user-created' messages when they are edited.
This is more complexity than you seem to need
It seems much simpler to create messages from system templates, then have them be regular messages.
A bit of extra storage is not going to break the bank
You have not mentioned any case where you would need to operate over only system-created to-do's. But in this case, you could include created-by metadata.
I think the key here is whether you need to be able to modify a "system todo", and that change to be reflected in all the "user todos"...
If that's a requirement (it sounds sensible to me), your only option is Option 2 - the real con of Option 1 is once you copied the "system todo" as a "user todo", you cannot tell anymore whether they're related...
I'd go for a model similar to this, with 2 entities/tables:
ToDoTemplate
Integer id
String name
String description
ToDoItem
Integer id
ToDoTemplate template
Boolean completed = false
?String name = null
?String description = null
When you create a ToDoItem, you create it based on a ToDoTemplate (it may be a blank template), and you set the name and description as null, reusing the template name/description... Only if the user modifies their own ToDoItem is when you store that value... i.e.
String getName() {
return this.name != null ? this.name : this.template.name;
}
This is the most flexible of the approaches, and the only valid in many situations... Note the con you mention:
Cons: System-created items have to persist forever in the configuration even if the item is no longer relevant for new to-do lists because otherwise the user's reference will be broken.
This is not a con really - as long as there's one ToDoItem that uses a given ToDoTemplate, the template is still relevant, and of course there's no reason to remove it...

How to access Customizable Text Fields From Prestashop Module?

I'm creating a new module for Prestashop where users can design their own product from a third party service. When the user later adds the product to their cart, I would like to save a ID that I get from this Third Party Service where the user designed their product.
I guess the best way to do this is to create a Customization Textfield within Prestashop called "designID". Now I want to know how I save data to this field from module development in Prestashop instead of letting the users manually fill in the data.
So basically... How do I add data to these customizable fields from within a Prestashop module, when the user adds the product to their cart?
These customization fields are used if you are simple user and you are not designing a module. Using it to save the designID will be just a hack.
Since you're creating a new module my advice is to keep the 3rd party ID in a newly created database table, which will match the id_product, id_design, id_cart, id_order, etc...
You can hook to "actionCartSave" and add the record with the matching ids, and all the other required data at your table.
If you want to stick to that Customization feature, add a sample field and review the following database tables:
ps_customization
ps_customization_field
ps_customization_field_lang
ps_customized_data
and replicate the changes when you receive the 3rd party ID.
If all your products will be customized, consider adding the required data in ps_customization_field & ps_customization_field_lang (the table for the field structure) during the module installation, so after it's installed you can just fill
ps_customization & ps_customized_data (the tables for the field data)
PrestaShop does not have proper API for adding customizations, only for retrieving data, so you'll have to write the SQL queries yourself. Just review the ProductController for the ps_customization & ps_customized_data changes and the AdminProductsController for ps_customization_field & ps_customization_field_lang.
Do not forget to remove the Customization markup code from your product & cart templates.
I was able to find this out by myself by first trying to use Customization for a couple of hours without any success.
So basically how my module work is that the customer can open a popup iframe to a third party design tool, the customer then save the design in the iframe, which then sends the data to the parent window (The Prestashop Window).
So to store this I did the following:
Add a new column to the database table ps_cart_product
Hook into any display-hook on the product page and check if any post data is send containing the data from the third party module. If so, then:
if(isset($_POST['thirdparty'])){
$id_product = (int)Tools::getValue('id_product');
if (!$this->context->cart->id){
$this->context->cart->add();
if ($this->context->cart->id)
$this->context->cookie->id_cart = (int)$this->context->cart->id;
}
$this->context->cart->updateQty(1, $id_product);
if(!Db::getInstance()->update('cart_product', array('id_design'=> pSQL(trim($_POST['thirdparty']))) ,'id_cart = '.$this->context->cart->id.' AND id_product = '.(int)Tools::getValue('id_product') ))
$this->context->controller->_errors[] = Tools::displayError('Error: ').mysql_error();
}
So basically first I check if POST is set, then I check if any cart exist, if cart does not exist then add a new cart with ->add() (This function took hours to find, 0 documentation). updateQty() is used to update the cart with the new product.
The last part is the SQL query that updates the value of id_design column with the data that is send from the third party.

Ektron Workarea

I need to develop an application that extracts all the contents in Content Tab of the Ektron Workarea and I have to keep tree structure of folders (taxonomies,collections,forms,etc.) also.When I click the content I need to get the Content ID in the code behind also.I need to do all these in a single function.
I tried this requirement with the concept of content block widget in workarea.When we drag that widget and edit it a pop up will come and it displays the folders of work area in tree structure.But when I created an aspx page, put the same code and I browse that page I didn't get the tree structure of all contents.Only the main tabs(Folders,Taxonomies and search ) are visible.Then I drag the user control in the aspx page .But it also doest work.
So how will I solve the above problem.
Can I pull all the contents in tree structure from work area from the root using API codes?.Then can anyone please give the API code to solve?
Please anyone reply!
Assuming you are using 8.6 look here to start with:
http://reference.ektron.com/developer/framework/content/contentmanager/getlist.aspx
Update:
I think I misread your question the first time around. Allow me to expand on my answer a bit. My original answer with the web services assumes that you are rendering the content tree from some sort of "presentation tier" -- a different web site, a console app, or a WPF/WinForms app, etc.
You can get the recursive folder structure with something like this:
private FolderData GetFolderWithChildren(long folderId)
{
var folderApi = new Ektron.Cms.API.Folder();
var folderData = folderApi.GetFolder(folderId);
// This next method is marked as obsolete in v9.0;
// a newer overload is available in v9.0, but I
// don't know if it's available in v8.0
folderData.ChildFolders = folderApi.GetChildFolders(folderId, true);
}
I'm a little confused as to what exactly you're trying to accomplish. If you want to show the entire tree structure graphically, have you tried taking the code and markup from the edit view of the content widget and using it on your non-edit view?
I must say, your requirement that "I need to do all these in a single function" worries me a bit. Workarea content trees can get really large very quickly. If you're trying to load all of the folders and all the taxonomies and all the collections, etc. Then the user will likely be waiting a long time for the page to load, and you risk running into timeout issues.
-- Original Answer --
Ektron v8.0 doesn't have the 3-tier option, which is too bad because that would really make your job a lot easier. In v8.0, there are ASMX web services that you can reference, including:
/workarea/webservices/content.asmx
/workarea/webservices/webserviceapi/user/user.asmx
There are lots more than this; browse through the folders within /workarea/ to see what's available.
It's been a while since I've worked with these services, so I'm a little rusty...
Suppose you add references to those two services I listed above and name them ContentService and UserService. The first thing you'll want to do is set the authentication headers. Then you can call the service methods in much the same way as the old legacy apis.
var contentApi = new ContentService.Content();
contentApi.AuthenticationHeaderValue = new ContentService.AuthenticationHeader();
contentApi.AuthenticationHeaderValue.Username = username;
contentApi.AuthenticationHeaderValue.Password = password;
contentApi.AuthenticationHeaderValue.Domain = domain;
var userApi = new UserService.User();
userApi.AuthenticationHeaderValue = new UserService.AuthenticationHeader();
userApi.AuthenticationHeaderValue.Username = username;
userApi.AuthenticationHeaderValue.Password = password;
userApi.AuthenticationHeaderValue.Domain = domain;
var ud = userApi.GetUserbyUsername("jimmy456");
long folderID = 85;
bool recursive = true;
ContentData[] folderContent = contentApi.GetChildContent(folderID, recursive, "content_id");

ASP.net MVC: Execute Razor from DB String?

I was thinking about giving end users the ability to drop Partial Views (controls) into the information being stored in the database. Is there a way to execute a string I get from the database as part of the Razor view?
Update (I forgot all about this)
I had asked this question previously (which lead me to create RazorEngine) Pulling a View from a database rather than a file
I know of at least two: RazorEngine, MvcMailer
I have a bias towards RazorEngine as it's one that I've worked on but I have a much simpler one at Github called RazorSharp (though it only supports c#)
These are all pretty easy to use.
RazorEngine:
string result = RazorEngine.Razor.Parse(razorTemplate, new { Name = "World" });
MvcMailer
I haven't used this one so I can't help.
RazorSharp
RazorSharp also supports master pages.
string result = RazorSharp.Razor.Parse(new { Name = "World" },
razorTemplate,
masterTemplate); //master template not required
Neither RazorSharp, nor RazorEngine support any of the Mvc helpers such as Html and Url. Since these libraries are supposed to exist outside of Mvc and thus require more work to get them to work with those helpers. I can't say anything about MvcMailer but I suspect the situation is the same.
Hope these help.

Eclipse RCP: How to order perspective buttons belonging to different plugins?

My application has 5 plugins. Each plugin has a perspective of it's own and hence each perspective extension definition is under individual plugin's plugin.xml.
Now, I want to control the order in which these perspectives appear in my application. How to do it?
There is one main plugin that holds "ApplicationWorkBenchAdvisor.java". This has initialize() method in which I am iterating through the perspective registry using
PlatformUI.getWorkbench().getPerspectiveRegistry().getPerspectives();
and then appending perspective ids in a comma separated fashion to a String variable (pbar) which is used later like this.
PlatformUI.getPreferenceStore().setDefault(IWorkbenchPreferenceConstants.PERSPECTIVE_BAR_EXTRAS, pbar);
PlatformUI.getPreferenceStore().setValue(IWorkbenchPreferenceConstants.PERSPECTIVE_BAR_EXTRAS, pbar);
When iterating thourgh the perspective registry, I can compare perspective ids and sort it(when adding to 'pbar' by comparing ids) the way I want it to appear but, I don't want to do this ordering here as it appears like a dirty way.
Is there any other place where we can fix the order in which perspectives appear? (Each perspective resides in different plugin).
ADDED
1) Could we also control the ordering in the perspective switcher?
2) Is there a way to control entry into perspective registry to in inflict the desired order. If not could we write back into perspective registry?
If your application is encapsulated as an eclipse product, you may tweak the plugin.properties/plugin_customization.ini file.
(file referenced by the 'preferenceCustomization' property in your product extension point.)
This file is a java.io.Properties format file. Typically this file is used to set the values for preferences that are published as part of a plug-in's public API.
(Example of such a file for org.eclipse.platform)
So if the string representing the order of perspective can be referenced as a property, you can define the default order in there.
Since the source code of IWorkbenchPreferenceConstants mentions:
/**
* Lists the extra perspectives to show in the perspective bar.
* The value is a comma-separated list of perspective ids.
* The default is the empty string.
*
* #since 3.2
*/
public static final String JavaDoc PERSPECTIVE_BAR_EXTRAS = "PERSPECTIVE_BAR_EXTRAS"; //$NON-NLS-1$
Maybe a line in the plugin_customization.ini file:
org.eclipse.ui/PERSPECTIVE_BAR_EXTRAS=perspectiveId1,perspectiveId2,perspectiveId3
would allow you to specify that order without having to hard-code it.
Additional notes:
IPerspectiveRegistry (or PerspectiveRegistry) is not made to write anything (especially for perspective defined in an extension)
Ordering may be found in the state of the workbench (stored in the workspace and then restored when its launched again, .metadata/.plugins/org.eclipse.ui.workbench/workbench.xml)
Do you confirm that:
IPerspectiveRegistry registry = PlatformUI.getWorkbench().getPerspectiveRegistry();
IPerspectiveDescriptor[] perspectives = registry.getPerspectives();
is not in the right order when the plugin_customization.ini does define that order correctly ?
Liverpool 5 - 0 Aston Villa does confirm that (in the comments), but also indicates the (ordered) ini file entries internally get recorded into preference store, which means they can be retrieved through the preference store API:
PatformUI.getPreferenceStore().getDefault(
IWorkbenchPreferenceConstants.PERSPECTIVE_BAR_EXTRAS)
Liverpool 5 - 0 Aston Villa then add:
perspective registry (the initial "PlatformUI.getWorkbench().getPerspectiveRegistry().getPerspectives();" bit) remains unaltered (and unordered).
But, you still can "readily access to ordered list of perspectives" through preference store.
So, for other tasks, instead of iterating though perspective registry (which is still unordered), we can use the ordered variable that stores list of ordered perpective ids.
.
.
.
.
Note: another possibility is to Replace the Perspective-Switcher in RCP apps
=> to:
You can more easily define the order in a menu or in buttons there.
Extreme solution: re-implement a perspective switcher.
To sum up all the observations and findings,
1) It is not possible to alter entries in the perspective registry. It is read-only.
2) To make perspective appear in the order that we want on perspective bar, we can achieve it by adding an entry in plugin_customization.ini (or preferences.ini) as shown below.
org.eclipse.ui/PERSPECTIVE_BAR_EXTRAS=perspectiveId1,perspectiveId2,perspectiveId3
3) If we want to fetch this ordered list, we can't fetch it directly. But as this ini file entry internally gets recorded in PreferenceStore we can fetch the same value from PreferenceStore using the following API as shown below.
PlatformUI.getPreferenceStore().getDefault(
IWorkbenchPreferenceConstants.PERSPECTIVE_BAR_EXTRAS);
Why would someone need to access the entry defined in ini file at all?
Well, in my case I had a view in which i had to display links to every perspective. As my perspective bar was sorted in desired order, I also wanted to maintain the same order in my view while displaying links to perspectives.
4) There is no known way to inflict the same sort order in the display of default perspective switcher. While a new custom perspective switcher can be written to achieve the desired effect.