Is there a easy way to customize Acumatica build-in dropdown list? - acumatica

For example, in screen CR301000, source field is having 5 items right now, but I want to have 6 different items listing here, please advice how to do it. Thanks.

You can do it a few ways.
1) Customization to create a custom string/int list then override the dac attribute in the BLC to point to your custom list.
First create the custom stringlist:
public class CustomSourceAttribute : PXStringListAttribute
{
public const string _LEADPROSPECT = "1";
public const string _INITIALCONTACT = "2";
public const string _QUALIFIED = "3";
public const string _INITIALPRICE = "4";
public const string _PROPOSALSENT = "5";
public const string _POSITIVEPROPOSAL = "6";
public const string _VERBALCOMMIT = "7";
public const string _READYFORCONTRACT = "R";
public const string _CONTRACTSENT = "8";
public const string _CONTRACTSIGNED = "9";
public const string _CLOSEDLOST = "0";
public const string _TARGET = "T";
public CustomSourceAttribute()
: base(new string[]
{
_LEADPROSPECT,
_INITIALCONTACT,
_QUALIFIED,
_INITIALPRICE,
_PROPOSALSENT,
_POSITIVEPROPOSAL,
_VERBALCOMMIT,
_READYFORCONTRACT,
_CONTRACTSENT,
_CONTRACTSIGNED,
_CLOSEDLOST,
_TARGET
},
new string[]
{
"Lead/Prospecting",
"Initial Contact",
"Qualified",
"Initial Pricing Sent",
"Proposal Sent",
"Positive Proposal Discussions",
"Verbal Commitment",
"Ready for Contract",
"Contract Sent",
"Contract Signed",
"Closed Lost",
"Target"
})
{
}
}
Then override the dac attribute in a BLC Extension:
[PXDBString(1, IsFixed = true)]
[PXUIField(DisplayName = "Stage")]
[CustomSourceAttribute]
[PXDefault(CustomSourceAttribute._INITIALCONTACT)]
[PXMassUpdatableField]
protected void CROpportunity_StageID_CacheAttached(PXCache cache)
{
}
This sample is from the Opportunity screen but the same holds true w/ leads
2) Automation step to provide the new values.
See here for automation step locations
the second way doesn't require customization but does take more work if there is already automation steps defined. You need to create the custom list for each step that exists.
For something like Leads, I'd go with option 1 as there is tons of steps

Add the Values you want:
Just a quick note if you chose to add via automation - to add a new field click in the white space of the lookup field - You will see the current values - in the white space below - dbl click.

Here is an example of creating Acumatica dropdown list field. Add constatnt fields and Pair them in Tuple<T1, T2>[].
public class Operators
{
public const string And = "&&";
public const string Or = "||";
public class UI
{
public const string And = "And";
public const string Or = "Or";
}
public class OperatorsAttribute : PXStringListAttribute
{
public OperatorsAttribute() : base(new Tuple<string, string>[]
{
Pair(And, UI.And),
Pair(Or, UI.Or)
})
{}
}
}
Then you use the nested OperatorsAttribute attribute class on the field like this.
#region Operator
public abstract class operators : BqlString.Field<operators> { }
[PXDBString(15)]
[PXDefault(1)]
[OperatorsAttribute]
[PXUIField(FieldName = "Operators", DisplayName = "Operators")]
public virtual string Operators { get; set; }
#endregion
To change already existing fields, create Extension classes for DACs and Graphs. Here is the detailed documentation for creating extension classes — Acumatica ERP Customization Guide

Related

Acumatica Vendor ID segment key different to BIZZACCOUNT segment length

