0

So looks like seemingly easy things in Acumatica are terribly complicated to implement. All I wanna do is to copy last row of my grid as a new one. I would like the user to persist the changes himself, so my code would put it just in cache. This is my action so far:

    public PXAction<SOOrder> copyLastRow;
    [PXUIField(DisplayName = "Copy Last Row", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select)]
    [PXLookupButton]
    public virtual IEnumerable CopyLastRow(PXAdapter adapter)
    {
        SOLine line = Base.Transactions.Select().LastOrDefault();
        int? lineNbr = 0;

        foreach(SOLine line2 in Base.Transactions.Select())            
            if (line2.LineNbr > lineNbr)
                lineNbr = line2.LineNbr;



        line.LineNbr = lineNbr + 1;
        Base.Transactions.Cache.Insert(line);           

        return adapter.Get();
    }

So maybe I am not getting something or completely wrong in my code, but I'm getting errors no matter what I do. The grid is not getting refreshed with my row and I keep getting all sorts of errors, such as "This record cannot be saved" or "another process updated this record", etc. Also, any ideas on how to generate a new lineNbr without clunky logic I have? Much appreciated if anyone can help.

Stan A
  • 133
  • 8
  • The Acumatica platform is similar to a 4GL programming language. It's common for these systems to make hard things easy and simple things hard. The idea being that the time lost on small details is compensated by not having to re-implement higher level systems like ORM, Concurrency, Security, Reports, DB Scripts etc.. I'd recommend tailoring your designs to the platform standard templates and best practices, by reading T100-T200-T300 training material you'll get a better idea of how everything is put together. – Hugues Beauséjour Dec 21 '17 at 19:55

4 Answers4

2

If you just want to take the line and copy all values you can use cache copy and null the lineid. Then on insert of the copied line it will get the next linenbr automatically... adding to your sample code in your question...

SOLine line = Base.Transactions.Select().LastOrDefault();
var copy = (SOLine)Base.Transactions.Cache.CreateCopy(line);
copy.LineNbr = null;
Base.Transactions.Cache.Insert(copy);

This method should also be upgrade friendly in the event new fields or customization are added to SOLine they will continue to be copied without having to selectively include all fields to be copied (using CreateCopy).

Brendan
  • 5,428
  • 2
  • 17
  • 33
  • That worked perfectly! Thank you very much! Also, I am able to make the user save themselves. – Stan A Dec 22 '17 at 14:58
  • Perfect. I always try to let the user do the persisting unless absolutely necessary related to some long running process. Action buttons performing changes on the same graph/records i let the user do the saving. – Brendan Dec 22 '17 at 18:33
1

The code should be like this:

public PXAction<SOOrder> copyLastRow;
[PXUIField(DisplayName = "Copy Last Row", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select)]
[PXProcessButton]
public virtual IEnumerable CopyLastRow(PXAdapter adapter)
{
    SOLine line = Base.Transactions.Select().LastOrDefault();
    SOLine newLine = new SOLine();
    ... (copy all you need from line to newLine)
    Base.Transactions.Cache.Insert(newLine);           
    Base.Actions.PressSave();
    return adapter.Get();
} 
Ilya Kalmykov
  • 216
  • 2
  • 5
  • Ilya, wouldnt PressSave persist the changes to db? I would like the user to do that himself, i.e. press save button. Also what about lineNbr? Should I just leave it blank or generate it myself like in the code I posted. Thanks, – Stan A Dec 21 '17 at 13:18
  • Press "Save" in GUI to save line changed in action will not work - different threads. You need to press "Save" in the action, or copy and save in GUI. LineNbr will be generated automatically. You can see the following C# attribute declared for SOLine DAC: [PXLineNbr(typeof(SOOrder.lineCntr))] Always pay attention to what C# attributes are specified - a lot of things in Acumatica are done by logic in the C# attributes. – Ilya Kalmykov Dec 21 '17 at 13:32
  • me personally i would avoid the persist/press save in this situation. Just let the user click the save button when ready. It shouldn't be necessary for solving this question. – Brendan Dec 21 '17 at 21:38
  • @Brendan That's what I am trying to ideally accomplish, but from what Illya says it might not be possible – Stan A Dec 22 '17 at 14:43
  • @IlyaKalmykov thank you for your contribution. I marked Brendan's answer as most correct – Stan A Dec 22 '17 at 14:59
0

It is my guess that Line Number will get automatically generated ! It is not in sequence anyway.

I suggest you create a new SOline row and transfer the enterable fields from the selected row (Last row) in the same and Insert. Should work.

0

If you don't want attachments or notes to copy make sure to add

copy.NoteID = null;
Henry Ecker
  • 34,399
  • 18
  • 41
  • 57
rjean99
  • 3
  • 4