Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Explicit compositions are required

Status
Not open for further replies.

SneeKee

Programmer
Aug 24, 2009
7
CA
Hello All,

I am attempting to build a plugin that will modify the payment schedule of an AR Invoice. I am having an issue when i am attempting to insert the records into the system using the XAPI.

Here is a sample of my code;
Code:
    PaymentSchedule.Init();

    PaymentSchedule.RecordGenerate(false);

    PaymentSchedule.Fields.Item("CNTBTCH").Value = pmt.BatchNumber;
    PaymentSchedule.Fields.Item("CNTITEM").Value = pmt.EntryNumber;
    // I also tried assigning this to 1 > than max existing id
    PaymentSchedule.Fields.Item("CNTPAYM").Value = -1;
    PaymentSchedule.Fields.Item("DATEDUE").Value = pmt.DueDate;
    PaymentSchedule.Fields.Item("AMTDUE").Value = pmt.AmountDue;

    PaymentSchedule.Fields.Item("DATEDISC").Value = 0; // For testing only
    PaymentSchedule.Fields.Item("AMTDISC").Value = 0;// For testing only
    PaymentSchedule.Fields.Item("AMTDUEHC").Value = 0;// For testing only
    PaymentSchedule.Fields.Item("AMTDISCHC").Value = 0;// For testing only


    PaymentSchedule.Verify();
    PaymentSchedule.Process();
    PaymentSchedule.Insert();

this fails with the following error;
Code:
Internal error. ARIBS: Explicit compositions are required. (1580 ARIBS1.C).
 
2 things:
You need to compose the required views, record a macro to get the compositions.
Your code is to insert a new record and not modify an existing one.
 
Okay,

So now i am composing my views, but i am getting a new error.

Code:
Invoice Payment Schedule.
Record not found.

Here is my code now.

NOTE:
ARInvoicePaymentSchedule is a struct i have built to mimic a AR Invoice Payment Schedule
Code:
public bool SavePaymentSchedule(List<ARInvoicePaymentSchedule> payments)
{
    try
    {

        // Compose
        xapiView ARINVOICE1batch;
        xapiFields ARINVOICE1batchFields;
        ARINVOICE1batch = OpenView("AR0031");
        ARINVOICE1batchFields = ARINVOICE1batch.Fields;

        xapiView ARINVOICE1header;
        xapiFields ARINVOICE1headerFields;
        ARINVOICE1header = OpenView("AR0032");
        ARINVOICE1headerFields = ARINVOICE1header.Fields;

        xapiView ARINVOICE1detail1;
        xapiFields ARINVOICE1detail1Fields;
        ARINVOICE1detail1 = OpenView("AR0033");
        ARINVOICE1detail1Fields = ARINVOICE1detail1.Fields;

        xapiView ARINVOICE1detail2;
        xapiFields ARINVOICE1detail2Fields;
        ARINVOICE1detail2 = OpenView("AR0034");
        ARINVOICE1detail2Fields = ARINVOICE1detail2.Fields;

        xapiView ARINVOICE1detail3;
        xapiFields ARINVOICE1detail3Fields;
        ARINVOICE1detail3 = OpenView("AR0402");
        ARINVOICE1detail3Fields = ARINVOICE1detail3.Fields;

        xapiView ARINVOICE1detail4;
        xapiFields ARINVOICE1detail4Fields;
        ARINVOICE1detail4 = OpenView("AR0401");
        ARINVOICE1detail4Fields = ARINVOICE1detail4.Fields;

        ARINVOICE1batch.Compose(new object[]{ARINVOICE1header});
        ARINVOICE1header.Compose(new object[]{ARINVOICE1batch, ARINVOICE1detail1, ARINVOICE1detail2, ARINVOICE1detail3, null});
        ARINVOICE1detail1.Compose(new  object[]{ARINVOICE1header, ARINVOICE1batch, ARINVOICE1detail4});
        ARINVOICE1detail2.Compose(new  object[]{ARINVOICE1header});
        ARINVOICE1detail3.Compose(new  object[]{ARINVOICE1header});
        ARINVOICE1detail4.Compose(new  object[]{ARINVOICE1detail1});

        foreach (ARInvoicePaymentSchedule pmt in payments)
        {
            if (!PaymentExists(pmt.BatchNumber, pmt.EntryNumber, pmt.PaymentNumber))
            { // only insert it if it doesnt exist
               // ARINVOICE1detail2.RecordClear();

                ARINVOICE1detail2.Init();
                ARINVOICE1detail2.RecordGenerate(false);

                ARINVOICE1detail2.Fields.Item("CNTBTCH").Value = pmt.BatchNumber;
                ARINVOICE1detail2.Fields.Item("CNTITEM").Value = pmt.EntryNumber;
                ARINVOICE1detail2.Fields.Item("CNTPAYM").Value = pmt.PaymentNumber;
                ARINVOICE1detail2.Fields.Item("DATEDUE").Value = pmt.DueDate;
                ARINVOICE1detail2.Fields.Item("AMTDUE").Value = pmt.AmountDue;
                ARINVOICE1detail2.Fields.Item("DATEDISC").Value = 0;
                ARINVOICE1detail2.Fields.Item("AMTDISC").Value = 0;
                ARINVOICE1detail2.Fields.Item("AMTDUEHC").Value = 0;
                ARINVOICE1detail2.Fields.Item("AMTDISCHC").Value = 0;
                ARINVOICE1detail2.Verify();
                ARINVOICE1detail2.Process();
                
                // Fails here
                ARINVOICE1detail2.Insert();
            }
        }

        return true;
    }
    catch (Exception ex)
    {
        //TODO: Error Handling
        string temp = GetXAPIError();
        return false;
    }
    finally
    {
    }

}
 