I want to know if it's possible to setup Vendor ID segment keys with a less number of characters than the BiZAccounts..
For example I have created branch Keys like USBRANCH1 but now I want to create Vendor ID like V001 but not give the user possibility to enter more than 4 characters?
I'm not sure why BIZaccount is tied to vendors, customers, employees in terms of segment keys as this reduces flexibility and changing key length and type
Thanks
You can do the following to achieve that:
1. Create your own Segmented Key like below:
Create Cache Extension to the Vendor's DAC to change Default VENDOR Segmented Key which is inherited from BIZACCTto yours MYVENDOR like below:
using PX.Data;
using PX.Data.EP;
using PX.Objects.AP;
using PX.Objects.CR;
using PX.Objects.GL;
using System;
namespace ClassLibrary1.DAC
{
public class VendorExt:PXCacheExtension<Vendor>
{
[MyVendorRaw(IsKey = true)]
[PXDefault]
[PXFieldDescription]
public virtual string AcctCD { get; set; }
}
[PXDBString(30, IsUnicode = true, InputMask = "")]
[PXUIField(DisplayName = "Vendor", Visibility = PXUIVisibility.Visible)]
public sealed class MyVendorRawAttribute : AcctSubAttribute
{
public MyVendorRawAttribute() : this(null)
{
}
public MyVendorRawAttribute(Type where)
{
Type type = BqlCommand.Compose(new Type[]
{
typeof(Search2<, , >),
typeof(Vendor.acctCD),
typeof(LeftJoin<Contact, On<Contact.bAccountID, Equal<Vendor.bAccountID>, And<Contact.contactID, Equal<Vendor.defContactID>>>, LeftJoin<Address, On<Address.bAccountID, Equal<Vendor.bAccountID>, And<Address.addressID, Equal<Vendor.defAddressID>>>>>),
(where == null) ? typeof(Where<Match<Current<AccessInfo.userName>>>) : BqlCommand.Compose(new Type[]
{
typeof(Where2<, >),
typeof(Where<Match<Current<AccessInfo.userName>>>),
typeof(And<>),
where
})
});
PXDimensionSelectorAttribute pxdimensionSelectorAttribute;
this._Attributes.Add(pxdimensionSelectorAttribute = new PXDimensionSelectorAttribute("MYVENDOR", type, typeof(Vendor.acctCD), new Type[]
{
typeof(Vendor.acctCD),
typeof(Vendor.acctName),
typeof(Vendor.vendorClassID),
typeof(Vendor.status),
typeof(Contact.phone1),
typeof(Address.city),
typeof(Address.countryID)
}));
pxdimensionSelectorAttribute.DescriptionField = typeof(Vendor.acctName);
this._SelAttrIndex = this._Attributes.Count - 1;
this.Filterable = true;
((PXDimensionSelectorAttribute)this._Attributes[this._SelAttrIndex]).CacheGlobal = true;
}
public const string DimensionName = "MYVENDOR";
}
}
After this Vendor CD will work with 4 length. But as you can see on the screenshot below there will be some issues with the existing records. So I recommend you to do this only in case if the system has not existing Vendors.
Also after doing this I assume you to check all the pages which use Vendor for correct working.

Orchard cms Html from IContent items

