Merge branch 'base' into develop
commit
15ced10bb1
|
|
@ -14,6 +14,7 @@ use Dcat\Admin\Grid;
|
|||
use Dcat\Admin\Http\Controllers\AdminController;
|
||||
use Dcat\Admin\Show;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class ProductSkuController extends AdminController
|
||||
{
|
||||
|
|
@ -135,6 +136,13 @@ class ProductSkuController extends AdminController
|
|||
$form->select('attr_group')->options(ProductGroup::all()->pluck('name', 'id'));
|
||||
$form->selectAttr('attrs')->listen('attr_group');
|
||||
$form->hidden('verify_state');
|
||||
|
||||
$form->ignore(['attr_group']);
|
||||
$form->display('created_at');
|
||||
$form->display('updated_at');
|
||||
|
||||
$form->hidden('is_pre_sale')->default(0);
|
||||
|
||||
$form->saving(function (Form $form) {
|
||||
if (!(is_null($form->model()->release_at) || $form->model()->verify_state == 1)) {
|
||||
return $form->response()->error('当前sku商品无法修改');
|
||||
|
|
@ -142,11 +150,9 @@ class ProductSkuController extends AdminController
|
|||
$form->verify_state = 0;
|
||||
});
|
||||
|
||||
$form->ignore(['attr_group']);
|
||||
$form->display('created_at');
|
||||
$form->display('updated_at');
|
||||
|
||||
$form->hidden('is_pre_sale')->default(0);
|
||||
$form->disableEditingCheck();
|
||||
$form->disableCreatingCheck();
|
||||
$form->disableDeleteButton();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -179,4 +185,14 @@ class ProductSkuController extends AdminController
|
|||
})
|
||||
]);
|
||||
}
|
||||
|
||||
public function update($id)
|
||||
{
|
||||
$last = url()->previous();
|
||||
$redirect = null;
|
||||
if (Str::contains($last, 'product-spus')) {
|
||||
$redirect = admin_route('product_spus.sku_list', ['spu' => ProductSkuModel::where('id', $id)->value('spu_id')]);
|
||||
}
|
||||
return $this->form()->update($id, request()->all(), $redirect);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -229,12 +229,7 @@ class ProductSpuController extends AdminController
|
|||
|
||||
return parent::destroy($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
public function skuList(Content $content, ProductSpuModel $spu)
|
||||
{
|
||||
return $content->header(__('product-spu.labels.ProductSpu'))
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use App\Enums\PayWay;
|
|||
use Dcat\Admin\Layout\Row;
|
||||
use Dcat\Admin\Widgets\{Box, Tab, Card};
|
||||
use App\Constants\OrderStatus;
|
||||
use App\Models\Store\Store;
|
||||
use App\Models\Store\{Store, Desk};
|
||||
|
||||
class OrderController extends AdminController
|
||||
{
|
||||
|
|
@ -33,7 +33,7 @@ class OrderController extends AdminController
|
|||
|
||||
protected function grid()
|
||||
{
|
||||
$grid = new Grid(Order::with(['user', 'userInfo', 'inviter', 'inviterInfo', 'store']));
|
||||
$grid = new Grid(Order::with(['user', 'userInfo', 'inviter', 'inviterInfo', 'store', 'userCoupon']));
|
||||
|
||||
$user = Admin::user();
|
||||
$canAdmin = $this->canAdmin();
|
||||
|
|
@ -70,6 +70,7 @@ class OrderController extends AdminController
|
|||
$grid->column('market_price')->display(fn ($value) => bcdiv($value, 100, 2))->prepend('¥');
|
||||
$grid->column('cost_price')->display(fn ($value) => bcdiv($value, 100, 2))->prepend('¥');
|
||||
$grid->column('profit_price')->display(fn () => round(($this->total_amount - $this->cost_price) / 100, 2, PHP_ROUND_HALF_DOWN));
|
||||
$grid->column('user_coupon_id')->display(fn ($value) => $value ? data_get($this->userCoupon, 'coupon_name') . '(¥'.round($this->coupon_discount_amount/100, 2, PHP_ROUND_HALF_DOWN).')' : '');
|
||||
$grid->column('sales_value');
|
||||
$grid->column('order_status')->using($this->statusMap)->dot($this->statusColor);
|
||||
$grid->column('created_at');
|
||||
|
|
@ -108,6 +109,7 @@ class OrderController extends AdminController
|
|||
// PayWay::WxpayMiniProgram->value => PayWay::WxpayMiniProgram->text(),
|
||||
// PayWay::Offline->value => PayWay::Offline->text(),
|
||||
// ])->width(3);
|
||||
$filter->between('created_at')->dateTime()->width(6);
|
||||
$filter->where('order_status', function ($q) {
|
||||
switch ($this->input) {
|
||||
case OrderStatus::PENDING:
|
||||
|
|
@ -137,8 +139,9 @@ class OrderController extends AdminController
|
|||
OrderStatus::COMPLETED => '已完成',
|
||||
OrderStatus::CANCELLED => '已取消'
|
||||
])->width(3);
|
||||
$filter->between('created_at')->dateTime()->width(6);
|
||||
$filter->where('user_coupon_id', fn($q) => $this->input ? $q->whereNotNull('user_coupon_id') : $q->whereNull('user_coupon_id'))->select(['未使用', '已使用'])->width(3);
|
||||
$filter->between('completed_at')->dateTime()->width(6);
|
||||
$filter->where('pay_at', fn($q) => $this->input ? $q->whereNotNull('pay_at') : $q->whereNull('pay_at')->where('status', '!=', Order::STATUS_CANCELLED), '付款状态')->select(['待付款', '已付款'])->width(3);
|
||||
});
|
||||
|
||||
$grid->footer(function ($collection) use ($grid) {
|
||||
|
|
@ -175,35 +178,35 @@ class OrderController extends AdminController
|
|||
|
||||
protected function detail($id)
|
||||
{
|
||||
$show = Show::make($id, Order::with(['user', 'inviter']));
|
||||
$show = Show::make($id, Order::with(['user', 'inviter', 'userCoupon', 'source']));
|
||||
$model = $show->model();
|
||||
$show->field('id');
|
||||
$show->field('sn');
|
||||
$show->field('user.phone');
|
||||
$show->field('inviter.phone');
|
||||
$show->field('products_total_amount')->as(fn($value) => bcdiv($value, 100, 2))->prepend('¥');
|
||||
$show->field('total_amount')->as(fn ($value) => bcdiv($value, 100, 2));
|
||||
$show->field('market_price')->as(fn ($value) => bcdiv($value, 100, 2));
|
||||
$show->field('cost_price')->as(fn ($value) => bcdiv($value, 100, 2));
|
||||
$show->field('profit_price')->as(fn () => round(($this->total_amount - $this->cost_price) / 100, 2, PHP_ROUND_HALF_DOWN));
|
||||
$show->field('vip_discount_amount')->as(fn ($v) => bcdiv($v, 100, 2))->prepend('- ¥');
|
||||
|
||||
// 优惠券
|
||||
$show->field('user_coupon_id')->as(fn() => data_get($this->userCoupon, 'coupon_name'));
|
||||
$show->field('coupon_discount_amount')->as(fn($value) => bcdiv($value, 100, 2))->prepend('- ¥');
|
||||
|
||||
$userCouponId = $show->model()->user_coupon_id;
|
||||
if ($userCouponId) {
|
||||
$show->field('coupon_discount_amount')->as(fn($value) => bcdiv($value, 100, 2))->prepend('- ¥');
|
||||
}
|
||||
$show->field('shipping_fee')->as(fn ($v) => bcdiv($v, 100, 2))->prepend('+ ¥');
|
||||
$show->field('reduced_amount')->as(fn($value) => bcdiv($value, 100, 2))->prepend('- ¥');
|
||||
$show->field('total_amount', '支付金额')->as(fn($value) => bcdiv($value, 100, 2))->prepend('¥');
|
||||
$show->field('total_amount')->as(fn($value) => bcdiv($value, 100, 2))->prepend('¥');
|
||||
$show->field('sales_value');
|
||||
$show->field('order_status')->as(function ($v) {
|
||||
return $this->order_status;
|
||||
})->using($this->statusMap)->dot($this->statusColor);
|
||||
$show->field('pay_way')->as(function ($v) {
|
||||
return $this->pay_way?->mallText();
|
||||
})->circleDot(PayWay::colors());
|
||||
$show->field('order_status')->as(fn() => $this->order_status)->using($this->statusMap)->dot($this->statusColor);
|
||||
$show->field('pay_way')->as(fn() => $this->pay_way?->mallText())->circleDot(PayWay::colors());
|
||||
$show->field('created_at');
|
||||
$show->field('pay_at');
|
||||
$show->field('completed_at');
|
||||
|
||||
if ($model->source_type == Desk::class) {
|
||||
$show->field('desk_id')->as(fn() => data_get($model->source, 'name'));
|
||||
}
|
||||
|
||||
$show->panel()->tools(function (Show\Tools $tools) {
|
||||
$tools->disableEdit();
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ class StockTotalController extends AdminController
|
|||
$filter->equal('store_id', '门店')->select(Store::pluck('title', 'id'))->width(3);
|
||||
$filter->equal('category_id', '分类')->select(ProductCategory::selectOptions())->width(3);
|
||||
$filter->equal('product_name', '商品')->width(3);
|
||||
$filter->equal('tag_id', '类目')->select(StockLog::tags()->pluck('name', 'id'))->width(3);
|
||||
// $filter->in('tag_id', '类目')->multipleSelect(StockLog::tags()->pluck('name', 'id'))->width(3);
|
||||
$filter->between('date', '时间')->date()->width(6);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use App\Models\Store\{StockLog, ProductSku};
|
|||
use Dcat\Admin\Repositories\Repository;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class StoreTockRepository extends Repository
|
||||
{
|
||||
|
|
@ -30,6 +31,7 @@ class StoreTockRepository extends Repository
|
|||
$self = $stock->where('product_sku_id', $item->product_sku_id)->where('tag_id', StockLog::TAG_SELF)->sum('amount');
|
||||
$sell_price = data_get($item->productSku, 'sell_price') / 100;
|
||||
$cost_price = data_get($item->productSku, 'cost_price') / 100;
|
||||
$current_stock = data_get($item, 'amount');
|
||||
$subData = [
|
||||
'id' => $item->product_sku_id,
|
||||
'store_name' => data_get($item->store, 'title'),
|
||||
|
|
@ -38,7 +40,7 @@ class StoreTockRepository extends Repository
|
|||
'category_name' => data_get($item->productSku, 'category.name'),
|
||||
'cost_price' => $cost_price,
|
||||
'sell_price' => $sell_price,
|
||||
'stock' => data_get($item, 'amount'),
|
||||
'stock' => $current_stock,
|
||||
// 入库数
|
||||
'tag_in' => $in,
|
||||
// 销售数 = 提货数 + 发货数
|
||||
|
|
@ -53,8 +55,8 @@ class StoreTockRepository extends Repository
|
|||
'init_stock' => data_get($item->stockLog, 'balance', 0),
|
||||
// 调货数 = 出库数
|
||||
'tag_out' => $stock->where('product_sku_id', $item->product_sku_id)->where('tag_id', StockLog::TAG_OUT)->sum('amount'),
|
||||
// 毛利 = (入库数-报损数-自用数) x (售价-成本)
|
||||
'total_profit' => floor(($in - $loss - $self) * ($sell_price - $cost_price)),
|
||||
// 毛利 = 现有库存 x (售价-成本)
|
||||
'total_profit' => round($current_stock * ($sell_price - $cost_price), PHP_ROUND_HALF_DOWN),
|
||||
];
|
||||
array_push($data, $subData);
|
||||
}
|
||||
|
|
@ -69,17 +71,25 @@ class StoreTockRepository extends Repository
|
|||
'productSku.category',
|
||||
'stockLogs' => function ($q) use ($model) {
|
||||
$q->select('id', 'product_sku_id', DB::raw('abs(`amount`) as `amount`'), 'tag_id');
|
||||
if ($start = $model->filter()->input('date.start')) {
|
||||
$filter = $model->filter();
|
||||
if ($start = $filter->input('date.start')) {
|
||||
$start = Carbon::createFromFormat('Y-m-d', $start)->startOfDay();
|
||||
$q->where('created_at', '>=', $start);
|
||||
}
|
||||
if ($end = $model->filter()->input('date.end')) {
|
||||
if ($end = $filter->input('date.end')) {
|
||||
$end = Carbon::createFromFormat('Y-m-d', $end)->endOfDay();
|
||||
$q->where('created_at', '<=', $end);
|
||||
}
|
||||
if ($store_id = $model->filter()->input('store_id')) {
|
||||
if ($store_id = $filter->input('store_id')) {
|
||||
$q->where('store_id', $store_id);
|
||||
}
|
||||
// $tag_ids = data_get($filter->filters(), 3);
|
||||
// if ($tag_ids && $tag_ids->getValue()) {
|
||||
// $q->whereIn('tag_id', $tag_ids->getValue());
|
||||
// }
|
||||
if ($tag_id = $filter->input('tag_id')) {
|
||||
$q->where('tag_id', $tag_id);
|
||||
}
|
||||
},
|
||||
'stockLog' => function ($q) use ($model) {
|
||||
if ($store_id = $model->filter()->input('store_id')) {
|
||||
|
|
@ -134,7 +144,7 @@ class StoreTockRepository extends Repository
|
|||
'total_cost_price' => 0,
|
||||
// 现有总价值 = 库存 * 售价
|
||||
'total_sell_price' => 0,
|
||||
// 毛利 = (入库数-报损数-自用数) x (售价-成本)
|
||||
// 毛利 = 库存 x (售价-成本)
|
||||
'total_profit' => 0,
|
||||
];
|
||||
foreach ($list as $item) {
|
||||
|
|
@ -154,7 +164,7 @@ class StoreTockRepository extends Repository
|
|||
$data['total_out'] += $stock->where('product_sku_id', $item->product_sku_id)->where('tag_id', StockLog::TAG_OUT)->sum('amount') * $cost_price;
|
||||
$data['total_cost_price'] += $current_stock * $cost_price;
|
||||
$data['total_sell_price'] += $current_stock * $sell_price;
|
||||
$data['total_profit'] += ($in_amount - $loss_amount - $self_amount) * ($sell_price - $cost_price);
|
||||
$data['total_profit'] += $current_stock * ($sell_price - $cost_price);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,9 +56,7 @@ Route::group([
|
|||
$router->resource('product-spus', 'ProductSpuController')->names('product_spus');
|
||||
$router->get('product-spus/{spu}/sku-list', 'ProductSpuController@skuList')->name('product_spus.sku_list');
|
||||
|
||||
$router->resource('product-skus', 'ProductSkuController')->only([
|
||||
'index', 'edit', 'update', 'destroy',
|
||||
])->names('product_skus');
|
||||
$router->resource('product-skus', 'ProductSkuController')->only(['index', 'edit', 'update', 'destroy'])->names('product_skus');
|
||||
|
||||
$router->resource('product-sku-verifies', 'ProductSkuVerifyController')->only([
|
||||
'index', 'edit', 'update', 'destroy',
|
||||
|
|
|
|||
|
|
@ -20,4 +20,21 @@ class AliOssController extends Controller
|
|||
'domain'=>config('filesystems.disks.aliyun.domain'),
|
||||
], $aliStsService->createSts($request->user()?->phone)));
|
||||
}
|
||||
|
||||
public function signature(Request $request, AliStsService $aliStsService)
|
||||
{
|
||||
$request->validate([
|
||||
'filename' => 'required'
|
||||
]);
|
||||
$path = $request->input('path', 'uploads').'/'.date('Y-m-d');
|
||||
|
||||
$data = [
|
||||
"accessid" => "",
|
||||
"host" => "https://post-test.oss-cn-hangzhou.aliyuncs.com",
|
||||
"policy" => "eyJleHBpcmF0aW9uIjoiMjAxNS0xMS0wNVQyMDoyMzoyM1oiLCJjxb25kaXRpb25zIjpbWyJjcb250ZW50LWxlbmd0aC1yYW5nZSIsMCwxMDQ4NTc2MDAwXSxbInN0YXJ0cy13aXRoIiwiJGtleSIsInVzZXItZGlyXC8i****",
|
||||
"signature" => "VsxOcOudx******z93CLaXPz+4s=",
|
||||
"expire" => 1446727949,
|
||||
"dir" => $path.'/'.$request->input('filename'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,11 @@ class ProductSkuController extends Controller
|
|||
$user = $request->user();
|
||||
$spu = ProductSpu::with(['specs', 'features'])->findOrFail($id);
|
||||
|
||||
$sku = $spu->skus()->with(['buynote', 'spu'])->online()->first();
|
||||
$sku = $spu->skus()
|
||||
->with(['buynote', 'spu'])
|
||||
->online()
|
||||
->when($request->filled('sku_id'), fn($q) => $q->where('id', $request->input('sku_id')))
|
||||
->first();
|
||||
if (!$sku) {
|
||||
throw new BizException('商品sku未上架');
|
||||
}
|
||||
|
|
@ -96,7 +100,7 @@ class ProductSkuController extends Controller
|
|||
$spuSpecItems[] = [
|
||||
'name' => $value['name'],
|
||||
'selected' => $sku->is($mapSku),
|
||||
'sku_id' => (int) $mapSku?->id,
|
||||
'sku_id' => (int) $mapSku->id,
|
||||
'sku_stock' => (int) $mapSku?->saleable_stock,
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use App\Endpoint\Api\Http\Resources\ProductFeatureResource;
|
|||
use App\Events\ProductSkuViewed;
|
||||
use App\Models\Store\Desk;
|
||||
use App\Endpoint\Api\Http\Resources\DeskResource;
|
||||
use App\Exceptions\BizException;
|
||||
|
||||
class StoreController extends Controller
|
||||
{
|
||||
|
|
@ -44,7 +45,7 @@ class StoreController extends Controller
|
|||
$input['sort'] = '-id';
|
||||
}
|
||||
|
||||
$spuIds = StoreProductSku::where('store_id', $store->id)->where('status', 1)->pluck('product_spu_id')->toArray();
|
||||
$spuIds = StoreProductSku::where('store_id', $store->id)->where('amount', '>', 0)->where('status', 1)->pluck('product_spu_id')->toArray();
|
||||
$spuIds = array_unique($spuIds);
|
||||
$spuIds = array_values($spuIds);
|
||||
$list = ProductSpu::with(['specs'])->whereIn('id', $spuIds)->filter($input)->simplePaginate(Paginator::resolvePerPage('per_page', 20, 50));
|
||||
|
|
@ -66,7 +67,11 @@ class StoreController extends Controller
|
|||
$user = $request->user();
|
||||
$spu = $store->productSpus()->with(['specs', 'features'])->findOrFail($id);
|
||||
|
||||
$sku = $store->productSkus()->where('product_spu_id', $spu->id)->first();
|
||||
$sku = $store->productSkus()
|
||||
->where('product_spu_id', $spu->id)
|
||||
->where('amount', '>', 0)
|
||||
->when($request->filled('sku_id'), fn($q) => $q->where('product_sku_id', $request->input('sku_id')))
|
||||
->first();
|
||||
if (!$sku) {
|
||||
throw new BizException('商品sku未上架');
|
||||
}
|
||||
|
|
@ -74,7 +79,7 @@ class StoreController extends Controller
|
|||
$spuSpecs = [];
|
||||
|
||||
if (count($original = (array) $sku->specs) > 0) {
|
||||
$skus = $spu->skus()->get(['id', 'specs', 'stock', 'release_at']);
|
||||
$skus = $store->productSkus()->where('product_spu_id', $spu->id)->where('status', 1)->get();
|
||||
|
||||
$mapSkus = $skus->mapWithKeys(function ($item) {
|
||||
$key = implode('_', $item->specs) ?: $item->id;
|
||||
|
|
@ -92,12 +97,13 @@ class StoreController extends Controller
|
|||
|
||||
$key = implode('_', $jSpecs);
|
||||
$mapSku = $mapSkus->get($key);
|
||||
if ($mapSku) {
|
||||
$stock = (int) data_get($mapSku?->pivot, 'amount');
|
||||
if ($mapSku && $stock > 0) {
|
||||
$spuSpecItems[] = [
|
||||
'name' => $value['name'],
|
||||
'selected' => $sku->is($mapSku),
|
||||
'sku_id' => (int) $mapSku?->id,
|
||||
'sku_stock' => (int) $mapSku?->saleable_stock,
|
||||
'sku_id' => (int) $mapSku->id,
|
||||
'sku_stock' => $stock,
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -66,4 +66,18 @@ class AliStsService
|
|||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
public function signatureUpload($file)
|
||||
{
|
||||
$config = config('filesystems.disks.aliyun');
|
||||
$host = (data_get($config, 'use_ssl') ? 'https://' : 'http://') . data_get($config, 'bucket') . '.' . data_get($config, 'endpoint');
|
||||
$data = [
|
||||
"accessid" => $this->accessId,
|
||||
"host" => $host,
|
||||
"policy" => "eyJleHBpcmF0aW9uIjoiMjAxNS0xMS0wNVQyMDoyMzoyM1oiLCJjxb25kaXRpb25zIjpbWyJjcb250ZW50LWxlbmd0aC1yYW5nZSIsMCwxMDQ4NTc2MDAwXSxbInN0YXJ0cy13aXRoIiwiJGtleSIsInVzZXItZGlyXC8i****",
|
||||
"signature" => "VsxOcOudx******z93CLaXPz+4s=",
|
||||
"expire" => 1446727949,
|
||||
"dir" => $file,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ return [
|
|||
'market_price' => '市场价',
|
||||
'cost_price' => '成本价',
|
||||
'profit_price' => '毛利',
|
||||
'desk_id' => '桌号',
|
||||
],
|
||||
'options' => [
|
||||
],
|
||||
|
|
|
|||
Loading…
Reference in New Issue