6
0
Fork 0

小票机管理

base
panliang 2023-02-23 16:28:44 +08:00
parent 653bd1cc13
commit f38b5773d4
26 changed files with 902 additions and 17 deletions

View File

@ -0,0 +1,27 @@
<?php
namespace App\Admin\Actions\Store;
use Dcat\Admin\Grid\RowAction;
use App\Models\Store\Desk;
class RowDeskWxCode extends RowAction
{
protected $title = '生成小程序码';
public function handle()
{
$model = Desk::findOrFail($this->getKey());
$result = $model->generateWxCode();
if ($result !== true) {
return $this->response()->error(data_get($result, 'errmsg'))->refresh();
}
return $this->response()->success('操作成功')->refresh();
}
public function confirm()
{
return ['是否确定?'];
}
}

View File

@ -0,0 +1,90 @@
<?php
namespace App\Admin\Controllers\Store;
use Dcat\Admin\{Form, Grid, Admin, Show};
use Dcat\Admin\Http\Controllers\AdminController;
use App\Models\Store\{Store, Desk};
use App\Models\{ProductCategory};
class DeskController extends AdminController
{
protected $translation = 'store-desk';
protected function grid()
{
return Grid::make(Desk::with(['store']), function (Grid $grid) {
$grid->model()->orderBy('created_at', 'desc');
$grid->column('id');
$grid->column('store_id')->display(fn() => data_get($this->store, 'title'));
$grid->column('name');
// $grid->column('status')->switch();
$grid->column('wxcode')->image('', 100, 100);
$grid->column('remarks')->editable();
$user = Admin::user();
$grid->showViewButton($user->can('dcat.admin.store.desk.show'));
$grid->showCreateButton($user->can('dcat.admin.store.desk.create'));
$grid->showEditButton($user->can('dcat.admin.store.desk.edit'));
$grid->showDeleteButton($user->can('dcat.admin.store.desk.destroy'));
$grid->filter(function (Grid\Filter $filter) {
$filter->panel();
$filter->equal('store_id')->select('api/store')->width(3);
$filter->like('name')->width(3);
});
$grid->actions(new \App\Admin\Actions\Store\RowDeskWxCode());
});
}
protected function form()
{
return Form::make(new Desk(), function (Form $form) {
$form->select('store_id')->options(Store::pluck('title', 'id'))->required();
$form->text('name')->required();
// $form->switch('status')->default(1);
$form->text('remarks');
$form->embeds('extra', function (Form\EmbeddedForm $form) {
$form->select('category_id')->options(ProductCategory::selectOptions());
});
$form->disableCreatingCheck();
$form->disableEditingCheck();
$form->disableDeleteButton();
$form->disableResetButton();
$form->saved(function (Form $form, $result) {
// 新增桌号, 生成小程序码
if ($form->isCreating()) {
}
});
});
}
protected function detail($id)
{
return Show::make($id, Desk::with(['store']), function (Show $show) {
$show->field('id');
$show->field('store_id')->as(fn() => data_get($this->store, 'name'));
$show->field('name');
// $show->field('status')->bool();
$show->field('wxcode');
$show->field('remarks');
$model = $show->model();
$category_id = data_get($model->extra, 'category_id');
if ($category_id) {
$category = ProductCategory::find($category_id);
$show->field('category_id')->as(fn() => $category ? $category->name : $category_id);
}
$show->disableEditButton();
$show->disableDeleteButton();
});
}
}

View File