@ettienne

Yes, I know that I am adding new records to the existing payment schedule. I guess my wording
SneeKee said:
plugin that will modify the payment schedule of an AR Invoice

was misleading
 
If you are adding something to an existing record then you must .Read the existing record first.
You need to read the batch first and then the entry in the header before you can do anything with the detail records.
You are diving straight into a detail record but no batch or header record has been read - hence the record not found error.
 
@ettienne

Thanks for your input, I am not receiving any errors right now.

But there is still a problem, the records I am inserting are not being persisted to the database. I am calling POST on the Batch, Header and Payment Schedule Details but nothing is actually being saved.

Here is the new code listing;

Code:
public bool SavePaymentSchedule(List<ARInvoicePaymentSchedule> payments)
{
    try
    {

        // Compose
        xapiView ARINVOICE1batch;
        xapiFields ARINVOICE1batchFields;
        ARINVOICE1batch = OpenView("AR0031");
        ARINVOICE1batchFields = ARINVOICE1batch.Fields;

        xapiView ARINVOICE1header;
        xapiFields ARINVOICE1headerFields;
        ARINVOICE1header = OpenView("AR0032");
        ARINVOICE1headerFields = ARINVOICE1header.Fields;

        xapiView ARINVOICE1detail1;
        xapiFields ARINVOICE1detail1Fields;
        ARINVOICE1detail1 = OpenView("AR0033");
        ARINVOICE1detail1Fields = ARINVOICE1detail1.Fields;

        xapiView ARINVOICE1detail2;
        xapiFields ARINVOICE1detail2Fields;
        ARINVOICE1detail2 = OpenView("AR0034");
        ARINVOICE1detail2Fields = ARINVOICE1detail2.Fields;

        xapiView ARINVOICE1detail3;
        xapiFields ARINVOICE1detail3Fields;
        ARINVOICE1detail3 = OpenView("AR0402");
        ARINVOICE1detail3Fields = ARINVOICE1detail3.Fields;

        xapiView ARINVOICE1detail4;
        xapiFields ARINVOICE1detail4Fields;
        ARINVOICE1detail4 = OpenView("AR0401");
        ARINVOICE1detail4Fields = ARINVOICE1detail4.Fields;

        ARINVOICE1batch.Compose(new object[]{ARINVOICE1header});
        ARINVOICE1header.Compose(new object[]{ARINVOICE1batch, ARINVOICE1detail1, ARINVOICE1detail2, ARINVOICE1detail3, null});
        ARINVOICE1detail1.Compose(new  object[]{ARINVOICE1header, ARINVOICE1batch, ARINVOICE1detail4});
        ARINVOICE1detail2.Compose(new  object[]{ARINVOICE1header});
        ARINVOICE1detail3.Compose(new  object[]{ARINVOICE1header});
        ARINVOICE1detail4.Compose(new  object[]{ARINVOICE1detail1});

        // Read
        ARINVOICE1batch.Browse("CNTBTCH = " + payments[0].BatchNumber, 1);
        ARINVOICE1batch.Read();

        ARINVOICE1header.Browse("CNTBTCH = " + payments[0].BatchNumber + " AND CNTITEM = " + payments[0].EntryNumber, 1);
        ARINVOICE1header.Read();
        ARINVOICE1header.Fetch();

        foreach (ARInvoicePaymentSchedule pmt in payments)
        {
            if (!PaymentExists(pmt.BatchNumber, pmt.EntryNumber, pmt.PaymentNumber))
            { // only insert it if it doesnt exist
               // ARINVOICE1detail2.RecordClear();

                ARINVOICE1detail2.Init();
                ARINVOICE1detail2.RecordGenerate(false);

                ARINVOICE1detail2.Fields.Item("CNTBTCH").Value = pmt.BatchNumber;
                ARINVOICE1detail2.Fields.Item("CNTITEM").Value = pmt.EntryNumber;
                ARINVOICE1detail2.Fields.Item("CNTPAYM").Value = pmt.PaymentNumber;
                ARINVOICE1detail2.Fields.Item("DATEDUE").Value = pmt.DueDate;
                ARINVOICE1detail2.Fields.Item("AMTDUE").Value = pmt.AmountDue;
                ARINVOICE1detail2.Fields.Item("DATEDISC").Value = pmt.DueDate;
                ARINVOICE1detail2.Fields.Item("AMTDISC").Value = 0;
                ARINVOICE1detail2.Fields.Item("AMTDUEHC").Value = 0;
                ARINVOICE1detail2.Fields.Item("AMTDISCHC").Value = 0;
                ARINVOICE1detail2.Verify();
                ARINVOICE1detail2.Process();
                
                ARINVOICE1detail2.Insert();
            }
        }

        ARINVOICE1batch.Post();
        ARINVOICE1header.Post();
        ARINVOICE1detail2.Post();

        return true;
    }
    catch (Exception ex)
    {
        //TODO: Error Handling
        string temp = GetXAPIError();
        return false;
    }
    finally
    {
    }

}
 
