Update TaxDetails in Sales order when Override check box is clicked - events

I am customizing Sales order screen to populate Customer Tax Zone ID when Override tax zone check box is checked.
When "Override Check box" is clicked, I want to populate tax zone from project screen into the Customer taxZone ID and parallelly tax details in Tax tab should also populate based on the customer tax zone but this is not happening, I can populate Customer tax zone in its but unable to populate tax details. Below is the code I am using.
public class SOOrderEntry_Extension : PXGraphExtension<SOOrderEntry>
{
protected void SOOrder_OverrideTaxZone_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e)
{
var row = (SOOrder)e.Row;
SOOrderEntry docgraph = PXGraph.CreateInstance<SOOrderEntry>();
PMProject proj = PXSelect<PMProject, Where<PMProject.contractID, Equal<Required<PMProject.contractID>>>>.Select(Base, row.ProjectID);
ContractExt contract = PXCache<Contract>.GetExtension<ContractExt>(proj);
row.TaxZoneID = contract.UsrCustomerTaxZone;
}
}

You should use sender.SetValueExt<SOOrder.taxZoneID>(row, contract.UsrCustomerTaxZone); to execute all needed events after the TaxZoneID changing. Your code will be the follwing:
protected void SOOrder_OverrideTaxZone_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e)
{
var row = (SOOrder)e.Row;
SOOrderEntry docgraph = PXGraph.CreateInstance<SOOrderEntry>();
PMProject proj = PXSelect<PMProject, Where<PMProject.contractID, Equal<Required<PMProject.contractID>>>>.Select(Base, row.ProjectID);
ContractExt contract = PXCache<Contract>.GetExtension<ContractExt>(proj);
sender.SetValueExt<SOOrder.taxZoneID>(row, contract.UsrCustomerTaxZone);
}

Related

How to create separate DetailTable on each row in a RadGrid?

