Viewing File: /home/ubuntu/vedadeals-backend-base/app/Http/Controllers/Api/OrderApiController.php

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;

use Illuminate\Http\Request;

use App\Helpers\Helper;

use DB, Exception, Setting, stdClass, Storage;

use Carbon\Carbon;

use App\Models\{ User, Order, UserWallet, UserCard, Product, OrderProduct, Cart, OrderPayment, OrderTracking };

use Illuminate\Validation\Rule;

use App\Http\Resources\{ OrderResource, ProductResource, OrderPaymentPreviewResource };

use Illuminate\Support\Facades\Cache;

use App\Services\{ PaymentService, OrderService, ProductService, EmailService };

use Barryvdh\DomPDF\Facade\Pdf;

use App\Jobs\{ SendInvoiceEmailJob, OrderNotificationJob };

class OrderApiController extends Controller
{
    protected $loginUser;

    protected $skip, $take;

    public function __construct(Request $request) {

        info(url()->current());

        info("Request Data".print_r($request->all(), true));
        
        $this->loginUser = User::find($request->id);

        $this->skip = $request->skip ?: 0;

        $this->take = $request->take ?: (Setting::get('admin_take_count') ?: TAKE_COUNT);

        $this->timezone = $this->loginUser->timezone ?? "America/New_York";

        $request->request->add(['timezone' => $this->timezone ? : "America/New_York"]);

    }

    /**
     * @method orders_direct_checkout()
     *
     * @uses to complete the order process by cart checkout type.
     *
     * @created Karthick
     *
     * @updated 
     *
     * @param
     * 
     * @return success / failure message
     */
    public function orders_direct_checkout(Request $request) {

        try {

            $rules = [ 
                'product_id' => ['required', 'exists:products,id'],
                'quantity' => ['required', 'numeric', "min:1"],
                'delivery_address_id' => ['required', 'exists:delivery_addresses,id,user_id,'.$request->id],
                'payment_mode' => ['required', Rule::in(PAYMENT_MODE_WALLET, PAYMENT_MODE_CARD)],
                'user_card_id' => [Rule::requiredIf($request->payment_mode == PAYMENT_MODE_CARD), 'exists:user_cards,id,user_id,'.$request->id],
            ];

            $custom_errors = [
                'product_id.exists' => api_error(1009, strtolower(tr('product'))),
                'delivery_address_id.exists' => api_error(123),
            ];

            Helper::custom_validator($request->all(), $rules, $custom_errors);

            $checkout_data = new stdClass();

            $checkout_data->payment_mode = $request->payment_mode; $checkout_data->quantity = $request->quantity;

            $checkout_data->user_id = $request->id; $checkout_data->product_id = $request->product_id;

            $checkout_data->user_card_id = $request->user_card_id ? : 0; $checkout_data->delivery_address_id = $request->delivery_address_id;

            if($request->payment_mode == PAYMENT_MODE_WALLET) {

                $result = OrderService::handle_direct_checkout($checkout_data);

            } elseif($request->payment_mode == PAYMENT_MODE_CARD) {

                $user_card = UserCard::firstWhere(['id' => $request->user_card_id, 'user_id' => $request->id]);

                if(!$user_card) {

                    throw new Exception(api_error(125), 125);
                }

                $result = OrderService::handle_direct_checkout($checkout_data);

            }

            if(!$result['result']) {

                throw new Exception($result['message']);
            }

            $data['order_unique_id'] = $result['order_unique_id'];

            EmailService::order_status_email($data['order_unique_id']);

            return $this->sendResponse(api_success(144), 144, $data);

        } catch (Exception $e) {

            return $this->sendError($e->getMessage(), $e->getCode());
        }
    }