@ -0,0 +1,99 @@
<?php
namespace App\Admin\Controllers\Store;
use Dcat\Admin\{Form, Grid, Admin, Show};
use Dcat\Admin\Http\Controllers\AdminController;
use App\Models\Store\{Store, Device, DeviceRecord};
use Illuminate\Validation\Rule;
class DeviceController extends AdminController
{
protected $translation = 'store-device';
protected function grid()
{
return Grid::make(Device::with(['store']), function (Grid $grid) {
$grid->model()->orderBy('id', 'desc');
$grid->column('store_id')->display(fn () => data_get($this->store, 'title'));
$grid->column('name');
$grid->column('device_no');
$grid->column('status')->switch();
$grid->column('remarks')->editable();
$user = Admin::user();
$grid->showViewButton($user->can('dcat.admin.store.device.show'));
$grid->showCreateButton($user->can('dcat.admin.store.device.create'));
$grid->showEditButton($user->can('dcat.admin.store.device.edit'));
$grid->showDeleteButton($user->can('dcat.admin.store.device.destroy'));
$grid->filter(function (Grid\Filter $filter) {
$filter->panel();
$filter->equal('store_id')->select('api/store')->width(3);
$filter->where('name', function ($q) {
$input = $this->input;
$q->where(fn($q1) => $q1->where('name', 'like', '%'.$input.'%')->orWhere('device_no', 'like', '%'.$input.'%'));
})->placeholder('名称或者设备编号')->width(3);
});
});
}
protected function form()
{
return Form::make(new Device(), function (Form $form) {
$unique = Rule::unique('store_devices', 'device_no');
if ($form->isEditing()) {
$unique->ignore($form->getKey());
}
$form->select('store_id')->options(Store::pluck('title', 'id'))->required();
$form->text('name')->required();
$form->text('device_no')->rules([$unique])->required();
$form->switch('status')->default(1);
$form->text('remarks');
$form->disableCreatingCheck();
$form->disableEditingCheck();
$form->disableDeleteButton();
$form->disableResetButton();
$form->deleted(function (Form $form, $result) {
$data = array_column($form->model()->toArray(), 'id');
// 删除设备记录
DeviceRecord::whereIn('device_id', $data)->delete();
});
});
}
protected function detail($id)
{
return Show::make($id, Device::with(['store']), function (Show $show) {
$show->field('id');
$show->field('store_id');
$show->field('name');
$show->field('device_no');
$show->field('status')->bool();
$show->field('remarks');
$show->disableEditButton();
$show->disableDeleteButton();
$show->relation('records', function ($model) {
$grid = new Grid(new DeviceRecord());
$grid->model()->where('device_id', $model->id)->orderBy('created_at', 'desc');
$grid->column('status')->using(DeviceRecord::$statusMap)->label(DeviceRecord::$statusColor);
$grid->column('data')->display(fn($v) => json_encode($v, JSON_UNESCAPED_UNICODE));
// $grid->column('result')->display(fn($v) => json_encode($v, JSON_UNESCAPED_UNICODE));
$grid->column('created_at');
$grid->disableActions();
$grid->disableCreateButton();
return $grid;
});
});
}
}

View File

@ -194,8 +194,9 @@ class OrderController extends AdminController
$show->field('pay_way')->as(function ($v) {
return $this->pay_way?->mallText();
})->circleDot(PayWay::colors());
$show->field('pay_at');
$show->field('created_at');
$show->field('pay_at');
$show->field('completed_at');
$show->panel()->tools(function ($tools) {
$tools->disableEdit();

View File

@ -164,4 +164,21 @@ class OrderPackageService
]);
}
}
/**
* 订单全部发货
*
* @param Order $order
*
* @return OrderPackage $package
*/
public function createAll(Order $order, $params = [])
{
$shipping_company = data_get($params, 'shipping_company');
$shipping_number = data_get($params, 'shipping_number');
$products = [];
foreach($order->products as $item) {
}
}
}

View File

