Invoices are not inserted in quickbook - php

i'm trying to create invoice with multiple product/item in quickbook with help of this code https://github.com/IntuitDeveloper/SampleApp-CRUD-PHP/blob/master/CRUD_Examples/Invoice/InvoiceCreate.php but variable $resultingObj always gives num value when data are takes forloop but when passing only one product details successfully create invoice.
i applied this method Inserting contents of array into object not working gives as answer but still null.
invoice:
$num = 1;
$Lines = [];
foreach ($json as $rec) {
foreach ($rec['products'] as $pro) {
$productDetails = getItemObj($pro, $collection1);
if ($productDetails == 'Error') {
continue;
}
$taxDetails = getTaxObj($dataService, $pro);
if ($taxDetails == 'Error') {
continue;
}
$Lines[] =
[
"Id" => $num,
"Amount" => $pro['amount'],
"Description" => $pro['productDescription'],
"DetailType" => "SalesItemLineDetail",
"SalesItemLineDetail" => [
"ItemRef" => [
"value" => $productDetails->Id,
],
"TaxCodeRef" => [
"value" => $taxDetails->Id
],
"UnitPrice" => $pro['unitPrice'],
"Qty" => $pro['quantity'],
]
];
$num++;
}
$Lines[] = [
"Amount" => $rec['invoiceTotal'],
"DetailType" => "SubTotalLineDetail",
"SubTotalLineDetail" => []
];
$customerRef = getCustomerObj($dataService, $rec['clientName']);
$invoiceObj = Invoice::create([
"Line" => $Lines,
"CustomerRef" => [
"value" => $customerRef->Id
],
]);
$resultingInvoiceObj = $dataService->Add($invoiceObj);

Related

How to recursively sort associative array

I'd like to sort the following associative array:
$tree = [
"id" => 245974,
"children" => [
[
"id" => 111
],
[
"id" => 245982,
"children" => [
[
"id" => 246093,
"children" => [
[
"id" => 225892
],
[
"id" => 225893
],
[
"id" => 225902
]
]
]
]
]
]
];
Desired sort order after the "search value" of id => 225902:
[
"id" => 245974,
"children" => [
[
"id" => 245982, // <-- this is moved up
"children" => [
[
"id" => 246093,
"children" => [
[
"id" => 225902 // <-- this is moved up
],
[
"id" => 225892
],
[
"id" => 225893
]
]
]
]
],
[
"id" => 111
]
]
];
What I've tried:
<?php
$category_id = 225902;
function custom_sort(&$a, &$b) {
global $category_id;
if ($a['id'] === $category_id) {
return -1;
}
if ($b['id'] === $category_id) {
return 1;
}
if (array_key_exists('children', $a)) {
if (usort($a['children'], "custom_sort")) {
return -1;
}
}
if (array_key_exists('children', $b)) {
if (usort($b['children'], "custom_sort")) {
return 1;
}
}
return 0;
}
function reorder_tree($tree) {
usort($tree['children'], "custom_sort");
return $tree;
}
echo "<pre>";
var_dump(reorder_tree($tree));
echo "</pre>";
However, that returns:
[
"id" => 245974,
"children" => [
[
"id" => 245982, // <- this is moved up
"children" => [
[
"id" => 246093,
"children" => [
[
"id" => 225892
],
[
"id" => 225893
],
[
"id" => 225902 // <- this is *not* moved up
]
]
]
]
],
[
"id" => 111
],
]
];
How would I be able to also sort the children arrays?
Great attempt and very much on the right track. The problem with recursion in the comparator is that usort will not call the comparator function when the array length is 1, so whether or not you explore the whole tree is at the whim of usort. This will abandon id => 245982's branch of the tree.
The solution is to avoid recursing in the usort's comparator function directly. Rather, use a regular recursive function that calls usort as needed, namely, the current array or a child array contains the target id. I use a separate array to keep track of which elements should be moved forward, but you can break out of the loop and splice/unshift a single element to the front if you prefer.
We can also make $category_id a parameter to the function.
Here's one approach:
function reorder_tree_r(&$children, $target) {
$order = [];
$should_sort = false;
foreach ($children as $i => &$child) {
$order[$i] = false;
if (array_key_exists("children", $child) &&
reorder_tree_r($child["children"], $target) ||
$child["id"] === $target) {
$order[$i] = true;
$should_sort = true;
}
}
if ($should_sort) {
$priority = [];
$non_priority = [];
for ($i = 0; $i < count($children); $i++) {
if ($order[$i]) {
$priority[]= $children[$i];
}
else {
$non_priority[]= $children[$i];
}
}
$children = array_merge($priority, $non_priority);
}
return $should_sort;
}
function reorder_tree($tree, $target) {
if (!$tree || !array_key_exists("children", $tree)) {
return $tree;
}
reorder_tree_r($tree["children"], $target);
return $tree;
}
var_export(reorder_tree($tree, 225902));
Output:
array (
'id' => 245974,
'children' =>
array (
0 =>
array (
'id' => 245982,
'children' =>
array (
0 =>
array (
'id' => 246093,
'children' =>
array (
0 =>
array (
'id' => 225902,
),
1 =>
array (
'id' => 225892,
),
2 =>
array (
'id' => 225893,
),
),
),
),
),
1 =>
array (
'id' => 111,
),
),

php - How to insert a foreach loop inside a multidimensional array

How to insert a foreach loop inside a multidimensional array ?
I have a multidimensional array that I use to connect my website to Mailchimp. I have to check with a foreach loop the number of products that the user buys, and add these insiede a array call "lines".
This is at moment my json code, that after I will send to Mailchimp:
$json_data = '{
"id": "2'. $order->id .'",
"customer": {
"id": "71",
"email_address": "'.$order->email.'",
"opt_in_status": true,
"company": "'.$order->company_name.'",
"first_name": "'.$order->pad_firstname.'",
"last_name": "'.$order->pad_lastname.'",
"orders_count": 1,
"total_spent": 86
},
"checkout_url": "https://www.mywebsite.it/en/checkout/confirmation/",
"currency_code": "EUR",
"order_total": 86,
"lines"[{
'.$line_result.'
}]
}';
The $line_result is where I try to add the array of the products.
I know is wrong.
all the array inside the "lines" need be like this:
"lines":[
{
data product 1 ...
},
{
data product 2 ...
}
]
This is my foreach:
foreach ($order->pad_products as $product) {
$line_result['line'] = array(
"id" => "$order->id",
"product_id" => "$product->pad_product_id",
"product_title" => "$product->title",
"product_variant_id" => "$product->id",
"product_variant_title" => "$product->title",
"quantity" => "$product->pad_quantity",
"price" => "$product->prezzo",
);
};
what is the correct way to insert this data and create a multidimensional array like the one I need?
Thank you.
You just need to store all $line_result in global variable, and then, bind it to your json model :
$results = [];
foreach ($order->pad_products as $product) {
$results[] = array(
"id" => $order->id,
"product_id" => $product->pad_product_id,
"product_title" => $product->title,
"product_variant_id" => $product->id,
"product_variant_title" => $product->title,
"quantity" => $product->pad_quantity,
"price" => $product->prezzo,
);
};
$data = json_decode($json_data, true);
$data['lines'] = $results;
$json = json_encode($data);
EDIT : Script array to json
$lines = [];
foreach ($order->pad_products as $product) {
$lines[] = array(
"id" => $order->id,
"product_id" => $product->pad_product_id,
"product_title" => $product->title,
"product_variant_id" => $product->id,
"product_variant_title" => $product->title,
"quantity" => $product->pad_quantity,
"price" => $product->prezzo,
);
}
$data = [
'id' => '2'.$order->id,
'customer' => [
'id' => '71',
'email_address' => $order->email,
'opt_in_status' => true,
'company' => $order->company_name,
'first_name' => $order->pad_firstname,
'last_name' => $order->pad_lastname,
'orders_count' => 1,
'total_spent' => 86
],
'checkout_url' => 'https://www.mywebsite.it/en/checkout/confirmation',
'currency_code' => 'EUR',
'order_total' => 86,
'lines' => $lines
];
$jsonData = json_encode($data, JSON_UNESCAPED_UNICODE);
I want say thank you to #adrianRosi for the help and the input he gives me.
In the end I find my solution, that it's json_encode the array before add into $data in json format.
in this way:
$product_list = [];
foreach ($order->pad_products as $product) {
$product_list[] = array(
"id" => "$id",
"..." => "...",
);
};
$data_products['lines'] = $product_list;
$json_products = json_encode($data_products);
$json_products_edit = substr($json_products, 1, -1); // to delete the {}
$prezzo_totale = $order->pad_price_total;
$json_data = '{
...
...
'.$json_products_edit.'
}';

