Unable to Post an invoice to Sage One via API 422 Error - vb.net

I am able to authenticate against the SAGE ONE API and also able to retrieve data from the API however I am now trying to post a simple invoice however keep getting a 422 error. Is there something obvious I am missing?
I have double checked the JSON structure and the values i am providing and are all valid. Not sure what i am doing wrong here!
my JSON package looks like this
{"contact_id":"66b76fa19edc11e797950a57719b2edb",
"date":"2019-04-13",
"invoice_lines":[{"description":"Test Description",
"ledger_account_id":"0367afd89ece11e797950a57719b2edb","quantity":1,"unit_price":100}]}
code
Dim http As HttpWebRequest = WebRequest.Create(New Uri("https://api.columbus.sage.com/uki/sageone/accounts/v3/sales_invoices"))
http.Method = "POST"
http.ContentType = "application/json"
http.Accept = "application/json"
http.Headers.Add("X-Site", "mysite")
http.Headers.Add("ocp-apim-subscription-key", "mykey")
http.Headers.Add("Authorization", "Bearer " mytoken)
Dim data = Encoding.UTF8.GetBytes(json)
http.ContentLength = data.Length
Dim stream = http.GetRequestStream()
stream.Write(data, 0, data.Length)
stream.Close()
Dim response = http.GetResponse().GetResponseStream()

This POST body worked for me (with different ids):
{
"sales_invoice": {
"contact_id": "66b76fa19edc11e797950a57719b2edb",
"date": "2019-04-13",
"main_address": { "address_line_1": "42 Test Street" },
"invoice_lines": [
{
"description": "Test Description",
"ledger_account_id": "0367afd89ece11e797950a57719b2edb",
"quantity": 1,
"unit_price": 100,
"tax_rate_id": "GB_NO_TAX"
}
]
}
}
You need to wrap your JSON structure with a key, which is the name of your resource ("sales_invoice" in this case).
You also need to specify a main address, as well as a tax rate id for each line item.
To be sure to have a valid ledger account for your sales invoice, get a list of possible accounts with:
GET /ledger_accounts?visible_in=sales

Related

Karate API : * def from response is throwing syntax error

I am setting up an E2E test and chaining my request/responses. I am defining variables from each response and using them in the next call.
Its working up to a point, and then a problem surfaces when defining off the 2nd response.
If I def operationId, operationSubject, or operationStatus (e.g response.operationId), it works.
If I store anything from the results (e.g response.results.0.personId) it throws this error
Expected ; but found .0
response.results.0.personId
My response:
{
"operationId": "922459ecxxxxx",
"operationSubject": "BATCH_ENROLLMENT",
"operationStatus": "PROCESSED",
"results": {
"0": {
"personId": "367a73b5xxxx",
"status": "PRE_AUTH",
"email": "mquinter+TEST.69387488#email.com",
"loanNumber": null
},
"1": {
"personId": "56f060fd-e34xxxxxx",
"status": "PRE_AUTH",
"email": "mquintxxxx#email.com",
"loanNumber": null
}
}
}
That's not how to access data in JSON. See this similar question: https://stackoverflow.com/a/71847841/143475
Maybe you meant to do this:
* def foo = response.results[0].personId
https://stackoverflow.com/users/143475/peter-thomas
I see the issue - It wasn't finding the response because I wasn't giving it enough time before the next call.
I put a sleep in there and its working as expected.
Thanks

JToken "becomes" null during iteration