@ -194,6 +194,8 @@ Route::group([
$router->resource('store/order', 'Store\OrderController')->only(['index', 'show'])->names('store.order');
$router->resource('store/stock', 'Store\StockController')->only(['index', 'create', 'store', 'show'])->names('store.stock');
$router->resource('store/batch', 'Store\StockBatchController')->names('store.batch');
$router->resource('store/device', 'Store\DeviceController')->names('store.device');
$router->resource('store/desk', 'Store\DeskController')->names('store.desk');
$router->resource('profit', 'OrderProfitController');

View File

@ -58,6 +58,10 @@ class OrderController extends Controller
'product.sku_id' => ['bail', 'required', 'int'],
'product.quantity' => ['bail', 'required', 'int', 'min:1'],
],
$request->filled('store_id') => [
'products.*.sku_id' => ['bail', 'required', 'int'],
'products.*.quantity' => ['bail', 'required', 'int', 'min:1'],
],
default => [
'shopping_cart' => ['bail', 'required', 'array'],
]
@ -77,6 +81,16 @@ class OrderController extends Controller
$orderService = new OrderService();
return match (true) {
$request->filled('store_id') => $orderService->createOrderByStore(
$user,
$request->input('store_id'),
$request->input('products'),
[
'desk' => $request->input('desk'),
'note' => $request->input('note'),
'coupon_id' => $request->input('coupon_id'),
]
),
$request->filled('order_pre') => $orderService->createOrderByPre($user, OrderPre::findOrFail($request->input('order_pre')), $request->input('coupon_id'), $request->input('note')),
$request->filled('product') => $orderService->createQuickOrder(
$user,

View File

@ -10,6 +10,8 @@ use App\Models\Store\ProductSku as StoreProductSku;
use App\Endpoint\Api\Http\Resources\{StoreResource, StoreProductSkuResource, StoreProductSpuResource, ProductSpuResource};
use App\Endpoint\Api\Http\Resources\ProductFeatureResource;
use App\Events\ProductSkuViewed;
use App\Models\Store\Desk;
use App\Endpoint\Api\Http\Resources\DeskResource;
class StoreController extends Controller
{
@ -149,4 +151,10 @@ class StoreController extends Controller
return StoreProductSkuResource::make($sku);
}
public function desk($id)
{
$info = Desk::with(['store'])->findOrFail($id);
return DeskResource::make($info);
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace App\Endpoint\Api\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class DeskResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'extra' => $this->extra,
'name' => $this->name,
'remarks' => $this->remarks,
'status' => $this->status,
'store_id' => $this->store_id,
'wxcode' => $this->wxcode,
'store' => StoreResource::make($this->whenLoaded('store')),
];
}
}

View File

@ -233,6 +233,9 @@ Route::group([
Route::get('store/{store}/product-sku/{id}', [StoreController::class, 'productSku']);
Route::apiResource('store', StoreController::class)->only(['index', 'show']);
// 门店桌号信息
Route::get('store/desk/{id}', [StoreController::class, 'desk']);
// 门店下单
Route::group(['middleware' => ['auth:api', \App\Endpoint\Api\Http\Middleware\CheckUserStatus::class]], function () {
Route::get('order-pre/{id}', [App\Endpoint\Api\Http\Controllers\Order\OrderPreController::class, 'show']);

View File

@ -0,0 +1,64 @@
<?php
namespace App\Listeners;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use App\Models\Order;
use App\Models\Store\{Desk, DeviceRecord};
use App\Services\PrintService;
/**
* 打印订单小票
*/
class OrderPrint
{
public function handle($event)
{
$order = $event->order;
// 门店订单, 桌号信息
if ($order->store_id && $order->source_type == Desk::class) {
$store = $order->store;
$desk = $order->source;
// 门店设备
$devices = $store->devices()->where('status', 1)->get();
$templateId = app_settings('custom.key_value.order_desk_print_template');
if ($devices->count() > 0 && $templateId) {
$service = PrintService::make();
$products = [];
foreach($order->products as $item) {
array_push($products, [
'name' => $item->name,
'price' => round($item->sell_price / 100, 2, PHP_ROUND_HALF_DOWN),
'amount' => $item->quantity,
'money' => round($item->total_amount / 100, 2, PHP_ROUND_HALF_DOWN),
]);
}
$data = [
'name' => $store->title,
'sn' => $order->sn,
'time' => $order->created_at->format('Y-m-d H:i:s'),
'desk' => $desk->name,
'products' => $products,
'total' => round($order->total_amount, 2, PHP_ROUND_HALF_DOWN),
'remarks' => $order->note,
];
foreach($devices as $item) {
$result = $service->template($item->device_no, $templateId, $data);
$status = data_get($result, 'code') == 0 ? DeviceRecord::STATUS_SUCCESS : DeviceRecord::STATUS_FAIL;
// 添加打印的日志记录
$item->records()->create([
'data' => $data,
'device_id' => $item->id,
'result' => $result,
'resource_id' => $order->id,
'resource_type' => $order->getMorphClass(),
'status' => $status,
'store_id' => $store->id
]);
}
}
}
}
}

View File

@ -0,0 +1,64 @@
<?php
namespace App\Models\Store;
use Illuminate\Database\Eloquent\Model;
use Dcat\Admin\Traits\HasDateTimeFormatter;
use EasyWeChat\Kernel\Http\StreamResponse;
use Illuminate\Support\Facades\Storage;
class Desk extends Model
{
use HasDateTimeFormatter;
protected $table = 'store_desks';
protected $fillable = ['extra', 'name', 'remarks', 'status', 'store_id', 'wxcode'];
protected $casts = [
'extra' => 'json'
];
public function store()
{
return $this->belongsTo(Store::class, 'store_id');
}
public function generateWxCode()
{
$model = $this;
$scene = http_build_query([
'd' => $model->id,
'c' => data_get($model->extra, 'category_id'),
's' => $model->store_id
]);
if (config('app.env') == 'local') {
$url = 'https://ui-avatars.com/api/?name=pd&scene=' . urlencode($scene);
} else {
// 生成小程序码
$app = \EasyWeChat\Factory::miniProgram(config('wechat.mini_program.default'));
$response = $app->app_code->getUnlimit($scene, [
'page' => 'pages/welcome/index',
'check_path' => false,
// release: 正式版, develop: 开发版, trial: 体验版
'env_version' => config('app.debug') ? 'trial' : 'release',
'width' => 200,
]);
// 保存小程序码
if ($response instanceof StreamResponse) {
$disk = Storage::disk('public');
$filepath = 'store-desk';
$filename = $model->id . '.png';
$response->saveAs($disk->path($filepath), $filename);
$url = $disk->url($filepath . '/' . $filename);
} else {
logger('store-desk 小程序码生成失败', $response);
return $response;
}
}
$model->update(['wxcode' => $url]);
return true;
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace App\Models\Store;
use Illuminate\Database\Eloquent\Model;
use Dcat\Admin\Traits\HasDateTimeFormatter;
class Device extends Model
{
use HasDateTimeFormatter;
protected $table = 'store_devices';
protected $fillable = ['device_no', 'extra', 'name', 'remarks', 'status', 'store_id', 'type'];
protected $casts = [
'extra' => 'json'
];
protected $attributes = [
'type' => 'print',
'status' => 1
];
public function store()
{
return $this->belongsTo(Store::class, 'store_id');
}
public function records()
{
return $this->hasMany(DeviceRecord::class, 'device_id');
}
}

View File

@ -0,0 +1,51 @@
<?php
namespace App\Models\Store;
use Illuminate\Database\Eloquent\Model;
use Dcat\Admin\Traits\HasDateTimeFormatter;
class DeviceRecord extends Model
{
use HasDateTimeFormatter;
public const STATUS_PROCESSING = 0;
public const STATUS_SUCCESS = 1;
public const STATUS_FAIL = 2;
protected $table = 'store_device_records';
protected $fillable = ['data', 'device_id', 'result', 'resource_id', 'resource_type', 'status', 'store_id'];
protected $casts = [
'result' => 'json',
'data' => 'json',
];
public static $statusMap = [
self::STATUS_PROCESSING => '处理中',
self::STATUS_SUCCESS => '成功',
self::STATUS_FAIL => '失败',
];
public static $statusColor = [
self::STATUS_PROCESSING => 'primary',
self::STATUS_SUCCESS => 'success',
self::STATUS_FAIL => 'danger',
];
public function device()
{
return $this->belongsTo(Device::class, 'device_id');
}
public function store()
{
return $this->belongsTo(Store::class, 'store_id');
}
public function resource()
{
return $this->morphTo();
}
}

View File

@ -49,6 +49,16 @@ class Store extends Model
return $this->hasMany(StockLog::class, 'store_id');
}
public function desks()
{
return $this->hasMany(Desk::class, 'store_id');
}
public function devices()
{
return $this->hasMany(Device::class, 'store_id');
}
public function scopeEffective($q)
{
return $q->where('status', 1);

View File

@ -20,7 +20,8 @@ class EventServiceProvider extends ServiceProvider
\App\Listeners\OrderPaidNotify::class,
\App\Listeners\SendCoupons::class,
\App\Listeners\OrderPackage::class,
\App\Listeners\OrderDistribute::class
\App\Listeners\OrderDistribute::class,
\App\Listeners\OrderPrint::class,
],
];

View File

@ -21,7 +21,7 @@ use App\Models\ProductSku;
use App\Models\ShippingAddress;
use App\Models\SocialiteUser;
use App\Models\{User, OrderPre, Tag};
use App\Models\Store\Store;
use App\Models\Store\{Store, Desk};
use App\Models\UserCoupon;
use App\Services\Payment\WxpayService;
use Illuminate\Database\Eloquent\Builder;
@ -171,8 +171,7 @@ class OrderService
}
/**
* 添加店铺订单
*
* 预订单, 扫码下单
*/
public function createOrderByPre(User $user, OrderPre $order_pre, $coupon_id = null, $note = null)
{
@ -236,6 +235,100 @@ class OrderService
return $order;
}
/**
* 门店直接下单
*
* @param User $user
* @param int $storeId
* @param array $products 商品信息 [{sku_id, quantity}]
* @param array $params {coupon_id: 优惠券id, desk: 桌号id}
*
* @return Order
* @throws BizException
*/
public function createOrderByStore(User $user, $storeId, array $products, array $params = [])
{
$store = Store::find($storeId);
if (!$store) {
throw new BizException('门店不存在');
}
if (!$store->status) {
throw new BizException('门店: '.$store->title.' 已关闭');
}
$coupon_id = data_get($params, 'coupon_id');
$note = data_get($params, 'note');
$sourceType = Store::class;
$sourceId = $store->id;
// 桌号下单
if ($deskId = data_get($params, 'desk')) {
$desk = $store->desks()->find($deskId);
if (!$desk) {
throw new BizException('门店桌号不存在');
}
if (!$desk->status) {
throw new BizException('门店桌号: '.$desk->name.' 已关闭');
}
$sourceType = Desk::class;
$sourceId = $desk->id;
}
// 检查门店商品库存
$skuList = $store->productSkus;
foreach($products as &$item) {
$sku = $skuList->firstWhere('id', $item['sku_id']);
if (!$sku) {
throw new BizException('门店商品: '.$item->name.' 不存在');
}
if ($sku->pivot->amount < $item['quantity']) {
throw new BizException('门店商品: '.$item->name.' 库存不足');
}
$item['sku'] = $sku;
}
// 优惠券
$coupon = null;
if ($coupon_id) {
$coupon = $user->coupons()->onlyAvailable()->lockForUpdate()->findOrFail($coupon_id);
}
$mapProducts = $this->mapProducts($user, $products, $coupon);
list($productsTotalAmount, $vipDiscountAmount, $couponDiscountAmount, $salesValue) = $this->calculateFees($mapProducts);
$order = $this->storeOrder(
$user,
$productsTotalAmount,
$couponDiscountAmount,
$vipDiscountAmount,
0,
$salesValue,
null,
$note,
$coupon,
null,
$mapProducts
);
$order->update([
'store_id' => $store->id,
'source_type' => $sourceType,
'source_id' => $sourceId,
]);
$this->storeOrderProducts($order, $mapProducts);
// 将优惠券标记为已使用
$coupon?->markAsUse();
if ($order->total_amount === 0) {
$this->pay($order, PayWay::Balance);
$order->refresh();
}
return $order;
}
/**
* 保存订单
*

View File

@ -0,0 +1,88 @@
<?php
namespace App\Services;
use Illuminate\Support\Facades\Http;
/**
* 佳博云打印
* https://dev.poscom.cn/docs
*/
class PrintService
{
protected $memberCode;
protected $apiKey;
function __construct()
{
$this->memberCode = config('postcom.memberCode');
$this->apiKey = config('postcom.apiKey');
}
/**
* 通过模板打印
* https://dev.poscom.cn/openapi?templetPrint
*
* @param string $deviceID
* @param string $templetID
* @param array $data
*
* @return array {code: 0(成功), msg: '错误信息'}
*/
public function template($deviceID, $templetID, $data)
{
$result = ['code' => 0, 'msg' => ''];
if (config('app.env') === 'local') {
return $result;
}
$url = 'https://api.poscom.cn/apisc/templetPrint';
$params = $this->params(['deviceID' => $deviceID]);
$params['templetID'] = $templetID;
$params['tData'] = json_encode($data);
$response = Http::asForm()->post($url, $params);
if ($response->successful()) {
$result = $response->json();
} else {
$result['code'] = 1;
$result['msg'] = '请求失败: ' . $response->status();
}
return $result;
}
/**
* 构造请求参数
*
* @param array $data {deviceID: 终端编号}
* @return array
*/
protected function params($data = [])
{
$reqTime = $this->getMillisecond();
$deviceID = data_get($data, 'deviceID');
$memberCode = $this->memberCode;
$msgNo = '';
$securityCode = md5($memberCode.$deviceID.$msgNo.$reqTime.$this->apiKey);
return [
'reqTime' => $reqTime,
'securityCode' => $securityCode,
'memberCode' => $memberCode,
'deviceID' => $deviceID,
];
}
protected function getMillisecond()
{
list($t1, $t2) = explode(' ', microtime());
return (float)sprintf('%.0f',(floatval($t1)+floatval($t2))*1000);
}
/**
* @return PrintService
*/
public static function make(...$params)
{
return new static(...$params);
}
}

View File

@ -0,0 +1,6 @@
<?php
return [
'member_code' => env('POSTCOM_MEMBER_CODE'),
'api_key' => env('POSTCOM_API_KEY'),
];

View File

@ -0,0 +1,27 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use App\Models\Store\{Store, Device};
class StoreDeviceFactory extends Factory
{
protected $model = Device::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
do {
$code = $this->faker->isbn10();
} while(Device::where('device_no', $code)->exists());
return [
'device_no' => $code,
'name' => $code,
'store_id' => Store::inRandomOrder()->value('id')
];
}
}

View File

@ -0,0 +1,36 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use App\Models\Store\{Device, DeviceRecord};
class StoreDeviceRecordFactory extends Factory
{
protected $model = DeviceRecord::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
$device = Device::inRandomOrder()->first();
$status = $this->faker->randomElement([DeviceRecord::STATUS_SUCCESS, DeviceRecord::STATUS_FAIL]);
$data = [
'title' => $this->faker->word(),
'description' => $this->faker->sentence(),
'content' => $this->faker->paragraph(),
];
$result_success = ['code' => 0, 'msg' => '成功'];
$result_fail = ['code' => 1, 'msg' => '请求超时'];
return [
'data' => $data,
'device_id' => $device->id,
'result' => $status ? $result_success : $result_fail,
'status' => $status,
'store_id' => $device->store_id,
];
}
}

View File

@ -0,0 +1,62 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePrintDeskTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('store_devices', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('store_id')->comment('门店 stores.id');
$table->string('type')->default('print')->comment('设备类型(print: 小票打印机)');
$table->string('name')->comment('设备名称');
$table->string('device_no')->comment('设备编号');
$table->unsignedTinyInteger('status')->default(0)->comment('状态(0: 不可用, 1: 可用)');
$table->string('remarks')->nullable()->comment('备注');
$table->json('extra')->nullable()->comment('其他配置');
$table->timestamps();
});
Schema::create('store_device_records', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('store_id')->comment('门店 stores.id');
$table->unsignedBigInteger('device_id')->comment('设备 store_devices.id');
$table->json('result')->nullable()->comment('返回的结果');
$table->json('data')->nullable()->comment('请求内容');
$table->unsignedTinyInteger('status')->default(0)->comment('状态(0: 处理中, 1: 成功, 2: 失败)');
$table->nullableMorphs('resource');
$table->timestamps();
});
Schema::create('store_desks', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('store_id')->comment('门店 stores.id');
$table->string('name')->comment('名称');
$table->unsignedTinyInteger('status')->default(0)->comment('状态(0: 不可用, 1: 可用)');
$table->string('wxcode')->nullable()->comment('小程序码');
$table->string('remarks')->nullable()->comment('备注');
$table->json('extra')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('store_devices');
Schema::dropIfExists('store_device_records');
Schema::dropIfExists('store_desks');
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\Store\{Store, Device, DeviceRecord};
use Database\Factories\{StoreDeviceFactory, StoreDeviceRecordFactory};
class StoreDeviceSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
Device::truncate();
DeviceRecord::truncate();
(new StoreDeviceFactory())->count(10)->create();
(new StoreDeviceRecordFactory())->count(100)->create();
}
}

