Acumatica - Action "Reverse and Apply Memo" Default Post Period to active financial period - customization

Can a customization be created to set the post period to the current active financial period after pressing the "Reverse and Apply to Memo" action in "Invoices and Memos" screen?
We've noticed the newly created credit memo defaults to the post period of the invoice which could be incorrect if it's credited in the following financial period.

The solution defined below was developed within Acumatica 20.102.0015 and changes the date and post period for the created credit memo on "Reverse and Apply Memo" action to the default of a new document instead of the date from the reversed invoice.
namespace AARAMPostPeriod
{
public class AAARInvoiceEntryExtension : PXGraphExtension<ARInvoiceEntry>
{
public delegate IEnumerable ReverseDocumentAndApplyToReversalIfNeededDel(PXAdapter adapter, ReverseInvoiceArgs reverseArgs);
[PXOverride]
public virtual IEnumerable ReverseDocumentAndApplyToReversalIfNeeded(PXAdapter adapter, ReverseInvoiceArgs reverseArgs, ReverseDocumentAndApplyToReversalIfNeededDel del)
{
if(reverseArgs.ApplyToOriginalDocument) reverseArgs.DateOption = ReverseInvoiceArgs.CopyOption.SetDefault;
return del(adapter, reverseArgs);
}
}
}
Default value for reverseArgs.DateOption is typically
ReverseInvoiceArgs.CopyOption.SetOriginal

You are talking about the receivables side of things, but I did something similar on the payables side. It isn't exactly what you are asking for, but it is too big for a comment.
You may be able to get the general idea from this and apply to your scenario. The approach I took was to check the period when releasing.
protected virtual void _(Events.FieldUpdated<APInvoice.finPeriodID> e)
{
APInvoice row = (APInvoice)e.Row;
CheckPeriod(e.Cache, row);
}
#region Release override
public delegate IEnumerable ReleaseDelegate(PXAdapter adapter);
[PXOverride]
public virtual IEnumerable Release(PXAdapter adapter, ReleaseDelegate baseMethod)
{
CheckPeriod(Base.Caches[typeof(APInvoice)], Base.Document.Current);
return baseMethod(adapter);
}
#endregion
protected virtual void CheckPeriod(PXCache cache, APInvoice invoice)
{
if (invoice?.FinPeriodID == null) return;
string currentPeriod = GetCurrentPeriod(invoice.BranchID);
if (currentPeriod != invoice.FinPeriodID)
{
PXUIFieldAttribute.SetError<APInvoice.finPeriodID>(cache, invoice, "Invalid period");
}
}
public virtual string GetCurrentPeriod(int? branchID)
{
PXResultset<Branch> Results = PXSelectJoin<GL.Branch,
InnerJoin<FinPeriod, On<FinPeriod.organizationID, Equal<Branch.organizationID>>>,
Where<Branch.branchID, Equal<Required<Branch.branchID>>,
And<FinPeriod.startDate, LessEqual<Required<FinPeriod.startDate>>,
And<FinPeriod.endDate, Greater<Required<FinPeriod.endDate>>>>>> // End Date is the date AFTER the period ends
.SelectSingleBound(Base, null, branchID, Base.Accessinfo.BusinessDate, Base.Accessinfo.BusinessDate);
if (Results != null)
{
foreach (PXResult<GL.Branch, FinPeriod> result in Results)
{
FinPeriod period = result;
return period.FinPeriodID;
}
}
return null;
}
As you can see, I put an override on the Release to perform my validation which sets an error condition if the period is not current. The validation is performed by retrieving the current period of the current business date and comparing to the period on the APInvoice.
You could explore leveraging GetCurrentPeriod from the example and put into an override on FieldDefaulting if it helps with your goal.

Related

Can someone please explain the proper usage of Timers and Triggers in Apache Beam?

