Changes in cache saved in database before calling Persist() - acumatica

I have created a new grid with Case classes in Contract Template screen which updates case classes for particular Contract Template. There is a checkbox for every case class in the grid and when I check/Uncheck, RowUpdatedEventHandler is triggered and I am updating the contents of Cache.
I have overridden Persist() to save the contents of the cache in Database. But before Persist() is being called the changes are saved in the database and the cache is cleared.Please, Someone help me with this
protected void CRCaseClass_RowUpdated(PXCache sender, PXRowUpdatedEventArgs
e)
{
CRCaseClass newrow = (CRCaseClass)e.Row;
CRCaseClass oldrow = (CRCaseClass)e.OldRow;
ContractTemplate row = contracts.Current;
CaseContract c = new CaseContract();
CRCaseClassExt newrow_ext =
PXCache<CRCaseClass>.GetExtension<CRCaseClassExt>(newrow);
CRCaseClassExt oldrow_ext =
PXCache<CRCaseClass>.GetExtension<CRCaseClassExt>(oldrow);
c.CaseClassID = newrow.CaseClassID;
c.ContractID = row.ContractID;
c.Active = newrow_ext.Check.Value;
caseContract.Insert(c);
}
[PXOverride]
public void Persist()
{
bool c = caseContract.Cache.IsInsertedUpdatedDeleted;
CaseContract cc = null;
IEnumerable cacheRecords = caseContract.Cache.Inserted;
List<CaseContract> recordsToBePersisted = new List<CaseContract>();
ContractTemplate row = contracts.Current;
foreach (CaseContract cr in cacheRecords)
{
PXResultset<CaseContract> v = PXSelect<CaseContract, Where<CaseContract.contractID,
Equal<Required<ContractTemplate.contractID>>, And<CaseContract.caseClassID,
Equal<Required<CRCaseClass.caseClassID>>>>>.Select(Base, row.ContractID, cr.CaseClassID);
if (v.Count != 0 && v.Count == 1)
{
cc = v.GetEnumerator().Current;
cc.Active = cr.Active;
}
else if (v.Count == 0)
{
cc = new CaseContract();
cc.CaseClassID = cr.CaseClassID;
cc.ContractID = cr.ContractID;
cc.Active = cr.Active;
}
else {
//Error Logic
}
recordsToBePersisted.Add(cc);
}
//clean all cache
//insert all values from recordsToBePersisted
caseContract.Cache.Clear();
foreach (CaseContract i in recordsToBePersisted) {
caseContract.Insert(i);
}
Base.Persist();

The Acumatica way to override virtual methods in BLC extensions is slightly different from what you get used to with the .Net framework. Below is the updated version of your code, that should resolve the issue with empty caches. For more details on this topic, please refer to the Acumatica Customization Guide
[PXOverride]
public void Persist(Action del)
{
bool c = caseContract.Cache.IsInsertedUpdatedDeleted;
CaseContract cc = null;
IEnumerable cacheRecords = caseContract.Cache.Inserted;
List<CaseContract> recordsToBePersisted = new List<CaseContract>();
ContractTemplate row = contracts.Current;
foreach (CaseContract cr in cacheRecords)
{
PXResultset<CaseContract> v = PXSelect<CaseContract, Where<CaseContract.contractID,
Equal<Required<ContractTemplate.contractID>>, And<CaseContract.caseClassID,
Equal<Required<CRCaseClass.caseClassID>>>>>.Select(Base, row.ContractID, cr.CaseClassID);
if (v.Count != 0 && v.Count == 1)
{
cc = v.GetEnumerator().Current;
cc.Active = cr.Active;
}
else if (v.Count == 0)
{
cc = new CaseContract();
cc.CaseClassID = cr.CaseClassID;
cc.ContractID = cr.ContractID;
cc.Active = cr.Active;
}
else
{
//Error Logic
}
recordsToBePersisted.Add(cc);
}
//clean all cache
//insert all values from recordsToBePersisted
caseContract.Cache.Clear();
foreach (CaseContract i in recordsToBePersisted)
{
caseContract.Insert(i);
}
del();
}

Related

Add an additional line on the grid

I am looking for help, I hope I can solve this problem.
I've created a new screen and I'm filtering all the Revalue Accounts information.
With this screen, what I want to do is insert and at the same time add an additional new line within the grid.
Here is my new created screen and the button that inserts GLTran
I am attaching an image where I want the line to be added at insert time
Here I share code that I have and it does not work for the additional line.
private void CreateDNGL(Batch batch)
{
var graph = PXGraph.CreateInstance<JournalEntry>();
if (graph.BatchModule.Current == null)
{
Batch cmbatch = new Batch();
cmbatch.BranchID = batch.BranchID;
cmbatch.Module = batch.Module;
cmbatch.Status = "U";
cmbatch.AutoReverse = true;
cmbatch.Released = true;
cmbatch.Hold = false;
cmbatch.CuryDebitTotal = batch.CuryDebitTotal;
cmbatch.CuryCreditTotal = batch.CuryCreditTotal;
cmbatch.FinPeriodID = batch.FinPeriodID;
cmbatch.CuryID = batch.CuryID;
cmbatch.CuryInfoID = batch.CuryInfoID;
cmbatch.DebitTotal = batch.DebitTotal;
cmbatch.CreditTotal = batch.CreditTotal;
cmbatch.Description = "Head new insert";
cmbatch = graph.BatchModule.Insert(cmbatch);
}
foreach (GLTran item in PXSelect<GLTran,
Where<GLTran.module, Equal<Required<GLTran.module>>,
And<GLTran.batchNbr, Equal<Required<GLTran.batchNbr>>>>>.Select(this, batch.Module, batch.BatchNbr))
{
GLTran tran = new GLTran();
tran.SummPost = item.SummPost;
tran.ZeroPost = false;
tran.DebitAmt = item.DebitAmt;
tran.CreditAmt = item.CreditAmt;
tran.CuryDebitAmt = item.CuryDebitAmt;
tran.CuryCreditAmt = item.CuryCreditAmt;
tran.AccountID = item.AccountID;
tran.SubID = item.SubID;
tran.LineNbr = item.LineNbr;
tran.LedgerID = item.LedgerID;
tran.TranType = item.TranType;
tran.TranClass = item.TranClass;
tran.RefNbr = string.Empty;
tran.FinPeriodID = item.FinPeriodID;
tran.TranDesc = "Test detail";
tran.Released = true;
tran.ReferenceID = item.ReferenceID;
tran = graph.GLTranModuleBatNbr.Insert(tran);
Account account = PXSelect<Account, Where<Account.accountID,
Equal<Required<Account.accountID>>>>.Select(graph, item.AccountID);
xLocEquivalAcct equivalAcct = PXSelect<xLocEquivalAcct, Where<xLocEquivalAcct.acctCD,
Equal<Required<xLocEquivalAcct.acctCD>>>>.Select(graph, account.AccountCD);
if (equivalAcct != null)
{
/*here is added for an additional line*/
var glTran = graph.GLTranModuleBatNbr.Insert();
graph.GLTranModuleBatNbr.SetValueExt<GLTran.accountID>(glTran, 343567);
graph.GLTranModuleBatNbr.SetValueExt<GLTran.subID>(glTran, 281);
glTran.TranDesc = "add extra line";
if (item.DebitAmt != 0m && item.CreditAmt == 0m)
{
if (batch.Module == BatchModule.CM)
{
graph.GLTranModuleBatNbr.SetValueExt<GLTran.curyDebitAmt>(glTran, item.CuryDebitAmt);
graph.GLTranModuleBatNbr.SetValueExt<GLTran.debitAmt>(glTran, item.DebitAmt);
}
}
if (item.CreditAmt != 0m && item.DebitAmt == 0m)
{
if (batch.Module == BatchModule.CM)
{
graph.GLTranModuleBatNbr.SetValueExt<GLTran.curyCreditAmt>(glTran, item.CuryCreditAmt);
graph.GLTranModuleBatNbr.SetValueExt<GLTran.creditAmt>(glTran, item.CreditAmt);
}
}
glTran = graph.GLTranModuleBatNbr.Update(glTran);
}
}
graph.Save.Press();
}
I hope I was clear with my question.
This code will create a copy of the originating batch and insert additional lines.
#Warning Your original code was attempting to create a batch that was already released but unposted. I can update my answer to match your requirement but this will break Acumatica work-flow.
Please find code example below :
public class JournalEntryExtension : PXGraphExtension<JournalEntry>
{
public PXAction<Batch> CopyCreate;
//CommitChanges being set to false allows the graph to not be considered dirty when there are errors that we manually show on screen. Case #207998
[PXButton(CommitChanges = false)]
[PXUIField(DisplayName = "Copy Create", MapEnableRights = PXCacheRights.Update, MapViewRights = PXCacheRights.Update, Enabled = true)]
protected virtual IEnumerable copyCreate(PXAdapter pxAdapter)
{
if (Base.BatchModule.Current != null)
{
if (Base.IsDirty)
{
Base.BatchModule.Ask("You must discard your unsaved changes to be able to press this button.", MessageButtons.OK);
}
else
{
Batch batch = Base.BatchModule.Current;
PXLongOperation.StartOperation(this, () => CreateDNGL(batch));
}
}
return pxAdapter.Get();
}
private static void CreateDNGL(Batch batch)
{
JournalEntry graph = PXGraph.CreateInstance<JournalEntry>();
Batch newBatch = PXCache<Batch>.CreateCopy(batch);
newBatch.NoteID = null;
newBatch.Description = "Test header";
newBatch = graph.BatchModule.Insert(newBatch);
GLTran newTran;
foreach (GLTran tran in PXSelectReadonly<GLTran,
Where<GLTran.module, Equal<Required<GLTran.module>>,
And<GLTran.batchNbr, Equal<Required<GLTran.batchNbr>>>>>.Select(graph, batch.Module, batch.BatchNbr))
{
newTran = PXCache<GLTran>.CreateCopy(tran);
newTran.Module = null;
newTran.BatchNbr = null;
newTran.NoteID = null;
newTran.TranDesc = "Test detail";
newTran = graph.GLTranModuleBatNbr.Insert(newTran);
}
if (true)
{
newTran = graph.GLTranModuleBatNbr.Insert();
newTran.AccountID = 1190;
newTran.SubID = 467;
newTran.CuryDebitAmt = 1000;
newTran.TranDesc = "Additional Line 1";
newTran = graph.GLTranModuleBatNbr.Update(newTran);
newTran = graph.GLTranModuleBatNbr.Insert();
newTran.AccountID = 1190;
newTran.SubID = 467;
newTran.CuryCreditAmt = 1000;
newTran.TranDesc = "Additional Line 2";
newTran = graph.GLTranModuleBatNbr.Update(newTran);
}
graph.Save.Press();
}
}
Original Batch :
New Batch :

Unable to open SO screen SO301000 using Action from Quote screen CR304500

I have created a Action called CREATE SO in Sales Quote screen to create Sales order.
I am unable to open the sales order screen using this action. though the sales order is getting created
but the SO screen is not opening while creating the SO. I am not sure where i am making mistake in my code. Please suggest. Thanks.
#region Create Sales Order
public PXAction<CRQuote> createSalesOrder;
[PXUIField(DisplayName = "Create SO", MapEnableRights = PXCacheRights.Update, MapViewRights = PXCacheRights.Update)]
[PXProcessButton(CommitChanges = true)]
public IEnumerable CreateSalesOrder(PXAdapter adapter)
{
QuoteMaint graphObject = PXGraph.CreateInstance<QuoteMaint>();
foreach (CRQuote quote in adapter.Get())
{
//Create resultset for Quote Details
PXResultset<CROpportunityProducts> PXSetLine = PXSelect<CROpportunityProducts,
Where<CROpportunityProducts.quoteID,
Equal<Required<CROpportunityProducts.quoteID>>>>.Select(this.Base, quote.QuoteID);
List<CROpportunityProducts> QuoteList = new List<CROpportunityProducts>();
foreach (CROpportunityProducts line in PXSetLine)
{
QuoteList.Add(line);
}
PXLongOperation.StartOperation(this, () => CreateSalesOrderMethod(quote, QuoteList));
yield return quote;
}
}
//Private Method for Create Sales Order
public virtual void CreateSalesOrderMethod(CRQuote quote, List<CROpportunityProducts> QuoteList)
{
//Base.Save.Press();
bool var_orderCreated = false;
bool erroroccured = false;
string ErrMsg = "";
SOOrderEntry orderGraphObjet = PXGraph.CreateInstance<SOOrderEntry>();
SOOrder orderHeaderObject = new SOOrder();
QuoteMaint currGRPH = PXGraph.CreateInstance<QuoteMaint>();
BAccount customer = PXSelect<BAccount, Where<BAccount.bAccountID, Equal<Current<CRQuote.bAccountID>>>>.Select(this.Base, quote.BAccountID);
if (customer.Type == "CU")
{
orderHeaderObject.CustomerID = quote.BAccountID;
}
else
{
throw new PXException("Business Account not converted to Customer yet"); // THIS ERROR IS ALSO NOT SHOWING WHILE ENCOUNTERING.
}
orderHeaderObject.CuryOrderTotal = quote.CuryProductsAmount;
orderHeaderObject.CuryTaxTotal = quote.CuryTaxTotal;
orderHeaderObject.OrderDesc = quote.Subject;
orderHeaderObject = orderGraphObjet.CurrentDocument.Insert(orderHeaderObject);
orderGraphObjet.CurrentDocument.Current = orderHeaderObject;
orderGraphObjet.Actions.PressSave();
orderHeaderObject = orderGraphObjet.CurrentDocument.Current;
foreach (CROpportunityProducts tran in QuoteList)
{
SOLine transline = new SOLine(); //EMPTY DAC OBJECT
transline.OrderNbr = orderHeaderObject.OrderNbr;
transline.BranchID = orderHeaderObject.BranchID;
transline.InventoryID = tran.InventoryID;
transline.TranDesc = tran.Descr;
transline.UOM = tran.UOM;
transline.OrderQty = tran.Quantity;
transline.SiteID = tran.SiteID;
transline.CuryUnitPrice = tran.CuryUnitPrice;
transline.CuryExtPrice = tran.CuryExtPrice;
orderGraphObjet.Transactions.Insert(transline); //INSERT DAC INTO DATAVIEW
CROpportunityProductsExt xOppProductExt = PXCache<CROpportunityProducts>.GetExtension<CROpportunityProductsExt>(tran);
SOLineExt _soLext = PXCache<SOLine>.GetExtension<SOLineExt>(transline); // GET DAC ENTENSION
_soLext.UsrXSeqID = xOppProductExt.UsrXSequenceID;
_soLext.UsrXGroupID = xOppProductExt.UsrXGroupID;
_soLext.UsrInternalRemk = xOppProductExt.UsrInternalRemk; // ASSIGN CUSTOM FIELDS
orderGraphObjet.Transactions.Update(transline); // UPDATE DAC OBJECT IN DATAVIEW
}
orderGraphObjet.Actions.PressSave();
var_orderCreated = true;
//if (orderGraphObjet != null && orderHeaderObject != null)
if (var_orderCreated)
{
orderGraphObjet.Document.Current = orderHeaderObject; // HERE I AM GETTING THE OrderType as well as OrderNbr to open the Document.
throw new PXRedirectRequiredException(orderGraphObjet, "Document") { Mode = PXBaseRedirectException.WindowMode.NewWindow };
}
}
#endregion
}
}
The issue is that the redirection is in the PXLongOperation. A PXLongOperation starts a separate thread that is not related with the UI. In order to solve this you can use the PXCustomInfo structure to talk back with the UI thread after the long operation finishes and thus be able to redirect to the so screen.
// PXCustomInfoDefinition
public sealed class SORedirectionCustomInfo: IPXCustomInfo
{
private PXGraph _OrderGraph;
public SORedirectionCustomInfo(PXGraph orderGraph)
{
_OrderGraph = orderGraph;
}
public void Complete(PXLongRunStatus status, PXGraph graph)
{
if (status == PXLongRunStatus.Completed && graph is <YourQuoteGraphType>)
{
throw new PXRedirectRequiredException(orderGraphObjet, "Document") { Mode = PXBaseRedirectException.WindowMode.NewWindow };
}
}
}
// Long Operation Method
public virtual void CreateSalesOrderMethod(CRQuote quote, List<CROpportunityProducts> QuoteList)
{
// Your code to create SO....
if (var_orderCreated)
{
PXLongOperation.SetCustomInfo(new SORedirectionCustomInfo(orderGraphObjet));
}
}
This should be able to redirect successfully once the long operation is completed and the order is created.

