6
0
Fork 0

Merge branch 'base' into develop

base
panliang 2023-10-17 13:39:42 +08:00
commit 15ced10bb1
11 changed files with 112 additions and 46 deletions

View File

@ -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);
}
}

View File

@ -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'))

View File

@ -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();

View File

@ -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);
});

View File

@ -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;
}

View File

@ -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',

View File

@ -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'),
];
}
}

View File

@ -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,
];
}

View File

@ -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,
];
}

View File

@ -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,
];
}
}

View File

@ -61,6 +61,7 @@ return [
'market_price' => '市场价',
'cost_price' => '成本价',
'profit_price' => '毛利',
'desk_id' => '桌号',
],
'options' => [
],