I am developing a sort of gateway API for an Ionic mobile-app, which has to talk to some online API that doesn't accept front-end calls.
One call returns a JSON object, with a "data"-array of JObjects. A response of the server looks like this (below JSON just shows one result, to give an idea of what the server's response looks like):
{
"currentPage": 1,
"numberOfPages": 1,
"totalResults": 19,
"data": [
{
"id": "BznahA",
"name": "Anheuser-Busch InBev",
"nameShortDisplay": "Anheuser-Busch InBev",
"description": "Anheuser-Busch operates 12 breweries in the United States, 14 in China and one in the United Kingdom. Anheuser-Busch's operations and resources are focused on adding to life's enjoyment not only through the responsible consumption of beer by adults, but through theme park entertainment and packaging. In the United States, the company holds a 48.5 percent share of U.S. beer sales. Worldwide, Anheuser-Busch's beer sales volume was 128.4 million barrels in 2007. The St. Louis-based company's subsidiaries include one of the largest U.S. manufacturers of aluminum beverage containers and one of the world's largest recyclers of aluminum beverage cans. Anheuser-Busch also has interests in malt production, rice milling, real estate development, turf farming, metalized and paper label printing, bottle production and transportation services.",
"website": "http://www.anheuser-busch.com/",
"established": "1852",
"isOrganic": "N",
"images": {
"icon": "https://brewerydb-images.s3.amazonaws.com/brewery/BznahA/upload_0FkKKl-icon.png",
"medium": "https://brewerydb-images.s3.amazonaws.com/brewery/BznahA/upload_0FkKKl-medium.png",
"large": "https://brewerydb-images.s3.amazonaws.com/brewery/BznahA/upload_0FkKKl-large.png",
"squareMedium": "https://brewerydb-images.s3.amazonaws.com/brewery/BznahA/upload_0FkKKl-squareMedium.png",
"squareLarge": "https://brewerydb-images.s3.amazonaws.com/brewery/BznahA/upload_0FkKKl-squareLarge.png"
},
"status": "verified",
"statusDisplay": "Verified",
"createDate": "2012-01-03 02:41:44",
"updateDate": "2018-11-02 02:15:01",
"isMassOwned": "Y",
"isInBusiness": "Y",
"isVerified": "N",
"locations": [
{
"id": "ZApGug",
"name": "Main Brewery",
"streetAddress": "One Busch Place",
"locality": "Saint Louis",
"region": "Missouri",
"postalCode": "63118",
"phone": "(314) 577-2626",
"website": "http://www.anheuser-busch.com/",
"latitude": 38.5985037,
"longitude": -90.2093428,
"isPrimary": "Y",
"inPlanning": "N",
"isClosed": "N",
"openToPublic": "Y",
"locationType": "macro",
"locationTypeDisplay": "Macro Brewery",
"countryIsoCode": "US",
"yearOpened": "1852",
"status": "verified",
"statusDisplay": "Verified",
"createDate": "2012-01-03 02:41:44",
"updateDate": "2018-11-02 02:14:56"
Now, my gateway API processes this into self-made objects and returns it to the mobile app. The methods are defined as such:
var resp = await _clientFactory.CreateClient().GetAsync(
apiCall.Uri
);
var token = JToken.Parse(await resp.Content.ReadAsStringAsync());
var data = token["data"]; // gets data array from parsed JToken
// iterates through data, makes models and returns
return data.Select(ParseBrewery).ToList();
This next method is where the NullPointer error occurs. This method takes the JTokens from the data in the method above. However, the breweryToken parameter throws a NullPointer exception.
// takes JToken and assigns element to returned model
private static Brewery ParseBrewery(JToken breweryToken) => new Brewery()
{
Id = breweryToken["id"].ToObject<string>(),
Name = breweryToken["name"].ToObject<string>(),
NameShortDisplay = breweryToken["nameShortDisplay"]?.ToObject<string>(),
CreateDate = breweryToken["createDate"].ToObject<DateTimeOffset>(),
UpdateDate = breweryToken["updateDate"]?.ToObject<DateTimeOffset>(),
Status = breweryToken["status"].ToObject<string>(),
InBusiness = breweryToken["inBusiness"]?.ToObject<string>() != "N",
IsVerified = breweryToken["isVerified"].ToObject<string>() != "N",
Locations = JToken.Parse(breweryToken["locations"].ToString())?.Select(ParseLocation).ToList()
};
The ParseLocation-method handles the location object (a subobject in each object in the data JToken).
// takes JToken (parsed in ParseBrewery method) and assigns values to returned model
private static Location ParseLocation(JToken locationToken) => new Location()
{
Id = locationToken["id"].ToObject<string>(),
Name = locationToken["name"].ToObject<string>(),
StreetAddress = locationToken["streetAddress"].ToObject<string>(),
City = locationToken["locality"].ToObject<string>(),
Region = locationToken["region"].ToObject<string>(),
PostalCode = locationToken["postalCode"].ToObject<string>(),
Website = locationToken["website"].ToObject<string>(),
Latitude = locationToken["latitude"].ToObject<double>(),
Longitude = locationToken["longitude"].ToObject<double>(),
CreateDate = locationToken["createDate"].ToObject<DateTimeOffset>(),
Status = locationToken["status"].ToObject<string>(),
Country = ParseCountry(locationToken["country"])
};
This method again handles a subobject of the location object.
// takes JToken from ParseLocation method and returns filled model
private static Country ParseCountry(JToken countryToken) => new Country()
{
IsoCode = countryToken["isoCode"].ToObject<string>(),
Name = countryToken["name"].ToObject<string>(),
IsoThree = countryToken["isoThree"]?.ToObject<string>(),
NumberCode = countryToken["numberCode"]?.ToObject<int>(),
CreateDate = countryToken["createDate"].ToObject<DateTimeOffset>()
};
The problem I am running into is, as I mentioned at the corresponding method, somehow the JToken from data seems to become null at some point or another. Debugging through the code shows there is definitely data being returned, but after two or three iterations, it just jumps to the end of the call and throws a NullPointer exception.
I have tried running the variable data through JToken.Parse separately, but I keep running into the same issue. Parsing each separate item in the ParseBrewery method call also returns an error.
I am at a point where I do not know what else I could try to get this to work. I have simply no idea why this could be happening, but I am quite sure it must be a tiny thing as another part of the API which works exactly the same way does return data succesfully.
Hopefully I have provided you with enough info and example code to help understand my problem. If not or if you have any questions, of course feel free to ask and I will answer to the best of my ability!
Thankyou in advance.

autorisation required for share file in google drive

With Google Drive for VB.Net, I managed to get a shareable link with another person, but when the person tries to open the file or put the link into the address bar, an error occurs "Authorization required".
Here is my code:
Dim list = Service.Files.List()
Dim count = list.Execute()
For Each fich In count.Items
If (fich.Title) = fichier Then
fich.Shared = True
Dim userpermit = New Permission()
userpermit.Type = "user"
userpermit.Role = "Reader"
userpermit.Value = "*********"
userpermit.EmailAddress = "*******"
userpermit.WithLink = True
listfile.adr_mail.Text = fich.AlternateLink ' to Get a shareable link
Dim req = Service.Permissions.Insert(userpermit, fich.Id)
req.Fields = "id"
Exit For
End If
Next
Here are the reasons why the user aside from the owner cannot directly access the file even if there is a shareable link,
The file may be private (for the owner only)
The user trying to open the file may not be in the list of authorized user
To check the list of the users, use the Try it now part.
You need to supply the fileId.
GET https://www.googleapis.com/drive/v2/files/fileId/permissions
and you will get response like this:
{
"kind": "",
"etag": "",
"id": "",
"selfLink": "",
"name": "",
"emailAddress": "#something.com",
"domain": "something.com",
"role": "owner",
"type": "user",
"deleted":
}

Postman JSON value check test fails

I have an API which has response as below:
"data": {
"catalog_list_items": [
{
"catalog_list_items": [
{
"catalog_list_items": [
{
"title": "L13",
"content_id": "58a85146b0000ec",
"sequence_no": 1,
"language": "hindi",
"genres": [
"xxxx"
]
I would like to create a test in postman to verify that the language key has value as 'hindi'. I am writing below test in Postman which always fails. Cannot find the reason.
var jsonData = JSON.parse(responseBody);
tests["Language is hindi"] = jsonData.data.catalog_list_items[3].language === "hindi";
However, when I use the similar structure to test sequence_no, it works fine
var jsonData = JSON.parse(responseBody);
tests["Sequence No is 1"]= jsonData.data.catalog_list_items[3].sequence_no === 1;
Can anyone shed a light for me?
I could see 3 level nested arrays in your response body.
So I don't know how are you getting your value through this expression:
jsonData.data.catalog_list_items[3].language
The correct expression to get the 'language' key from above response should be:
jsonData.data.catalog_list_items[0].catalog_list_items[0].catalog_list_items[0].language

JSON parsing using JSON.net

I am accessing the facebook api and using the json.net library (newtonsoft.json.net)
I declare a Jobject to parse the content and look for the specific elements and get their values. Everything works fine for the first few but then I get this unexplained nullexception error " (Object reference not set to an instance of an object)
Now I took a look at the declaration but cannot see how to change it. Any help appreciated:
Dim jobj as JObject = JObject.Parse(responseData)
message = jobj("message").tostring
The error occurs at the last line above.I check to see if message is null and then look for the next desired field as follows
catch exception..
dim jobj2 as JObject = JObject.parse(responseData)
description = jobj2("description").tostring
JSON responsedata:
{
"id": "5281959998_126883980715630",
"from": {
"name": "The New York Times",
"category": "Company",
"id": "5281959998"
},
"picture": "http://external.ak.fbcdn.net /safe_image.php?d=e207958ca7563bff0cdccf9631dfe488&w=
90&h=90&url=http\u00253A\u00252F\u00252Fgraphics8.nytimes.com\u00252Fimages\u00252F2011\u00252F02\u00252F04\u00252Fbusiness\u00252FMadoff\u00252FMadoff-thumbStandard.jpg",
"link": "http://nyti.ms/hirbn0",
"name": "JPMorgan Said to Have Doubted Madoff Long Before His Scheme Was Revealed",
"caption": "nyti.ms",
"description": "Newly unsealed court documents show that bank
executives were suspicious of Bernard Madoff\u2019s accounts
and steered clients away from him but did not alert regulators.",
"icon": "http://static.ak.fbcdn.net/rsrc.php/yD/r/aS8ecmYRys0.gif",
"type": "link",
"created_time": "2011-02-04T16:09:03+0000",
"updated_time": "2011-02-06T20:09:51+0000",
"likes": {
"data": [
{
"name": "Siege Ind.",
"category": "Product/service",
"id": "152646224787462"
},
{
"name": "Lindsey Souter",
"id": "100000466998283"
},
This is one example where "message" does not appear in the first few lines but appears later. So what I do is look for position of message and description and which ever is first go and get that and if I get an error or the fields do not return anything, I try and parse by regex and even that is not working right.
Well, presumably jobj("message") has returned Nothing, which will happen if jobj doesn't have a message property. If you think this is incorrect, please post a short but complete piece of JSON to help us investigate.
(Is there any reason why you're declaring message and assigning it a value on the second line, only to overwrite that value on the third line?)