View File

@ -0,0 +1,20 @@
<?php
return [
'labels' => [
'store' => '门店管理',
'Desk' => '桌号管理',
'desk' => '桌号管理',
],
'fields' => [
'store_id' => '门店',
'name' => '名称',
'status' => '状态',
'remarks' => '备注',
'extra' => '其他',
'wxcode' => '小程序码',
'category_id' => '商品分类'
],
'options' => [
],
];

View File

@ -0,0 +1,22 @@
<?php
return [
'labels' => [
'store' => '门店管理',
'Device' => '设备管理',
'device' => '设备管理',
],
'fields' => [
'store_id' => '门店',
'name' => '名称',
'device_no' => '编号',
'status' => '状态',
'remarks' => '备注',
'extra' => '其他',
'records' => '日志',
'data' => '发送',
'result' => '接收',
],
'options' => [
],
];

View File

@ -2,11 +2,8 @@
namespace Tests\Feature;
use App\Models\OrderProfit;
use App\Services\DistributeService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Tests\TestCase;
use App\Services\PrintService;
class ExampleTest extends TestCase
{
@ -17,13 +14,17 @@ class ExampleTest extends TestCase
*/
public function test_example()
{
$service = new DistributeService();
try {
DB::beginTransaction();
$service->wechatTransfers(OrderProfit::whereIn('id', [1, 5])->get());
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
}
dd(PrintService::make()->template('00596456352258754', 'a4fcc59f40fd438d9afdd4fc2e9b99fc', [
'name' => '乡村基',
'sn' => '20230223133856127032',
'time' => '2023-02-23 13:38:56',
'desk' => '10号桌',
'products' => [
['name' => '香草拿铁(大杯)', 'price' => '32.00', 'amount' => '1', 'money' => '32.00'],
['name' => '西瓜汁(大杯)', 'price' => '18.00', 'amount' => '1', 'money' => '18.00'],
],
'total' => '50.00',
'remarks' => '打包'
]));
}
}