how to attach an XML file in the "Files" tab of an action

I have a big question, you can attach XML through an action, when you import the XML and also save it in the "Files" tab, the question is. if it can be attached?.
Here is an example image:
what is missing is that I automatically attach in the "Files" tab, when I put upload
Here is my code where, I attached the XML
public PXAction<ARInvoice> CargarXML;
[PXUIField(DisplayName = "Carga de código hash")]
[PXButton()]
public virtual void cargarXML()
{
var Result = NewFilePanel.AskExt(true);
if (Result == WebDialogResult.OK)
{
PX.SM.FileInfo fileInfo = PX.Common.PXContext.SessionTyped<PXSessionStatePXData>().FileInfo["CargaSessionKey"];
string result = System.Text.Encoding.UTF8.GetString(fileInfo.BinData);
ARInvoice ari = Base.Document.Current;
xtFECodHashEntry graph2 = PXGraph.CreateInstance<xtFECodHashEntry>();
var pchExt = ari.GetExtension<ARRegisterExt>();
string Valor = "";
XmlDocument xm = new XmlDocument();
xm.LoadXml(result);
XmlNodeList elemList = xm.GetElementsByTagName("ds:DigestValue");
for (int i = 0; i < elemList.Count;)
{
Valor = (elemList[i].InnerXml);
break;
}
PXLongOperation.StartOperation(Base, delegate ()
{
xtFECodHash dac = new xtFECodHash();
dac.RefNbr = ari.RefNbr;
dac.DocType = ari.DocType;
dac.Nrocomprobante = ari.InvoiceNbr;
dac.Hash = Valor;
dac.Tipo = pchExt.UsrTDocSunat;
graph2.xtFECodHashs.Insert(dac);
graph2.Actions.PressSave();
});
}
}
If you have the FileInfo object which it seems like you do I have used something like this:
protected virtual void SaveFile(FileInfo fileInfo, PXCache cache, object row)
{
if (fileInfo == null)
{
return;
}
var fileGraph = PXGraph.CreateInstance<UploadFileMaintenance>();
if (!fileGraph.SaveFile(fileInfo, FileExistsAction.CreateVersion))
{
return;
}
if (!fileInfo.UID.HasValue)
{
return;
}
PXNoteAttribute.SetFileNotes(cache, row, fileInfo.UID.Value);
}
So in your example you could call this method as shown above using the following:
SaveFile(fileInfo, Base.Document.Cache, Base.Document.Current);

