Problem with getting the sales price of item in Exact Online - exact-online

I am trying to use the exact online API, my web application can connect with the API and create Accounts, Items and all the other things.
But now, inside off my web application I need those Accounts and Items etcetera, I got it done to select all the Items and import those into my database, but I can't find the SalesPrice of an Item, only the 'CostPriceNew' and 'CostPriceStandard'!
After a while searching, I found out that there is another class called: ItemDetailsByID inside this class i found SalesPrice
At first i get an error: Fatal error: Uncaught TypeError: Argument 1 passed to Picqer\Financials\Exact\ItemDetailsByID::get() must be of the type array, string given
This is the code I used:
`
//Retrieve items
$items = new \Picqer\Financials\Exact\Item($connection);
$result = $items->get();
foreach ($result as $item) {
try {
$ItemDetails = new \Picqer\Financials\Exact\ItemDetailsByID($connection);
$result1 = $ItemDetails->get($item->ID);
foreach ($result1 as $ItemDetail) {
var_dump($ItemDetail);
}
} catch (\Exception $e) {
echo json_encode(array(get_class($e) . ' : ' . $e->getMessage()));
}
}
`
After reading the documentation from exact online i still don't managed to use this class.. now I am getting this error: ["Picqer\\Financials\\Exact\\ApiException : Error 400: Bad Request - Error in query syntax."]
After the first error I changed my code $result1 = $ItemDetails->get($item->ID);
into
$result1 = $ItemDetails->get(["eq guid" => "'$item->ID'"]);
I have tried multiple array keys like: 'eq guid', 'Edm.Guid', 'guid', 'id' but I stil get the error.
I hope that someone can help me or pointing me into the right direction.

You dont want to list all item prices, so instead of using get, you should use find. Since you only get one result, after that you can directly use the returned object:
$ItemDetails = new \Picqer\Financials\Exact\ItemDetailsByID($connection);
$result1 = $ItemDetails->find($item->ID);
var_dump($result1->SalesPrice);

Your question is not very clear, I try to give you a general suggestion before you add more info.
log the http protocol and compare with the doc, if you do not have a client log, you can send your request to httpbin.org(be careful with your password and other personal piracy using third party service), just like https://httpbin.org/get?itemId=guid'00000000-0000-0000-0000-000000000000'&$select=Code,SalesCurrency,SalesPrice.
It will print request info, this can help to debug
{
"args": {
"$select": "Code,SalesCurrency,SalesPrice",
"itemId": "guid'00000000-0000-0000-0000-000000000000'"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate, br",
"Cache-Control": "no-cache",
"Host": "httpbin.org",
"User-Agent": "PostmanRuntime/7.26.5",
},
"origin": "a.b.c.d",
"url": "https://httpbin.org/get?itemId=guid'00000000-0000-0000-0000-000000000000'&$select=Code,SalesCurrency,SalesPrice"
}

Related

Postman: POST request of nested JSON via form-data not working (while via raw-data ok)