Group subarray data by one column and form comma-separated values from the secondary value in each group [duplicate]

This question already has answers here:
Group subarrays by one column, make comma-separated values from other column within groups
(2 answers)
Closed last month.
I have a two dimensional array which needs to be restructured. Rows must be grouped by date values, and within each group, the name values should be formed into a single comma-delimited string.
My input:
$missedFridgeLog = [
[
"date" => "01/01/18",
"name" => "Medicine"
],
[
"date" => "01/01/18",
"name" => "Drugs"
],
[
"date" => "02/01/18",
"name" => "Medicine"
],
[
"date" => "02/01/18",
"name" => "Drugs"
]
];
I have tried implementing a solution from Implode or join multidimentional array with comma, but it did not work as desired.
Desired output:
[
[
'date' => '01/01/18',
'name' => 'Medicine,Drugs',
],
[
'date' => '02/01/18',
'name' => 'Medicine,Drugs',
]
]
$missedFridgeLog = [
[
"date" => "01/01/18",
"name" => "Medicine"
],[
"date" => "01/01/18",
"name" => "Drugs"
]
[
"date" => "02/01/18",
"name" => "Medicine"
],
[
"date" => "02/01/18",
"name" => "Drugs"
]
];
$byDates = [];
foreach ($missedFridgeLog as $mfg) {
$byDates[$mfg['date']][] = $mfg['name'];
}
$res = [];
foreach ($byDates as $date => $name) {
$res[] = [
'name' => join(',',$name),
'date' => $date
];
}
var_dump($res);
You need to search key, value pair everytime you make a insert or update to result array. use this function() to search associate array. If match then update with additional name info else make a new insert to result array.
function filter_array($array){
///$array your previous array data
$result = array();
foreach($array["missedFridgeLog"] as $m){
$flag = true;
foreach($result as $k=>$r) {
if (is_in_array($r, "date", $m["date"]) == "yes") {
$result[$k]["name"] = $r["name"] . ',' . $m["name"];
$flag = false;
break;
}
}
if($flag==true){
$result[] = $m;
}
}
return array("missedFridgeLog"=>$result);
}
function is_in_array($array, $key, $key_value){
$within_array = 'no';
foreach( $array as $k=>$v ){
if( is_array($v) ){
$within_array = is_in_array($v, $key, $key_value);
if( $within_array == 'yes' ){
break;
}
} else {
if( $v == $key_value && $k == $key ){
$within_array = 'yes';
break;
}
}
}
return $within_array;
}
May be this is not the best way to do this, but it will help
$arr['missedFridgeLog'] = [
[
'date' => '01/01/18',
'name' => 'Medicine1'
],
[
'date' => '02/01/18',
'name' => 'New Medicine2'
],
[
'date' => '01/01/18',
'name' => 'Drugs1'
],
[
'date' => '02/01/18',
'name' => 'Medicine2'
],
[
'date' => '01/01/18',
'name' => 'New Drugs1'
],
[
'date' => '02/01/18',
'name' => 'Drugs2'
]
];
echo "<pre>";
$new_arr = array();
$date = array();
foreach ($arr['missedFridgeLog'] as $k => $a) {
if (in_array($a['date'], $date))
continue;
$new_arr[$k]['name'] = $a['name'];
$new_arr[$k]['date'] = "";
foreach ($arr[missedFridgeLog] as $key => $val) {
if ($key != $k) {
if ($a['date'] == $val['date']) {
$date[] = $new_arr[$k]['date'] = $a['date'];
$new_arr[$k]['name'] .= ", " . $val['name'];
}
}
}
if (empty($new_arr[$k]['date']))
unset($new_arr[$k]);
}
print_r($new_arr);
You can try below :-
Input array :-
$chkArray = [
'missedFridgeLog' => [
'0' => [
'date' => '01/01/18',
'name' => 'Medicine'
],
'1' => [
'date' => '01/01/18',
'name' => 'Drugs'
],
'2' => [
'date' => '02/01/18',
'name' => 'Medicine'
],
'3' => [
'date' => '02/01/18',
'name' => 'Drugs'
],
'4' => [
'date' => '02/01/18',
'name' => 'My Drugs'
]
]
];
$i = 0;
$finalarray = array();
foreach($chkArray['missedFridgeLog'] as $key=>$value) {
$checkExist = array_search($value['date'], array_column($finalarray, 'date'), true);
if($checkExist !== false) {
$finalarray[$checkExist]['name'] = $finalarray[$checkExist]['name'].','.$value['name'];
}
else {
$finalarray[$i]['date'] = $value['date'];
$finalarray[$i]['name'] = $value['name'];
$i++;
}
}
print_r($finalarray);
OutPut :-
Array
(
[0] => Array
(
[date] => 01/01/18
[name] => Medicine,Drugs
)
[1] => Array
(
[date] => 02/01/18
[name] => Medicine,Drugs,My Drugs
)
)
Do not use:
More than one loop,
Nested loops,
in_array(), or
array_search().
You only need one loop to apply temporary grouping keys. When a date/group is encountered after the first time, append its name value to the group's name value. When finished iterating, re-index the array.
Code: (Demo)
$result = [];
foreach ($missedFridgeLog as $row) {
if (!isset($result[$row['date']])) {
$result[$row['date']] = $row;
} else {
$result[$row['date']]['name'] .= ",{$row['name']}";
}
}
var_export(array_values($result));
Output:
array (
0 =>
array (
'date' => '01/01/18',
'name' => 'Medicine,Drugs',
),
1 =>
array (
'date' => '02/01/18',
'name' => 'Medicine,Drugs',
),
)