    /**
     * @method orders_cart_checkout()
     *
     * @uses to complete the order process by direct checkout type.
     *
     * @created Karthick
     *
     * @updated 
     *
     * @param
     * 
     * @return success / failure message
     */
    public function orders_cart_checkout(Request $request) {

        try {

            $rules = [ 
                'delivery_address_id' => ['required', 'exists:delivery_addresses,id,user_id,'.$request->id],
                'payment_mode' => ['required', Rule::in(PAYMENT_MODE_WALLET, PAYMENT_MODE_CARD, PAYMENT_MODE_UPI, PAYMENT_MODE_COD)],
                'user_card_id' => [Rule::requiredIf($request->payment_mode == PAYMENT_MODE_CARD), 'exists:user_cards,id,user_id,'.$request->id],
                'payment_id' => [Rule::requiredIf($request->payment_mode == PAYMENT_MODE_UPI), 'unique:order_payments,payment_id'],
            ];

            $custom_errors = [ 'delivery_address_id.exists' => api_error(123) ];

            Helper::custom_validator($request->all(), $rules, $custom_errors);

            $checkout_data = new stdClass();

            $checkout_data->payment_mode = $request->payment_mode; $checkout_data->quantity = $request->quantity;

            $checkout_data->user_id = $request->id; $checkout_data->product_id = $request->product_id;

            $checkout_data->user_card_id = $request->user_card_id ? : 0; $checkout_data->delivery_address_id = $request->delivery_address_id;

            $checkout_data->payment_id = $request->payment_id ?? "";

            if($request->payment_mode == PAYMENT_MODE_CARD) {

                $user_card = UserCard::firstWhere(['id' => $request->user_card_id, 'user_id' => $request->id]);

                if(!$user_card) {

                    throw new Exception(api_error(125), 125);
                }
            }

            $result = OrderService::handle_cart_checkout($checkout_data); 

            if(!$result['result']) {

                throw new Exception($result['message']);
            }

            $data['order_unique_id'] = $result['order_unique_id'];

            EmailService::order_status_email($data['order_unique_id']);

            return $this->sendResponse(api_success(144), 144, $data);

        } catch (Exception $e) {

            return $this->sendError($e->getMessage(), $e->getCode());
        }
    }

    /**
     * @method orders_list()
     *
     * @uses to get all the orders list of an user
     *
     * @created Karthick
     *
     * @updated 
     *
     * @param 
     * 
     * @return
     */
    public function orders_list(Request $request) {

        try {

            $rules = [
                'status' => ['nullable', Rule::in(ORDER_RECEIVED, ORDER_AWAITING_PICKUP, ORDER_AWAITING_SHIPMENT, ORDER_SHIPPED, ORDER_COMPLETED, ORDER_CANCELLED, ORDER_RETURN_INITIATED, ORDER_RETURN_REJECTED, ORDER_RETURN_ACCEPTED, ORDER_RETURN_USER_DAMAGE, ORDER_RETURN_SUCCESS, ORDER_REFUND_INITIATED, ORDER_REFUND_SUCCESS, ORDER_REFUND_FAILED)],
                'order_status' => ['nullable', Rule::in(ORDER_STATUS_PENDING, ORDER_STATUS_CANCELLED, ORDER_STATUS_RETURNED, ORDER_STATUS_COMPLETED)]
            ];

            Helper::custom_validator($request->all(), $rules, $custom_errors = []);

            $base_query = Order::where(['user_id' => $request->id])
                        ->with(['deliveryAddress', 'orderProducts', 'orderProducts.product.category'])
                        ->with(['orderProducts.product' => fn($query) => $query->withTrashed()])
                        ->withSum('orderProducts', 'discount_price')
                        ->withSum('orderProducts', 'total')
                        ->orderBy('updated_at', 'desc');

            if($request->filled('status')) {

                $base_query = $base_query->where('status', $request->status);
            }

            if($request->filled('order_status')) {

                $base_query = $base_query->where('order_status', $request->order_status);
            }

            $data['total_orders'] = $base_query->count();

            $orders = $base_query->skip($this->skip)->take($this->take)->get();

            $data['orders'] = OrderResource::collection($orders);

            return $this->sendResponse("", "", $data);

        } catch (Exception $e) {

            return $this->sendError($e->getMessage(), $e->getCode());
        }
    }

