HEX
Server: LiteSpeed
System: Linux s917.lon1.mysecurecloudhost.com 4.18.0-477.21.1.lve.1.el8.x86_64 #1 SMP Tue Sep 5 23:08:35 UTC 2023 x86_64
User: assibfaf (3034)
PHP: 7.4.33
Disabled: NONE
Upload Files
File: /home/assibfaf/public_html/prox-controllers/Api/Orders.php
<?php
/**
 * @package    Proxim
 * @author     Davison Pro <davisonpro.coder@gmail.com | https://davisonpro.dev>
 * @copyright  2019 Proxim
 * @version    1.0.0
 * @since      File available since Release 1.0.0
 */

namespace Proxim\Api;

use Db;
use Exception;
use Proxim\Database\DbQuery;
use Proxim\Configuration;
use Proxim\Notification;
use Proxim\Currency;
use Proxim\User\Customer;
use Proxim\User\Employee;
use Proxim\Order\Order;
use Proxim\Order\AdditionalService;
use Proxim\Order\Meta;
use Proxim\Order\Rating as OrderRating;
use Proxim\Order\File;
use Proxim\Order\Rating;
use Proxim\Order\OrderMessage;
use Proxim\Coupon;
use Proxim\Mail;
use Proxim\PriceCalculator;
use Proxim\Application;
use Proxim\Tools;
use Proxim\Validate;
use Proxim\Route;
use Proxim\Util\ArrayUtils;
use Proxim\Util\DateUtils;
use Proxim\Crypto\Hashing;
use Proxim\Hook;
use Proxim\Module\Module;
use Proxim\Module\PaymentModule;
use Proxim\Preference\Deadline;
use Proxim\Preference\Discipline;
use Proxim\Preference\PaperFormat;
use Proxim\Preference\PaperType;
use Proxim\Presenter\Order\OrderPresenter;
use Proxim\User\Wallet;

class Orders extends Route {

