Question

Auto Post Check and Payment doesn't generate Project Transaction

  • 16 February 2024
  • 3 replies
  • 33 views

Userlevel 3
Badge

I do customization on Release of Check and Payment with the goal:

  • When the exchange of currency change, the amount of gain (or loss) will be link to an account
    • Gain mean: the additional revenue which come from the rate of currency → link to account 635
    • Loss mean: the money we loss because of rate of currency → link to account 515
  • This amount of money will be tracked in Project information

For example: I have a Check and Payment Record as following: The cross rate is 26.000 (which is higher than the exchange currency in Bill and Adjustment)

  1. Then release this one will generate a GL transaction as following:
     

    Note: there is a row for Account 635 which include information from APBill and APPayment → this is what I customize

  2. Post GL Transaction: As a result, there is a Project Transactions generated 
     

  3. This cost will be tracked in Project Cost Budget
     

     

However, When I turn on Auto Post on Release, There is no Project Transaction being generated. It leads to the cost isn’t statistical in Project cost budget.

 

Here is the code of my customization

using PX.Common;
using PX.Data;
using PX.Objects.GL;
using System.Collections;

namespace PX.Objects.AP
{
// Acuminator disable once PX1016 ExtensionDoesNotDeclareIsActiveMethod extension should be constantly active
public class APPaymentEntry_Extension : PXGraphExtension<APPaymentEntry>
{
#region Event Handlers
protected class ProcessBatch : IPrefetchable
{
private Batch _Batch;
public Batch Batch
{
get
{
return _Batch;
}
}
public ProcessBatch(Batch batch)
{
_Batch = batch;
}
void IPrefetchable.Prefetch()
{
}
}
protected class ProcessTran : IPrefetchable
{
private GLTran _Tran;
public GLTran Tran
{
get
{
return _Tran;
}
}
private int? _SubID;
private int? _ProjectID;
private int? _TaskID;
public int? SubID
{
get
{
return _SubID;
}
}
public int? ProjectID
{
get
{
return _ProjectID;
}
}
public int? TaskID
{
get
{
return _TaskID;
}
}
public ProcessTran(GLTran tran, int? subID, int? projectID, int? taskID)
{
_Tran = tran;
_SubID = subID;
_ProjectID = projectID;
_TaskID = taskID;
}
void IPrefetchable.Prefetch()
{
}
}

private void PopulateFromAPTran(PXCache cache, PXRowPersistingEventArgs args, bool storeInSlot = false)
{
var tran = (GLTran)args.Row;
if (tran == null || args.Operation != PXDBOperation.Insert || tran.Module != BatchModule.AP) return;
if (storeInSlot)
{
PXContext.SetSlot<ProcessTran>(new ProcessTran(tran, tran.SubID, tran.ProjectID, tran.TaskID));
}
else
{
ProcessTran processTran = PXContext.GetSlot<ProcessTran>();
if (processTran != null && tran == processTran.Tran)
{
tran.SubID = processTran.SubID;
tran.ProjectID = processTran.ProjectID;
tran.TaskID = processTran.TaskID;
}
}
var account = (Account)PXSelectorAttribute.Select<GLTran.accountID>(cache, tran);
//Account account = PXSelect<Account, Where<Account.accountID, Equal<Required<Account.accountID>>>>.Select(Base, tran.AccountID);
// if account is null or Account isn't 635, 515 -> Skip handling.
if (account == null || (account.AccountClassID != "515" && account.AccountClassID != "635")) return;
var currentSub = (Sub)PXSelectorAttribute.Select<GLTran.subID>(cache, tran);
//Sub currentSub = PXSelect<Sub, Where<Sub.subID, Equal<Required<Sub.subID>>>>.Select(Base, tran.SubID);
if (currentSub == null || currentSub.SubCD != "000000000000") return;
// populate SubID from Bill and Adjustment to GLTran
// find index of GLTran Gain and Lost
var docOrder = 0;
var secondGainAndLostClassID = account.AccountClassID == "515" ? "635" : "515";
Account secondGainAndLostAcc = PXSelect<Account, Where<Account.accountClassID, Equal<Required<Account.accountClassID>>>>.Select(Base, secondGainAndLostClassID);
if (secondGainAndLostAcc != null)
{
PXResultset<GLTran> glTranGainAndLost = PXSelect<GLTran,
Where<GLTran.batchNbr, Equal<Required<GLTran.batchNbr>>,
And<GLTran.lineNbr, NotEqual<Required<GLTran.lineNbr>>, And<Where<GLTran.accountID, Equal<Required<GLTran.accountID>>,
Or<GLTran.accountID, Equal<Required<GLTran.accountID>>>>>>>>
.Select(Base, tran.BatchNbr, tran.LineNbr, account.AccountID, secondGainAndLostAcc.AccountID);
docOrder = glTranGainAndLost.Count;
}
else
{
PXResultset<GLTran> glTranGainAndLost = PXSelect<GLTran,
Where<GLTran.batchNbr, Equal<Required<GLTran.batchNbr>>,
And<GLTran.accountID, Equal<Required<GLTran.accountID>>>>>
.Select(Base, tran.BatchNbr, account.AccountID);
docOrder = glTranGainAndLost.Count;
}

// Get list Bill and Adjustment
PXResultset<APAdjust> documentLines = PXSelect<APAdjust, Where<APAdjust.adjgRefNbr, Equal<Required<APPayment.refNbr>>>>.Select(Base, tran.RefNbr);
if (documentLines.Count <= docOrder) return;
APAdjust docLine = documentLines[docOrder];
//get first row of detail tab
APTran firstLine = PXSelect<APTran, Where<APTran.refNbr, Equal<Required<APTran.refNbr>>>, OrderBy<Asc<APTran.lineNbr>>>.Select(Base, docLine.AdjdRefNbr);
if (firstLine == null) return;
if (!firstLine.SubID.HasValue && !firstLine.ProjectID.HasValue && !firstLine.TaskID.HasValue) return;
if (firstLine.SubID.HasValue)
{
// get sub CD of APTran
var orgSub = (Sub)PXSelectorAttribute.Select<APTran.subID>(cache, firstLine);
//Sub orgSub = PXSelect<Sub, Where<Sub.subID, Equal<Required<Sub.subID>>>>.Select(Base, firstLine.SubID);
if (orgSub != null)
{
// find Sub by SubCD
var newSubCD = orgSub.SubCD.Substring(0, orgSub.SubCD.Length - "CC22".Length) + "CC22";
Sub newSub = PXSelect<Sub, Where<Sub.subCD, Equal<Required<Sub.subCD>>>>.Select(Base, newSubCD);
if (newSub == null)
{
// newSubCD doesn't exist yet. Set SubCD to TranDesc temporary so that it could be created in RowPersisting event handler
Sub sub = new Sub
{
SubCD = newSubCD
};
PXCache<Sub> subCache = new PXCache<Sub>(Base);
sub = subCache.Insert(sub) as Sub;
Base.Caches[typeof(Sub)].PersistInserted(sub);
if (sub != null)
{
tran.SubID = sub.SubID;
tran.OrigSubID = sub.SubID;
}
}
else
{
// newSubCD exist. Add link to Tran
tran.SubID = newSub.SubID;
tran.OrigSubID = newSub.SubID;
}
if (firstLine.ProjectID.HasValue)
{
tran.ProjectID = firstLine.ProjectID;
}
if (firstLine.TaskID.HasValue)
{
tran.TaskID = firstLine.TaskID;
}
}
}

cache.Update(tran);
}

public PXAction<APPayment> release;
[PXUIField(DisplayName = "Release", MapEnableRights = PXCacheRights.Update, MapViewRights = PXCacheRights.Update)]
[PXProcessButton]
public IEnumerable Release(PXAdapter adapter)
{
PXGraph.InstanceCreated.AddHandler<JournalEntry>((graph) =>
{
//graph.RowInserting.AddHandler<GLTran>((cache, args) =>
//{
// PopulateFromAPTran(cache, args, true);
//});
graph.RowPersisting.AddHandler<GLTran>((cache, args) =>
{
PopulateFromAPTran(cache, args);
});
});
PXGraph.InstanceCreated.AddHandler<JournalEntry>((graph) =>
{
graph.RowInserting.AddHandler<Batch>((cache, args) =>
{
PXContext.SetSlot<ProcessBatch>(null);
});
});
PXGraph.InstanceCreated.AddHandler<JournalEntry>((graph) =>
{
graph.RowPersisted.AddHandler<Batch>((cache, args) =>
{
if (args.TranStatus == PXTranStatus.Completed)
{
PXContext.SetSlot<ProcessBatch>(
new ProcessBatch((Batch)args.Row));
}
});
});
return Base.release.Press(adapter);
}

#endregion
}
}

 

Thank you in advance,

Khoi


3 replies

Badge +18

Hello,

Does the Currency Gain or Loss account have an Account Group connected in Finance → Chart of Accounts screen?

Ability to add Project to a transaction is controlled by Account Group

Laura

Userlevel 3
Badge

hello @Laura02,

Yes, it connected to a certain Account Group.

 

 

Userlevel 7
Badge

Hi @mrthanhkhoi were you able to find a solution? Thank you!

Reply


About Acumatica ERP system
Acumatica Cloud ERP provides the best business management solution for transforming your company to thrive in the new digital economy. Built on a future-proof platform with open architecture for rapid integrations, scalability, and ease of use, Acumatica delivers unparalleled value to small and midmarket organizations. Connected Business. Delivered.
© 2008 — 2024  Acumatica, Inc. All rights reserved