    /**
     * @method orders_view()
     *
     * @uses to view a order details based on order_unique_id
     *
     * @created Karthick
     *
     * @updated 
     *
     * @param 
     * 
     * @return
     */
    public function orders_view(Request $request) {

        try {

            $rules = [ 'order_unique_id' => ['required', 'exists:orders,unique_id,user_id,'.$request->id] ];

            $custom_errors = ['exists' => api_error(1009, strtolower(tr('order')))];

            Helper::custom_validator($request->all(), $rules, $custom_errors);

            $order = Order::with(['deliveryAddress', 'orderPayment', 'orderProducts', 'orderProducts.product.category', 'orderTracking'])
                    ->with(['orderProducts.product' => fn($query) => $query->withTrashed()])
                    ->firstWhere(['unique_id' => $request->order_unique_id, 'user_id' => $request->id]);

            if(!$order) {

                throw new Exception(api_error(1009, strtolower(tr('order'))));
            }

            $data['order'] = new OrderResource($order);

            return $this->sendResponse("", "", $data);

        } catch (Exception $e) {

            return $this->sendError($e->getMessage(), $e->getCode());
        }
    }

    /**
     * @method orders_cancel()
     *
     * @uses to cancel a order
     *
     * @created Karthick
     *
     * @updated 
     *
     * @param order_unique_id
     * 
     * @return
     */
    public function orders_cancel(Request $request) {

        try {

            $rules = [ 
                'order_unique_id' => ['required', 'exists:orders,unique_id,user_id,'.$request->id],
                'cancelled_reason' => 'nullable',
            ];

            $custom_errors = ['exists' => api_error(1009, strtolower(tr('order')))];

            Helper::custom_validator($request->all(), $rules, $custom_errors);

            $order = Order::firstWhere('unique_id', $request->order_unique_id);

            if(!$order) {

                throw new Exception(api_error(1009, strtolower(tr('order'))));
            }

            if($order->is_cancelled == YES && $order->status == ORDER_REFUND_INITIATED) {

                throw new Exception(api_error(135), 135);
            }

            if($order->status == ORDER_COMPLETED) {

                throw new Exception(api_error(134), 134);
            }

            $order_payment = OrderPayment::firstWhere(['order_id' => $order->id]);

            DB::beginTransaction();

            $order_result = $order->update(['is_cancelled' => YES, 'cancelled_reason' => $request->cancelled_reason ? : '', 'status' => ORDER_REFUND_INITIATED, 'order_status' => ORDER_STATUS_CANCELLED]);

            $order_payment_result = $order_payment->update(['is_cancelled' => YES, 'cancelled_reason' => $request->cancelled_reason ? : '', 'cancelled_at' => now(), 'status' => CANCELLED]);

            if(!$order_result || !$order_payment_result) {

                throw new Exception(api_error(133), 133);
            }

            $order_products = OrderProduct::where(['order_id' => $order->id])->get(['product_id', 'quantity']);

            foreach($order_products as $order_product) {

                $update_product_inventory = ProductService::update_product_inventory($order_product->product_id, $order_product->quantity, PRODUCT_CANCELLED);
            }

            $amount = $order_payment->total;

            $payment_data = new stdClass;

            $payment_data->user_id = $request->id; $payment_data->amount = $amount;

            $payment_data->amount_type = AMOUNT_TYPE_ADD; $payment_data->payment_type = WALLET_PAYMENT_TYPE_REFUND;

            $payment_data->payment_mode = PAYMENT_MODE_WALLET; $payment_data->user_billing_account_id = 0;

            $user_wallet_payment = PaymentService::user_wallet_payment_save($payment_data);

            if(!$user_wallet_payment['result']) {

                throw new Exception($user_wallet_payment['message']);
            }

            $user_wallet = UserWallet::firstOrCreate(['user_id' => $request->id]);

            $user_wallet->remaining += $amount;

            $user_wallet->total = $order_payment->payment_mode == PAYMENT_MODE_CARD ? $user_wallet->total + $amount : $user_wallet->total;

            $user_wallet->used = $order_payment->payment_mode == PAYMENT_MODE_WALLET ? $user_wallet->used - $amount : $user_wallet->used;

            $result = $user_wallet->save();

            if(!$result) {

                throw new Exception(api_error(133), 133);
            }

            DB::commit();

            EmailService::order_status_email($order->order_unique_id);

            return $this->sendResponse(api_success(150, formatted_amount($amount)), 150, []);

            throw new Exception(api_error(104), 104);

        } catch (Exception $e) {

            DB::rollback();

            return $this->sendError($e->getMessage(), $e->getCode());
        }
    }

