Create new items in QuickBooks via C# - c#

I have a C# tool that I wrote to sync orders from a DB to QB, and every step has been a giant pain.
I'm trying to create the line items that we have in our DB in QB so I can attach the invoice items correctly, but our system allows sales staff to enter custom words, so I can't just add all the possible line items to QB through the QB interface.
I have this piece of code here
IMsgSetRequest AddItemRequestMsgSet = sessionManager.CreateMsgSetRequest("US", 8, 0);
AddItemRequestMsgSet.Attributes.OnError = ENRqOnError.roeContinue;
IItemServiceAdd itemAddRq = AddItemRequestMsgSet.AppendItemServiceAddRq();
itemAddRq.Name.SetValue(Item);
// itemAddRq.ORSalesPurchase.
IMsgSetResponse ItemAddResponseMsgSet = sessionManager.DoRequests(AddItemRequestMsgSet);
IResponse ItemAddResponse = ItemAddResponseMsgSet.ResponseList.GetAt(0);
But this is throwing an error that:
ORSalesPurchase: required field is missing
I haven't the slightest idea of what that means, and for the life of me I can't find anything about ORSalesPurchase or IItemServiceAdd elsewhere on the Internet, including their docs.
I can tell with Visual Studio's autocomplete that itemAddRq.ORSalesPurchase has a bunch of options, but I haven't been able to infer from that what QB is asking for.
What are the required fields for adding a service item to QB?
And if someone can point me to where this is in their docs that would be extra wonderful:)
Stack trace:
System.Runtime.InteropServices.COMException (0x80040307):
ItemServiceAdd ORSalesPurchase: required field is missing End of
ItemServiceAdd
at QBFC12Lib.IQBSessionManager.DoRequests(IMsgSetRequest request)
at SterlingQBExport.Form1.CheckNewInvoices(Object source,
ElapsedEventArgs e) in C:\Users\brian\Documents\Visual Studio
2015\Projects\SterlingQBExport\SterlingQBExport\Form1.cs:line 537

Based on an article I found while searching for ORSalesPurchase ...
C# .NET Application with QuickBooks Desktop Edition
This article is an introduction on how to integrate a .NET application with QuickBooks Desktop Edition using the QuickBooks Foundation Classes (QBFC) Library and C#.
... and the error message, it would seem that you are missing certain fields expected to be part of the requests ORSalesPurchase
Using a sample from the article I would suspect it looks something like the following
//Create the message set request object to hold our request
IMsgSetRequest addItemRequestMsgSet = sessionManager.CreateMsgSetRequest("US", 8, 0);
addItemRequestMsgSet.Attributes.OnError = ENRqOnError.roeContinue;
IItemServiceAdd itemServiceAddRq = addItemRequestMsgSet.AppendItemServiceAddRq();
itemServiceAddRq.Name.SetValue(Item.Name);
itemServiceAddRq.ORSalesPurchase.SalesOrPurchase.Desc.SetValue(Item.Description);
itemServiceAddRq.ORSalesPurchase.SalesOrPurchase.ORPrice.Price.SetValue(Item.Price);
itemServiceAddRq.ORSalesPurchase.SalesOrPurchase.AccountRef.FullName.SetValue("Some custom service description here");
//...
Now there was more which seems to infer that the fields set differ based on the items already having a quickbooks id where it was set using
itemServiceModRq.ListID.SetValue(Item.QuickBooksID);
Now, I am not entirely certain what the required fields are at this point, but this should be a good starting point to check if providing the fields above helps.

Related

