File: /var/www/vhost/disk-apps/comfama.sports-crowd.com/app/Http/Controllers/ShopifyController.php
<?php
namespace App\Http\Controllers;
use Exception;
use App\ErpLog;
use App\Product;
use App\Parameter;
use App\SystemLog;
use Carbon\Carbon;
use App\ErpParameter;
use App\ProductAttribute;
use App\CorporateIdentity;
use Slince\Shopify\Client;
use App\IntegrationProvider;
use App\Services\ErpService;
use Illuminate\Http\Request;
use PHPMailer\PHPMailer\PHPMailer;
use App\Repositories\ERPRepository;
use Illuminate\Support\Facades\Auth;
use App\Repositories\ERPLogRepository;
use App\Http\Controllers\UserController;
use Slince\Shopify\PrivateAppCredential;
use App\Http\Controllers\OrderController;
use App\Http\Controllers\BrandsController;
use App\Http\Controllers\AddressController;
use App\Http\Controllers\ProductController;
use App\Http\Controllers\CategoryController;
use App\Http\Controllers\AttributeController;
class ShopifyController extends Controller implements ERPLogRepository
{
private $validSync = false;
private $parameters;
public ERPRepository $ERPRepository;
private $controllerOrder;
private $utilController;
private $inventoryController;
private $ERPPrefix = 'AS';
public function __construct($ERPRepository = null)
{
$this->utilController = new UtilController;
$this->initApiRest();
$this->controllerOrder = new OrderController;
$this->inventoryController = new InventoryController;
if ($ERPRepository != null) {
$this->ERPRepository = $ERPRepository;
} else {
$defaultErp = config('erp.default');
$erp = config("erp.{$defaultErp}.class");
$this->ERPRepository = new $erp;
}
}
//Mostrar tienda embebida en un iframe
public function showExternalShop()
{
$collections = $this->httpRequest('GET', 'custom_collections.json', 'COP')['custom_collections'];
$corporateIdentity = CorporateIdentity::first();
return view('shopify.collections', compact('collections', 'corporateIdentity'));
}
public function showExternalShopProducts($collectionId)
{
return view('shopify.shop', compact('collectionId'));
}
public function initApiRest()
{
$this->parameters = Parameter::select('sync_shopify', 'sucursal_products')->find(1);
if ($this->parameters && $this->parameters->sync_shopify) {
$this->validSync = true;
}
}
public function getIntegrationProvider($currency)
{
return IntegrationProvider::where([['ecommerce_type_id', 3], ['active', true], ['currency', $currency]])->first();
}
// produtcs
public function createProduct($data, $currency)
{
try {
if ($this->validSync) {
return $this->httpRequest('POST', "products.json", $currency, $data)['product'];
}
return null;
} catch (\Exception $e) {
dump($e->getMessage(), $data, 'createProduct');
return null;
}
}
public function updateProduct($id, $data, $currency)
{
try {
if ($this->validSync && $id && $id != "") {
$this->httpRequest('PUT', "products/" . $id . ".json", $currency, $data);
}
} catch (\Exception $e) {
return null;
}
}
public function addImageProduct($id, $data, $currency)
{
try {
if ($this->validSync && $id && $id != "") {
$integrationProvider = $this->getIntegrationProvider($currency);
$credential = new PrivateAppCredential(
$integrationProvider->key_public,
$integrationProvider->password,
$integrationProvider->key_private
);
$shopify = new Client(
$credential,
$integrationProvider->endpoint,
[
'metaCacheDir' => './tmp',
'apiVersion' => '2023-04',
],
);
$shopify->getProductImageManager()->create($id, $data);
}
} catch (\Exception $e) {
return null;
}
}
public function deleteProduct($id, $currency)
{
try {
if ($this->validSync && $id && $id != "") {
$integrationProvider = $this->getIntegrationProvider($currency);
$credential = new PrivateAppCredential(
$integrationProvider->key_public,
$integrationProvider->password,
$integrationProvider->key_private
);
$shopify = new Client(
$credential,
$integrationProvider->endpoint,
[
'metaCacheDir' => './tmp',
'apiVersion' => '2023-04',
],
);
$shopify->delete('products/' . $id);
}
} catch (\Exception $e) {
return null;
}
}
// Variant
public function createVariant($product_id, $data, $currency)
{
try {
if ($this->validSync && $product_id && $product_id != "") {
$response = $this->httpRequest('POST', "products/" . $product_id . "/variants.json", $currency, $data);
return $response['variant'];
}
return null;
} catch (\Exception $e) {
dump($e->getMessage(), $product_id, 'createVariant');
return null;
}
}
public function updateVariant($variant_id, $data)
{
try {
if ($this->validSync && $variant_id && $variant_id != "") {
$client = new \GuzzleHttp\Client();
$client->put($this->baseUrl . "variants/" . $variant_id . ".json", [
\GuzzleHttp\RequestOptions::JSON => $data,
'headers' => [
'X-Shopify-Access-Token' => $this->integration->password
]
]);
}
} catch (\Exception $e) {
return null;
}
}
public function deleteVariant($variant_id, $product_id, $currency)
{
try {
if ($this->validSync && $variant_id && $variant_id != "" && $product_id && $product_id != "") {
$integrationProvider = $this->getIntegrationProvider($currency);
$credential = new PrivateAppCredential(
$integrationProvider->key_public,
$integrationProvider->password,
$integrationProvider->key_private
);
$shopify = new Client(
$credential,
$integrationProvider->endpoint,
[
'metaCacheDir' => './tmp',
'apiVersion' => '2023-04',
],
);
$shopify->getProductVariantManager()->remove($product_id, $variant_id);
}
} catch (\Exception $e) {
return null;
}
}
public function updateInventoryLevel($inventory_item_id, $quantity_adjustment, $location, $currency)
{
try {
if ($this->validSync && $inventory_item_id && $inventory_item_id != "") {
$locations = $this->httpRequest('GET', 'locations.json', $currency)['locations'];
$locations = array_filter($locations, function ($item) use ($location) {
return $item['name'] == $location;
}, ARRAY_FILTER_USE_BOTH);
$data = [
"location_id" => end($locations)['id'],
"inventory_item_id" => $inventory_item_id,
"available" => intval($quantity_adjustment),
];
$this->httpRequest('POST', "inventory_levels/set.json", $currency, $data);
}
} catch (\Exception $e) {
return null;
}
}
private function updateShopifyMetafield($value, $order, $fieldName)
{
try {
$data = array(
"metafield" => array(
"value" => $value,
"owner_id" => $order['id'],
"namespace" => "checkoutcustomizer",
"key" => $fieldName,
"owner_resource" => "order",
"type" => "single_line_text_field",
)
);
$this->httpRequest('POST', "orders/" . $order['id'] . "/metafields.json", $order['currency'], $data);
} catch (\Exception $e) {
return null;
}
}
public function newRequest($data)
{
return new Request($data);
}
public function sync()
{
if ($this->validSync) {
$loadDate = Carbon::now();
$integrationProviders = IntegrationProvider::where([['ecommerce_type_id', 3], ['active', true]])->get();
foreach ($integrationProviders as $integrationProvider) {
$this->getOrdersFromShopify($integrationProvider->currency, $integrationProvider->last_load_date);
$integrationProvider->last_load_date = $loadDate;
$integrationProvider->update();
$this->syncInventoryERP($integrationProvider->currency);
}
}
}
//---------------------------------------------------weebhook-------------------------------------------------------
public function webhooksListener(Request $request)
{
try {
$order = json_decode($request->getContent(), true);
$previousWebhook = SystemLog::select('id')->where('data', 'like', '%:' . $order['id'] . '%')->first();
if (!$previousWebhook) {
$utilController = new UtilController();
$utilController->logFile($request, 'shopify');
$this->saveData($order);
}
} catch (Exception $e) {
$this->saveERPLog(json_encode($order), $e->getMessage(), 'webhooksListener');
}
return response(array('r' => true, 'm' => "Recibido", 'd' => null));
}
private function saveData($order)
{
try {
if (!$this->controllerOrder->getOrderByReference($order['order_number'])) {
$confirmUser = $this->registerUserFromOrder($order);
if ($confirmUser) $this->saveOrder($order);
}
$this->syncERP($order);
} catch (Exception $e) {
$this->saveERPLog(json_encode($order), $e->getMessage(), 'saveData');
}
}
private function httpRequest($method, $endpoint, $currency, $data = null)
{
$integrationProviders = $this->getIntegrationProvider($currency);
$client = new \GuzzleHttp\Client();
$url = 'https://' . $integrationProviders->endpoint . '/admin/api/2023-04/';
$body = [
'headers' => ['X-Shopify-Access-Token' => $integrationProviders->password]
];
switch ($method) {
case 'GET':
$response = $client->get($url . $endpoint, $body);
break;
case 'POST':
$body = array_merge($body, [\GuzzleHttp\RequestOptions::JSON => $data]);
$response = $client->post($url . $endpoint, $body);
break;
case 'PUT':
$body = array_merge($body, [\GuzzleHttp\RequestOptions::JSON => $data]);
$response = $client->put($url . $endpoint, $body);
break;
}
return json_decode($response->getBody()->getContents(), true);
}
public function getProduct($productId, $currency)
{
return $this->httpRequest('GET', 'products/' . $productId . '.json', $currency)['product'];
}
private function getMetafields($order)
{
return $this->httpRequest('GET', 'orders/' . $order['id'] . '/metafields.json', $order['currency'])['metafields'];
}
public function getSuccessTransaction($order)
{
$transactions = $this->httpRequest(
'GET',
'orders/' . $order['id'] . '/transactions.json',
$order['currency']
)['transactions'];
$successTransactions = array_filter($transactions, function ($item) {
return $item['status'] == 'success';
}, ARRAY_FILTER_USE_BOTH);
// $successTransactions = $transactions;
if (count($successTransactions)) {
return end($successTransactions);
}
return null;
}
public function getOrdersFromShopify($currency, $lastLoadDate, $sinceId = 1)
{
$date = Carbon::parse($lastLoadDate)->toIso8601String();
$filters = $lastLoadDate ? '&updated_at_min=' . $date : '';
$filters .= '&since_id=' . $sinceId;
$response = $this->httpRequest(
'GET',
'orders.json?status=any&financial_status=paid&limit=250' . $filters,
$currency
);
$orders = $response["orders"];
foreach ($orders as $order) {
$this->saveData($order);
}
if (count($orders) > 0) {
$this->getOrdersFromShopify($currency, $lastLoadDate, end($orders)['id']);
}
}
private function saveOrder($order)
{
$request_params = new Request([]);
$controllerAddress = new AddressController();
$controllerUser = new UserController($request_params);
$address_id = null;
$customer = $order['customer'];
$billingAddress = $order['billing_address'];
$shippingAddress = $order['shipping_address'] ?? $billingAddress;
$document = $this->getBuyerDocument($order);
if (!$customer || !$customer['email']) {
return;
}
$user = $controllerUser->searchUser(
$document,
$customer['email'],
$customer['first_name'],
$customer['last_name'],
$order['phone']
);
if ($user) {
$user_id = $user->id;
if ($shippingAddress) {
$address = $controllerAddress->searchAddressByAddress($shippingAddress['address1'], $user_id);
if ($address) {
$address_id = $address;
}
}
}
if ($shippingAddress) {
$city_id = $controllerAddress->searchCityByName($shippingAddress['city']);
}
$products = [];
foreach ($order['line_items'] as $key => $product) {
$current_product = Product::where('reference_shopify_id', $product['product_id'])->first();
if ($current_product) {
$valuesAttributes = [];
$product_atribute = ProductAttribute::where([['product_id', $current_product->id], ['reference_shopify_id', $product['variant_id']]])
->with('attribute')
->first();
if ($product_atribute) {
$arrayAttribute = array(
'attribute' => $product_atribute->attribute->toArray(),
'attribute_id' => $product_atribute->attribute->id,
'available_units' => $product_atribute->available_units,
'dispatched_units' => $product_atribute->dispatched_units,
'ean' => $product_atribute->ean,
'high' => $product_atribute->high,
'id' => $product_atribute->id,
'length' => $product_atribute->length,
'main_position' => $product_atribute->main_position,
'observation' => $product_atribute->observation,
'packaging' => $product_atribute->packaging,
'pmi' => $product_atribute->pmi,
'price_additional' => $product_atribute->price_additional,
'product_id' => $product_atribute->product_id,
'quantity' => $product['quantity'],
'sku' => $product_atribute->sku,
'stowage_pattern' => null,
'value' => $product['variant_title'],
'weight' => null,
'width' => null,
'created_at' => null,
'updated_at' => null,
);
$valuesAttributes[] = $arrayAttribute;
}
$newProduct = array(
'quantity' => $product['quantity'],
'max_units_per_order' => $current_product->max_units_per_order,
'price' => $product['price'],
'priceTotal' => $product['price'],
'id' => $current_product->id,
'plu' => $current_product->plu,
'name' => $current_product->name,
'priceAfterDiscount' => null,
'priceAfterFlash' => null,
'percentage_discount' => null,
'start_discount' => null,
'limit_discount' => null,
'limit_hour_discount' => null,
'flash_price' => null,
'start_flash_discount' => null,
'limit_flash_discount' => null,
'limit_hour_flash_discount' => null,
'product_attributes_selected' => $valuesAttributes
);
$products[] = $newProduct;
}
}
$priceDomicile = $order['shipping_lines'];
if (count($priceDomicile) > 0) {
$priceDomicile = $priceDomicile[0]['price'];
} else {
$priceDomicile = 0;
}
$phone = $shippingAddress['phone'];
$address = $shippingAddress['address1'];
$data = array('data' => array(
'first_name' => $customer ? $customer['first_name'] : null,
'last_name' => $customer ? $customer['last_name'] : null,
'document' => $document,
'phone' => $phone,
'email' => $customer ? $customer['email'] : null,
'order_reference' => $order['order_number'],
'sucursal' => null,
'products' => $products,
'confirmOrder' => array(
'observations' => "",
'effectivePayment' => 0,
'cellphone' => $phone,
'wayPay' => 5,
'address' => $address_id,
'address_new' => array(
'direction' => $shippingAddress['address1'],
'district' => '',
'instru' => $shippingAddress['address2'],
'lat' => '',
'lng' => '',
),
),
'dCampana' => null,
'dReferred' => null,
'dCoupone' => null,
'subtotal' => $order['subtotal_price'],
'discount' => $order['total_discounts'],
'priceDomicile' => $priceDomicile,
'total' => $order['total_price'],
'productsNotFound' => null,
'order_type_id' => 5,
'client_id' => $user_id ?? null,
'city_id' => $city_id,
'delivery_man_id' => null,
'job_sync' => true,
'code' => $order['id']
));
if (count($products)) {
$request = new Request($data);
$newOrder = $this->controllerOrder->create($request, false);
if (!is_array($newOrder)) {
$this->registerLog(
$user_id,
'Error creando order: ' . json_encode($newOrder->getData()),
json_encode($order),
"Create",
3
);
return;
}
}
}
public function getBuyerDocument($order)
{
$metafields = $this->getMetafields($order);
if (count($metafields)) {
$metafields = json_decode($metafields[0]['value']);
$juridicalPerson = isset($metafields->selectedTypeCustomer) && $metafields->selectedTypeCustomer == 'persona_juridica';
if (!empty($metafields->selectedNIT) || !empty($metafields->selectedDocument)) {
return $juridicalPerson ? $metafields->selectedNIT : $metafields->selectedDocument;
}
}
$customer = $order['customer'];
$billingAddress = $order['billing_address'];
$customerDocument = isset($customer['document']) ? $customer['document'] : null;
if ($billingAddress) {
$customerDocument = $customerDocument ?? $billingAddress['document'] ?? $billingAddress['company'];
}
return $customerDocument;
}
private function registerUserFromOrder($order)
{
$carnetController = new CarnetController();
$userController = new UserController();
$customer = $order['customer'];
$billingAddress = $order['billing_address'];
if (!$customer) {
return;
}
$email = $customer['email'] ?? $order['contact_email'] ?? $order['email'];
$password = base64_encode(random_bytes(4));
$tags = [];
foreach ($order['line_items'] as $item) {
if (!$item['product_id']) {
continue;
}
$shopifyProduct = $this->getProduct($item['product_id'], $order['currency']);
$this->saveProduct($shopifyProduct);
foreach (explode(', ', $shopifyProduct['tags']) as $tag) {
$carnet = $carnetController->getBySegmentation($tag);
if ($carnet) {
array_push($tags, $carnet->tag_id);
}
}
}
$customerDocument = $this->getBuyerDocument($order);
$userRespose = $userController->createClient(new Request([
'first_name' => $customer['first_name'] ?? $billingAddress['first_name'] ?? 'User',
'last_name' => $customer['last_name'] ?? $billingAddress['last_name'],
'email' => $email,
'password' => $password,
'tags' => $tags,
'phone' => $customer['phone'] ?? $billingAddress['phone'] ?? '1234',
'document' => $customerDocument,
'document_type' => '',
'direction' => $billingAddress['address1'] . ',' . $billingAddress['city'] . ',' . $billingAddress['province'] . ',' . $billingAddress['country']
]), false);
if (count($tags) > 0) {
$parameters = Parameter::select('android_play_store', 'ios_app_store')->first();
$corporateIdentity = CorporateIdentity::first();
$appStoreUrl = 'https://apps.apple.com/us/app/' . $parameters->ios_app_store;
$playStoreUrl = 'https://play.google.com/store/apps/details?id=' . $parameters->android_play_store;
$customer['email'] = $email;
$parameters = [
'isNewUser' => !isset($userRespose['oldUser']) || !$userRespose['oldUser'],
'email' => $email,
'password' => $password,
'segmentation' => $tag,
'appStoreUrl' => $appStoreUrl,
'playStoreUrl' => $playStoreUrl,
'corporateIdentity' => $corporateIdentity
];
$this->sendConfirmationEmail($customer, $tag, $parameters);
}
return true;
}
public function sendConfirmationEmail(array $customer, string $subject, array $params = [])
{
try {
$mail = new PHPMailer(true);
// $mail->SMTPDebug = SMTP::DEBUG_SERVER; //Enable verbose debug output
$mail->isSMTP(); //Send using SMTP
$mail->Host = env('MAIL_HOST_HED'); //Set the SMTP server to send through
$mail->SMTPAuth = true; //Enable SMTP authentication
$mail->Username = env('MAIL_USERNAME_HED'); //SMTP username
$mail->Password = env('MAIL_PASSWORD_HED'); //SMTP password
$mail->SMTPSecure = env('MAIL_ENCRYPTION'); //Enable implicit TLS encryption
$mail->Port = env('MAIL_PORT');
$mail->setFrom(env('MAIL_USERNAME_HED'), env('MAIL_FROM_NAME'));
$mail->addAddress($customer['email'], $customer['first_name']);
$mail->isHTML(true);
$mail->Subject = $subject;
$mail->Body = view('mails.createdUserAndCarnet')->with([
'isNewUser' => $parameters['isNewUser'] ?? false,
'email' => $customer['email'],
'password' => $params['password'] ?? '',
'segmentation' => $params['tag'] ?? '',
'appStoreUrl' => $params['appStoreUrl'],
'playStoreUrl' => $params['playStoreUrl'],
'corporateIdentity' => $params['corporateIdentity']
])->render();
$mail->send();
} catch (\Exception $e) {
echo "Message could not be sent. Mailer Error: " . $e->getMessage();
}
}
private function saveProduct($product)
{
$request_params = $this->newRequest([]);
$brand = new BrandsController($request_params);
$category = new CategoryController($request_params);
$product_controller = new ProductController($request_params);
$productAttribute_controller = new ProductAttributeController($request_params);
$attribute_controller = new AttributeController($request_params);
$current_product = Product::where('name', $product['title'])->first();
// si existe actualizamos si no creamos
if ($current_product) {
$current_product->reference_shopify_id = $product['id'];
$product_id = $current_product->id;
$current_product->update();
$this->saveProductImages($product, $current_product->id);
} else {
$default_sucursal_id = 2;
if (Auth::user()) {
$default_sucursal_id = Auth::user()->userInfo->sucursal_id;
}
$sucursal_id = $this->parameters->sucursal_products ? $default_sucursal_id : null;
$brand_id = null;
$c_brand = $brand->create($this->newRequest(['name' => $product['vendor']]));
if ($c_brand) {
$brand_id = $c_brand["d"]["id"];
}
$subcategory_id = null;
$data_category = [
'name' => $product['product_type'],
'sucursal_id' => $sucursal_id,
'priority' => 1,
'store_type' => 'main'
];
$c_category = $category->create($this->newRequest($data_category), false);
if ($c_category) {
$subcategory_id = $c_category["s"];
}
$price = 0;
$available_units = 0;
foreach ($product['variants'] as $variant) {
$price = $variant['price'];
$available_units = $available_units + $variant['inventory_quantity'];
}
$product_id = null;
$data_product = [
'name' => $product['title'],
'plu' => $product['handle'],
'bar_code' => null,
'price' => $price,
'available_units' => $available_units,
'max_units_per_order' => 100,
'percentage_discount' => null,
'start_discount' => null,
'limit_discount' => null,
'limit_hour_discount' => null,
'flash_price' => null,
'start_flash_discount' => null,
'limit_flash_discount' => null,
'limit_hour_flash_discount' => null,
'brand_id' => $brand_id,
'order' => 1,
'chkAgeProduct' => false,
'sucursal_id' => $sucursal_id,
'sub_categories' => [$subcategory_id],
'reference_shopify_id' => $product['id'],
'active' => true,
'store_type' => 'main'
];
$cproduct = $product_controller->create($this->newRequest($data_product), false);
if ($cproduct) {
$product_id = $cproduct["d"]["id"];
$this->saveProductImages($product, $cproduct['d']['id']);
}
}
foreach ($product['variants'] as $variant) {
$name_attribute = "Tallas checkbox único";
foreach ($product['options'] as $options) {
foreach ($options['values'] as $option) {
if ($option == $variant['title']) {
$name_attribute = $options['name'];
break;
}
}
}
$attribute_id = null;
$data_attribute = [
"name" => $name_attribute,
"display_name" => $name_attribute,
"is_more_one" => false,
"required" => true,
"attribute_type_id" => 2,
"active" => true,
];
$catrribute = $attribute_controller->store($this->newRequest($data_attribute), false);
if ($catrribute) {
$attribute_id = $catrribute["d"];
}
$data_productAttribute = [
"product_id" => $product_id,
"attribute_id" => $attribute_id,
"value" => $variant['title'],
"price_additional" => 0,
"sku" => $variant['sku'],
"available_units" => $variant['inventory_quantity'],
"pmi" => 0,
"packaging" => 0,
"weight" => 0,
"ean" => 0,
"width" => 0,
"length" => 0,
"high" => 0,
"observation" => 0,
"main_position" => 0,
"stowage_pattern" => 0,
"reference_shopify_variation_id" => $variant['inventory_item_id'],
"reference_shopify_id" => $variant['id'],
];
$productAttribute_controller->store($this->newRequest($data_productAttribute), $product_id, false);
}
}
private function saveProductImages($productShopify, $productId)
{
foreach ($productShopify['images'] as $image) {
$product_controller = new ProductController();
$product_controller->uploadImageFromUrl($image['src'], $image['id'], $productId);
}
}
public function searchProductVariant($data, $variant)
{
$result = array_filter($data, function ($productVariant) use ($variant) {
return $productVariant['id'] == $variant;
}, ARRAY_FILTER_USE_BOTH);
if (count($result)) {
$result = reset($result);
}
return $result;
}
public function saveERPLog($data, $message, $action)
{
$erpLog = new ErpLog();
$erpLog->origin = 'shopify';
$erpLog->action = $action;
$erpLog->origin_class = get_class($this);
$erpLog->data = $data;
$erpLog->message = $message;
$erpLog->save();
}
public function retrySyncERP($data, $action)
{
$this->syncERP(json_decode($data, true), $action);
}
public function syncERP($order, $action = null)
{
$erpSync = ErpParameter::where('key', 'shop_sync')->first();
if (!$erpSync || $erpSync->value == 'false') {
$this->saveERPLog(json_encode($order), 'Sinc ERP deshabilitada', 'syncERP');
return;
}
if (!$this->controllerOrder->validateSyncWithERPPayment($order['id'])) {
return;
}
$previousBill = $this->ERPRepository->getBill($order['order_number']);
if ($previousBill['r'] && count($previousBill['d']->detalle->Table)) {
$this->controllerOrder->confirmSyncERP($order['order_number']);
return;
}
switch ($action) {
case 'createOrder':
$this->createOrderERP($order);
break;
case 'createRC':
$this->createRCERP($order);
break;
case 'createBill':
$this->createBillERP($order);
break;
case 'saveData':
$this->saveData($order);
break;
default:
$this->createThirdClientERP($order);
break;
}
}
private function createThirdClientERP($order)
{
$billingAddress = $order['billing_address'];
$metafieldsResponse = $this->getMetafields($order);
$metafields = count($metafieldsResponse) ? json_decode($metafieldsResponse[0]['value']) : null;
$birthDate = $metafields ? str_replace('-', '/', $metafields->selectedAge) : Carbon::now();
$documentType = $metafields && !empty($metafields->selectedTypeDocument) ? $metafields->selectedTypeDocument : 'O';
$typeCustomer = $metafields && isset($metafields->selectedTypeCustomer) ? $metafields->selectedTypeCustomer : 'persona_natural';
$juridicalPerson = $typeCustomer == 'persona_juridica';
$gender = $metafields ? $metafields->selectedGenero : 'O';
$establishmentName = $metafields && isset($metafields->selectedNombreEstablecimiento) ? $metafields->selectedNombreEstablecimiento : null;
$district = $metafields && isset($metafields->selectedNeighborhood) ? $metafields->selectedNeighborhood : '';
$customerDocument = $this->getBuyerDocument($order);
$birthDate = str_contains($birthDate, '/') ? Carbon::createFromFormat('d/m/Y', $birthDate) : Carbon::parse($birthDate);
$province = $metafields && !empty($metafields->selectedDepartment) ? $metafields->selectedDepartment : $billingAddress['province'];
$city = $metafields && !empty($metafields->selectedCity) ? $metafields->selectedCity : $billingAddress['city'];
$socialReason = $metafields && isset($metafields->selectedRazonSocial) ? $metafields->selectedRazonSocial : null;
$ciiu = $metafields && isset($metafields->selectedCodigoCIIU) ? $metafields->selectedCodigoCIIU : null;
$namePersonContact = $metafields && isset($metafields->selectedPersonaContacto) ? $metafields->selectedPersonaContacto : null;
$nit = $metafields && isset($metafields->selectedNIT) ? $metafields->selectedNIT : null;
$this->updateShopifyMetafield($birthDate->toDateString(), $order, 'fechadecumpleaos_v1');
$this->updateShopifyMetafield($customerDocument, $order, 'numerodedocumento_v1');
$this->updateShopifyMetafield($documentType, $order, 'tipodedocumento_v1');
$this->updateShopifyMetafield($typeCustomer, $order, 'tipodecomprador_v1');
$this->updateShopifyMetafield($province, $order, 'departamento_v1');
$this->updateShopifyMetafield($district, $order, 'barrio_v1');
$this->updateShopifyMetafield($gender, $order, 'genero_v1');
$this->updateShopifyMetafield($city, $order, 'ciudad_v1');
$this->updateShopifyMetafield($establishmentName, $order, 'nombredelestablecimiento_v1');
$this->updateShopifyMetafield($namePersonContact, $order, 'nombredelapersonadecontacto_v1');
$this->updateShopifyMetafield($ciiu, $order, 'codigociiu_v1');
$this->updateShopifyMetafield($nit, $order, 'nit_v1');
$this->updateShopifyMetafield($socialReason, $order, 'razonsocial_v1');
$siesaThirdClient = $this->ERPRepository->thirdClientValidate($customerDocument);
$isHED = $this->isHED($order);
$hasHED = $this->hasHED($order);
$isLocal = $order['currency'] == 'COP';
$params = new \stdClass();
$third = new \stdClass();
$third->document = $customerDocument;
$third->firstName = $billingAddress['first_name'];
$third->lastName = $billingAddress['last_name'];
$third->contact = $juridicalPerson ? $namePersonContact : $billingAddress['name'];
$third->phone = $billingAddress['phone'];
$third->email = $order['customer']['email'];
$third->isNew = count($siesaThirdClient) == 0;
$third->documentType = $this->ERPRepository->mapDocumentType($juridicalPerson ? 'nit' : $documentType);
$third->birthDate = $birthDate->format('Ymd');
$third->typeThird = $typeCustomer;
$third->gender = $this->ERPRepository->mapGender($gender);
$third->socialReason = $juridicalPerson ? $socialReason : $billingAddress['name'];
$third->establishmentName = $establishmentName;
$third->ciiu = $juridicalPerson ? $ciiu : null;
$params->third = $third;
$params->client = $third;
$params->address = $billingAddress['address1'] . ' | ' . $district;
$params->shortAddress = $billingAddress['address1'];
$params->country = $billingAddress['country'];
$params->province = $province;
$params->city = $city;
$params->sucursal = $isLocal ? '001' : '010';
$params->price_list = $isLocal ? '001' : '014';
$params->typeClient = $isHED ? 'CHED' : ($isLocal ? 'CTDS' : 'CTTI');
$params->postal = substr($billingAddress['zip'], 0, 10);
$params->hasTaxes = $isLocal ? '1' : '0';
$params->createThirdPos = !$isHED;
$params->idCriteria = $hasHED ? '105' : null;
$params->criteria = $hasHED ? '1051' : null;
$params->currency = $order['currency'];
$response = $this->ERPRepository->createThirdClient($params);
if (!$response['r']) {
$this->saveERPLog(json_encode($order), json_encode($response['d']), 'createThirdClient');
return;
}
$this->createOrderERP($order);
}
public function isHED($order)
{
foreach ($order['line_items'] as $index => $item) {
$variant = $this->getShopifyVariant(null, null, 1, $item['variant_id'], $order['currency']);
if (!$variant || $variant['barcode'] != '1104424520023') {
return false;
}
}
return true;
}
public function hasHED($order)
{
foreach ($order['line_items'] as $index => $item) {
$variant = $this->getShopifyVariant(null, null, 1, $item['variant_id'], $order['currency']);
if ($variant && $variant['barcode'] == '1104424520023') {
return true;
}
}
return false;
}
private function createOrderERP($order)
{
$successTransaction = $this->getSuccessTransaction($order);
if (!$successTransaction) {
$this->saveERPLog(json_encode($order), 'La orden no tiene transacciones exitosas', 'createOrder');
return;
}
$response = $this->ERPRepository->getOrder($order['order_number']);
if ($response['r']) {
$previousOrders = array_filter($response['d']->detalle->Table, function ($siesaOrder) use ($order, $successTransaction) {
return str_contains($siesaOrder->Notas, $order['checkout_id']) ||
str_contains($siesaOrder->Notas, $successTransaction['payment_id']);
}, ARRAY_FILTER_USE_BOTH);
if (count($previousOrders)) {
$this->createRCERP($order);
return;
}
}
$response = $this->ERPRepository->createOrderShop($order, $this);
if (!$response['r']) {
$this->saveERPLog(json_encode($order), json_encode($response['d']), 'createOrder');
return;
}
$this->syncInventoryERPFromOrder($order);
$this->createRCERP($order);
}
private function createRCERP($order)
{
$response = $this->ERPRepository->getOrder($order['order_number']);
if (!$response['r']) {
$this->saveERPLog(json_encode($order), json_encode($response['d']), 'createRC');
return;
}
$successTransaction = $this->getSuccessTransaction($order);
$isHED = $this->isHED($order);
$isLocal = $order['currency'] == 'COP';
$prefixNote = $isHED ? 'HED - ' : '';
foreach ($response['d']->detalle->Table as $index => $siesaOrder) {
$response = $this->ERPRepository->getRC($this->getBuyerDocument($order), $siesaOrder->CentroDeOperacion);
if ($response['r']) {
$previousRC = array_filter($response['d']->detalle->Table, function ($item) use ($order) {
return str_contains($item->Notas, $order['order_number']);
}, ARRAY_FILTER_USE_BOTH);
if (count($previousRC)) {
$this->createBillERP($order);
continue;
}
}
$parameters = new \stdClass();
$parameters->paymentDate = Carbon::parse($order['created_at'])->format('Ymd');
$parameters->idThird = $this->getBuyerDocument($order);
$parameters->currency = $order['currency'];
$parameters->siesaOrder = $siesaOrder;
$parameters->fe = '1104';
$parameters->note = $prefixNote . 'Número de pedido:' . $order['order_number'] . ' - IDPAGO:' . $successTransaction['payment_id'];
$parameters->assistant = $isHED ? '28050507' : ($isLocal ? '28050506' : '28050508');
$parameters->sucursal = $isLocal ? '001' : '010';
$parameters->paymetMethod = $isLocal ? 'PYV' : 'PYV';
$parameters->UN = $isHED ? '104' : '102';
$parameters->price = round($order['total_price']);
$response = $this->ERPRepository->createRC($parameters);
if (!$response['r']) {
$this->saveERPLog(json_encode($order), json_encode($response['d']), 'createRC');
return;
}
}
$this->createBillERP($order);
}
private function createBillERP($order)
{
$previousBill = $this->ERPRepository->getBill($order['order_number']);
if ($previousBill['r'] && count($previousBill['d']->detalle->Table)) {
return;
}
$response = $this->ERPRepository->getOrder($order['order_number']);
if (!$response['r']) {
$this->saveERPLog(json_encode($order), json_encode($response['d']), 'createBill');
return;
}
$thirdDocument = $this->getBuyerDocument($order);
foreach ($response['d']->detalle->Table as $index => $siesaOrder) {
$parameters = new \stdClass();
$parameters->siesaOrder = $siesaOrder;
$parameters->thirdDocument = $thirdDocument;
$parameters->note = $order['order_number'];
$parameters->price = $order['total_price'];
$parameters->typeDocument = $order['currency'] == 'COP' ? 'FE1' : 'FE2';
$response = $this->ERPRepository->createBill($parameters);
if (!$response['r']) {
$this->saveERPLog(json_encode($order), json_encode($response['d']), 'createBill');
return;
}
}
$this->controllerOrder->confirmSyncERP($order['order_number']);
}
private function syncInventoryERPFromOrder($order)
{
foreach ($order['line_items'] as $index => $product) {
$variant = $this->getShopifyVariant(null, null, 1, $product['variant_id'], $order['currency']);
if ($variant && $variant['barcode']) {
$integrationProviders = IntegrationProvider::where([['ecommerce_type_id', 3], ['active', true]])->get();
foreach ($integrationProviders as $integrationProvider) {
$this->syncInventoryERP($integrationProvider->currency, $variant['barcode']);
}
}
}
}
private function syncInventoryERP($currency, $barcode = null)
{
$erpSync = ErpParameter::where('key', 'shop_sync')->first();
if (!config('erp_siesa.sync_inventory') || !$erpSync || $erpSync->value == 'false') {
return;
}
$priceList = $currency == 'COP' ? '001' : '014';
$locationNames = ['BDHED','TI108'];
foreach ($locationNames as $index => $locationName) {
$siesaInventory = $this->inventoryController->syncInventoryERP(
$priceList,
'main',
true,
$this,
$locationName,
$currency,
$barcode
);
if (!$barcode) {
$this->syncInventoryWithOutStock(1, $siesaInventory, $locationName, $currency);
}
}
}
public function syncProductByReference($item, $location, $currency)
{
$variant = $this->getShopifyVariant($item->CodigoDeBarras, null, 1, null, $currency);
if ($variant) {
$this->updateInventoryFromVariant($variant, $item->Existencias, $location, $currency);
return;
}
$data_variant = array(
"option1" => $item->Talla ?? 'ÚNICA',
"option2" => $item->Color ?? 'ÚNICO',
"price" => $item->Precio,
"barcode" => $item->CodigoDeBarras,
"inventory_management" => "shopify",
);
$product = $this->getShopifyVariant(null, $item->Referencia, 1, null, $currency);
if ($product) {
$variant = $this->createVariant($product['product_id'], array("variant" => $data_variant), $currency);
$this->updateInventoryFromVariant($variant, $item->Existencias, $location, $currency);
return;
}
$data_sho = array("product" => array(
"title" => $item->Descripcion,
"vendor" => $item->Marca,
"product_type" => $item->Linea,
"status" => "draft",
"variants" => [
$data_variant
],
"options" => [
array(
"name" => "Tamaño",
"position" => 1
),
array(
"name" => "Color",
"position" => 2
),
]
));
$shopifyProduct = $this->createProduct($data_sho, $currency);
if ($shopifyProduct) {
$this->updateInventoryFromVariant($shopifyProduct['variants'][0], $item->Existencias, $location, $currency);
}
}
private function updateInventoryFromVariant($variant, $stock, $location, $currency)
{
if ($variant) {
$reference_shopify_variation_id = $variant['inventory_item_id'];
$this->updateInventoryLevel($reference_shopify_variation_id, $stock, $location, $currency);
}
}
private function getShopifyVariant($barcode, $reference, $sinceId = 1, $variantId = null, $currency)
{
try {
$content = $this->httpRequest(
'GET',
'variants' . ($variantId ? '/' . $variantId : '') . '.json?limit=250&since_id=' . $sinceId,
$currency
);
if ($variantId) {
return $content['variant'];
}
$variants = $content["variants"];
$result = array_filter($variants, function ($productVariant) use ($barcode, $reference) {
if ($barcode) {
return $productVariant['barcode'] == $barcode;
} else {
$productReference = substr($productVariant['barcode'], 0, 5) . substr($productVariant['barcode'], -4);
return $productReference == $reference;
}
}, ARRAY_FILTER_USE_BOTH);
if (count($result)) {
return reset($result);
}
if (count($variants)) {
return $this->getShopifyVariant($barcode, $reference, end($variants)['id'], $variantId, $currency);
}
return null;
} catch (Exception $exception) {
return null;
}
}
function syncInventoryWithOutStock($sinceId = 1, $siesaInventory, $location, $currency)
{
$variants = $this->httpRequest('GET', 'variants.json?limit=250&since_id=' . $sinceId, $currency)["variants"];
foreach ($variants as $index => $item) {
if (!$item['barcode']) {
continue;
}
$siesaProducts = array_filter($siesaInventory, function ($productVariant) use ($item) {
return $productVariant->CodigoDeBarras == $item['barcode'];
}, ARRAY_FILTER_USE_BOTH);
if (!count($siesaProducts)) {
$this->updateInventoryFromVariant($item, 0, $location, $currency);
}
}
if (count($variants)) {
return $this->syncInventoryWithOutStock(end($variants)['id'], $siesaInventory, $location, $currency);
}
}
//-----------------------------------------------END_weebhook-------------------------------------------------------
}