I'm looking for some examples of usage of Triggers and Timers in Apache beam, I wanted to use Processing-time timers for listening my data from pub sub in every 5 minutes and using Processing time triggers processing the above data collected in an hour altogether in python.
Please take a look at the following resources: Stateful processing with Apache Beam and Timely (and Stateful) Processing with Apache Beam
The first blog post is more general in how to handle states for context, and the second has some examples on buffering and triggering after a certain period of time, which seems similar to what you are trying to do.
A full example was requested. Here is what I was able to come up with:
PCollection<String> records =
pipeline.apply(
"ReadPubsub",
PubsubIO.readStrings()
.fromSubscription(
"projects/{project}/subscriptions/{subscription}"));
TupleTag<Iterable<String>> every5MinTag = new TupleTag<>();
TupleTag<Iterable<String>> everyHourTag = new TupleTag<>();
PCollectionTuple timersTuple =
records
.apply("WithKeys", WithKeys.of(1)) // A KV<> is required to use state. Keying by data is more appropriate than hardcode.
.apply(
"Batch",
ParDo.of(
new DoFn<KV<Integer, String>, Iterable<String>>() {
#StateId("buffer5Min")
private final StateSpec<BagState<String>> bufferedEvents5Min =
StateSpecs.bag();
#StateId("count5Min")
private final StateSpec<ValueState<Integer>> countState5Min =
StateSpecs.value();
#TimerId("every5Min")
private final TimerSpec every5MinSpec =
TimerSpecs.timer(TimeDomain.PROCESSING_TIME);
#StateId("bufferHour")
private final StateSpec<BagState<String>> bufferedEventsHour =
StateSpecs.bag();
#StateId("countHour")
private final StateSpec<ValueState<Integer>> countStateHour =
StateSpecs.value();
#TimerId("everyHour")
private final TimerSpec everyHourSpec =
TimerSpecs.timer(TimeDomain.PROCESSING_TIME);
#ProcessElement
public void process(
#Element KV<Integer, String> record,
#StateId("count5Min") ValueState<Integer> count5MinState,
#StateId("countHour") ValueState<Integer> countHourState,
#StateId("buffer5Min") BagState<String> buffer5Min,
#StateId("bufferHour") BagState<String> bufferHour,
#TimerId("every5Min") Timer every5MinTimer,
#TimerId("everyHour") Timer everyHourTimer) {
if (Objects.firstNonNull(count5MinState.read(), 0) == 0) {
every5MinTimer
.offset(Duration.standardMinutes(1))
.align(Duration.standardMinutes(1))
.setRelative();
}
buffer5Min.add(record.getValue());
if (Objects.firstNonNull(countHourState.read(), 0) == 0) {
everyHourTimer
.offset(Duration.standardMinutes(60))
.align(Duration.standardMinutes(60))
.setRelative();
}
bufferHour.add(record.getValue());
}
#OnTimer("every5Min")
public void onTimerEvery5Min(
OnTimerContext context,
#StateId("buffer5Min") BagState<String> bufferState,
#StateId("count5Min") ValueState<Integer> countState) {
if (!bufferState.isEmpty().read()) {
context.output(every5MinTag, bufferState.read());
bufferState.clear();
countState.clear();
}
}
#OnTimer("everyHour")
public void onTimerEveryHour(
OnTimerContext context,
#StateId("bufferHour") BagState<String> bufferState,
#StateId("countHour") ValueState<Integer> countState) {
if (!bufferState.isEmpty().read()) {
context.output(everyHourTag, bufferState.read());
bufferState.clear();
countState.clear();
}
}
})
.withOutputTags(every5MinTag, TupleTagList.of(everyHourTag)));
timersTuple
.get(every5MinTag)
.setCoder(IterableCoder.of(StringUtf8Coder.of()))
.apply(<<do something every 5 min>>);
timersTuple
.get(everyHourTag)
.setCoder(IterableCoder.of(StringUtf8Coder.of()))
.apply(<< do something every hour>>);
pipeline.run().waitUntilFinish();

Acumatica - Adding Multiple Tracking Numbers in Field