How to use EUInformation on a OPC-UA server (C#)?

I'm new in OPC-UA. I looked into the reference SDK and some online tutorial.
I'm creating a OPC-UA server for a simulation of an industrial machine.
I created my xml model with some motors and sensors. They both have an AnalogItemType variable.
I'm taking the motor in example:
<opc:ObjectType SymbolicName="Motor" BaseType="ua:BaseObjectType">
<opc:Description>A motor.</opc:Description>
<opc:Children>
<opc:Variable SymbolicName="Speed" DataType="ua:Double" ValueRank="Scalar" TypeDefinition="ua:AnalogItemType" AccessLevel="ReadWrite" />
<opc:Method SymbolicName="Start" ModellingRule="Mandatory"></opc:Method>
<opc:Method SymbolicName="Stop" ModellingRule="Mandatory"></opc:Method>
</opc:Children>
</opc:ObjectType>
I use the UA.ModelCompiler (from OPC-UA Foundation) to compile the xml and generate the code for the server.
I use the Reference client in the Reference SDK.
When I run my server, I can see only the EURange property of the AnalogItem and not the EngineeringUnits (both should be optional and not mandatory).
I tried to set both in my NodeManager.cs :
Server.Motor.Speed.EURange.Value = new Opc.Ua.Range() {Hingh = 900, Low = 100};
Server.Motor.Speed.EngineeringUnits.Value = new EUInformation("rad", "radiants", "http://www.opcfoundation.org/UA/units/un/cefact");
The first instruction is ok but the second throws an exception because, it says, the EngineeringUnits is null (while the EURange is of type [Variable]EURange).
How can I set the EngineeringUnits (and maybe diable EURange) in my C# code?
How can I enable the EngineeringUnits (and maybe diable EURange) in the MyModelDesign.xml?

Call a SAP transaction/program with the SAP 3.0 .NET Connector

I am aware of the option to call RFC-functions with .NCo 3.0 but is it possible to call transactions/programs directly with the SAP Connector? (Like using the fields defined in SAP as parameters and fill them, or use a variation, something like this?).
This answer provides a workaround that I am aware of, and sure - I could call a VBScript from my C# code but that is not what I want to do.
I also checked all of the 64 Questions tagged with sap-connector but there was nowhere a direct answer if it is possible or not.
Also the SAP documentations I got from the SAP marketplace aren't mentioning transactions/programs at all. Does this mean it is not wanted/possible ?
If so, why is it possible to do it with macros/pre-recorded VBScripts but not with the .NET-Connector ? Or am I just doing something wrong ?
When I try to call a program/transaction with the standart-code:
SAPHandle.ECCDestinationConfig cfg = new SAPHandle.ECCDestinationConfig();
RfcDestinationManager.RegisterDestinationConfiguration(cfg);
RfcDestination dest = RfcDestinationManager.GetDestination("QP2");
dest.Ping(); //works fine -> Connection is OK
RfcRepository repo = dest.Repository;
IRfcFunction zzmkalzzm23fnc = repo.CreateFunction("ZMZKALZZM23");
it gives me the following (expectable) error:
metadata for function ZMZKALZZM23 not available: FU_NOT_FOUND:
function module ZMZKALZZM23 is not available
CreateFunction, as the name already suggests, creates a proxy to call a remote-enabled function module in the SAP system. You can't call a transaction or program this way. I am not aware of any way to call a report with SAP .Net Connector. The solution you linked uses SAP Gui, which provides the SAP system with a UI to display graphical elements. AFAIK, SAP NCo doesn't provide such an interface and you can't call reports from NCo.
However, there are products that allow you to execute transactions and catch their output. We are using the product Theobald Xtract to extract SAP ERP data for BI purposes, but they also have a more generic .Net library (Theobald ERPConnect) available that may be able to provide this functionality. It won't be as simple as calling a function and extracting the strongly typed data, but with some filtering you should be able to get the output you need. Those products are not cheap, but they do provide a nice set of functionality you otherwise would have to reinvent yourself.
Some example code how you could call the transaction you ended up calling through VBS-Scripts.
From the Theobald ERPConnect Knowledgbase:
private void button1_Click(object sender, System.EventArgs e)
{
// Reset the batch steps
transaction1.BatchSteps.Clear();
// fill new steps
transaction1.ExecutionMode = ERPConnect.Utils.TransactionDialogMode.ShowOnlyErrors;
transaction1.TCode = "MMBE";
transaction1.AddStepSetNewDynpro("RMMMBEST","1000");
transaction1.AddStepSetOKCode("ONLI");
transaction1.AddStepSetCursor("MS_WERKS-LOW");
transaction1.AddStepSetField("MS_MATNR-LOW",textBox1.Text);
transaction1.AddStepSetField("MS_WERKS-LOW",textBox2.Text);
// connect to SAP
r3Connection1.UseGui = true;
R3Connection r3Connection1= new R3Connection("SAPServer",00,"SAPUser","Password","EN","800");
r3Connection1.Open(false);
// Run
transaction1.Execut e();
}

Payment on a bill not working using QBFC12 for QuickBooks 2013

I am using C# to connect with QuickBooks desktop 2013. I need to record payments against a bill, but cannot figure out why it is not working. My current code keeps throwing an error of 3120 saying it can't find the bill, even though the bill object is open in my control. I've used the IDN Unified OSR provided by intuit for the BillPaymentCheckAdd object structure, but the "data" they pass in is just random and not helpful for what I actually need to pass in as values. So I could use some help. Here is my code for the pay bill method:
IBillPaymentCheckAdd paymentAdd = requestMsgSet.AppendBillPaymentCheckAddRq();
paymentAdd.PayeeEntityRef.ListID.SetValue(vendorId);
paymentAdd.TxnDate.SetValue(DateTime.Now);
paymentAdd.BankAccountRef.ListID.SetValue(bankAccount.ListID.GetValue());
paymentAdd.ORCheckPrint.IsToBePrinted.SetValue(true);
paymentAdd.Memo.SetValue(bankAccount.Name.GetValue());
IAppliedToTxnAdd appliedToTxnAdd = paymentAdd.AppliedToTxnAddList.Append();
appliedToTxnAdd.TxnID.SetValue(bill.TxnID.GetValue());
appliedToTxnAdd.PaymentAmount.SetValue((double)amount);
ISetCredit setCredit = appliedToTxnAdd.SetCreditList.Append();
setCredit.CreditTxnID.SetValue(bill.TxnID.GetValue());
setCredit.AppliedAmount.SetValue((double)amount);
paymentAdd.IncludeRetElementList.Add(bankAccount.Name.GetValue());
IMsgSetResponse responseMsgSet = sessionManager.DoRequests(requestMsgSet);
IResponse response = responseMsgSet.ResponseList.GetAt(0);
IBillPaymentCheckRet paymentRet = (IBillPaymentCheckRet)response.Detail;
I think the error that you are getting is referring to the setCredit section. The credits are used to apply a previous vendor credit to a bill. You are passing in the Bill TxnID as the credit, but it's a bill transaction, not a credit transaction so QuickBooks is saying it can't find the credit transaction as it doesn't really exist.
If you remove the 4 line section for the ISetCredit, your payment should go through correctly.

QuickBooks Intuit IPP Issue Check

I am attempting to issue a check to a vendor through the Intuit.IPP API (Interop.QBFC12) using the following code:
IMsgSetRequest messageSet = session.CreateMsgSetRequest("US", 7, 0);
ICheckAdd cheque = messageSet.AppendCheckAddRq();
cheque.AccountRef.ListID.SetValue(vendor.ListID.GetValue());
cheque.AccountRef.FullName.SetValue("myAccountName");
cheque.TxnDate.SetValue(DateTime.Today);
IMsgSetResponse responseSet = session.DoRequests(messageSet);
IResponse response = responseSet.ResponseList.GetAt(0);
responseType = (ENResponseType)response.Type.GetValue();
if (responseType == ENResponseType.rtCheckAddRq)
returnMessage = response.StatusMessage;
The resulting response.StatusMessage = "Object 80000005-1374598713 specified in the request cannot be found. " The object ID specified is the ListID I pulled for the vendor.
I'm coding pretty much blind as I'm not finding the IPP documentation very helpful or up to date for version 12.
What am I missing?
This:
cheque.AccountRef.ListID.SetValue(vendor.ListID.GetValue());
cheque.AccountRef.FullName.SetValue("myAccountName");
Is what's causing you the problem.
The AccountRef node is for specifying an Account, not a Vendor. An Account is something from the QuickBooks Chart of Accounts (an "Account" object). A Vendor is something from the vendor list (a "Vendor" object) and they are not interchangable objects.
Since you're already setting an AccountRef/FullName:
cheque.AccountRef.FullName.SetValue("myAccountName");
You don't need to set a AccountRef/ListID.
You should always either set a ListID or a FullName - there's no reason to set both (it's just alternative ways to reference the same object - both are "foreign keys" of sorts to QuickBooks).
What you probably meant to do is set the AccountRef like you meant to, but also set the PayeeEntityRef. For example:
cheque.PayeeEntityRef.ListID.SetValue(vendor.ListID.GetValue());
Also, regarding this:
I'm coding pretty much blind as I'm not finding the IPP documentation
very helpful or up to date for version 12.
IPP is an entirely different API from what you're using. The IPP docs aren't going to be useful to you, because it's not anywhere close to the API you're using.
What you should be using for reference is the QuickBooks OSR:
https://member.developer.intuit.com/qbSDK-current/Common/newOSR/index.html
And also the QuickBooks SDK downloadable .EXE, which has a bunch of relevant PDF documentation.

