Sage100.ObjectManagement Interfaces .net Error when creating line entry

SOLVED

   
           var sessionLogon = new SessionLogon
            {
                CompanyCode = companyCode,
                UserLogon = new NetworkCredential { UserName = userName, Password = password },
                ModuleCode = ModuleNames.AccountsReceivable,
                ModuleDate = DateTime.Today
            };




            using (var sySession = new MasSession(homePath))
            {
               sySession.InitSession(sessionLogon);


   
   
    using (var soInvoice = sySession.CreateObject<IMasBusinessObject>("SO_Invoice_bus", "SO_Invoice_ui", "S/O"))
            {

                soInvoice.SetValue("SalesPersonNo$", "0000");
                soInvoice.SetValue("SalesPersonDivisionNo$", "00");
                soInvoice.SetValue("ARDivisionNo$", "00");
                soInvoice.SetValue("InvoiceType$", "IN");
                soInvoice.SetValue("InvoiceNo$", "stapiIN");
                soInvoice.SetValue("InvoiceDate$", "20220710");
                soInvoice.SetValue("InvoiceDueDate$", "20220716");
                soInvoice.SetValue("DiscountDueDate$", "20220716");
                soInvoice.SetValue("TaxSchedule$", "DEFAULT");
                soInvoice.SetValue("OrderDate$", "20220502");
                soInvoice.SetValue("CustomerNo$", "0031330");
                soInvoice.SetValue("TermsCode$", "00");
                soInvoice.SetValue("OrderType$", "S");
                soInvoice.SetValue("PrintInvoice$", "N");
                soInvoice.SetValue("WarehouseCode$", "011");


                var soInvoiceLn = sySession.CreateObject<ILineEntry>("SO_InvoiceDetail_Bus", "SO_InvoiceDetail_Bus", "S/O");
                
                
            }
        }

Hello, we are getting an error when trying to create a line for a SO_Invoice using the Business Object dll in .net Sage100.ObjectManagementInterfaces