Inserting new Activity for Case Screen by code

I am trying to insert a new Activity for Case. The code which I have written executes without any error but it even does not inserts any Activity. Let me know if I am missing anything.
Here is the code
CRActivity actiCloud9 = new CRActivity();
actiCloud9.Type = "N"; // Note
actiCloud9.Subject = current.Summary;
actiCloud9.Body = current.Description;
actiCloud9.UIStatus = current.Status;
actiCloud9.StartDate = current.StartDate;
actiCloud9.IsPrivate = true; // current.IsInternal;
actiCloud9.RefNoteID = Base.CaseCurrent.Current.NoteID;
Base.Activities.Cache.Insert(actiCloud9);
Try this.
[PXOverride]
public void Persist(Action del)
{
if ((Base.Case.Cache.GetStatus(Base.Case.Current) == PXEntryStatus.Inserted || Base.Case.Cache.GetStatus(Base.Case.Current) == PXEntryStatus.Updated))
{
CRActivityMaint objGraph = PXGraph.CreateInstance<CRActivityMaint>();
CRActivity actiCloud9 = new CRActivity();
actiCloud9.Type = "N"; // Note
actiCloud9.Subject = "Subject";
actiCloud9.Body = "Body";
actiCloud9.RefNoteID = Base.CaseCurrent.Current.NoteID;
objGraph.Activities.Cache.Insert(actiCloud9);
objGraph.Actions.PressSave();
}
del();
}