ExchangeServiceBinding namespace error

Summary: application will not accept the ExchangeServiceBinding command.
Details:
I am trying to loop through a very large mailbox, so I am using an index to break the inbox into 200 email chunks. The only example I could find (shown below) keeps returning
the type or namespace name “ExchangeServiceBinding” could not be found (are you missing a using directive or an assembly reference? )
Which I find strange, because I am using it using Microsoft.Exchange.WebServices;. Any ideas or help is greatly appreciated. I am running Windows 7 and Visual Studio 2010 and trying to access Exchange 2007 mailboxes.
Things I've tried:
searching Google
searching Stack Overflow
searching MSDN
slamming my head on my desk
trial and error
Code:
// Create binding variable to be used for GetItemsFromInbox().
// Set up the binding with credentials and URL.
ExchangeServiceBinding binding = new ExchangeServiceBinding();
binding.Credentials = new NetworkCredential(dUser, dPassword, dDomain);
binding.Url = new Uri("https://" + ExchangeServerName + "/EWS/Exchange.asmx");
// Set up the binding for Exchange impersonation.
binding.ExchangeImpersonation = new ExchangeImpersonationType();
binding.ExchangeImpersonation.ConnectingSID = new ConnectingSIDType();
binding.ExchangeImpersonation.ConnectingSID.PrimarySmtpAddress = "mailboxnamehere”;
// Call GetItemsFromInbox()
int index = 0;
bool looping = true;
while (looping)
{
List<ItemType> items = GetItemsFromInbox(binding, index, 200, index);
if (items == null || items.count == 0)
{
looping = false;
break;
}
// Do your work here
}
Instead of the Exchange Web Services, use the Exchange Managed API.
SDK: http://msdn.microsoft.com/en-us/library/dd633710(v=exchg.80).aspx
Download: http://www.microsoft.com/download/en/details.aspx?id=13480
It's much easier to use than the WebServices.
I found my error. This methodology only works for Exchange 2010. Since I am running Exchange 2007 I will have to figure out a completely different way to make this work.
Thank you everyone for you help, I really appreciate it.
You should add a WebReference to your solution to the exchange WebService.
https://exchaneServerName/EWS/Exchange.asmx
ExchangeServiceBinding is contained into the ews.dll. According to your error, you didn't add a reference to this DLL file.
More information about Generating Exchange Web Services Proxy Classes:
So now you have a code file with the autogenerated proxies. Next, you compile your code file into an assembly for use in your Exchange Web Services projects. The C# compiler is available with the Visual Studio 2005 Command Prompt. Assuming that you named your code file EWS.cs, you can run the following command at the command prompt to compile your code into an assembly:
csc /target:library /out:EWS.dll EWS.cs
Notice that EWS.dll is the name of the compiled assembly. This is how EWS.dll is created.

Categories

Resources