'array', 'extra_price' => 'array', 'package_compare' => 'array', 'requirements' => 'array', 'faqs' => 'array', ]; protected $bookingClass; protected $bookingTimeSlotsClass; protected $reviewClass; protected $gigDateClass; protected $gigTermClass; protected $gigTranslationClass; protected $userWishListClass; protected $locationClass; protected $attributes = [ 'status'=>'draft' ]; public function __construct(array $attributes = []) { parent::__construct($attributes); $this->bookingClass = Booking::class; $this->bookingTimeSlotsClass = BookingTimeSlots::class; $this->reviewClass = Review::class; $this->gigTermClass = GigTerm::class; $this->gigTranslationClass = GigTranslation::class; $this->userWishListClass = UserWishList::class; $this->locationClass = Location::class; } public static function getModelName() { return __("Gig"); } public static function getTableName() { return with(new static)->table; } /** * Get SEO fop page list * * @return mixed */ static public function getSeoMetaForPageList() { $meta['seo_title'] = __("Search for Gigs"); if (!empty($title = setting_item_with_lang("gig_page_list_seo_title",false))) { $meta['seo_title'] = $title; }else if(!empty($title = setting_item_with_lang("gig_page_search_title"))) { $meta['seo_title'] = $title; } $meta['seo_image'] = null; if (!empty($title = setting_item("gig_page_list_seo_image"))) { $meta['seo_image'] = $title; }else if(!empty($title = setting_item("gig_page_search_banner"))) { $meta['seo_image'] = $title; } $meta['seo_desc'] = setting_item_with_lang("gig_page_list_seo_desc"); $meta['seo_share'] = setting_item_with_lang("gig_page_list_seo_share"); $meta['full_url'] = url(env('GIG_ROUTE_PREFIX','gig')); return $meta; } public function terms(){ return $this->hasMany($this->gigTermClass, "target_id"); } public function getDetailUrl($include_param = true) { $param = []; if($include_param){ if(!empty($date = request()->input('date'))){ $dates = explode(" - ",$date); if(!empty($dates)){ $param['start'] = $dates[0] ?? ""; $param['end'] = $dates[1] ?? ""; } } if(!empty($adults = request()->input('adults'))){ $param['adults'] = $adults; } if(!empty($children = request()->input('children'))){ $param['children'] = $children; } } $urlDetail = "gig/" . $this->slug; if(!empty($param)){ $urlDetail .= "?".http_build_query($param); } return url($urlDetail); } public static function getLinkForPageSearch( $locale = false , $param = [] ){ return url(env('GIG_ROUTE_PREFIX','gig')."?".http_build_query($param)); } public function getGallery($featuredIncluded = false) { if (empty($this->gallery)) return $this->gallery; $list_item = []; if ($featuredIncluded and $this->image_id) { $list_item[] = [ 'large' => FileHelper::url($this->image_id, 'full'), 'thumb' => FileHelper::url($this->image_id, 'thumb') ]; } $items = explode(",", $this->gallery); foreach ($items as $k => $item) { $large = FileHelper::url($item, 'full'); $thumb = FileHelper::url($item, 'thumb'); $list_item[] = [ 'large' => $large, 'thumb' => $thumb ]; } return $list_item; } public function getEditUrl() { return url(route('gig.admin.edit',['id'=>$this->id])); } public function getDiscountPercentAttribute() { if ( !empty($this->price) and $this->price > 0 and !empty($this->sale_price) and $this->sale_price > 0 and $this->price > $this->sale_price ) { $percent = 100 - ceil($this->sale_price / ($this->price / 100)); return $percent . "%"; } } public function fill(array $attributes) { if(!empty($attributes)){ foreach ( $this->fillable as $item ){ $attributes[$item] = $attributes[$item] ?? null; } } return parent::fill($attributes); // TODO: Change the autogenerated stub } public function isBookable() { if ($this->status != 'publish') return false; return parent::isBookable(); } public static function searchForMenu($q = false) { $query = static::select('id', 'title as name'); if (strlen($q)) { $query->where('title', 'like', "%" . $q . "%"); } $a = $query->limit(10)->get(); return $a; } public static function getMinMaxPrice() { $model = parent::selectRaw('MIN( basic_price ) AS min_price , MAX( basic_price ) AS max_price ')->where("status", "publish")->first(); if (empty($model->min_price) and empty($model->max_price)) { return [ 0, 100 ]; } return [ $model->min_price, $model->max_price ]; } public function getReviewEnable() { return setting_item("gig_enable_review", 0); } public function getReviewApproved() { return setting_item("gig_review_approved", 0); } public static function getReviewStats() { $reviewStats = []; if (!empty($list = setting_item("gig_review_stats", []))) { $list = json_decode($list, true); foreach ($list as $item) { $reviewStats[] = $item['title']; } } return $reviewStats; } public function getReviewDataAttribute() { $list_score = [ 'score_total' => 0, 'score_text' => __("Not rated"), 'total_review' => 0, 'rate_score' => [], ]; $dataTotalReview = $this->reviewClass::selectRaw(" AVG(rate_number) as score_total , COUNT(id) as total_review ")->where('object_id', $this->id)->where('object_model', $this->type)->where("status", "approved")->first(); if (!empty($dataTotalReview->score_total)) { $list_score['score_total'] = number_format($dataTotalReview->score_total, 1); $list_score['score_text'] = Review::getDisplayTextScoreByLever(round($list_score['score_total'])); } if (!empty($dataTotalReview->total_review)) { $list_score['total_review'] = $dataTotalReview->total_review; } $list_data_rate = $this->reviewClass::selectRaw('COUNT( CASE WHEN rate_number = 5 THEN rate_number ELSE NULL END ) AS rate_5, COUNT( CASE WHEN rate_number = 4 THEN rate_number ELSE NULL END ) AS rate_4, COUNT( CASE WHEN rate_number = 3 THEN rate_number ELSE NULL END ) AS rate_3, COUNT( CASE WHEN rate_number = 2 THEN rate_number ELSE NULL END ) AS rate_2, COUNT( CASE WHEN rate_number = 1 THEN rate_number ELSE NULL END ) AS rate_1 ')->where('object_id', $this->id)->where('object_model', $this->type)->where("status", "approved")->first()->toArray(); for ($rate = 5; $rate >= 1; $rate--) { if (!empty($number = $list_data_rate['rate_' . $rate])) { $percent = ($number / $list_score['total_review']) * 100; } else { $percent = 0; } $list_score['rate_score'][$rate] = [ 'title' => $this->reviewClass::getDisplayTextScoreByLever($rate), 'total' => $number, 'percent' => round($percent), ]; } return $list_score; } public function getScoreReview() { $gig_id = $this->id; $list_score = Cache::rememberForever('review_'.$this->type.'_' . $gig_id, function () use ($gig_id) { $dataReview = $this->reviewClass::selectRaw(" AVG(rate_number) as score_total , COUNT(id) as total_review ")->where('object_id', $gig_id)->where('object_model', $this->type)->where("status", "approved")->first(); $score_total = !empty($dataReview->score_total) ? number_format($dataReview->score_total, 1) : 0; return [ 'score_total' => $score_total, 'total_review' => !empty($dataReview->total_review) ? $dataReview->total_review : 0, ]; }); $list_score['review_text'] = $list_score['score_total'] ? Review::getDisplayTextScoreByLever( round( $list_score['score_total'] )) : __("Not rated"); return $list_score; } public function getNumberReviewsInService($status = false) { return $this->reviewClass::countReviewByServiceID($this->id, false, $status,$this->type) ?? 0; } public function getReviewList(){ return $this->reviewClass::select(['id','title','content','rate_number','author_ip','status','created_at','vendor_id','create_user'])->where('object_id', $this->id)->where('object_model', 'gig')->where("status", "approved")->orderBy("id", "desc")->with('author')->paginate(setting_item('gig_review_number_per_page', 5)); } public function getNumberServiceInLocation($location) { $number = 0; if(!empty($location)) { $number = parent::join('jp_locations', function ($join) use ($location) { $join->on('jp_locations.id', '=', $this->table.'.location_id')->where('jp_locations._lft', '>=', $location->_lft)->where('jp_locations._rgt', '<=', $location->_rgt); })->where($this->table.".status", "publish")->with(['translations'])->count($this->table.".id"); } if(empty($number)) return false; if ($number > 1) { return __(":number Gigs", ['number' => $number]); } return __(":number Gig", ['number' => $number]); } public function hasWishList(){ return $this->hasOne($this->userWishListClass, 'object_id','id')->where('object_model' , $this->type)->where('user_id' , Auth::id() ?? 0); } public function isWishList() { if(Auth::id()){ if(!empty($this->hasWishList) and !empty($this->hasWishList->id)){ return 'active'; } } return ''; } public static function getServiceIconFeatured(){ return "flaticon-climbing"; } public static function isEnable(){ return setting_item('gig_disable') == false; } public function isDepositEnable(){ return (setting_item('gig_deposit_enable') and setting_item('gig_deposit_amount')); } public function getDepositAmount(){ return setting_item('gig_deposit_amount'); } public function getDepositType(){ return setting_item('gig_deposit_type'); } public function getDepositFomular(){ return setting_item('gig_deposit_fomular','default'); } public static function search($filters = []) { $request = \request(); $model_gig = parent::query()->select("jp_gigs.*"); $model_gig->where("jp_gigs.status", "publish"); if (!empty($location_id = $request->query('location_id'))) { $location = Location::where('id', $location_id)->where("status","publish")->first(); if(!empty($location)){ $model_gig->join('jp_locations', function ($join) use ($location) { $join->on('jp_locations.id', '=', 'jp_gigs.location_id') ->where('jp_locations._lft', '>=', $location->_lft) ->where('jp_locations._rgt', '<=', $location->_rgt); }); } } if(!empty($filters['category'])){ $model_gig->where(function ($q) use($filters){ $q->where('cat_id', $filters['category']) ->orWhere('cat2_id', $filters['category']) ->orWhere('cat3_id', $filters['category']); }); } if(!empty($filters['cat2_id'])){ $model_gig->where('cat2_id',$filters['cat2_id']); } if(!empty($filters['cat3_id'])){ $model_gig->where('cat3_id',$filters['cat3_id']); } if (!empty($pri_from = $request->query('amount_from')) && !empty($pri_to = $request->query('amount_to'))) { $raw_sql_min_max = "( jp_gigs.basic_price >= ?) AND ( jp_gigs.basic_price <= ? )"; $model_gig->WhereRaw($raw_sql_min_max,[$pri_from,$pri_to]); } $terms = $request->query('terms'); if($term_id = $request->query('term_id')) { $terms[] = $term_id; } if (is_array($terms) && !empty($terms)) { $terms = Arr::where($terms, function ($value, $key) { return !is_null($value); }); if(!empty($terms)){ $model_gig->join('jp_gig_term as tt', 'tt.target_id', "jp_gigs.id")->whereIn('tt.term_id', $terms); } } $review_scores = $request->query('review_score'); if (is_array($review_scores) && !empty($review_scores)) { $where_review_score = []; $params = []; foreach ($review_scores as $number){ $where_review_score[] = " ( jp_gigs.review_score >= ? AND jp_gigs.review_score <= ? ) "; $params[] = $number; $params[] = $number.'.9'; } $sql_where_review_score = " ( " . implode("OR", $where_review_score) . " ) "; $model_gig->WhereRaw($sql_where_review_score,$params); } if(!empty( $service_name = $request->query("service_name") )){ if( setting_item('site_enable_multi_lang') && setting_item('site_locale') != app()->getLocale() ){ $model_gig->leftJoin('jp_gig_translations', function ($join) { $join->on('jp_gigs.id', '=', 'jp_gig_translations.origin_id'); }); $model_gig->where('jp_gig_translations.title', 'LIKE', '%' . $service_name . '%'); }else{ $model_gig->where('jp_gigs.title', 'LIKE', '%' . $service_name . '%'); } } if(!empty($lat = $request->query('map_lat')) and !empty($lgn = $request->query('map_lgn'))){ $model_gig->orderByRaw("POW((jp_gigs.map_lng-?),2) + POW((jp_gigs.map_lat-?),2)",[$lgn,$lat]); } if(!empty( $delivery_time = $request->query("delivery_time") ) and $delivery_time != "any_time"){ $model_gig->where('jp_gigs.basic_delivery_time', '<=', $delivery_time); } $orderby = $request->input("orderby"); switch($orderby) { case"new": $model_gig->orderBy("id", "desc"); break; case"old": $model_gig->orderBy("id", "asc"); break; case"name_high": $model_gig->orderBy("title", "asc"); break; case"name_low": $model_gig->orderBy("title", "desc"); break; default: $model_gig->orderBy("is_featured", "desc"); $model_gig->orderBy("id", "desc"); break; } $model_gig->groupBy("jp_gigs.id"); $max_guests = (int)($request->query('adults') + $request->query('children')); if($max_guests){ $model_gig->where('max_guests','>=',$max_guests); } return $model_gig->with(['location','hasWishList','translations']); } public function getNumberWishlistInService($status = false) { return $this->hasOne($this->userWishListClass, 'object_id','id')->where('object_model' , $this->type)->count(); } static public function getFiltersSearch() { $min_max_price = self::getMinMaxPrice(); return [ [ "title" => __("Filter Price"), "field" => "price_range", "position" => "1", "min_price" => floor ( Currency::convertPrice($min_max_price[0]) ), "max_price" => ceil (Currency::convertPrice($min_max_price[1]) ), ], [ "title" => __("Review Score"), "field" => "review_score", "position" => "2", "min" => "1", "max" => "5", ], [ "title" => __("Attributes"), "field" => "terms", "position" => "3", "data" => Attributes::getAllAttributesForApi("event") ] ]; } public function saveTag($tags_name, $tag_ids) { if (empty($tag_ids)) $tag_ids = []; $tag_ids = array_merge(Tag::saveTagByName($tags_name), $tag_ids); $tag_ids = array_filter(array_unique($tag_ids)); // Delete unused GigTag::query()->whereNotIn('tag_id', $tag_ids)->where('target_id', $this->id)->delete(); //Add GigTag::addTag($tag_ids, $this->id); } public function author() { return $this->belongsTo(User::class,'author_id'); } public function cat(){ return $this->belongsTo(GigCategory::class,'cat_id'); } public function cat2(){ return $this->belongsTo(GigCategory::class,'cat2_id'); } public function cat3(){ return $this->belongsTo(GigCategory::class,'cat3_id'); } public function orderEmailToCustomer(Order $order,OrderItem $orderItem){ Mail::to($order->customer)->queue(new GigOrderEmail($order,$orderItem,$this,'customer')); } public function orderEmailToAuthor(GigOrder $gig_order){ Mail::to($this->author)->queue(new GigOrderEmail($gig_order,$this,'author')); } public function orderEmailToAdmin(Order $order,OrderItem $orderItem){ if(!setting_item('admin_email')) return; Mail::to(setting_item('admin_email'))->queue(new GigOrderEmail($order,$orderItem,$this,'admin')); } public function sendNotifyToAuthor(GigOrder $gig_order){ $user = $gig_order->author; $data = [ 'id' => $gig_order->id, 'to' => 'candidate', 'name' => $gig_order->customer->getDisplayName() ?? '', 'avatar' => $gig_order->customer->avatar_url ?? '', 'link' => route('seller.order', ['id'=> $gig_order->id]), 'type' => 'order_gig', 'message' => __(':name ordered the gig ":gig"', ['name' => $gig_order->customer->getDisplayName() ?? '', 'gig' => $gig_order->gig->title ?? '']) ]; $user->notify(new PrivateChannelServices($data)); } public function sendNotifyToAdmin(GigOrder $gig_order){ $user = $gig_order->author; $data = [ 'id' => $gig_order->id, 'name' => $gig_order->customer->getDisplayName() ?? '', 'avatar' => $gig_order->customer->avatar_url ?? '', 'link' => route('gig_order.admin.index'), 'type' => 'order_gig', 'message' => __(':name ordered the gig ":gig"', ['name' => $gig_order->customer->getDisplayName() ?? '', 'gig' => $gig_order->gig->title ?? '']) ]; $user->notify(new AdminChannelServices($data)); } public function initOrder(Order $order,OrderItem $orderItem){ $gig_order = GigOrder::firstOrNew([ 'gig_id'=>$this->id, 'order_item_id'=>$orderItem->id ]); if($gig_order->id){ return $gig_order; } $packages = collect($this->packages); $package = $packages->where('key',$orderItem->meta['package'] ?? '')->first(); $data = [ 'order_id'=>$order->id, 'author_id'=>$this->author_id, 'customer_id'=>$order->customer_id, 'revision'=>$package['revision'] ?? 1, 'delivery_time'=>$package['delivery_time'] ?? 1, 'package'=>$orderItem->meta['package'] ?? '', 'extra_prices'=>$orderItem->meta['extra_prices'] ?? [], 'requirements'=>$this->requirements, 'status'=>GigOrder::INCOMPLETE, 'price'=>$orderItem->price, 'total'=>$orderItem->subtotal ]; if(empty($this->requirements)){ $data['status'] = GigOrder::IN_PROGRESS; $data['start_date'] = date('Y-m-d H:i:s'); $delivery_date = date('Y-m-d H:i:s', strtotime('+'.($package['delivery_time'] ?? 1).' days')); $data['delivery_date'] = $delivery_date; } $gig_order->fillByAttr(array_keys($data),$data); $is_new = $gig_order->id; $gig_order->save(); if($gig_order->status == GigOrder::IN_PROGRESS){ $gig_order->addActivity(GigOrderActivity::TYPE_ORDER_STARTED); $gig_order->addActivity(GigOrderActivity::TYPE_DELIVERY_DATE); } if($is_new){ $gig_order->addActivity('init',[],$order->customer_id); } $gig_order->is_new = 1; return $gig_order; } public function addToCart($param){ $extra_prices = []; $base_price = 0; switch ($param['package']){ case"basic": $base_price = $this->basic_price; break; case"standard": $base_price = $this->standard_price; break; case"premium": $base_price = $this->premium_price; break; } if(empty($base_price)){ return [ 'status'=>0, 'message'=> __("Please select another package") ]; } $tmp_extra_price = []; if (!empty($this->extra_price) and !empty($param['extra_services'])) { $extra_price_input = $param['extra_services']; $extra_prices = $this->extra_price; foreach ( $extra_prices as $k => $type) { if (isset($extra_price_input[$k]) and !empty($extra_price_input[$k]['enable'])) { $tmp_extra_price[] = $type; } } } CartManager::clear(); CartManager::add($this,$this->title,1,$base_price,['package'=>$param['package'],'extra_prices'=>$tmp_extra_price]); return [ 'status'=>1, 'message'=> __("Add to cart success!") ]; } public function count_remain_review() { $number_review = Review::countReviewByServiceID($this->id, Auth::id(), false, $this->type) ?? 0; $number_booking = OrderItem::where("jp_order_items.object_id", $this->id) ->rightJoin('jp_orders', function ($join) { $join->on('jp_orders.id', '=', 'jp_order_items.order_id') ->where('jp_orders.customer_id', Auth::id()) ->where('jp_orders.status',"completed"); }) ->count("jp_order_items.id"); $number = $number_booking - $number_review; if($number < 0) $number = 0; return $number; } public function getTags() { $tags = GigTag::where('target_id', $this->id)->get(); $tag_ids = []; if (!empty($tags)) { foreach ($tags as $key => $value) { $tag_ids[] = $value->tag_id; } } return Tag::whereIn('id', $tag_ids)->with('translations')->get(); } }