You use .Browse and .Fetch together, but you do not use .Browse and .Read together.
Either do .PutWithoutVerification and .Read or .Browse and .Fetch

For a .Read you need to put the primary key fields first and then .Read - this is a fast way to retrieve a specific record.
For a .Fetch you set the filter with .Browse, this does not have to be key fields.

I would change the section after //Read to

// Read
ARINVOICE1batch.Fields("CNTBTCH").PutWithoutVerification payments[0].BatchNumber;
ARINVOICE1batch.Read();

ARINVOICE1header.Fields("CNTITEM").PutWithoutVerification payments[0].EntryNumber;
ARINVOICE1header.Read();

foreach....
 
Also drop these lines

ARINVOICE1batch.Post();
ARINVOICE1header.Post();
ARINVOICE1detail2.Post();

and only do

ARINVOICE1header.Update();
 
You can also take out these lines: ARINVOICE1detail2.Fields.Item("CNTBTCH").Value = pmt.BatchNumber; ARINVOICE1detail2.Fields.Item("CNTITEM").Value = pmt.EntryNumber; ARINVOICE1detail2.Fields.Item("CNTPAYM").Value = pmt.PaymentNumber;

CNTBATCH and CNTITEM are set by the batch and header because of the composed views, CNTPAYM is incremented because of the .RecordGenerate - you can test this to be sure.
 