I have a telerik radgrid where columns and detail tables are declared like:
<telerik:RadGrid>
<Columns>
<telerik:GridBoundColumn/>
<telerik:GridBoundColumn/>
</Columns>
<DetailTables>
<telerik:GridTableView
<Columns>
<telerik:GridBoundColumn/>
<telerik:GridBoundColumn/>
</Columns>
</telerik:GridTableView
</DetailTables>
</telerik:RadGrid>
Which gives a nested grid like this:
Now, what I want is to be able to specify a detail table (those sub tables) per row, programmatically.
(I cannot be sure that the columns for the nested table that comes up when I expand the line fgvbvb will be the same as the columns when expanding the line xcxcv).
I have tried, without luck in the OnDataBound handler of the radgrid (in which I omitted <DetailTables>) to access the data structure for nested tables like this:
protected void OnRadGridDataBound(object sender, EventArgs e)
{
foreach (GridDataItem item in grdActivitiesToCopy.MasterTableView.Items)
{
var dg = item.ChildItem.NestedTableViews[0];
}
}
This will overindex the array NestedTableViews because it is empty. Also, item.ChildItem.NestedTableViews has no setter.
How do I populate each row with a detail table one by one manually?
According to Telerik:
RadGrid does not support mixing declarative grid columns with grid
columns added dynamically at runtime. You should either create all the
columns in the grid programmatically, or else define them all in the
ASPX file. When creating Detail tables, it should be created in the
PageInit event.
Creating a Hierarchical Grid Programmatically:
You should follow these basic steps in order to create hierarchical
RadGrid programmatically in the code-behind (having a data source
control for data content generation):
Create the grid dynamically in the Page_Init handler of the page by
calling its constructor.
Specify the preferred settings for your grid instance through its
properties.
Create columns for the grid dynamically. Keep in mind that you have to
first set their properties and then add them to the
MasterTableView/GridTableView collection (discussed in the first
paragraph of this same topic). Thus, their ViewState will be properly
persisted (as LoadViewState is raised after the Init event of the
page).
Set the proper ParentTableRelations for the GridTableViews (along with
their MasterKeyField and DetailKeyField attributes) and DataKeyNames
for the MasterTableView/GridTableViews in the code-behind of the page.
Assign data sources (through the DataSourceID attribute) for each
table in the grid hierarchy.If you do not want to use declarative
relations, generate the data in the NeedDataSource/DetailTableDataBind
handlers of the grid. On DetailTableDataBind you can determine which
data source should be related to the currently bound GridTableView by
checking its Name/DataSourceID property. Here, the Name property must
have a unique value for each detail table (this value has to be
defined previously by the developer) and the DataSourceID is the ID of
the DataSource control responsible for the corresponding detail table
content generation.
Code Sample:
RadGrid RadGrid1 = new RadGrid();
RadGrid1.DataSourceID = "SqlDataSource1";
RadGrid1.MasterTableView.DataKeyNames = new string[] { "CustomerID" };
RadGrid1.Skin = "Default";
RadGrid1.Width = Unit.Percentage(100);
RadGrid1.PageSize = 15;
RadGrid1.AllowPaging = true;
RadGrid1.AutoGenerateColumns = false;
//Add columns
GridBoundColumn boundColumn;
boundColumn = new GridBoundColumn();
boundColumn.DataField = "CustomerID";
boundColumn.HeaderText = "CustomerID";
RadGrid1.MasterTableView.Columns.Add(boundColumn);
boundColumn = new GridBoundColumn();
boundColumn.DataField = "ContactName";
boundColumn.HeaderText = "Contact Name";
RadGrid1.MasterTableView.Columns.Add(boundColumn);
//Detail table - Orders (II in hierarchy level)
GridTableView tableViewOrders = new GridTableView(RadGrid1);
tableViewOrders.DataSourceID = "SqlDataSource2";
tableViewOrders.DataKeyNames = new string[] { "OrderID" };
GridRelationFields relationFields = new GridRelationFields();
relationFields.MasterKeyField = "CustomerID";
relationFields.DetailKeyField = "CustomerID";
tableViewOrders.ParentTableRelation.Add(relationFields);
RadGrid1.MasterTableView.DetailTables.Add(tableViewOrders);
Please refer to this help article for more details:
http://docs.telerik.com/devtools/aspnet-ajax/controls/grid/defining-structure/creating-a-radgrid-programmatically#creating-a-hierarchical-grid-programmatically
First of all , because of the life cicle of a asp page. You can't access to a event on a detail table.
If you need to access detail tables , items etc ..
You need to add an method to the PreRender in the MasterTableView like this:
<MasterTableView DataSourceID="myDataSource"
AllowMultiColumnSorting="True"
DataKeyNames="Key1,Key2,KeyN"
HierarchyDefaultExpanded="True"
OnPreRender="Unnamed_PreRender" >
The method will recursively iterate through the grid.
The way you do it can change depending on your HieararchyLoadMode.
So this is my way to do it, easiest way exist if you are on Client or Serverbind mode.
Traversing and load mode by the telerik doc .
I'm pretty sure you don't want to :
"populate each row with a detail table one by one manually"
You want to have Multiple table at a Sub Level in your grid and display the rigth one programmatically.
And this is can be done in two easy step:
1/. Create every Detail table in your apsx page.
Please refer to this documentation for more information :
Several tables at a level
2/. Handle the display:
protected void Unnamed_PreRender(object sender, EventArgs e)
{
if (!IsPostBack) myControler(MASTERGRID.MasterTableView);
}
private void myControler(GridTableView gridTableView)
{
GridItem[] nestedViewItems = gridTableView.GetItems(GridItemType.NestedView);
foreach (GridNestedViewItem nestedViewItem in nestedViewItems)
{
foreach (GridTableView nestedView in nestedViewItem.NestedTableViews)
{
if (nestedView.Name == "mytable12" && nestedView.Items.Count == 0)
{ HideExpandColumn(nestedView, nestedView.ParentItem["ExpandColumn"]); }
else if (nestedView.Name == "mytable23")
{
if (nestedView.Items.Count == 0)//
HideExpandColumn(nestedView, nestedView.ParentItem["ExpandColumn"]);
else
{ }
}
if (nestedView.HasDetailTables)
{ myControler(nestedView); }
}
}
}
private void HideExpandColumn(GridTableView _GNVI, TableCell _cell)
{
if (_cell.Controls.Count > 0)
{
_cell.Controls[0].Visible = false;
_cell.Text = " ";
}
_GNVI.Visible = false;
}
You can hide a detail table using :
HideExpandColumn(nestedView, nestedView.ParentItem["ExpandColumn"]);
Or you can hide the parent of the detail table you tested using the detail table that is in param of the controler :
HideExpandColumn(gridTableView, nestedView.ParentItem["ExpandColumn"]);
HideExpandColumn will hide the expand control that stay sometimes even if you hide th detail table.
Bonus: If you need to access to a control in a detail table.
You can use this:
public static class ControlExtensions
{
public static Control FindIt(this Control control, string id)
{
if (control == null) return null;
Control ctrl = control.FindControl(id);
if (ctrl == null)
{
foreach (Control child in control.Controls)
{
ctrl = FindIt(child, id);
if (ctrl != null) break;
}
}
return ctrl;
}
}
Calling it in your controler like this :
else if (nestedView.Name == "DetailPV")
{
if (nestedView.Items.Count == 0)
HideExpandColumn(gridTableView, nestedView.ParentItem["ExpandColumn"]);
else
{
RadLabel ctrl = (RadLabel)this.FindIt("RadLabel11");
ctrl.Text += "<b>" + nestedView.Items.Count.ToString() + "</b>";
}

Magmi: Import "Not Logged In" Pricing

I am trying to use magmi to import group and tier pricing for the not logged in group and am not sure what the format is for my csv headers or where to find it.
I have successfully used group and tier price imports with magmi on all (sku,price,tier_price:_all_), none (sku,group_price:None,tier_price:None) and other custom groups I have. A (sku,group_price:A,tier_price:A), B (sku,group_price:B,tier_price:B) and so on.
It is just the formatting for not logged in I can't figure out and I can't seem to find anything on it in the documentation.
Here is what I have tried so far.
sku,group_price:NOT LOGGED IN,tier_price:NOT LOGGED IN
sku,group_price:'NOT LOGGED IN',tier_price:'NOT LOGGED IN'
sku,group_price:_not_,tier_price:_not_
sku,group_price:General,tier_price:General
Any ideas?
yes it is works.. create directory /var/www/html/../magmi/plugins/extra/itemprocessors/groupprice
put this grouppriceprocessor.php on this directory ,
select this profile in magmi .. group_price:NOT LOGGED IN
this is header in csv file put value for this and it works ..
code of grouppriceprocessor.php
<?php
/**
* Class Tier price processor
* #author dweeves
*
* This imports tier prices for columns names called "group_price:"
*/
class GrouppriceProcessor extends Magmi_ItemProcessor
{
protected $_tpcol=array();
protected $_singlestore=0;
protected $__pricescope=2;
public function getPluginInfo()
{
return array(
"name" => "Group price importer",
"author" => "Dweeves,bepixeld,Jason",
"version" => "0.0.1",
);
}
/**
* you can add/remove columns for the item passed since it is passed by reference
* #param Magmi_Engine $mmi : reference to magmi engine instance (convenient to perform database operations)
* #param unknown_type $item : modifiable reference to item before import
* the $item is a key/value array with column names as keys and values as read from csv file.
* #return bool :
* true if you want the item to be imported after your custom processing
* false if you want to skip item import after your processing
*/
public function processItemAfterId(&$item,$params=null)
{
$pid=$params["product_id"];
$tpn=$this->tablename("catalog_product_entity_group_price");
$tpcol=array_intersect(array_keys($this->_tpcol),array_keys($item));
//do nothing if item has no group price info or has not change
if(count($tpcol)==0 )
{
return true;
}
else
{
//it seems that magento does not handle "per website" tier price on single store deployments , so force it to "default"
//so we test wether we have single store deployment or not.
//bepixeld patch : check pricescope from general config
if($this->_singlestore==0 && $this->_pricescope!=0)
{
$wsids=$this->getItemWebsites($item);
}
else
{
$wsids=array(0);
}
$wsstr=$this->arr2values($wsids);
//clear all existing tier price info for existing customer groups in csv
$cgids=array();
foreach($tpcol as $k)
{
$tpinf=$this->_tpcol[$k];
if($tpinf["id"]!=null)
{
$cgids[]=$tpinf["id"];
}
else
{
$cgids=array();
break;
}
}
//if we have specific customer groups
if(count($cgids)>0)
{
//delete only for thos customer groups
$instr=$this->arr2values($cgids);
//clear tier prices for selected tier price columns
$sql="DELETE FROM $tpn WHERE entity_id=? AND customer_group_id IN ($instr) AND website_id IN ($wsstr)";
$this->delete($sql,array_merge(array($pid),$cgids,$wsids));
}
else
{
//delete for all customer groups
$sql="DELETE FROM $tpn WHERE entity_id=? AND website_id IN ($wsstr)";
$this->delete($sql,array_merge(array($pid),$wsids));
}
}
foreach($tpcol as $k)
{
//get tier price column info
$tpinf=$this->_tpcol[$k];
//now we've got a customer group id
$cgid=$tpinf["id"];
//add tier price
$sql="INSERT INTO $tpn
(entity_id,all_groups,customer_group_id,value,website_id) VALUES ";
$inserts=array();
$data=array();
if($item[$k]=="")
{
continue;
}
$tpvals=explode(";",$item[$k]);
foreach($wsids as $wsid)
{
//for each tier price value definition
foreach($tpvals as $tpval)
{
$tpprice=str_replace(",",".",$tpval);
if($tpprice=="")
{
continue;
}
if(substr($tpprice,-1)=="%")
{
//if no reference price,skip % tier price
if(!isset($item["price"]))
{
$this->warning("No price define, cannot apply % on group price");
continue;
}
$fp=(float)(str_replace(",",".",$item["price"]));
$pc=(float)(substr($tpprice,0,-1));
$m=($pc<0?(100+$pc):$pc);
$tpprice=strval(($fp*($m))/100.0);
}
$inserts[]="(?,?,?,?,?)";
$data[]=$pid;
//if all , set all_groups flag
$data[]=(isset($cgid)?0:1);
$data[]=(isset($cgid)?$cgid:0);
$data[]=$tpprice;
$data[]=$wsid;
}
}
if(count($inserts)>0)
{
$sql.=implode(",",$inserts);
$sql.=" ON DUPLICATE KEY UPDATE `value`=VALUES(`value`)";
$this->insert($sql,$data);
}
}
return true;
}
public function processColumnList(&$cols,$params=null)
{
//inspect column list for getting tier price columns info
foreach($cols as $col)
{
if(preg_match("|group_price:(.*)|",$col,$matches))
{
$tpinf=array("name"=>$matches[1],"id"=>null);
//if specific tier price
if($tpinf["name"]!=="_all_")
{
//get tier price customer group id
$sql="SELECT customer_group_id from ".$this->tablename("customer_group")." WHERE customer_group_code=?";
$cgid=$this->selectone($sql,$tpinf["name"],"customer_group_id");
$tpinf["id"]=$cgid;
}
else
{
$tpinf["id"]=null;
}
$this->_tpcol[$col]=$tpinf;
}
}
return true;
}
public function initialize($params)
{
$sql="SELECT COUNT(store_id) as cnt FROM ".$this->tablename("core_store")." WHERE store_id!=0";
$ns=$this->selectOne($sql,array(),"cnt");
if($ns==1)
{
$this->_singlestore=1;
}
//bepixeld patch : check pricescope from general config
$sql = "SELECT value FROM ". $this->tablename('core_config_data') ." WHERE path=?";
$this->_pricescope = intval($this->selectone($sql, array('catalog/price/scope'), 'value')); //0=global, 1=website
}
}
thanks
I found out from further testing that the tier pricing magmi plugin worked just fine with the above csv format. the original plugin I got to work with some code change but then decided to check for an update.
While searching I found an alternate magmi plugin for the group price importer and it worked.
Replace the current file in the magmi/plugins/extra/itemprocessors/groupprice folder with this one.
Here is the website found at if you would like to see more info.

ASPxGridView Group Summary Sorting - It sorts the content inside, not the summary outside

I have done grouping of the grid by giving groupindex to a particular column in aspxgridview.
For example, if I am grouping by means of persons name and the orders details made by that particular person would come in the detailed content when the arrow is clicked to view the content.
When I click on the header fields to sort, it is sorting the data inside the groupContent but it is not used for sorting the data of groupsummary
I am showing all the totals as a part of group summary besides the person's name.
For example if you see in the below link:
https://demos.devexpress.com/ASPxGridViewDemos/Summary/GroupSortBySummary.aspx
If you sort by company name, the content would be sorted, but the summary showing the country and sum has no means to get sorted at outside level.
Please do suggest me options to work out this problem.
Thanks.
Here is workaround, based on this example.
The main idea is to create summary item which shows the minimum or maximum value of Country column inside City group and sort City group by this summary values. For this BeforeColumnSortingGrouping event is used to change the sorting behavior.
Here is example:
<dx:ASPxGridView ...
OnBeforeColumnSortingGrouping="gridCustomers_BeforeColumnSortingGrouping">
private void SortByCountry()
{
gridCustomers.GroupSummary.Clear();
gridCustomers.GroupSummarySortInfo.Clear();
var sortOrder = gridCustomers.DataColumns["Country"].SortOrder;
SummaryItemType summaryType = SummaryItemType.None;
switch (sortOrder)
{
case ColumnSortOrder.None:
return;
break;
case ColumnSortOrder.Ascending:
summaryType = SummaryItemType.Min;
break;
case ColumnSortOrder.Descending:
summaryType = SummaryItemType.Max;
break;
}
var groupSummary = new ASPxSummaryItem("Country", summaryType);
gridCustomers.GroupSummary.Add(groupSummary);
var sortInfo = new ASPxGroupSummarySortInfo();
sortInfo.SortOrder = sortOrder;
sortInfo.SummaryItem = groupSummary;
sortInfo.GroupColumn = "City";
gridCustomers.GroupSummarySortInfo.AddRange(sortInfo);
}
protected void Page_Load(object sender, EventArgs e)
{
SortByCountry();
}
protected void gridCustomers_BeforeColumnSortingGrouping(object sender, ASPxGridViewBeforeColumnGroupingSortingEventArgs e)
{
SortByCountry();
}
When you group by a column devexpress automatically uses that column to sort. Without sorting the data the grouping is not possible. To overcome this issue we have sorted the datasource itself then applied that datasource to the grid.

Clear a group of cache in asp.net mvc 3

I am saving a list to cache. so that there is no need to go to the database eache time when the list needs.
here is the code
public IEnumerable<SelectListItem> GetCategoriesByParentId(int parentCategoryId)
{
string cacheKey = "PC" + parentCategoryId.ToString();
DateTime expiration = DateTime.Now.AddDays(1);
IEnumerable<SelectListItem> categoryList ;
categoryList = HttpContext.Current.Cache[cacheKey] as IEnumerable<SelectListItem>;
if (categoryList == null)
{
categoryList = GetCategoryList(parentCategoryId); // getting category from database
HttpContext.Current.Cache.Add(cacheKey, categoryList, null, expiration, TimeSpan.Zero, System.Web.Caching.CacheItemPriority.Normal, null);
}
return categoryList;
}
My problem is when a new category is added to the database ,i am still gettting old category list .the list do not contain new category..How can clear the cache ( only category cache) after adding or changing a category
Any ideas?
When you insert a new category to the database I suppose you have the parent category id into which this category was inserted so you could remove it from the cache:
HttpContext.Current.Cache.Remove("PC" + parentCategoryId);
Now if the adding of a new category is not done by your application and you have no control over it you may take a look at cache expiration with SQL dependency.

Custom message in Tablewizard

How do I show a custom message in the table wizard when table has no data. I am working with Telerik Reports Q1 2011.
There is NoDataMessage property of table item. You can add epression and the message will be displayed. Also, you can give styling to NoDataMessage. Or go to itemdatabound event of table item and then set the value for no data message.
private void table1_ItemDataBound(object sender, EventArgs e)
{
//Take the Telerik.Reporting.Processing.DataItem instance
Telerik.Reporting.Processing.Table tbl = Telerik.Reporting.Processing.DataItem)sender;
//Check if data is retrieved by graph or not.
if (table1.Items.Count == 0)
{
//If no data retrieved, then set the NoDataMessage property.
tbl.NoDataMessage = "No Data Found";
}
}
Link:
http://www.telerik.com/help/reporting/report-structure-dataitem-set-no-data-message.html

Resources