    /**
     * @method orders_invoice()
     *
     * @uses to download or get order invoice via email or download directly.
     *
     * @created Karthick
     *
     * @updated 
     *
     * @param order_unique_id
     * 
     * @return order payment invoice pdf
     */
    public function orders_invoice(Request $request) {

        try {

            $rules = [ 
                'order_unique_id' => ['required', 'exists:orders,unique_id,user_id,'.$request->id],
                'invoice_via' => Rule::in(VIA_EMAIL, VIA_DOWNLOAD)
            ];

            $custom_errors = ['exists' => api_error(1009, strtolower(tr('order')))];

            Helper::custom_validator($request->all(), $rules, $custom_errors);

            $order = Order::with(['deliveryAddress:id,address,city,state,pincode', 'orderPayment:id,order_id,unique_id,paid_date,total,payment_mode,payment_id', 'orderProducts:id,order_id,product_id,quantity,total', 'orderProducts.product:id,name'])
                    ->firstWhere(['unique_id' => $request->order_unique_id, 'user_id' => $request->id]);

            if(!$order) {

                throw new Exception(api_error(1009, strtolower(tr('order'))));
            }

            if($request->invoice_via == VIA_DOWNLOAD) {

                $data['order'] = $order;

                $data['timezone'] = $this->timezone;

                $data['url'] = Setting::get('frontend_url').'orders/tracking/'.$request->order_unique_id;

                $pdf = Pdf::loadView('pdf.invoice', $data)->setPaper('a4');

                return $pdf->download("$order->unique_id.pdf");

            } else {

                EmailService::send_order_invoice_email($order);

                return $this->sendResponse(api_success(151), 150, []);
            }

            throw new Exception(api_error(104), 104);

        } catch (Exception $e) {

            DB::rollback();

            return $this->sendError($e->getMessage(), $e->getCode());
        }
    }

    /**
     * @method orders_checkout()
     *
     * @uses to complete the order process.
     *
     * @created Karthick
     *
     * @updated 
     *
     * @param
     * 
     * @return success / failure message
     */
    public function orders_checkout(Request $request) {

        try {

            $rules = [ 
                'delivery_address_id' => ['required', 'exists:delivery_addresses,id,user_id,'.$request->id],
                'payment_mode' => ['required', Rule::in(PAYMENT_MODE_CRYPTO, PAYMENT_MODE_ADMIN)],
                'transaction_hash' => [Rule::requiredIf($request->payment_mode == PAYMENT_MODE_CRYPTO)],
                'currency' => [Rule::requiredIf($request->payment_mode == PAYMENT_MODE_CRYPTO)],
                'wallet_address' => [Rule::requiredIf($request->payment_mode == PAYMENT_MODE_CRYPTO)]
            ];

            $custom_errors = [ 'delivery_address_id.exists' => api_error(123) ];

            Helper::custom_validator($request->all(), $rules, $custom_errors);

            $checkout_data = new stdClass();

            $checkout_data->payment_mode = $request->payment_mode; $checkout_data->user_id = $request->id;

            $checkout_data->delivery_address_id = $request->delivery_address_id; $checkout_data->transaction_hash = $request->transaction_hash ? : null;

            $checkout_data->currency = $request->currency ? : Setting::get('currency');

            $checkout_data->wallet_address = $request->wallet_address ? : null;

            $result = OrderService::handle_checkout($checkout_data); 

            if(!$result['result']) {

                throw new Exception($result['message']);
            }

            $data['order_unique_id'] = $result['order_unique_id'];

            OrderNotificationJob::dispatch($data['order_unique_id']);

            EmailService::new_order_email_to_admin($data['order_unique_id']);

            return $this->sendResponse(api_success(144), 144, $data);

        } catch (Exception $e) {

            return $this->sendError($e->getMessage(), $e->getCode());
        }
    }