Sharepoint 2010 custom webpart paging

I am trying to implement simple paging on my sharepoint webpart. I have a single news articles list which has some simple columns. I want to be able to have then five on a page and with some numerical paging at the bottom. I have gone through the net trying to understand splistitemcollectionposition but with no luck. If anyone can help please can you give me a simple code example or some guidanc
Many thanks
Chris
I would suggest using SPDataSource and a SPGridView, together they will implement paging and many other cool features with minimal or no code.
Use this a a guide for some of the classes/methods/properties you might need to use to get paging to work. Be aware that this code does not compile, i have just pulled together various code snippets that i have in my own list results framework, which includes paging, sorting, grouping and caching. It should be enough to get you started though.
public class PagedListResults : System.Web.UI.WebControls.WebParts.WebPart {
protected SPPagedGridView oGrid;
protected override void CreateChildControls() {
this.oGrid = new SPPagedGridView();
oGrid.AllowPaging = true;
oGrid.PageIndexChanging += new GridViewPageEventHandler(oGrid_PageIndexChanging);
oGrid.PagerTemplate = null; // Must be called after Controls.Add(oGrid)
oGrid.PagerSettings.Mode = PagerButtons.NumericFirstLast;
oGrid.PagerSettings.PageButtonCount = 3;
oGrid.PagerSettings.Position = PagerPosition.TopAndBottom;
base.CreateChildControls();
}
public override void DataBind() {
base.DataBind();
SPQuery q = new SPQuery();
q.RowLimit = (uint)info.PageSize;
if (!string.IsNullOrEmpty(info.PagingInfoData)) {
SPListItemCollectionPosition pos = new SPListItemCollectionPosition(info.PagingInfoData);
q.ListItemCollectionPosition = pos;
} else {
//1st page, dont need a position, and using a position breaks things
}
q.Query = info.Caml;
SPListItemCollection items = SPContext.Current.List.GetItems(q);
FilterInfo info = null;
string tmp = "<View></View>";
tmp = tmp.Replace("<View><Query>", string.Empty);
tmp = tmp.Replace("</Query></View>", string.Empty);
info.Caml = tmp;
info.PagingInfoData = string.Empty;
info.CurrentPage = oGrid.CurrentPageIndex;
info.PageSize = oGrid.PageSize;
if (oGrid.PageIndex == 0 || oGrid.CurrentPageIndex == 0) {
//do nothing
} else {
StringBuilder value = new StringBuilder();
value.Append("Paged=TRUE");
value.AppendFormat("&p_ID={0}", ViewState[KEY_PagingPrefix + "ID:" + oGrid.PageIndex]);
info.PagingInfoData = value.ToString();
}
int pagecount = (int)Math.Ceiling(items.Count / (double)oGrid.PageSize);
for (int i = 1; i < pagecount; i++) { //not always ascending index numbers
ResultItem item = items[(i * oGrid.PageSize) - 1];
ViewState[KEY_PagingPrefix + "ID:" + i] = item.ID;
}
oGrid.VirtualCount = items.Count;
DateTime time3 = DateTime.Now;
DataTable table = new DataTable("Data");
DataBindListData(table, items);
this.oGrid.DataSource = table;
this.oGrid.DataBind();
this.oGrid.PageIndex = oGrid.CurrentPageIndex; //need to reset this after DataBind
}
void oGrid_PageIndexChanging(object sender, GridViewPageEventArgs e) {
oGrid.PageIndex = e.NewPageIndex;
oGrid.CurrentPageIndex = oGrid.PageIndex;
}
}
public class FilterInfo {
public string Caml;
public string PagingInfoData;
public int CurrentPage;
public int PageSize;
}
public class SPPagedGridView : SPGridView {
protected override void InitializePager(GridViewRow row, int columnSpan, PagedDataSource pagedDataSource) {
pagedDataSource.AllowCustomPaging = true;
pagedDataSource.VirtualCount = virtualcount;
pagedDataSource.CurrentPageIndex = currentpageindex;
base.InitializePager(row, columnSpan, pagedDataSource);
}
private int virtualcount = 0;
public int VirtualCount {
get { return virtualcount; }
set { virtualcount = value; }
}
private int currentpageindex = 0;
public int CurrentPageIndex {
get { return currentpageindex; }
set { currentpageindex = value; }
}
}
check out my post on how to page using SPListItemCollectionPosition, I did a component to page over lists, maybe it can help -> http://hveiras.wordpress.com/2011/11/07/listpagert-using-splistitemcollectionposition/

Resources