File: /var/www/vhost/disk-apps/demo.sports-crowd.com/app/Http/Controllers/ERPSapController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Repositories\ERPRepository;
use GuzzleHttp\Exception\RequestException;
class ERPSapController extends ERPBaseController implements ERPRepository
{
private $api;
private $clientGuzzle;
private $headers;
public $erpId;
private $font = "05";
private $cashRegister = '5505';
public function __construct($erpId)
{
$this->erpId = $erpId;
$token = $this->auth($erpId);
$this->api = $this->getParameter($erpId, 'url');
$this->clientGuzzle = new \GuzzleHttp\Client([
'base_uri' => $this->api,
'defaults' => [
'exceptions' => false,
]
]);
$this->headers = [
'Accept' => 'application/json',
'Authorization' => 'Bearer ' . $token,
'Ocp-Apim-Subscription-Key' => $this->getParameter($erpId, 'subscription-Key')
];
}
public function thirdClientValidate($document)
{
$data = [];
$response = $this->getThirdClient($document);
if ($response['r']) {
$data = $response['d']->detalle->Table;
$data = json_decode(json_encode($data), true);
}
return $data;
}
public function getThirdClient($parameters)
{
$params = array(
'ConsultaCliente' =>
array(
'NRONIT' => $parameters->third->document,
'SOCIEDAD' => 'DE01',
'GRUPOCUENTAS' => '1001',
'CANAL' => '06',
'ORGANIZACION' => $this->cashRegister,
'CENTRO' => $this->cashRegister
)
);
$endpoint = 'consultaclienteslegadoverdolaga';
$url = (string) $this->clientGuzzle->getConfig('base_uri') . $endpoint;
try {
$responseGuzzle = $this->clientGuzzle->post($endpoint, [
\GuzzleHttp\RequestOptions::JSON => $params,
'headers' => $this->headers
]);
$body = (string) $responseGuzzle->getBody();
if ($responseGuzzle->getStatusCode() == 200) {
$body = json_decode($body)->RespuestaConsulta[0];
if (isset($body->CLIENTE)) {
return array('r' => true, 'd' => $body);
} else {
return $this->buildErrorResponseData($body->ExcepcionConsultaSAC->MESSAGE, $url, $params);
}
}
return array('r' => true, 'd' => $body);
} catch (RequestException $e) {
return $this->buildErrorResponseData(json_decode((string) $e->getResponse()->getBody()), $url, $params);
}
}
public function clientAddressValidationByName($address, $latitude = null, $longitude = null)
{
$controller = new AddressController;
if ($latitude && $longitude) {
$response = $controller->geocodeAddressByCoordinates($latitude, $longitude);
} else {
$response = $controller->geocodeAddress($address);
}
return $this->decodeGmapsData($response, 0);
}
private function decodeGmapsData($response, $index)
{
$data = [];
$arrayLenght = count($response);
if ($arrayLenght && $arrayLenght > $index && count($response[$index]->address_components)) {
$data = $response[$index]->address_components;
$neighborhood = $this->searchAddressData($data, 'neighborhood');
if (!$neighborhood)
$neighborhood = $this->searchAddressData($data, 'route');
$country = $this->searchAddressData($data, 'country');
$province = $this->searchAddressData($data, 'administrative_area_level_1');
$city = $this->searchAddressData($data, 'locality');
$postalCode = $this->searchAddressData($data, 'postal_code');
if (!$city)
$city = $this->searchAddressData($data, 'administrative_area_level_2');
if (is_array($country) || is_array($province) || is_array($city)) {
return $this->decodeGmapsData($response, $index + 1);
}
return array(
'country' => $country,
'province' => $province,
'city' => $city,
'postalCode' => is_array($postalCode) ? null : $postalCode
);
}
return $data;
}
private function searchAddressData($data, $type)
{
$result = array_filter($data, function ($v) use ($type) {
return in_array($type, $v->types);
}, ARRAY_FILTER_USE_BOTH);
if (count($result)) {
$result = [reset($result)];
$result = $result[0]->long_name;
}
return $result;
}
public function createThirdClient($parameters)
{
// $response = $this->validateCashRegister($parameters);
// if (!$response['r']) {
// return $response;
// }
$clientResponse = $this->getThirdClient($parameters);
if ($clientResponse['r']) {
return $clientResponse;
}
$response = $this->mapThirdClientData($parameters);
if (!$response['r']) {
return $response;
}
$body = $response['d'];
$endpoint = 'creacionclienteslegadoverdolaga';
$url = (string) $this->clientGuzzle->getConfig('base_uri') . $endpoint;
try {
$responseGuzzle = $this->clientGuzzle->post($endpoint, [
\GuzzleHttp\RequestOptions::JSON => $body,
'headers' => $this->headers
]);
$response = (string) $responseGuzzle->getBody();
if ($responseGuzzle->getStatusCode() == 200) {
$response = json_decode($response)->RespuestaSolicitudCreacionSAC->ExcepcionSolicitudCreacionSAC[0];
if ($response->Type == 'S') {
return array('r' => true, 'd' => $response, 'm' => $response->Message);
}
}
return $this->buildErrorResponseData($response, $url, $body);
} catch (RequestException $e) {
return $this->buildErrorResponseData(json_decode((string) $e->getResponse()->getBody()), $url, $body);
}
}
private function mapThirdClientData($params)
{
$names = explode(" ", $params->third->firstName);
$lastNames = explode(" ", $params->third->lastName);
$divicolaCode = $this->getDivipolaCode($params);
if (!$divicolaCode) {
return array(
'r' => false,
'd' => 'No se encontro código divipola para la dirección: ' . $params->shortAddress . (', ' . $params->city . ', ' . $params->province . ', ' . $params->country)
);
}
$body = array(
'ReqSolicitudClientes' =>
array(
'TRATAMIENTO' => $params->third->typeThird == 'NATURAL_PERSON' ? 'Sr./Sra.' : 'Empresa',
'NOMBR1' => $names[0],
'NOMBR2' => count($names) > 1 ? $names[1] : '',
'APELL1' => $lastNames[0],
'APELL2' => count($lastNames) > 1 ? $lastNames[1] : '',
'EMAIL1' => $params->third->email,
"IDENTI" => $params->third->documentType,
"NRONIT" => $params->third->document,
"PAIS" => "CO",
"CODDEP" => $divicolaCode['cod_dpto'],
"CDMPIO" => '0' . substr($divicolaCode['cod_mpio'], 2),
"PERSONAFISICA" => "X",
"CLASEIMPUESTO" => "PN",
"CONCEPTODEBUSQUEDA" => "NACIONAL",
"DIRECC" => mb_substr(explode(",", $params->shortAddress)[0], 0, 40, 'UTF-8'),
"CELULA" => $params->third->phone,
"SOCIEDAD" => "DE01",
"ORGANIZACIONVENTA" => $this->cashRegister,
"CENTRO" => $this->cashRegister,
"CANAL" => "06",
"SECTOR" => "01",
"CLASNE" => "97"
)
);
return array('r' => true, 'd' => $body);
}
public function createOrder($parameters)
{
$response = $this->mapOrderData($parameters);
if (!$response['r']) {
return $response;
}
$body = $response['d'];
$endpoint = 'solicitudpedidos';
$url = (string) $this->clientGuzzle->getConfig('base_uri') . $endpoint;
try {
$responseGuzzle = $this->clientGuzzle->post($endpoint, [
\GuzzleHttp\RequestOptions::JSON => $body,
'headers' => $this->headers
]);
$response = (string) $responseGuzzle->getBody();
if ($responseGuzzle->getStatusCode() == 200 && json_decode($response)->Mensaje == "OK") {
return $this->hasPreviousBill($parameters->reference);
}
return $this->buildErrorResponseData($response, $url, $body);
} catch (RequestException $e) {
return $this->buildErrorResponseData(json_decode((string) $e->getResponse()->getBody()), $url, $body);
}
}
public function createOrderShop($order = null, $parentController) {}
private function mapOrderData($parameters)
{
$clientResponse = $this->getThirdClient($parameters);
if (!$clientResponse['r']) {
return $clientResponse;
}
$address = $parameters->address;
$city = $address->city;
$gmapsData = $this->clientAddressValidationByName(
$address->direction . ($city ? ', ' . $city->name . ',' . $city->state->name . ',' . $city->state->country->name : ''),
$address->lat,
$address->long
);
if (!count($gmapsData)) {
return array('r' => false, 'd' => 'No se encontro ciudad para la dirección ' . $address->direction);
}
$names = explode(" ", $parameters->third->firstName);
$lastNames = explode(" ", $parameters->third->lastName);
$applicant = $clientResponse['d']->CLIENTE;
$authorizationCode = $parameters->transaction->pin;
$paymetMethod = null;
if ($parameters->transaction->gateway_payments_id) {
$paymentController = new PaymentController(
new Request([
'paymentGatewayId' => $parameters->transaction->gateway_payments_id
])
);
$authorizationCode = $paymentController->getAuthorizationCode($parameters->transaction);
$paymetMethod = $paymentController->getPaymentMethod($parameters->transaction);
}
$additionalInfo = [];
foreach ($parameters->items as $item) {
$additionalInfoItem = array(
"Id_transaccion" => $parameters->transaction->id,
"Forma_pago" => $paymetMethod ?? $parameters->transaction->gateway_payments->name ?? 'Efectivo',
"Referencia" => $parameters->transaction->pin,
"Fecha_transaccion" => $parameters->date,
"Codigo_autorizacion" => $authorizationCode ?? $parameters->transaction->pin,
"Franquicia" => $this->mapFranchise($paymetMethod),
"Num_tarjeta" => "",
"Moneda" => "COP",
"Valor" => $item["Precio_total"],
"Impuesto" => "0",
"Base_dev" => "0",
"Codigo_banco" => "",
"Indicador_iva" => ""
);
array_push($additionalInfo, $additionalInfoItem);
}
$body = array(
"Fuente" => $this->font,
"Id_unico" => $parameters->reference,
"Accion" => 'C',
"Documento" => $document ?? "",
"Num_pedido" => $parameters->numeroPedido,
"Tipo_operacion" => "01",
"Tipo_producto" => "SCHL",
"Organizacion_ventas" => $this->cashRegister,
"Canal_distribucion" => "06",
"Centro" => $this->cashRegister,
"Puesto_expedicion" => $this->cashRegister,
"Sector" => "01",
"Origen_solicitante" => "01",
"Solicitante" => $applicant,
"Origen_destinatario" => "01",
"Destinatario" => $applicant,
"Ori_cross_docking" => "",
"Cl_cross_docking" => "",
"EAN" => "",
"Tipo_documento" => $parameters->third->documentType,
"Doc_identificacion" => $parameters->document,
"Primer_nombre" => $names[0],
"Segundo_nombre" => count($names) > 1 ? $names[1] : '',
"Primer_apellido" => $lastNames[0],
"Segundo_apellido" => count($lastNames) > 1 ? $lastNames[1] : '',
"Cod_pais" => "CO",
"Region" => "05",
"Ciudad" => $gmapsData['city'],
"Direccion" => mb_substr(str_replace('#', 'N', $address->direction), 0, 60, 'UTF-8'),
"Telefono_fijo" => "",
"Telefono_celular" => $parameters->third->phone,
"Correo" => $parameters->third->email,
"Fecha_documento" => $parameters->date,
"Fec_max_entrega" => $parameters->date,
"Fec_minima_entrega" => $parameters->date,
"Orden_compra" => $parameters->numeroPedido,
"Cod_vendedor" => $this->cashRegister,
"Cod_mot_pedido" => "520",
"Observacion" => "Pago desde SporstCrowd",
"Detalle" => $parameters->items,
"InfoAdicional" => $additionalInfo
);
return array('r' => true, 'd' => $body);
}
public function mapDocumentType($typeDocument)
{
switch ($typeDocument) {
case 'CC':
case 'Cedula de Ciudadania':
case 'cedula_ciudadania':
return 'CC';
case 'CE':
case 'Cedula de Extranjeria':
case 'cedula_extranjeria':
return 'CE';
case 'PA':
case 'Pasaporte':
case 'pasaporte':
return 'PP';
case 'TI':
case 'Tarjeta de identidad':
case 'tarjeta_identidad':
return 'TI';
case 'nit':
return 'NI';
default:
return 'CC';
}
}
public function mapDocumentTypeOrder($typeDocument)
{
switch ($typeDocument) {
case 'CC':
case 'Cedula de Ciudadania':
case 'cedula_ciudadania':
return 'C';
case 'CE':
case 'Cedula de Extranjeria':
case 'cedula_extranjeria':
return 'E';
case 'PA':
case 'Pasaporte':
case 'pasaporte':
return 'P';
case 'TI':
case 'Tarjeta de identidad':
case 'tarjeta_identidad':
return 'T';
case 'nit':
return 'N';
case 'RC':
return 'R';
default:
return 'C';
}
}
public function mapGender($gender)
{
switch ($gender) {
case 'Hombre':
case 'hombre':
case 'M':
return '2';
case 'Mujer':
case 'mujer':
case 'F':
return '1';
default:
return '0';
}
}
public function mapFranchise($paymentMethod)
{
switch ($paymentMethod) {
case 'pse':
return '0';
case 'visa':
return 'O';
case 'master':
return 'H';
case 'amex':
return 'C';
default:
return 'E';
}
}
public function createRC($parameters)
{
return array('r' => true, 'd' => 'No aplica para SAP');
}
public function getOrder($reference, $operationCenter = null)
{
$params = array(
'IFuente' => $this->font,
'IIdenti' => $reference
);
$endpoint = 'consultapedidos';
$url = (string) $this->clientGuzzle->getConfig('base_uri') . $endpoint;
try {
$responseGuzzle = $this->clientGuzzle->post($endpoint, [
\GuzzleHttp\RequestOptions::JSON => $params,
'headers' => $this->headers
]);
$body = (string) $responseGuzzle->getBody();
if ($responseGuzzle->getStatusCode() == 200) {
$body = json_decode($body);
if (isset($body->EtDocs)) {
$etDocs = $body->EtDocs;
$etDocsFilter = array_filter($etDocs, function ($item) {
return $item->Docum == "FAC";
}, ARRAY_FILTER_USE_BOTH);
if (count($etDocsFilter)) {
return array('r' => true, 'd' => $body, 'saveLog' => ($body->EEstado != '03'));
}
}
}
return $this->buildErrorResponseData($body, $url, $params);
} catch (RequestException $e) {
return $this->buildErrorResponseData(json_decode((string) $e->getResponse()->getBody()), $url, $params);
}
}
public function createBill($parameters)
{
return array('r' => true, 'd' => 'No aplica para SAP');
}
public function getRC($thirdDocument, $operationCenter, $date = '-1')
{
return array('r' => true, 'd' => 'No aplica para SAP');
}
public function getInventory($priceList, $locationName) {}
public function getBill($reference)
{
return array('r' => true, 'd' => 'No aplica para SAP');
}
public function hasPreviousBill($reference)
{
$response = $this->getOrder($reference);
if ($response['r']) {
$etDocs = $response['d']->EtDocs;
$etDocsFilter = array_filter($etDocs, function ($item) {
return $item->Docum == "FAC";
}, ARRAY_FILTER_USE_BOTH);
$response['error'] = $response['d'];
$response['d'] = end($etDocsFilter)->Vbeln;
return $response;
}
return $response;
}
public function hasPreviousOrder($reference, $transactionReference, $transactionId)
{
$response = $this->getOrder($reference);
return $response['r'];
}
public function generateOrderItem($parameters)
{
$taxes = round(($parameters->price * 19) / 119, 2);
return array(
"Origen_material" => "01",
"Material" => $parameters->serviceCode,
"Total_cross_doking" => "0",
"Cantidad" => "1",
"Unidad_medida" => "ST",
"Precio_um" => round($parameters->price - $taxes, 2),
"Precio_total" => round($parameters->price, 2),
"Moneda" => "COP",
"IVA" => $taxes,
"Ipoconsumo" => "0",
"Descuento" => "0"
);
}
private function auth($erpId)
{
$client = new \GuzzleHttp\Client();
$authUrl = $this->getParameter($erpId, 'urlAuth');
$response = $client->post(
$authUrl,
[
'form_params' => [
'client_secret' => $this->getParameter($erpId, 'client_secret'),
'client_id' => $this->getParameter($erpId, 'client_id'),
'scope' => $this->getParameter($erpId, 'scope'),
'grant_type' => $this->getParameter($erpId, 'grant_type')
]
]
);
if ($response->getStatusCode() == 200) {
return json_decode($response->getBody()->getContents(), true)['access_token'];
}
return null;
}
private function getDivipolaCode($params)
{
$utilController = new UtilController();
$gmapsData = $this->clientAddressValidationByName(
$params->shortAddress . (', ' . $params->city . ', ' . $params->province . ', ' . $params->country),
$params->latitude ?? null,
$params->longitude ?? null
);
if (!count($gmapsData)) {
return null;
}
$city = $utilController->removeStrAccent(mb_strtoupper($gmapsData['city'], 'UTF-8'));
$province = $utilController->removeStrAccent(
mb_strtoupper($gmapsData['province'], 'UTF-8')
);
$postalCode = $gmapsData['postalCode'];
$extraParam = $postalCode ? '?cod_dpto=' . substr($postalCode, 0, 2) : '';
$client = new \GuzzleHttp\Client();
$url = 'https://www.datos.gov.co/resource/gdxc-w37w.json' . $extraParam;
$response = json_decode($client->get($url)->getBody()->getContents(), true);
$cityInfo = array_filter($response, function ($item) use ($city, $province, $utilController) {
$cityName = $utilController->removeStrAccent($item['nom_mpio']);
$provinceName = $utilController->removeStrAccent($item['dpto']);
return str_contains($provinceName, $province) && str_contains($cityName, $city);
}, ARRAY_FILTER_USE_BOTH);
return end($cityInfo);
}
public function createCreditNote($parameters)
{
$response = $this->mapCreditNoteData($parameters);
if (!$response['r']) {
return $response;
}
$body = $response['d'];
$endpoint = 'solicitudpedidos';
$url = (string) $this->clientGuzzle->getConfig('base_uri') . $endpoint;
try {
$responseGuzzle = $this->clientGuzzle->post($endpoint, [
\GuzzleHttp\RequestOptions::JSON => $body,
'headers' => $this->headers
]);
$response = (string) $responseGuzzle->getBody();
if ($responseGuzzle->getStatusCode() == 200 && json_decode($response)->Mensaje == "OK") {
return $this->getCreditNote('NC' . $parameters->reference, $parameters->document);
}
return $this->buildErrorResponseData($response, $url, $body);
} catch (RequestException $e) {
return $this->buildErrorResponseData(json_decode((string) $e->getResponse()->getBody()), $url, $body);
}
}
private function mapCreditNoteData($parameters)
{
$clientResponse = $this->getThirdClient($parameters);
if (!$clientResponse['r']) {
return $clientResponse;
}
$address = $parameters->address;
$city = $address->city;
$gmapsData = $this->clientAddressValidationByName(
$address->direction . ($city ? ', ' . $city->name . ',' . $city->state->name . ',' . $city->state->country->name : ''),
$address->lat,
$address->long
);
$names = explode(" ", $parameters->third->firstName);
$lastNames = explode(" ", $parameters->third->lastName);
$applicant = $clientResponse['d']->CLIENTE;
$additionalInfo = [];
foreach ($parameters->items as $item) {
$additionalInfoItem = array(
"Id_transaccion" => $parameters->transaction->id,
"Forma_pago" => $parameters->transaction->gateway_payments->name ?? 'Efectivo',
"Referencia" => $parameters->transaction->pin,
"Fecha_transaccion" => $parameters->date,
"Codigo_autorizacion" => $parameters->transaction->pin,
"Franquicia" => "I",
"Num_tarjeta" => "",
"Moneda" => "COP",
"Valor" => $item["Precio_total"],
"Impuesto" => "0",
"Base_dev" => "0",
"Codigo_banco" => "",
"Indicador_iva" => ""
);
array_push($additionalInfo, $additionalInfoItem);
}
$response = $this->getOrder($parameters->oderReference);
if ($response['r']) {
$etDocs = $response['d']->EtDocs;
$etDocsFilter = array_filter($etDocs, function ($item) {
return $item->Docum == "FAC";
}, ARRAY_FILTER_USE_BOTH);
$document = end($etDocsFilter)->Vbeln;
}
$body = array(
"Fuente" => $this->font,
"Id_unico" => $parameters->reference,
"Accion" => 'E',
"Documento" => $document ?? "",
"Num_pedido" => $parameters->numeroPedido,
"Tipo_operacion" => "04",
"Tipo_producto" => "SCHL",
"Organizacion_ventas" => $this->cashRegister,
"Canal_distribucion" => "06",
"Centro" => $this->cashRegister,
"Puesto_expedicion" => $this->cashRegister,
"Sector" => "01",
"Origen_solicitante" => "01",
"Solicitante" => $applicant,
"Origen_destinatario" => "01",
"Destinatario" => $applicant,
"Ori_cross_docking" => "",
"Cl_cross_docking" => "",
"EAN" => "",
"Tipo_documento" => $parameters->third->documentType,
"Doc_identificacion" => $parameters->document,
"Primer_nombre" => $names[0],
"Segundo_nombre" => count($names) > 1 ? $names[1] : '',
"Primer_apellido" => $lastNames[0],
"Segundo_apellido" => count($lastNames) > 1 ? $lastNames[1] : '',
"Cod_pais" => "CO",
"Region" => "05",
"Ciudad" => $gmapsData['city'],
"Direccion" => str_replace('#', 'N', $address->direction . ' | ' . $address->district),
"Telefono_fijo" => "",
"Telefono_celular" => $parameters->third->phone,
"Correo" => $parameters->third->email,
"Fecha_documento" => $parameters->date,
"Fec_max_entrega" => $parameters->date,
"Fec_minima_entrega" => $parameters->date,
"Orden_compra" => $parameters->reference,
"Cod_vendedor" => $this->cashRegister,
"Cod_mot_pedido" => "520",
"Observacion" => "Pago desde SporstCrowd",
"Detalle" => $parameters->items,
"InfoAdicional" => $additionalInfo
);
return array('r' => true, 'd' => $body);
}
public function getCreditNote($reference, $userDocument)
{
$params = array(
'Nota_credito' => $reference,
'Cliente' => $userDocument
);
$endpoint = 'consultanotacredito';
$url = (string) $this->clientGuzzle->getConfig('base_uri') . $endpoint;
try {
$responseGuzzle = $this->clientGuzzle->post($endpoint, [
\GuzzleHttp\RequestOptions::JSON => $params,
'headers' => $this->headers
]);
$body = (string) $responseGuzzle->getBody();
if ($responseGuzzle->getStatusCode() == 200) {
$body = json_decode($body);
if ($body->Id_estado == '03') {
return array('r' => true, 'd' => $body);
}
}
return $this->buildErrorResponseData($body, $url, $params);
} catch (RequestException $e) {
return $this->buildErrorResponseData(json_decode((string) $e->getResponse()->getBody()), $url, $params);
}
}
public function getNextReference($reference)
{
if (str_contains($reference, '-')) {
$referenceSplit = explode('-', $reference);
return $referenceSplit[0] . '-' . ($referenceSplit[1] + 1);
}
return $reference . '-1';
}
public function validateCashRegister($parameters)
{
$params = array(
'IdCaja' => $this->cashRegister
);
$endpoint = 'consultacajasactivas';
$url = (string) $this->clientGuzzle->getConfig('base_uri') . $endpoint;
try {
$responseGuzzle = $this->clientGuzzle->post($endpoint, [
\GuzzleHttp\RequestOptions::JSON => $params,
'headers' => $this->headers
]);
$body = (string) $responseGuzzle->getBody();
$body = json_decode($body);
if ($responseGuzzle->getStatusCode() == 200) {
if ($body->Estado == '03') {
return array('r' => true, 'd' => $body);
}
}
return $this->buildErrorResponseData(
'Caja inhabilitada para faturar: ' . $this->cashRegister,
$url,
$params
);
} catch (RequestException $e) {
return $this->buildErrorResponseData(json_decode((string) $e->getResponse()->getBody()), $url, $params);
}
}
public function getDefaultAddress($userId)
{
$addressController = new AddressController;
$addressId = $addressController->create(
"Generada automaticamente",
"Calle 52 N 47 - 42, Medellín, Antioquia, Colombia",
"",
"",
null,
null,
null,
$userId
);
return $addressId;
}
function buildErrorResponseData($response, $url, $body)
{
$data = new \stdClass();
$data->response = $response;
$data->url = $url;
$data->body = $body;
return array('r' => false, 'd' => $data);
}
}