    /**
     * @method order_payments_list()
     *
     * @uses to get all the order payments list of an user
     *
     * @created Karthick
     *
     * @updated 
     *
     * @param 
     * 
     * @return
     */
    public function order_payments_list(Request $request) {

        try {

            $base_query = OrderPayment::with(['order:id,unique_id'])->where(['user_id' => $request->id])->orderBy('updated_at', 'desc');

            $data['total_order_payments'] = $base_query->count();

            $order_payments = $base_query->skip($this->skip)->take($this->take)->get();

            $data['order_payments'] = OrderPaymentPreviewResource::collection($order_payments);

            return $this->sendResponse("", "", $data);

        } catch (Exception $e) {

            return $this->sendError($e->getMessage(), $e->getCode());
        }
    }

    /**
     * @method orders_send_cancel_request()
     *
     * @uses to cancel a order
     *
     * @created Karthick
     *
     * @updated 
     *
     * @param order_unique_id
     * 
     * @return
     */
    public function orders_send_cancel_request(Request $request) {

        try {

            $rules = [ 
                'order_unique_id' => ['required', 'exists:orders,unique_id,user_id,'.$request->id],
                'cancelled_reason' => 'nullable',
            ];

            $custom_errors = ['exists' => api_error(1009, strtolower(tr('order')))];

            Helper::custom_validator($request->all(), $rules, $custom_errors);

            $order = Order::with(['deliveryAddress', 'orderPayment', 'orderProducts', 'orderProducts.product', 'orderProducts.product.category', 'orderTracking'])
                    ->firstWhere(['unique_id' => $request->order_unique_id, 'user_id' => $request->id]);

            if(!$order) {

                throw new Exception(api_error(1009, strtolower(tr('order'))));
            }

            $data['order'] = new OrderResource($order);

            if(!$order) {

                throw new Exception(api_error(1009, strtolower(tr('order'))));
            }

            if($order->is_cancelled == YES && $order->order_status == ORDER_STATUS_CANCELLED) {

                throw new Exception(api_error(135), 135);
            }

            if($order->status == ORDER_COMPLETED) {

                throw new Exception(api_error(134), 134);
            }

            $order_payment = OrderPayment::firstWhere(['order_id' => $order->id]);

            $amount = $order_payment->total;

            $order_tracking = OrderTracking::firstWhere(['order_id' => $order->id, 'user_id' => $order->user_id]);

            DB::beginTransaction();

            $now = now();

            $order_result = $order->update(['is_cancelled' => YES, 'order_status' => ORDER_STATUS_CANCELLED, 'cancelled_reason' => $request->cancelled_reason ? : '', 'status' => ORDER_REFUND_INITIATED]);

            $order_payment_result = $order_payment->update(['is_cancelled' => YES, 'cancelled_reason' => $request->cancelled_reason ? : '', 'cancelled_at' => $now, 'status' => CANCELLED]);

            $order_tracking_result = $order_tracking->update(['cancelled_at' => $now, 'refund_initiated_at' => $now, 'status' => ORDER_REFUND_INITIATED]);

            if(!$order_result || !$order_payment_result && !$order_tracking_result) {

                throw new Exception(api_error(133), 133);
            }

            $order_products = OrderProduct::where(['order_id' => $order->id])->get(['product_id', 'quantity']);

            foreach($order_products as $order_product) {

                $update_product_inventory = ProductService::update_product_inventory($order_product->product_id, $order_product->quantity, PRODUCT_CANCELLED);
            }

            DB::commit();

            OrderNotificationJob::dispatch($order->order_unique_id);

            $data['order'] = new OrderResource($order->refresh());

            return $this->sendResponse(api_success(150, formatted_amount($amount)), 150, $data);

            throw new Exception(api_error(104), 104);

        } catch (Exception $e) {

            DB::rollback();

            return $this->sendError($e->getMessage(), $e->getCode());
        }
    }

