$INFO['erp_url'] = 'http://crm.beta/odata/';
$INFO['erp_service'] = 'http://crm.beta/service/';
$INFO['erp_user'] = 'admin';
$INFO['erp_password'] = 'password';
class Data1c extends Singleton implements Instantiatable
{
private static $retry = 0;
public static function Units()
{
$url = 'Catalog_КлассификаторЕдиницИзмерения?$format=application/json';
$url .= '&$select=Ref_Key, Description, НаименованиеПолное';
$data = self::_getJsonData($url);
$struct = [];
foreach ($data['value'] as $row)
{
$new = [];
$new['id'] = $row['Ref_Key'];
$new['name'] = $row['НаименованиеПолное'] . " ({$row['Description']})";
$new['desc'] = $row['Description'];
if ($row['НаименованиеПолное']) {
$struct[] = $new;
}
}
return $struct;
}
public static function finish()
{
if (Info::me()->vars['erp_sessions']) {
self::RequestODATA("",null,"GET","finish");
}
}
private static function _getJsonData($url,$service="odata")
{
if ($service == "hs") {
return json_decode(self::RequestSERVICE($url),true);
} else {
return json_decode(self::RequestODATA($url),true);
}
}
public static function RequestODATA($url, $content=null, $method="GET", $state = "start")
{
$url = Info::me()->vars['erp_url'] . self::myUrlEncode($url);
return self::Request($url, $content, $method, $state);
}
public static function RequestSERVICE($url, $content=null, $method="GET", $state = "start")
{
$url = Info::me()->vars['erp_service'] . self::myUrlEncode($url);
return self::Request($url, $content, $method, $state);
}
// функция обращения к сайту
private static function Request($url, $content, $method, $state)
{
//FIXME: вывод эксепшина при получении нулевой длины
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERAGENT, 'CRM Internal');
curl_setopt($ch, CURLOPT_HTTPGET, true);
if ($content !== null) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $content );
}
switch ($method) {
case "POST":
curl_setopt($ch, CURLOPT_POST, true);
break;
case "PATCH":
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PATCH');
break;
case "PUT":
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT');
break;
case "GET":
curl_setopt($ch, CURLOPT_POST, false);
break;
default:
throw new Exception("Unknown method");
break;
}
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, Info::me()->vars['erp_user'].":".Info::me()->vars['erp_password']);
if (Info::me()->vars['erp_sessions']) {
switch ($state) {
case "start":
self::$retry++;
if (self::$retry > 3) {
throw new Exception("Too many connection retiries. Can't initiate session");
}
if ($_SERVER['IBSession'] != null) {
curl_setopt($ch, CURLOPT_COOKIE, "ibsession=".$_SERVER['IBSession']);
// echo("Reusing session: ".$_SERVER['IBSession']."\n");
} else {
curl_setopt($ch, CURLOPT_HTTPHEADER, array('IBSession: start'));
// echo("Starting session\n");
}
$response = curl_exec($ch);
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($response, 0, $header_size);
$body = substr($response, $header_size);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
// echo("HTTP code: $httpcode\n\n");
if ($httpcode == 0) { throw new Exception("No connection"); }
if ($httpcode == 406) { throw new Exception("406 Not Acceptable. ERP can't initiate new session"); }
if ($httpcode == 400 ) {$_SERVER['IBSession'] = null; return self::Request($url,$content,$method,"start"); }
preg_match_all('/^Set-Cookie:\s*([^;]*)/mi', $header, $matches);
$cookies = array();
foreach($matches[1] as $item) {
parse_str($item, $cookie);
$cookies = array_merge($cookies, $cookie);
}
if ($cookies['ibsession']) {
// echo("Cookie: ".$cookies['ibsession']."\n");
$_SERVER['IBSession'] = $cookies['ibsession'];
}
curl_close($ch);
self::$retry = 0;
return ($httpcode>=200 && $httpcode<300) ? $body : false;
break;
case "finish":
if ($_SERVER['IBSession'] != null) {
curl_setopt($ch, CURLOPT_COOKIE, "ibsession=".$_SERVER['IBSession']);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('IBSession: finish'));
curl_exec($ch);
curl_close($ch);
$_SERVER['IBSession'] = null;
}
break;
default:
throw new Exception("Non standart IBSession header");
break;
}
} else {
$response = curl_exec($ch);
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($response, 0, $header_size);
$body = substr($response, $header_size);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($httpcode == 0) { throw new Exception("No connection"); }
curl_close($ch);
return ($httpcode>=200 && $httpcode<300) ? $body : false;
}
}
private static function myUrlEncode($string) {
$entities = array('%20', '%27');
$replacements = array(' ', "'");
$string = str_replace($replacements, $entities, $string);
return $string;
}
}
function InvoiceCreate()
{
$('invoice_create').disabled = true;
$('invoice_create').setAttribute("style","-webkit-filter:grayscale(100%);");
$('InvoiceDisabler').style.display = "";
if (!$('rate').value || $('rate').value == 0) {smoke.alert('Укажите курс'); return; }
if (!$('Организация_Key').value) {smoke.alert('Укажите органиазацию'); return; }
if (!$('КодНазначенияПлатежа').value) {smoke.alert('Укажите КНП'); return; }
if (!$('СтруктурнаяЕдиница').value) {smoke.alert('Укажите банковский счет'); return; }
if (!$('Контрагент_Key').value) {smoke.alert('Укажите контрагента'); return; }
if (!$('Склад_Key').value) {smoke.alert('Укажите склад'); return; }
if (!$('ДоговорКонтрагента_Key').value) {smoke.alert('Укажите договор с контрагентом'); return; }
if (!$('Автор_Key').value || $('Автор_Key').value == 0) {smoke.alert('Укажите ответственное лицо'); return; }
var data = {
'Организация_Key' : $('Организация_Key').value,
'КодНазначенияПлатежа' : $('КодНазначенияПлатежа').value,
'СтруктурнаяЕдиница' : $('СтруктурнаяЕдиница').value,
'Склад_Key' : $('Склад_Key').value,
'Контрагент_Key' : $('Контрагент_Key').value,
'ДоговорКонтрагента_Key' : $('ДоговорКонтрагента_Key').value,
'Комментарий' : $('Комментарий').value,
'Автор_Key' : $('Автор_Key').value,
'НомерЗаказа' : "Заказ №" + DATA[0].order_number,
'rows' : []
};
var interrelation = new Array();
for (var i=0; i < $('goods').children.length; i++){
var tr = $('goods').children[i];
var elem = {
'Номенклатура_Key' : '',
'СтавкаНДС_Key' : '',
'ЕдиницаИзмерения_Key' : '',
'Количество' : '',
'Цена' : '',
'Сумма' : '',
'СуммаНДС' : '',
};
var inter = {
invoice_uuid : '',
item_uuid : '',
quantity : '',
price : '',
order_data_id : ''
};
for (var l=0; l < tr.cells.length; l++) {
var td = tr.cells[l];
if (td.hasAttribute('data-element')) {
for (var h=0; h < td.childNodes.length; h++) {
if (td.childNodes[h].nodeName == "INPUT" && td.childNodes[h].name == "good") {
if (!td.childNodes[h].value || td.childNodes[h].value == '') {
smoke.alert('Не указан товар из списка'); return;
}
elem.Номенклатура_Key = td.childNodes[h].value;
var agood = FindGood(elem.Номенклатура_Key);
elem.СтавкаНДС_Key = agood.СтавкаНДС_Key;
elem.ЕдиницаИзмерения_Key = agood.БазоваяЕдиницаИзмерения_Key;
inter.item_uuid = elem.Номенклатура_Key;
inter.order_data_id = td.childNodes[h].getAttribute('data-order_data_id');
}
}
}
if (td.hasAttribute('data-quantity')) {
elem.Количество = parseInt(td.getAttribute('data-quantity'));
}
if (td.hasAttribute('data-price')) {
for (var k=0; k < td.childNodes.length; k++) {
if (td.childNodes[k].nodeName == "INPUT" && td.childNodes[k].name == "price") {
elem.Цена = parseFloat(td.childNodes[k].value);
}
}
}
}
elem.Сумма = elem.Цена * elem.Количество;
elem.СуммаНДС = FormatNumberBy3(roundNumber((elem.Сумма / 112 * 12),2),'.', '', true);
data.rows.push(elem);
inter.quantity = elem.Количество;
inter.price = elem.Цена;
interrelation.push(inter);
}
new (Ajax.Request)
(
"/",
{
method: "POST",
parameters: {
'Motion' : '<?=Motion::ADD_INVOICE?>',
'data' : Base64.encode(Object.toJSON(data)),
'interrelation': Base64.encode(Object.toJSON(interrelation)),
'order_id' : $('order_id').value
},
encoding: 'UTF-8',
onComplete: function (a) {
resp = a.responseJSON;
if (resp.result == 'success') {
updateInvoiceTable(resp);
} else {
alert('Обновление номера счета в заказе не выполнено. Обратитесь к разработчику.');
}
},
onFailure: function (a) {alert('Во время работы произошла ошибка, пожалуйста сообщите администратору!');}
}
);
}
protected function addInvoice()
{
$db = $this->db;
$site = $this->site;
$data = json_decode(base64_decode($site->getInputVar('data')),true);
$interrelation = json_decode(base64_decode($site->getInputVar('interrelation')),true);
require_once (__DIR__."/../lib/vendor/autoload.php");
$xml = LSS\Array2XML::createXML('xml', Structure1c::Invoice($data));
//print_r($data);
//print_r($xml->saveXML());
$result = Data1c::RequestODATA("Document_СчетНаОплатуПокупателю", $xml->saveXML(), "POST");
//print_r($result);
$array = LSS\XML2Array::createArray($result);
$entry = $array['entry']['content']['m:properties'];
$invoice = array(
'invoice_uuid' => $entry['d:Ref_Key'],
'invoice_number' => $entry['d:Number'],
'invoice_date' => $entry['d:Date'],
'invoice_amount' => $entry['d:СуммаДокумента'],
'invoice_customer' => $entry['d:Контрагент_Key'],
'order_id' => $site->getInputVarInt('order_id')
);
$db->insert("invoices",$invoice);
foreach ($interrelation as $row) {
$row['invoice_uuid'] = $entry['d:Ref_Key'];
$db->insert("invoice_data",$row);
}
$data = Data1c::InvoiceData($entry['d:Ref_Key']);
$this->setSkin(JSONSkin::create());
$viewResolver = MultiPrefixPhpViewResolver::create()->addPrefix( PATH_SHARED_TEMPLATE );
$partViewer = new PartViewer($viewResolver, $this);
$html = $partViewer->content('invoice', SimpleModule::create()->setVar('data', $data) );
//BUGFIX for 1C, while ODATA, onSave does not happen
$structure = array
(
'action' => "update",
'order_id' => $site->getInputVarInt('order_id'),
'order_data' => array(),
'document' => array(
'type' => 'invoice',
'uuid' => $entry['d:Ref_Key'],
'date' => $entry['d:Date'],
'number' => $entry['d:Number'],
'amount' => $entry['d:СуммаДокумента']
),
'parent' => array()
);
$socket = "Driver1c:".json_encode($structure, JSON_UNESCAPED_UNICODE);
new WebSocketClient(array($socket));
return $this->setVar(
'json', array
(
'result' => 'success',
'invoice_number' => $entry['d:Number'],
'invoice_uuid' => $entry['d:Ref_Key'],
'invoice_amount' => $entry['d:СуммаДокумента'],
'html' => base64_encode($html),
'data' => $data
)
);
}
public static function Invoice($data)
{
$array = Array
(
'entry' => Array
(
'content' => Array
(
'm:properties' => Array
(
'd:СтруктурнаяЕдиница' => $data['СтруктурнаяЕдиница'],
'd:СтруктурнаяЕдиница_Type' => "StandardODATA.Catalog_БанковскиеСчета",
'd:ВалютаДокумента_Key' => "9af5b7f8-e570-11e1-b16a-6431507e6097", // TODO: get by ODATA
'd:ДоговорКонтрагента_Key' => $data['ДоговорКонтрагента_Key'],
'd:Автор_Key' => $data['Автор_Key'],
'd:Ответственный_Key' => $data['Автор_Key'],
'd:Контрагент_Key' => $data['Контрагент_Key'],
'd:Организация_Key' => $data['Организация_Key'],
'd:Склад_Key' => $data['Склад_Key'],
'd:ТипЦен_Key' => "00000000-0000-0000-0000-000000000000",
'd:СтруктурноеПодразделение_Key' => "00000000-0000-0000-0000-000000000000",
'd:КодНазначенияПлатежа' => $data['КодНазначенияПлатежа'],
//'d:СуммаДокумента' => "111111111",//$data['СуммаДокумента'],
'd:Date' => date("c"),
'd:Комментарий' => $data['НомерЗаказа']."\n".$data['Комментарий'],
'd:АдресДоставки' => "",
'd:УчитыватьНДС' => "true",
'd:УчитыватьАкциз' => "false",
'd:СуммаВключаетАкциз' => "false",
'd:СуммаВключаетНДС' => "true",
'd:DeletionMark' => "false",
'd:Posted' => "false",
'd:КратностьВзаиморасчетов' => "1",
'd:КурсВзаиморасчетов' => "1",
'd:Number' => "",
'd:DataVersion' => "",
'd:Услуги' => Array
(
'@value' => "",
'@attributes' => Array
(
'm:type' => "Collection(StandardODATA.Document_СчетНаОплатуПокупателю_Услуги_RowType)"
)
),
'd:ОС' => Array
(
'@value' => "",
'@attributes' => Array
(
'm:type' => "Collection(StandardODATA.Document_СчетНаОплатуПокупателю_ОС_RowType)"
)
),
'd:Товары' => Array
(
'd:element' => Array (),
'@attributes' => Array
(
'm:type' => "Collection(StandardODATA.Document_СчетНаОплатуПокупателю_Товары_RowType)"
)
),
'@attributes' => array
(
'xmlns:d' => "http://schemas.microsoft.com/ado/2007/08/dataservices",
'xmlns:m' => "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
)
),
'@attributes' => Array
(
'type' => "application/xml"
)
)
)
);
$i=1;
foreach ($data['rows'] as $row)
{
$element = Array
(
'd:LineNumber' => $i,
'd:СтавкаАкциза_Key' => "00000000-0000-0000-0000-000000000000",
'd:СуммаАкциза' => "0",
'd:Коэффициент' => 1,
'd:Номенклатура_Key' => $row['Номенклатура_Key'],
'd:СтавкаНДС_Key' => $row['СтавкаНДС_Key'],
'd:ЕдиницаИзмерения_Key' => $row['ЕдиницаИзмерения_Key'],
'd:Количество' => $row['Количество'],
'd:Цена' => $row['Цена'],
'd:Сумма' => $row['Сумма'],
'd:СуммаНДС' => $row['СуммаНДС'],
'@attributes' => Array
(
'm:type' => "StandardODATA.Document_СчетНаОплатуПокупателю_Товары_RowType"
)
);
$array['entry']['content']['m:properties']['d:Товары']['d:element'][] = $element;
$i++;
}
return $array;
}