My question is related to this one, but instead of changing a question I thought it Would be better to ask a new one.
I've now got a list of IContent items using the _taxonomyService.GetContentItems(term)
as suggested by #Bertrand Le Roy in the question mentioned above
But how do I turn this into a useful Html string, that I can update on the client via an ajax post?
public class HomeController : Controller
{
private readonly IOrchardServices _services;
private readonly IBlogService _blogService;
private readonly IBlogPostService _blogPostService;
private readonly IFeedManager _feedManager;
private readonly IArchiveConstraint _archiveConstraint;
private readonly ITaxonomyService _taxonomyService;
public HomeController(
IOrchardServices services,
IBlogService blogService,
IBlogPostService blogPostService,
IFeedManager feedManager,
IShapeFactory shapeFactory,
IArchiveConstraint archiveConstraint,
ITaxonomyService taxonomyService) {
_services = services;
_blogService = blogService;
_blogPostService = blogPostService;
_feedManager = feedManager;
_archiveConstraint = archiveConstraint;
T = NullLocalizer.Instance;
Shape = shapeFactory;
_taxonomyService = taxonomyService;
}
dynamic Shape { get; set; }
public Localizer T { get; set; }
public ActionResult Index()
{
return View();
}
[HttpPost]
public JsonResult ListByArchive(string path, IEnumerable<string> category)
{
try
{
// get year and month from path
path = path.ToLower().Substring(path.LastIndexOf(#"/archive/", StringComparison.Ordinal) + 9);
var date = path.Split('/');
var month = int.Parse(date[1]);
var year = int.Parse(date[0]);
// get list of terms ids from strings
var taxonomyPart = _taxonomyService.GetTaxonomyByName("Category");
var terms = category.Select(cat => _taxonomyService.GetTermByName(taxonomyPart.Id, cat)).ToList();
// get list of content items by term avoiding duplicates
var posts = new List<IContent>();
foreach (var term in terms)
{
var items = _taxonomyService.GetContentItems(term);
foreach (var item in items)
{
if (!posts.Select(p => p.Id).Contains(item.Id))
{
posts.Add(item);
}
}
}
// filter by date
var byDate = posts.Where(x =>
{
var publishedUtc = x.ContentItem.As<CommonPart>().CreatedUtc;
return
publishedUtc != null
&& publishedUtc.Value.Month == month
&& publishedUtc.Value.Year == year;
});
....
This gets me my list of IContent, but how do I get a the html for the rendered list ?
I've tried
var range = byDate.Select(x => _services.ContentManager.BuildDisplay(x, "Summary"));
var list = Shape.List();
list.AddRange(range);
dynamic viewModel = Shape.ViewModel().ContentItems(list);
var html = View((object)viewModel);
return Json(new { html = html });
but it returns an empty view,
{"html":{"MasterName":"","Model":[],"TempData":[],"View":null,"ViewBag":{},"ViewData":[],"ViewEngineCollection":[{"HostContainer":{}}],"ViewName":""}}
I have a view called ListByArchive.cshtml, that matches the one it the orchard.blog module.
As an aside, I should be returning a partial view result, instead of a jason result, but when I change the Action result type I get a 404. result from the server.
This is never going to work the way you think it does:
var html = View((object)viewModel);
The easiest way to return HTML representing the content item is to:
Mark your action with ThemedAttribute, ie. [Themed(false)]
Return new ShapeResult(this, viewModel) (full view) or new ShapePartialResult(this, viewModel) (partial view) instead of Json(new { html = html })
Rendering a shape/view to string inside the action is also possible, but way more tricky.
EDIT: I assumed you already have /Views/ViewModel.cshtml file in place. Like Bertrand Le Roy noted below - if it's not there, you need to add one to be able to create a shape using Shape.ViewModel().

Add new property in subsonic partial class

I added a new column(DateCreated) in a table(Activity) in sqlserver.
and I am using subsonic 2.0, how can I add this column as property in subsonic partial class, so that I can insert and update the value of "DateCreated" Column.
DateCreated will be provided by the user from the GUI.
following is the code I m using but it insert NULL & retrive NULL from the database.
public partial class ActivityInscription
{
public struct Columns
{
public static string IsInMixedList = #"IsInMixedList";
}
public bool? IsInMixedList
{
get;
set;
}
}
Please any one help me to resolve this issue.
If you added the column to the database then just rebuild the DAL. It will pick up the new column and add it to the subsonic DAL. There is no reason for a Partial class in your case. This will work providing that the table "Activity" is part of your subsonic list (includeTableList) of tables in the config file.
Following is the solution, I used and it is working:
public partial class Activity
{
public DateTime? DateCreated
{
get;
set;
}
protected override void BeforeInsert()
{
TableSchema.Table tblSchema = Schema;
TableSchema.TableColumn ccDateCreated = new TableSchema.TableColumn(tblSchema);
ccrDateCreated.ColumnName = "DateCreated";
ccDateCreated.DataType = DbType.DateTime;
ccDateCreated.MaxLength = 0;
ccDateCreated.AutoIncrement = false;
ccDateCreated.IsNullable = false;
ccDateCreated.IsPrimaryKey = false;
ccDateCreated.IsForeignKey = false;
ccDateCreated.IsReadOnly = false;
ccDateCreated.DefaultSetting = #"";
ccDateCreated.ForeignKeyTableName = "";
if (!tblSchema.Columns.Contains("DateCreated"))
{
tblSchema.Columns.Add(ccDateCreated);
}
if (this.GetSchema().Columns.Contains("DateCreated"))
this.SetColumnValue(Columns.DateCreated, DateCreated);
base.BeforeInsert();
}
}
Now it is working fine & inserting the values that I provide from the GUI.

Sharepoint search fails when using DataKeynames

We have a Sharepoint site which uses search.
We get the following error:
Unable to validate data. at
System.Web.Configuration.MachineKeySection.EncryptOrDecryptData
(Boolean fEncrypt, Byte[] buf, Byte[] modifier, Int32 start, Int32 length,
IVType ivType, Boolean useValidationSymAlgo)
at System.Web.UI.ObjectStateFormatter.Deserialize(String inputString)
After a bit of testing we have found that the error occurs when we use DateKeyNames on a GridView control.
Not sure why there should be any combination between Search, this error and DataKeyNames.
Any ideas?
Update: Here is some code
[Guid("8891224e-e830-4ffa-afbd-f789583d8d14")]
public class TestErrorGridView : System.Web.UI.WebControls.WebParts.WebPart
{
Control ascxToAdd;
public TestErrorGridView()
{
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
}
protected override void CreateChildControls()
{
base.CreateChildControls();
Table test = new Table();
TestBindObject t1 = new TestBindObject() { ID = 1, Name = "Test" };
List<TestBindObject> l1 = new List<TestBindObject>();
l1.Add(t1);
SPGridView testGrid = new SPGridView() { AutoGenerateColumns = false};
BoundField header = new BoundField();
header.DataField = "ID";
BoundField name = new BoundField();
name.DataField = "Name";
testGrid.Columns.Add(header);
testGrid.Columns.Add(name);
testGrid.DataSource = l1;
testGrid.DataBind();
// If you comment out this line search works
testGrid.DataKeyNames = new string[] { "ID" };
this.Controls.Add(testGrid);
base.CreateChildControls();
SPGridView testGrid = new SPGridView() { AutoGenerateColumns = false, EnableViewState=false };
testGrid.DataKeyNames = new string[] { "testid" };
this.Controls.Add(testGrid);
}
}
public class TestBindObject
{
public int ID { get; set; }
public string Name { get; set; }
}
UPDATE
This error occurrs on the developer machines, so it is not realated to machine keys being different on different machines in a cluster.
One of the developers has MOSS installed, he does not get the error. The developers who have just WSS installed get the error.
UPDATE 2
Have added datasource to code
I'm going to throw out a guess here since the code where you set the GridView's datasource is missing as well, but here goes...
It probably has something to do with the order in which you are setting the GridView's properties. My guess is that you need to set it in this order:
Create your GridView
Set the GridView's datasource (so that it has data)
Set DataKeyNames
Call GridView.DataBind()
Step 3 and 4 are the steps I am not sure about. You may have to DataBind and then set DataKeyNames.
We eventually solved this by following the example in this link:
http://msdn.microsoft.com/en-us/library/bb466219.aspx
I think that is was binding to a data table rather than a list that made the difference.
The fact that Sharepoint grids do not allow autogenerated columns appears to be one of the factors leading to this problem.

SharePoint 2007 (wss) search and Unable to validate data Exception

We have a problem with SharePoint's search box. Whenever we try to search for something we get:
Unable to validate data. at
System.Web.Configuration.MachineKeySection.EncryptOrDecryptData(Boolean
fEncrypt, Byte[] buf, Byte[] modifier,
Int32 start, Int32 length, IVType
ivType, Boolean useValidationSymAlgo)
at
System.Web.UI.ObjectStateFormatter.Deserialize(String
inputString) exeption.
Does any one know the reason for this exception, or a way to work around it?
New entry:
I'm using a SPGridView where i use the datakeys property in a web part. The webpart works, but we found that using the datakeys property breaks seach in that if you try to use the search textbox and click the seach button it gets this exception:
Unable to validate data. at System.Web.Configuration.MachineKeySection.EncryptOrDecryptData(Boolean fEncrypt, Byte[] buf, Byte[] modifier, Int32 start, Int32 length, IVType ivType, Boolean useValidationSymAlgo)
at System.Web.UI.ObjectStateFormatter.Deserialize(String inputString)
This is what i have tryed to do:
Make the gridview not spgridview and set autogenerate true (works)
Remove the datakeynames (works)
Test with a empty gridvew (failes)
Test with a non-empty gridview (failes)
Change Machine Keys (failes)
Turn of view state on the gridvew (failes)
Move the gridview ti a ascx file (failes)
I can't seem to figure this one out. Have enyone got this error and been able to work around it?
EDit 10.09.2009
This is the last code I tested. I used a MSDN excample as referance. I have also tried without Data table MSDN Example
public class TestErrorGridView : System.Web.UI.WebControls.WebParts.WebPart
{
Control ascxToAdd;
protected DataTable PropertyCollection = new DataTable();
private DataColumn key;
public TestErrorGridView()
{
key = PropertyCollection.Columns.Add("ID", typeof(string));
PropertyCollection.Columns.Add("Name", typeof(string));
}
public void AddProperty(TestBindObject data)
{
DataRow newRow = PropertyCollection.Rows.Add();
newRow["ID "] = data.ID;
newRow["Name"] = data.Name;
}
public void BindGrid(SPGridView grid)
{
SPBoundField fldPropertyName = new SPBoundField();
fldPropertyName.HeaderText = "ID";
fldPropertyName.DataField = "ID";
grid.Columns.Add(fldPropertyName);
SPBoundField fldPropertyValue = new SPBoundField();
fldPropertyValue.HeaderText = "Name";
fldPropertyValue.DataField = "Name";
grid.Columns.Add(fldPropertyValue);
PropertyCollection.PrimaryKey = new DataColumn[] { key };
grid.DataSource = PropertyCollection.DefaultView;
grid.DataKeyNames = new string[] { key.ColumnName };
grid.DataBind();
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
}
protected override void CreateChildControls()
{
base.CreateChildControls();
TestBindObject t1 = new TestBindObject() { ID = 1, Name = "Test3" };
this.AddProperty(t1);
SPGridView testGrid = new SPGridView() { AutoGenerateColumns = false };
this.BindGrid(testGrid);
this.Controls.Add(testGrid);
}
}
[Serializable]
public class TestBindObject
{
public int ID { get; set; }
public string Name { get; set; }
}
From the error message I'd say that you are operating in a web-farm environment. Have you set the same machineKey in each of the SharePoint web.config files? See this link for a little more info.

Resources