I want to POST the following JSON-object via Postman:
{
"title": "test_title",
"date": "2021-12-31",
"attachments": [
{
"name": "test_attachment"
}
]
}
This works perfectly fine, when using Postman's raw input form for the request-body: I get a "201 Created"-response back.
However, when using the form-data to POST the data, I get the error "Invalid data. Expected a dictionary, but got str." (see also screenshot below) What am I doing wrong here? I tried all kind of other versions to enter the attachment-key:value pair but nothing worked so far
I managed to make it work! (note: I added some additional fields compared to the screenshot in question. See below for details:
You did nothing wrong.
If you want to make a request with json object, then you go with raw type (json) in postman.
If you want to upload file, then you use form-data
One more thing, status 201 means the request is succeed, your object has been created.
var express = require('express')
const multer = require('multer')
const upload = multer()
var app = express()
app.use(express.json());
app.post('/test',upload.none(), function (req, res, next) {
res.send(req.body)
})
app.listen(80, function () {
console.log('web server listening on port 80')
})
Above is a sample endpoint which works with both form-data and json , just do a post to http://localhost:80/test with both form data and raw json
you can see both will get parsed correclty
APIs are just abstraction , its like a function that takes in many attribute, how you parse it depends on the implementation ( how the api function is written) .
so answer is "Talk to the developer" on how the API is implemented and what it is supporting
I'm having issue in placing json into form format the way Daniel did in Postman. Need help in figuring out what is it required to place the cascaded json objects into form data format. Please see here that I'm trying to accomplish.
JSON Format (to be filled into Postman form-data section:
{
"primary_object": {
"child_object_1": [{"id": 12345678, "value": "abc"},{"id": 87654321, "value": "xyz"}],
"child_object_2": [
"first_val",
"second_val"
]
}
}

GuzzleHttp - Get JSON encoded body

I created an API client for my company to fetch orders from our distributors. I need to acknowledge download of orders back to them with a PUT. The PUT is working properly but I get an error on their confirmation of my acknowledgement.
Using Postman, I get a JSON body message back.
When I PUT a acknowledgement back, I get the following error:
Type error: Argument 1 passed to GuzzleHttp\Client::send() must
implement interface Psr\Http\Message\RequestInterface, instance of
GuzzleHttp\Psr7\Response given, called in
/var/www/orders/app/Http/Controllers/edi/OrderController.php on line 86
This is line 86:
$response = $client->send($apirequest);
The relevant code:
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Client as GuzzleHttpClient;
use GuzzleHttp\Psr7\Stream;
use Illuminate\Support\Facades\Input;
use Response;
use XmlParser;
use Psr\Http\Message\RequestInterface;
public function orderConfirm()
{
$uri = config('services.orders.orderack');
$formdata = Input::all();
$orders = Input::get('orders');
try {
$client = new GuzzleHttpClient([
'headers'=> [
'Authorization' => '$user',
'ContractID' => '$contract',
'Content-Type' => 'application/json']
]);
$apirequest = $client->request('PUT', $uri,
['body' => json_encode(
[
$orders
]
)]
);
$response = $client->send($apirequest);
$contents = (string) $response->getBody();
return $contents;
}
catch (RequestException $ex) {
//Exception Handling
echo $ex;
}
Output from Postman was:
"Number of Orders Acknowledged: 1"
from other posts on SO, this:
$contents = (string) $response->getBody();
is the way to get the body and other people fixed their problems, but it's not working for me.
Obviously I'm still missing something here!
Calling $client->request() actually does the request (which is why it's returning an instance of GuzzleHttp\Psr7\Response) instead of building a request object to send later. You don't need to tell the client to send anything because it's already been sent; you just need to set the $response variable to the value of the call to $client->request().
This can be seen in the Body example in their PSR7 documentation.
$response = $client->request('GET', 'http://httpbin.org/get');
To build a request object manually, you will have to create an instance of GuzzleHttp\Psr7\Request using its constructor, as documented under Requests.
// Create a request using a completely custom HTTP method
$request = new \GuzzleHttp\Psr7\Request('MOVE', 'http://httpbin.org/move');
echo $request->getMethod();
// MOVE

cakephp 3.x _serialize key not working

I an trying to return json from a cakephp 3.1 controller function. My problem is that no matter what I do with the _serialize flag, the response is always that there is a missing view template file.
In the cake docs it says to set the _serialize flag if you do not need to use a template to format the response. Cake Docs on View _serialize
Below is the Javascript on the client side that initializes the process
function save_activity( mod, act, resp ) {
$.ajax({
method: 'POST',
url: '/activities/saveActivity',
data: {
'module' : "example1",
'activity_name' : "example2",
'response' : "example3"
},
dataType: 'json',
error: function( xhr, status, error ){
alert( status + error );
},
success: function( data, status, xhr ){
alert( status + data.success );
}
});
}
The Controller code that handles the json from the client.
public function saveActivity()
{
$user = $this->Auth->user();
//This line does not seem to do anything
//$this->request->input('json_decode', 'true');
//Debugger::log($this->request->data);
$activityTable = TableRegistry::get('Activities');
$activity = $activityTable->newEntity();
$activity->user_id = $user['id'];
$activity->module = $this->request->data('module');
$activity->activity_name = $this->request->data('activity_name');
$activity->response = $this->request->data('response');
//These lines do not have any effect
//$this->RequestHandler->renderAs($this, 'json');
//$this->response->type('application/json');
//$this->viewBuilder()->layout(null);
//$this->render(false);
$msg = '';
if ($activityTable->save($activity)) {
$msg = 'Activity Stored';
} else {
$msg = 'Activity Not Stored';
}
$this->set(['response' => $msg]);
//comment or uncomment this line and it makes no difference
//as it still returns a json response about a missing template.
$this->set('_serialize', true);
}
The error message I get when I include or remove the _serialize flag.
"Template file "Pages\json\module1\activity4.ctp" is missing."
Anyone have any insight into this mechanims? The workaround I have found is to include the template file... but this means I will have to generate a few dozen essentially empty template files to handle all the places this call is generated from.
Any help please?
Problem cause:- Violation of assumption.
My assumption was that the saveActivity method was being executed. While the reality was that AuthComponent was failing to allow access to that method and the default handler was being run instead, then the default view template was being looked for... and failing.
I found this by looking at the stack track attached to the error message in the returned page via devTools. I should also have verified this assumption with some simple trace logging calls. I already had the clue when I commented out the "$this->set('_serialize', true);" and nothing changed.
Then the simple solution was to authorise the method in the controllers beforeFilter:
public function beforeFilter(Event $event)
{
parent::beforeFilter($event);
$this->Auth->allow('saveActivity');
$this->Auth->allow('getActivity');
$this->eventManager()->off($this->Csrf);
}
Thanks for the assist ndm.

Angular resource 404 Not Found

I've read other posts that have similar 404 errors, my problem is that I can correctly query the JSON data, but can't save without getting this error.
I'm using Angular's $resource to interact with a JSON endpoint. I have the resource object returning from a factory as follows:
app.factory('Product', function($resource) {
return $resource('api/products.json', { id: '#id' });
});
My JSON is valid and I can successfully use resource's query() method to return the objects inside of my directive, like this:
var item = Product.query().$promise.then(function(promise) {
console.log(promise) // successfully returns JSON objects
});
However, when I try to save an item that I've updated, using the save() method, I get a 404 Not Found error.
This is the error that I get:
http://localhost:3000/api/products.json/12-34 404 (Not Found)
I know that my file path is correct, because I can return the items to update the view. Why am I getting this error and how can I save an item?
Here is my data structure:
[
{
"id": "12-34",
"name": "Greece",
"path": "/images/athens.png",
"description": ""
},
...
]
By default the $save method use the POST verb, you will need to figure out which HTTP verbs are accepted by your server en order to make an update, most modern api servers accept PATCH or PUT requests for updating data rather than POST.
Then configure your $resource instance to use the proper verb like this :
app.factory('Product', function($resource) {
return $resource('api/products.json', { id: '#id' }, {'update': { method:'PUT' }});
});
check $resource docs for more info.
NOTE: $resource is meant to connect a frontend with a backend server supporting RESTful protocol, unless you are using one to receive data & save it into a file rather than a db.
Otherwise if you are only working with frontend solution where you need to implement $resource and have no server for the moment, then use a fake one, there is many great solutions out there like deployd.
You probably don't implement POST method for urls like /api/products.json/12-34. POST method is requested from angular for saving a new resource. So you need to update your server side application to support it and do the actual saving.
app.factory('Product', function($resource) {
return $resource('api/products.json/:id', { id: '#id' });
});
Try adding "/:id" at the end of the URL string.

Laravel 4 & Mandrill JSON response

I've started sending mails through Laravel (4.2) and its embedded Mandrill driver these days, but I need to catch Mandrill's response somehow.
Here's the code I use to send the message:
Mail::queue('emails.customerspromo', array('messaggio'=>$content, 'disclaimer'=>$disclaimer, 'user_email'=>$to, 'user_id'=>$uid), function($message) use ($sender, $to, $subject) {
$message->from('my#address.it', $sender);
$message->to($to);
$message->subject($subject);
$message->setCharset('UTF-8');
$message->getHeaders()->addTextHeader('X-MC-GoogleAnalytics', 'www.my-site.it');
$message->getHeaders()->addTextHeader('X-MC-GoogleAnalyticsCampaign', 'my-campaign');
});
What I need to intercept is Mandrill's JSON response, for example:
[
{
"email": "destination#address.com",
"status": "sent",
"_id": "80e1ca49d3ed4cbb9d9a3d932c0a14f8",
"reject_reason": null
}
]
How can I do that using Laravel's integrated drivers for Mandrill?
I could use Mail::send instead of Mail::queue, if it's necessary to interpret the response in real time.
Put a variable before your mail function like this:
$response = Mail::queue('emails.customerspromo', array('messaggio'=>$content, 'disclaimer'=>$disclaimer, 'user_email'=>$to, 'user_id'=>$uid), function($message) use ($sender, $to, $subject) {
$message->from('my#address.it', $sender);
$message->to($to);
$message->subject($subject);
$message->setCharset('UTF-8');
$message->getHeaders()->addTextHeader('X-MC-GoogleAnalytics', 'www.my-site.it');
$message->getHeaders()->addTextHeader('X-MC-GoogleAnalyticsCampaign', 'my-campaign');
});
It will still work but now you can see the response from mandrill.