@ettienne

Thanks again for all your help, but now I've hit another problem and hope you can shed some light on it.

The error message;
Code:
Invalid input. The document discount amount does not match the payment schedule discount amount.

Heres the new code;
Code:
public bool SavePaymentSchedule(List<ARInvoicePaymentSchedule> payments)
{
    try
    {

        // Compose
        ... Same as before

        // Read - Changed
        ARINVOICE1batch.Fields.Item("CNTBTCH").PutWithoutVerification(payments[0].BatchNumber);
        ARINVOICE1batch.Read();

        ARINVOICE1header.Fields.Item("CNTITEM").PutWithoutVerification(payments[0].EntryNumber);
        ARINVOICE1header.Read();

        foreach (ARInvoicePaymentSchedule pmt in payments)
        {
            if (!PaymentExists(pmt.BatchNumber, pmt.EntryNumber, pmt.PaymentNumber))
            { // only insert it if it doesnt exist
                ARINVOICE1detail2.RecordClear();
                ARINVOICE1detail2.Init();
                ARINVOICE1detail2.RecordGenerate(false);

                ARINVOICE1detail2.Fields.Item("DATEDUE").Value = pmt.DueDate;
                ARINVOICE1detail2.Fields.Item("AMTDUE").Value = pmt.AmountDue;
                ARINVOICE1detail2.Fields.Item("DATEDISC").Value = pmt.DueDate;

                // also tried ARINVOICE1header.Fields.Item("AMTDISCAVL").Value
                ARINVOICE1detail2.Fields.Item("AMTDISC").Value = 0;

                //Removed these 2 because the documentation says they are calculated
                //ARINVOICE1detail2.Fields.Item("AMTDUEHC").Value = 0;
                //ARINVOICE1detail2.Fields.Item("AMTDISCHC").Value = 0;

                ARINVOICE1detail2.Verify();
                ARINVOICE1detail2.Process();
                ARINVOICE1detail2.Insert();
            }
        }

        ARINVOICE1header.Update();

        return true;
    }
    catch (Exception ex)
    {
        //TODO: Error Handling
        string temp = GetXAPIError();
        return false;
    }
    finally
    {
    }

}
 
And by the way, why are you trying to do this in the first place? I've been programming Accpac for 20 years and haven't had to do a mod like this.
 
@tuba2007

Thanks for the reply but this error occurs even if i don't set the fields;

Updated Code:

Code:
public bool SavePaymentSchedule(List<ARInvoicePaymentSchedule> payments)
{
    try
    {

        // Compose
        ... Same as before

        // Read
        ... Same as before

        foreach (ARInvoicePaymentSchedule pmt in payments)
        {
            if (!PaymentExists(pmt.BatchNumber, pmt.EntryNumber, pmt.PaymentNumber))
            { // only insert it if it doesnt exist
                ARINVOICE1detail2.RecordClear();
                ARINVOICE1detail2.Init();
                ARINVOICE1detail2.RecordGenerate(false);

                ARINVOICE1detail2.Fields.Item("DATEDUE").Value = pmt.DueDate;
                ARINVOICE1detail2.Fields.Item("AMTDUE").Value = pmt.AmountDue;

                ARINVOICE1detail2.Verify();
                ARINVOICE1detail2.Process();
                ARINVOICE1detail2.Insert();
            }
        }

        ARINVOICE1header.Update();

        return true;
    }
    catch (Exception ex)
    {
        //TODO: Error Handling
        string temp = GetXAPIError();
        return false;
    }
    finally
    {
    }

}
 
@tuba2007

Yes this is a very strange request, but the client wants the an amount to be added to the invoice and then have the new amount added to the payment schedule in even payments.
 
The only thing I can think of is after you add the amount to the invoice detail line and update the header, you would need to delete all ARIBS lines and add them back. But I don't know, I've never had to do it. I once did a mod for recalculating the schedule for posted invoices, but that's AROBS.
 
You need to change the terms code to one that has a Multiple Payment Schedule, the view logic is blocking you at this point because of your terms code.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top