    public function create() {
        global $globals;
        $app = $this->app;
		$payload = $app->request->post();
        $user = $app->container->user;

        /** Existinf Order ID */
        $fid = (int) ArrayUtils::get($payload, 'fid');
        $form_type = ArrayUtils::get($payload, 'formType');
        $form_type_id = (int) ArrayUtils::get($payload, 'form_type_id');

        /** Customer GMT */
        $gmt = (int) ArrayUtils::get($payload, 'gmt');
        /** Validate existing phone */
        $validatePhone = (bool) ArrayUtils::get($payload, 'doValidateExistPhone');

        /** Order */
        $order_type = ArrayUtils::get($payload, 'orderType');
        $trackingId = ArrayUtils::get($payload, 'trackingId');
        if($trackingId && Tools::strlen($trackingId) < 3) {
            return $app->response([
                "success" => false,
                "errors" => [
                    "The tracking ID must be at least 3 characters long. Please try another"
                ]
            ]);
        }

        $toptitle = ArrayUtils::get($payload, 'toptitle');
        if (!$toptitle) {
			return $app->response([
                "success" => false,
            ]);
        }

        $academic_level_id = ArrayUtils::get($payload, 'academiclevel');
        if ( !$academic_level_id ) {
			return $app->response([
                "success" => false,
            ]);
        }

        /** Writer Category */
        $writer_cat_id = (int) ArrayUtils::get($payload, 'writerCategoryId');
        $writerPreferences = ArrayUtils::get($globals, 'writerPreferences');

        $writer_percent = 0;
        if (ArrayUtils::has($writerPreferences, $writer_cat_id)) {
            $writer_preference = ArrayUtils::get($writerPreferences, $writer_cat_id);
            $writer_percent = ArrayUtils::has($writer_preference, 'percent') ? (int) ArrayUtils::get($writer_preference, 'percent') : 0;
        }

        /** Pages / Charts / Slides */
        $charts = (int) ArrayUtils::get($payload, 'chartsreq');
        $pages = (int) ArrayUtils::get($payload, 'pagesreq');
        $slides = (int) ArrayUtils::get($payload, 'slidesreq');
        $min_sources = (int) ArrayUtils::get($payload, 'minSource');

        // @todo both pages, charts, and slides can't be zero
		if ( $pages == 0 && $slides == 0 && $charts == 0) {
			return $app->response([
                "success" => false,
                "errors" => [
                    "You need to order at least 1 page or 1 slide or 1 chart"
                ]
            ]);
		}

        /** Spacing */
        $spacing = ArrayUtils::get($payload, 'spacing');
        if ( !$spacing || !in_array($spacing, array(Order::SPACING_SINGLE, Order::SPACING_DOUBLE)) ) {
			return $app->response([
                "success" => false,
            ]);
        }

        /** Topic category */
        $topic_cat_id = (int) ArrayUtils::get($payload, 'topcatId');

        $isComplexAssignment = false;
		if ( $topic_cat_id == 52 ) {
			$topic_cat_option = ArrayUtils::get($payload, 'topcatOption');
		} else {
            $discipline = new Discipline( $topic_cat_id );
            if(!Validate::isLoadedObject($discipline)) {
                return $app->response([
                    "success" => false,
                ]);
            }

            $topic_cat_option = $discipline->title;
            $isComplexAssignment = $discipline->is_complex_assignment;
		}

        /** Paper Type */
        $paper_type_id = (int) ArrayUtils::get($payload, 'paperTypeId');

        if ( $paper_type_id == 64 ) {
            $paper_type_option = ArrayUtils::get($payload, 'paperTypeOption');
        } else {
            $paperType = new PaperType( $paper_type_id );
            if(!Validate::isLoadedObject($paperType)) {
                return $app->response([
                    "success" => false,
                ]);
            }

            $paper_type_option = $paperType->title;
        }

        /** Paper Format */
        $paper_format_id = (int) ArrayUtils::get($payload, 'paperformat');

        $paperFormat = new PaperFormat( $paper_format_id );
        if(Validate::isLoadedObject($paperFormat)) {
            $paper_format_option = $paperFormat->title;
        } else {
            $paper_format_id = 4;
			$paper_format_option = ArrayUtils::get($payload, 'paperFormatTypeOption');
        }

        $tariff_id = ArrayUtils::get($payload, 'tariffId');
        $max_ext_time = ArrayUtils::get($payload, 'maxExtTime');

        if (!$tariff_id) {
			return $app->response([
                "success" => false,
            ]);
        }

        $tariff = new Deadline( $tariff_id );
        if(!Validate::isLoadedObject($tariff)) {
            return $app->response([
                "success" => false,
            ]);
        }

        $price_per_page = (float) $tariff->price_per_page;
		$hrs_customer = (int) $tariff->hrs_customer;
		$hrs_writer = (int) $tariff->hrs_writer;

        $paper_details = ArrayUtils::get($payload, 'paperDetails');

        $has_add_materials = ArrayUtils::get($payload, 'addmaterialsHidden');

        /** Additional Services */
        $used_sources = ArrayUtils::has($payload, 'usedsources') ? true : false;
        $writer_samples = ArrayUtils::has($payload, 'samplesNeeded') ? true : false;
        $progressive_delivery = ArrayUtils::get($payload, 'progressiveDeliveryHidden');
        $expert_proofreading = ArrayUtils::has($payload, 'expertProofreading') ? true : false;
        $vip_support = ArrayUtils::has($payload, 'vipSupport') ? true : false;
        $plagiarism_report = ArrayUtils::has($payload, 'plagiarismReport') ? true : false;
        $draft_outline = ArrayUtils::has($payload, 'draftOutline') ? true : false;

        /** Payment Method */
        $payment_method = ArrayUtils::get($payload, 'payment_system_hidden');

        $order = new Order();
        $order->payment_method = $payment_method;

        $currency = new Currency( (int) ArrayUtils::get($payload, 'currencyId') );
        if(Validate::isLoadedObject($currency)) {
            $order->currency_id = $currency->id;
            $order->currency_to_usd_rate = $currency->conversion_rate;
        }

        /** Additional Services */
        $order->used_sources = $used_sources;
        $order->writer_samples = $writer_samples;
        $order->expert_proofreading = $expert_proofreading;
        $order->vip_support = $vip_support;
        $order->plagiarism_report = $plagiarism_report;
        $order->draft_outline = $draft_outline;
        $order->progressive_delivery = $progressive_delivery;

        $order->form_type_id = $form_type_id;
        $order->form_type = $form_type;
        $order->tracking_id = $trackingId;
        $order->gmt = $gmt;
        $order->customer_id = $user->id;

        if (ArrayUtils::get($payload, 'requestedWriterId')) {
            $requested_writer_id = ArrayUtils::get($payload, 'requestedWriterId');
            $writer = new Employee( (int) $requested_writer_id );
            if(!Validate::isLoadedObject($writer)) {
                return $app->response([
                    "success" => false,
                    "errors" => [
                        "The writer you requested does not exist"
                    ]
                ]);
            }
            $order->requested_writer_id = $writer->id;
        }

        $order->service_type = Order::COMPLEX_ASSIGNMENT;
        $order->tariff_id = $tariff->id;

        $order->title = $toptitle;
        $order->academic_level_id = $academic_level_id;
        $order->paper_type_id = $paper_type_id;
        $order->paper_type_option = $paper_type_option;
        $order->topic_category_id = $topic_cat_id;
        $order->topic_category_option = $topic_cat_option;
        $order->is_complex_assignment = $isComplexAssignment;
        $order->paper_format_id = $paper_format_id;
        $order->paper_format_option = $paper_format_option;

        $order->writer_category_id = $writer_cat_id;
        $order->writer_percent = $writer_percent;

        $order->sources = $min_sources;
        $order->pages = $pages;
        $order->charts = $charts;
        $order->slides = $slides;
        $order->spacing = $spacing;
        $order->paper_details = $paper_details;
        $order->price_per_page = $price_per_page;
        $order->hrs_customer = $hrs_customer;
        $order->customer_deadline = $max_ext_time;
        $order->hrs_writer = $hrs_writer;

        if( ArrayUtils::get($payload, 'couponId') ) {
            $couponId = (int) ArrayUtils::get($payload, 'couponId');
            $discount = (int) ArrayUtils::get($payload, 'discount');
            $discount_type = (int) ArrayUtils::get($payload, 'discount_type');

            $order->discount = $discount;
            $order->discount_type = $discount_type;
        } 

        $calc = $order->calculate();
        $baseCost = ArrayUtils::get($calc, 'rawCost');
        $servicesById = ArrayUtils::get($calc, 'servicesById');

        $order->raw_cost = $baseCost;
        $order->total = ArrayUtils::get($calc, 'totalCost');
        $order->writer_pay = ArrayUtils::get($calc, 'writerCost');
        $order->editor_pay = ArrayUtils::get($calc, 'editorCost');

        $serviceProvideSamples = $servicesById[PriceCalculator::SERVICES_IDS['PROVIDE_ME_SAMPLES']];
        if ($serviceProvideSamples['cost'] > 0) {
            $order->writer_samples = true;
        } else {
            $order->writer_samples = false;
        }

        $serviceUsedSources = $servicesById[PriceCalculator::SERVICES_IDS['USED_SOURCES']];
        if ($serviceUsedSources['cost'] > 0) {
            $order->used_sources = true;
        } else {
            $order->used_sources = false;
        }

        $serviceComplexAssignment = $servicesById[PriceCalculator::SERVICES_IDS['COMPLEX_ASSIGNMENT']];
        if ($serviceComplexAssignment['cost'] > 0) {
            $order->is_complex_assignment = true;
        } else {
            $order->is_complex_assignment = false;
        }

        $serviceExpertProofreading = $servicesById[PriceCalculator::SERVICES_IDS['EXPERT_PROOFREADING']];
        if ($serviceExpertProofreading['cost'] > 0) {
            $order->expert_proofreading = true;
        } else {
            $order->expert_proofreading = false;
        }

        $serviceVipSupport = $servicesById[PriceCalculator::SERVICES_IDS['VIP_SUPPORT']];
        if ($serviceVipSupport['cost'] > 0) {
            $order->vip_support = true;
        } else {
            $order->vip_support = false;
        }

        $servicePlagiarismReport = $servicesById[PriceCalculator::SERVICES_IDS['PLAGIARISM_REPORT']];
        if ($servicePlagiarismReport['cost'] > 0) {
            $order->plagiarism_report = true;
        } else {
            $order->plagiarism_report = false;
        }

        $serviceDraftOutline = $servicesById[PriceCalculator::SERVICES_IDS['DRAFT_OUTLINE']];
        if ($serviceDraftOutline['cost'] > 0) {
            $order->draft_outline = true;
        } else {
            $order->draft_outline = false;
        }

        $serviceProgressiveDelivery = $servicesById[PriceCalculator::SERVICES_IDS['PROGRESSIVE_DELIVERY']];
        if ($serviceProgressiveDelivery['cost'] > 0) {
            $order->progressive_delivery = true;
        } else {
            $order->progressive_delivery = false;
        }

        if ( $order->total <= 0 ) {
            $order->status_id = Order::NEW_PAID;
        } elseif (
            $order_type == "inquiry" ||
            $order_type == "classhelp"
        ) {
			$order->status_id = Order::FREE_INQUIRY;
		} else {
			$order->status_id = Order::FAKE;
        }

        $new_order = false;
        if ( $fid && Validate::isUnsignedId($fid) ) {
            $new_order = false;
			$order->id = $fid;
			$ok = $order->update();
        } else {
            $new_order = true;
            $ok = $order->add();
        }

        if(!$ok) {
            return $app->response([
                "success" => false,
            ]);
        }

        // add additional materials
		if ( ArrayUtils::has($payload, 'additionalMaterialsFiles') ) {
			$additionalMaterialsFiles = ArrayUtils::get($payload, 'additionalMaterialsFiles');

			if (is_array($additionalMaterialsFiles) && !empty($additionalMaterialsFiles)) {
				// loop through all files
				foreach ($additionalMaterialsFiles as $file_id) {
					$file = new File( (int) $file_id );
					// insert if the file exists
					if ( Validate::isLoadedObject($file) ) {
                        // reorder files
                        if(
                            $file->uploader_id != $order->customer_id ||
                            $file->order_id != $order->id
                        ) {
                            $newFile = new File();
                            $newFile->uploader_id = $order->customer_id;
                            $newFile->order_id = $order->id;
                            $newFile->file_type_id = $file->file_type_id;
                            $newFile->file_description = $file->file_description;
                            $newFile->name = $file->name;
                            $newFile->source = $file->source;
                            $newFile->size = $file->size;
                            $newFile->extension = $file->extension;
                            $newFile->add();
                        } else {
                            $file->order_id = $order->id;
                            $file->update();
                        }
					}
				}
			}
        }

        /** user last academic level **/
		$user->last_academic_level = $academic_level_id;
        $user->update();

        if ($new_order) {
            /** Send new Order Notification to Admin ***/
            $notification = new Notification();
            $notification->from_department = DEPARTMENT_CUSTOMER;
            $notification->from_user_id = $user->id;
            $notification->action = Notification::ACTION_ORDER;
            $notification->node_type = Notification::TYPE_NEW_ORDER;
            $notification->node_url = $order->id;
            $notification->send(DEPARTMENT_SUPPORT);

            try {
                $orderPresenter = new OrderPresenter();
                $site_url = Configuration::get('SITE_DOMAIN', PROX_ADMIN_SITE_ID, $app->base_uri);
                $mailParams = array(
                    'type' => 'order',
                    'order' => $orderPresenter->present($order),
                    'admin_site_name' => Configuration::get('SITE_NAME', PROX_ADMIN_SITE_ID),
                    'admin_order_url' => $site_url . '/order/' . (int) $order->id,
                    'order_url' => $site_url . '/order/' . (int) $order->id,
                );

                $receivers = array();
                $receivers[] = Configuration::get('SITE_EMAIL', PROX_ADMIN_SITE_ID);
                $notification_emails = $app->getNotificationEmails();
                $receivers = array_merge($receivers, $notification_emails);
                $receivers = array_unique($receivers);

                foreach($receivers as $receiver) {
                    Mail::Send(
                        'new_order',
                        'New Order #' . $order->id . ' placed at ' . Configuration::get('SITE_NAME'),
                        $mailParams,
                        $receiver,
                        null,
                        null,
                        null,
                        null,
                        null,
                        null,
                        null,
                        null,
                        null,
                        null,
                        PROX_ADMIN_SITE_ID
                    );
                }
            } catch(\Exception $e) {
            }
        }

        $orderUri = Configuration::get('SITE_DOMAIN') . '/dashboard/order/' . $order->id;

        // wallet payment method
        if($order->payment_method == "wallet") {
            try {

                $success = Wallet::chargeWallet( 
                    $user->id, 
                    $order->total, 
                    $currency->id,
                    $order->id,
                    'order' 
                );

                if($success) {
                    $redirectUri = Configuration::get('SITE_DOMAIN') . '/payment/wallet/success?redirectUri=' . $orderUri;
                } else {
                    $redirectUri = Configuration::get('SITE_DOMAIN') . '/payment/wallet/failed?redirectUri=' . $orderUri;
                }
                
            } catch( Exception $e ) {
                return $app->response([
                    "success" => false,
                    "errors" => [
                        $e->getMessage()
                    ]
                ]);
            }

        } else {
            if ( $order_type == "inquiry" ||
                $order_type == "classhelp"
            ) {
                $redirectUri = $orderUri;
            } elseif( $order->payment_method ) {
                $redirectUri = Configuration::get('SITE_DOMAIN') . '/checkout/' . $order->payment_method . '/order/' . $order->id;
            } else {
                $redirectUri = $orderUri;
            }
        }

        return $app->response([
			"success" => true,
			'newOrderId' => (int) $order->id,
			'totcharg' => (float) $order->total,
			'errors' => null,
			'url' => $redirectUri,
		]);
    }

