Browse Source

增加产品规格

master
李可松 4 years ago
parent
commit
466126c318
  1. 18
      MySQL_change.sql
  2. 29
      app/AdminSupplier/Controllers/ProductController.php
  3. 3
      app/Console/Commands/OrderTimeout.php
  4. 3
      app/Http/Controllers/Api/AgentProductController.php
  5. 84
      app/Http/Controllers/Api/OrderController.php
  6. 1
      app/Models/Order.php
  7. 5
      app/Models/Product.php
  8. 24
      app/Models/ProductSpec.php

18
MySQL_change.sql

@ -44,7 +44,7 @@ CREATE TABLE `industry_products` (
`id` INT(10) NOT NULL AUTO_INCREMENT,
`supplier_id` INT(10) NOT NULL COMMENT '供应商ID',
`category_id` INT(10) NOT NULL COMMENT '分类ID',
`type` TINYINT(3) NOT NULL DEFAULT '0' COMMENT '0:旅游线路、1:店、2:景区、3:餐厅、4:车队、5:单项',
`type` TINYINT(3) NOT NULL DEFAULT '0' COMMENT '0:旅游线路、1:店、2:景区、3:餐厅、4:车队、5:单项',
`title` VARCHAR(255) NOT NULL COMMENT '标题' COLLATE 'utf8_general_ci',
`price` DECIMAL(20,2) NOT NULL COMMENT '售价',
`original_price` DECIMAL(20,2) NOT NULL DEFAULT '0.00' COMMENT '原价',
@ -72,7 +72,7 @@ ENGINE=InnoDB;
ALTER TABLE `industry_orders`
ADD COLUMN `deposit` DECIMAL(20,2) NOT NULL DEFAULT 0 COMMENT '需要扣除的交易金数量' AFTER `verify_code`;
# 15:59 2021/9/18
# 15:59 2021/9/18 修改注释
ALTER TABLE `agent_products`
CHANGE COLUMN `guide_id` `guide_id` INT(10) NOT NULL DEFAULT '0' COMMENT '绑定地接(计调版旅行社才能绑定)' AFTER `category_id`,
CHANGE COLUMN `type` `type` TINYINT(3) NOT NULL DEFAULT '0' COMMENT '0:单品销售;1:组合销售;2:计调旅行社的云产品;' AFTER `is_rec`,
@ -81,3 +81,17 @@ ALTER TABLE `agent_products`
ALTER TABLE `orders`
CHANGE COLUMN `agent_cloud_pid` `agent_cloud_pid` INT(10) NOT NULL DEFAULT '0' COMMENT '计调云产品ID' AFTER `verify_code`,
CHANGE COLUMN `agent_cloud_price` `agent_cloud_price` DECIMAL(20,2) NOT NULL DEFAULT '0.00' COMMENT '计调云产品销售价格' AFTER `agent_cloud_pid`;
# 11:33 2021/9/22
ALTER TABLE `products`
CHANGE COLUMN `status` `status` TINYINT(3) NOT NULL DEFAULT '0' COMMENT '-2:下架,-1:审核拒绝,0:未审核,1:上架' AFTER `sale`;
# 12:00 2021/9/22
ALTER TABLE `orders`
ADD COLUMN `info` JSON NULL DEFAULT NULL COMMENT '订单信息' AFTER `single_price`;
# 16:09 2021/9/22
ALTER TABLE `order_product_items`
ADD COLUMN `product_spec_id` INT NOT NULL DEFAULT 0 COMMENT '产品规格ID' AFTER `price`;

29
app/AdminSupplier/Controllers/ProductController.php

@ -94,7 +94,7 @@ class ProductController extends AdminController
{
Admin::user()->publish_type = json_decode(Admin::user()->publish_type, true);
return Form::make(new Product(), function (Form $form) {
return Form::make(new Product(['spec']), function (Form $form) {
//不允许编辑非自己数据
if ($form->isEditing() && $form->model()->supplier_id != Admin::user()->id) {
return $form->response()->error('数据不存在');
@ -108,7 +108,13 @@ class ProductController extends AdminController
$form->currency('price')->symbol('¥')->required();
$form->currency('original_price')->symbol('¥')->required();
$form->number('service_persons')->required();
$form->number('stock')->required();
// $form->number('stock')->required();
$form->table('spec', function ($form) {
$form->hidden('id');
$form->text('name')->required();
$form->text('stock')->required();
$form->text('price')->required();
})->required();
if ($form->isEditing() && in_array($form->model()->status, [ProductStatus::SOLD_OUT, ProductStatus::ON_SALE])) {
$form->radio('status')->options([1 => '上架', -2 => '下架'])->default(1);
}
@ -221,17 +227,24 @@ class ProductController extends AdminController
}
}
//用户可编辑的状态
$user_status = [ProductStatus::SOLD_OUT, ProductStatus::ON_SALE];
//规格处理
if (!$form->spec || !$spec = array_filter($form->spec, fn($v) => !$v['_remove_'])) {
return $form->response()->error('请输入产品规格');
}
//处理库存
$form->hidden('stock');
$form->stock = array_sum(array_column($form->spec, 'stock'));
//特殊字段处理
if ($form->isCreating()) {
$form->hidden(['status', 'supplier_id']); //表单没有的字段,必须加上这句才能重置值
$form->supplier_id = Admin::user()->id;
$form->status = ProductStatus::UNAUDITED;
}
//用户可编辑的状态
$user_status = [ProductStatus::SOLD_OUT, ProductStatus::ON_SALE];
if ($form->isEditing() && in_array($form->model()->status, $user_status) && in_array($form->status, $user_status)) { //如果原来是下架或上架状态才允许修改
} else if ($form->isEditing() && in_array($form->model()->status, $user_status) && in_array($form->status, $user_status)) { //如果原来是下架或上架状态才允许修改
$form->status = $form->status == ProductStatus::ON_SALE ? ProductStatus::ON_SALE : ProductStatus::SOLD_OUT;
} else {
$form->deleteInput('status');

3
app/Console/Commands/OrderTimeout.php

@ -78,6 +78,9 @@ class OrderTimeout extends Command
}
}
});
//TODO 产品规格表加库存
$this->line('[' . date('Y-m-d H:i:s') . "] ID游标:$min_id ,等待下一个任务");
sleep(3);
}

3
app/Http/Controllers/Api/AgentProductController.php

@ -64,8 +64,7 @@ class AgentProductController extends Controller
} else {
$where = ['id' => $id, 'agent_id' => $this->agent_id, 'status' => ProductStatus::ON_SALE];
}
$agent_product = AgentProduct::query()
->with(['coupon:tag,agent_product_id'])
$agent_product = AgentProduct::with(['coupon:tag,agent_product_id', 'product.spec'])
->whereDoesntHave('agentProductItem', function ($query) {
return $query->whereHas('product', function ($query) {
return $query->where('stock', '<=', 0)->orWhere('status', '<>', ProductStatus::ON_SALE);

84
app/Http/Controllers/Api/OrderController.php

@ -12,6 +12,7 @@ use App\Models\AgentSetting;
use App\Models\Coupon;
use App\Models\OrderProductItem;
use App\Models\Product;
use App\Models\ProductSpec;
use App\Models\SystemSetting;
use App\Models\User;
use App\Models\Order;
@ -109,7 +110,7 @@ class OrderController extends Controller
//提交订单
public function create(Request $request)
{
$formData = $request->only(['id', 'name', 'mobile', 'pay_type', 'num']);
$formData = $request->input();
$formData = array_map(fn($v) => trim($v), $formData); //过滤,删除首尾空
//表单验证
@ -120,6 +121,8 @@ class OrderController extends Controller
'mobile' => ['required', 'regex:/^1[3-9]\d{9}$/'],
'pay_type' => ['required', 'in:' . $pay_type_values],
'num' => ['required', 'min:1'],
'spec_id' => ['required', 'min:1', 'integer'],
'id_card' => ['regex:/^\d{17}[\dXx]$/'],
], [
'id.required' => '未指定产品ID',
'name.required' => '请输入联系人姓名',
@ -131,10 +134,12 @@ class OrderController extends Controller
'pay_type.in' => '不存在此支付方式',
'num.required' => '请输入购买数量',
'num.min' => '购买数量输入错误',
'spec_id.*' => '请选择产品规格',
'id_card.regex' => '身份证号输入不正确',
]);
$ap = AgentProduct::query()
->with(['coupon', 'product', 'agentCloudProduct:id,price'])
->with(['coupon', 'product.spec', 'agentCloudProduct:id,price'])
->where('stock', '>=', $formData['num'])
->where(['id' => $formData['id'], 'status' => ProductStatus::ON_SALE, 'agent_id' => $this->agent_id]) //判断agent_id,防止新入驻小程序的演示产品被下单
->whereDoesntHave('agentProductItem', function ($query) {
@ -147,6 +152,63 @@ class OrderController extends Controller
return $this->error('产品已下架或库存不足');
}
if (is_null($ap->product->spec) || !array_filter($ap->product->spec->toArray(), fn($v) => $v['id'] == $formData['spec_id'])) {
return $this->error('你选择的产品规格不存在');
}
$order_info = [];
//0:单品销售;1:组合销售
if ($ap->type == 0) {
//0:旅游线路、1:酒店、2:景区、3:餐厅、4:车队、5:单项 => admin_trans('product.options.publish_type')
switch ($ap->product->type) {
case 0:
if (empty($formData['departure_time']) || !strtotime($formData['departure_time'])) {
return $this->error('请选择出发时间');
}
if (empty($formData['return_time']) || !strtotime($formData['return_time'])) {
return $this->error('请选择回程时间');
}
if (empty($formData['id_card'])) {
return $this->error('请输入身份证号');
}
$order_info['departure_time'] = $formData['departure_time']; //出发时间
$order_info['return_time'] = $formData['return_time']; //回程时间
$order_info['id_card'] = $formData['id_card']; //身份证号
break;
case 1:
if (empty($formData['check_in_time']) || !strtotime($formData['check_in_time'])) {
return $this->error('请选择入住时间');
}
if (empty($formData['check_out_time']) || !strtotime($formData['check_out_time'])) {
return $this->error('请选择离店时间');
}
if (empty($formData['arrival_time']) || !strtotime($formData['arrival_time'])) {
return $this->error('请选择到店时间');
}
if (empty($formData['id_card'])) {
return $this->error('请输入身份证号');
}
$order_info['check_in_time'] = $formData['departure_time']; //入住时间
$order_info['check_out_time'] = $formData['return_time']; //离店时间
$order_info['arrival_time'] = $formData['arrival_time']; //到店时间
$order_info['id_card'] = $formData['id_card']; //身份证号
break;
case 2:
if (empty($formData['enter_time']) || !strtotime($formData['enter_time'])) {
return $this->error('请选择入园时间');
}
if (empty($formData['id_card'])) {
return $this->error('请输入身份证号');
}
$order_info['enter_time'] = $formData['enter_time']; //到店时间
$order_info['id_card'] = $formData['id_card']; //身份证号
break;
}
} else if ($ap->type == 1) {
}
//支付小程序的产品不允许购买
if (AdminSetting::val('payee_appid') == Agent::where('id', $this->agent_id)->value('appid')) {
return $this->error('系统出错了,购买失败~~');
@ -173,6 +235,15 @@ class OrderController extends Controller
throw new \Exception('供应产品库存不足');
}
//产品规格减表减库存
$affect_row = ProductSpec::query()
->where('stock', '>=', $formData['num']) //乐观锁
->where('id', $formData['spec_id'])
->decrement('stock', $formData['num']);
if (!$affect_row) {
throw new \Exception('你选择的产品规格库存不足');
}
//代理商产品表减库存
$affect_row = AgentProduct::query()
->where('stock', '>=', $formData['num']) //乐观锁
@ -220,12 +291,13 @@ class OrderController extends Controller
'agent_cloud_price' => $ap->agentCloudProduct->price ?? 0,
'prepay_price ' => $prepayPrice ?? 0,
'prepay_timeout' => $prepayTimeout ?? 0,
'service_persons' => SystemSetting::val('single', 'price')
'service_persons' => SystemSetting::val('single', 'price'),
'info' => $order_info,
]);
//存入订单产品表
$supplier_product_info = Product::whereIn('id', $product_ids)
->orderBy('id')->get(['id AS product_id', 'supplier_id', 'price','service_persons'])->toArray();
->orderBy('id')->get(['type', 'id AS product_id', 'supplier_id', 'price', 'service_persons'])->toArray();
$order_id = $order->id;
$agent_id = $this->agent_id;
@ -236,6 +308,10 @@ class OrderController extends Controller
$v['agent_id'] = $agent_id;
$v['agent_product_id'] = $agent_product_id;
$v['num'] = $formData['num'];
if ($v['type'] == 0) { //TODO 此处未处理组合产品
$v['product_spec_id'] = $formData['spec_id'];
}
unset($v['type']);
}
OrderProductItem::insert($supplier_product_info);

1
app/Models/Order.php

@ -14,6 +14,7 @@ class Order extends BaseModel
{
use HasFactory, SoftDeletes;
protected $guarded = ['created_at', 'updated_at']; //不可批量赋值的属性
protected $casts = ['info' => 'json'];
protected $dispatchesEvents = [
'updated' => OrderUpdated::class,

5
app/Models/Product.php

@ -49,4 +49,9 @@ class Product extends BaseModel
{
return $this->belongsTo(Category::class);
}
public function spec()
{
return $this->hasMany(ProductSpec::class);
}
}

24
app/Models/ProductSpec.php

@ -0,0 +1,24 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ProductSpec extends Model
{
use HasFactory;
protected $fillable = ['name', 'price', 'stock'];
public function __construct(array $attributes = [])
{
parent::__construct($attributes);
$this->timestamps = false;
}
public function product()
{
return $this->belongsTo(Product::class);
}
}
Loading…
Cancel
Save