Elasticsearch partial bulk update

I have 6k of data to update in ElasticSearch. And I have to use PHP.
I search in the documentation and I have found this, Bulk Indexing but this is not keeping the previous data.
I have structure:
[
{
'name': 'Jonatahn',
'age' : 21
}
]
My code snippet to update:
$params =[
"index" => "customer",
"type" => "doc",
"body" => [
[
"index" => [
"_index" => "customer",
"_type" => "doc",
"_id" => "09310451939"
]
],
[
"name" => "Jonathan"
]
]
];
$client->bulk($params);
When I send ['name' => 'Jonathan'] I expect the name will be updated and keep the age, but the age gets deleted.
Sure, I still can update data-by-data but this will take a long time, is there any better way to do that?
My error was to using "index", but the correct way to do what I want, was "update".
The final code is:
$params =[
"index" => "customer",
"type" => "doc",
"body" => [
[
"update" => [
// ^^^^^^ Here I change from index to update
"_index" => "customer",
"_type" => "doc",
"_id" => "09310451939"
]
],
[
"doc" => [
"name" => "Jonathan"
]
]
]
];
$client->bulk($params);
Using the code above, my data keep previous data and just update the data I passing in params.
Response:
Array
(
[took] => 7
[timed_out] =>
[_shards] => Array
(
[total] => 5
[successful] => 5
[skipped] => 0
[failed] => 0
)
[hits] => Array
(
[total] => 1
[max_score] => 1
[hits] => Array
(
[0] => Array
(
[_index] => customer
[_type] => doc
[_id] => 09310451939
[_score] => 1
[_source] => Array
(
[name] => Jonathan
[age] => 23
)
)
)
)
)
As per docs, Bulk API possible actions are index, create, delete and update. update expects that the partial doc, upsert and script and its options are specified on the next line.
POST _bulk
{ "update" : {"_id" : "1", "_type" : "_doc", "_index" : "test"} }
{ "doc" : {"field2" : "value2"} }
Here is my final code.
<?php
require_once('../elasticsearch.php');
//initialize elasticsearch
$params = array();
$params['index'] = $elastcsearch_index;
$params['type'] = $elastcsearch_type;
///////////////////////////////////////////////////
//update seeders n leechers in elasticsearch
//get updated records
$get_updated_records = mysqli_query($conn, "SELECT content_id, seeders, leechers FROM content WHERE is_updated = '1' order by seeders DESC") ;
//create blank array
$results = array();
while($row = mysqli_fetch_assoc($get_updated_records)){
//put all results in array
$results[] = $row;
}
//from https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/_indexing_documents.html
$params = ['body' => []];
for($i = 0; $i < count($results); $i++) {
$params["body"][]= [
"update" => [
"_index" => $elastcsearch_index,
"_type" => $elastcsearch_type,
"_id" => $results[$i]['content_id']
]
];
$params["body"][]= [
"doc" => [
"seeders" => intval($results[$i]['seeders']) ,
"leechers" => intval($results[$i]['leechers']) ,
]
];
// Every 1000 documents stop and send the bulk request
if ($i % 1000 == 0) {
$responses = $elasticsearch->bulk($params);
// erase the old bulk request
$params = ['body' => []];
// unset the bulk response when you are done to save memory
unset($responses);
}
}
// Send the last batch if it exists
if (!empty($params['body'])) {
$responses = $elasticsearch->bulk($params);
}
$batch_elastics is array of result
i just unset this two value from row each time....
because I don't need this value in insert or update
unset($batch_row['type']);
unset($batch_row['diamonds_id']);
code start from here...
if(count($batch_elastics)){
// echo 'hi';die;
$params = array();
$params = ['body' => []];
$i=1;
foreach($batch_elastics as $batch_row){
$type=$batch_row['type'];
$id=$batch_row['diamonds_id'];
unset($batch_row['type']);
unset($batch_row['diamonds_id']);
if($type=="create"){
$params["body"][]= [
"create" => [
"_index" => 'diamonds',
"_id" => $id,
]
];
$params["body"][]= $batch_row;
if ($i % 1000 == 0) {
$responses = $client->bulk($params);
$params = ['body' => []];
unset($responses);
}
}
$i=$i+1;
}
// Send the last batch if it exists
if (!empty($params['body'])) {
$responses = $client->bulk($params);
}
$params = array();
$params = ['body' => []];
$i=1;
foreach($batch_elastics as $batch_row){
$type=$batch_row['type'];
$id=$batch_row['diamonds_id'];
unset($batch_row['type']);
unset($batch_row['diamonds_id']);
if($type=="update"){
$params["body"][]= [
"update" => [
"_index" => 'diamonds',
"_id" => $id,
]
];
$params["body"][]= [
"doc"=>$batch_row
];
if ($i % 1000 == 0) {
$responses = $client->bulk($params);
$params = ['body' => []];
unset($responses);
}
}
$i=$i+1;
}
// Send the last batch if it exists
if (!empty($params['body'])) {
$responses = $client->bulk($params);
}
}

