Files
crm.twinpol.com/modules/EcmInventorys/ajax.php
2025-05-12 15:44:39 +00:00

647 lines
22 KiB
PHP
Executable File

<?php
if(!defined('sugarEntry') || !sugarEntry) die('-1');
if (!$_POST['job'] || $_POST['job']=='') die ('-1');
switch ($_POST['job']) {
case 'getParentInfo': getParentInfo($_POST['id'], $_POST['type']); break;
case 'generateNumber': generateNumber($_POST['stock'],$_POST['date']); break;
case 'searchProducts': searchProducts($_POST['searchKey'], $_POST['searchCategory'], $_POST['searchStock'], $_POST['searchSort'], $_POST['searchStockId']); break;
case 'getProduct': getProduct($_POST['id'], $_POST['stockId']); break;
case 'getItems': getItems($_POST['record']); break;
case 'getCategoriesList': getCategoriesList(); break;
case 'getTranslation': getTranslation($_POST['product_id'], $_POST['language'], $_REQUEST['unit_id']); break;
case 'getPricesInfo': getPricesInfo($_POST['product_id'], $_POST['pricebook_id'], $_POST['account_id']); break;
case 'getStockArray' : getStockArray($_POST['product_id']); break;
case 'getPurchaseArray' : getPurchaseArray($_POST['product_id']); break;
case 'getStockState' : getStockState($_POST['id'], $_POST['stockId']); break;
case 'getComponents' : getComponents($_POST['product_id']); break;
case 'AutocompliteProductCode' : AutocompliteProductCode($_POST['code'], $_POST['stock_id']); break;
case 'AutocompliteProductName' : AutocompliteProductName($_POST['name'], $_POST['stock_id']); break;
case 'getProductListById' : getProductListById($_POST['id_list'], $_POST['stock_id']); break;
case 'add_from_stock' : add_from_stock($_POST['stock_id'],$_POST['add_options'],$_POST['rewrite_state']); break;
case 'getPositionList' : getPositionList($_POST['ecminventory_id']); break;
case 'savePositionList' : savePositionList($_POST['ecminventory_id'], $_POST['data'],$_POST['deleteOld']); break;
case 'create_ks_documents' : create_ks_documents($_POST['ecminventory_id'], $_POST['ks_date_document']); break;
case 'createEcmInventory' : createEcmInventory($_POST['name'], $_POST['document_no'], $_POST['stock_id'], $_POST['register_date'], $_POST['ecmproductstockindex_id'], $_POST['pdf_text']); break;
}
function create_ks_documents($id_dokumentu, $ks_date_document){
include_once('modules/EcmStockDocCorrects/EcmStockDocCorrect.php');
global $db, $current_user;
$EcmInventory = new EcmInventory();
$EcmInventory->retrieve($id_dokumentu);
$tmp = $EcmInventory->create_ks_documents($ks_date_document);
print json_encode($tmp);
}
function createEcmInventory($name, $document_no, $stock_id, $register_date, $ecmproductstockindex_id, $pdf_text){
$EcmInventory = new EcmInventory();
$EcmInventory->name = $name;
$EcmInventory->document_no = $document_no;
$EcmInventory->stock_id = $stock_id;
$EcmInventory->register_date = $register_date;
$EcmInventory->ecmproductstockindex_id = $ecmproductstockindex_id;
$EcmInventory->pdf_text = $pdf_text;
$id = $EcmInventory->save();
print json_encode($id);
}
function savePositionList($ecminventory_id, $data, $delte_old_values){
$db = $GLOBALS ['db'];
if($ecminventory_id==''){
}else{
if($delte_old_values == 'true'){
$del_query = "DELETE FROM ecminventoryitems WHERE ecminventory_id = '" . $ecminventory_id ."'";
$db->query($del_query);
}
global $current_user, $app_list_strings;
foreach ($data as $key => $value) {
if ($value ['ecmproduct_id'] == '') {
continue;
}
$item_id = create_guid();
// $_POST ['price'] = unformat_number( $_POST ['price']);
// $_POST ['quantity'] = unformat_number( $_POST ['quantity']);
$arr = array (
'id' => $item_id,
'date_entered' => 'NOW()',
'date_modified' => 'NOW()',
'modified_user_id' => $current_user->id,
'assigned_user_id' => $current_user->id,
'created_by' => $current_user->id,
'deleted' => '0',
'position' => $key,
strtolower ('EcmInventory') . '_id' => $ecminventory_id,
'ecmproduct_id' => $value ['ecmproduct_id'],
'position' => $value,
'code' => $value['code'],
'name' => $value ['name'],
'price'=> $value ['price'],
'total'=> ROUND($value ['price'] * $value ['quantity'],2),
'quantity' => $value ['quantity'],
'dd_unit_id' => $value ['dd_unit_id'],
'dd_unit_name' => $app_list_strings['ecmproducts_unit_dom'][$value ['dd_unit_id']],
'ecmproductcategory_id' => $value ['ecmproductcategory_id'],
//'is_consignment' => $p['product_is_consignment'],
);
$keys = array_keys($arr);
$values = array_values($arr);
$inster_query = 'INSERT INTO ecminventoryitems (' . implode(",",$keys) .') VALUES ("' . implode('","',$values) . '");';
$inster_query = str_replace ( '"NOW()"', 'NOW()', $inster_query );
$db->query ($inster_query);
}
}
//print json_encode($inster_query);
}
function getPositionList($ecminventory_id){
$db = $GLOBALS ['db'];
$q = 'SELECT ecmproduct_id, quantity,stock_state FROM ecminventoryitems WHERE ecminventory_id ="' . $ecminventory_id . '";';
$rs = $db->query($q);
$quantity_array = array();
$id_array = array();
$states=array();
while ($row = $db->fetchByAssoc($rs)) {
$id_array[] = $row['ecmproduct_id'];
$quantity_array[$row['ecmproduct_id']] = $row['quantity'];
$states[$row['ecmproduct_id']]=$row['stock_state'];
}
$inv = new EcmInventory();
$inv->retrieve($ecminventory_id);
if(count($id_array)==0){
$result = null;
}else{
$query_stock_id = 'SELECT stock_id FROM ecminventorys WHERE id ="' . $ecminventory_id . '";';
$result_stock_id = $db->query($query_stock_id);
$stock_id = $row = $db->fetchByAssoc($result_stock_id);
$tmp = getProductListById($id_array, $stock_id['stock_id'] ,false ,true);
foreach($tmp as $k => $v){
$tmp[$k]['quantity'] = $quantity_array[$v['ecmproduct_id']];
$tmp[$k]['difference'] = $tmp[$k]['quantity'] - $tmp[$k]['stock_state'];
if($inv->status=='implemented'){
$tmp[$k]['stock_state']=$states[$v['ecmproduct_id']];
$tmp[$k]['difference'] = $tmp[$k]['quantity'] - $states[$v['ecmproduct_id']];
}
}
$json = json_encode($tmp);
print $json;
}
}
function add_from_stock($stock_id, $add_options, $rewrite_state){
$db = $GLOBALS ['db'];
if($add_options=='all_positions'){
$q = 'SELECT product_id FROM ecmstockoperations WHERE stock_id ="' . $stock_id . '" AND deleted = 0 group by product_id;';
$id_array = array();
$rs = $db->query($q);
while ($row = $db->fetchByAssoc($rs)) {
$id_array[] = $row['product_id'];
}
getProductListById($id_array,$stock_id,$rewrite_state);
}else if($add_options=='not_eq_zero'){
$qplus = 'SELECT
product_id, SUM(quantity) as quantity
FROM
ecmstockoperations
WHERE
stock_id ="' . $stock_id . '" AND type=0 AND deleted = 0
GROUP BY
product_id;';
$qminus = 'SELECT
product_id, SUM(quantity) as quantity
FROM
ecmstockoperations
WHERE
stock_id ="' . $stock_id . '" AND type=1 AND deleted = 0
GROUP BY
product_id;';
$product_array = array();
$id_array = array();
$rs = $db->query($qplus);
while ($row = $db->fetchByAssoc($rs)) {
$product_array[$row['product_id']] = $row['quantity'];
}
$rs = $db->query($qminus);
while ($row = $db->fetchByAssoc($rs)) {
$product_array[$row['product_id']] -= $row['quantity'];
}
foreach($product_array as $key => $value){
if($value>0){
$id_array[] = $key;
}
}
getProductListById($id_array,$stock_id, $rewrite_state);
}else if($add_options=='eq_zero'){
$qplus = 'SELECT
product_id, SUM(quantity) as quantity
FROM
ecmstockoperations
WHERE
stock_id ="' . $stock_id . '" AND type=0 AND deleted = 0
GROUP BY
product_id;';
$qminus = 'SELECT
product_id, SUM(quantity) as quantity
FROM
ecmstockoperations
WHERE
stock_id ="' . $stock_id . '" AND type=1 AND deleted = 0
GROUP BY
product_id;';
$product_array = array();
$id_array = array();
$rs = $db->query($qplus);
while ($row = $db->fetchByAssoc($rs)) {
$product_array[$row['product_id']] = $row['quantity'];
}
$rs = $db->query($qminus);
while ($row = $db->fetchByAssoc($rs)) {
$product_array[$row['product_id']] -= $row['quantity'];
}
foreach($product_array as $key => $value){
if($value<=0){
$id_array[] = $key;
}
}
getProductListById($id_array,$stock_id,$rewrite_state);
}
}
function getProductListById($id_list, $stock_id, $rewrite_state = false, $return_array = false){
global $current_language;
$app_list_strings = return_app_list_strings_language($current_language);
$db = $GLOBALS ['db'];
$q = '
SELECT
product.id AS id,
product.name AS name,
product.code AS code,
product.product_category_id AS product_category_id,
product_category.name AS product_category_name,
product.unit_id AS dd_unit_id
FROM
ecmproducts AS product
LEFT JOIN
ecmproductcategories AS product_category ON product.product_category_id = product_category.id
WHERE
product.deleted = 0
AND product.id IN ("' . implode('","',$id_list) .'")
ORDER BY product.code, product.name';
$result = array();
$rs = $db->query($q);
while ($row = $db->fetchByAssoc($rs)) {
$a_json_row ['ecmproduct_id'] = $row ['id'];
$a_json_row ['name'] = $row ['name'];
$a_json_row ['code'] = $row ['code'];
$a_json_row ['product_category_id'] = $row ['product_category_id'];
$a_json_row ['product_category_name'] = $row ['product_category_name'];
$a_json_row ['dd_unit_id'] = $row ['dd_unit_id'];
$a_json_row ['dd_unit_precision'] = $app_list_strings['ecmproducts_unit_dom_precision'][$row ['dd_unit_id']];
$a_json_row ['dd_unit_name'] = $app_list_strings['ecmproducts_unit_dom'][$row ['dd_unit_id']];
//Cena zakupu
$price_query = '
SELECT
price
FROM
ecmstockdocins
LEFT JOIN
ecmstockdocinitems ON ecmstockdocins.id = ecmstockdocinitems.ecmstockdocin_id
WHERE ecmstockdocinitems.ecmproduct_id = "' . $row ['id'] . '"
AND ecmstockdocins.deleted =0
ORDER BY ecmstockdocins.register_date DESC, ecmstockdocins.document_no DESC, ecmstockdocinitems.position DESC
LIMIT 1;';
$price_result = $db->query($price_query);
if($price_result->num_rows > 0){
$price_row = $db->fetchByAssoc($price_result);
$a_json_row ['price'] = $price_row['price'];
}else{
$a_json_row ['price'] = 0;
}
//Stan magazynowy
$a_json_row['stock_state'] = EcmStockOperation::getStock($row['id'], $stock_id);
if($rewrite_state=="true"){
$a_json_row['quantity'] = $a_json_row['stock_state'];
}else{
$a_json_row['quantity'] = 0;
}
$result [] = $a_json_row;
}
if(!$return_array){
$json = json_encode($result);
print $json;
}else{
return $result;
}
}
function AutocompliteProductCode($code,$stock_id){
global $current_language;
$app_list_strings = return_app_list_strings_language($current_language);
$db = $GLOBALS ['db'];
$result = array();
$q = '
SELECT
product.id AS id,
product.name AS name,
product.code AS code,
product.product_category_id AS product_category_id,
product_category.name AS product_category_name,
product.unit_id AS dd_unit_id
FROM
ecmproducts AS product
LEFT JOIN
ecmproductcategories AS product_category ON product.product_category_id = product_category.id
WHERE
product.deleted = 0
AND product.code LIKE "%' . $code .'%"
ORDER BY product.code, product.name
LIMIT 10;';
$rs = $db->query($q);
if ($rs->num_rows > 0) {
while ($row = $db->fetchByAssoc($rs)) {
$a_json_row ['id'] = $row ['id'];
$a_json_row ['name'] = $row ['name'];
$a_json_row ['code'] = $row ['code'];
$a_json_row ['product_category_id'] = $row ['product_category_id'];
$a_json_row ['product_category_name'] = $row ['product_category_name'];
$a_json_row ['dd_unit_id'] = $row ['dd_unit_id'];
$a_json_row ['dd_unit_precision'] = $app_list_strings['ecmproducts_unit_dom_precision'][$row ['dd_unit_id']];
$a_json_row ['dd_unit_name'] = $app_list_strings['ecmproducts_unit_dom'][$row ['dd_unit_id']];
$a_json_row ['label'] = "Kategoria: <span style='color: blue;'>" . $a_json_row ['product_category_name'] . "</span><br>Indeks: <span style='color: blue;'>" . $row ['code'] . "</span><br>Nazwa: <span style='color: blue;'>" . $row ['name'] . '</span>';
$a_json_row ['value'] = $row ['code'];
//Cena zakupu
$price_query = '
SELECT
price
FROM
ecmstockdocins
LEFT JOIN
ecmstockdocinitems ON ecmstockdocins.id = ecmstockdocinitems.ecmstockdocin_id
WHERE ecmstockdocinitems.ecmproduct_id = "' . $row ['id'] . '"
ORDER BY ecmstockdocins.register_date DESC
LIMIT 1;';
$price_result = $db->query($price_query);
if($price_result->num_rows > 0){
$price_row = $db->fetchByAssoc($price_result);
$a_json_row ['price'] = $price_row['price'];
}else{
$a_json_row ['price'] = 0;
}
//Stan magazynowy
$a_json_row['stock_state'] = EcmStockOperation::getStock($row['id'], $stock_id);
$result [] = $a_json_row;
}
} else {
$a_json_row ['id'] = '';
$a_json_row ['name'] = '';
$a_json_row ['code'] = '';
$a_json_row ['product_category_id'] = '';
$a_json_row ['product_category_name'] = '';
$a_json_row ['dd_unit_id'] = '';
$a_json_row ['dd_unit_name'] = '';
$a_json_row ['price'] = '';
$a_json_row ['label'] = "<span style='color: red;'>Brak czynności o szukanej nazwie</span>";
$a_json_row ['value'] = '';
$result [] = $a_json_row;
}
$json = json_encode($result);
print $json;
}
function AutocompliteProductName($name,$stock_id){
global $current_language;
$app_list_strings = return_app_list_strings_language($current_language);
$db = $GLOBALS ['db'];
$result = array();
$q = '
SELECT
product.id AS id,
product.name AS name,
product.code AS code,
product.product_category_id AS product_category_id,
product_category.name AS product_category_name,
product.unit_id AS dd_unit_id
FROM
ecmproducts AS product
LEFT JOIN
ecmproductcategories AS product_category ON product.product_category_id = product_category.id
WHERE
product.deleted = 0
AND product.name LIKE "%' . $name .'%"
ORDER BY product.name, product.code
LIMIT 10;';
$rs = $db->query($q);
if ($rs->num_rows > 0) {
while ($row = $db->fetchByAssoc($rs)) {
$a_json_row ['id'] = $row ['id'];
$a_json_row ['name'] = $row ['name'];
$a_json_row ['code'] = $row ['code'];
$a_json_row ['product_category_id'] = $row ['product_category_id'];
$a_json_row ['product_category_name'] = $row ['product_category_name'];
$a_json_row ['dd_unit_id'] = $row ['dd_unit_id'];
$a_json_row ['dd_unit_name'] = $app_list_strings['ecmproducts_unit_dom'][$row ['dd_unit_id']];
$a_json_row ['dd_unit_precision'] = $app_list_strings['ecmproducts_unit_dom_precision'][$row ['dd_unit_id']];
$a_json_row ['label'] = "Kategoria: <span style='color: blue;'>" . $a_json_row ['product_category_name'] . "</span><br>Indeks: <span style='color: blue;'>" . $row ['code'] . "</span><br>Nazwa: <span style='color: blue;'>" . $row ['name'] . '</span>';
$a_json_row ['value'] = $row ['name'];
//Cena zakupu
$price_query = '
SELECT
price
FROM
ecmstockdocins
LEFT JOIN
ecmstockdocinitems ON ecmstockdocins.id = ecmstockdocinitems.ecmstockdocin_id
WHERE ecmstockdocinitems.ecmproduct_id = "' . $row ['id'] . '"
ORDER BY ecmstockdocins.register_date DESC
LIMIT 1;';
$price_result = $db->query($price_query);
if($price_result->num_rows > 0){
$price_row = $db->fetchByAssoc($price_result);
$a_json_row ['price'] = $price_row['price'];
}else{
$a_json_row ['price'] = 0;
}
//Stan magazynowy
$a_json_row['stock_state'] = EcmStockOperation::getStock($row['id'], $stock_id);
$result [] = $a_json_row;
}
} else {
$a_json_row ['id'] = '';
$a_json_row ['name'] = '';
$a_json_row ['code'] = '';
$a_json_row ['product_category_id'] = '';
$a_json_row ['product_category_name'] = '';
$a_json_row ['dd_unit_id'] = '';
$a_json_row ['dd_unit_name'] = '';
$a_json_row ['price'] = '';
$a_json_row ['label'] = "<span style='color: red;'>Brak czynności o szukanej nazwie</span>";
$a_json_row ['value'] = '';
$result [] = $a_json_row;
}
$json = json_encode($result);
print $json;
}
function generateNumber($mag,$date) {
$data = array();
$data['number'] = EcmInventory::generateNumber($date);
$data['document_no'] = EcmInventory::generateDocNumberStock($mag,$date);
echo json_encode($data);
unset($data);
return;
}
function searchProducts($searchKey, $searchCategory, $searchStock, $searchSort, $searchStockId) {
$db = $GLOBALS['db'];
$q = "SELECT id, code, name FROM ecmproducts WHERE
(UPPER(code) LIKE '%$searchKey%' OR
UPPER(name) LIKE '%$searchKey%')
AND deleted='0' ";
if ($searchCategory && $searchCategory!="")
$q.="AND product_category_id='$searchCategory' ";
if ($searchSort=='1')
$q.="ORDER BY code";
else if ($searchSort=='2')
$q.="ORDER BY code DESC";
else if ($searchSort=='3')
$q.="ORDER BY name";
else if ($searchSort=='4')
$q.="ORDER BY name DESC";
$q.=" LIMIT 0,50";
$res = $db->query($q);
$result = array();
$stock_id = $searchStockId;
while ($row = $db->fetchByAssoc($res)) {
$tmp = array();
$tmp['id'] = $row['id'];
$tmp['name'] = $row['name'];
$tmp['code'] = $row['code'];
//get stock if necessary
if ($searchStock!='1') {
$tmp['stock_state'] = EcmStockOperation::getStock($row['id'], $stock_id);
}
if ($searchStock=='3' && $tmp['stock_state']==0) continue; //don't show null stock
$result[] = $tmp;
}
echo json_encode($result);
return;
}
function getProduct($id, $stockId) {
$db = $GLOBALS['db'];
$p = $db->fetchByAssoc($db->query("SELECT p.is_consignment, p.id, p.code, p.name, p.unit_id, p.product_category_id FROM ecmproducts as p INNER JOIN ecmvats as v ON v.id=p.vat_id WHERE p.id='$id'"));
global $app_list_strings;
$p['unit_name'] = $app_list_strings['ecmproducts_unit_dom'][$p['unit_id']];
$p['stock_state'] = $tmp['stock_state'] = EcmStockOperation::getStock($id, $stockId);
$p['unit_precision'] = $app_list_strings['ecmproducts_unit_dom_precision'][$p['unit_id']];
echo json_encode($p);
return;
}
function getItems($record) {
$mm = new EcmInventory();
$mm->retrieve($record);
$pl = $mm->getPositionList(true);
unset($mm);
echo json_encode($pl);
return;
}
function getCategoriesList() {
$db = $GLOBALS['db'];
$res = $db->query("SELECT id, name FROM ecmproductcategories WHERE deleted='0'");
$result = array();
while ($row = $db->fetchByAssoc($res)) {
$tmp = array();
$tmp['id'] = $row['id'];
$tmp['name'] = $row['name'];
$result[] = $tmp;
}
echo json_encode($result);
return;
}
function getTranslation($product_id, $language, $unit_id) {
$db = $GLOBALS['db'];
$result = array();
if ($language=='en_us') {
$r = $db->fetchByAssoc($db->query("SELECT short_description FROM ecmproduct_language WHERE ecmproduct_id='$product_id' AND language='en'"));
$result['name'] = htmlspecialchars_decode($r['short_description']);
} else if ($language=='pl_pl') {
$p = new EcmProduct();
$p->retrieve($product_id);
$result['name'] = htmlspecialchars_decode($p->name);
unset($p);
}
$lists = return_app_list_strings_language($language);
$result['unit_name'] = $lists['ecmproducts_unit_dom'][$unit_id];
unset($lists);
echo json_encode($result);
return;
}
function getPricesInfo($product_id, $pricebook_id, $account_id) {
$db = $GLOBALS['db'];
$result = array();
if ($pricebook_id && $pricebook_id!='') {
//try get price from pricebook
$res = $db->fetchByAssoc($db->query("SELECT price FROM ecmpricebooks_ecmproducts WHERE ecmpricebook_id='$pricebook_id' AND ecmproduct_id='$product_id' AND deleted='0'"));
if ($res['price'] && $res['price']!='' && $res['price']!=0) {
$tmp = array();
$tmp['name'] = 'pricebook';
$tmp['price'] = $res['price'];
$result[] = $tmp;
}
}
//get from ecmprices
$res = $db->query("SELECT p.name, pp.price FROM ecmprices_ecmproducts AS pp
INNER JOIN ecmprices AS p
ON p.id=pp.ecmprice_id
WHERE
pp.ecmproduct_id='$product_id'
AND pp.price!=0");
while ($row = $db->fetchByAssoc($res)) {
$tmp = array();
$tmp['name'] = $row['name'];
$tmp['price'] = $row['price'];
$tmp['module']='EcmPrices';
$tmp['visible']='1';
$result[] = $tmp;
}
//get last invoice price
if ($account_id && $account_id!='') {
$res = $db->fetchByAssoc($db->query("SELECT ii.subprice, i.id, i.document_no FROM ecminvoiceoutitems AS ii
INNER JOIN ecminvoiceouts AS i
ON ii.ecminvoiceout_id=i.id
WHERE ii.ecmproduct_id='$product_id'
AND i.parent_id='$account_id'
AND ii.deleted='0'
AND i.deleted='0'
AND i.canceled='0'
ORDER BY i.register_date DESC
LIMIT 0,1"));
if ($res && $res['subprice']!='') {
$tmp = array();
$tmp['name'] = '<a href="index.php?module=EcmInvoiceOuts&action=DetailView&record='.$res['id'].'">'.$res['document_no'].'</a>';
$tmp['price'] = $res['subprice'];
$tmp['module']='EcmInvoiceOuts';
$tmp['visible']='1';
$result[] = $tmp;
}
}
//get from ecmstockdocins
$res = $db->query("SELECT ii.price, i.id, i.document_no,ii.quantity,i.register_date FROM ecmstockdocinitems AS ii
INNER JOIN ecmstockdocins AS i
ON ii.ecmstockdocin_id=i.id
WHERE ii.ecmproduct_id='$product_id'
AND ii.deleted='0'
AND i.deleted='0'
ORDER BY i.register_date DESC");
while ($row = $db->fetchByAssoc($res)) {
$tmp = array();
$tmp['name'] = '<a href="index.php?module=EcmStockDocIns&action=DetailView&record='.$row['id'].'">'.$row['document_no'].'</a>';
$tmp['price'] = $row['price'];
$tmp['module']='EcmStockDocIns';
$tmp['quantity']=$row['quantity'];
$tmp['register_date']=$row['register_date'];
$tmp['visible']='0';
$result[] = $tmp;
}
echo json_encode($result);
return;
}
function getStockArray($product_id) {
$o = new EcmStockOperation();
echo json_encode($o->getStockArray($product_id));
unset($o);
return;
}
function getPurchaseArray($product_id) {
$o = new EcmStockOperation();
echo json_encode($o->getPurchaseArray($product_id));
unset($o);
return;
}
function getStockState($id, $stock_id) {
echo EcmStockOperation::getStock($id, $stock_id);
return;
}
function getComponents($product_id) {
$p = new EcmProduct();
$p->retrieve($product_id);
echo json_encode($p->getPositionList(true));
return;
}