I am adding the Tracking Number data field from SOPackageDetail to the Invoices screen (SO303000) on the Freight Details Tab. I know that it only shows one ShipmentNbr and this is what I'm using to join the two tables but I would like all of the tracking numbers, since there can be more than one per shipment number, to show in the field instead of just one. They can be just separated in the field value by a comma. Here is my code and it does work for just one tracking number.
Graph:
public class SOInvoiceEntry_Extension : PXGraphExtension<SOInvoiceEntry>
{
#region Event Handlers
protected void SOFreightDetail_RowSelecting(PXCache cache, PXRowSelectingEventArgs e, PXRowSelecting del)
{
if (del != null)
del(cache, e);
var row = (SOFreightDetail)e.Row;
if (row == null) return;
using (new PXConnectionScope())
{
SOPackageDetail track = PXSelect<SOPackageDetail, Where<SOPackageDetail.shipmentNbr, Equal<Required<SOFreightDetail.shipmentNbr>>>>.Select(Base, row.ShipmentNbr);
if(track != null){
SOFreightDetailExt invoiceExt = row.GetExtension<SOFreightDetailExt>();
if (invoiceExt != null){
invoiceExt.TrackNumber = track.TrackNumber;
}
}
}
}
#endregion
}
DAC Extension:
public class SOFreightDetailExt : PXCacheExtension<PX.Objects.SO.SOFreightDetail>
{
#region TrackNumber
public abstract class trackNumber : PX.Data.IBqlField
{
}
protected string _TrackNumber;
[PXString()]
[PXDefault()]
[PXUIField(DisplayName = "Tracking Number", IsReadOnly = true)]
public virtual string TrackNumber
{
get
{
return this._TrackNumber;
}
set
{
this._TrackNumber = value;
}
}
#endregion
}
I want all tracking numbers associated with the Shipment Nbr to be displayed in this field, right now it only shows one. This only will happen if there is multiple packages for one shipment number.
You need to loop on your records (PXSelect) in a foreach. You then need to add each string value to your tracknumber field. Something like this should work...
SOFreightDetailExt invoiceExt = row.GetExtension<SOFreightDetailExt>();
if(invoiceExt == null)
return;
foreach(SOPackageDetail track in PXSelect<SOPackageDetail, Where<SOPackageDetail.shipmentNbr, Equal<Required<SOFreightDetail.shipmentNbr>>>>.Select(Base, row.ShipmentNbr))
{
invoiceExt.TrackNumber = $"{invoiceExt.TrackNumber}, {track.TrackNumber}";
}
Also, there is no need for the PXConnectionScope. You can remove that.

Can I change the current date and time for a specific process?