    public function getOrders() {
        $app = $this->app;
		$payload = $app->request->get();
        $user = $app->container->user;

        $batch = (int) ArrayUtils::get($payload, 'batch');
        $startFrom = (int) ArrayUtils::get($payload, 'startFrom');
        $type = ArrayUtils::get($payload, 'type');

        $orders = array();

        $orders_query = new DbQuery();
        $orders_query->select('o.order_id');
        $orders_query->from('order', 'o');
        $orders_query->where('o.`customer_id` = ' . (int) $user->id );

        if ( $type == "byStatus" ) {

            $statusId = (int) ArrayUtils::get($payload, 'statusId');
            $orders_query->where('o.`status_id` = ' . (int) $statusId);

        } else {
            switch ($type) {
                case 'recent':
                    $recent_statuses = array(
                        Order::FAKE,
                        Order::NEW_PAID,
                        Order::ORDER_PUBLISHED,
                        Order::CONFIRMATION_PENDING,
                        Order::WRITER_ASSIGNED,
                        Order::WRITER_ACCEPTED,
                        Order::FREE_INQUIRY,
                        Order::DONE,
                        Order::DELIVERED,
                        Order::REVISION,
                        Order::REPLY_PENDING,
                        Order::INQUERY_PUBLISHED
                    );

                    $cancelled_statuses = array(
                        Order::CANCELLED,
                    );

                    $cancelled_statuses = implode(',', $cancelled_statuses);

                    $status = implode(',', $recent_statuses);
                    $orders_query->where("
                        o.`status_id` IN ( $status )
                        OR DATE_SUB(curdate(), INTERVAL 1 WEEK) <= DATE(o.date_add)
                        AND status_id NOT IN ( $cancelled_statuses )
                    ");

                    break;

                case 'finished':
                    $finished_statuses = array(
                        Order::FINISHED
                    );

                    $status = implode(',', $finished_statuses);
                    $orders_query->where("o.`status_id` IN ( $status )");
                    break;

                case 'cancelled':
                    $cancelled_statuses = array(
                        Order::CANCELLED,
                    );

                    $finished_statuses = array(
                        Order::FINISHED,
                        Order::DISPUTE
                    );

                    $status = implode(',', $cancelled_statuses);
                    $orders_query->where("o.`status_id` IN ( $status )");

                    break;

            }
        }

        $results_query = clone $orders_query;

        if( $startFrom ) {
            $results_query->where('o.`order_id` < ' . (int) $startFrom );
        }

        /** Limit results */
        $results_query->orderBy('o.order_id DESC');
        $results_query->limit( $batch );

        $result = Db::getInstance(PROX_USE_SQL_SLAVE)->executeS( $results_query );

        $order_presenter = new OrderPresenter();
        foreach ($result as $order) {
			$order = new Order($order['order_id'], true);
			if ( Validate::isLoadedObject($order) ) {
				$orders[] = $order_presenter->present($order);
			}
        }

        $showMoreButton = false;
        if ( count($orders) ) {
            $lastOrder = end($orders);
			if ($lastOrder->id) {
                $startFrom = $lastOrder->id;
                $show_more_query = clone $orders_query;
                $show_more_query->where('o.`order_id` < ' . (int) $startFrom );
                $show_more_query->orderBy('order_id DESC');
                $showMoreButton = (bool) Db::getInstance(PROX_USE_SQL_SLAVE)->getValue( $show_more_query );
			}
		}

        return $app->response([
			"success" => true,
			"startFrom" => (int) $startFrom,
			"batch" => count($orders),
			"showMoreButton" => $showMoreButton,
			"type" => $type,
			"orders" => $orders
		]);
    }

    public function getUnpaidOrders() {
        $app = $this->app;
		$payload = $app->request->get();
		$user = $app->container->user;

        $orders = array();
        
        $orders_query = new DbQuery();
        $orders_query->select('o.order_id');
        $orders_query->from('order', 'o');
        $orders_query->where('o.`customer_id` = ' . (int) $user->id );
        $orders_query->where('o.`status_id` = ' . (int) Order::FAKE );
        $orders_query->orderBy('o.order_id DESC');
        $orders_query->limit( 1 );
        $result = Db::getInstance(PROX_USE_SQL_SLAVE)->executeS( $orders_query );

        $order_presenter = new OrderPresenter();
        foreach ($result as $order) {
			$order = new Order($order['order_id'], true);
			if ( Validate::isLoadedObject($order) ) {
				$orders[] = $order_presenter->present($order);
			}
        }

		return $app->response([
			"success" => true,
			"unpaidOrders" => $orders
		]);
    }

    public function getOrder( $orderId ) {
        $app = $this->app;
		$user = $app->container->user;

		$order = new Order( (int) $orderId, true);
		if (!Validate::isLoadedObject($order) ) {
			return $app->response([
				"success" => false,
				"errors" => "Invalid order id: %d"
			]);
		}

		if ($order->customer_id != $user->id) {
			return $app->response([
				"success" => false,
				"errors" => "Invalid order id: %d"
			]);
        }
        
        $order_presenter = new OrderPresenter();

		return $app->response([
			"success" => true,
			"order" => $order_presenter->present($order)
		]);
    }

    public function getSamples( $orderId ) {
        $app = $this->app;
        $user = $app->container->user;

        $order = new Order( (int) $orderId);
        if ( !Validate::isLoadedObject($order) || $order->customer_id != $user->id ) {
            return $app->response([
                "success" => false,
                "errors" => "Invalid order id: %d"
            ]);
        }

        if ( !$order->writer_assigned || !$order->writer_id ) {
            return $app->response([
                "success" => true,
                "hasSources" => false,
                "message" => "SAMPLES_NO_WRITER",
                "sources" => []
            ]);
        }

        $sql = new DbQuery();
        $sql->select('f.file_id');
        $sql->from('order_file', 'f');
        $sql->where('f.`order_id` = ' . (int) $order->id );
        $sql->where('f.`uploader_id` = ' . (int) $order->writer_id );
        // $sql->where('f.`file_type_id` = ' . (int) File::SAMPLE );
        $sql->limit('2');

        $result = Db::getInstance(PROX_USE_SQL_SLAVE)->executeS($sql);

        if (!count($result)) {
            return $app->response([
                "success" => true,
                "hasSamples" => false,
                "message" => "SAMPLES_NOT_READY",
                "samples" => []
            ]);
        }

        $samples = array();

        foreach ( $result as $file ) {
            $file = new File( (int) $file['file_id'] );
            if ( Validate::isLoadedObject( $file ) ) {
                $samples[] = array(
                    "id" => (int) $file->id,
                    "name" => $file->name,
                    "status" => "",
                    "description" => $file->file_description,
                    "isNew" => (bool) $file->downloaded,
                    "createdAt" => $file->date_add
                );
            }

        }

        return $app->response([
            "success" => true,
            "hasSamples" => count($samples) > 0 ? true : false,
            "samples" => $samples
        ]);
    }

    public function getSources( $orderId ) {
        $app = $this->app;
		$user = $app->container->user;

		$order = new Order( (int) $orderId);
		if ( !Validate::isLoadedObject($order) || $order->customer_id != $user->id ) {
			return $app->response([
				"success" => false,
				"errors" => "Invalid order id: %d"
			]);
		}

		if ( !$order->writer_assigned || !$order->writer_id ) {
			return $app->response([
				"success" => true,
				"hasSources" => false,
				"message" => "SOURCES_NOT_READY",
				"sources" => []
			]);
		}

        /** Get sources upload by writer or admin */
		$sql = new DbQuery();
		$sql->select('f.file_id');
		$sql->from('order_file', 'f');
		$sql->where('f.`order_id` = ' . (int) $order->id);
		$sql->where('f.`uploader_id` != ' . (int) $user->id);
		$sql->where('f.`file_type_id` = ' . (int) File::SOURCES);

		$result = Db::getInstance(PROX_USE_SQL_SLAVE)->executeS($sql);

		if (!count($result)) {
			return $app->response([
				"success" => true,
				"hasSources" => false,
				"message" => "SOURCES_NOT_READY",
				"sources" => []
			]);
		}

		$sources = array();

		foreach ( $result as $file ) {
            $file = new File( (int) $file['file_id'] );
            if ( Validate::isLoadedObject( $file ) ) {
                $sources[] = array(
                    "id" => (int) $file->id,
                    "name" => $file->name,
                    "status" => $file->name,
                    "description" => $file->file_description,
                    "isNew" => (bool) $file->downloaded,
                    "createdAt" => $file->date_add
                );
            }

		}

		return $app->response([
			"success" => true,
			"hasSources" => count($sources) > 0 ? true : false,
			"sources" => $sources
		]);
    }

    public function sendTipsForWriters( $orderId ) {
        $app = $this->app;
        $user = $app->container->user;
        $payload = $app->request->post();

        $order = new Order( (int) $orderId );
        if ( !Validate::isLoadedObject($order) ) {
            return $app->response([
                "success" => false,
                "errors" => "Invalid order id: " . $orderId
            ]);
        }

        $orderUri = Configuration::get('SITE_DOMAIN') . '/dashboard/order/' . $order->id;
        $amount = ArrayUtils::get($payload, 'amount');
        $paymentMethod = ArrayUtils::get($payload, 'payment_method');

        if(!Validate::isPrice($amount)) {
			return $app->response([
				"success" => false,
				"errors" => [
                    "Enter a valid amount"
                ]
			]);
        }

        if($paymentMethod == "wallet") {
            
            try {

                $success = Wallet::chargeWallet( 
                    $user->id, 
                    $amount, 
                    $order->currency->id,
                    $order->id,
                    'tip' 
                );

                if($success) {
                    $redirect = Configuration::get('SITE_DOMAIN') . '/payment/wallet/success?redirectUri=' . $orderUri;
                } else {
                    $redirect = Configuration::get('SITE_DOMAIN') . '/payment/wallet/failed?redirectUri=' . $orderUri;
                }
                
            } catch( Exception $e ) {
                return $app->response([
                    "success" => false,
                    "errors" => [
                        $e->getMessage()
                    ]
                ]);
            }
        } else {
            $paymentModule = Module::getInstanceByName($paymentMethod);
            if(!Validate::isLoadedObject($paymentModule)) {
                return $app->response([
                    "success" => false,
                    "errors" => [
                        "Select a valid payment method"
                    ]
                ]);
            }

    		$redirect = Configuration::get('SITE_DOMAIN') . '/checkout/' . $paymentMethod . '/tip/' . $order->id . '?amount=' . $amount;
        }


		return $app->response([
			"success" => true,
			"redirect_to" => $redirect
		]);
    }

    public function addServices( $orderId ) {
        global $globals;
        $app = $this->app;
        $payload = $app->request->post();

        $values = array(
            'ADD_WRITING_PAGES' => 0,
            'ADD_WRITING_SLIDES' => 0,
            'ADD_WRITING_CHARTS' => 0,
            'ADD_PROVIDE_ME_SAMPLES' => false,
            'ADD_PROGRESSIVE_DELIVERY' => false,
            'ADD_USED_SOURCES' => false,
            'ADD_BOOST_CATEGORY' => false,
            'ADD_SHORTEN_DEADLINE' => false,
            'ADD_EXPERT_PROOFREADING' => false,
        );

        $order = new Order( (int) $orderId );
        if ( !Validate::isLoadedObject($order) ) {
            return $app->response([
                "success" => false,
                "errors" => "Invalid order id: " . $orderId
            ]);
        }

        $payment_method = ArrayUtils::get($payload, 'paymentSystemId');
        $comment = ArrayUtils::get($payload, 'comment');

        $services = ArrayUtils::get($payload, 'services');
        if(!$services) {
            return $app->response([
                "success" => false
            ]);
        }

        $services = Tools::jsonDecode($services, true);
        if (!is_array($services)) {
            return $app->response([
                "success" => false
            ]);
        }

        /** Additional Service **/
        $additionalService = new AdditionalService();
        $additionalService->order_id = $order->id;
        $additionalService->comment = $comment;

        $originalOrder = $order->defaultOrder();

        foreach ( $services as $service ) {
            $type = ArrayUtils::get($service, 'type');

            switch( $type ) {
                case "page":
                    $pages = (int) ArrayUtils::get( $service, 'quantity');

                    $additionalService->pages = $pages;
                    $values['ADD_WRITING_PAGES'] = $pages;
                    break;

                case "slide":
                    $slides = (int) ArrayUtils::get( $service, 'quantity');

                    $additionalService->slides = $slides;
                    $values['ADD_WRITING_SLIDES'] = $slides;
                    break;

                case "chart":
                    $charts = (int) ArrayUtils::get( $service, 'quantity');

                    $additionalService->charts = $charts;
                    $values['ADD_WRITING_CHARTS'] = $charts;
                    break;

                case "samples":
                    $additionalService->writer_samples = 1;
                    $values['ADD_PROVIDE_ME_SAMPLES'] = true;
                    break;

                case "sources":
                    $additionalService->used_sources = 1;
                    $values['ADD_USED_SOURCES'] = true;
                    break;

                case "progressive":
                    $additionalService->progressive_delivery = 1;
                    $values['ADD_PROGRESSIVE_DELIVERY'] = true;
                    break;

                case "boost":
                    $writerCategoryId = ArrayUtils::get($service, 'writerCategoryId');

                    $additionalService->writer_category_id = $writerCategoryId;
                    $values['ADD_BOOST_CATEGORY'] = $writerCategoryId;
                    break;

                case "shorten":
                    $tariffId = (int) ArrayUtils::get($service, 'tariffId');

                    $additionalService->tariff_id = $tariffId;
                    $values['ADD_SHORTEN_DEADLINE'] = $tariffId;
                    break;
            }
        }

        $tariff = $category = array();
        $tariffId = ArrayUtils::get($values, 'ADD_SHORTEN_DEADLINE');
        if($tariffId) {
            $tariff = new Deadline( (int) $tariffId );
            if(!Validate::isLoadedObject($tariff)) {
                return $app->response([
                    "success" => false
                ]);
            }
        }

        $writerCategoryId = ArrayUtils::get($values, 'ADD_BOOST_CATEGORY');
        if ($writerCategoryId) {
            $category = ArrayUtils::get($globals['writerPreferences'], $writerCategoryId );
        }

        $aService = array(
            'shortenDeadlineHrs' => Validate::isLoadedObject($tariff) ? (int) $tariff->hrs_customer : false,
            'shortenDeadlinePricePerPage' => Validate::isLoadedObject($tariff) ? (int) $tariff->price_per_page : false,
            'boostWriterCategoryId' => $writerCategoryId ? $writerCategoryId : false,
            'boostWriterPercent' => ArrayUtils::has($category, 'percent') ? ArrayUtils::get($category, 'percent') : false,
            'newPagesQuantity' => $order->pages + (int) ArrayUtils::get($values, 'ADD_WRITING_PAGES'),
            'newSlidesQuantity' => $order->slides + (int) ArrayUtils::get($values, 'ADD_WRITING_SLIDES'),
            'newChartsQuantity' => $order->charts + (int) ArrayUtils::get($values, 'ADD_WRITING_CHARTS'),
            'getUsedSourcesOn' => (bool) ArrayUtils::get($values, 'ADD_USED_SOURCES'),
            'getSamplesOn' => (bool) ArrayUtils::get($values, 'ADD_PROVIDE_ME_SAMPLES'),
            'getProgressiveDeliveryOn' => (bool) ArrayUtils::get($values, 'ADD_PROGRESSIVE_DELIVERY'),
            'expertProofreading' => (bool) ArrayUtils::get($values, 'ADD_EXPERT_PROOFREADING')
        );

        // remove discount
        $priceCalculator = new PriceCalculator();
        $addServicesById = $priceCalculator->calculateAddServices( $aService, $originalOrder );
        $totalCost = $priceCalculator->getTotalCost( $addServicesById );

        $additionalService->total = $totalCost;
        $success = $additionalService->add();

        $redirectUri = Configuration::get('SITE_DOMAIN') . '/dashboard/add-payment/' . $additionalService->id;

        return $app->response([
            "success" => true,
            "redirect" => $redirectUri
        ]);
    }

    public function getAdditionalPayments( $addPaymentId ) {
        $app = $this->app;
        $payload = $app->request->post();
        $user = $app->container->user;
        $options = array();

        $addPayment = new AdditionalService( (int) $addPaymentId );
        if ( !Validate::isLoadedObject($addPayment) ) {
            return $app->response([
                "success" => false
            ]);
        }


        $order = new Order( (int) $addPayment->order_id );
        if (!Validate::isLoadedObject($order)) {
            return $app->response([
                "success" => false
            ]);
        }

        $options['currency'] = array(
            'symbol' => $order->currency->symbol,
            'rate' => $order->currency->conversion_rate
        );

        return $app->response([
            "success" => true,
            "order" => array(
                "order_parent_id" => (int) $order->id,
                "title" => "Payment of ". formatPrice($addPayment->total, $options),
                "description" => $addPayment->comment,
                "currency_id" => (int) $order->currency->id,
                "currency_rate" => (float) $order->currency->conversion_rate,
                "total_charge" => (float) $addPayment->total
            )
        ]);
    }

    public function payAdditionalPayment( $addPaymentId ) {
        $app = $this->app;
        $payload = $app->request->post();
        $user = $app->container->user;

        $addPayment = new AdditionalService( (int) $addPaymentId );
        if ( !Validate::isLoadedObject($addPayment) ) {
            return $app->response([
                "success" => false
            ]);
        }

        $order = new Order( (int) $addPayment->order_id );
        if (!Validate::isLoadedObject($order)) {
            return $app->response([
                "success" => false
            ]);
        }

        $orderUri = Configuration::get('SITE_DOMAIN') . '/dashboard/order/' . $order->id;
        $payment_method = ArrayUtils::get($payload, 'payment_method_value');

        if($payment_method == "wallet") {
            try {

                $success = Wallet::chargeWallet( 
                    $user->id, 
                    $addPayment->total, 
                    $order->currency->id,
                    $addPayment->id,
                    'add-payment' 
                );

                if($success) {
                    $redirectUri = Configuration::get('SITE_DOMAIN') . '/payment/wallet/success?redirectUri=' . $orderUri;
                } else {
                    $redirectUri = Configuration::get('SITE_DOMAIN') . '/payment/wallet/failed?redirectUri=' . $orderUri;
                }
            } catch( Exception $e ) {
                return $app->response([
                    "success" => false,
                    "errors" => [
                        $e->getMessage()
                    ]
                ]);
            }
        } else {
            $redirectUri = Configuration::get('SITE_DOMAIN') . '/checkout/' . $payment_method . '/add-payment/' . $addPayment->id;
        }

        return $app->response([
            "success" => true,
            "redirect_to" => $redirectUri
        ]);
    }

    public function payOrder( $orderId ) {
        $app = $this->app;
        $user = $app->container->user;
        $params = $app->request->get();

        $payment_method = ArrayUtils::get($params, 'payment_method_value');

		$order = new Order( (int) $orderId );
		if ( !Validate::isLoadedObject($order) ) {
			return $app->response([
				"success" => false,
				"errors" => "Invalid order id: " . $orderId
			]);
        }

        $order->payment_method = $payment_method;
        $order->update();

        if( $payment_method == "wallet" ) {
            $orderUri = Configuration::get('SITE_DOMAIN') . '/dashboard/order/' . $order->id;

            try {

                $success = Wallet::chargeWallet( 
                    $user->id, 
                    $order->total, 
                    $order->currency->id,
                    $order->id,
                    'order' 
                );

                if($success) {
                    $redirectUri = Configuration::get('SITE_DOMAIN') . '/payment/wallet/success?redirectUri=' . $orderUri;
                } else {
                    $redirectUri = Configuration::get('SITE_DOMAIN') . '/payment/wallet/failed?redirectUri=' . $orderUri;
                }
                
            } catch( Exception $e ) {
                return $app->response([
                    "success" => false,
                    "errors" => [
                        $e->getMessage()
                    ]
                ]);
            }

        } else {
            $redirectUri = Configuration::get('SITE_DOMAIN') . '/checkout/' . $payment_method . '/order/' . $order->id;
        }

		return $app->response([
			"success" => true,
			'redirect_to' => $redirectUri,
		]);
    }

    public function cancelOrder( $orderId ) {
        $app = $this->app;
        $smarty = $app->container->smarty;

		$order = new Order( (int) $orderId );
		if ( !Validate::isLoadedObject($order) ) {
			return $app->response([
				"success" => false,
				"errors" => "Invalid order id: " . $orderId
			]);
		}

		$order->status_id = Order::CANCELLED;
		$order->cancelled_at = DateUtils::now();
		$order->update();

        $customer = $order->getCustomer();
        $smarty->assign([
            'customer_name' => $customer->name,
        ]);

        /** Add Revision Note **/
        $message = new OrderMessage();
        $message->order_id = $order->id;
        $message->sender_id = Employee::START_ID;
        $message->from_department = DEPARTMENT_SUPPORT;
        $message->to_department = DEPARTMENT_CUSTOMER;
        $message->is_verified = true;
        $message->verified_at = DateUtils::now();
        $message->subject = "Please consider using our service again";
        $message->body = $smarty->fetch('messages/order-cancelled.tpl');
        $message->add();

        $order_presenter = new OrderPresenter();

		return $app->response([
			"success" => true,
			"errors" => null,
			"order" => $order_presenter->present($order)
		]);
    }

    public function pdScheduleConfirm( $orderId ) {

    }

    public function pdScheduleReject( $orderId ) {

    }

    public function approveOrder( $orderId ) {
        $app = $this->app;
        $payload = $app->request->post();
        $user = $app->container->user;

        $order = new Order( (int) $orderId, true );
        if ( !Validate::isLoadedObject($order) ) {
            return $app->response([
                "success" => false
            ]);
        }

        if ($order->customer_id != $user->id) {
            return $app->response([
                "success" => false
            ]);
        }

        $noteBody = ArrayUtils::get($payload, 'noteBody');
        // Rate the quality of the paper received
        $rate = (int) ArrayUtils::get($payload, 'rate');
        // Rate the service of the support team
        $rate1 = (int) ArrayUtils::get($payload, 'rate1');
        // Did you receive your paper on time?
        $recPap = (bool) ArrayUtils::get($payload, 'recPap');

        $rating = new OrderRating();
        $rating->order_id = $order->id;
        $rating->paper_rating = $rate ? $rate : null;
        $rating->service_rating = $rate1 ? $rate1 : null;
        $rating->comment = $noteBody;
        $rating->paper_on_time = $recPap;
        $rating->add();

        $order->status_id = Order::FINISHED;
        $order->approved_at = DateUtils:: now();
        $order->update();

        return $app->response([
            "success" => true
        ]);
    }

    public function requestRevision( $orderId ) {
        $app = $this->app;
        $payload = $app->request->post();
        $user = $app->container->user;
        $smarty = $app->container->smarty;

        $order = new Order( (int) $orderId, true );
        if ( !Validate::isLoadedObject($order) ) {
            return $app->response([
                "success" => false
            ]);
        }

        $fileIdToRevision = ArrayUtils::get($payload, 'fileIdToRevision');

        $fileToRevision = new File( (int) $fileIdToRevision );
        if (!Validate::isLoadedObject($fileToRevision)) {
            return $app->response([
                "success" => false,
                "errors" => [
                    "The file you selected does not exist"
                ]
            ]);
        }

        $noteBody = ArrayUtils::get($payload, 'noteBody');
        if (!is_array($noteBody) || !count($noteBody)) {
            return $app->response([
                "success" => false,
                "errors" => [
                    "You have to select at least 1 section"
                ]
            ]);
        }

        $clientdeadline = (int) ArrayUtils::get($payload, 'clientdeadline');
        $revisionDiffWriter = ArrayUtils::has($payload, 'revisionDiffWriter') ? true : false;

        $time = time();
        $revisionTime = $clientdeadline*60*60;
        $customer_deadline = DateUtils::date( $time + $revisionTime );

        $writer_revision_time = ($revisionTime*70) / 100;
        $writer_deadline = DateUtils::date( $time + $writer_revision_time );

        $deadline = DateUtils::convertToISOFormat($customer_deadline);
        $deadline = DateUtils::date( strtotime($deadline) , null, 'M jS, Y \\a\\t g:i A' );

        $smarty->assign([
            'orderId' => $order->id,
            'deadline' => $deadline,
            'revisionDiffWriter' => (bool) $revisionDiffWriter,
            'format' => ArrayUtils::get($noteBody, 'format'),
            'grammar' => ArrayUtils::get($noteBody, 'grammar'),
            'instructions' => ArrayUtils::get($noteBody, 'instructions'),
            'sources' => ArrayUtils::get($noteBody, 'sources'),
            'customize_cont' => ArrayUtils::get($noteBody, 'cust_cont'),
            'other' => ArrayUtils::get($noteBody, 'other')
        ]);

        $refund_revision_body = $smarty->fetch('messages/free-revision.tpl');

        /** Add Revision Note **/
        $message = new OrderMessage();
        $message->order_id = $order->id;
        $message->sender_id = Employee::START_ID;
        $message->from_department = DEPARTMENT_SUPPORT;
        $message->to_department = DEPARTMENT_WRITER;
        $message->subject = "Order #".$order->id.": Please revise the order";
        $message->body = $refund_revision_body;
        $message->is_verified = true;
        $message->verified_at = DateUtils::now();
        $success = $message->add();

        $order->customer_deadline = $customer_deadline;
        $order->writer_deadline = $writer_deadline;
        $order->status_id = Order::REVISION;
        $order->update();

        $writer = new Employee( (int) $order->writer_id );
        if(Validate::isLoadedObject($writer)) {
            $writer->total_orders_revised = $writer->total_orders_revised+1;
            $writer->update();
        }

        $editor = new Employee( (int) $order->editor_id );
        if(Validate::isLoadedObject($editor)) {
            $editor->total_orders_revised = $editor->total_orders_revised+1;
            $editor->update();
        }

        $send_to = array(
            Configuration::get('SITE_EMAIL', PROX_ADMIN_SITE_ID),
            $writer->email
        );

        $notification_emails = $app->getNotificationEmails();
        $send_to = array_merge($send_to, $notification_emails);
		$send_to = array_unique($send_to);

        foreach( $send_to as $mail_to ) {
            try {
                Mail::Send(
                    'order_revision',
                    $message->subject,
                    array(
                        'body' => $message->body,
                        'order_url' => Configuration::get('SITE_DOMAIN', PROX_ADMIN_SITE_ID) . '/order/' . $order->id
                    ),
                    $mail_to,
                    null,
                    null,
                    null,
                    null,
                    null,
                    null,
                    null,
                    null,
                    null,
                    null,
                    PROX_ADMIN_SITE_ID
                );
            } catch( \Exception $e ) {

            }
        }

        return $app->response([
            "success" => true
        ]);
    }

    public function requestPaidRevision( $orderId ) {
        global $globals;

        $app = $this->app;
        $payload = $app->request->post();
        $user = $app->container->user;

        $order = new Order( (int) $orderId );
        if ( !Validate::isLoadedObject($order) ) {
            return $app->response([
                "success" => false
            ]);
        }

        $tariff_id = ArrayUtils::get($payload, 'tariffId');
        $service_type = ArrayUtils::get($payload, 'serviceType');
        $sources = ArrayUtils::get($payload, 'sources');
        $discount = ArrayUtils::get($payload, 'discount');
        $requested_writer_id = ArrayUtils::get($payload, 'requestedWriterId');
        $revision_paid_file = ArrayUtils::get($payload, 'revision_paid_file');
        $paper_details = ArrayUtils::get($payload, 'paperDetails');
        $payment_method = ArrayUtils::get($payload, 'payment_system_hidden');

        if(!$revision_paid_file) {
            return $app->response([
                "success" => false,
                "errors" => [
                    "You have to select at least 1 file that you want revised"
                ]
            ]);
        }

        if ( !$tariff_id || !$service_type ) {
            return $app->response([
                "success" => false
            ]);
        }

        if ( !$paper_details ) {
            return $app->response([
                "success" => false,
                "errors" => [
                    "You have to select at least 1 section"
                ]
            ]);
        }

        $service = new Order();
        $service->payment_method = $payment_method;
        $service->service_type = (int) $service_type;
        $service->status_id = Order::FAKE;
        $service->parent_id = $order->id;
        $service->writer_category_id = $order->writer_category_id;
        $service->writer_percent = $order->writer_percent;
        $service->form_type_id = $order->form_type_id;
        $service->form_type = $order->form_type;
        $service->gmt = $order->gmt;
        $service->customer_id = $order->customer_id;

        $service->title = $order->title;
        $service->academic_level_id = $order->academic_level_id;
        $service->paper_type_id = $order->paper_type_id;
        $service->paper_type_option = $order->paper_type_option;
        $service->topic_category_id = $order->topic_category_id;
        $service->topic_category_option = $order->topic_category_option;
        $service->is_complex_assignment = $order->is_complex_assignment;
        $service->paper_format_id = $order->paper_format_id;
        $service->paper_format_option = $order->paper_format_option;

        $service->sources  = (int) $sources;
        $service->pages = $order->pages;
        $service->charts = $order->charts;
        $service->slides = $order->slides;
        $service->spacing = $order->spacing;
        $service->paper_details = $order->paper_details;

        if( $requested_writer_id ) {
            $writer = new Employee( (int) $requested_writer_id );
            if(!Validate::isLoadedObject($writer)) {
                return $app->response([
                    "success" => false,
                    "errors" => [
                        "The writer you requeste does not exist"
                    ]
                ]);
            }

            $service->requested_writer_id = $writer->id;
            $service->writer_category_id = $writer->writer_category;
            $service->writer_percent = $writer->writer_percent;
        }

        if( $discount ) {
            $coupon = new Coupon( (int) $discount );
            if(Validate::isLoadedObject($coupon)) {
                $service->discount_type = $coupon->coupon_type;
                $service->discount = $coupon->coupon_value;
            }
        }

        /** Deadlines **/
        $paidRevisionDeadlines = ArrayUtils::get($globals['paidRevisionDeadlines'], $service_type);
        $deadlines = ArrayUtils::get($paidRevisionDeadlines, $order->academic_level_id);
        $tariff = ArrayUtils::get($deadlines, $tariff_id);

        if (!is_array($tariff)) {
            return $app->response([
                "success" => false,
            ]);
        }

        $price_per_page = (float) ArrayUtils::get($tariff, 'price_per_page');
        $hrs_customer = (int) ArrayUtils::get($tariff, 'hrs');
        $hrs_writer = (int) ArrayUtils::get($tariff, 'hrs_writer');

        $service->tariff_id = (int) $tariff_id;
        $service->price_per_page = $price_per_page;
        $service->hrs_customer = $hrs_customer;
        $service->hrs_writer = $hrs_writer;

        $customer_deadline = time() + ($hrs_customer*60*60);
        $service->customer_deadline = DateUtils::date($customer_deadline);

        $calc = $service->calculate();
        $service->raw_cost = ArrayUtils::get($calc, 'rawCost');
        $service->total = ArrayUtils::get($calc, 'totalCost');

        $success = $service->add();
        if(!$success) {
            return $app->response([
                "success" => false,
            ]);
        }

        if (is_array($revision_paid_file) && !empty($revision_paid_file)) {
            foreach ( $revision_paid_file as $file_id => $file_name ) {

                $file = new File( (int) $file_id );
                if ( !Validate::isLoadedObject($file) ) {
                    return $app->response([
                        "success" => false,
                        "errors" => [
                            "The file (" . $file_name . ") does not exist"
                        ]
                    ]);
                }

                /** Do not reupload file if already exists **/
                if ( $file->order_id != $service->id ) {
                    $newFile = new File();
                    $newFile->uploader_id = $service->customer_id;
                    $newFile->order_id = $service->id;
                    $newFile->file_type_id = $file->file_type_id;
                    $newFile->file_description = $file->file_description;
                    $newFile->name = $file->name;
                    $newFile->source = $file->source;
                    $newFile->size = $file->size;
                    $newFile->extension = $file->extension;
                    $newFile->add();
                }
            }
        }

        /** Add Revision Note **/
        $message = new OrderMessage();
        $message->order_id = $service->id;
        $message->sender_id = $order->customer_id;
        $message->from_department = DEPARTMENT_CUSTOMER;
        $message->to_department = DEPARTMENT_WRITER;
        $message->body = $paper_details;
        $message->add();

        if( $payment_method == "wallet" ) {
            $orderUri = Configuration::get('SITE_DOMAIN') . '/dashboard/order/' . $service->id;

            try {

                $success = Wallet::chargeWallet( 
                    $user->id, 
                    $service->total, 
                    $order->currency->id,
                    $service->id,
                    'order' 
                );

                if($success) {
                    $redirectUri = Configuration::get('SITE_DOMAIN') . '/payment/wallet/success?redirectUri=' . $orderUri;
                } else {
                    $redirectUri = Configuration::get('SITE_DOMAIN') . '/payment/wallet/failed?redirectUri=' . $orderUri;
                }
                
            } catch( Exception $e ) {
                return $app->response([
                    "success" => false,
                    "errors" => [
                        $e->getMessage()
                    ]
                ]);
            }

        } else {
            $redirectUri = Configuration::get('SITE_DOMAIN') . '/checkout/' . $payment_method . '/order/' . $service->id;
        }

        return $app->response([
            "success" => true,
            "redirect" => $redirectUri
        ]);
    }

    public function updatePaidRevision( $orderId ) {
        $app = $this->app;
        $payload = $app->request->post();
        $user = $app->container->user;

        $order = new Order( (int) $orderId );
        if ( !Validate::isLoadedObject($order) ) {
            return $app->response([
                "success" => false
            ]);
        }
    }

    public function requestRefund( $orderId ) {
        $app = $this->app;
        $payload = $app->request->post();
        $user = $app->container->user;
        $smarty = $app->container->smarty;

        $order = new Order( (int) $orderId );
        if ( !Validate::isLoadedObject($order) ) {
            return $app->response([
                "success" => false
            ]);
        }

        $noteBody = Tools::jsonDecode(ArrayUtils::get($payload, 'noteBody'), true);
        $rate = ArrayUtils::get($payload, 'rate');
        $rate1 = ArrayUtils::get($payload, 'rate1');
        $refundType = ArrayUtils::get($payload, 'refundType');

        if (!is_array($noteBody) || !count($noteBody)) {
            return $app->response([
                "success" => false,
                "errors" => [
                    "You have to select at least 1 section"
                ]
            ]);
        }

        $smarty->assign([
            'noteBody' => $noteBody,
            'orderId' => $order->id,
            'full_refund' => $refundType == 1 ? true : false,
            'content' => ArrayUtils::get($noteBody, 'content'),
            'sources' => ArrayUtils::get($noteBody, 'sources'),
            'format' => ArrayUtils::get($noteBody, 'format'),
            'grammar' => ArrayUtils::get($noteBody, 'grammar'),
            'instructions' => ArrayUtils::get($noteBody, 'instructions'),
            'other' => ArrayUtils::get($noteBody, 'other')
        ]);

        $refund_request_body = $smarty->fetch('messages/refund.tpl');

        $message = new OrderMessage();
        $message->order_id = $order->id;
        $message->sender_id = $order->customer_id;
        $message->from_department = DEPARTMENT_CUSTOMER;
        $message->to_department = DEPARTMENT_SUPPORT;
        $message->subject = "Refund request for order #" . $order->id;
        $message->is_verified = true;
        $message->verified_at = DateUtils::now();
        $message->body = $refund_request_body;
        $message->add();

        return $app->response([
            "success" => true
        ]);
    }

    public function trustpilot( $orderId, $fromStatus = "recent" ) {
        $app = $this->app;
        $user = $app->container->user;

        $order = new Order( (int) $orderId );
        if ( !Validate::isLoadedObject($order) ) {
            return $app->response([
                "success" => false
            ]);
        }
    }
}