下单全过程4

Laravel框架
457
0
0
2022-11-12

下单全过程4

下单全过程4

下单全过程4

下单全过程4

下单全过程4

订单详情表```php

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Order extends Model
{
//mysql的配置:default-storage-engine=INNODB 创建的表默认存储引擎为innodb存储引擎
use HasFactory;
protected $fillable = [
    'no',
    'address',
    'total_amount',
    'remark',
    'paid_at',
    'payment_method',
    'payment_no',
    'refund_status',
    'refund_no',
    'closed',
    'reviewed',
    'ship_status',
    'ship_data',
    'extra',
];

protected $casts = [
    'closed' => 'boolean',
    'reviewed'  => 'boolean',
    'address'   => 'json',
    'ship_data' => 'json',
    'extra'     => 'json',
];

/**
 * @var array 支付时间
 */
protected $dates = [
    'paid_at',
];

protected static function boot()
{
    parent::boot(); // TODO: Change the autogenerated stub  
    static::creating(function ($model){
        if (!$model->no){
            $model->no = static::findAvailableNo();

            //如果编号生成失败,终止订单的创建  
            if (!$model->no){
                return false;
            }
        }

    });
}

public static function findAvailableNo()
{
    // 订单流水号前缀  
    $prefix = date('YmdHis');
    for ($i = 0; $i < 10; $i++) {
        // 随机生成 6 位的数字  
        $no = $prefix.str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT);
        // 判断是否已经存在  
        if (!static::query()->where('no', $no)->exists()) {
            return $no;
        }
    }
    \Log::warning('find order no failed');

    return false;
}

public function user()
{
    return $this->belongsTo(User::class);
}
 //一个订单可以有多个详情
public function items()
{
    return $this->hasMany(OrderItem::class);
}

}

![下单全过程4](https://cdn.learnku.com/uploads/images/202208/16/55573/GkKzWS7uQ2.png!large)



![下单全过程4](https://cdn.learnku.com/uploads/images/202208/16/55573/RjyLfeYswF.png!large)
创建契约


![下单全过程4](https://cdn.learnku.com/uploads/images/202208/16/55573/nx4gKxyxuD.png!large)

```html
<?php
namespace App\Contracts\Order;

interface OrderContracts
{
    /**
     * @param $address
     * @param $user
     * @param $remark
     * @param $items
     * @return mixed
     * 订单生成 对于控制器
     */ 
    public function store($address,$user,$remark,$items);

    /**
     * @param $addressId
     * @return mixed
     * 更新收货地址使用时间
     */ 
    public function updateMemberAddressTime($addressId);

    /**
     * @param $address
     * @param $remark
     * @param $user
     * @return mixed
     * 创建订单
     */ 
    public function orderSave($address,$remark,$user);

    /**
     * @param $order
     * @param $sku
     * @return mixed
     * 订单详情数据生成
     */ 
    public function orderItemSave($order,$sku);

    /**
     * @param $order
     * @param $total_amount
     * @return mixed
     * 修改订单总金额
     */ 
    public function updateTotalAmount($order,$total_amount);

    /**
     * @param $user
     * @param $sku
     * @return mixed
     * 移除购物车商品
     */ 
    public function RemoveCart($user,$sku);
}

下单全过程4

下单全过程4

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class ProductSku extends Model
{
    use HasFactory;

    protected $fillable = [
        'title','on_sale','price','stock'
    ];

    protected $dates = [
        'on_sale' => 'boolean',//on_sale是布尔类型的数据
    ];

    public function product()
    {
        return $this->belongsTo(Product::class);
    }

    public function cartItems()
    {
        return $this->hasMany(CartItem::class);
    }

    public function attribute()
    {
        return $this->belongsToMany(Attribute::class,ProductSkuAttribute::class,'product_sku_id','attribute_id');
    }

    public function decreaseStock($amount)
    {
        if ($amount < 0){
            throw new \Exception('减库存不能小于0');
        }

        return $this->where('id',$this->id)->where('stock','>=',$amount)->decrement('stock',$amount);
    }

    public function addStock($amount)
    {
        if ($amount < 0){
            throw new \Exception('加库存不能小于0');
        }

        return $this->increment('stock',$amount);
    }
}
<?php
namespace App\Services\Order;

use App\Contracts\Order\OrderContracts;
use App\Jobs\CloseOrder;
use App\Models\MemberAddress;
use App\Models\Order;
use App\Models\ProductSku;
use Carbon\Carbon;
use Illuminate\Contracts\Container\Container;

class OrderService implements OrderContracts
{
    protected $app;

    protected $config;

    public function __construct(Container $container)
    {
        $this->app = $container;
        $this->config = $container->make('config');
    }

    public function store($address, $user, $remark, $items)
    {
        $order = \DB::transaction(function () use ($user,$address,$remark,$items){
            if (!$address = $this->updateMemberAddressTime($address)){
                return [
                  'code' => 400,
                  'error' =>  $this->config->get('error.order.address'),
                ];
            }

            if (!$order = $this->orderSave($address,$remark,$user)){
                return [
                    'code' => 400,
                    'error' =>  $this->config->get('error.order.order_save'),
                ];
            }

            if (!$total_amount = $this->orderItemSave($order,$items)){
                return [
                    'code' => 400,
                    'error' =>  $this->config->get('error.order.order_items'),
                ];
            }

            $this->updateTotalAmount($order,$total_amount);

            if (!$cart = $this->RemoveCart($user,$items)){
                return [
                    'code' => 400,
                    'error' =>  $this->config->get('error.order.cart'),
                ];
            }

            return $order;
        });

        dispatch(new CloseOrder($order,3));

        return $order;
    }

    //修改地址  
    public function updateMemberAddressTime($addressId)
    {
        $address = MemberAddress::query()->find($addressId);
        $address->update([
            'last_used_at' => Carbon::now()//获取当前时间
        ]);

        return $address;
    }

    public function orderSave($address, $remark, $user)
    {
        $order = new Order([
            'address' => [
                'address' => $address->full_address,
                'zip' => $address->zip,
                'contact_name' => $address->contact_name,
                'contact_phone' => $address->contact_phone
            ],
            'remark' => $remark,
            'total_amount' => 0
        ]);

        $order->user()->associate($user);

        $order->save();

        return $order;
    }

    //计算订单总金额  
    public function orderItemSave($order, $skus)
    {
        $total_amount = 0;

        foreach ($skus as $data){
            $sku = ProductSku::query()->find($data["sku_id"]);

            $item = $order->items()->make([
                'amount' => $data["amount"],
                'price' => $sku->price
            ]);

            $item->product()->associate($sku->product_id);
            $item->productSku()->associate($sku);
            $item->save();

            $total_amount += $sku->price *  $data["amount"];

            if ($sku->decreaseStock($data["amount"]) <= 0){
                throw  new \Exception("该商品库存不足");
            }
        }

        return $total_amount;
    }

    public function updateTotalAmount($order, $total_amount)
    {
        return $order->update([
            'total_amount' => $total_amount
        ]);
    }

    public function RemoveCart($user, $sku)
    {
        $skuIds = collect($sku)->pluck('sku_id')->all();
        if (!is_array($skuIds)){
            $skuIds = [$skuIds];
        }

        $cart = $user->cartItems()->whereIn('product_sku_id',$skuIds)->delete();
        return $cart;
    }

}

下单全过程4

下单全过程4

下单全过程4

下单全过程4

下单全过程4

下单全过程4

下单全过程4

下单全过程4

订单延迟处理