Array Operations to add / remove entries from 1 to another

I have 2 sets of array:
Data:
$data = [
[
'company_code' => 'ABC',
'supplier_codes' => [
'S-2',
'S-3',
'S-5',
],
],
];
Source (from database):
$database = [
'company_code' => 'ABC',
'suppliers' => [
[
'code' => 'S-1',
],
[
'code' => 'S-2',
'reference' => '12345'
],
[
'code' => 'S-3',
],
[
'code' => 'S-4',
'reference' => 'some string',
]
],
];
What I need to achieve:
If a supplier code is missing in $data but exists in $database,
remove it from $database.
If a supplier code exists in $data but missing in $database, add it into $database
The output of the example here should be as follows:
$output = [
'company_code' => 'ABC',
'suppliers' => [
[
'code' => 'S-2',
'reference' => '12345'
],
[
'code' => 'S-3',
],
[
'code' => 'S-5',
]
],
];
I was thinking of removing the suppliers subarray, then reconstruct the structure based on the data from supplier_codes. But the problem is some of the entries in suppliers may have an optional field called reference.
Try this
<?php
$data = [
[
'company_code' => 'ABC',
'supplier_codes' => ['S-2','S-3','S-5'],
],
];
$database = [
'company_code' => 'ABC',
'suppliers' => [
[
'code' => 'S-1',
],
[
'code' => 'S-2',
'reference' => '12345'
],
[
'code' => 'S-3',
],
[
'code' => 'S-4',
'reference' => 'some string',
]
],
];
foreach($database['suppliers'] as $k=>$v){
foreach($data as $kd=>$vd){
$valueremove = false;
$removeIndex = '';
foreach($vd['supplier_codes'] as $key=>$val){
if($val == $v['code']){
$valueremove = false;
$removeIndex = '';
break;
} else {
$valueremove = true;
$removeIndex = $k;
}
}
if($valueremove == true){
unset($database['suppliers'][$removeIndex]);
} else {
$valueinsert = false;
foreach($data as $kd=>$vd){
foreach($vd['supplier_codes'] as $key=>$val){
foreach($database['suppliers'] as $kc=>$vc){
if($val == $vc['code']){
$valueinsert = false;
$insertIndex = '';
$insertVal = '';
break;
} else {
$valueinsert = true;
$insertIndex = count($database['suppliers'])+1;
$insertVal = $val;
}
}
if($valueinsert == true){
$database['suppliers'][$insertIndex] = array('code'=>$insertVal);
}
}
}
}
}
}
echo "<PRE>"; print_r($database);
I end up solving my problem this way:
$result = $database;
$result['suppliers'] = [];
foreach($data as $tag) {
foreach($tag['supplier_codes'] as $code) {
$found = false;
foreach($database['suppliers'] as $supplier) {
if($supplier['code'] === $code) {
$result['suppliers'][] = $supplier;
$found = true;
}
}
if(!$found) {
$result['suppliers'][] = ['code' => $code];
}
}
}
Output of print_r($result);:
Array
(
[company_code] => ABC
[suppliers] => Array
(
[0] => Array
(
[code] => S-2
[reference] => 12345
)
[1] => Array
(
[code] => S-3
)
[2] => Array
(
[code] => S-5
)
)
)

Categories