I am trying to create an Adjustment to my stock as I am scanning the item.
The code works and the adjustment is released as expected. The problem is the data is not submitted to SQL before the base method is invoked. Is there a way to force the data to be pushed to SQL before the base method is called?
I have tried adding a PXTransactionScope but after the ts.complete the data on SQL has not been updated
[PXOverride]
public virtual void ProcessLotSerialBarcode(string barcode, ProcessLotSerialBarcodeDelegate baseMethod)
{
string LotnumberWithOutPrf =// code to extract Lotnumber from QR code
//check if lot has stock
INItemLotSerial iNItemLotSerial = PXSelect<
INItemLotSerial,
Where<INItemLotSerial.lotSerialNbr, Equal<Required<INItemLotSerial.lotSerialNbr>>,
And<INItemLotSerial.inventoryID, Equal<Required<INItemLotSerial.inventoryID>>>>>
.Select(Base, Lotnumber, Base.HeaderView.Current.InventoryID);
//if there is no stock do adjustment
if (iNItemLotSerial.QtyHardAvail == 0)
{
using (PXTransactionScope ts = new PXTransactionScope())
{
INAdjustmentEntry iNAdjustmentEntryEntry = PXGraph.CreateInstance<INAdjustmentEntry>();
INRegister iNRegister = new INRegister();
iNRegister.ExtRefNbr = "N/A";
iNRegister.TranDesc = "Adjustment for Shipment: " + Base.HeaderView.Current.RefNbr;
iNRegister.Hold = false;
iNAdjustmentEntryEntry.adjustment.Insert(iNRegister);
INTran iNTran = iNAdjustmentEntryEntry.transactions.Insert();
iNTran.InventoryID = Base.HeaderView.Current.InventoryID;
iNTran.SiteID = 9;
iNTran.LocationID = 77;
iNTran.Qty = 1;
iNTran.UOM = Base.HeaderView.Current.UOM;
iNAdjustmentEntryEntry.transactions.Update(iNTran);
iNTran.LotSerialNbr = LotnumberWithOutPrf;
iNAdjustmentEntryEntry.transactions.Update(iNTran);
iNAdjustmentEntryEntry.Save.PressButton();
iNAdjustmentEntryEntry.release.Press();
iNAdjustmentEntryEntry.Save.PressButton();
iNAdjustmentEntryEntry.Cancel.PressButton();
ts.Complete(Base);
}
}
baseMethod?.Invoke(LotnumberWithOutPrf);
}
Related
I’m writing a customization to add records to a timecard and I’m trying to create a new record to add to the timecard. Using the logic in T230 I’m creating a variable and I’m being told by the compiler that EPTimecardDetail cannot be found.
I’ve added using PX.Objects.EP and PX.Objects.PM but I figure that if TimeCardMaint can be found then EPTimecardDetail should be able be found as well. I’ve included my using code as well but I think I’m missing something else.
using System;
using System.Collections;
using PX.Data;
using PX.Data.BQL.Fluent;
using PX.Data.BQL;
using PX.Objects.CS;
using PX.Objects.PM;
using PX.Objects.EP;
using PX.Objects.CR;
using PX.Objects.AR;
using PX.Objects.CT;
using PX.Objects.GL.FinPeriods;
using PX.TM;
using System.Collections.Generic;
namespace TimecardImport
{
public class NLTimecardLineEntry : PXGraph<NLTimecardLineEntry>
{
private static void DoPopulateTimeCard(Int32 employeeID, DateTime startDate, NLTimecardLine record)
{
TimeCardMaint graph = PXGraph.CreateInstance<TimeCardMaint>();
Int32 cardWeekID = PXWeekSelector2Attribute.GetWeekID(graph, startDate);
//look for an employee timecard with the current weekID
EPTimeCard card = PXSelectReadonly<EPTimeCard,
Where<EPTimeCard.employeeID, Equal<Required<EPTimeCard.employeeID>>,
And<EPTimeCard.weekId, Equal<Required<EPTimeCard.weekId>>>>>.SelectWindowed(graph, 0, 1, employeeID, cardWeekID);
if (card == null) //if a card was not found, create one
{
card = (EPTimeCard)graph.Document.Cache.CreateInstance();
card.WeekID = cardWeekID;
card.EmployeeID = employeeID;
card = graph.Document.Insert(card);
}
//at this point card is the card that we're going to work with
var detailLine = (EPTimecardDetail)graph.Activities.Cache.CreateCopy(
graph.Activities.Insert());
//detailLine.SetValueExt<detailLine.Date_Date>(record, record.InDate);
//detailLine.EarningTypeID = "RG";
//detailLine = graph.Activities.Update(detailLine);
graph.Save.Press();
}
}}
The error I'm getting is "The type or namespace name 'EPTimecardDetail' could not be found (are you missing a using directive or an assembly reference?)".
EPTimecardDetail is defined within PX.Objects.EP so I'm not sure why I'm having a problem there. Or, perhaps this is not the way to add records to the Details tab of the Employee Time Card screen?
For the namespace issue you can declare using PX.Object.EP and refer to the type as TimeCardMaint.EPTimecardDetail
Or you can declare using static PX.Objects.EP.TimeCardMaint and refer to the type as EPTimecardDetail
For inserting the record check the source code in file TimeCardMaint.cs There are examples on how to insert this DAC record.
Make sure the fields used for SQL joins like OrigNoteID and RefNoteID have the proper value (non null).
This example is from the Correct action in TimeCardMaint:
[PXUIField(DisplayName = Messages.Correct)]
[PXButton(ImageKey = PX.Web.UI.Sprite.Main.Release)]
public virtual IEnumerable Correct(PXAdapter adapter)
{
if (Document.Current != null)
{
EPTimeCard source = GetLastCorrection(Document.Current);
if (source.IsReleased != true)
return new EPTimeCard[] { source };
EPTimeCard newCard = (EPTimeCard)Document.Cache.CreateInstance();
newCard.WeekID = source.WeekID;
newCard.OrigTimeCardCD = source.TimeCardCD;
newCard = Document.Insert(newCard);
newCard.EmployeeID = source.EmployeeID;
PXNoteAttribute.CopyNoteAndFiles(Document.Cache, source, Document.Cache, newCard, true, true);
bool failed = false;
Dictionary<string, TimeCardSummaryCopiedInfo> summaryDescriptions = new Dictionary<string, TimeCardSummaryCopiedInfo>();
foreach (EPTimeCardSummary summary in Summary.View.SelectMultiBound(new object[] { source }))
{
string key = GetSummaryKey(summary);
if (!summaryDescriptions.ContainsKey(key))
{
string note = PXNoteAttribute.GetNote(Summary.Cache, summary);
var info = new TimeCardSummaryCopiedInfo(summary.Description, note);
summaryDescriptions.Add(key, info);
}
}
foreach (EPTimecardDetail act in TimecardActivities.View.SelectMultiBound(new object[] { source }))
{
EPTimecardDetail newActivity = PXCache<EPTimecardDetail>.CreateCopy(act);
newActivity.Released = false;
newActivity.Billed = false;
newActivity.NoteID = null;
newActivity.TimeCardCD = null;
newActivity.TimeSheetCD = null;
newActivity.OrigNoteID = act.NoteID; //relation between the original activity and the corrected one.
newActivity.Date = act.Date;
newActivity.Billed = false;
newActivity.SummaryLineNbr = null;
newActivity.NoteID = null;
newActivity.ContractCD = null;
isCreateCorrectionFlag = true;
try
{
newActivity = Activities.Insert(newActivity);
}
catch (PXSetPropertyException ex)
{
failed = true;
Activities.Cache.RaiseExceptionHandling<EPTimecardDetail.summary>(act, act.Summary, new PXSetPropertyException(ex.MessageNoPrefix, PXErrorLevel.RowError));
continue;
}
newActivity.TrackTime = act.TrackTime; //copy as is.
isCreateCorrectionFlag = false;
newActivity.ApprovalStatus = ActivityStatusAttribute.Completed;
newActivity.RefNoteID = act.NoteID == act.RefNoteID ? newActivity.NoteID : act.RefNoteID;
newActivity.ContractCD = act.ContractCD;
PXNoteAttribute.CopyNoteAndFiles(Activities.Cache, act, Activities.Cache, newActivity);
Activities.Cache.SetValue<EPTimecardDetail.isCorrected>(act, true);
Activities.Cache.SetStatus(act, PXEntryStatus.Updated);
}
if (failed)
{
throw new PXException(Messages.FailedToCreateCorrectionTC);
}
foreach (EPTimeCardItem item in Items.View.SelectMultiBound(new object[] { source }))
{
EPTimeCardItem record = Items.Insert();
record.ProjectID = item.ProjectID;
record.TaskID = item.TaskID;
record.Description = item.Description;
record.InventoryID = item.InventoryID;
record.CostCodeID = item.CostCodeID;
record.UOM = item.UOM;
record.Mon = item.Mon;
record.Tue = item.Tue;
record.Wed = item.Wed;
record.Thu = item.Thu;
record.Fri = item.Fri;
record.Sat = item.Sat;
record.Sun = item.Sun;
record.OrigLineNbr = item.LineNbr;//relation between the original activity and the corrected one.
}
foreach (EPTimeCardSummary summary in Summary.Select())
{
string key = GetSummaryKey(summary);
if (summaryDescriptions.ContainsKey(key))
{
PXNoteAttribute.SetNote(Summary.Cache, summary, summaryDescriptions[key].Note);
Summary.Cache.SetValue<EPTimeCardSummary.description>(summary, summaryDescriptions[key].Description);
}
}
return new EPTimeCard[] { newCard };
}
return adapter.Get();
}
I have BLC code that is parsing out the AuditHistory 'ModifiedFields' field so that I have multiple lines with separate 'Field' and 'Value' fields. The 'ModifiedFields' field contains null separated values, so my BLC C# code uses the split function to put these into an array. This all works fine. The problem I'm having is saving to a table in Acumatica via the Graph / Cache 'insert' function. If I use the 'Actions.PressSave()' method after every iteration of the array, it doesn't save every record - effectively skipping records. I have no idea why this would happen. If I put the 'Actions.PressSave()' method at the very end of everything, I get all the records - but sometimes it times out, I'm assuming because of (in some cases) the massive amount of records being cached before the save.
Putting the PressSave method at ANY other point in the loop(s) results in missed records.
Here is my BLC code (note the several places I placed the PressSave method for testing, but commented out - leaving the last one):
public PXAction<AUAuditSetup> CreateAuditRecords;
[PXProcessButton]
[PXUIField(DisplayName = "Create Audit Records", MapEnableRights = PXCacheRights.Update, MapViewRights = PXCacheRights.Update)]
protected virtual IEnumerable createAuditRecords(PXAdapter adapter)
{
PXLongOperation.StartOperation(Base, delegate ()
{
//Create graph of TAC screen...
var osdm = PXGraph.CreateInstance<OpenSourceDataMaint>();
xTACOpenSourceDetail osd;
int recordID = 1;
//Get records from AuditHistory
//PXResultset<AuditHistory> res = PXSelect<AuditHistory>.Select(Base);
PXResultset<AuditHistory> res = PXSelect<AuditHistory,
Where<AuditHistory.changeDate, GreaterEqual<Required<AuditHistory.changeDate>>>>.Select(Base, Convert.ToDateTime("01/01/2013"));
var companyID = Convert.ToString(PX.Common.PXContext.GetSlot<int?>("singleCompanyID"));
foreach (PXResult<AuditHistory> rec in res)
{
var ah = (AuditHistory)rec;
if (ah != null)
{
string[] fields = ah.ModifiedFields.Split('\0');
for (int i = 0; i < fields.GetUpperBound(0); i+=2)
{
osd = new xTACOpenSourceDetail();
osd.OpenSourceName = "AuditHistoryTable";
osd.DataID = "1";
osd.String01 = Convert.ToString(PX.Common.PXContext.GetSlot<int?>("singleCompanyID"));
osd.Number01 = ah.BatchID;
osd.Number02 = ah.ChangeID;
osd.Number03 = recordID;
osd.String02 = ah.ScreenID;
osd.String03 = Convert.ToString(ah.UserID);
osd.Date01 = ah.ChangeDate;
osd.String04 = ah.Operation;
osd.String05 = ah.TableName;
osd.String06 = ah.CombinedKey;
osd.String07 = fields[i];
osd.String08 = fields[i + 1];
osd.String09 = Convert.ToString(ah.ChangeDate);
osdm.OpenSourceDataDetail.Insert(osd);
//if (osd != null)
//osdm.Actions.PressSave();
recordID++;
}
recordID = 1;
//osdm.Actions.PressSave();
}
//osdm.Actions.PressSave();
}
osdm.Actions.PressSave();
});
return adapter.Get();
}
Any ideas?
A couple of things you could try:
Instead of instantiating osd directly, replace with:
osd = osdm.OpenSourceDataDetail.Insert();
and then after assigning values and prior to PressSave(), use .Update on the cache:
osdm.OpenSourceDataDetail.Update(osd);
and then after PressSave(), clear the graph:
osdm.Clear();
Importantly, does your DAC have an IsKey = true on the DataID field and marked PXDBIdentity, hence auto-assigned and unique?
Example:
public abstract class dataID : PX.Data.IBqlField {}
[PXDBIdentity(IsKey = true)]
[PXUIField(Visible = false, Enabled = false)]
public virtual int? DataID {get; set;}
If the changes are successful, you could then try moving the .PressSave() and .Clear() after the For loop.
I have a customization where I have added three user fields to the Sales Order (SO301000) screen transactions grid. I would like to set fields on the 'Create Purchase Order' screen (PO505000). I had used the POFixedDemand's 'RowSelected' event, which works fine - but that causes a problem when anyone tries to modify anything in a row - which re-triggers that event - not a desired outcome.
I've tried the 'RowInserting' and 'RowInserted' events - but they're never triggered. I'm assuming at this point that I'll have to intercept some code in the 'POCreate' BLC that creates the POFixedDemand records in the Create Purchase Order screen - but I don't really know where to start. Would I put it somewhere in the EnumerateAndPrepareFixedDemands method?
Here's the code I created which works for the RowSelected event, but is no good for when a row is modified by a user. Any help is appreciated. Thank you.
protected virtual void POFixedDemand_RowSelected(PXCache sender, PXRowSelectedEventArgs e)
{
var pofd = (POFixedDemand)e.Row;
if (pofd == null) return;
var filter = Base.Filter.Current;
var ordernbr = filter.OrderNbr;
var ordertype = filter.OrderType;
var solinesplit = (SOLineSplit)PXSelect<SOLineSplit, Where<SOLineSplit.planID, Equal<Required<SOLineSplit.planID>>>>.Select(Base, pofd.PlanID);
if (solinesplit != null)
{
var soline = (SOLine)PXSelect<SOLine,
Where<SOLine.orderNbr, Equal<Required<SOLine.orderNbr>>,
And<SOLine.orderType, Equal<Required<SOLine.orderType>>,
And<SOLine.lineNbr, Equal<Required<SOLine.lineNbr>>>>>>.Select(Base, solinesplit.OrderNbr, solinesplit.OrderType, solinesplit.LineNbr);
if (soline != null)
{
var solineext = PXCache<SOLine>.GetExtension<SOLineExt>(soline);
pofd.VendorID = solineext.UsrVendor;
pofd.EffPrice = solineext.UsrVendorUnitCost;
pofd.ExtCost = solineext.UsrVendorExtendedCost;
//Now set the Vendor location...
var location = (Location)PXSelect<Location,
Where<Location.bAccountID, Equal<Required<Location.bAccountID>>>>.Select(Base, pofd.VendorID);
if (location != null)
{
pofd.LocationID = location.LocationID;
}
}
}
}
I'm assuming at this point that I'll have to intercept some code in
the 'POCreate' BLC
Yes you need to do something along those lines.
There's a similar answer here for initializing the POLine instead of POFixedDemand:
https://stackoverflow.com/a/37255340/7376238
With some minor adjustments, the general pattern would be:
public class POCreateExt : PXGraphExtension<POCreate>
{
public override void Initialize()
{
PXGraph.InstanceCreated.AddHandler<POOrderEntry>((graph) =>
{
graph.RowInserting.AddHandler<POFixedDemand>((sender, e) =>
{
// Initialize fields when row is inserted
POFixedDemand demand = e.Row as POFixedDemand;
demand.DACField = [initialization value];
});
graph.RowUpdating.AddHandler<POFixedDemand>((sender, e) =>
{
// Sometimes fields are updated so you need to
// hook RowUpdating too and re-initialize
POFixedDemand demand = e.NewRow as POFixedDemand;
demand.DACField = [initialization value];
});
});
}
}
What I came up with after some investigation is to override the 'EnumerateAndPrepareFixedDemands' method to set the values. Code is as follows:
public delegate IEnumerable EnumerateAndPrepareFixedDemandsDelegate(PXResultset<POFixedDemand> fixedDemands);
[PXOverride]
public IEnumerable EnumerateAndPrepareFixedDemands(PXResultset<POFixedDemand> fixedDemands, EnumerateAndPrepareFixedDemandsDelegate baseMethod)
{
foreach (PXResult<POFixedDemand> rec in fixedDemands)
{
POFixedDemand demand = rec;
var solinesplit = (SOLineSplit)PXSelect<SOLineSplit, Where<SOLineSplit.planID, Equal<Required<SOLineSplit.planID>>>>.Select(Base, demand.PlanID);
if (solinesplit != null)
{
var soline = (SOLine)PXSelect<SOLine,
Where<SOLine.orderNbr, Equal<Required<SOLine.orderNbr>>,
And<SOLine.orderType, Equal<Required<SOLine.orderType>>,
And<SOLine.lineNbr, Equal<Required<SOLine.lineNbr>>>>>>.Select(Base, solinesplit.OrderNbr, solinesplit.OrderType, solinesplit.LineNbr);
if (soline != null)
{
var solineext = PXCache<SOLine>.GetExtension<SOLineExt>(soline);
demand.VendorID = solineext.UsrVendor;
demand.EffPrice = solineext.UsrVendorUnitCost;
demand.ExtCost = solineext.UsrVendorExtendedCost;
//Now set the Vendor location...
var location = (Location)PXSelect<Location,
Where<Location.bAccountID, Equal<Required<Location.bAccountID>>>>.Select(Base, solineext.UsrVendor);
if (location != null)
{
demand.VendorLocationID = location.LocationID;
}
}
}
}
return baseMethod(fixedDemands);
}
I am trying to write a process screen to allocate stock on the sales order in FIFO. The Process screen list all the sales order for a period for allocation.
I have gone through the code LSSOLine and not able to figure out the piece of code where allocation is done. anybody knows how to do it?
Update
I have tried the following code and it is working. Is there any better way to do it?
private static void DoStockAllocation(SOLine row, SOOrderEntry grp)
{
try
{
grp.Document.Current = PXSelect<
SOOrder,
Where<SOOrder.orderType, Equal<Required<SOOrder.orderType>>,
And<SOOrder.orderNbr, Equal<Required<SOOrder.orderNbr>>>>>
.Select(grp, row.OrderType, row.OrderNbr);
if (grp.Document.Current != null && grp.Document.Current.Status == SOOrderStatus.Open)
{
grp.Transactions.Current = row;
PXSelectBase<INLocationStatus> cmd = new PXSelectReadonly2<INLocationStatus,
InnerJoin<INLocation, On<INLocation.locationID, Equal<INLocationStatus.locationID>>,
LeftJoin<INSiteStatus, On<INSiteStatus.inventoryID, Equal<INLocationStatus.inventoryID>,
And<INSiteStatus.subItemID, Equal<INLocationStatus.subItemID>,
And<INSiteStatus.siteID, Equal<INLocationStatus.siteID>>>>>>,
Where<INLocationStatus.inventoryID, Equal<Required<INLocationStatus.inventoryID>>,
And<INLocationStatus.subItemID, Equal<Required<INLocationStatus.subItemID>>,
And<INLocationStatus.siteID, Equal<Required<INLocationStatus.siteID>>,
And<INLocation.salesValid, Equal<boolTrue>,
And<INLocation.inclQtyAvail, Equal<boolTrue>,
And<INLocationStatus.qtyOnHand, Greater<decimal0>>>>>>>>(grp);
foreach (PXResult<INLocationStatus, INLocation, INSiteStatus> ln in cmd.Select(row.InventoryID,row.SubItemID,row.SiteID))
{
INLocationStatus locationStatus = ln;
INSiteStatus siteStatus = ln;
SiteStatus accumsiteavail = new SiteStatus();
PXCache<INSiteStatus>.RestoreCopy(accumsiteavail, siteStatus);
accumsiteavail = (SiteStatus)grp.Caches[typeof(SiteStatus)].Insert(accumsiteavail);
decimal? AvailableQty = 0m;
decimal? SiteAvailableQty = locationStatus.QtyHardAvail;//siteStatus.QtyHardAvail + accumsiteavail.QtyHardAvail;
AvailableQty = SiteAvailableQty;
if (AvailableQty <= 0m)
{
continue;
}
if (row.LocationID == null)
{
row.LocationID = locationStatus.LocationID;
grp.Transactions.Update(row);
}
SOLineSplit split = new SOLineSplit();
if ( grp.splits.Select().Count > 0)
{
split = grp.splits.Select(row.OrderType, row.OrderNbr, row.LineNbr);
}
else
{
split = new SOLineSplit();
split = grp.splits.Insert(split);
split.InventoryID = row.InventoryID;
split.SiteID = row.SiteID;
split.OrderType = row.OrderType;
split.OrderNbr = row.OrderNbr;
split.LineNbr = row.LineNbr;
split.UOM = row.UOM;
split = PXCache<SOLineSplit>.CreateCopy(grp.splits.Update(split));
}
//split.LocationID = locationStatus.LocationID;
split.Qty = (AvailableQty < row.OrderQty) ? AvailableQty : row.OrderQty;
split.IsAllocated = true;
grp.splits.Update(split);
break;
}
grp.Save.Press();
}
}
catch(Exception ex)
{
}
}
You will need to reference the combination of LSSOLine and SOLineSplitPlanID on SOLineSplit.PlanID in your process page. Alternatively you might be able to use an instance of SOOrderEntry to do the updates/mark of allocation.
The following have been copied from the SOOrderEntry graph and are the 2 componenetis from what i can tell that drive the allocation logic. From there you just need to mark the split lines that should be allocated and should be good. Or at least a start. The problem you might have is anything that is looking for current SOOrder. You might have to set the current before marking solines splits as allocated. (assuming i under stand your question correctly)
Manage the allocation records...
public LSSOLine lsselect;
Append the use of SOLineSplitPlanID which drives the INItemPlan records...
[PXMergeAttributes(Method = MergeMethod.Append)]
[SOLineSplitPlanID(typeof(SOOrder.noteID), typeof(SOOrder.hold), typeof(SOOrder.orderDate))]
protected virtual void SOLineSplit_PlanID_CacheAttached(PXCache sender)
{
}
When I release a Cash Sales document, after everything verifies successfully and the GL Batch is created, I execute code which created a second GL Batch that handles other transactions related to the cash sale. After that batch is created, I want to save the second GL Batch's Ref Nbr on the Cash Sales document as well. When I try to save it, I get an error:
Here is my code overriding the normal Release process:
public delegate IEnumerable ReleaseDelegate(PXAdapter adapter);
[PXOverride]
public IEnumerable Release(PXAdapter adapter, ReleaseDelegate baseMethod)
{
ARCashSale cashSale = Base.Document.Current;
PXGraph.InstanceCreated.AddHandler<JournalEntry>(delegate (JournalEntry oldJournalEntry)
{
oldJournalEntry.RowPersisted.AddHandler<Batch>(delegate (PXCache sender, PXRowPersistedEventArgs e)
{
Batch oldBatch = oldJournalEntry.BatchModule.Current;
if (oldBatch != null && isCreated == false && e.Operation == PXDBOperation.Insert && e.TranStatus == PXTranStatus.Completed)
{
isCreated = true;
if (CFBSAdjustments.Select().Count > 0)
{
JournalEntry newJournalEntry = PXGraph.CreateInstance<JournalEntry>();
Batch newBatch = new Batch();
newBatch = newJournalEntry.BatchModule.Insert(newBatch);
Customer customer = PXSelect<Customer, Where<Customer.bAccountID, Equal<Required<Customer.bAccountID>>>>.Select(Base, cashSale.CustomerID);
newBatch.Description = "Fund Entry for Cash Sales Reference " + cashSale.RefNbr;
newBatch.FinPeriodID = oldBatch.FinPeriodID;
newBatch.LedgerID = oldBatch.LedgerID;
newBatch.DateEntered = oldBatch.DateEntered;
decimal? debit = 0;
decimal? credit = 0;
foreach (CFBSCashSalesAdjustment row in CFBSAdjustments.Select())
{
GLTran tran = newJournalEntry.GLTranModuleBatNbr.Insert();
tran.SummPost = true;
tran.BranchID = cashSale.BranchID;
tran.TranType = GLTran.tranClass.Normal;
tran.TranClass = GL.Messages.RoundingDiff;
tran.LedgerID = newBatch.LedgerID;
tran.FinPeriodID = newBatch.FinPeriodID;
tran.TranDate = newBatch.DateEntered;
tran.CuryInfoID = Base.currencyinfo.Current.CuryInfoID;
tran.AccountID = row.Account;
tran.SubID = row.Subaccount;
tran.DebitAmt = row.DebitAmt;
tran.CuryDebitAmt = row.DebitAmt;
debit += row.DebitAmt;
tran.CreditAmt = row.CreditAmt;
tran.CuryCreditAmt = row.CreditAmt;
credit += row.CreditAmt;
tran.RefNbr = row.CashSalesRefNbr;
tran.TranDesc = customer.AcctCD + " - " + customer.AcctName;
newJournalEntry.GLTranModuleBatNbr.Update(tran);
}
newBatch = newJournalEntry.BatchModule.Update(newBatch);
if (GLSetup.Current.GetExtension<GLSetupExt>().UsrAutoRelease == true)
{
newJournalEntry.BatchModule.Current.Hold = false;
newJournalEntry.release.Press();
}
newJournalEntry.Save.Press();
if (isCreated)
isCreated = false;
cashSale.GetExtension<ARRegisterExt>().UsrFundBatch = newJournalEntry.BatchModule.Current.BatchNbr;
//Base.Document.Current.GetExtension<ARRegisterExt>().UsrFundBatch = newJournalEntry.BatchModule.Current.BatchNbr;
//Base.dummy_CATran.View.RequestRefresh();
Base.Document.Update(cashSale);
//TODO - Figure out why the fund batch isn't saving to the Cash Sale
Base.Actions.PressSave();
//Base.dummy_CATran.Cache.ClearQueryCache();
//Base.Persist(typeof(ARCashSale), PXDBOperation.Update);
}
}
});
});
return baseMethod(adapter);
}
I left in all of the different methods I've tried to get the ref nbr to save. I've ever tried to add a field updated handler for the BatchNbr field and force the new number in that way, but it did not work.
EDIT: I also noticed that I cannot successfully set an extended field on the Batch DAC. For example, I have the line newBatch.GetExtension<BatchExt>().ExtRefNbr = cashSale.RefNbr; to set the ref nbr in that document as well, but any time I run 'NewJournal.Press.Save()' it changes the set value of the extended field to null. If anyone knows how to set the extension field, I may be able to work with that instead to go down a different path that may do what I need.
I believe the appropriate place to perform your update is in graph ARDocumentRelease. Try something like this....
public class ARDocumentReleaseExtension : PXGraphExtension<ARDocumentRelease>
{
public override void Initialize()
{
ARSetup setup = Base.arsetup.Current;
Base.ARDocumentList.SetProcessDelegate(
delegate (List<BalancedARDocument> list)
{
List<ARRegister> newlist = new List<ARRegister>(list.Count);
foreach (BalancedARDocument doc in list)
{
newlist.Add(doc);
}
ARDocumentRelease.ReleaseDoc(newlist, true);
CreateSecondBatch(newlist);
}
);
Base.ARDocumentList.SetProcessCaption(PX.Objects.AR.Messages.Release);
Base.ARDocumentList.SetProcessAllCaption(PX.Objects.AR.Messages.ReleaseAll);
}
private void CreateSecondBatch(List<ARRegister> docs)
{
foreach(BalancedARDocument register in docs)
{
if (register.DocType == ARDocType.CashSale)
{
//create the second batch and assign the 2nd ref nbr to the cash sale user field
}
}
}
}