Is there a way to change the date and time seen by a specific process as opposed to the entire computer (i.e. the time returned by time() in C, by DateTime.Now in C#, by datetime.now() in Python, by new Date() in JavaScript, by System.currentTimeMillis() in Java, etc.)?
For instance, is there a way to fool a program into thinking it's midnight while it's 7 AM on the rest of the computer, or to make it think it's Christmas or Leap Day while the system clock shows July 18th?
An applicable situation would be when you're writing unit tests and you want to quickly test any special behavior the program has on Christmas or on Leap Day or on the demo's expiration date, and you want to test this behavior without having to use the date changing function in the OS and interfere with programs that rely on the date being correct (much less forcing me to have superuser privileges over the computer).
Previously mentioned Typemock also has an API for C++, which also allows you to fake time, in C++:
TEST_METHOD(FakeCurrentTime)
{
SYSTEMTIME fakeTime;
fakeTime.wYear = 2000;
fakeTime.wMonth = 1;
fakeTime.wDay = 1;
FAKE_GLOBAL(GetSystemTime);
WHEN_CALLED(GetSystemTime(RET(&fakeTime))).Ignore();
SYSTEMTIME now;
GetSystemTime(&now);
Assert::IsTrue(now.wMilliseconds - fakeTime.wMilliseconds == 0);
}
I don't think you can do what you want to do in C#. There aren't any hooks that I know of to make DateTime.Now return arbitrary values out of the box. The standard way to implement unit testing that is time sensitive is to create a time provider interface. This is the approach taken by third party libraries such as Noda Time that values testing time related functions. One such implementation is below (not Noda Time compatible):
public ITimeProvider
{
DateTime CurrentTime { get; }
DateTime CurrentUtcTime { get; }
}
public DefaultTimeProvider : ITimeProvider
{
public DateTime CurrentTime { get { return DateTime.Now; } }
public DateTime CurrentUtcTime { get { return DateTime.UtcNow; } }
}
Then when you want to unit test the code you replace the DefaultTimeProvider implementation with a mock implementation. You can use your favorite mocking framework or just write something like this:
public MockTimeProvider : ITimeProvider
{
private readonly DateTime _currentTime;
private readonly DateTime _currentUtcTime;
public MockTimeProvider(DateTime currentTime, DateTime currentUtcTime)
{
_currentTime = currentTime;
_currentUtcTime = currentUtcTime;
}
public DateTime CurrentTime { get { return _currentTime; } }
public DateTime CurrentUtcTime { get { return _currentUtcTime; } }
}
Disclaimer, I work at Typemock.
You can use Typemock Isolator for this:
[TestMethod]
public void isLicenseExpiredTest()
{
Isolate.WhenCalled(() => DateTime.Now).WillReturn(new DateTime(2017, 5, 4));
bool result = Licenses.IsLicenseExpired();
Assert.IsFalse(result);
}
public static class Licenses
{
public static bool IsLicenseExpired()
{
if (DateTime.Now > new DateTime(2016, 5, 4))
{
return false;
}
else
{
return true;
}
}
}
java.time
Java 8 and later has the java.time framework built in. Supplants the old date-time classes.
Clock
Includes the Clock class. You can override this class to make your own faked current time.
A few alternate implementations are included via static methods. You can ask for a Clock that stays fixed on a single moment you specify. You can shift the current time by some specified amount. And you have the Clock report the current moment rounded to the whole second or minute and so on.

Sitecore workflow approval state query

I have created workflow in my sitecore project and on final state ( Approval ) I just want auto publish to a particular database.
So where should I do the changes to point to database.
Thanks
In order to perform automatic publishing, your final state should contain a workflow action, that does the job for you. You may take a look on Sample Workflow (that comes by default with Sitecore) - Approved state. It contains child item Auto Publish, that has two fields.
Type string:
Sitecore.Workflows.Simple.PublishAction, Sitecore.Kernel
sets the class that in fact does publishing. You may inherit from that class and implement your own behavior, supply extra parameters etc. I would advise you to take dotPeek or Reflector and look-up this class implementation so that you may adjust your own code.
Parameters:
deep=0
..stands for publishing child items recursively.
Update: Lets take a look on decompiled class from Sample Workflow Auto Publish action:
public class PublishAction
{
public void Process(WorkflowPipelineArgs args)
{
Item dataItem = args.DataItem;
Item innerItem = args.ProcessorItem.InnerItem;
Database[] targets = this.GetTargets(dataItem);
PublishManager.PublishItem(dataItem, targets, new Language[1]
{
dataItem.Language
}, (this.GetDeep(innerItem) ? 1 : 0) != 0, 0 != 0);
}
private bool GetDeep(Item actionItem)
{
return actionItem["deep"] == "1" || WebUtil.ParseUrlParameters(actionItem["parameters"])["deep"] == "1";
}
private Database[] GetTargets(Item item)
{
using (new SecurityDisabler())
{
Item obj = item.Database.Items["/sitecore/system/publishing targets"];
if (obj != null)
{
ArrayList arrayList = new ArrayList();
foreach (BaseItem baseItem in obj.Children)
{
string name = baseItem["Target database"];
if (name.Length > 0)
{
Database database = Factory.GetDatabase(name, false);
if (database != null)
arrayList.Add((object)database);
else
Log.Warn("Unknown database in PublishAction: " + name, (object)this);
}
}
return arrayList.ToArray(typeof(Database)) as Database[];
}
}
return new Database[0];
}
}
GetTargets() method from above default example does publishing to all targets that are specified under /sitecore/system/publishing targets path. As I mentioned above, you may create your own class with your own implementation and reference that from workflow action definition item.
You can look into Sample workflow's Auto publish action. But in general you can create a Workflow Action with type: Sitecore.Workflows.Simple.PublishAction, Sitecore.Kernel and set parameters as deep=1&related=1&targets=somedb,web&alllanguages=1

Writing a test class on a Trigger in Salesforce

I am a complete code noob and need help writing a test class for a trigger in Salesforce. Any help would be greatly appreciated.
Here is the trigger:
trigger UpdateWonAccounts on Opportunity(before Update) {
Set < Id > accountIds = new Set < Id > ();
//Collect End user Ids which has won Opportunities
for (Opportunity o : Trigger.new) {
if (o.isWon && o.EndUserAccountName__c != null) {
accountIds.add(o.EndUserAccountName__c);
}
}
List < Account > lstAccount = new List < Account > ();
//Iterate and collect all the end user records
for (Account a : [Select Id, Status__c From Account where Id IN : accountIds]) {
lstAccount.add(new Account(Id = a.Id, Status__c = true));
}
//If there are any accounts then update the records
if (!lstAccount.isEmpty()) {
update lstAccount;
}
}
Read An Introduction to Apex Code Test Methods and How To Write A Trigger Test.
Basically, you want to create a new testmethod that updates (inserts, deletes, undeletes, etc. depending on your trigger conditions) a record or sObject.
It looks somewhat like this:
public class myClass {
static testMethod void myTest() {
// Add test method logic to insert and update a new Opportunity here
}
}