the error is  message attempted to perform an unauthorized operation.

  • 0 in reply to Russell Libby

    Sage returns {"<Error: 88 in Method SETKEY>"} when i try poEntry.SetKey(nextOrderNo);

  • +1 in reply to Anastasia Maher
    verified answer

    Definitely not the expected result. I did test this on v2023, and it worked properly. Do you know what version of Sage 100 this is, and if there are any 3rd party modifications installed? One other thing to try is using SetKeyValue (with the $ on the field name), and then SetKey() after.

                        using (var poEntry = sySession.CreateObject<ILineEntry>("PO_PurchaseOrder_bus", "PO_PurchaseOrder_ui", "P/O"))
                        {
                            var nextOrderNo = poEntry.GetNextDocumentNumber();
    
                            Trace.WriteLine(nextOrderNo);
    
                            poEntry.SetKeyValue("PurchaseOrderNo$", nextOrderNo);
                            poEntry.SetKey();
                            
                            ...

    Regards,

    Russell

  • 0 in reply to Russell Libby

    Ah Russell you are the best, i believe there is probably a modification or custom script ! thank you so much

  • 0 in reply to Anastasia Maher

    Hello   do you have an example for Goods Receipt , this code enters the batch but does not have any lines in the receipt. I cannot see any methods on ILineEntry for copy purchase order lines either.

      using (var sySession = new MasSession(homePath))
                {
                    sySession.InitSession(sessionLogon);
    
                    CI.ColumnNames.Add("PO_Receipt_bus", new Dictionary<string, string> { { CI.NextNumberMethod,
                            "nGetNextReceiptNo" }, { CI.HeaderKeyColumns, "ReceiptNo$" } });
    
                    using (var recEntry = sySession.CreateObject<ILineEntry>("PO_Receipt_bus", "PO_ReceiptofGoods_ui", "P/O"))
                    {
                        if (recEntry.BatchEnabled)
                        {
                           
    
                            var batch = recEntry.SelectBatch("03317");
    
                        }
                        
                        
                         var nextOrderNo = recEntry.GetNextDocumentNumber();
    
             
                        recEntry.SetValue("ReceiptType$", "G");
                        recEntry.SetKeyValue("ReceiptNo$", nextOrderNo);
                        recEntry.SetKey();
                      
                        recEntry.SetValue("PurchaseOrderNo$", "6000009");
                     
                        recEntry.SetValue("APDivisionNo$", "00");
                        recEntry.SetValue("VendorNo$", "0008056");
                       
                 
    
                       recEntry.SetValue("WarehouseCode$", "033");
    
    
    
                         var lines =   recEntry.GetProperty("oLines");
              
                        recEntry.AddLine();
                        
    
                          Trace.WriteLine(recEntry.Lines.GetKey());
    
        
                           recEntry.Lines.SetValue("ItemCode", "441162");
                           recEntry.Lines.SetValue("QuantityReceived", 1);
    
                           recEntry.Lines.Write();
    
    
                        if (!recEntry.Write())
                        {
                            response1 = recEntry.LastErrorMessage;
                            recEntry.Clear();
                        }
                        
                        }
                        }

  • 0 in reply to Anastasia Maher

      the above code also does not enter the purchase order in the Goods Receipt entry, it is completely blank with no lines

  • 0 in reply to Anastasia Maher

      , there is a function called CopyPurchaseOrderLines(receiveComplete) that you can call after doing the SetValue() for the Purchase Order Number.  The receiveComplete is an integer flag, set it to 1 to make the quantity received to be equal to the quantity ordered when the lines are copied.

    Hope that helps

    Elliott

  • +1 in reply to Anastasia Maher
    verified answer

    The PO_Receipt_bus class contains the CopyPurchaseOrderLines() method, not the lines. If you need to access class specific methods (like this) that are not covered by the interfaces, you can use the PvxObject property which provides direct access to the class instance. Just keep in mind that the method name will need to be prefixed with the result type: n = numeric, s = string, o = object.

    Example:

    /* Copy the purchase order lines; 1 for receiveComplete, 0 to not receiveComplete, method result value should be 1 */
    var result = receiptEntry.PvxObject.nCopyPurchaseOrderLines(0, purchaseOrderNo);

    Anyways, once you have the lines copied, you will need to walk the collection using MoveFirst, while not EOF {...} MoveNext.

    Full example provided.

    using Sage100.ObjectManagement;
    using Sage100.ObjectManagement.Interfaces;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    
    namespace ConsoleApp12
    {
        class Program
        {
            static void TestExample()
            {
                /* Numbers used */
                var batchNo = "00001";
                var purchaseOrderNo = "0010032";
                var vendorDiv = "01";
                var vendorNo = "AIRWAY";
                var wareHouseCode = "000";
    
                var sessionLogon = new SessionLogon
                {
                    CompanyCode = "ABC",
                    UserLogon = new NetworkCredential { UserName = "all", Password = "" },
                    ModuleCode = "P/O",
                    ModuleDate = DateTime.Today
                };
    
                try
                {
                    using (var session = new MasSession(@"d:\sage\sage 100\mas90\home"))
                    {
                        session.InitSession(sessionLogon);
    
                        CI.ColumnNames.Add("PO_Receipt_bus", new Dictionary<string, string> { { CI.NextNumberMethod, "nGetNextReceiptNo" }, { CI.HeaderKeyColumns, "ReceiptNo$" } });
    
                        using (var receiptEntry = session.CreateObject<ILineEntry>("PO_Receipt_bus", "PO_ReceiptofGoods_ui", "P/O"))
                        {
                            if (receiptEntry.BatchEnabled) receiptEntry.SelectBatch(batchNo);
    
                            var entryNo = receiptEntry.GetNextDocumentNumber();
    
                            receiptEntry.SetKeyValue("ReceiptType$", "G");
                            receiptEntry.SetKeyValue("ReceiptNo$", entryNo);
    
                            if (receiptEntry.SetKey() != 2) throw new ApplicationException(receiptEntry.LastErrorMessage);
    
                            receiptEntry.SetValue("PurchaseOrderNo$", purchaseOrderNo);
                            receiptEntry.SetValue("APDivisionNo$", vendorDiv);
                            receiptEntry.SetValue("VendorNo$", vendorNo);
                            receiptEntry.SetValue("WarehouseCode$", wareHouseCode);
    
                            /* Copy the purchase order lines; 1 for receiveComplete, 0 to not receiveComplete, result value should be 1 */
                            var result = receiptEntry.PvxObject.nCopyPurchaseOrderLines(0, purchaseOrderNo);
    
                            /* Sample data that is item code and QuantityReceived count */
                            var lineData = new Dictionary<string, double> /* ItemCode and QuantityReceived */
                            {
                                { "6655", 1 },
                                { "1001-HON-H252", 2 }
                            };
    
                            if (receiptEntry.Lines.MoveFirst())
                            {
                                while (!receiptEntry.Lines.EOF)
                                {
                                    var item = receiptEntry.Lines.GetValue<string>("ItemCode$");
                                    var received = lineData.Where(kvp => kvp.Key.Equals(item)).Select(kvp => kvp.Value).Sum();
    
                                    if (received != 0.0)
                                    {
                                        Console.WriteLine($"Updating {item} QuantityReceived to {received} for line {receiptEntry.Lines.GetKey()}");
                                        
                                        receiptEntry.Lines.SetValue("QuantityReceived", received);
    
                                        if (!receiptEntry.Lines.Write()) throw new ApplicationException(receiptEntry.Lines.LastErrorMessage);
                                    }
    
                                    receiptEntry.Lines.MoveNext();
                                }
                            }
    
                            if (!receiptEntry.Write()) throw new ApplicationException(receiptEntry.Lines.LastErrorMessage);
                        }
                    }
                } 
                catch (Exception exception)
                {
                    Console.WriteLine(exception.Message);
                }
            }
    
            static void Main(string[] args)
            {
                TestExample();
    
                Console.ReadLine();
            }
        }
    }

  • 0 in reply to Russell Libby

    Thank you   , this was SO helpful as i could not find any c# sample online. I tried the code you pasted and am receiving this error as soon as i try to copypurchaseorderlines {"<Error: 548 in Method COPYPURCHASEORDERLINES>"}

       private static void TestExample()
            {
                /* Numbers used */
                var batchNo = "03328";
                var purchaseOrderNo = "6000010";
                var vendorDiv = "00";
                var vendorNo = "0test";
                var wareHouseCode = "033";
    
                var sessionLogon = new SessionLogon
                {
                    CompanyCode = "test",
                    UserLogon = new NetworkCredential { UserName = "test", Password = "test!" },
                    ModuleCode = "P/O",
                    ModuleDate = DateTime.Today
                };
    
                try
                {
                    using (var session = new MasSession(@"\\test\Sage\Sage2019\MAS90\Home\"))
                    {
                        session.InitSession(sessionLogon);
    
                        CI.ColumnNames.Add("PO_Receipt_bus", new Dictionary<string, string> { { CI.NextNumberMethod, "nGetNextReceiptNo" }, { CI.HeaderKeyColumns, "ReceiptNo$" } });
    
                        using (var receiptEntry = session.CreateObject<ILineEntry>("PO_Receipt_bus", "PO_ReceiptofGoods_ui", "P/O"))
                        {
                            if (receiptEntry.BatchEnabled) receiptEntry.SelectBatch(batchNo);
    
                            var entryNo = receiptEntry.GetNextDocumentNumber();
    
                            receiptEntry.SetKeyValue("ReceiptType$", "G");
                            receiptEntry.SetKeyValue("ReceiptNo$", entryNo);
    
                            if (receiptEntry.SetKey() != 2) throw new ApplicationException(receiptEntry.LastErrorMessage);
    
                            receiptEntry.SetValue("PurchaseOrderNo$", purchaseOrderNo);
                            receiptEntry.SetValue("APDivisionNo$", vendorDiv);
                            receiptEntry.SetValue("VendorNo$", vendorNo);
                            receiptEntry.SetValue("WarehouseCode$", wareHouseCode);
    
                            /* Copy the purchase order lines; 1 for receiveComplete, 0 to not receiveComplete, result value should be 1 */
                            var result = receiptEntry.PvxObject.nCopyPurchaseOrderLines(0, purchaseOrderNo);
    /* ERROR THROWN RIGHT HERE */
    
    
                            /* Sample data that is item code and QuantityReceived count */
                            var lineData = new Dictionary<string, double> /* ItemCode and QuantityReceived */
                            {
                                { "441162", 1 }
                            };
    
                            if (receiptEntry.Lines.MoveFirst())
                            {
                                while (!receiptEntry.Lines.EOF)
                                {
                                    var item = receiptEntry.Lines.GetValue<string>("ItemCode$");
                                    var received = lineData.Where(kvp => kvp.Key.Equals(item)).Select(kvp => kvp.Value).Sum();
    
                                    if (received != 0.0)
                                    {
                                        Console.WriteLine($"Updating {item} QuantityReceived to {received} for line {receiptEntry.Lines.GetKey()}");
    
                                        receiptEntry.Lines.SetValue("QuantityReceived", received);
    
                                        if (!receiptEntry.Lines.Write()) throw new ApplicationException(receiptEntry.Lines.LastErrorMessage);
                                    }
    
                                    receiptEntry.Lines.MoveNext();
                                }
                            }
    
                            if (!receiptEntry.Write()) throw new ApplicationException(receiptEntry.Lines.LastErrorMessage);
                        }
                    }
                }
                catch (Exception exception)
                {
                    Console.WriteLine(exception.Message);
                }
            }

  • 0 in reply to Anastasia Maher

       i think i got it! i just changed this one line ...
      var result = receiptEntry.PvxObject.nCopyPurchaseOrderLines(0, purchaseOrderNo);
    to 
      var result = receiptEntry.PvxObject.nCopyPurchaseOrderLines(1);

    and it copied the purchase order lines! i will try setting it to 0 to see if it allows the partial. but this is much further than ive gotten all month , thank you SO much 

  • 0 in reply to Anastasia Maher

    Sorry about that, you didn't mention the version of Sage 100 so the example I gave was based on 2023. Older versions did not have the overloaded method which took the PO number. Whenever you get an error 548 using BOI externally, it means the method name was found but the arguments passed did not match the method parameters or its overloads, as was the case here.

    Regards,
    Russell