belongsTo(Orders::class); } public function customer() { return $this->hasOneThrough(Customer::class, Orders::class, "id", "id", "customer_id", "order_id"); } public function product() { return $this->hasOneThrough(Product::class, ProductItems::class, "id", "id", "product_item_id", "product_id"); } public function productItem() { return $this->belongsTo(ProductItems::class); } public function productParamedicLevel() { return $this->belongsTo(ProductParamedicLevel::class); } public function paramedicLevel() { return $this->hasOneThrough(ParamedicLevel::class, ProductParamedicLevel::class, "id", "id", "product_paramedic_level_id", "paramedic_level_id"); } public function bed() { return $this->belongsTo(Bed::class); } public function room() { return $this->hasOneThrough(Room::class, Bed::class, "id", "id", "bed_id", "room_id"); } public function building() { return $this->hasOneThrough(Building::class, Bed::class, "id", "id", "bed_id", "building_id"); } public function area() { return $this->hasOneThrough(Area::class, Bed::class, "id", "id", "bed_id", "area_id"); } public function paramedic() { return $this->belongsTo(Paramedic::class); } public function calculateFee() { $factors = json_decode($this->factors); $factor_texts = []; foreach ($factors as $factor_item) { if ($factor_item->used_for_fee) { $add_text = "(管理费{$factor_item->fee_percent}%+{$factor_item->fee})"; } else { $add_text = ""; } $factor_texts[] = "{$factor_item->factor_name}:{$factor_item->factor_item_name}{$add_text}"; } $this->factor_texts = $factor_texts; switch ($this->product->fee_type) { case "factor": $factor = collect($factors)->filter(function ($item) { return $item->used_for_fee; })->first(); if (!$factor) { //todo:检查factors为什么没有进去、缺失的factors已经手工补录进去了 $factor = (new Factor()) ->with("factorItems") ->where("product_id", $this->product->id) ->where("used_for_fee", 1) ->first() ->factorItems ->first(); } $fee = $factor->fee_percent * $this->total / 100 + $factor->fee - $this->fee_free; $paramedic_total = $this->total - $fee; $this->paramedic_total = $paramedic_total; $this->fee = $fee; break; } return $this; } public function autoCheckout($before_today = false) { $threshold = 100; $last_id = cache("last_auto_checkout_order_item_id", 0); dump("last_auto_checkout_order_item_id:" . $last_id); $unpaid_order_items = $this ->whereHas("order", function ($query) { $query->where("status", Orders::STATUS_ONGOING); }) ->whereNull("paid_at") ->where("id", ">", $last_id); if ($before_today) { $today = strtotime(date("Y-m-d")); $unpaid_order_items->whereRaw("UNIX_TIMESTAMP(`service_date`) < {$today}"); } $unpaid_order_items = $unpaid_order_items ->orderBy("id") ->limit($threshold) ->get(); dump("count:" . $unpaid_order_items->count()); if (!$unpaid_order_items->count()) { cache(['last_auto_checkout_order_item_id' => null], now()->addSeconds(90)); return; } foreach ($unpaid_order_items as $item) { cache(['last_auto_checkout_order_item_id' => $item->id], now()->addSeconds(90)); $customer = $item->order->customer; if ($customer->balance < $item->total || $item->total == 0) { dump("balance not enough"); continue; } $item->update([ "paid_at" => date("Y-m-d H:i:s") ]); $balance = $customer->balance - $item->total; $customer->update([ "balance" => $balance ]); (new Balance())->create([ "customer_id" => $customer->id, "order_id" => $item->order_id, "belongs_type" => get_class($item), "belongs_id" => $item->id, "money" => -$item->total, "balance" => $balance ]); $item->order->refreshTotal(); dump($item->id.":".$item->service_date); } } public function balance() { return $this->hasOne(Balance::class, "belongs_id")->where("belongs_type", self::class); } }