    /**
     * @method orders_send_return_request()
     *
     * @uses to send return order request
     *
     * @created Karthick
     *
     * @updated 
     *
     * @param order_unique_id
     * 
     * @return
     */
    public function orders_send_return_request(Request $request) {

        try {

            $rules = [ 
                'order_unique_id' => ['required', 'exists:orders,unique_id,user_id,'.$request->id],
                'cancelled_reason' => 'required',
            ];

            $custom_errors = [
                'exists' => api_error(1009, strtolower(tr('order'))),
                'cancelled_reason.required' => api_error(141)
            ];

            Helper::custom_validator($request->all(), $rules, $custom_errors);

            $order = Order::with(['deliveryAddress', 'orderPayment', 'orderProducts', 'orderProducts.product', 'orderProducts.product.category', 'orderTracking'])
                    ->firstWhere(['unique_id' => $request->order_unique_id, 'user_id' => $request->id]);

            if(!$order) {

                throw new Exception(api_error(1009, strtolower(tr('order'))));
            }

            if($order->order_status == ORDER_STATUS_RETURNED) {

                if($order->status == ORDER_RETURN_REJECTED) {

                    throw new Exception(api_error(142), 142);
                }

                if($order->status == ORDER_RETURN_USER_DAMAGE) {

                    throw new Exception(api_error(143), 143);
                }

                throw new Exception(api_error(140), 140);
            }

            $order_tracking = OrderTracking::firstWhere(['order_id' => $order->id, 'user_id' => $order->user_id]);

            DB::beginTransaction();

            $now = now();

            $order_result = $order->update(['is_cancelled' => YES, 'order_status' => ORDER_STATUS_RETURNED, 'cancelled_reason' => $request->cancelled_reason ? : '', 'status' => ORDER_RETURN_INITIATED]);

            $order_tracking_result = $order_tracking->update(['return_initiated_at' => $now, 'status' => ORDER_RETURN_INITIATED]);

            if(!$order_result || !$order_tracking_result) {

                throw new Exception(api_error(133), 133);
            }

            DB::commit();

            OrderNotificationJob::dispatch($order->order_unique_id);

            $data['order'] = new OrderResource($order->refresh());

            return $this->sendResponse(api_success(153), 153, $data);

            throw new Exception(api_error(104), 104);

        } catch (Exception $e) {

            DB::rollback();

            return $this->sendError($e->getMessage(), $e->getCode());
        }
    }

    /**
     * @method orders_invoice_download()
     *
     * @uses to store the invoice file in storage.
     *
     * @created Karthick
     *
     * @updated 
     *
     * @param order_unique_id
     * 
     * @return order payment invoice pdf
     */
    public function orders_invoice_download(Request $request) {

        try {

            $rules = [ 
                'order_unique_id' => ['required', 'exists:orders,unique_id,user_id,'.$request->id]
            ];

            $custom_errors = ['exists' => api_error(1009, strtolower(tr('order')))];

            Helper::custom_validator($request->all(), $rules, $custom_errors);

            $order = Order::with(['deliveryAddress:id,address,city,state,pincode', 'orderPayment:id,order_id,unique_id,paid_date,total,payment_mode,payment_id', 'orderProducts:id,order_id,product_id,quantity,total', 'orderProducts.product:id,name'])
                    ->firstWhere(['unique_id' => $request->order_unique_id, 'user_id' => $request->id]);

            if(!$order) {

                throw new Exception(api_error(1009, strtolower(tr('order'))));
            }

            $invoice_location = ORDER_INVOICE_PATH."$order->unique_id.pdf";

            $invoice['url'] = Storage::disk('public')->url($invoice_location);

            if(Storage::disk('public')->exists($invoice_location)) {

                return $this->sendResponse('', '' , $invoice);
            }

            $data['order'] = $order;

            $data['timezone'] = $this->timezone;

            $data['url'] = Setting::get('frontend_url').'orders/tracking/'.$request->order_unique_id;

            $output = Pdf::loadView('pdf.invoice', $data)->setPaper('a4')->output();

            Storage::disk('public')->put($invoice_location, $output);

            return $this->sendResponse('', '' , $invoice);

        } catch (Exception $e) {

            DB::rollback();

            return $this->sendError($e->getMessage(), $e->getCode());
        }
    }
}
Back to Directory File Manager