初始化项目
This commit is contained in:
18
.editorconfig
Normal file
18
.editorconfig
Normal file
@@ -0,0 +1,18 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.{yml,yaml}]
|
||||
indent_size = 2
|
||||
|
||||
[docker-compose.yml]
|
||||
indent_size = 4
|
||||
94
.env.example
Normal file
94
.env.example
Normal file
@@ -0,0 +1,94 @@
|
||||
APP_NAME=xiaokang
|
||||
APP_ENV=local
|
||||
APP_KEY=
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://xiaokang.test
|
||||
APP_BEIAN=
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_DEPRECATIONS_CHANNEL=null
|
||||
LOG_LEVEL=debug
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=xiaokang
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=root
|
||||
DB_PREFIX=
|
||||
|
||||
BROADCAST_DRIVER=log
|
||||
CACHE_DRIVER=file
|
||||
FILESYSTEM_DISK=local
|
||||
QUEUE_CONNECTION=sync
|
||||
SESSION_DRIVER=file
|
||||
SESSION_LIFETIME=120
|
||||
|
||||
MEMCACHED_HOST=127.0.0.1
|
||||
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
REDIS_DB=1
|
||||
REDIS_CACHE_DB=1
|
||||
|
||||
MAIL_MAILER=smtp
|
||||
MAIL_HOST=mailhog
|
||||
MAIL_PORT=1025
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
MAIL_FROM_ADDRESS="hello@example.com"
|
||||
MAIL_FROM_NAME="${APP_NAME}"
|
||||
|
||||
AWS_ACCESS_KEY_ID=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
AWS_DEFAULT_REGION=us-east-1
|
||||
AWS_BUCKET=
|
||||
AWS_USE_PATH_STYLE_ENDPOINT=false
|
||||
|
||||
PUSHER_APP_ID=
|
||||
PUSHER_APP_KEY=
|
||||
PUSHER_APP_SECRET=
|
||||
PUSHER_HOST=
|
||||
PUSHER_PORT=443
|
||||
PUSHER_SCHEME=https
|
||||
PUSHER_APP_CLUSTER=mt1
|
||||
|
||||
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||
VITE_PUSHER_HOST="${PUSHER_HOST}"
|
||||
VITE_PUSHER_PORT="${PUSHER_PORT}"
|
||||
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
|
||||
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||
|
||||
#########################################
|
||||
# 附加配置
|
||||
#########################################
|
||||
|
||||
# 微信小程序
|
||||
## 用户端
|
||||
MEMBER_WECHAT_MINI_APP_APPID=
|
||||
MEMBER_WECHAT_MINI_APP_SECRET=
|
||||
## 医生端
|
||||
SERVICE_WECHAT_MINI_APP_APPID=
|
||||
SERVICE_WECHAT_MINI_APP_SECRET=
|
||||
|
||||
# 支付
|
||||
## 微信支付
|
||||
PAY_WECHAT_MCH_ID=
|
||||
PAY_WECHAT_MCH_SECRET_KEY=
|
||||
PAY_WECHAT_MCH_SECRET_CERT=
|
||||
PAY_WECHAT_MCH_PUBLIC_CERT_PATH=
|
||||
PAY_WECHAT_MINI_APP_ID=
|
||||
|
||||
# 物流
|
||||
EXPRESS_KEY=
|
||||
EXPRESS_CUSTOMER=
|
||||
|
||||
# 内部服务API密钥
|
||||
INTERNAL_SERVICE_API_TOKEN=
|
||||
|
||||
# 开发配置
|
||||
SQL_LOGGER_ALL_QUERIES_ENABLED=false
|
||||
SQL_LOGGER_SLOW_QUERIES_ENABLED=false
|
||||
QUERY_DETECTOR_ENABLED=false
|
||||
11
.gitattributes
vendored
Normal file
11
.gitattributes
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
* text=auto
|
||||
|
||||
*.blade.php diff=html
|
||||
*.css diff=css
|
||||
*.html diff=html
|
||||
*.md diff=markdown
|
||||
*.php diff=php
|
||||
|
||||
/.github export-ignore
|
||||
CHANGELOG.md export-ignore
|
||||
.styleci.yml export-ignore
|
||||
27
.gitignore
vendored
Normal file
27
.gitignore
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/node_modules
|
||||
/public/build
|
||||
/public/hot
|
||||
/public/storage
|
||||
/storage/*.key
|
||||
lang/*
|
||||
!lang/en/
|
||||
!lang/zh_CN/
|
||||
!lang/en.json
|
||||
!lang/zh_CN.json
|
||||
public/uploads
|
||||
public/vendor
|
||||
.env
|
||||
.env.backup
|
||||
.env.production
|
||||
.phpunit.result.cache
|
||||
Homestead.json
|
||||
Homestead.yaml
|
||||
auth.json
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
/.fleet
|
||||
.phpstorm.meta.php
|
||||
_ide_helper.php
|
||||
/.idea
|
||||
/.vscode
|
||||
install.lock
|
||||
23
README.md
Normal file
23
README.md
Normal file
@@ -0,0 +1,23 @@
|
||||
## 关于
|
||||
|
||||
[Laravel](https://github.com/laravel/laravel)本地化(中文化)项目模板,带一键安装更新命令,目前[Laravel](https://github.com/laravel/laravel)版本是9.x版本。
|
||||
|
||||
## 快速开始
|
||||
|
||||
复制`.env.example`到`.env`文件,在`.env`文件里配置好数据库配置,在命令行里执行`php artisan system install`即可。
|
||||
|
||||
## 使用
|
||||
|
||||
内置了vendor环境,如不需要,请去`.gitignore`内添加`/vendor`,在命令行里执行`git rm -r --cached ./vendor`,然后再提交到git库即可。
|
||||
|
||||
如果需要使用内置vendor环境,请在开发前更新一下环境,执行`composer update`即可。
|
||||
|
||||
一键安装/更新命令 `php artisan system install`,`php artisan system update`。
|
||||
|
||||
`php artisan system install`会在项目根目录产生`install.lock`文件,如果无权限,请自行更改命令代码。
|
||||
|
||||
建议查看一下`app/Console/Commands/SystemCommand.php`(`php artisan system`)逻辑,以便更好的使用该命令。
|
||||
|
||||
目前问题:在`production`环境下无法正确执行询问形命令,目前尚无解决方法。
|
||||
|
||||
其他命令`php artisan`查看。
|
||||
74
app/Console/Commands/DataSyncCommand.php
Normal file
74
app/Console/Commands/DataSyncCommand.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\YiiModels\Platform;
|
||||
use Exception;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class DataSyncCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'data:sync {--type=} {--data=}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = '数据同步';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$type = $this->option('type');
|
||||
$data = $this->option('data');
|
||||
log_s('数据同步 => 开始发送:' . $type, 'sync', 'send');
|
||||
log_s($data, 'sync-old', 'send');
|
||||
try {
|
||||
$platform = Platform::first();
|
||||
if (!$platform) {
|
||||
log_s('数据同步 => 发送结果:无平台数据', 'sync', 'send');
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
if ($platform->status != Platform::STATUS_PASS) {
|
||||
log_s('数据同步 => 发送结果:权限不足', 'sync', 'send');
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
$response = $this->newRequest()->post($platform->url_new, [
|
||||
'form_params' => [
|
||||
'platform_token' => $platform->token,
|
||||
'type' => $type,
|
||||
'data' => json_encode($data),
|
||||
]
|
||||
]);
|
||||
$contents = $response->getBody()->getContents();
|
||||
$result = json_decode($contents, true);
|
||||
log_s('数据同步 => 发送结果:' . var_export($result, true), 'sync', 'send');
|
||||
} catch (Exception $exception) {
|
||||
log_s('数据同步 => 错误信息:' . $exception->getMessage(), 'sync', 'send');
|
||||
}
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
|
||||
public function newRequest(): Client
|
||||
{
|
||||
return new Client([
|
||||
'timeout' => 10,
|
||||
'verify' => false,
|
||||
'http_errors' => false,
|
||||
]);
|
||||
}
|
||||
}
|
||||
80
app/Console/Commands/DataSyncOldCommand.php
Normal file
80
app/Console/Commands/DataSyncOldCommand.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\YiiModels\Platform;
|
||||
use Exception;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class DataSyncOldCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'data:sync-old {--type=} {--data=}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = '数据同步(老)';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$type = $this->option('type');
|
||||
$data = $this->option('data');
|
||||
log_s('数据同步(老) => 开始发送:' . $type, 'sync-old', 'send');
|
||||
log_s($data, 'sync-old', 'send');
|
||||
try {
|
||||
$platform = Platform::first();
|
||||
if (!$platform) {
|
||||
log_s('数据同步(老) => 发送结果:无平台数据', 'sync-old', 'send');
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
if ($platform->status != Platform::STATUS_PASS) {
|
||||
log_s('数据同步(老) => 发送结果:权限不足', 'sync-old', 'send');
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
[$uri, $form_params] = $this->$type($data);
|
||||
$response = $this->newRequest()->post(rtrim($platform->url, '/') . '/' . $uri, [
|
||||
'headers' => [
|
||||
'Authorization' => "Bearer $platform->token",
|
||||
],
|
||||
'form_params' => $form_params
|
||||
]);
|
||||
$contents = $response->getBody()->getContents();
|
||||
console_info($contents);
|
||||
$result = json_decode($contents, true);
|
||||
log_s('数据同步(老) => 发送结果:' . var_export($result, true), 'sync-old', 'send');
|
||||
} catch (Exception $exception) {
|
||||
log_s('数据同步(老) => 错误信息:' . $exception->getMessage(), 'sync-old', 'send');
|
||||
}
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
|
||||
public function newRequest(): Client
|
||||
{
|
||||
return new Client([
|
||||
'timeout' => 10,
|
||||
'verify' => false,
|
||||
'http_errors' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
private function syncOrder($data): array
|
||||
{
|
||||
return ['platform/v1/sync/order', json_decode($data, true)];
|
||||
}
|
||||
}
|
||||
197
app/Console/Commands/ExpressCommand.php
Normal file
197
app/Console/Commands/ExpressCommand.php
Normal file
@@ -0,0 +1,197 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\ExpressCompany;
|
||||
use App\Models\ExpressDetail;
|
||||
use App\Models\ExpressNo;
|
||||
use Exception;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Collection;
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
|
||||
class ExpressCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'express {type?} {--code=} {--no=} {--id=}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = '物流相关';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$type = $this->argument('type');
|
||||
switch ($type) {
|
||||
case 'update': // 物流更新
|
||||
$this->update();
|
||||
break;
|
||||
case 'import': // 快递公司导入 快递公司没有对应API只有文件,所以需要手动更新文件并执行
|
||||
$this->import();
|
||||
break;
|
||||
|
||||
default:
|
||||
$this->error('参数错误');
|
||||
break;
|
||||
}
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
|
||||
private function update()
|
||||
{
|
||||
$code = $this->option('code');
|
||||
$no = $this->option('no');
|
||||
$id = $this->option('id');
|
||||
log_s("物流更新请求参数:--code=$code --no=$no --id=$id", 'express', 'message', true);
|
||||
if ($code && $no) {
|
||||
$expressNo = ExpressNo::firstOrCreate([
|
||||
'express_company_code' => $code,
|
||||
'express_no' => $no,
|
||||
]);
|
||||
try {
|
||||
$this->updateHandle($expressNo);
|
||||
} catch (Exception $exception) {
|
||||
$message = "物流请求错误:$expressNo->express_company_name $expressNo->express_no => {$exception->getMessage()}";
|
||||
console_error($message);
|
||||
log_s($message, 'express', 'error', true);
|
||||
}
|
||||
} elseif ($id) {
|
||||
$expressNo = ExpressNo::find($id);
|
||||
if (!$expressNo) {
|
||||
$message = "物流请求错误:未找到{$id}对应单号";
|
||||
console_error($message);
|
||||
log_s($message, 'express', 'error', true);
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
$this->updateHandle($expressNo);
|
||||
} catch (Exception $exception) {
|
||||
$message = "物流请求错误:$expressNo->express_company_name $expressNo->express_no => {$exception->getMessage()}";
|
||||
console_error($message);
|
||||
log_s($message, 'express', 'error', true);
|
||||
}
|
||||
} else {
|
||||
ExpressNo::with(['detail'])
|
||||
->whereNotNull('express_company_code')
|
||||
->whereNotNull('express_no')
|
||||
->chunk(100, function (Collection $collection) {
|
||||
/* @var ExpressNo $expressNo */
|
||||
foreach ($collection as $expressNo) {
|
||||
try {
|
||||
if ($expressNo->detail) {
|
||||
if ($expressNo->state == ExpressNo::STATE_SIGN) {
|
||||
if (now()->diffInHours($expressNo->detail->detail_at) > 720) {
|
||||
$expressNo->update(['sync_at' => now()]);
|
||||
$message = "物流请求跳过:已签收且超过30天";
|
||||
console_info($message);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (now()->diffInDays($expressNo->created_at) > 15) {
|
||||
$expressNo->update(['sync_at' => now()]);
|
||||
$message = "物流请求跳过:该件15天无物流信息";
|
||||
console_info($message);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$this->updateHandle($expressNo);
|
||||
} catch (Exception $exception) {
|
||||
$message = "物流请求错误:$expressNo->express_company_name $expressNo->express_no => {$exception->getMessage()}";
|
||||
console_error($message);
|
||||
log_s($message, 'express', 'error', true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public function updateHandle(ExpressNo $expressNo)
|
||||
{
|
||||
console_comment("物流请求开始:$expressNo->express_company_name $expressNo->express_no");
|
||||
if (!$expressNo->express_company_name) {
|
||||
$expressNo->load(['company']);
|
||||
if ($expressNo->company) {
|
||||
$expressNo->express_company_name = $expressNo->company->name;
|
||||
$expressNo->save();
|
||||
}
|
||||
}
|
||||
if ($expressNo->sync_at && now()->diffInMinutes($expressNo->sync_at) < 60) {
|
||||
$message = "物流请求跳过:距离上次获取不到60分钟";
|
||||
console_info($message);
|
||||
return true;
|
||||
}
|
||||
|
||||
$response = app('express')->track($expressNo->express_no, $expressNo->express_company_code, ['phone' => $expressNo->mobile]);
|
||||
$result = json_decode($response, true);
|
||||
if ($result === false) {
|
||||
$message = "物流请求错误:$expressNo->express_company_name $expressNo->express_no => $response";
|
||||
console_error($message);
|
||||
log_s($message, 'express', 'error', true);
|
||||
return true;
|
||||
}
|
||||
if (($result['status'] ?? '') != 200) {
|
||||
$message = "物流请求失败:$expressNo->express_company_name $expressNo->express_no =>" . var_export($result, true);
|
||||
console_info($message);
|
||||
log_s($message, 'express', 'fail', true);
|
||||
return true;
|
||||
}
|
||||
$message = "物流请求成功:$expressNo->express_company_name $expressNo->express_no";
|
||||
console_info($message);
|
||||
log_s($message, 'express', 'success', true);
|
||||
|
||||
$detailIds = [];
|
||||
foreach ($result['data'] as $value) {
|
||||
/* @var ExpressDetail $detail */
|
||||
$detail = $expressNo->details()->updateOrCreate([
|
||||
'status' => $value['status'],
|
||||
'detail_at' => $value['ftime'],
|
||||
'detail' => $value['context'],
|
||||
]);
|
||||
console_info("$expressNo->express_company_name $expressNo->express_no => {$value['context']}");
|
||||
$detailIds[] = $detail->id;
|
||||
}
|
||||
$expressNo->details()->whereNotIn('id', $detailIds)->delete();
|
||||
$expressNo->update([
|
||||
'state' => $result['state'],
|
||||
'sync_at' => now(),
|
||||
]);
|
||||
|
||||
console_info("$expressNo->express_company_name $expressNo->express_no => {$expressNo->state_string}");
|
||||
}
|
||||
|
||||
private function import()
|
||||
{
|
||||
$spreadsheet = IOFactory::load(storage_path('files/快递100快递公司标准编码.xlsx'));
|
||||
$sheet = $spreadsheet->setActiveSheetIndex(0);
|
||||
$data = $sheet->toArray();
|
||||
$ids = [];
|
||||
foreach ($data as $k => $value) {
|
||||
if ($k < 2) {
|
||||
continue;
|
||||
}
|
||||
$expressCompany = ExpressCompany::updateOrCreate([
|
||||
'code' => $value[1],
|
||||
], [
|
||||
'name' => $value[0],
|
||||
'type' => $value[2],
|
||||
'sort' => $k,
|
||||
]);
|
||||
$ids[] = $expressCompany->id;
|
||||
console_info("$value[1] => $value[0]");
|
||||
}
|
||||
ExpressCompany::whereNotIn('id', $ids)->delete();
|
||||
}
|
||||
}
|
||||
108
app/Console/Commands/SystemCommand.php
Normal file
108
app/Console/Commands/SystemCommand.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
|
||||
class SystemCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'system {type?}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = '系统安装/更新';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return false|void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$type = $this->argument('type');
|
||||
switch ($type) {
|
||||
case 'ready':
|
||||
if (!app()->isLocal()) {
|
||||
$this->error('非法环境');
|
||||
return 0;
|
||||
}
|
||||
$this->language();
|
||||
$this->comment('准备发布完成:)');
|
||||
break;
|
||||
case 'install':
|
||||
if (file_exists(__DIR__ . '/../../../install.lock')) {
|
||||
$this->error('如需重装,请删除“install.lock”文件!');
|
||||
return 0;
|
||||
}
|
||||
|
||||
$this->migrate();
|
||||
$this->keyGenerate();
|
||||
$this->queueRestart();
|
||||
|
||||
file_put_contents('install.lock', 'Install on ' . date('Y-m-d H:i:s'));
|
||||
$this->comment('安装完成:)');
|
||||
break;
|
||||
case 'update':
|
||||
$this->migrate();
|
||||
$this->queueRestart();
|
||||
|
||||
$this->comment('更新完成:)');
|
||||
break;
|
||||
|
||||
default:
|
||||
$this->error('只允许type参数类型为“ready”、“install”、“update”');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private function keyGenerate(): void
|
||||
{
|
||||
if ($this->laravel['config']['app.key']) {
|
||||
$this->comment('Laravel Key 已存在' . PHP_EOL);
|
||||
} else {
|
||||
Artisan::call('key:generate', [
|
||||
'--ansi' => true,
|
||||
], $this->output);
|
||||
$this->comment('Laravel Key 已生成' . PHP_EOL);
|
||||
}
|
||||
}
|
||||
|
||||
private function migrate(): void
|
||||
{
|
||||
Artisan::call('migrate', [], $this->output);
|
||||
$this->comment('数据库迁移完成' . PHP_EOL);
|
||||
}
|
||||
|
||||
private function queueRestart(): void
|
||||
{
|
||||
Artisan::call('queue:restart');
|
||||
$this->comment('队列已重启' . PHP_EOL);
|
||||
}
|
||||
|
||||
private function language(): void
|
||||
{
|
||||
Artisan::call('lang:add', [
|
||||
'locales' => ['en', 'zh_CN'],
|
||||
], $this->output);
|
||||
$this->comment('Laravel语言包更新完成' . PHP_EOL);
|
||||
}
|
||||
}
|
||||
35
app/Console/Kernel.php
Normal file
35
app/Console/Kernel.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console;
|
||||
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
|
||||
class Kernel extends ConsoleKernel
|
||||
{
|
||||
/**
|
||||
* Define the application's command schedule.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
{
|
||||
$schedule->command('express update')
|
||||
->name('定时刷新物流')
|
||||
->hourlyAt(12)
|
||||
// ->everyMinute() // fixme test
|
||||
->withoutOverlapping(30);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the commands for the application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function commands()
|
||||
{
|
||||
$this->load(__DIR__ . '/Commands');
|
||||
|
||||
require base_path('routes/console.php');
|
||||
}
|
||||
}
|
||||
47
app/Exceptions/Handler.php
Normal file
47
app/Exceptions/Handler.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions;
|
||||
|
||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||
use Throwable;
|
||||
|
||||
class Handler extends ExceptionHandler
|
||||
{
|
||||
/**
|
||||
* A list of exception types with their corresponding custom log levels.
|
||||
*
|
||||
* @var array<class-string<\Throwable>, \Psr\Log\LogLevel::*>
|
||||
*/
|
||||
protected $levels = [
|
||||
];
|
||||
|
||||
/**
|
||||
* A list of the exception types that are not reported.
|
||||
*
|
||||
* @var array<int, class-string<\Throwable>>
|
||||
*/
|
||||
protected $dontReport = [
|
||||
];
|
||||
|
||||
/**
|
||||
* A list of the inputs that are never flashed to the session on validation exceptions.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $dontFlash = [
|
||||
'current_password',
|
||||
'password',
|
||||
'password_confirmation',
|
||||
];
|
||||
|
||||
/**
|
||||
* Register the exception handling callbacks for the application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->reportable(function (Throwable $e) {
|
||||
});
|
||||
}
|
||||
}
|
||||
41
app/Handlers/QueryDetectorLogHandler.php
Normal file
41
app/Handlers/QueryDetectorLogHandler.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Handlers;
|
||||
|
||||
use BeyondCode\QueryDetector\Outputs\Output;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log as LaravelLog;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class QueryDetectorLogHandler implements Output
|
||||
{
|
||||
public function boot()
|
||||
{
|
||||
}
|
||||
|
||||
public function output(Collection $detectedQueries, Response $response)
|
||||
{
|
||||
$this->log('Detected N+1 Query');
|
||||
|
||||
foreach ($detectedQueries as $detectedQuery) {
|
||||
$logOutput = 'Model: ' . $detectedQuery['model'] . PHP_EOL;
|
||||
|
||||
$logOutput .= 'Relation: ' . $detectedQuery['relation'] . PHP_EOL;
|
||||
|
||||
$logOutput .= 'Num-Called: ' . $detectedQuery['count'] . PHP_EOL;
|
||||
|
||||
$logOutput .= 'Call-Stack:' . PHP_EOL;
|
||||
|
||||
foreach ($detectedQuery['sources'] as $source) {
|
||||
$logOutput .= '#' . $source->index . ' ' . $source->name . ':' . $source->line . PHP_EOL;
|
||||
}
|
||||
|
||||
$this->log($logOutput);
|
||||
}
|
||||
}
|
||||
|
||||
private function log(string $message)
|
||||
{
|
||||
LaravelLog::channel('query_detector')->info($message);
|
||||
}
|
||||
}
|
||||
58
app/Http/Controllers/Controller.php
Normal file
58
app/Http/Controllers/Controller.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class Controller extends BaseController
|
||||
{
|
||||
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
|
||||
|
||||
/**
|
||||
* 验证
|
||||
*
|
||||
* @param array $rules
|
||||
* @param array $messages
|
||||
* @param array $customAttributes
|
||||
* @param bool|array $only
|
||||
* @return array
|
||||
*/
|
||||
public function toValidator(array $rules, array $messages = [], array $customAttributes = [], bool|array $only = []): array
|
||||
{
|
||||
$input = request()->all();
|
||||
$validator = Validator::make($input, $rules, $messages, $customAttributes)->stopOnFirstFailure();
|
||||
if ($validator->fails()) {
|
||||
$messages = $validator->messages()->getMessages();
|
||||
json_error(Arr::first($messages)[0]);
|
||||
}
|
||||
if ($only === true) {
|
||||
return Arr::only($input, array_keys($rules));
|
||||
}
|
||||
if (count($only)) {
|
||||
return Arr::only($input, $only);
|
||||
}
|
||||
return $input;
|
||||
}
|
||||
|
||||
/**
|
||||
* ID验证
|
||||
*
|
||||
* @param string $idField
|
||||
* @return int
|
||||
*/
|
||||
public function getId(string $idField = 'id'): int
|
||||
{
|
||||
$id = request()->input($idField);
|
||||
$validator = Validator::make(['id' => $id], ['id' => 'required|integer|min:1'], ['id' => '数据传参错误'])->stopOnFirstFailure();
|
||||
if ($validator->fails()) {
|
||||
$messages = $validator->messages()->getMessages();
|
||||
json_error(Arr::first($messages)[0]);
|
||||
}
|
||||
return $id;
|
||||
}
|
||||
}
|
||||
90
app/Http/Controllers/InternalService/ApiController.php
Normal file
90
app/Http/Controllers/InternalService/ApiController.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\InternalService;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Jobs\ProductOrderCancelJob;
|
||||
use App\Models\YiiModels\Platform;
|
||||
use App\Models\YiiModels\ProductOrder;
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* 内部通讯API
|
||||
*/
|
||||
class ApiController extends Controller
|
||||
{
|
||||
private ?Platform $platform = null;
|
||||
|
||||
/**
|
||||
* 内部服务
|
||||
*
|
||||
* @param Request $request
|
||||
* @return void
|
||||
*/
|
||||
public function handle(Request $request)
|
||||
{
|
||||
$token = $request->input('token');
|
||||
log_i($token, 'token', 'internal_services');
|
||||
if ($token != config('services.internal_service.api_token')) {
|
||||
json_error('通讯错误');
|
||||
}
|
||||
|
||||
$type = $request->input('type');
|
||||
if (method_exists($this, $type)) {
|
||||
log_i(' 开始执行:' . $type, 'token', 'internal_services');
|
||||
log_i(json_encode(request()->all()), $type, 'internal_services');
|
||||
$this->{$type}();
|
||||
} else {
|
||||
log_i('内部服务数据错误 ' . $type, 'token', 'internal_services');
|
||||
json_error('内部服务数据错误 ' . $type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建订单自动取消任务
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function createOrderAutoCancel()
|
||||
{
|
||||
$product_order_id = request()->input('product_order_id');
|
||||
$minutes = request()->input('minutes');
|
||||
|
||||
ProductOrderCancelJob::dispatch($product_order_id)->delay(now()->addMinutes($minutes));
|
||||
|
||||
json_success('自动取消队列启动成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建退款请求
|
||||
*
|
||||
* @return void
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function createOrderRefundHandle()
|
||||
{
|
||||
$product_order_id = request()->input('product_order_id');
|
||||
$refund_no = request()->input('refund_no');
|
||||
|
||||
$productOrder = ProductOrder::where('id', $product_order_id)->first();
|
||||
if (!$productOrder) {
|
||||
json_error('订单信息不存在');
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
$refundResult = [];
|
||||
try {
|
||||
$refundResult = $productOrder->toRefund($productOrder->total_pay_price, $refund_no);
|
||||
|
||||
DB::commit();
|
||||
} catch (Exception $exception) {
|
||||
DB::rollBack();
|
||||
log_s('申请错误:' . var_export(request()->all(), true) . $exception->getMessage() . $exception->getTraceAsString(), 'order', 'error');
|
||||
json_error('申请错误,请重试');
|
||||
}
|
||||
|
||||
response()->json($refundResult)->throwResponse();
|
||||
}
|
||||
}
|
||||
151
app/Http/Controllers/Member/CartController.php
Normal file
151
app/Http/Controllers/Member/CartController.php
Normal file
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Member;
|
||||
|
||||
use App\Models\Cart;
|
||||
use App\Models\YiiModels\Drug;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
|
||||
/**
|
||||
* 购物车
|
||||
*/
|
||||
class CartController extends MemberBaseController
|
||||
{
|
||||
/**
|
||||
* 添加购物车
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function cartAdd()
|
||||
{
|
||||
$input = $this->toValidator([
|
||||
'drug_id' => 'required|integer',
|
||||
'change_qty' => 'nullable|integer',
|
||||
'true_qty' => 'nullable|integer',
|
||||
], [], [
|
||||
'drug_id' => '商品',
|
||||
'change_qty' => '数量',
|
||||
'true_qty' => '数量',
|
||||
], true);
|
||||
|
||||
if (!$input['change_qty'] && !$input['true_qty']) {
|
||||
json_error('商品数量不正确');
|
||||
}
|
||||
|
||||
/* @var Drug $drug */
|
||||
$drug = Drug::with([
|
||||
'drugStoreRelation' => function (Relation $relation) {
|
||||
$relation->select(['drug_id', 'total_sales_volume', 'status'])
|
||||
->where('store_id', $this->getStoreId());
|
||||
},
|
||||
'drugstoreDrug' => function (Relation $relation) {
|
||||
$relation->select(['drug_id', 'price', 'stock'])
|
||||
->where('drugstore_id', $this->getDrugstoreId());
|
||||
},
|
||||
])
|
||||
->select([
|
||||
'id', 'status',
|
||||
])
|
||||
->whereHasIn('drugStoreRelation', function (Builder $builder) {
|
||||
$builder->where('store_id', $this->getStoreId());
|
||||
})
|
||||
->where('id', $input['drug_id'])
|
||||
->first();
|
||||
if (!$drug && !$drug->drugStoreRelation && !$drug->drugstoreDrug) {
|
||||
json_error('商品不存在');
|
||||
}
|
||||
if ($drug->status != Drug::STATUS_ON || $drug->drugStoreRelation->status != Drug::STATUS_ON) {
|
||||
json_error('商品已下架');
|
||||
}
|
||||
$cart = $this->user()->carts()->firstOrCreate([
|
||||
'drug_id' => $input['drug_id'],
|
||||
'store_id' => $this->getStoreId(),
|
||||
]);
|
||||
if ($input['change_qty']) {
|
||||
if ($input['change_qty'] > $drug->drugstoreDrug->stock) {
|
||||
json_error("库存不足,最多可加入{$drug->drugstoreDrug->stock}个");
|
||||
}
|
||||
$cart->increment('qty', $input['change_qty'], ['join_at' => now()]);
|
||||
if ($cart->qty <= 0) {
|
||||
$cart->delete();
|
||||
json_success('购物车商品已删除');
|
||||
}
|
||||
} else {
|
||||
if (($input['true_qty'] - $cart['qty']) > $drug->drugstoreDrug->stock) {
|
||||
json_error("库存不足,最多可加入{$drug->drugstoreDrug->stock}个");
|
||||
}
|
||||
$cart->update([
|
||||
'qty' => $input['true_qty'],
|
||||
'join_at' => now(),
|
||||
]);
|
||||
if ($cart->qty <= 0) {
|
||||
$cart->delete();
|
||||
json_success('购物车商品已删除');
|
||||
}
|
||||
}
|
||||
json_success('已加入购物车');
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空购物车
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clearAll()
|
||||
{
|
||||
Cart::where('store_id', $this->getStoreId())
|
||||
->where('user_id', $this->userId())
|
||||
->delete();
|
||||
json_success('已清空购物车');
|
||||
}
|
||||
|
||||
/**
|
||||
* 购物车列表
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function cartLists()
|
||||
{
|
||||
$carts = Cart::with([
|
||||
'drug' => function (Relation $relation) {
|
||||
$relation->with([
|
||||
'drugStoreRelation' => function (Relation $relation) {
|
||||
$relation->select(['drug_id', 'total_sales_volume', 'status'])
|
||||
->where('store_id', $this->getStoreId());
|
||||
},
|
||||
'drugstoreDrug' => function (Relation $relation) {
|
||||
$relation->select(['drug_id', 'price', 'stock'])
|
||||
->where('drugstore_id', $this->getDrugstoreId());
|
||||
},
|
||||
])
|
||||
->select(['id', 'drug_name', 'source', 'type', 'is_otc', 'small_info', 'usage', 'specification', 'image', 'status']);
|
||||
}
|
||||
])
|
||||
->whereHasIn('drug')
|
||||
->where('store_id', $this->getStoreId())
|
||||
->where('user_id', $this->userId())
|
||||
->orderByDesc('join_at')
|
||||
->get();
|
||||
|
||||
$valid = $invalid = [];
|
||||
/* @var Cart $cart */
|
||||
foreach ($carts as $cart) {
|
||||
if (!$cart->drug || !$cart->drug->drugStoreRelation || !$cart->drug->drugstoreDrug) {
|
||||
$invalid[] = $cart;
|
||||
continue;
|
||||
}
|
||||
if ($cart->drug->status != Drug::STATUS_ON || $cart->drug->drugStoreRelation->status != Drug::STATUS_ON) {
|
||||
$invalid[] = $cart;
|
||||
continue;
|
||||
}
|
||||
$valid[] = $cart;
|
||||
}
|
||||
|
||||
json_success([
|
||||
'store_name' => $this->getStore()->name,
|
||||
'valid' => $valid,
|
||||
'invalid' => $invalid,
|
||||
]);
|
||||
}
|
||||
}
|
||||
110
app/Http/Controllers/Member/DrugController.php
Normal file
110
app/Http/Controllers/Member/DrugController.php
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Member;
|
||||
|
||||
use App\Models\DrugCategory;
|
||||
use App\Models\DrugStoreRelation;
|
||||
use App\Models\YiiModels\Drug;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
|
||||
/**
|
||||
* 药品
|
||||
*/
|
||||
class DrugController extends MemberBaseController
|
||||
{
|
||||
/**
|
||||
* 药品分类
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function drugCategory()
|
||||
{
|
||||
json_success(DrugCategory::getCategory());
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品列表(带库存)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function drugLists()
|
||||
{
|
||||
$category_first = request('category_first');
|
||||
$category_second = request('category_second');
|
||||
$keyword = request('keyword');
|
||||
// $this->toValidator([
|
||||
// 'category_first' => 'required|integer',
|
||||
// 'category_second' => 'required|integer',
|
||||
// ], [], [
|
||||
// 'category_first' => '一级分类',
|
||||
// 'category_second' => '二级分类',
|
||||
// ]);
|
||||
|
||||
$drugs = Drug::with([
|
||||
'drugstoreDrug' => function (Relation $relation) {
|
||||
$relation->select(['drug_id', 'price', 'stock'])
|
||||
->where('drugstore_id', $this->getDrugstoreId());
|
||||
},
|
||||
])
|
||||
->select([
|
||||
'id', 'drug_name', 'source', 'type', 'is_otc', 'category_first', 'category_second',
|
||||
'usage', 'small_info', 'specification', 'image',
|
||||
])
|
||||
->whereHasIn('drugStoreRelation', function (Builder $builder) {
|
||||
$builder->where('status', DrugStoreRelation::STATUS_ON)
|
||||
->where('store_id', $this->getStoreId());
|
||||
})
|
||||
->when($keyword, function (Builder $builder) use ($keyword) {
|
||||
$builder->where('drug_name', 'like', "%$keyword%");
|
||||
})
|
||||
->where('status', Drug::STATUS_ON)
|
||||
->where('type_id', [Drug::TYPE_CHINESE_DRUG, Drug::TYPE_PELLET_PATENT])
|
||||
->where('is_otc', Drug::IS_OTC_FALSE)
|
||||
->where('category_first', $category_first)
|
||||
->where('category_second', $category_second)
|
||||
->get();
|
||||
|
||||
json_success($drugs);
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品详情
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function drugDetail()
|
||||
{
|
||||
$id = $this->getId();
|
||||
|
||||
/* @var Drug $drug */
|
||||
$drug = Drug::with([
|
||||
'drugStoreRelation' => function (Relation $relation) {
|
||||
$relation->select(['store_id', 'drug_id', 'total_sales_volume', 'status'])
|
||||
->with(['store:id,name'])
|
||||
->where('store_id', $this->getStoreId());
|
||||
},
|
||||
'drugstoreDrug' => function (Relation $relation) {
|
||||
$relation->select(['drugstore_id', 'drug_id', 'price', 'stock'])
|
||||
->where('drugstore_id', $this->getDrugstoreId());
|
||||
},
|
||||
])
|
||||
->select([
|
||||
'id', 'drug_name', 'source', 'type', 'is_otc', 'category_first', 'category_second',
|
||||
'usage', 'specification', 'image', 'small_info', 'info', 'content', 'status',
|
||||
])
|
||||
->whereHasIn('drugStoreRelation', function (Builder $builder) {
|
||||
$builder->where('store_id', $this->getStoreId());
|
||||
})
|
||||
->where('id', $id)
|
||||
->first();
|
||||
if (!$drug || !$drug->drugStoreRelation || !$drug->drugstoreDrug) {
|
||||
json_error('商品不存在');
|
||||
}
|
||||
if ($drug->status != Drug::STATUS_ON || $drug->drugStoreRelation->status != Drug::STATUS_ON) {
|
||||
json_error('商品已下架');
|
||||
}
|
||||
|
||||
json_success($drug);
|
||||
}
|
||||
}
|
||||
20
app/Http/Controllers/Member/ExpressController.php
Normal file
20
app/Http/Controllers/Member/ExpressController.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Member;
|
||||
|
||||
use App\Models\ExpressFee;
|
||||
|
||||
/**
|
||||
* 物流
|
||||
*/
|
||||
class ExpressController extends MemberBaseController
|
||||
{
|
||||
public function feeInfo()
|
||||
{
|
||||
$expressFeeInfo = ExpressFee::getDefaultExpressFee();
|
||||
if (!$expressFeeInfo) {
|
||||
json_error('运费信息错误');
|
||||
}
|
||||
json_success($expressFeeInfo);
|
||||
}
|
||||
}
|
||||
92
app/Http/Controllers/Member/MemberBaseController.php
Normal file
92
app/Http/Controllers/Member/MemberBaseController.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Member;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\YiiModels\Drugstore;
|
||||
use App\Models\YiiModels\Store;
|
||||
use App\Models\YiiModels\User;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
/**
|
||||
* 用户端基类
|
||||
*/
|
||||
class MemberBaseController extends Controller
|
||||
{
|
||||
protected ?Store $store = null;
|
||||
protected ?Drugstore $drugstore = null;
|
||||
protected ?int $store_id = 0;
|
||||
protected ?int $drugstore_id = 0;
|
||||
|
||||
/**
|
||||
* @comment 用户
|
||||
* @return \App\Models\YiiModels\User|\Illuminate\Contracts\Auth\Authenticatable|null
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return Auth::guard(User::GUARD)->user();
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 用户id
|
||||
* @return int
|
||||
*/
|
||||
public function userId(): int
|
||||
{
|
||||
return $this->user()->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前仓库ID
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getDrugstoreId(): int
|
||||
{
|
||||
if (!$this->drugstore_id) {
|
||||
$this->drugstore_id = $this->getStore()->drugstore_id;
|
||||
}
|
||||
return $this->drugstore_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前仓库
|
||||
*
|
||||
* @return Drugstore
|
||||
*/
|
||||
public function getDrugstore(): Drugstore
|
||||
{
|
||||
$this->drugstore = Drugstore::where('id', $this->getDrugstoreId())->first();
|
||||
if (!$this->drugstore) {
|
||||
json_error('药房信息获取失败');
|
||||
}
|
||||
return $this->drugstore;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取门店ID
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getStoreId(): int
|
||||
{
|
||||
if (!$this->store_id) {
|
||||
$this->store_id = (int)request()->input('store_id');
|
||||
}
|
||||
return $this->store_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取门店
|
||||
*
|
||||
* @return Store
|
||||
*/
|
||||
public function getStore(): Store
|
||||
{
|
||||
$this->store = Store::where('id', $this->getStoreId())->first();
|
||||
if (!$this->store) {
|
||||
json_error('门店信息获取失败');
|
||||
}
|
||||
return $this->store;
|
||||
}
|
||||
}
|
||||
23
app/Http/Controllers/Member/TestController.php
Normal file
23
app/Http/Controllers/Member/TestController.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Member;
|
||||
|
||||
use App\Models\YiiModels\User;
|
||||
|
||||
/**
|
||||
* @deprecated fixme delete 测试接口
|
||||
*/
|
||||
class TestController extends MemberBaseController
|
||||
{
|
||||
public function testLogin()
|
||||
{
|
||||
if (app()->isLocal() && file_exists(base_path('./../dev.ini'))) {
|
||||
/* @var User $user */
|
||||
$user = User::where('mobile', request('mobile'))->first();
|
||||
if ($user) {
|
||||
json_success('登陆成功', ['token' => $user->token, 'user_id' => $user->id]);
|
||||
}
|
||||
}
|
||||
json_error('错误示例');
|
||||
}
|
||||
}
|
||||
100
app/Http/Controllers/Pay/NotifyController.php
Normal file
100
app/Http/Controllers/Pay/NotifyController.php
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Pay;
|
||||
|
||||
use App\Models\Pay\Bill;
|
||||
use App\Models\Pay\RefundBill;
|
||||
use Carbon\Carbon;
|
||||
use Exception;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Yansongda\LaravelPay\Facades\Pay;
|
||||
|
||||
class NotifyController
|
||||
{
|
||||
/**
|
||||
* 微信异步通知入口
|
||||
*
|
||||
* @param $config_name
|
||||
* @return \Psr\Http\Message\ResponseInterface|void
|
||||
* @throws \Throwable
|
||||
* @throws \Yansongda\Pay\Exception\ContainerException
|
||||
* @throws \Yansongda\Pay\Exception\InvalidParamsException
|
||||
*/
|
||||
public function payWechat($config_name)
|
||||
{
|
||||
$result = Pay::wechat()->callback(null, ['_config' => $config_name]);
|
||||
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
switch ($result['event_type']) {
|
||||
case 'TRANSACTION.SUCCESS': // 支付成功
|
||||
$payData = $result['resource']['ciphertext'];
|
||||
if ($payData['trade_state'] == 'SUCCESS') {
|
||||
$data = [
|
||||
'mchid' => $payData['mchid'],
|
||||
'appid' => $payData['appid'],
|
||||
'pay_no' => $payData['out_trade_no'],
|
||||
'pay_service_no' => $payData['transaction_id'],
|
||||
'pay_amount' => $payData['amount']['total'] / 100,
|
||||
'pay_at' => Carbon::parseFromLocale($payData['success_time'])->toDateTimeString(),
|
||||
];
|
||||
$handleResult = Bill::handleNotify($data, Bill::PAY_WAY_WECHAT);
|
||||
if ($handleResult === true) {
|
||||
DB::commit();
|
||||
return Pay::wechat()->success();
|
||||
} else {
|
||||
log_i('支付成功处理失败-' . $handleResult . "\n" . var_export($result, true), 'pay-handle-error', 'wechat');
|
||||
}
|
||||
} else {
|
||||
log_i('支付通知失败' . "\n" . var_export($result, true), 'pay-notify-error', 'wechat');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'REFUND.SUCCESS': // 退款成功
|
||||
$payData = $result['resource']['ciphertext'];
|
||||
if ($payData['refund_status'] == 'SUCCESS') {
|
||||
$data = [
|
||||
'refund_no' => $payData['out_refund_no'],
|
||||
'refund_service_no' => $payData['refund_id'],
|
||||
'pay_no' => $payData['out_trade_no'],
|
||||
'pay_service_no' => $payData['transaction_id'],
|
||||
'refund_amount' => $payData['amount']['refund'] / 100,
|
||||
'refund_at' => Carbon::parseFromLocale($payData['success_time'])->toDateTimeString(),
|
||||
];
|
||||
$handleResult = RefundBill::handleNotify($data);
|
||||
if ($handleResult === true) {
|
||||
DB::commit();
|
||||
return Pay::wechat()->success();
|
||||
} else {
|
||||
log_i('退款成功处理失败-' . $handleResult . "\n" . var_export($result, true), 'refund-handle-error', 'wechat');
|
||||
}
|
||||
} else {
|
||||
log_i('退款通知失败' . "\n" . var_export($result, true), 'refund-notify-error', 'wechat');
|
||||
}
|
||||
break;
|
||||
|
||||
default: // 其他情况
|
||||
log_i('其他通知失败' . "\n" . var_export($result, true), 'other-notify-error', 'wechat');
|
||||
break;
|
||||
}
|
||||
} catch (Exception $exception) {
|
||||
log_i('通知处理失败-程序出错' . $exception->getMessage() . "\n" . $exception->getTraceAsString() . "\n" . var_export($result, true), 'all-handle-exception', 'wechat');
|
||||
}
|
||||
|
||||
DB::rollBack();
|
||||
return new Response(
|
||||
500,
|
||||
['Content-Type' => 'application/json'],
|
||||
json_encode(['code' => 'FAIL', 'message' => '失败']),
|
||||
);
|
||||
}
|
||||
|
||||
public function messageWechatMini($config_name)
|
||||
{
|
||||
$server = app('easywechat.official_account.' . $config_name)->getServer();
|
||||
$message = $server->getDecryptedMessage();
|
||||
log_s($message);
|
||||
return $server->serve();
|
||||
}
|
||||
}
|
||||
51
app/Http/Controllers/Platform/PlatformApi.php
Normal file
51
app/Http/Controllers/Platform/PlatformApi.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Platform;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\YiiModels\Platform;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* 平台通讯API
|
||||
*/
|
||||
class PlatformApi extends Controller
|
||||
{
|
||||
private ?Platform $platform = null;
|
||||
|
||||
/**
|
||||
* 同步
|
||||
*
|
||||
* @param Request $request
|
||||
* @return void
|
||||
*/
|
||||
public function handle(Request $request)
|
||||
{
|
||||
$platform_token = $request->input('platform_token');
|
||||
$this->platform = Platform::where('token', $platform_token)->first();
|
||||
log_i($platform_token, 'token', 'sync');
|
||||
if (!$this->platform) {
|
||||
log_i($platform_token . ' 未找到', 'token', 'sync');
|
||||
json_error('通讯错误');
|
||||
}
|
||||
if ($this->platform->status != Platform::STATUS_PASS) {
|
||||
log_i($platform_token . ' 无权限', 'token', 'sync');
|
||||
json_error('无权限');
|
||||
}
|
||||
|
||||
$type = $request->input('type');
|
||||
if (method_exists($this, $type)) {
|
||||
log_i($platform_token . ' 开始执行:' . $type, 'token', 'sync');
|
||||
log_i(json_encode(request()->all()), $type, 'sync');
|
||||
$this->{$type}();
|
||||
} else {
|
||||
log_i($platform_token . '同步数据错误 ' . $type, 'token', 'sync');
|
||||
json_error('同步数据错误 ' . $type);
|
||||
}
|
||||
}
|
||||
|
||||
private function prescriptionSync()
|
||||
{
|
||||
$data = request('data');
|
||||
}
|
||||
}
|
||||
53
app/Http/Controllers/Service/ServiceBaseController.php
Normal file
53
app/Http/Controllers/Service/ServiceBaseController.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Service;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\YiiModels\ServiceUser;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
/**
|
||||
* 用户端基类
|
||||
*/
|
||||
class ServiceBaseController extends Controller
|
||||
{
|
||||
/**
|
||||
* @comment 用户
|
||||
* @return \App\Models\YiiModels\ServiceUser|\Illuminate\Contracts\Auth\Authenticatable|null
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return Auth::guard(ServiceUser::GUARD)->user();
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 用户id
|
||||
* @return int
|
||||
*/
|
||||
public function userId()
|
||||
{
|
||||
return $this->user()->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 当前仓库id
|
||||
* @return int
|
||||
*/
|
||||
public function currentDrugstoreId()
|
||||
{
|
||||
$serviceUser = $this->user();
|
||||
$serviceUser->loadMissing(['storeDoctorOnline.store']);
|
||||
return $serviceUser->storeDoctorOnline->store->drugstore_id ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 当前门店id
|
||||
* @return int
|
||||
*/
|
||||
public function currentStoreId()
|
||||
{
|
||||
$serviceUser = $this->user();
|
||||
$serviceUser->loadMissing(['storeDoctorOnline']);
|
||||
return $serviceUser->storeDoctorOnline->store_id ?? 0;
|
||||
}
|
||||
}
|
||||
26
app/Http/Controllers/Service/TestController.php
Normal file
26
app/Http/Controllers/Service/TestController.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Service;
|
||||
|
||||
use App\Models\YiiModels\ServiceUserToken;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
/**
|
||||
* @deprecated fixme delete 测试接口
|
||||
*/
|
||||
class TestController extends ServiceBaseController
|
||||
{
|
||||
public function testLogin()
|
||||
{
|
||||
if (app()->isLocal() && file_exists(base_path('./../dev.ini'))) {
|
||||
/* @var ServiceUserToken $token */
|
||||
$token = ServiceUserToken::whereHasIn('serviceUser', fn(Builder $builder) => $builder->where('mobile', request('mobile')))
|
||||
->where('is_disable', ServiceUserToken::IS_DISABLE_IS_ABLE)
|
||||
->first();
|
||||
if ($token) {
|
||||
json_success('登陆成功', ['token' => $token->token, 'user_id' => $token->su_id]);
|
||||
}
|
||||
}
|
||||
json_error('错误示例');
|
||||
}
|
||||
}
|
||||
76
app/Http/Controllers/Tests/TestController.php
Normal file
76
app/Http/Controllers/Tests/TestController.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Tests;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\ExpressNo;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
|
||||
class TestController extends Controller
|
||||
{
|
||||
|
||||
public const ALLOW_LISTS = [
|
||||
'express',
|
||||
'express_update',
|
||||
];
|
||||
|
||||
/**
|
||||
* TestController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (!app()->isLocal() && in_array(__FUNCTION__, self::ALLOW_LISTS)) {
|
||||
abort(404);
|
||||
}
|
||||
}
|
||||
|
||||
public function t($fun = '')
|
||||
{
|
||||
if (0 == strlen($fun)) {
|
||||
$fun = 'a';
|
||||
}
|
||||
$result = $this->$fun();
|
||||
if (!empty($result)) {
|
||||
return $result;
|
||||
}
|
||||
dd('结束运行方法:' . $fun);
|
||||
}
|
||||
|
||||
public function express()
|
||||
{
|
||||
$expressNo = ExpressNo::where('express_no', request('no'))->first();
|
||||
if (!$expressNo) {
|
||||
dda('单号对应数据库不存在');
|
||||
}
|
||||
$response = app('express')->track($expressNo->express_no, $expressNo->express_company_code, ['phone' => $expressNo->mobile]);
|
||||
$result = json_decode($response, true);
|
||||
dda($expressNo, $result);
|
||||
}
|
||||
|
||||
public function express_update()
|
||||
{
|
||||
$id = request('id');
|
||||
$parameters = [
|
||||
'type' => 'update',
|
||||
];
|
||||
if ($id) {
|
||||
$parameters['--id'] = $id;
|
||||
$expressNo = ExpressNo::where('id', $id)->first();
|
||||
if (!$expressNo) {
|
||||
json_error("{$id}数据不存在");
|
||||
}
|
||||
}
|
||||
Artisan::call('express', $parameters);
|
||||
json_success("{$id}更新完成");
|
||||
}
|
||||
|
||||
// public function a()
|
||||
// {
|
||||
// //
|
||||
// }
|
||||
|
||||
public function a()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
71
app/Http/Kernel.php
Normal file
71
app/Http/Kernel.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http;
|
||||
|
||||
use App\Http\Middleware\AuthMemberMiddleware;
|
||||
use App\Http\Middleware\AuthServiceMiddleware;
|
||||
use Illuminate\Foundation\Http\Kernel as HttpKernel;
|
||||
|
||||
class Kernel extends HttpKernel
|
||||
{
|
||||
/**
|
||||
* The application's global HTTP middleware stack.
|
||||
*
|
||||
* These middleware are run during every request to your application.
|
||||
*
|
||||
* @var array<int, class-string|string>
|
||||
*/
|
||||
protected $middleware = [
|
||||
// \App\Http\Middleware\TrustHosts::class,
|
||||
\App\Http\Middleware\TrustProxies::class,
|
||||
\Illuminate\Http\Middleware\HandleCors::class,
|
||||
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
|
||||
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
|
||||
\App\Http\Middleware\TrimStrings::class,
|
||||
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* The application's route middleware groups.
|
||||
*
|
||||
* @var array<string, array<int, class-string|string>>
|
||||
*/
|
||||
protected $middlewareGroups = [
|
||||
'web' => [
|
||||
\App\Http\Middleware\EncryptCookies::class,
|
||||
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
||||
\Illuminate\Session\Middleware\StartSession::class,
|
||||
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||
\App\Http\Middleware\VerifyCsrfToken::class,
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
],
|
||||
|
||||
'api' => [
|
||||
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
|
||||
'throttle:api',
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* The application's route middleware.
|
||||
*
|
||||
* These middleware may be assigned to groups or used individually.
|
||||
*
|
||||
* @var array<string, class-string|string>
|
||||
*/
|
||||
protected $routeMiddleware = [
|
||||
'auth' => \App\Http\Middleware\Authenticate::class,
|
||||
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
||||
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
|
||||
'auth.member' => AuthMemberMiddleware::class,
|
||||
'auth.service' => AuthServiceMiddleware::class,
|
||||
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
|
||||
'can' => \Illuminate\Auth\Middleware\Authorize::class,
|
||||
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
|
||||
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
|
||||
'signed' => \App\Http\Middleware\ValidateSignature::class,
|
||||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
||||
];
|
||||
}
|
||||
35
app/Http/Middleware/AuthMemberMiddleware.php
Normal file
35
app/Http/Middleware/AuthMemberMiddleware.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Models\YiiModels\User;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class AuthMemberMiddleware
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
|
||||
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if (!$request->input('store_id')) {
|
||||
json_error('缺少门店参数');
|
||||
}
|
||||
|
||||
$token = $request->bearerToken();
|
||||
$user = User::where('token', $token)->first();
|
||||
|
||||
if (!$user) {
|
||||
json_guest();
|
||||
}
|
||||
|
||||
Auth::guard(User::GUARD)->login($user);
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
34
app/Http/Middleware/AuthServiceMiddleware.php
Normal file
34
app/Http/Middleware/AuthServiceMiddleware.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Models\YiiModels\ServiceUser;
|
||||
use App\Models\YiiModels\ServiceUserToken;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class AuthServiceMiddleware
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
|
||||
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
$token = $request->bearerToken();
|
||||
$serviceUserToken = ServiceUserToken::with('serviceUser')
|
||||
->where('is_disable', ServiceUserToken::IS_DISABLE_IS_ABLE)
|
||||
->where('token', $token)
|
||||
->first();
|
||||
if (!$serviceUserToken || !$serviceUserToken->serviceUser) {
|
||||
json_guest();
|
||||
}
|
||||
|
||||
Auth::guard(ServiceUser::GUARD)->login($serviceUserToken->serviceUser);
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
22
app/Http/Middleware/Authenticate.php
Normal file
22
app/Http/Middleware/Authenticate.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Auth\Middleware\Authenticate as Middleware;
|
||||
|
||||
class Authenticate extends Middleware
|
||||
{
|
||||
/**
|
||||
* Get the path the user should be redirected to when they are not authenticated.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
protected function redirectTo($request)
|
||||
{
|
||||
if (!$request->expectsJson()) {
|
||||
return route('login');
|
||||
}
|
||||
}
|
||||
}
|
||||
16
app/Http/Middleware/EncryptCookies.php
Normal file
16
app/Http/Middleware/EncryptCookies.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
|
||||
|
||||
class EncryptCookies extends Middleware
|
||||
{
|
||||
/**
|
||||
* The names of the cookies that should not be encrypted.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $except = [
|
||||
];
|
||||
}
|
||||
16
app/Http/Middleware/PreventRequestsDuringMaintenance.php
Normal file
16
app/Http/Middleware/PreventRequestsDuringMaintenance.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance as Middleware;
|
||||
|
||||
class PreventRequestsDuringMaintenance extends Middleware
|
||||
{
|
||||
/**
|
||||
* The URIs that should be reachable while maintenance mode is enabled.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $except = [
|
||||
];
|
||||
}
|
||||
32
app/Http/Middleware/RedirectIfAuthenticated.php
Normal file
32
app/Http/Middleware/RedirectIfAuthenticated.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class RedirectIfAuthenticated
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
|
||||
* @param string|null ...$guards
|
||||
*
|
||||
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function handle(Request $request, Closure $next, ...$guards)
|
||||
{
|
||||
$guards = empty($guards) ? [null] : $guards;
|
||||
|
||||
foreach ($guards as $guard) {
|
||||
if (Auth::guard($guard)->check()) {
|
||||
return redirect(RouteServiceProvider::HOME);
|
||||
}
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
19
app/Http/Middleware/TrimStrings.php
Normal file
19
app/Http/Middleware/TrimStrings.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
|
||||
|
||||
class TrimStrings extends Middleware
|
||||
{
|
||||
/**
|
||||
* The names of the attributes that should not be trimmed.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $except = [
|
||||
'current_password',
|
||||
'password',
|
||||
'password_confirmation',
|
||||
];
|
||||
}
|
||||
20
app/Http/Middleware/TrustHosts.php
Normal file
20
app/Http/Middleware/TrustHosts.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Http\Middleware\TrustHosts as Middleware;
|
||||
|
||||
class TrustHosts extends Middleware
|
||||
{
|
||||
/**
|
||||
* Get the host patterns that should be trusted.
|
||||
*
|
||||
* @return array<int, string|null>
|
||||
*/
|
||||
public function hosts()
|
||||
{
|
||||
return [
|
||||
$this->allSubdomainsOfApplicationUrl(),
|
||||
];
|
||||
}
|
||||
}
|
||||
28
app/Http/Middleware/TrustProxies.php
Normal file
28
app/Http/Middleware/TrustProxies.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Http\Middleware\TrustProxies as Middleware;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class TrustProxies extends Middleware
|
||||
{
|
||||
/**
|
||||
* The trusted proxies for this application.
|
||||
*
|
||||
* @var array<int, string>|string|null
|
||||
*/
|
||||
protected $proxies;
|
||||
|
||||
/**
|
||||
* The headers that should be used to detect proxies.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $headers =
|
||||
Request::HEADER_X_FORWARDED_FOR |
|
||||
Request::HEADER_X_FORWARDED_HOST |
|
||||
Request::HEADER_X_FORWARDED_PORT |
|
||||
Request::HEADER_X_FORWARDED_PROTO |
|
||||
Request::HEADER_X_FORWARDED_AWS_ELB;
|
||||
}
|
||||
22
app/Http/Middleware/ValidateSignature.php
Normal file
22
app/Http/Middleware/ValidateSignature.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Routing\Middleware\ValidateSignature as Middleware;
|
||||
|
||||
class ValidateSignature extends Middleware
|
||||
{
|
||||
/**
|
||||
* The names of the query string parameters that should be ignored.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $except = [
|
||||
// 'fbclid',
|
||||
// 'utm_campaign',
|
||||
// 'utm_content',
|
||||
// 'utm_medium',
|
||||
// 'utm_source',
|
||||
// 'utm_term',
|
||||
];
|
||||
}
|
||||
21
app/Http/Middleware/VerifyCsrfToken.php
Normal file
21
app/Http/Middleware/VerifyCsrfToken.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
|
||||
|
||||
class VerifyCsrfToken extends Middleware
|
||||
{
|
||||
/**
|
||||
* The URIs that should be excluded from CSRF verification.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $except = [
|
||||
'wechat',
|
||||
'notify/*',
|
||||
'return/*',
|
||||
'platformApi/*',
|
||||
'internalServiceApi/*',
|
||||
];
|
||||
}
|
||||
99
app/Http/Resources/ProductOrderDetailResource.php
Normal file
99
app/Http/Resources/ProductOrderDetailResource.php
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use App\Models\ProductOrderItem;
|
||||
use App\Models\YiiModels\Prescription;
|
||||
use App\Models\YiiModels\ProductOrder;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
/**
|
||||
* @mixin ProductOrder
|
||||
*/
|
||||
class ProductOrderDetailResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'store_id' => $this->store_id,
|
||||
'su_id' => $this->su_id,
|
||||
'user_id' => $this->user_id,
|
||||
'up_id' => $this->up_id,
|
||||
'order_no' => $this->order_no,
|
||||
'sync_order_no' => $this->sync_order_no,
|
||||
'p_id' => $this->p_id,
|
||||
'order_type' => $this->order_type,
|
||||
'type' => $this->type,
|
||||
'type_string' => $this->type_string,
|
||||
'is_pay' => $this->is_pay,
|
||||
'items_price' => $this->items_price,
|
||||
'total_pay_price' => $this->total_pay_price,
|
||||
'pay_time' => $this->pay_time,
|
||||
'address_id' => $this->address_id,
|
||||
'address' => $this->address,
|
||||
'cancel_status' => $this->cancel_status,
|
||||
'cancel_status_string' => $this->cancel_status_string,
|
||||
'cancel_time' => $this->cancel_time,
|
||||
'cancel_remark' => $this->cancel_remark,
|
||||
'refund_status' => $this->refund_status,
|
||||
'refund_time' => $this->refund_time,
|
||||
'received_time' => $this->received_time,
|
||||
'auto_cancel_time' => $this->auto_cancel_time,
|
||||
'status' => $this->status,
|
||||
'pay_method' => $this->pay_method,
|
||||
'trans_expenses' => $this->trans_expenses,
|
||||
'free_ship' => $this->free_ship,
|
||||
'remark' => $this->remark,
|
||||
'express_name' => $this->express_name,
|
||||
'express_mobile' => $this->express_mobile,
|
||||
'express_region' => $this->express_region,
|
||||
'express_address' => $this->express_address,
|
||||
'express_no_id' => $this->express_no_id,
|
||||
'created_at_format' => $this->created_at_format,
|
||||
'items' => $this->items->map(function (ProductOrderItem $item) {
|
||||
return [
|
||||
'id' => $item->id,
|
||||
'product_order_id' => $item->product_order_id,
|
||||
'drug_id' => $item->drug_id,
|
||||
'drug_image' => $item->drug_image,
|
||||
'number' => $item->number,
|
||||
'price' => $item->price,
|
||||
'drug_name' => $item->drug_name,
|
||||
'small_info' => $item->small_info,
|
||||
];
|
||||
}),
|
||||
'prescription' => $this->getPrescription(),
|
||||
];
|
||||
}
|
||||
|
||||
private function getPrescription()
|
||||
{
|
||||
if (!$this->prescription) {
|
||||
return [];
|
||||
}
|
||||
if (in_array($this->prescription->prescription_type, [Prescription::CHINESE_MEDICINES_DECOCTION_PIECE, Prescription::DISPENSING_GRANULES])) {
|
||||
return [
|
||||
'id' => $this->prescription->id,
|
||||
'dosage_price' => $this->items->sum('price'),
|
||||
'dosage' => $this->prescription->content['repice'][0]['dosage'],
|
||||
'prescription_type' => $this->prescription->prescription_type,
|
||||
'prescription_type_string' => $this->prescription->prescription_type_string,
|
||||
];
|
||||
}
|
||||
if (in_array($this->prescription->prescription_type, (array)Prescription::WESTERN_ZHONG_CHENG_MEDICINE)) {
|
||||
return [
|
||||
'id' => $this->prescription->id,
|
||||
'dosage_price' => $this->items->sum('price'),
|
||||
'prescription_type' => $this->prescription->prescription_type,
|
||||
'prescription_type_string' => $this->prescription->prescription_type_string,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
42
app/Http/Traits/ProductOrderTrait.php
Normal file
42
app/Http/Traits/ProductOrderTrait.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Traits;
|
||||
|
||||
use App\Models\YiiModels\ProductOrder;
|
||||
use App\Models\YiiModels\SystemNotice;
|
||||
use App\Models\YiiModels\FundWater;
|
||||
|
||||
trait ProductOrderTrait
|
||||
{
|
||||
public function createNotice(ProductOrder $productOrder, $message): void
|
||||
{
|
||||
SystemNotice::create([
|
||||
'store_id' => $productOrder->store_id, // 门店id
|
||||
'content' => $message, // 通知内容
|
||||
// 'url' => '', // 链接
|
||||
// 'url_type' => '', // 链接类型
|
||||
'base_type' => SystemNotice::BASE_TYPE_ORDER, // 通知类型1订单通知2挂号通知3拒诊通知4处方开具消息5处方审核消息 99系统通知
|
||||
'scene_type' => SystemNotice::SCENE_TYPE_MEMBER, // 场景类型:1用户端,2服务端(角色)
|
||||
// 'user_role' => '', // 通知用户类型
|
||||
'user_id' => $productOrder->user_id, // 用户id
|
||||
'notice_at' => now(), // 通知时间
|
||||
]);
|
||||
}
|
||||
|
||||
public function createFundWater(ProductOrder $productOrder): void
|
||||
{
|
||||
FundWater::create([
|
||||
'store_id' => $productOrder->store_id, // 门店id
|
||||
'order_id' => $productOrder->id, // 订单id
|
||||
'order_type' => FundWater::BASE_TYPE_ORDER, // 订单类型 1产品订单 2挂号订单
|
||||
'user_id' => $productOrder->user_id, // 用户id
|
||||
'type' => FundWater::FUND_WATER_TYPE_ENTER,//入账
|
||||
'price' => $productOrder->total_pay_price,
|
||||
'order_no' => $productOrder->order_no,
|
||||
'refund_no' => 0,
|
||||
'pay_type' => $productOrder->type, // 支付类型 1微信 2易票联
|
||||
'created_at' => time(),
|
||||
'updated_at' => time()
|
||||
]);
|
||||
}
|
||||
}
|
||||
95
app/Jobs/ProductOrderCancelJob.php
Normal file
95
app/Jobs/ProductOrderCancelJob.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\YiiModels\ProductOrder;
|
||||
use Carbon\Carbon;
|
||||
use Exception;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class ProductOrderCancelJob implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
private ?int $productOrderId = null;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($productOrderId)
|
||||
{
|
||||
$this->productOrderId = $productOrderId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return bool
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$productOrder = ProductOrder::find($this->productOrderId);
|
||||
if (!$productOrder) {
|
||||
log_s('订单信息不存在:' . "[productOrderId:$this->productOrderId]", 'job', 'order-cancel');
|
||||
return true;
|
||||
}
|
||||
if ($productOrder->is_pay == ProductOrder::IS_PAY_TRUE) {
|
||||
log_s('订单已支付:' . "[productOrderId:$this->productOrderId]", 'job', 'order-cancel');
|
||||
return true;
|
||||
}
|
||||
if ($productOrder->status != ProductOrder::STATUS_UNPAID) {
|
||||
log_s('取消失败,订单状态为' . $productOrder->status_string . "[productOrderId:$this->productOrderId]", 'job', 'order-cancel');
|
||||
return true;
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
$productOrder->status = ProductOrder::STATUS_CANCEL;
|
||||
$productOrder->cancel_status = ProductOrder::CANCEL_STATUS_TRUE;
|
||||
$productOrder->cancel_time = time();
|
||||
$productOrder->cancel_remark = '未支付超时取消';
|
||||
$productOrder->save();
|
||||
|
||||
$productOrder->logs()->create([
|
||||
'content' => '未支付超时取消订单'
|
||||
]);
|
||||
|
||||
$this->createNotice($productOrder, '您的订单因超时已取消');
|
||||
|
||||
// // 同步数据
|
||||
// $productOrder->refresh();
|
||||
// $productOrder->load(['items']);
|
||||
// Artisan::call('data:sync', [
|
||||
// '--type' => 'product_order_sync',
|
||||
// '--data' => $productOrder->toArray(),
|
||||
// ]);
|
||||
|
||||
if ($productOrder->is_online == ProductOrder::IS_ONLINE_TRUE && $productOrder->sync_order_no) {
|
||||
// 同步数据(老)
|
||||
Artisan::call('data:sync-old', [
|
||||
'--type' => 'syncOrder',
|
||||
'--data' => json_encode([
|
||||
'order_no' => $productOrder->sync_order_no,
|
||||
'status' => 2, // 1已支付 2已取消 3已退款
|
||||
'time' => Carbon::createFromTimestamp($productOrder->cancel_time)->toDateTimeString(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
} catch (Exception $exception) {
|
||||
DB::rollBack();
|
||||
log_s('超时取消错误:' . "[productOrderId:$this->productOrderId]" . $exception->getMessage() . $exception->getTraceAsString(), 'order', 'error');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
60
app/Models/BaseAuthModel.php
Normal file
60
app/Models/BaseAuthModel.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModelTrait;
|
||||
use DateTimeInterface;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* App\Models\BaseAuthModel
|
||||
*
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\BaseAuthModel newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\BaseAuthModel newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\BaseAuthModel query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class BaseAuthModel extends Authenticatable
|
||||
{
|
||||
protected $dateFormat = 'U';
|
||||
|
||||
use BaseModelTrait;
|
||||
use HasFactory;
|
||||
|
||||
public $connection = 'mysql'; // 使用数据库链接
|
||||
protected $guarded = [];
|
||||
|
||||
/**
|
||||
* created_at_format
|
||||
*
|
||||
* @comment 创建时间的格式化
|
||||
* @return string
|
||||
*/
|
||||
public function getCreatedAtFormatAttribute(): string
|
||||
{
|
||||
return $this[self::CREATED_AT]->toDateTimeString();
|
||||
}
|
||||
|
||||
/**
|
||||
* updated_at_format
|
||||
*
|
||||
* @comment 更新时间的格式化
|
||||
* @return string
|
||||
*/
|
||||
public function getUpdatedAtFormatAttribute(): string
|
||||
{
|
||||
return $this[self::UPDATED_AT]->toDateTimeString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 为数组 / JSON 序列化准备日期。
|
||||
*/
|
||||
protected function serializeDate(DateTimeInterface $date): string
|
||||
{
|
||||
return $date->format($this->dateFormat ?: 'Y-m-d H:i:s');
|
||||
}
|
||||
}
|
||||
74
app/Models/BaseModel.php
Normal file
74
app/Models/BaseModel.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* App\Models\BaseModel
|
||||
*
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\BaseModel newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\BaseModel newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\BaseModel query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class BaseModel extends Model
|
||||
{
|
||||
use BaseModelTrait;
|
||||
use HasFactory;
|
||||
|
||||
public $connection = 'mysql'; // 使用数据库链接
|
||||
protected $guarded = [];
|
||||
|
||||
public const SELECT_ARR_KEY = '-selectArr';
|
||||
public const STATUS = [
|
||||
0 => '无效',
|
||||
1 => '有效',
|
||||
];
|
||||
|
||||
/**
|
||||
* status_string
|
||||
*
|
||||
* @comment 状态名称
|
||||
* @return string
|
||||
*/
|
||||
public function getStatusStringAttribute(): string
|
||||
{
|
||||
return self::STATUS[$this['status']] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* created_at_format
|
||||
*
|
||||
* @comment 创建时间的格式化
|
||||
* @return string
|
||||
*/
|
||||
public function getCreatedAtFormatAttribute(): string
|
||||
{
|
||||
return $this[self::CREATED_AT]->toDateTimeString();
|
||||
}
|
||||
|
||||
/**
|
||||
* updated_at_format
|
||||
*
|
||||
* @comment 更新时间的格式化
|
||||
* @return string
|
||||
*/
|
||||
public function getUpdatedAtFormatAttribute(): string
|
||||
{
|
||||
return $this[self::UPDATED_AT]->toDateTimeString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 为数组 / JSON 序列化准备日期。
|
||||
*/
|
||||
protected function serializeDate(DateTimeInterface $date): string
|
||||
{
|
||||
return $date->format($this->dateFormat ?: 'Y-m-d H:i:s');
|
||||
}
|
||||
}
|
||||
59
app/Models/BaseModelTrait.php
Normal file
59
app/Models/BaseModelTrait.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
trait BaseModelTrait
|
||||
{
|
||||
/**
|
||||
* 创建不重复新订单号.
|
||||
*/
|
||||
public static function getNewNumber(string $fieldName = 'number'): string
|
||||
{
|
||||
$number = now()->format('ymdHis') . rand(10000, 99999);
|
||||
if (self::findNumber($number, $fieldName)) {
|
||||
return self::getNewNumber();
|
||||
}
|
||||
|
||||
return $number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据订单号查询订单.
|
||||
*/
|
||||
public static function findNumber(int|string $number, string $fieldName = 'number'): ?Model
|
||||
{
|
||||
return self::where($fieldName, $number)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* 选项数字.
|
||||
*
|
||||
* @param bool|string $appendNull 是否添加空选项
|
||||
* @param string $key 键名
|
||||
* @param string $value 键值
|
||||
* @param array $suffixData 后缀选项 ['status', 1, '[无效]', []] [字段名, 等于判断值, 真返回值, 假返回值]
|
||||
*/
|
||||
public static function selectArr(bool|string $appendNull = '无', string $key = 'id', string $value = 'name', array $suffixData = []): array
|
||||
{
|
||||
$cacheKey = get_called_class() . self::SELECT_ARR_KEY . $key . $value . md5(implode('|', $suffixData));
|
||||
|
||||
return Cache::remember($cacheKey, 60, function () use ($appendNull, $key, $value, $suffixData) {
|
||||
$data = [];
|
||||
if (false !== $appendNull) {
|
||||
$data[''] = $appendNull;
|
||||
}
|
||||
foreach (self::get() as $model) {
|
||||
$suffix = '';
|
||||
if ($suffixData && 4 == count($suffixData)) {
|
||||
$suffix = $model[$suffixData[0]] == $suffixData[1] ? $suffixData[2] : $suffixData[3];
|
||||
}
|
||||
$data[$model[$key]] = $model[$value] . $suffix;
|
||||
}
|
||||
|
||||
return $data;
|
||||
});
|
||||
}
|
||||
}
|
||||
66
app/Models/Cart.php
Normal file
66
app/Models/Cart.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\YiiModels\Drug;
|
||||
use App\Models\YiiModels\DrugstoreDrug;
|
||||
use App\Models\YiiModels\Store;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
/**
|
||||
* App\Models\Cart
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $user_id 用户ID
|
||||
* @property int $drug_id 药品ID
|
||||
* @property int $store_id 门店ID
|
||||
* @property int $qty 数量
|
||||
* @property string|null $join_at 加入时间
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property-read \App\Models\YiiModels\Drug|null $drug 药品
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @property-read \App\Models\YiiModels\Store|null $store 门店
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Cart newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Cart newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Cart query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Cart extends BaseModel
|
||||
{
|
||||
protected $attributes = [
|
||||
'qty' => 0,
|
||||
];
|
||||
|
||||
protected static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
parent::creating(function (self $model) {
|
||||
if (!isset($model->join_at) && !$model->join_at) {
|
||||
$model->join_at = now();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 药品
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function drug(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Drug::class, 'drug_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 门店
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function store(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Store::class, 'store_id');
|
||||
}
|
||||
}
|
||||
73
app/Models/DrugCategory.php
Normal file
73
app/Models/DrugCategory.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
/**
|
||||
* App\Models\DrugCategory
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $level 分类等级
|
||||
* @property int $parent_id 父级id
|
||||
* @property string $category_name 分类名称
|
||||
* @property int $sort 排序
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property \Illuminate\Support\Carbon|null $deleted_at
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\DrugCategory[] $subs 子分类
|
||||
* @property-read int|null $subs_count
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\DrugCategory newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\DrugCategory newQuery()
|
||||
* @method static \Illuminate\Database\Query\Builder|\App\Models\DrugCategory onlyTrashed()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\DrugCategory query()
|
||||
* @method static \Illuminate\Database\Query\Builder|\App\Models\DrugCategory withTrashed()
|
||||
* @method static \Illuminate\Database\Query\Builder|\App\Models\DrugCategory withoutTrashed()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class DrugCategory extends BaseModel
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
* 药品分类
|
||||
*
|
||||
* @param $cache
|
||||
* @return \Illuminate\Cache\|mixed|mixed[]
|
||||
*/
|
||||
public static function getCategory($cache = true)
|
||||
{
|
||||
$cacheKey = __CLASS__ . '_data_cache';
|
||||
if (Cache::has($cacheKey) && $cache) {
|
||||
return Cache::get($cacheKey, []);
|
||||
}
|
||||
|
||||
$data = self::with(['subs:id,parent_id,category_name'])
|
||||
->select(['id', 'parent_id', 'category_name'])
|
||||
->where('level', 1)
|
||||
->orderBy('sort')
|
||||
->get()
|
||||
->toArray();
|
||||
|
||||
if ($data) {
|
||||
Cache::put($cacheKey, $data, 60);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 子分类
|
||||
* @return HasMany
|
||||
*/
|
||||
public function subs(): HasMany
|
||||
{
|
||||
return $this->hasMany(self::class, 'parent_id', 'id')
|
||||
->where('level', 2)
|
||||
->orderBy('sort');
|
||||
}
|
||||
}
|
||||
66
app/Models/DrugStoreRelation.php
Normal file
66
app/Models/DrugStoreRelation.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\YiiModels\Store;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
/**
|
||||
* App\Models\DrugStoreRelation
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $store_id 门店id
|
||||
* @property int $drug_id 药品id
|
||||
* @property string $price 销售价
|
||||
* @property int $status 状态1下架2上架
|
||||
* @property int $base_sales_volume 基础销量
|
||||
* @property int $true_sales_volume 真实销量
|
||||
* @property int $total_sales_volume 总销量
|
||||
* @property string|null $buy_price 进货(采购)价
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @property-read \App\Models\YiiModels\Store|null $store 门店
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\DrugStoreRelation newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\DrugStoreRelation newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\DrugStoreRelation query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class DrugStoreRelation extends BaseModel
|
||||
{
|
||||
// 状态
|
||||
public const STATUS_OFF = 1;
|
||||
public const STATUS_ON = 2;
|
||||
public const STATUS = [
|
||||
self::STATUS_OFF => '下架',
|
||||
self::STATUS_ON => '上架',
|
||||
];
|
||||
|
||||
protected static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
parent::creating(function (self $model) {
|
||||
$model->total_sales_volume = $model->base_sales_volume + $model->true_sales_volume;
|
||||
});
|
||||
parent::updating(function (self $model) {
|
||||
if (
|
||||
isset($model->total_sales_volume)
|
||||
&& isset($model->base_sales_volume)
|
||||
&& isset($model->true_sales_volume)
|
||||
) {
|
||||
$model->total_sales_volume = $model->base_sales_volume + $model->true_sales_volume;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 门店
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function store(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Store::class, 'store_id');
|
||||
}
|
||||
}
|
||||
32
app/Models/ExpressCompany.php
Normal file
32
app/Models/ExpressCompany.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
/**
|
||||
* App\Models\ExpressCompany
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $name 公司名称
|
||||
* @property string $code 公司编码
|
||||
* @property string $type 公司类型
|
||||
* @property int $sort 排序
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property \Illuminate\Support\Carbon|null $deleted_at
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ExpressCompany newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ExpressCompany newQuery()
|
||||
* @method static \Illuminate\Database\Query\Builder|\App\Models\ExpressCompany onlyTrashed()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ExpressCompany query()
|
||||
* @method static \Illuminate\Database\Query\Builder|\App\Models\ExpressCompany withTrashed()
|
||||
* @method static \Illuminate\Database\Query\Builder|\App\Models\ExpressCompany withoutTrashed()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class ExpressCompany extends BaseModel
|
||||
{
|
||||
use SoftDeletes;
|
||||
}
|
||||
32
app/Models/ExpressDetail.php
Normal file
32
app/Models/ExpressDetail.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
/**
|
||||
* App\Models\ExpressDetail
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $express_no_id 快递单号
|
||||
* @property string|null $status 状态
|
||||
* @property string|null $detail_at 时间
|
||||
* @property string|null $detail 详情
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property \Illuminate\Support\Carbon|null $deleted_at
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ExpressDetail newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ExpressDetail newQuery()
|
||||
* @method static \Illuminate\Database\Query\Builder|\App\Models\ExpressDetail onlyTrashed()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ExpressDetail query()
|
||||
* @method static \Illuminate\Database\Query\Builder|\App\Models\ExpressDetail withTrashed()
|
||||
* @method static \Illuminate\Database\Query\Builder|\App\Models\ExpressDetail withoutTrashed()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class ExpressDetail extends BaseModel
|
||||
{
|
||||
use SoftDeletes;
|
||||
}
|
||||
41
app/Models/ExpressFee.php
Normal file
41
app/Models/ExpressFee.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
/**
|
||||
* App\Models\ExpressFee
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $base_express_fee 基础运费
|
||||
* @property string $free_express_fee 免运费门槛
|
||||
* @property int $is_default 是否默认
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ExpressFee newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ExpressFee newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ExpressFee query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class ExpressFee extends BaseModel
|
||||
{
|
||||
public const IS_DEFAULT_FALSE = 0;
|
||||
public const IS_DEFAULT_TRUE = 1;
|
||||
public const IS_DEFAULT = [
|
||||
self::IS_DEFAULT_FALSE => '未使用',
|
||||
self::IS_DEFAULT_TRUE => '使用中',
|
||||
];
|
||||
|
||||
/**
|
||||
* 获取默认运费模板
|
||||
* @return static|null
|
||||
*/
|
||||
public static function getDefaultExpressFee(): ?self
|
||||
{
|
||||
return self::where('is_default', self::IS_DEFAULT_TRUE)
|
||||
->select(['base_express_fee', 'free_express_fee'])
|
||||
->first();
|
||||
}
|
||||
}
|
||||
85
app/Models/ExpressNo.php
Normal file
85
app/Models/ExpressNo.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
|
||||
/**
|
||||
* App\Models\ExpressNo
|
||||
*
|
||||
* @property int $id
|
||||
* @property string|null $express_company_name 公司名称
|
||||
* @property string $express_company_code 公司编码
|
||||
* @property string $express_no 快递单号
|
||||
* @property string|null $mobile 手机号码
|
||||
* @property int|null $state 物流状态
|
||||
* @property string|null $sync_at 同步时间
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property-read \App\Models\ExpressCompany|null $company 快递公司
|
||||
* @property-read \App\Models\ExpressDetail|null $detail 物流详情[单]
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\ExpressDetail[] $details 物流详情[多]
|
||||
* @property-read int|null $details_count
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $state_string 物流状态
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ExpressNo newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ExpressNo newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ExpressNo query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class ExpressNo extends BaseModel
|
||||
{
|
||||
const STATE_SIGN = 3;
|
||||
const STATE = [
|
||||
1 => '揽收',
|
||||
0 => '在途',
|
||||
5 => '派件',
|
||||
self::STATE_SIGN => '签收',
|
||||
6 => '退回',
|
||||
4 => '退签',
|
||||
7 => '转投',
|
||||
2 => '疑难',
|
||||
8 => '清关',
|
||||
14 => '拒签',
|
||||
];
|
||||
|
||||
/**
|
||||
* @comment 物流详情[单]
|
||||
* @return HasOne
|
||||
*/
|
||||
public function detail(): HasOne
|
||||
{
|
||||
return $this->hasOne(ExpressDetail::class, 'express_no_id')->orderByDesc('detail_at');
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 物流详情[多]
|
||||
* @return HasMany
|
||||
*/
|
||||
public function details(): HasMany
|
||||
{
|
||||
return $this->hasMany(ExpressDetail::class, 'express_no_id')->orderByDesc('detail_at');
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 快递公司
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function company(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ExpressCompany::class, 'express_company_code', 'code');
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 物流状态
|
||||
* @return string
|
||||
*/
|
||||
public function getStateStringAttribute(): string
|
||||
{
|
||||
return self::STATE[$this->state] ?? '';
|
||||
}
|
||||
}
|
||||
257
app/Models/Extend/SoftDeletesInt.php
Normal file
257
app/Models/Extend/SoftDeletesInt.php
Normal file
@@ -0,0 +1,257 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Extend;
|
||||
|
||||
/**
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder withTrashed(bool $withTrashed = true)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder onlyTrashed()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder withoutTrashed()
|
||||
*/
|
||||
trait SoftDeletesInt
|
||||
{
|
||||
/**
|
||||
* Indicates if the model is currently force deleting.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $forceDeleting = false;
|
||||
|
||||
/**
|
||||
* Boot the soft deleting trait for a model.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function bootSoftDeletesInt()
|
||||
{
|
||||
static::addGlobalScope(new SoftDeletingScopeInt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the soft deleting trait for an instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function initializeSoftDeletes()
|
||||
{
|
||||
// if (! isset($this->casts[$this->getDeletedAtColumn()])) {
|
||||
// $this->casts[$this->getDeletedAtColumn()] = 'datetime';
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a hard delete on a soft deleted model.
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
public function forceDelete()
|
||||
{
|
||||
if ($this->fireModelEvent('forceDeleting') === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->forceDeleting = true;
|
||||
|
||||
return tap($this->delete(), function ($deleted) {
|
||||
$this->forceDeleting = false;
|
||||
|
||||
if ($deleted) {
|
||||
$this->fireModelEvent('forceDeleted', false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a hard delete on a soft deleted model without raising any events.
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
public function forceDeleteQuietly()
|
||||
{
|
||||
return static::withoutEvents(fn() => $this->forceDelete());
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the actual delete query on this model instance.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function performDeleteOnModel()
|
||||
{
|
||||
if ($this->forceDeleting) {
|
||||
return tap($this->setKeysForSaveQuery($this->newModelQuery())->forceDelete(), function () {
|
||||
$this->exists = false;
|
||||
});
|
||||
}
|
||||
|
||||
return $this->runSoftDelete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the actual delete query on this model instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function runSoftDelete()
|
||||
{
|
||||
$query = $this->setKeysForSaveQuery($this->newModelQuery());
|
||||
|
||||
$time = $this->freshTimestamp();
|
||||
|
||||
// $columns = [$this->getDeletedAtColumn() => $this->fromDateTime($time)];
|
||||
|
||||
$columns = [$this->getDeletedAtColumn() => 1];
|
||||
|
||||
// $this->{$this->getDeletedAtColumn()} = $time;
|
||||
|
||||
$this->{$this->getDeletedAtColumn()} = 1;
|
||||
|
||||
if ($this->usesTimestamps() && !is_null($this->getUpdatedAtColumn())) {
|
||||
$this->{$this->getUpdatedAtColumn()} = $time;
|
||||
|
||||
$columns[$this->getUpdatedAtColumn()] = $this->fromDateTime($time);
|
||||
}
|
||||
|
||||
$query->update($columns);
|
||||
|
||||
$this->syncOriginalAttributes(array_keys($columns));
|
||||
|
||||
$this->fireModelEvent('trashed', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore a soft-deleted model instance.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function restore()
|
||||
{
|
||||
// If the restoring event does not return false, we will proceed with this
|
||||
// restore operation. Otherwise, we bail out so the developer will stop
|
||||
// the restore totally. We will clear the deleted timestamp and save.
|
||||
if ($this->fireModelEvent('restoring') === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// $this->{$this->getDeletedAtColumn()} = null;
|
||||
|
||||
$this->{$this->getDeletedAtColumn()} = 0;
|
||||
|
||||
// Once we have saved the model, we will fire the "restored" event so this
|
||||
// developer will do anything they need to after a restore operation is
|
||||
// totally finished. Then we will return the result of the save call.
|
||||
$this->exists = true;
|
||||
|
||||
$result = $this->save();
|
||||
|
||||
$this->fireModelEvent('restored', false);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore a soft-deleted model instance without raising any events.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function restoreQuietly()
|
||||
{
|
||||
return static::withoutEvents(fn() => $this->restore());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the model instance has been soft-deleted.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function trashed()
|
||||
{
|
||||
// return ! is_null($this->{$this->getDeletedAtColumn()});
|
||||
|
||||
return $this->{$this->getDeletedAtColumn()} == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a "softDeleted" model event callback with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function softDeleted($callback)
|
||||
{
|
||||
static::registerModelEvent('trashed', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a "restoring" model event callback with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function restoring($callback)
|
||||
{
|
||||
static::registerModelEvent('restoring', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a "restored" model event callback with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function restored($callback)
|
||||
{
|
||||
static::registerModelEvent('restored', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a "forceDeleting" model event callback with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function forceDeleting($callback)
|
||||
{
|
||||
static::registerModelEvent('forceDeleting', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a "forceDeleted" model event callback with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function forceDeleted($callback)
|
||||
{
|
||||
static::registerModelEvent('forceDeleted', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the model is currently force deleting.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isForceDeleting()
|
||||
{
|
||||
return $this->forceDeleting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the "deleted at" column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDeletedAtColumn()
|
||||
{
|
||||
return defined(static::class . '::DELETED_AT') ? static::DELETED_AT : 'is_delete';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully qualified "deleted at" column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedDeletedAtColumn()
|
||||
{
|
||||
return $this->qualifyColumn($this->getDeletedAtColumn());
|
||||
}
|
||||
}
|
||||
163
app/Models/Extend/SoftDeletingScopeInt.php
Normal file
163
app/Models/Extend/SoftDeletingScopeInt.php
Normal file
@@ -0,0 +1,163 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Extend;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Scope;
|
||||
|
||||
class SoftDeletingScopeInt implements Scope
|
||||
{
|
||||
/**
|
||||
* All of the extensions to be added to the builder.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $extensions = ['Restore', 'RestoreOrCreate', 'WithTrashed', 'WithoutTrashed', 'OnlyTrashed'];
|
||||
|
||||
/**
|
||||
* Apply the scope to a given Eloquent query builder.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return void
|
||||
*/
|
||||
public function apply(Builder $builder, Model $model)
|
||||
{
|
||||
$builder->where($model->getQualifiedDeletedAtColumn(), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend the query builder with the needed functions.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @return void
|
||||
*/
|
||||
public function extend(Builder $builder)
|
||||
{
|
||||
foreach ($this->extensions as $extension) {
|
||||
$this->{"add{$extension}"}($builder);
|
||||
}
|
||||
|
||||
$builder->onDelete(function (Builder $builder) {
|
||||
$column = $this->getDeletedAtColumn($builder);
|
||||
|
||||
return $builder->update([
|
||||
// $column => $builder->getModel()->freshTimestampString(),
|
||||
$column => 1,
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "deleted at" column for the builder.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @return string
|
||||
*/
|
||||
protected function getDeletedAtColumn(Builder $builder)
|
||||
{
|
||||
if (count((array)$builder->getQuery()->joins) > 0) {
|
||||
return $builder->getModel()->getQualifiedDeletedAtColumn();
|
||||
}
|
||||
|
||||
return $builder->getModel()->getDeletedAtColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the restore extension to the builder.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @return void
|
||||
*/
|
||||
protected function addRestore(Builder $builder)
|
||||
{
|
||||
$builder->macro('restore', function (Builder $builder) {
|
||||
$builder->withTrashed();
|
||||
|
||||
// return $builder->update([$builder->getModel()->getDeletedAtColumn() => null]);
|
||||
|
||||
return $builder->update([$builder->getModel()->getDeletedAtColumn() => 0]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the restore-or-create extension to the builder.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @return void
|
||||
*/
|
||||
protected function addRestoreOrCreate(Builder $builder)
|
||||
{
|
||||
$builder->macro('restoreOrCreate', function (Builder $builder, array $attributes = [], array $values = []) {
|
||||
$builder->withTrashed();
|
||||
|
||||
return tap($builder->firstOrCreate($attributes, $values), function ($instance) {
|
||||
$instance->restore();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the with-trashed extension to the builder.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @return void
|
||||
*/
|
||||
protected function addWithTrashed(Builder $builder)
|
||||
{
|
||||
$builder->macro('withTrashed', function (Builder $builder, $withTrashed = true) {
|
||||
if (!$withTrashed) {
|
||||
return $builder->withoutTrashed();
|
||||
}
|
||||
|
||||
return $builder->withoutGlobalScope($this);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the without-trashed extension to the builder.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @return void
|
||||
*/
|
||||
protected function addWithoutTrashed(Builder $builder)
|
||||
{
|
||||
$builder->macro('withoutTrashed', function (Builder $builder) {
|
||||
$model = $builder->getModel();
|
||||
|
||||
// $builder->withoutGlobalScope($this)->whereNull(
|
||||
// $model->getQualifiedDeletedAtColumn()
|
||||
// );
|
||||
|
||||
$builder->withoutGlobalScope($this)->where(
|
||||
$model->getQualifiedDeletedAtColumn(), 0
|
||||
);
|
||||
|
||||
return $builder;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the only-trashed extension to the builder.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @return void
|
||||
*/
|
||||
protected function addOnlyTrashed(Builder $builder)
|
||||
{
|
||||
$builder->macro('onlyTrashed', function (Builder $builder) {
|
||||
$model = $builder->getModel();
|
||||
|
||||
// $builder->withoutGlobalScope($this)->whereNotNull(
|
||||
// $model->getQualifiedDeletedAtColumn()
|
||||
// );
|
||||
|
||||
$builder->withoutGlobalScope($this)->where(
|
||||
$model->getQualifiedDeletedAtColumn(), 1
|
||||
);
|
||||
|
||||
return $builder;
|
||||
});
|
||||
}
|
||||
}
|
||||
272
app/Models/Pay/Bill.php
Normal file
272
app/Models/Pay/Bill.php
Normal file
@@ -0,0 +1,272 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Pay;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use App\Models\BaseModelTrait;
|
||||
use App\Models\YiiModels\User;
|
||||
use Exception;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
|
||||
/**
|
||||
* App\Models\Pay\Bill
|
||||
*
|
||||
* @property int $id
|
||||
* @property string|null $mchid 商户ID
|
||||
* @property string|null $appid 应用ID
|
||||
* @property string|null $billable_type 多态模型名称
|
||||
* @property int|null $billable_id 多态模型ID
|
||||
* @property int|null $user_id 用户ID
|
||||
* @property string|null $openid Openid(微信支付涉及)
|
||||
* @property string|null $title 订单名称
|
||||
* @property int|null $pay_way 支付方式
|
||||
* @property string $pay_amount 支付发起金额
|
||||
* @property string $pay_no 商户订单号
|
||||
* @property string|null $pay_service_no 支付商订单号
|
||||
* @property string|null $pay_at 支付成功时间
|
||||
* @property int $bill_status 账单状态
|
||||
* @property int $pay_status 支付状态
|
||||
* @property string|null $extra 额外数据
|
||||
* @property string|null $remark 备注
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property-read \Illuminate\Database\Eloquent\Model|\Eloquent $billable
|
||||
* @property-read string $bill_status_string 账单状态名称
|
||||
* @property-read float $can_refund_amount 可退款的金额
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $pay_status_string 支付状态名称
|
||||
* @property-read string $pay_way_alias 支付方式别名
|
||||
* @property-read string $pay_way_string 支付方式名称
|
||||
* @property-read float $refunded_amount 已退款的金额
|
||||
* @property-read float $refunding_amount 退款中的金额
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\Pay\RefundBill[] $refunds 退款单
|
||||
* @property-read int|null $refunds_count
|
||||
* @property-read \App\Models\YiiModels\User|null $user 用户
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Pay\Bill newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Pay\Bill newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Pay\Bill query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Bill extends BaseModel
|
||||
{
|
||||
use BaseModelTrait;
|
||||
|
||||
protected $attributes = [
|
||||
'bill_status' => self::BILL_STATUS_UNSUCCESSFUL,
|
||||
'pay_status' => self::PAY_STATUS_UN_PAY,
|
||||
];
|
||||
|
||||
// 支付方式
|
||||
const PAY_WAY_ALIAS = [
|
||||
self::PAY_WAY_WECHAT => 'wechat',
|
||||
self::PAY_WAY_ALIPAY => 'alipay',
|
||||
self::PAY_WAY_UNIPAY => 'unipay',
|
||||
];
|
||||
const PAY_WAY = [
|
||||
self::PAY_WAY_WECHAT => '微信',
|
||||
self::PAY_WAY_ALIPAY => '支付宝',
|
||||
self::PAY_WAY_UNIPAY => '银联',
|
||||
];
|
||||
const PAY_WAY_WECHAT = 1;
|
||||
const PAY_WAY_ALIPAY = 2;
|
||||
const PAY_WAY_UNIPAY = 3;
|
||||
|
||||
// 账单状态
|
||||
const BILL_STATUS_LABEL = [
|
||||
self::BILL_STATUS_UNSUCCESSFUL => 'warning',
|
||||
self::BILL_STATUS_SUCCESSFUL => 'success',
|
||||
];
|
||||
const BILL_STATUS = [
|
||||
self::BILL_STATUS_UNSUCCESSFUL => '未支付成功过',
|
||||
self::BILL_STATUS_SUCCESSFUL => '支付成功过',
|
||||
];
|
||||
const BILL_STATUS_UNSUCCESSFUL = 0;
|
||||
const BILL_STATUS_SUCCESSFUL = 1;
|
||||
|
||||
// 支付状态
|
||||
const PAY_STATUS_LABEL = [
|
||||
self::PAY_STATUS_UN_PAY => 'info',
|
||||
self::PAY_STATUS_SUCCESS => 'success',
|
||||
self::PAY_STATUS_FAIL => 'primary',
|
||||
self::PAY_STATUS_CANCEL => 'default',
|
||||
self::PAY_STATUS_REFUND_PART => 'warning',
|
||||
self::PAY_STATUS_REFUND_FULL => 'danger',
|
||||
];
|
||||
const PAY_STATUS = [
|
||||
self::PAY_STATUS_UN_PAY => '未支付',
|
||||
self::PAY_STATUS_SUCCESS => '付款成功',
|
||||
self::PAY_STATUS_FAIL => '付款失败',
|
||||
self::PAY_STATUS_CANCEL => '付款取消',
|
||||
self::PAY_STATUS_REFUND_PART => '部分退款',
|
||||
self::PAY_STATUS_REFUND_FULL => '全额退款',
|
||||
];
|
||||
const PAY_STATUS_UN_PAY = 1;
|
||||
const PAY_STATUS_SUCCESS = 2;
|
||||
const PAY_STATUS_FAIL = 4;
|
||||
const PAY_STATUS_CANCEL = 5;
|
||||
const PAY_STATUS_REFUND_PART = 7;
|
||||
const PAY_STATUS_REFUND_FULL = 8;
|
||||
|
||||
protected static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
static::creating(function (self $bill) {
|
||||
if (!$bill->pay_no) {
|
||||
$bill->pay_no = self::getNewNumber('pay_no');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function billable(): MorphTo
|
||||
{
|
||||
return $this->morphTo();
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 用户
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 退款单
|
||||
* @return HasMany
|
||||
*/
|
||||
public function refunds(): HasMany
|
||||
{
|
||||
return $this->hasMany(RefundBill::class, 'bill_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* pay_way_string
|
||||
*
|
||||
* @comment 支付方式名称
|
||||
* @return string
|
||||
*/
|
||||
public function getPayWayStringAttribute(): string
|
||||
{
|
||||
return self::PAY_WAY[$this->pay_way] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* pay_way_alias
|
||||
*
|
||||
* @comment 支付方式别名
|
||||
* @return string
|
||||
*/
|
||||
public function getPayWayAliasAttribute(): string
|
||||
{
|
||||
return self::PAY_WAY_ALIAS[$this->pay_way] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* bill_status_string
|
||||
*
|
||||
* @comment 账单状态名称
|
||||
* @return string
|
||||
*/
|
||||
public function getBillStatusStringAttribute(): string
|
||||
{
|
||||
return self::BILL_STATUS[$this->bill_status] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* pay_status_string
|
||||
*
|
||||
* @comment 支付状态名称
|
||||
* @return string
|
||||
*/
|
||||
public function getPayStatusStringAttribute(): string
|
||||
{
|
||||
return self::PAY_STATUS[$this->pay_status] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* refunded_amount
|
||||
*
|
||||
* @comment 已退款的金额
|
||||
* @return float
|
||||
*/
|
||||
public function getRefundedAmountAttribute(): float
|
||||
{
|
||||
return $this->refunds->where('refund_status', 2)->sum('refund_amount');
|
||||
}
|
||||
|
||||
/**
|
||||
* refunding_amount
|
||||
*
|
||||
* @comment 退款中的金额
|
||||
* @return float
|
||||
*/
|
||||
public function getRefundingAmountAttribute(): float
|
||||
{
|
||||
return $this->refunds->where('refund_status', 1)->sum('refund_amount');
|
||||
}
|
||||
|
||||
/**
|
||||
* can_refund_amount
|
||||
*
|
||||
* @comment 可退款的金额
|
||||
* @return float
|
||||
*/
|
||||
public function getCanRefundAmountAttribute(): float
|
||||
{
|
||||
return $this->pay_amount - $this->refunded_amount - $this->refunding_amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付回调通知处理 - 异步.
|
||||
*
|
||||
* @param array $data
|
||||
* @param int $payWay
|
||||
* @return bool|string
|
||||
*/
|
||||
public static function handleNotify(array $data, int $payWay): bool|string
|
||||
{
|
||||
$bill = self::where('pay_no', $data['pay_no'])->where('pay_way', $payWay)->first();
|
||||
if (!$bill) {
|
||||
log_i("找不到支付订单信息:{$data['pay_no']}", 'pay-bill-error', $bill->pay_way_alias);
|
||||
return '找不到支付订单信息';
|
||||
}
|
||||
if ($bill->pay_status != self::PAY_STATUS_UN_PAY) {
|
||||
// [付款失败, 付款取消] 安排退款
|
||||
if (in_array($bill->pay_status, [self::PAY_STATUS_FAIL, self::PAY_STATUS_CANCEL])) {
|
||||
// todo
|
||||
return true;
|
||||
}
|
||||
log_i("订单状态非未支付:{$data['pay_no']},订单状态:{$bill->pay_status_string}", 'pay-bill-error', $bill->pay_way_alias);
|
||||
return '订单状态非未支付';
|
||||
}
|
||||
if ($bill->pay_amount != $data['pay_amount']) {
|
||||
log_i("订单支付金额不一致:{$data['pay_no']},订单金额:{$bill->pay_amount},回调金额:{$data['pay_amount']}", 'pay-bill-error', $bill->pay_way_alias);
|
||||
return '订单支付金额不一致';
|
||||
}
|
||||
|
||||
$bill->fill([
|
||||
'mchid' => $data['mchid'],
|
||||
'appid' => $data['appid'],
|
||||
'pay_service_no' => $data['pay_service_no'],
|
||||
'pay_at' => $data['pay_at'],
|
||||
'bill_status' => self::BILL_STATUS_SUCCESSFUL,
|
||||
'pay_status' => self::PAY_STATUS_SUCCESS,
|
||||
]);
|
||||
$bill->save();
|
||||
|
||||
try {
|
||||
$bill->loadMissing(['billable']);
|
||||
if ($bill->billable) {
|
||||
$bill->billable->handlePied($bill);
|
||||
}
|
||||
} catch (Exception $exception) {
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
154
app/Models/Pay/RefundBill.php
Normal file
154
app/Models/Pay/RefundBill.php
Normal file
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Pay;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Exception;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
|
||||
/**
|
||||
* App\Models\Pay\RefundBill
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $bill_id 支付订单号id
|
||||
* @property string|null $refund_billable_type 多态模型名称
|
||||
* @property int|null $refund_billable_id 支付订单号id
|
||||
* @property string $refund_amount 退款发起金额
|
||||
* @property string $refund_no 退款商户订单号
|
||||
* @property string|null $refund_service_no 退款支付商订单号
|
||||
* @property string|null $refund_at 退款到账时间
|
||||
* @property int $refund_status 退款状态
|
||||
* @property string|null $remark 备注
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property-read \App\Models\Pay\Bill|null $bill 支付单
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $refund_status_string 退款状态名称
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @property-read \Illuminate\Database\Eloquent\Model|\Eloquent $refundBillable
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Pay\RefundBill newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Pay\RefundBill newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Pay\RefundBill query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class RefundBill extends BaseModel
|
||||
{
|
||||
protected $attributes = [
|
||||
'refund_status' => self::REFUND_STATUS_REFUNDING,
|
||||
];
|
||||
|
||||
// 退款状态
|
||||
const REFUND_STATUS_LABEL = [
|
||||
self::REFUND_STATUS_REFUNDING => 'info',
|
||||
self::REFUND_STATUS_SUCCESS => 'success',
|
||||
self::REFUND_STATUS_FAIL => 'error',
|
||||
self::REFUND_STATUS_CANCEL => 'default',
|
||||
];
|
||||
const REFUND_STATUS = [
|
||||
self::REFUND_STATUS_REFUNDING => '退款中',
|
||||
self::REFUND_STATUS_SUCCESS => '退款成功',
|
||||
self::REFUND_STATUS_FAIL => '退款失败',
|
||||
self::REFUND_STATUS_CANCEL => '退款取消',
|
||||
];
|
||||
const REFUND_STATUS_REFUNDING = 1;
|
||||
const REFUND_STATUS_SUCCESS = 2;
|
||||
const REFUND_STATUS_FAIL = 3;
|
||||
const REFUND_STATUS_CANCEL = 4;
|
||||
|
||||
|
||||
protected static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
static::creating(function (self $refundBill) {
|
||||
if (!$refundBill->refund_no) {
|
||||
$refundBill->refund_no = self::getNewNumber('refund_no');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 支付单
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function bill(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Bill::class, 'bill_id');
|
||||
}
|
||||
|
||||
public function refundBillable(): MorphTo
|
||||
{
|
||||
return $this->morphTo();
|
||||
}
|
||||
|
||||
/**
|
||||
* refund_status_string
|
||||
*
|
||||
* @comment 退款状态名称
|
||||
* @return string
|
||||
*/
|
||||
public function getRefundStatusStringAttribute(): string
|
||||
{
|
||||
return self::REFUND_STATUS[$this->refund_status] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款回调通知处理 - 异步.
|
||||
*
|
||||
* @param array $data
|
||||
* @return bool|string
|
||||
*/
|
||||
public static function handleNotify(array $data): bool|string
|
||||
{
|
||||
/* @var RefundBill $refund */
|
||||
$refund = self::with('bill')->where('refund_no', $data['refund_no'])->first();
|
||||
if (!$refund) {
|
||||
log_i("找不到退款订单信息:退款单 {$data['refund_no']} 支付单 {$data['pay_no']}", 'refund-bill-error', $refund->bill->pay_way_alias);
|
||||
return '找不到退款订单信息';
|
||||
}
|
||||
if ($refund->refund_status != self::REFUND_STATUS_REFUNDING) {
|
||||
log_i("订单状态非退款中:{$data['refund_no']},订单状态:{$refund->refund_status_string}", 'refund-bill-error', $refund->bill->pay_way_alias);
|
||||
return '订单状态非退款中';
|
||||
}
|
||||
if ($refund->refund_amount != $data['refund_amount']) {
|
||||
log_i("订单退款金额不一致:{$data['refund_no']},订单金额:{$refund->refund_amount},回调金额:{$data['refund_amount']}", 'refund-bill-error', $refund->bill->pay_way_alias);
|
||||
return '订单退款金额不一致';
|
||||
}
|
||||
|
||||
$refund->fill([
|
||||
'refund_service_no' => $data['refund_service_no'],
|
||||
'refund_at' => $data['refund_at'],
|
||||
'refund_status' => self::REFUND_STATUS_SUCCESS,
|
||||
]);
|
||||
$refund->save();
|
||||
|
||||
$refund->bill->load(['refunds' => function (Relation $relation) {
|
||||
$relation->where('refund_status', self::REFUND_STATUS_SUCCESS);
|
||||
}]);
|
||||
$refund->bill->fill([
|
||||
'pay_status' => $refund->bill->refunds->sum('refund_amount') == $refund->bill->pay_amount
|
||||
? Bill::PAY_STATUS_REFUND_FULL
|
||||
: Bill::PAY_STATUS_REFUND_PART
|
||||
]);
|
||||
$refund->bill->save();
|
||||
|
||||
try {
|
||||
if ($refund->refund_billable_type && $refund->refund_billable_id) {
|
||||
$refund->loadMissing(['refundBillable']);
|
||||
if ($refund->refundBillable) {
|
||||
$refund->refundBillable->handleRefunded($refund);
|
||||
}
|
||||
} else {
|
||||
$refund->bill->loadMissing(['billable']);
|
||||
if ($refund->bill->billable) {
|
||||
$refund->bill->billable->handleRefunded($refund);
|
||||
}
|
||||
}
|
||||
} catch (Exception $exception) {
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
61
app/Models/ProductOrderItem.php
Normal file
61
app/Models/ProductOrderItem.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\YiiModels\Drug;
|
||||
use App\Models\YiiModels\DrugstoreDrug;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
/**
|
||||
* App\Models\ProductOrderItem
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $product_order_id 商品订单id
|
||||
* @property int $drug_id 商品id
|
||||
* @property string|null $drug_image 图片
|
||||
* @property int $number 数量
|
||||
* @property string $price 价格
|
||||
* @property string $drug_name 商品名称
|
||||
* @property string|null $small_info 商品简介
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property-read \App\Models\YiiModels\Drug|null $drug 药品
|
||||
* @property-read \App\Models\DrugStoreRelation|null $drugStoreRelation 门店售卖药品关系表[单]
|
||||
* @property-read \App\Models\YiiModels\DrugstoreDrug|null $drugstoreDrug 门店药品关系(库存)
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ProductOrderItem newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ProductOrderItem newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ProductOrderItem query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class ProductOrderItem extends BaseModel
|
||||
{
|
||||
/**
|
||||
* @comment 药品
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function drug(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Drug::class, 'drug_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 门店售卖药品关系表[单]
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function drugStoreRelation(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(DrugStoreRelation::class, 'drug_id', 'drug_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 门店药品关系(库存)
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function drugstoreDrug(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(DrugstoreDrug::class, 'drug_id', 'drug_id');
|
||||
}
|
||||
}
|
||||
23
app/Models/YiiModels/ADemo.php
Normal file
23
app/Models/YiiModels/ADemo.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
use App\Models\Extend\SoftDeletesInt;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\ADemo
|
||||
*
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\ADemo newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\ADemo newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\ADemo query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class ADemo extends YiiBaseModel
|
||||
{
|
||||
use SoftDeletesInt;
|
||||
// public $table = 'a_demo';
|
||||
// public $timestamps = false;
|
||||
}
|
||||
31
app/Models/YiiModels/Address.php
Normal file
31
app/Models/YiiModels/Address.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
use App\Models\Extend\SoftDeletesInt;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\Address
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $user_id
|
||||
* @property string $name
|
||||
* @property string $mobile
|
||||
* @property string $region 地区
|
||||
* @property string $detail_address 详细地址
|
||||
* @property int $is_default 是否默认地址0否1是
|
||||
* @property \Illuminate\Support\Carbon $created_at
|
||||
* @property \Illuminate\Support\Carbon $updated_at
|
||||
* @property int $is_delete
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\Address newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\Address newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\Address query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Address extends YiiBaseModel
|
||||
{
|
||||
use SoftDeletesInt;
|
||||
}
|
||||
32
app/Models/YiiModels/ChineseRecipe.php
Normal file
32
app/Models/YiiModels/ChineseRecipe.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\ChineseRecipe
|
||||
*
|
||||
* @property int $id
|
||||
* @property string|null $content 药方内容
|
||||
* @property int $deployment 调配 1煎煮2外配
|
||||
* @property int $dosage 剂数
|
||||
* @property int $consumption 每天几次
|
||||
* @property int|null $usage 用法
|
||||
* @property int|null $fufa_id 关联使用时间表
|
||||
* @property int $volume
|
||||
* @property int|null $is_deepfry 是否浓煎 0否1是
|
||||
* @property string $cm_id 中药处方的中药表id
|
||||
* @property string $total_price 价格
|
||||
* @property string|null $remark 备注
|
||||
* @property \Illuminate\Support\Carbon $created_at
|
||||
* @property \Illuminate\Support\Carbon $updated_at
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\ChineseRecipe newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\ChineseRecipe newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\ChineseRecipe query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class ChineseRecipe extends YiiBaseModel
|
||||
{
|
||||
}
|
||||
34
app/Models/YiiModels/DoctorArticle.php
Normal file
34
app/Models/YiiModels/DoctorArticle.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
use App\Models\Extend\SoftDeletesInt;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\DoctorArticle
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $su_id 医生id
|
||||
* @property string|null $cover 封面
|
||||
* @property string $title 文章标题
|
||||
* @property string|null $intro 简介
|
||||
* @property string|null $content 内容
|
||||
* @property string|null $video_url 视频链接
|
||||
* @property int $read_num 阅读量
|
||||
* @property int $collection
|
||||
* @property int $is_draft 是否是草稿0否1是
|
||||
* @property \Illuminate\Support\Carbon $created_at
|
||||
* @property \Illuminate\Support\Carbon $updated_at
|
||||
* @property int $is_delete
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\DoctorArticle newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\DoctorArticle newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\DoctorArticle query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class DoctorArticle extends YiiBaseModel
|
||||
{
|
||||
use SoftDeletesInt;
|
||||
}
|
||||
165
app/Models/YiiModels/Drug.php
Normal file
165
app/Models/YiiModels/Drug.php
Normal file
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
use App\Models\DrugStoreBase;
|
||||
use App\Models\DrugStoreRelation;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\Drug
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $drug_name 药名
|
||||
* @property string $pinyin_simple 拼音首拼
|
||||
* @property string|null $source 货源(厂家)
|
||||
* @property string $type 类型 1中药2西药3颗粒配方
|
||||
* @property int $is_otc 是否处方药
|
||||
* @property int $category_first 一级分类
|
||||
* @property int $category_second 二级分类
|
||||
* @property string|null $small_info 简介
|
||||
* @property string|null $info 基础信息
|
||||
* @property string|null $content 详情信息
|
||||
* @property string|null $usage 用法
|
||||
* @property string|null $function 功能主治
|
||||
* @property string $specification 规格
|
||||
* @property string|null $image 药品图片
|
||||
* @property int $time_id 使用时间id
|
||||
* @property int $type_id 使用方法id
|
||||
* @property int $frequency_id 频率id
|
||||
* @property int|null $unit_id 单位id
|
||||
* @property int $number 数量
|
||||
* @property int $status 状态 1草稿 2下架 3上架
|
||||
* @property string|null $drug_number 药品编号
|
||||
* @property string|null $bar_code 条形码
|
||||
* @property string|null $guozi_no 国字准号
|
||||
* @property string|null $drug_alias 药品别名
|
||||
* @property string|null $place 产地
|
||||
* @property string|null $decotion 煎法
|
||||
* @property string|null $instruction 说明书图片
|
||||
* @property \Illuminate\Support\Carbon $updated_at
|
||||
* @property \Illuminate\Support\Carbon $created_at
|
||||
* @property-read \App\Models\DrugStoreRelation|null $drugStoreRelation 门店售卖药品关系表[单]
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\DrugStoreRelation[] $drugStoreRelations 门店售卖药品关系表[多]
|
||||
* @property-read int|null $drug_store_relations_count
|
||||
* @property-read \App\Models\YiiModels\DrugstoreDrug|null $drugstoreDrug 门店药品关系(库存)[单关联]
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\YiiModels\DrugstoreDrug[] $drugstoreDrugs 门店药品关系(库存)[多关联]
|
||||
* @property-read int|null $drugstore_drugs_count
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @property-read \App\Models\YiiModels\WestUnit|null $unit 单位
|
||||
* @property-read \App\Models\YiiModels\DrugUseTime|null $useTime 使用时间
|
||||
* @property-read \App\Models\YiiModels\DrugUseFrequency|null $userFrequency 频率
|
||||
* @property-read \App\Models\YiiModels\DrugUseType|null $userType 使用方法
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\Drug newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\Drug newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\Drug query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Drug extends YiiBaseModel
|
||||
{
|
||||
// 药品类型
|
||||
public const TYPE_CHINESE_DRUG = 1;
|
||||
public const TYPE_WEST_DRUG = 2;
|
||||
public const TYPE_PELLET_DRUG = 3;
|
||||
public const TYPE_PELLET_PATENT = 4;
|
||||
public const TYPE = [
|
||||
self::TYPE_CHINESE_DRUG => '中药',
|
||||
self::TYPE_WEST_DRUG => '西药',
|
||||
self::TYPE_PELLET_DRUG => '颗粒配方',
|
||||
self::TYPE_PELLET_PATENT => '中成药',
|
||||
];
|
||||
|
||||
// 处方类型
|
||||
public const IS_OTC_FALSE = 0;
|
||||
public const IS_OTC_TRUE = 1;
|
||||
public const IS_OTC = [
|
||||
self::IS_OTC_FALSE => '非处方药',
|
||||
self::IS_OTC_TRUE => '处方药',
|
||||
];
|
||||
|
||||
// 状态
|
||||
public const STATUS_DRAFT = 0;
|
||||
public const STATUS_OFF = 1;
|
||||
public const STATUS_ON = 2;
|
||||
public const STATUS = [
|
||||
self::STATUS_DRAFT => '草稿',
|
||||
self::STATUS_OFF => '下架',
|
||||
self::STATUS_ON => '上架',
|
||||
];
|
||||
|
||||
/**
|
||||
* @comment 门店药品关系(库存)[单关联]
|
||||
* @return HasOne
|
||||
*/
|
||||
public function drugstoreDrug(): HasOne
|
||||
{
|
||||
return $this->hasOne(DrugstoreDrug::class, 'drug_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 门店药品关系(库存)[多关联]
|
||||
* @return HasMany
|
||||
*/
|
||||
public function drugstoreDrugs(): HasMany
|
||||
{
|
||||
return $this->hasMany(DrugstoreDrug::class, 'drug_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 门店售卖药品关系表[单]
|
||||
* @return HasOne
|
||||
*/
|
||||
public function drugStoreRelation(): HasOne
|
||||
{
|
||||
return $this->hasOne(DrugStoreRelation::class, 'drug_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 门店售卖药品关系表[多]
|
||||
* @return HasMany
|
||||
*/
|
||||
public function drugStoreRelations(): HasMany
|
||||
{
|
||||
return $this->hasMany(DrugStoreRelation::class, 'drug_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 使用时间
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function useTime(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(DrugUseTime::class, 'time_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 使用方法
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function userType(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(DrugUseType::class, 'type_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 频率
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function userFrequency(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(DrugUseFrequency::class, 'frequency_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 单位
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function unit(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(WestUnit::class, 'unit_id');
|
||||
}
|
||||
}
|
||||
22
app/Models/YiiModels/DrugDosage.php
Normal file
22
app/Models/YiiModels/DrugDosage.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\DrugDosage
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $num
|
||||
* @property \Illuminate\Support\Carbon $created_at
|
||||
* @property \Illuminate\Support\Carbon $updated_at
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\DrugDosage newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\DrugDosage newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\DrugDosage query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class DrugDosage extends YiiBaseModel
|
||||
{
|
||||
}
|
||||
22
app/Models/YiiModels/DrugUseFrequency.php
Normal file
22
app/Models/YiiModels/DrugUseFrequency.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\DrugUseFrequency
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property \Illuminate\Support\Carbon $created_at
|
||||
* @property \Illuminate\Support\Carbon $updated_at
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\DrugUseFrequency newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\DrugUseFrequency newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\DrugUseFrequency query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class DrugUseFrequency extends YiiBaseModel
|
||||
{
|
||||
}
|
||||
22
app/Models/YiiModels/DrugUseNum.php
Normal file
22
app/Models/YiiModels/DrugUseNum.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\DrugUseNum
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property \Illuminate\Support\Carbon $created_at
|
||||
* @property \Illuminate\Support\Carbon $updated_at
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\DrugUseNum newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\DrugUseNum newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\DrugUseNum query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class DrugUseNum extends YiiBaseModel
|
||||
{
|
||||
}
|
||||
22
app/Models/YiiModels/DrugUseTime.php
Normal file
22
app/Models/YiiModels/DrugUseTime.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\DrugUseTime
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property \Illuminate\Support\Carbon $created_at
|
||||
* @property \Illuminate\Support\Carbon $updated_at
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\DrugUseTime newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\DrugUseTime newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\DrugUseTime query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class DrugUseTime extends YiiBaseModel
|
||||
{
|
||||
}
|
||||
22
app/Models/YiiModels/DrugUseType.php
Normal file
22
app/Models/YiiModels/DrugUseType.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\DrugUseType
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property \Illuminate\Support\Carbon $created_at
|
||||
* @property \Illuminate\Support\Carbon $updated_at
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\DrugUseType newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\DrugUseType newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\DrugUseType query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class DrugUseType extends YiiBaseModel
|
||||
{
|
||||
}
|
||||
23
app/Models/YiiModels/Drugstore.php
Normal file
23
app/Models/YiiModels/Drugstore.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\Drugstore
|
||||
*
|
||||
* @property int $id 主键id
|
||||
* @property string $name 药房名称
|
||||
* @property string $position 药房位置
|
||||
* @property \Illuminate\Support\Carbon $created_at
|
||||
* @property \Illuminate\Support\Carbon $updated_at
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\Drugstore newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\Drugstore newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\Drugstore query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Drugstore extends YiiBaseModel
|
||||
{
|
||||
}
|
||||
57
app/Models/YiiModels/DrugstoreDrug.php
Normal file
57
app/Models/YiiModels/DrugstoreDrug.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\DrugstoreDrug
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $drugstore_id 药房id
|
||||
* @property int $drug_id 药id
|
||||
* @property int $type 类型 1中药2西药3颗粒配方
|
||||
* @property string $price 销售价格
|
||||
* @property string|null $market_price 市场价
|
||||
* @property int $stock 库存
|
||||
* @property int|null $status 状态1下架2上架
|
||||
* @property int $frozen_number 冻结数量
|
||||
* @property \Illuminate\Support\Carbon $created_at
|
||||
* @property \Illuminate\Support\Carbon $updated_at
|
||||
* @property-read \App\Models\YiiModels\Drug|null $drug 药品
|
||||
* @property-read \App\Models\YiiModels\Drugstore|null $drugstore 药房
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\DrugstoreDrug newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\DrugstoreDrug newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\DrugstoreDrug query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class DrugstoreDrug extends YiiBaseModel
|
||||
{
|
||||
// 药品类型
|
||||
public const TYPE_CHINESE_DRUG = Drug::TYPE_CHINESE_DRUG;
|
||||
public const TYPE_WEST_DRUG = Drug::TYPE_WEST_DRUG;
|
||||
public const TYPE_PELLET_DRUG = Drug::TYPE_PELLET_DRUG;
|
||||
public const TYPE_PELLET_PATENT = Drug::TYPE_PELLET_PATENT;
|
||||
public const TYPE = Drug::TYPE;
|
||||
|
||||
/**
|
||||
* @comment 药品
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function drug(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Drug::class, 'drug_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 药房
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function drugstore(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Drugstore::class, 'drugstore_id');
|
||||
}
|
||||
}
|
||||
56
app/Models/YiiModels/FundWater.php
Normal file
56
app/Models/YiiModels/FundWater.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
use App\Models\Extend\SoftDeletesInt;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\Address
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $store_id
|
||||
* @property int $user_id
|
||||
* @property int $order_id
|
||||
* @property int $order_type
|
||||
* @property string $type
|
||||
* @property string $order_no
|
||||
* @property string $refund_no
|
||||
* @property number $price
|
||||
* @property int $pay_type
|
||||
* @property \Illuminate\Support\Carbon $created_at
|
||||
* @property \Illuminate\Support\Carbon $updated_at
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\Address newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\Address newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\Address query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class FundWater extends YiiBaseModel
|
||||
{
|
||||
use SoftDeletesInt;
|
||||
|
||||
// 订单类型
|
||||
const BASE_TYPE_ORDER = 1;
|
||||
const BASE_TYPE_REGISTER = 2;
|
||||
|
||||
const BASE_TYPE = [
|
||||
self::BASE_TYPE_ORDER => '产品订单',
|
||||
self::BASE_TYPE_REGISTER => '挂号订单',
|
||||
];
|
||||
|
||||
//流水类型
|
||||
const FUND_WATER_TYPE_ENTER = 'enter';
|
||||
const FUND_WATER_TYPE_REFUND = 'refund';
|
||||
const FUND_WATER_TYPE = [
|
||||
self::FUND_WATER_TYPE_ENTER => '入账',
|
||||
self::FUND_WATER_TYPE_REFUND => '出账',
|
||||
];
|
||||
|
||||
//支付类型
|
||||
const PAY_TYPE_WECHAT = 1;
|
||||
const PAY_TYPE_EPLPAY = 2;
|
||||
const PAY_TYPE = [
|
||||
self::PAY_TYPE_WECHAT => '微信',
|
||||
self::PAY_TYPE_EPLPAY => '易票联',
|
||||
];
|
||||
|
||||
}
|
||||
32
app/Models/YiiModels/GranularRecipe.php
Normal file
32
app/Models/YiiModels/GranularRecipe.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\GranularRecipe
|
||||
*
|
||||
* @property int $id
|
||||
* @property string|null $content 药方内容
|
||||
* @property int $deployment 调配 1煎煮2外配
|
||||
* @property int $dosage 剂数
|
||||
* @property int $consumption 用量
|
||||
* @property int|null $usage 用法
|
||||
* @property int|null $fufa_id 关联使用时间表
|
||||
* @property int|null $is_deepfry 是否浓煎 0否1是
|
||||
* @property int|null $volume 容量
|
||||
* @property string $gm_id 颗粒药处方的颗粒药表id
|
||||
* @property string $total_price 价格
|
||||
* @property string|null $remark 备注
|
||||
* @property \Illuminate\Support\Carbon $created_at
|
||||
* @property \Illuminate\Support\Carbon $updated_at
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\GranularRecipe newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\GranularRecipe newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\GranularRecipe query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class GranularRecipe extends YiiBaseModel
|
||||
{
|
||||
}
|
||||
35
app/Models/YiiModels/Platform.php
Normal file
35
app/Models/YiiModels/Platform.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\Platform
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $name 平台名称
|
||||
* @property string $token 平台密钥(后期使用)
|
||||
* @property string|null $url 通讯地址
|
||||
* @property string|null $url_new 通讯地址(新服务使用)
|
||||
* @property string $callbackurl
|
||||
* @property int $status 1使用 0不使用
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\Platform newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\Platform newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\Platform query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Platform extends YiiBaseModel
|
||||
{
|
||||
|
||||
// 状态
|
||||
public const STATUS_BLOCK = 0;
|
||||
public const STATUS_PASS = 1;
|
||||
public const STATUS = [
|
||||
self::STATUS_BLOCK => '封禁',
|
||||
self::STATUS_PASS => '正常',
|
||||
];
|
||||
}
|
||||
92
app/Models/YiiModels/Prescription.php
Normal file
92
app/Models/YiiModels/Prescription.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
use App\Models\Extend\SoftDeletesInt;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\Prescription
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $store_id 门店id
|
||||
* @property string $prescription_no 处方编号
|
||||
* @property int $register_id 挂号订单id
|
||||
* @property int $su_id su_id
|
||||
* @property int $user_id 用户id
|
||||
* @property int $up_id 就诊人id
|
||||
* @property int $status 状态 0待审核,1已通过,2未通过
|
||||
* @property int|null $valid_hours
|
||||
* @property int $is_online 1线上 0线下
|
||||
* @property int|null $is_dispense
|
||||
* @property array|null $content 处方快照
|
||||
* @property int $prescription_type 1中药处方 2西药处方 3颗粒药处方
|
||||
* @property int $category 类别 1自费2医保
|
||||
* @property string $doctor_order 医嘱
|
||||
* @property string|null $clinical_diagnose 临床诊断
|
||||
* @property string|null $doctor_sign 医生签名
|
||||
* @property int|null $pharmacist_id
|
||||
* @property int|null $pharmacist_view_time
|
||||
* @property int $first_view 初审药师id
|
||||
* @property string|null $first_sign 初审药师签名
|
||||
* @property int $first_time 初审时间
|
||||
* @property int $again_view 复审药师id
|
||||
* @property string|null $again_sign 复审药师签名
|
||||
* @property int $again_time 复审时间
|
||||
* @property int $type 类型 1普通方 2常用方
|
||||
* @property string $cr_ids 中药药方ids
|
||||
* @property string $gr_ids 颗粒药药方ids
|
||||
* @property string $wr_ids 西药药方ids
|
||||
* @property int $order_type 订单类型1处方2医技
|
||||
* @property string $total_pay_price
|
||||
* @property int $is_pay 是否支付0否1是
|
||||
* @property int $pay_time 支付时间
|
||||
* @property int $pay_type 支付类型 1微信2支付宝3银行卡4其他
|
||||
* @property int $cancel_status 取消状态0否1是
|
||||
* @property int $cancel_time 取消时间
|
||||
* @property string $cancel_remark 取消备注(未支付超时取消,主动取消,拒绝取消)
|
||||
* @property int $refund_status 退款状态
|
||||
* @property int $refund_time
|
||||
* @property int $auto_expire_time
|
||||
* @property \Illuminate\Support\Carbon $created_at
|
||||
* @property \Illuminate\Support\Carbon $updated_at
|
||||
* @property int $is_deleted
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $prescription_type_string 处方类型
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\Prescription newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\Prescription newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\Prescription query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Prescription extends YiiBaseModel
|
||||
{
|
||||
use SoftDeletesInt;
|
||||
|
||||
protected $casts = [
|
||||
'content' => 'array',
|
||||
];
|
||||
|
||||
const DELETED_AT = 'is_deleted';
|
||||
|
||||
// 处方类型
|
||||
const CHINESE_MEDICINES_DECOCTION_PIECE = 1;
|
||||
const WESTERN_ZHONG_CHENG_MEDICINE = 2;
|
||||
const DISPENSING_GRANULES = 3;
|
||||
const PRESCRIPTION_TYPE = [
|
||||
self::CHINESE_MEDICINES_DECOCTION_PIECE => '中药饮片',
|
||||
self::WESTERN_ZHONG_CHENG_MEDICINE => '西(中成)药',
|
||||
self::DISPENSING_GRANULES => '配方颗粒',
|
||||
];
|
||||
|
||||
/**
|
||||
* prescription_type_string
|
||||
*
|
||||
* @comment 处方类型
|
||||
* @return string
|
||||
*/
|
||||
public function getPrescriptionTypeStringAttribute(): string
|
||||
{
|
||||
return self::PRESCRIPTION_TYPE[$this->prescription_type] ?? '';
|
||||
}
|
||||
}
|
||||
494
app/Models/YiiModels/ProductOrder.php
Normal file
494
app/Models/YiiModels/ProductOrder.php
Normal file
@@ -0,0 +1,494 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
use App\Models\ExpressNo;
|
||||
use App\Models\Pay\Bill;
|
||||
use App\Models\Pay\MultiBill;
|
||||
use App\Models\Pay\RefundBill;
|
||||
use App\Models\ProductOrderItem;
|
||||
use Exception;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphOne;
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Yansongda\LaravelPay\Facades\Pay;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\ProductOrder
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $store_id 门店id
|
||||
* @property int|null $drugstore_id 仓库id
|
||||
* @property int $su_id
|
||||
* @property int $user_id 用户id
|
||||
* @property int $up_id 就诊人id
|
||||
* @property string $order_no 订单号
|
||||
* @property int|null $is_online 是否互医订单 1是
|
||||
* @property int|null $online_prescription_status 互医处方状态 1已通过 2已作废
|
||||
* @property string|null $sync_order_no
|
||||
* @property int $p_id 处方id
|
||||
* @property int $order_type 订单类型 1处方订单 2商城订单 2商城处方订单
|
||||
* @property int $type 支付类型 1微信2支付宝3银行卡4其他
|
||||
* @property int $is_pay 是否支付0否1是
|
||||
* @property string $total_pay_price 支付总价
|
||||
* @property string $items_price 商品总价
|
||||
* @property int $pay_time
|
||||
* @property int $address_id
|
||||
* @property string|null $address
|
||||
* @property int $cancel_status
|
||||
* @property int $cancel_time
|
||||
* @property string|null $cancel_remark 取消备注(未支付超时取消,主动取消,拒绝取消)
|
||||
* @property int $refund_status
|
||||
* @property int $refund_time
|
||||
* @property int $received_time
|
||||
* @property int $auto_cancel_time
|
||||
* @property int $status 产品订单状态0未支付1待发货2待收货3待评价4已退款5退款中6已收货7确认收货
|
||||
* @property int $pay_method 支付方式1线上2线下
|
||||
* @property string $trans_expenses 运费(默认包邮)
|
||||
* @property int $free_ship 是否包邮
|
||||
* @property string|null $remark 留言备注
|
||||
* @property string|null $express_name 收货人
|
||||
* @property string|null $express_mobile 收货电话
|
||||
* @property string|null $express_region 收货省市区
|
||||
* @property string|null $express_address 收货地址
|
||||
* @property int|null $express_no_id 快递单信息id
|
||||
* @property \Illuminate\Support\Carbon $created_at
|
||||
* @property \Illuminate\Support\Carbon $updated_at
|
||||
* @property-read \App\Models\Pay\Bill|null $billed 已支付的支付单
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\Pay\Bill[] $bills 支付单
|
||||
* @property-read int|null $bills_count
|
||||
* @property-read \App\Models\ExpressNo|null $expressNo 物流信息
|
||||
* @property-read string $cancel_status_string 取消状态
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $refund_status_string 退款状态
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $type_string 支付类型
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\ProductOrderItem[] $items 订单商品明细
|
||||
* @property-read int|null $items_count
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\YiiModels\ProductOrderLog[] $logs 订单日志
|
||||
* @property-read int|null $logs_count
|
||||
* @property-read \App\Models\YiiModels\Prescription|null $prescription 处方
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\YiiModels\ProductOrderRefund[] $refunds 退款单
|
||||
* @property-read int|null $refunds_count
|
||||
* @property-read \App\Models\YiiModels\Store|null $store 门店
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\ProductOrder newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\ProductOrder newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\ProductOrder query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class ProductOrder extends YiiBaseModel
|
||||
{
|
||||
// 订单类型
|
||||
public const ORDER_TYPE_PRESCRIPTION = 1;
|
||||
public const ORDER_TYPE_SHOP = 2;
|
||||
public const ORDER_TYPE_SHOP_PRESCRIPTION = 3;
|
||||
public const ORDER_TYPE = [
|
||||
self::ORDER_TYPE_PRESCRIPTION => '处方订单',
|
||||
self::ORDER_TYPE_SHOP => '商城订单',
|
||||
self::ORDER_TYPE_SHOP_PRESCRIPTION => '商城处方订单',
|
||||
];
|
||||
|
||||
// 订单类型
|
||||
public const TYPE_WECHAT = 1;
|
||||
public const TYPE_ALIPAY = 2;
|
||||
public const TYPE_BANK = 3;
|
||||
public const TYPE_OTHER = 4;
|
||||
public const TYPE = [
|
||||
self::TYPE_WECHAT => '微信',
|
||||
self::TYPE_ALIPAY => '支付宝',
|
||||
self::TYPE_BANK => '银行卡',
|
||||
self::TYPE_OTHER => '其他',
|
||||
];
|
||||
|
||||
// 是否支付
|
||||
public const IS_PAY_FALSE = 0;
|
||||
public const IS_PAY_TRUE = 1;
|
||||
public const IS_PAY = [
|
||||
self::IS_PAY_FALSE => '否',
|
||||
self::IS_PAY_TRUE => '是',
|
||||
];
|
||||
|
||||
// 是否互医订单
|
||||
public const IS_ONLINE_FALSE = 0;
|
||||
public const IS_ONLINE_TRUE = 1;
|
||||
public const IS_ONLINE = [
|
||||
self::IS_ONLINE_FALSE => '否',
|
||||
self::IS_ONLINE_TRUE => '是',
|
||||
];
|
||||
|
||||
// 订单状态
|
||||
const STATUS_UNPAID = 0;
|
||||
const STATUS_WAIT_SEND = 1;
|
||||
const STATUS_WAIT_ACCEPT = 2;
|
||||
const STATUS_WAIT_COMMENT = 3;
|
||||
const STATUS_REFUND = 4;
|
||||
const STATUS_REFUNDING = 5;
|
||||
const STATUS_ACCEPTED = 6;
|
||||
const STATUS_CONFIRM = 7;
|
||||
const STATUS_CANCEL = 9;
|
||||
const STATUS = [
|
||||
self::STATUS_UNPAID => '未支付',
|
||||
self::STATUS_WAIT_SEND => '待发货',
|
||||
self::STATUS_WAIT_ACCEPT => '待收货',
|
||||
self::STATUS_WAIT_COMMENT => '待评价',
|
||||
self::STATUS_REFUND => '已退款',
|
||||
self::STATUS_REFUNDING => '退款中',
|
||||
self::STATUS_ACCEPTED => '已收货',
|
||||
self::STATUS_CONFIRM => '确认收货',
|
||||
self::STATUS_CANCEL => '已取消',
|
||||
];
|
||||
|
||||
// 取消状态
|
||||
const CANCEL_STATUS_FALSE = 0;
|
||||
const CANCEL_STATUS_TRUE = 1;
|
||||
const CANCEL_STATUS = [
|
||||
self::CANCEL_STATUS_FALSE => '未取消',
|
||||
self::CANCEL_STATUS_TRUE => '已取消',
|
||||
];
|
||||
|
||||
// 退款状态
|
||||
const REFUND_STATUS_NORMAL = 0;
|
||||
const REFUND_STATUS_APPLYING = 1;
|
||||
const REFUND_STATUS_AGREE = 2;
|
||||
const REFUND_STATUS_END = 3;
|
||||
const REFUND_STATUS_PART = 4;
|
||||
const REFUND_STATUS_CANCEL = 9;
|
||||
const REFUND_STATUS = [
|
||||
self::REFUND_STATUS_NORMAL => '正常',
|
||||
self::REFUND_STATUS_APPLYING => '申请中',
|
||||
self::REFUND_STATUS_AGREE => '同意申请',
|
||||
self::REFUND_STATUS_END => '退款完成',
|
||||
self::REFUND_STATUS_PART => '部分退款完成',
|
||||
self::REFUND_STATUS_CANCEL => '取消退款申请',
|
||||
];
|
||||
|
||||
// 支付方式
|
||||
public const PAY_METHOD_ONLINE = 1;
|
||||
public const PAY_METHOD_OFFLINE = 2;
|
||||
public const PAY_METHOD = [
|
||||
self::PAY_METHOD_ONLINE => '线上',
|
||||
self::PAY_METHOD_OFFLINE => '线下',
|
||||
];
|
||||
|
||||
// 支付方式
|
||||
public const FREE_SHIP_FALSE = 0;
|
||||
public const FREE_SHIP_TRUE = 1;
|
||||
public const FREE_SHIP = [
|
||||
self::FREE_SHIP_FALSE => '不包邮',
|
||||
self::FREE_SHIP_TRUE => '包邮',
|
||||
];
|
||||
|
||||
/**
|
||||
* @comment 门店
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function store(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Store::class, 'store_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 订单商品明细
|
||||
* @return HasMany
|
||||
*/
|
||||
public function items(): HasMany
|
||||
{
|
||||
return $this->hasMany(ProductOrderItem::class, 'product_order_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 退款单
|
||||
* @return HasMany
|
||||
*/
|
||||
public function refunds(): HasMany
|
||||
{
|
||||
return $this->hasMany(ProductOrderRefund::class, 'order_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 订单日志
|
||||
* @return HasMany
|
||||
*/
|
||||
public function logs(): HasMany
|
||||
{
|
||||
return $this->hasMany(ProductOrderLog::class, 'p_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 支付单
|
||||
* @return MorphMany
|
||||
*/
|
||||
public function bills(): MorphMany
|
||||
{
|
||||
return $this->morphMany(Bill::class, 'billable');
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 已支付的支付单
|
||||
* @return MorphOne
|
||||
*/
|
||||
public function billed(): MorphOne
|
||||
{
|
||||
return $this->morphOne(Bill::class, 'billable')->where('bill_status', Bill::BILL_STATUS_SUCCESSFUL)->latest();
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 物流信息
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function expressNo(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ExpressNo::class, 'express_no_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 处方
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function prescription(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Prescription::class, 'p_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* status_string
|
||||
*
|
||||
* @comment 状态名称
|
||||
* @return string
|
||||
*/
|
||||
public function getStatusStringAttribute(): string
|
||||
{
|
||||
return self::STATUS[$this['status']] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* type_string
|
||||
*
|
||||
* @comment 支付类型
|
||||
* @return string
|
||||
*/
|
||||
public function getTypeStringAttribute(): string
|
||||
{
|
||||
return self::TYPE[$this->type] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* cancel_status_string
|
||||
*
|
||||
* @comment 取消状态
|
||||
* @return string
|
||||
*/
|
||||
public function getCancelStatusStringAttribute(): string
|
||||
{
|
||||
return self::CANCEL_STATUS[$this->cancel_status] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* refund_status_string
|
||||
*
|
||||
* @comment 退款状态
|
||||
* @return string
|
||||
*/
|
||||
public function getRefundStatusStringAttribute(): string
|
||||
{
|
||||
return self::CANCEL_STATUS[$this->refund_status] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付成功处理
|
||||
*
|
||||
* @param Bill $bill
|
||||
* @return void
|
||||
*/
|
||||
public function handlePied(Bill $bill): void
|
||||
{
|
||||
$this->is_pay = self::IS_PAY_TRUE;
|
||||
$this->pay_time = strtotime($bill->pay_at);
|
||||
$this->status = self::STATUS_WAIT_SEND;
|
||||
$this->save();
|
||||
|
||||
$this->logs()->create([
|
||||
'content' => '订单支付成功 - ' . $this->type_string,
|
||||
]);
|
||||
|
||||
$this->createFundWater($this);
|
||||
|
||||
$this->createNotice($this, '您的订单已支付成功');
|
||||
|
||||
$this->loadMissing(['items.drugStoreRelation' => fn(Relation $relation) => $relation->where('store_id', $this->store_id)]);
|
||||
foreach ($this->items as $item) {
|
||||
if ($item->drugStoreRelation) {
|
||||
$item->drugStoreRelation->true_sales_volume += $item->number;
|
||||
$item->drugStoreRelation->save();
|
||||
}
|
||||
}
|
||||
|
||||
// // 同步数据
|
||||
// $this->refresh();
|
||||
// $this->load(['items']);
|
||||
// Artisan::call('data:sync', [
|
||||
// '--type' => 'product_order_sync',
|
||||
// '--data' => $this->toArray(),
|
||||
// ]);
|
||||
|
||||
if ($this->is_online == self::IS_ONLINE_TRUE && $this->sync_order_no) {
|
||||
// 同步数据(老)
|
||||
Artisan::call('data:sync-old', [
|
||||
'--type' => 'syncOrder',
|
||||
'--data' => json_encode([
|
||||
'order_no' => $this->sync_order_no,
|
||||
'status' => 1, // 1已支付 2已取消 3已退款
|
||||
'time' => $bill->pay_at,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款操作
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function toRefund(int|string|float $refundAmount, $refundNo = null): array
|
||||
{
|
||||
if ($this->is_pay == ProductOrder::IS_PAY_FALSE) {
|
||||
$message = '订单未支付:' . "[productOrderId:$this->id]";
|
||||
log_s($message, 'order', 'refund');
|
||||
return json_result($message, [], 1);
|
||||
}
|
||||
if ($this->cancel_status == ProductOrder::CANCEL_STATUS_TRUE) {
|
||||
$message = '订单已取消:' . "[productOrderId:$this->id]";
|
||||
log_s($message, 'order', 'refund');
|
||||
return json_result($message, [], 1);
|
||||
}
|
||||
if ($this->refund_status == ProductOrder::REFUND_STATUS_PART) {
|
||||
$message = '订单已退款完成:' . "[productOrderId:$this->id]";
|
||||
log_s($message, 'order', 'refund');
|
||||
return json_result($message, [], 1);
|
||||
}
|
||||
if (in_array($this->status, [
|
||||
ProductOrder::STATUS_UNPAID,
|
||||
ProductOrder::STATUS_REFUND,
|
||||
ProductOrder::STATUS_CANCEL,
|
||||
])) {
|
||||
$message = '退款失败,订单状态为:' . $this->status_string . "[productOrderId:$this->id]";
|
||||
log_s($message, 'order', 'refund');
|
||||
return json_result($message, [], 1);
|
||||
}
|
||||
$this->loadMissing('billed');
|
||||
if (!$this->billed) {
|
||||
$message = '退款失败,无已支付的支付单:' . "[productOrderId:$this->id]";
|
||||
log_s($message, 'order', 'refund');
|
||||
return json_result($message, [], 1);
|
||||
}
|
||||
if ($this->billed->can_refund_amount < $refundAmount) {
|
||||
$message = '退款失败,申请金额超过可退金额不足:' . "[productOrderId:$this->id]";
|
||||
log_s($message, 'order', 'refund');
|
||||
return json_result($message, [], 1);
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
$data = [
|
||||
'refund_amount' => $refundAmount,
|
||||
];
|
||||
if ($refundNo) {
|
||||
$data['refund_no'] = $refundNo;
|
||||
}
|
||||
|
||||
/* @var RefundBill $refundBill */
|
||||
$refundBill = $this->billed->refunds()->create($data);
|
||||
$refundNo = $refundBill->refund_no;
|
||||
|
||||
$order = [
|
||||
'out_trade_no' => $this->billed->pay_no,
|
||||
'out_refund_no' => $refundBill->refund_no,
|
||||
'amount' => [
|
||||
'refund' => $refundBill->refund_amount * 100,
|
||||
'total' => $this->billed->pay_amount * 100,
|
||||
'currency' => 'CNY',
|
||||
],
|
||||
];
|
||||
$result = Pay::wechat()->refund($order);
|
||||
if (isset($result['code'])) {
|
||||
$message = '退款失败:' . ($result['message'] ?? '');
|
||||
log_s($message, 'order', 'refund');
|
||||
return json_result($message, [], 1);
|
||||
}
|
||||
|
||||
$this->logs()->create([
|
||||
'content' => "开始退款:{$this->billed->pay_way_string}[$refundBill->refund_amount]"
|
||||
]);
|
||||
|
||||
DB::commit();
|
||||
$message = '退款申请成功:' . var_export($result, true);
|
||||
log_s($message, 'order', 'refund');
|
||||
return json_result('退款申请成功', ['refund_no' => $refundNo]);
|
||||
} catch (Exception $exception) {
|
||||
DB::rollBack();
|
||||
$message = '退款错误:' . "[productOrderId:$this->id]" . $exception->getMessage() . $exception->getTraceAsString();
|
||||
log_s($message, 'order', 'error');
|
||||
return json_result($message, [], 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款成功处理
|
||||
*
|
||||
* @param RefundBill $refundBill
|
||||
* @return void
|
||||
*/
|
||||
public function handleRefunded(RefundBill $refundBill): void
|
||||
{
|
||||
$this->status = self::STATUS_REFUND;
|
||||
$this->refund_status = ProductOrder::REFUND_STATUS_END;
|
||||
$this->save();
|
||||
|
||||
$refund = ProductOrderRefund::where('refund_no', $refundBill->refund_no)->first();
|
||||
$refund->update([
|
||||
'is_refund' => ProductOrderRefund::IS_REFUND_TRUE,
|
||||
'refund_time' => $refundBill->refund_at,
|
||||
'status' => ProductOrderRefund::STATUS_PASS,
|
||||
]);
|
||||
|
||||
$this->logs()->create([
|
||||
'content' => '订单退款成功 - ' . $this->type_string,
|
||||
]);
|
||||
|
||||
$this->createNotice($this, '您的订单已退款成功');
|
||||
|
||||
$this->loadMissing(['items.drugstoreDrug' => fn(Relation $relation) => $relation->where('drugstore_id', $this->drugstore_id)]);
|
||||
foreach ($this->items as $item) {
|
||||
if ($item->drugstoreDrug) {
|
||||
$item->drugstoreDrug->stock += $item->number;
|
||||
$item->drugstoreDrug->frozen_number -= $item->number;
|
||||
$item->drugstoreDrug->save();
|
||||
}
|
||||
}
|
||||
|
||||
// // 同步数据
|
||||
// $this->refresh();
|
||||
// $this->load(['items']);
|
||||
// Artisan::call('data:sync', [
|
||||
// '--type' => 'product_order_sync',
|
||||
// '--data' => $this->toArray(),
|
||||
// ]);
|
||||
|
||||
if ($this->is_online == self::IS_ONLINE_TRUE && $this->sync_order_no) {
|
||||
// 同步数据(老)
|
||||
Artisan::call('data:sync-old', [
|
||||
'--type' => 'syncOrder',
|
||||
'--data' => json_encode([
|
||||
'order_no' => $this->sync_order_no,
|
||||
'status' => 3, // 1已支付 2已取消 3已退款
|
||||
'time' => $refundBill->refund_at,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
24
app/Models/YiiModels/ProductOrderLog.php
Normal file
24
app/Models/YiiModels/ProductOrderLog.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\ProductOrderLog
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $p_id 关联产品订单
|
||||
* @property string $content
|
||||
* @property \Illuminate\Support\Carbon $created_at
|
||||
* @property \Illuminate\Support\Carbon $updated_at
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\ProductOrderLog newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\ProductOrderLog newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\ProductOrderLog query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class ProductOrderLog extends YiiBaseModel
|
||||
{
|
||||
|
||||
}
|
||||
75
app/Models/YiiModels/ProductOrderRefund.php
Normal file
75
app/Models/YiiModels/ProductOrderRefund.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
use App\Models\Extend\SoftDeletesInt;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\ProductOrderRefund
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $user_id 用户id
|
||||
* @property int $order_id 关联产品订单
|
||||
* @property string $reason
|
||||
* @property string|null $remark 备注
|
||||
* @property string|null $refund_images
|
||||
* @property int $refund_type 0仅退款 1退货退款
|
||||
* @property string $refund_no 退款单号
|
||||
* @property string $refund_price 金额
|
||||
* @property int $is_refund 0待退款 1已退款
|
||||
* @property int $refund_time
|
||||
* @property int $status 0退款申请中 1申请通过 2撤销申请
|
||||
* @property \Illuminate\Support\Carbon $created_at
|
||||
* @property \Illuminate\Support\Carbon $updated_at
|
||||
* @property int $is_deleted 1撤销申请
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\ProductOrderRefund newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\ProductOrderRefund newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\ProductOrderRefund query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class ProductOrderRefund extends YiiBaseModel
|
||||
{
|
||||
use SoftDeletesInt;
|
||||
|
||||
const DELETED_AT = 'is_deleted';
|
||||
|
||||
// 原因类型
|
||||
const REASON = [
|
||||
1 => '发错货',
|
||||
2 => '少发/漏发',
|
||||
3 => '拍错了',
|
||||
4 => '商品破损',
|
||||
5 => '不想要了',
|
||||
];
|
||||
|
||||
// 退款类型
|
||||
const REFUND_TYPE_REFUND_ONLY = 0;
|
||||
const REFUND_TYPE_RETURNS_REFUNDS = 1;
|
||||
const REFUND_TYPE = [
|
||||
self::REFUND_TYPE_REFUND_ONLY => '仅退款',
|
||||
self::REFUND_TYPE_RETURNS_REFUNDS => '退货退款',
|
||||
];
|
||||
|
||||
// 退款状态
|
||||
const IS_REFUND_FALSE = 0;
|
||||
const IS_REFUND_TRUE = 1;
|
||||
const IS_REFUND_FAIL = -1;
|
||||
const IS_REFUND = [
|
||||
self::IS_REFUND_FALSE => '待退款',
|
||||
self::IS_REFUND_TRUE => '已退款',
|
||||
self::IS_REFUND_FAIL => '退款失败',
|
||||
];
|
||||
|
||||
// 状态
|
||||
const STATUS_APPLY = 0;
|
||||
const STATUS_PASS = 1;
|
||||
const STATUS_REVOKE = 2;
|
||||
const STATUS = [
|
||||
self::STATUS_APPLY => '退款申请中',
|
||||
self::STATUS_PASS => '申请通过',
|
||||
self::STATUS_REVOKE => '撤销申请',
|
||||
];
|
||||
}
|
||||
37
app/Models/YiiModels/ServiceUser.php
Normal file
37
app/Models/YiiModels/ServiceUser.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
use App\Models\Extend\SoftDeletesInt;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\ServiceUser
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $openid
|
||||
* @property string $session_key
|
||||
* @property string $unionid
|
||||
* @property string $mobile 手机号
|
||||
* @property string $password 密码
|
||||
* @property string $nickname 昵称
|
||||
* @property int $role 角色1医生2药师3导医4客服
|
||||
* @property int $status 状态0待激活1待审核2已认证3拒绝(需要修改激活资料)
|
||||
* @property string|null $reason 拒绝原因
|
||||
* @property int $im_status 客服或者导医的在线状态0下线1上线
|
||||
* @property int $plate_type 平台:1线上2线下
|
||||
* @property \Illuminate\Support\Carbon $created_at
|
||||
* @property \Illuminate\Support\Carbon $updated_at
|
||||
* @property int $is_delete
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\ServiceUser newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\ServiceUser newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\ServiceUser query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class ServiceUser extends YiiBaseAuthModel
|
||||
{
|
||||
use SoftDeletesInt;
|
||||
|
||||
const GUARD = 'service';
|
||||
}
|
||||
36
app/Models/YiiModels/ServiceUserToken.php
Normal file
36
app/Models/YiiModels/ServiceUserToken.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\ServiceUserToken
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $su_id 服务端用户id
|
||||
* @property string $token 用户token
|
||||
* @property int $is_disable 是否禁用,主动退出后=1
|
||||
* @property \Illuminate\Support\Carbon $created_at
|
||||
* @property \Illuminate\Support\Carbon $updated_at
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @property-read \App\Models\YiiModels\ServiceUser|null $serviceUser 用户
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\ServiceUserToken newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\ServiceUserToken newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\ServiceUserToken query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class ServiceUserToken extends YiiBaseAuthModel
|
||||
{
|
||||
public const IS_DISABLE_IS_ABLE = 0;
|
||||
|
||||
/**
|
||||
* @comment 用户
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function serviceUser(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ServiceUser::class, 'su_id');
|
||||
}
|
||||
}
|
||||
62
app/Models/YiiModels/Store.php
Normal file
62
app/Models/YiiModels/Store.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
use App\Models\Extend\SoftDeletesInt;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\Store
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $plate_id 平台id
|
||||
* @property int $drugstore_id 仓库id
|
||||
* @property string $name
|
||||
* @property string $position 位置
|
||||
* @property string|null $pic 图片
|
||||
* @property string $contact 联系人
|
||||
* @property string $mobile 联系电话
|
||||
* @property string|null $qr_code 门店二维码
|
||||
* @property int $start_time 开始营业时间
|
||||
* @property int $end_time 结束营业时间
|
||||
* @property string|null $z_buy_percent 中药采购比例
|
||||
* @property string|null $z_sale_percent 中药销售比例
|
||||
* @property string|null $g_bug_percent 配方颗粒采购比例
|
||||
* @property string|null $g_sale_percent 配方颗粒销售比例
|
||||
* @property \Illuminate\Support\Carbon $created_at
|
||||
* @property \Illuminate\Support\Carbon $updated_at
|
||||
* @property int $is_delete 是否删除0否1是
|
||||
* @property-read \App\Models\YiiModels\Drugstore|null $drugstore 仓库
|
||||
* @property-read \App\Models\YiiModels\DrugstoreDrug|null $drugstoreDrug 库存(单)
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\Store newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\Store newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\Store query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Store extends YiiBaseModel
|
||||
{
|
||||
use SoftDeletesInt;
|
||||
|
||||
/**
|
||||
* @comment 仓库
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function drugstore(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Drugstore::class, 'drugstore_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @comment 库存(单)
|
||||
*
|
||||
* @return HasOne
|
||||
*/
|
||||
public function drugstoreDrug(): HasOne
|
||||
{
|
||||
return $this->hasOne(DrugstoreDrug::class, 'drugstore_id', 'drugstore_id');
|
||||
}
|
||||
}
|
||||
47
app/Models/YiiModels/StoreDoctor.php
Normal file
47
app/Models/YiiModels/StoreDoctor.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
use App\Models\Extend\SoftDeletesInt;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\StoreDoctor
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $store_id 门店id
|
||||
* @property int $su_id 关联服务端用户表su_id
|
||||
* @property int $is_online 是否在该门店0否1是
|
||||
* @property int $last_login_time 最近登录时间
|
||||
* @property \Illuminate\Support\Carbon $created_at
|
||||
* @property \Illuminate\Support\Carbon $updated_at
|
||||
* @property int $is_delete 是否删除0否1是
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @property-read \App\Models\YiiModels\Store|null $store
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\StoreDoctor newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\StoreDoctor newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\StoreDoctor query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class StoreDoctor extends YiiBaseModel
|
||||
{
|
||||
use SoftDeletesInt;
|
||||
|
||||
public const IS_ONLINE_OFFLINE = 0;
|
||||
public const IS_ONLINE_ONLINE = 1;
|
||||
public const IS_ONLINE = [
|
||||
self::IS_ONLINE_OFFLINE => '离线',
|
||||
self::IS_ONLINE_ONLINE => '在线',
|
||||
];
|
||||
|
||||
/**
|
||||
* @comment
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function store(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Store::class, 'store_id');
|
||||
}
|
||||
}
|
||||
110
app/Models/YiiModels/SystemNotice.php
Normal file
110
app/Models/YiiModels/SystemNotice.php
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\SystemNotice
|
||||
*
|
||||
* @property int $id ID
|
||||
* @property int $store_id 门店id
|
||||
* @property string $content 通知内容
|
||||
* @property string|null $url 链接
|
||||
* @property int|null $url_type 链接类型
|
||||
* @property int|null $base_type 通知类型1订单通知2挂号通知3拒诊通知4处方开具消息5处方审核消息 99系统通知
|
||||
* @property int $scene_type 场景类型:1用户端,2服务端(角色)
|
||||
* @property int|null $user_role 通知用户类型
|
||||
* @property int|null $user_id 用户id
|
||||
* @property string|null $notice_at 通知时间
|
||||
* @property int $read_status 是否读取0否1是
|
||||
* @property \Illuminate\Support\Carbon $created_at 创建时间
|
||||
* @property \Illuminate\Support\Carbon $updated_at 更新时间
|
||||
* @property-read string $base_type_string 通知类型
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $read_status_string 通知类型
|
||||
* @property-read string $scene_type_string 场景类型
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\SystemNotice newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\SystemNotice newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\SystemNotice query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class SystemNotice extends YiiBaseModel
|
||||
{
|
||||
protected $attributes = [
|
||||
'read_status' => 0,
|
||||
'user_role' => 0,
|
||||
];
|
||||
|
||||
// 链接类型
|
||||
const URL_TYPE = [];
|
||||
|
||||
// 通知类型
|
||||
const BASE_TYPE_ORDER = 1;
|
||||
const BASE_TYPE_REGISTER = 2;
|
||||
const BASE_TYPE_REFUSAL = 3;
|
||||
const BASE_TYPE_PRESCRIPTION_ISSUANCE = 4;
|
||||
const BASE_TYPE_PRESCRIPTION_AUDIT = 5;
|
||||
const BASE_TYPE_SYSTEM = 99;
|
||||
|
||||
const BASE_TYPE = [
|
||||
self::BASE_TYPE_ORDER => '订单通知',
|
||||
self::BASE_TYPE_REGISTER => '挂号通知',
|
||||
self::BASE_TYPE_REFUSAL => '拒诊通知',
|
||||
self::BASE_TYPE_PRESCRIPTION_ISSUANCE => '处方开具消息',
|
||||
self::BASE_TYPE_PRESCRIPTION_AUDIT => '处方审核消息',
|
||||
self::BASE_TYPE_SYSTEM => '系统通知',
|
||||
];
|
||||
|
||||
// 场景类型
|
||||
const SCENE_TYPE_MEMBER = 1;
|
||||
const SCENE_TYPE_SERVICE = 2;
|
||||
const SCENE_TYPE = [
|
||||
self::SCENE_TYPE_MEMBER => '用户端',
|
||||
self::SCENE_TYPE_SERVICE => '服务端(角色)',
|
||||
];
|
||||
|
||||
// 通知用户类型
|
||||
const USER_ROLE = [];
|
||||
|
||||
// 是否读取
|
||||
const READ_STATUS_FALSE = 0;
|
||||
const READ_STATUS_TRUE = 1;
|
||||
const READ_STATUS = [
|
||||
self::READ_STATUS_FALSE => '未读',
|
||||
self::READ_STATUS_TRUE => '已读',
|
||||
];
|
||||
|
||||
/**
|
||||
* base_type_string
|
||||
*
|
||||
* @comment 通知类型
|
||||
* @return string
|
||||
*/
|
||||
public function getBaseTypeStringAttribute(): string
|
||||
{
|
||||
return self::BASE_TYPE[$this->base_type];
|
||||
}
|
||||
|
||||
/**
|
||||
* scene_type_string
|
||||
*
|
||||
* @comment 场景类型
|
||||
* @return string
|
||||
*/
|
||||
public function getSceneTypeStringAttribute(): string
|
||||
{
|
||||
return self::SCENE_TYPE[$this->scene_type];
|
||||
}
|
||||
|
||||
/**
|
||||
* read_status_string
|
||||
*
|
||||
* @comment 通知类型
|
||||
* @return string
|
||||
*/
|
||||
public function getReadStatusStringAttribute(): string
|
||||
{
|
||||
return self::READ_STATUS[$this->read_status];
|
||||
}
|
||||
}
|
||||
55
app/Models/YiiModels/User.php
Normal file
55
app/Models/YiiModels/User.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
use App\Models\Cart;
|
||||
use App\Models\Extend\SoftDeletesInt;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\User
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $openid
|
||||
* @property string $session_key
|
||||
* @property string $unionid
|
||||
* @property string $mobile 手机号
|
||||
* @property string $password 密码
|
||||
* @property string $nickname 昵称
|
||||
* @property int $gender 性别,值为1时是男性,值为2时是女性,值为0时是未知
|
||||
* @property string $country 国家
|
||||
* @property string $province 省份
|
||||
* @property string $city 城市
|
||||
* @property string $avatarurl 头像
|
||||
* @property string $token
|
||||
* @property string $idcard 身份证号
|
||||
* @property int $sex 性别0默认1男2女
|
||||
* @property int|null $age 年龄
|
||||
* @property int $status 身份状态 0待激活待完善,1待审核,2已认证,3已拒绝
|
||||
* @property \Illuminate\Support\Carbon $created_at
|
||||
* @property \Illuminate\Support\Carbon $updated_at
|
||||
* @property int $is_delete 是否删除0否
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\Cart[] $carts 购物车
|
||||
* @property-read int|null $carts_count
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\User newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\User newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\User query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class User extends YiiBaseAuthModel
|
||||
{
|
||||
use SoftDeletesInt;
|
||||
|
||||
const GUARD = 'member';
|
||||
|
||||
/**
|
||||
* @comment 购物车
|
||||
* @return HasMany
|
||||
*/
|
||||
public function carts(): HasMany
|
||||
{
|
||||
return $this->hasMany(Cart::class, 'user_id');
|
||||
}
|
||||
}
|
||||
31
app/Models/YiiModels/WestRecipe.php
Normal file
31
app/Models/YiiModels/WestRecipe.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\WestRecipe
|
||||
*
|
||||
* @property int $id
|
||||
* @property string|null $content
|
||||
* @property int $number 药品数量
|
||||
* @property string|null $instruction 说明书
|
||||
* @property int|null $time_id
|
||||
* @property int $type_id
|
||||
* @property int $grain_number 每天几粒
|
||||
* @property int $wu_id 西药单位id
|
||||
* @property int $available_days 可用天数
|
||||
* @property int $f_id 频率id
|
||||
* @property string $total_price 价格
|
||||
* @property \Illuminate\Support\Carbon $created_at
|
||||
* @property \Illuminate\Support\Carbon $updated_at 价格
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\WestRecipe newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\WestRecipe newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\WestRecipe query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class WestRecipe extends YiiBaseModel
|
||||
{
|
||||
}
|
||||
22
app/Models/YiiModels/WestUnit.php
Normal file
22
app/Models/YiiModels/WestUnit.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\WestUnit
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property \Illuminate\Support\Carbon $created_at
|
||||
* @property \Illuminate\Support\Carbon $updated_at
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\WestUnit newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\WestUnit newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\WestUnit query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class WestUnit extends YiiBaseModel
|
||||
{
|
||||
}
|
||||
26
app/Models/YiiModels/YiiBaseAuthModel.php
Normal file
26
app/Models/YiiModels/YiiBaseAuthModel.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
use App\Models\BaseAuthModel;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\YiiBaseAuthModel
|
||||
*
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\YiiBaseAuthModel newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\YiiBaseAuthModel newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\YiiBaseAuthModel query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class YiiBaseAuthModel extends BaseAuthModel
|
||||
{
|
||||
protected $dateFormat = 'U';
|
||||
|
||||
public function getTable(): string
|
||||
{
|
||||
return $this->table ?? Str::snake(class_basename($this));
|
||||
}
|
||||
}
|
||||
27
app/Models/YiiModels/YiiBaseModel.php
Normal file
27
app/Models/YiiModels/YiiBaseModel.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\YiiModels;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* App\Models\YiiModels\YiiBaseModel
|
||||
*
|
||||
* @property-read string $created_at_format 创建时间的格式化
|
||||
* @property-read string $status_string 状态名称
|
||||
* @property-read string $updated_at_format 更新时间的格式化
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\YiiBaseModel newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\YiiBaseModel newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\YiiModels\YiiBaseModel query()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class YiiBaseModel extends BaseModel
|
||||
{
|
||||
protected $dateFormat = 'U';
|
||||
|
||||
public function getTable(): string
|
||||
{
|
||||
return $this->table ?? Str::snake(class_basename($this));
|
||||
}
|
||||
}
|
||||
28
app/Providers/AppServiceProvider.php
Normal file
28
app/Providers/AppServiceProvider.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
}
|
||||
}
|
||||
28
app/Providers/AuthServiceProvider.php
Normal file
28
app/Providers/AuthServiceProvider.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
// use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
||||
|
||||
class AuthServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* The model to policy mappings for the application.
|
||||
*
|
||||
* @var array<class-string, class-string>
|
||||
*/
|
||||
protected $policies = [
|
||||
// 'App\Models\Model' => 'App\Policies\ModelPolicy',
|
||||
];
|
||||
|
||||
/**
|
||||
* Register any authentication / authorization services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$this->registerPolicies();
|
||||
}
|
||||
}
|
||||
21
app/Providers/BroadcastServiceProvider.php
Normal file
21
app/Providers/BroadcastServiceProvider.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\Facades\Broadcast;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class BroadcastServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Bootstrap any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
Broadcast::routes();
|
||||
|
||||
require base_path('routes/channels.php');
|
||||
}
|
||||
}
|
||||
41
app/Providers/EventServiceProvider.php
Normal file
41
app/Providers/EventServiceProvider.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Auth\Events\Registered;
|
||||
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
|
||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
|
||||
class EventServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* The event to listener mappings for the application.
|
||||
*
|
||||
* @var array<class-string, array<int, class-string>>
|
||||
*/
|
||||
protected $listen = [
|
||||
Registered::class => [
|
||||
SendEmailVerificationNotification::class,
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Register any events for your application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if events and listeners should be automatically discovered.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function shouldDiscoverEvents()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
62
app/Providers/RouteServiceProvider.php
Normal file
62
app/Providers/RouteServiceProvider.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Cache\RateLimiting\Limit;
|
||||
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\RateLimiter;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
class RouteServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* The path to the "home" route for your application.
|
||||
*
|
||||
* Typically, users are redirected here after authentication.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const HOME = '/home';
|
||||
|
||||
/**
|
||||
* Define your route model bindings, pattern filters, and other route configuration.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$this->configureRateLimiting();
|
||||
|
||||
$this->routes(function () {
|
||||
// 用户端
|
||||
Route::middleware('api')
|
||||
->prefix('member')
|
||||
->group(base_path('routes/member.php'));
|
||||
|
||||
// 服务端
|
||||
Route::middleware('api')
|
||||
->prefix('service')
|
||||
->group(base_path('routes/service.php'));
|
||||
|
||||
// Route::middleware('api')
|
||||
// ->prefix('api')
|
||||
// ->group(base_path('routes/api.php'));
|
||||
|
||||
Route::middleware('web')
|
||||
->group(base_path('routes/web.php'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the rate limiters for the application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function configureRateLimiting()
|
||||
{
|
||||
RateLimiter::for('api', function (Request $request) {
|
||||
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
|
||||
});
|
||||
}
|
||||
}
|
||||
53
artisan
Normal file
53
artisan
Normal file
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
define('LARAVEL_START', microtime(true));
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Register The Auto Loader
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Composer provides a convenient, automatically generated class loader
|
||||
| for our application. We just need to utilize it! We'll require it
|
||||
| into the script here so that we do not have to worry about the
|
||||
| loading of any of our classes manually. It's great to relax.
|
||||
|
|
||||
*/
|
||||
|
||||
require __DIR__.'/vendor/autoload.php';
|
||||
|
||||
$app = require_once __DIR__.'/bootstrap/app.php';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Run The Artisan Application
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When we run the console application, the current CLI command will be
|
||||
| executed in this console and the response sent back to a terminal
|
||||
| or another output device for the developers. Here goes nothing!
|
||||
|
|
||||
*/
|
||||
|
||||
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
|
||||
|
||||
$status = $kernel->handle(
|
||||
$input = new Symfony\Component\Console\Input\ArgvInput,
|
||||
new Symfony\Component\Console\Output\ConsoleOutput
|
||||
);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Shutdown The Application
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Once Artisan has finished running, we will fire off the shutdown events
|
||||
| so that any final work may be done by the application before we shut
|
||||
| down the process. This is the last thing to happen to the request.
|
||||
|
|
||||
*/
|
||||
|
||||
$kernel->terminate($input, $status);
|
||||
|
||||
exit($status);
|
||||
55
bootstrap/app.php
Normal file
55
bootstrap/app.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Create The Application
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The first thing we will do is create a new Laravel application instance
|
||||
| which serves as the "glue" for all the components of Laravel, and is
|
||||
| the IoC container for the system binding all of the various parts.
|
||||
|
|
||||
*/
|
||||
|
||||
$app = new Illuminate\Foundation\Application(
|
||||
$_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
|
||||
);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Bind Important Interfaces
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Next, we need to bind some important interfaces into the container so
|
||||
| we will be able to resolve them when needed. The kernels serve the
|
||||
| incoming requests to this application from both the web and CLI.
|
||||
|
|
||||
*/
|
||||
|
||||
$app->singleton(
|
||||
Illuminate\Contracts\Http\Kernel::class,
|
||||
App\Http\Kernel::class
|
||||
);
|
||||
|
||||
$app->singleton(
|
||||
Illuminate\Contracts\Console\Kernel::class,
|
||||
App\Console\Kernel::class
|
||||
);
|
||||
|
||||
$app->singleton(
|
||||
Illuminate\Contracts\Debug\ExceptionHandler::class,
|
||||
App\Exceptions\Handler::class
|
||||
);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Return The Application
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This script returns the application instance. The instance is given to
|
||||
| the calling script so we can separate the building of the instances
|
||||
| from the actual running of the application and sending responses.
|
||||
|
|
||||
*/
|
||||
|
||||
return $app;
|
||||
2
bootstrap/cache/.gitignore
vendored
Normal file
2
bootstrap/cache/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
||||
195
bootstrap/helpers.php
Normal file
195
bootstrap/helpers.php
Normal file
@@ -0,0 +1,195 @@
|
||||
<?php
|
||||
|
||||
if (!function_exists('is_wechat')) {
|
||||
/**
|
||||
* 判断是否是微信访问.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function is_wechat(): bool
|
||||
{
|
||||
return str_contains(\Jenssegers\Agent\Facades\Agent::getUserAgent(), 'MicroMessenger');
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('is_mobile')) {
|
||||
/**
|
||||
* 是否手机
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function is_mobile(): bool
|
||||
{
|
||||
$agent = new Jenssegers\Agent\Agent();
|
||||
|
||||
return $agent->isMobile();
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('json_success')) {
|
||||
/**
|
||||
* 成功
|
||||
*
|
||||
* @param mixed $message
|
||||
* @param mixed $data
|
||||
* @return void
|
||||
*/
|
||||
function json_success(mixed $message = '', mixed $data = []): void
|
||||
{
|
||||
if (is_string($message)) {
|
||||
$result = [
|
||||
'msg' => $message,
|
||||
'data' => $data,
|
||||
];
|
||||
} else {
|
||||
$result = [
|
||||
'msg' => '',
|
||||
'data' => $message,
|
||||
];
|
||||
}
|
||||
$result['code'] = 0;
|
||||
response()->json($result)->throwResponse();
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('json_page')) {
|
||||
/**
|
||||
* 分页
|
||||
*
|
||||
* @param $data
|
||||
* @param mixed $pageData
|
||||
* @param mixed $message
|
||||
* @return void
|
||||
*/
|
||||
function json_page($data, mixed $pageData = [], mixed $message = ''): void
|
||||
{
|
||||
$pageData['total'] = method_exists($data, 'total') ? $data->total() : null;
|
||||
$pageData['count'] = $data->count();
|
||||
$pageData['page'] = $data->currentPage();
|
||||
$pageData['per_page'] = $data->perPage();
|
||||
$pageData['last'] = method_exists($data, 'lastPage') ? $data->lastPage() : null;
|
||||
json_success($message, [
|
||||
'page_info' => $pageData,
|
||||
'page_data' => $data->toArray()['data'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('json_error')) {
|
||||
/**
|
||||
* 失败
|
||||
*
|
||||
* @param mixed $message
|
||||
* @param mixed $data
|
||||
* @param int $code
|
||||
* @return void
|
||||
*/
|
||||
function json_error(mixed $message = '', mixed $data = [], int $code = 1): void
|
||||
{
|
||||
$result = [
|
||||
'code' => $code,
|
||||
'msg' => $message,
|
||||
'data' => $data,
|
||||
];
|
||||
response()->json($result)->throwResponse();
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('json_guest')) {
|
||||
/**
|
||||
* 失败 - 未登录
|
||||
*
|
||||
* @param mixed $message
|
||||
* @param int $code
|
||||
* @return void
|
||||
*/
|
||||
function json_guest(mixed $message = '未登录,请先登录', int $code = 99): void
|
||||
{
|
||||
json_error($message, [], $code);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('json_result')) {
|
||||
/**
|
||||
* 结果
|
||||
*
|
||||
* @param mixed $message
|
||||
* @param mixed $data
|
||||
* @param int $code
|
||||
* @return array
|
||||
*/
|
||||
function json_result(mixed $message = '', mixed $data = [], int $code = 0): array
|
||||
{
|
||||
return [
|
||||
'code' => $code,
|
||||
'msg' => $message,
|
||||
'data' => $data,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('url_to_uri')) {
|
||||
/**
|
||||
* 网址去除域名段 获取 url
|
||||
*
|
||||
* @param $url
|
||||
* @return string|null
|
||||
*/
|
||||
function url_to_uri($url): ?string
|
||||
{
|
||||
if (!$url) {
|
||||
return null;
|
||||
}
|
||||
$arr = parse_url($url);
|
||||
if (isset($arr['scheme']) && isset($arr['host'])) {
|
||||
$domains = [config('filesystems.disks.' . config('filesystems.default') . '.domain')];
|
||||
$domain = $arr['scheme'] . '://' . $arr['host'];
|
||||
if (in_array($domain, $domains)) {
|
||||
$url = str_replace($arr['scheme'] . '://' . $arr['host'], '', $url);
|
||||
$url = preg_replace('/!.*/', '', $url);
|
||||
}
|
||||
} elseif (!str_starts_with($url, '/')) {
|
||||
$url = '/' . $url;
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('uri_to_image_url')) {
|
||||
/**
|
||||
* 还原图片网址
|
||||
*
|
||||
* @param $uri
|
||||
* @return string|null
|
||||
*/
|
||||
function uri_to_image_url($uri): ?string
|
||||
{
|
||||
if (!$uri) {
|
||||
return null;
|
||||
}
|
||||
return config('filesystems.disks.' . config('filesystems.default') . '.domain') . url_to_uri($uri);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('string_to_array')) {
|
||||
/**
|
||||
* 字符串转数组(针对非0传值场景)
|
||||
*
|
||||
* @param mixed $string 原始字符串
|
||||
* @param bool $sort 是否重新排序
|
||||
* @param string $separator 切割字符
|
||||
* @return array
|
||||
*/
|
||||
function string_to_array(mixed $string, bool $sort = false, string $separator = ','): array
|
||||
{
|
||||
$arr = explode($separator, $string);
|
||||
foreach ($arr as &$value) {
|
||||
$value = trim($value);
|
||||
}
|
||||
$arr = array_filter($arr);
|
||||
if ($sort) {
|
||||
sort($arr);
|
||||
}
|
||||
return $arr;
|
||||
}
|
||||
}
|
||||
88
composer.json
Normal file
88
composer.json
Normal file
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"name": "laravel/laravel",
|
||||
"type": "project",
|
||||
"description": "The Laravel Framework.",
|
||||
"keywords": [
|
||||
"framework",
|
||||
"laravel"
|
||||
],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^8.0.2",
|
||||
"asundust/laravel-helpers": "^9.0",
|
||||
"dcat/laravel-wherehasin": "^0.8.0",
|
||||
"guzzlehttp/guzzle": "^7.2",
|
||||
"jenssegers/agent": "^2.6",
|
||||
"laravel/framework": "^9.19",
|
||||
"laravel/sanctum": "^3.0",
|
||||
"laravel/tinker": "^2.7",
|
||||
"overtrue/laravel-wechat": "^7.0",
|
||||
"phpoffice/phpspreadsheet": "^1.28",
|
||||
"tudouer/express": "^1.0",
|
||||
"yansongda/laravel-pay": "^3.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"barryvdh/laravel-ide-helper": "^2.12",
|
||||
"beyondcode/laravel-dump-server": "^1.8",
|
||||
"beyondcode/laravel-query-detector": "^1.6",
|
||||
"fakerphp/faker": "^1.9.1",
|
||||
"kitloong/laravel-migrations-generator": "^6.8",
|
||||
"laravel-lang/common": "^3.1",
|
||||
"laravel/pint": "^1.0",
|
||||
"laravel/sail": "^1.0.1",
|
||||
"mnabialek/laravel-sql-logger": "^2.2",
|
||||
"mockery/mockery": "^1.4.4",
|
||||
"nunomaduro/collision": "^6.1",
|
||||
"phpunit/phpunit": "^9.5.10",
|
||||
"spatie/laravel-ignition": "^1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"App\\": "app/",
|
||||
"Database\\Factories\\": "database/factories/",
|
||||
"Database\\Seeders\\": "database/seeders/"
|
||||
},
|
||||
"files": [
|
||||
"bootstrap/helpers.php"
|
||||
]
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"post-autoload-dump": [
|
||||
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
|
||||
"@php artisan package:discover --ansi"
|
||||
],
|
||||
"post-update-cmd": [
|
||||
"@php artisan vendor:publish --tag=laravel-assets --ansi --force",
|
||||
"Illuminate\\Foundation\\ComposerScripts::postUpdate",
|
||||
"@php artisan ide-helper:generate",
|
||||
"@php artisan ide-helper:meta"
|
||||
],
|
||||
"post-root-package-install": [
|
||||
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
|
||||
],
|
||||
"post-create-project-cmd": [
|
||||
"@php artisan key:generate --ansi"
|
||||
]
|
||||
},
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"dont-discover": []
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"preferred-install": "dist",
|
||||
"sort-packages": true,
|
||||
"allow-plugins": {
|
||||
"pestphp/pest-plugin": true,
|
||||
"easywechat-composer/easywechat-composer": true
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true
|
||||
}
|
||||
12631
composer.lock
generated
Normal file
12631
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
213
config/app.php
Normal file
213
config/app.php
Normal file
@@ -0,0 +1,213 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Facade;
|
||||
|
||||
return [
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value is the name of your application. This value is used when the
|
||||
| framework needs to place the application's name in a notification or
|
||||
| any other location as required by the application or its packages.
|
||||
|
|
||||
*/
|
||||
|
||||
'name' => env('APP_NAME', 'Laravel'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Environment
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value determines the "environment" your application is currently
|
||||
| running in. This may determine how you prefer to configure various
|
||||
| services the application utilizes. Set this in your ".env" file.
|
||||
|
|
||||
*/
|
||||
|
||||
'env' => env('APP_ENV', 'production'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Debug Mode
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When your application is in debug mode, detailed error messages with
|
||||
| stack traces will be shown on every error that occurs within your
|
||||
| application. If disabled, a simple generic error page is shown.
|
||||
|
|
||||
*/
|
||||
|
||||
'debug' => (bool) env('APP_DEBUG', false),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application URL
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This URL is used by the console to properly generate URLs when using
|
||||
| the Artisan command line tool. You should set this to the root of
|
||||
| your application so that it is used when running Artisan tasks.
|
||||
|
|
||||
*/
|
||||
|
||||
'url' => env('APP_URL', 'http://localhost'),
|
||||
|
||||
'asset_url' => env('ASSET_URL'),
|
||||
|
||||
'beian' => env('APP_BEIAN', ''),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Timezone
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the default timezone for your application, which
|
||||
| will be used by the PHP date and date-time functions. We have gone
|
||||
| ahead and set this to a sensible default for you out of the box.
|
||||
|
|
||||
*/
|
||||
|
||||
'timezone' => 'Asia/Shanghai',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Locale Configuration
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The application locale determines the default locale that will be used
|
||||
| by the translation service provider. You are free to set this value
|
||||
| to any of the locales which will be supported by the application.
|
||||
|
|
||||
*/
|
||||
|
||||
'locale' => 'zh_CN',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Fallback Locale
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The fallback locale determines the locale to use when the current one
|
||||
| is not available. You may change the value to correspond to any of
|
||||
| the language folders that are provided through your application.
|
||||
|
|
||||
*/
|
||||
|
||||
'fallback_locale' => 'en',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Faker Locale
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This locale will be used by the Faker PHP library when generating fake
|
||||
| data for your database seeds. For example, this will be used to get
|
||||
| localized telephone numbers, street address information and more.
|
||||
|
|
||||
*/
|
||||
|
||||
'faker_locale' => 'en_US',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Encryption Key
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This key is used by the Illuminate encrypter service and should be set
|
||||
| to a random, 32 character string, otherwise these encrypted strings
|
||||
| will not be safe. Please do this before deploying an application!
|
||||
|
|
||||
*/
|
||||
|
||||
'key' => env('APP_KEY'),
|
||||
|
||||
'cipher' => 'AES-256-CBC',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Maintenance Mode Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| These configuration options determine the driver used to determine and
|
||||
| manage Laravel's "maintenance mode" status. The "cache" driver will
|
||||
| allow maintenance mode to be controlled across multiple machines.
|
||||
|
|
||||
| Supported drivers: "file", "cache"
|
||||
|
|
||||
*/
|
||||
|
||||
'maintenance' => [
|
||||
'driver' => 'file',
|
||||
// 'store' => 'redis',
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Autoloaded Service Providers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The service providers listed here will be automatically loaded on the
|
||||
| request to your application. Feel free to add your own services to
|
||||
| this array to grant expanded functionality to your applications.
|
||||
|
|
||||
*/
|
||||
|
||||
'providers' => [
|
||||
/*
|
||||
* Laravel Framework Service Providers...
|
||||
*/
|
||||
Illuminate\Auth\AuthServiceProvider::class,
|
||||
Illuminate\Broadcasting\BroadcastServiceProvider::class,
|
||||
Illuminate\Bus\BusServiceProvider::class,
|
||||
Illuminate\Cache\CacheServiceProvider::class,
|
||||
Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
|
||||
Illuminate\Cookie\CookieServiceProvider::class,
|
||||
Illuminate\Database\DatabaseServiceProvider::class,
|
||||
Illuminate\Encryption\EncryptionServiceProvider::class,
|
||||
Illuminate\Filesystem\FilesystemServiceProvider::class,
|
||||
Illuminate\Foundation\Providers\FoundationServiceProvider::class,
|
||||
Illuminate\Hashing\HashServiceProvider::class,
|
||||
Illuminate\Mail\MailServiceProvider::class,
|
||||
Illuminate\Notifications\NotificationServiceProvider::class,
|
||||
Illuminate\Pagination\PaginationServiceProvider::class,
|
||||
Illuminate\Pipeline\PipelineServiceProvider::class,
|
||||
Illuminate\Queue\QueueServiceProvider::class,
|
||||
Illuminate\Redis\RedisServiceProvider::class,
|
||||
Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
|
||||
Illuminate\Session\SessionServiceProvider::class,
|
||||
Illuminate\Translation\TranslationServiceProvider::class,
|
||||
Illuminate\Validation\ValidationServiceProvider::class,
|
||||
Illuminate\View\ViewServiceProvider::class,
|
||||
|
||||
/*
|
||||
* Package Service Providers...
|
||||
*/
|
||||
|
||||
/*
|
||||
* Application Service Providers...
|
||||
*/
|
||||
App\Providers\AppServiceProvider::class,
|
||||
App\Providers\AuthServiceProvider::class,
|
||||
// App\Providers\BroadcastServiceProvider::class,
|
||||
App\Providers\EventServiceProvider::class,
|
||||
App\Providers\RouteServiceProvider::class,
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Class Aliases
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This array of class aliases will be registered when this application
|
||||
| is started. However, feel free to register as many as you wish as
|
||||
| the aliases are "lazy" loaded so they don't hinder performance.
|
||||
|
|
||||
*/
|
||||
|
||||
'aliases' => Facade::defaultAliases()->merge([
|
||||
// 'ExampleClass' => App\Example\ExampleClass::class,
|
||||
])->toArray(),
|
||||
];
|
||||
129
config/auth.php
Normal file
129
config/auth.php
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Authentication Defaults
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default authentication "guard" and password
|
||||
| reset options for your application. You may change these defaults
|
||||
| as required, but they're a perfect start for most applications.
|
||||
|
|
||||
*/
|
||||
|
||||
'defaults' => [
|
||||
'guard' => 'web',
|
||||
'passwords' => 'users',
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Authentication Guards
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Next, you may define every authentication guard for your application.
|
||||
| Of course, a great default configuration has been defined for you
|
||||
| here which uses session storage and the Eloquent user provider.
|
||||
|
|
||||
| All authentication drivers have a user provider. This defines how the
|
||||
| users are actually retrieved out of your database or other storage
|
||||
| mechanisms used by this application to persist your user's data.
|
||||
|
|
||||
| Supported: "session"
|
||||
|
|
||||
*/
|
||||
|
||||
'guards' => [
|
||||
'member' => [
|
||||
'driver' => 'session',
|
||||
'provider' => 'member_users',
|
||||
],
|
||||
|
||||
'service' => [
|
||||
'driver' => 'session',
|
||||
'provider' => 'service_users',
|
||||
],
|
||||
|
||||
'web' => [
|
||||
'driver' => 'session',
|
||||
'provider' => 'users',
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| User Providers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| All authentication drivers have a user provider. This defines how the
|
||||
| users are actually retrieved out of your database or other storage
|
||||
| mechanisms used by this application to persist your user's data.
|
||||
|
|
||||
| If you have multiple user tables or models you may configure multiple
|
||||
| sources which represent each model / table. These sources may then
|
||||
| be assigned to any extra authentication guards you have defined.
|
||||
|
|
||||
| Supported: "database", "eloquent"
|
||||
|
|
||||
*/
|
||||
|
||||
'providers' => [
|
||||
'member_users' => [
|
||||
'driver' => 'eloquent',
|
||||
'model' => \App\Models\YiiModels\User::class,
|
||||
],
|
||||
|
||||
'service_users' => [
|
||||
'driver' => 'eloquent',
|
||||
'model' => \App\Models\YiiModels\ServiceUser::class,
|
||||
],
|
||||
|
||||
'users' => [
|
||||
'driver' => 'eloquent',
|
||||
'model' => App\Models\User::class,
|
||||
],
|
||||
|
||||
// 'users' => [
|
||||
// 'driver' => 'database',
|
||||
// 'table' => 'users',
|
||||
// ],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Resetting Passwords
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| You may specify multiple password reset configurations if you have more
|
||||
| than one user table or model in the application and you want to have
|
||||
| separate password reset settings based on the specific user types.
|
||||
|
|
||||
| The expire time is the number of minutes that each reset token will be
|
||||
| considered valid. This security feature keeps tokens short-lived so
|
||||
| they have less time to be guessed. You may change this as needed.
|
||||
|
|
||||
*/
|
||||
|
||||
'passwords' => [
|
||||
'users' => [
|
||||
'provider' => 'users',
|
||||
'table' => 'password_resets',
|
||||
'expire' => 60,
|
||||
'throttle' => 60,
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Password Confirmation Timeout
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may define the amount of seconds before a password confirmation
|
||||
| times out and the user is prompted to re-enter their password via the
|
||||
| confirmation screen. By default, the timeout lasts for three hours.
|
||||
|
|
||||
*/
|
||||
|
||||
'password_timeout' => 10800,
|
||||
];
|
||||
66
config/broadcasting.php
Normal file
66
config/broadcasting.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Broadcaster
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default broadcaster that will be used by the
|
||||
| framework when an event needs to be broadcast. You may set this to
|
||||
| any of the connections defined in the "connections" array below.
|
||||
|
|
||||
| Supported: "pusher", "ably", "redis", "log", "null"
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('BROADCAST_DRIVER', 'null'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Broadcast Connections
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may define all of the broadcast connections that will be used
|
||||
| to broadcast events to other systems or over websockets. Samples of
|
||||
| each available type of connection are provided inside this array.
|
||||
|
|
||||
*/
|
||||
|
||||
'connections' => [
|
||||
'pusher' => [
|
||||
'driver' => 'pusher',
|
||||
'key' => env('PUSHER_APP_KEY'),
|
||||
'secret' => env('PUSHER_APP_SECRET'),
|
||||
'app_id' => env('PUSHER_APP_ID'),
|
||||
'options' => [
|
||||
'host' => env('PUSHER_HOST') ?: 'api-' . env('PUSHER_APP_CLUSTER', 'mt1') . '.pusher.com',
|
||||
'port' => env('PUSHER_PORT', 443),
|
||||
'scheme' => env('PUSHER_SCHEME', 'https'),
|
||||
'encrypted' => true,
|
||||
'useTLS' => 'https' === env('PUSHER_SCHEME', 'https'),
|
||||
],
|
||||
'client_options' => [
|
||||
// Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html
|
||||
],
|
||||
],
|
||||
|
||||
'ably' => [
|
||||
'driver' => 'ably',
|
||||
'key' => env('ABLY_KEY'),
|
||||
],
|
||||
|
||||
'redis' => [
|
||||
'driver' => 'redis',
|
||||
'connection' => 'default',
|
||||
],
|
||||
|
||||
'log' => [
|
||||
'driver' => 'log',
|
||||
],
|
||||
|
||||
'null' => [
|
||||
'driver' => 'null',
|
||||
],
|
||||
],
|
||||
];
|
||||
106
config/cache.php
Normal file
106
config/cache.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
return [
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Cache Store
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default cache connection that gets used while
|
||||
| using this caching library. This connection is used when another is
|
||||
| not explicitly specified when executing a given caching function.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('CACHE_DRIVER', 'file'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cache Stores
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may define all of the cache "stores" for your application as
|
||||
| well as their drivers. You may even define multiple stores for the
|
||||
| same cache driver to group types of items stored in your caches.
|
||||
|
|
||||
| Supported drivers: "apc", "array", "database", "file",
|
||||
| "memcached", "redis", "dynamodb", "octane", "null"
|
||||
|
|
||||
*/
|
||||
|
||||
'stores' => [
|
||||
'apc' => [
|
||||
'driver' => 'apc',
|
||||
],
|
||||
|
||||
'array' => [
|
||||
'driver' => 'array',
|
||||
'serialize' => false,
|
||||
],
|
||||
|
||||
'database' => [
|
||||
'driver' => 'database',
|
||||
'table' => 'cache',
|
||||
'connection' => null,
|
||||
'lock_connection' => null,
|
||||
],
|
||||
|
||||
'file' => [
|
||||
'driver' => 'file',
|
||||
'path' => storage_path('framework/cache/data'),
|
||||
],
|
||||
|
||||
'memcached' => [
|
||||
'driver' => 'memcached',
|
||||
'persistent_id' => env('MEMCACHED_PERSISTENT_ID'),
|
||||
'sasl' => [
|
||||
env('MEMCACHED_USERNAME'),
|
||||
env('MEMCACHED_PASSWORD'),
|
||||
],
|
||||
'options' => [
|
||||
// Memcached::OPT_CONNECT_TIMEOUT => 2000,
|
||||
],
|
||||
'servers' => [
|
||||
[
|
||||
'host' => env('MEMCACHED_HOST', '127.0.0.1'),
|
||||
'port' => env('MEMCACHED_PORT', 11211),
|
||||
'weight' => 100,
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
'redis' => [
|
||||
'driver' => 'redis',
|
||||
'connection' => 'cache',
|
||||
'lock_connection' => 'default',
|
||||
],
|
||||
|
||||
'dynamodb' => [
|
||||
'driver' => 'dynamodb',
|
||||
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
||||
'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),
|
||||
'endpoint' => env('DYNAMODB_ENDPOINT'),
|
||||
],
|
||||
|
||||
'octane' => [
|
||||
'driver' => 'octane',
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cache Key Prefix
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When utilizing the APC, database, memcached, Redis, or DynamoDB cache
|
||||
| stores there might be other applications using the same cache. For
|
||||
| that reason, you may prefix every cache key to avoid collisions.
|
||||
|
|
||||
*/
|
||||
|
||||
'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_') . '_cache_'),
|
||||
];
|
||||
37
config/cors.php
Normal file
37
config/cors.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cross-Origin Resource Sharing (CORS) Configuration
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure your settings for cross-origin resource sharing
|
||||
| or "CORS". This determines what cross-origin operations may execute
|
||||
| in web browsers. You are free to adjust these settings as needed.
|
||||
|
|
||||
| To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
||||
|
|
||||
*/
|
||||
|
||||
'paths' => [
|
||||
'api/*',
|
||||
'member/*',
|
||||
'service/*',
|
||||
'sanctum/csrf-cookie',
|
||||
],
|
||||
|
||||
'allowed_methods' => ['*'],
|
||||
|
||||
'allowed_origins' => ['*'],
|
||||
|
||||
'allowed_origins_patterns' => [],
|
||||
|
||||
'allowed_headers' => ['*'],
|
||||
|
||||
'exposed_headers' => [],
|
||||
|
||||
'max_age' => 0,
|
||||
|
||||
'supports_credentials' => false,
|
||||
];
|
||||
145
config/database.php
Normal file
145
config/database.php
Normal file
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
return [
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Database Connection Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify which of the database connections below you wish
|
||||
| to use as your default connection for all database work. Of course
|
||||
| you may use many connections at once using the Database library.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('DB_CONNECTION', 'mysql'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Database Connections
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here are each of the database connections setup for your application.
|
||||
| Of course, examples of configuring each database platform that is
|
||||
| supported by Laravel is shown below to make development simple.
|
||||
|
|
||||
|
|
||||
| All database work in Laravel is done through the PHP PDO facilities
|
||||
| so make sure you have the driver for your particular database of
|
||||
| choice installed on your machine before you begin development.
|
||||
|
|
||||
*/
|
||||
|
||||
'connections' => [
|
||||
'sqlite' => [
|
||||
'driver' => 'sqlite',
|
||||
'url' => env('DATABASE_URL'),
|
||||
'database' => env('DB_DATABASE', database_path('database.sqlite')),
|
||||
'prefix' => '',
|
||||
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
|
||||
],
|
||||
|
||||
'mysql' => [
|
||||
'driver' => 'mysql',
|
||||
'url' => env('DATABASE_URL'),
|
||||
'host' => env('DB_HOST', '127.0.0.1'),
|
||||
'port' => env('DB_PORT', '3306'),
|
||||
'database' => env('DB_DATABASE', 'forge'),
|
||||
'username' => env('DB_USERNAME', 'forge'),
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'unix_socket' => env('DB_SOCKET', ''),
|
||||
'charset' => 'utf8mb4',
|
||||
'collation' => 'utf8mb4_unicode_ci',
|
||||
'prefix' => env('DB_PREFIX', ''),
|
||||
'prefix_indexes' => true,
|
||||
'strict' => false,
|
||||
'engine' => null,
|
||||
'options' => extension_loaded('pdo_mysql') ? array_filter([
|
||||
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
|
||||
]) : [],
|
||||
],
|
||||
|
||||
'pgsql' => [
|
||||
'driver' => 'pgsql',
|
||||
'url' => env('DATABASE_URL'),
|
||||
'host' => env('DB_HOST', '127.0.0.1'),
|
||||
'port' => env('DB_PORT', '5432'),
|
||||
'database' => env('DB_DATABASE', 'forge'),
|
||||
'username' => env('DB_USERNAME', 'forge'),
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'charset' => 'utf8',
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
'search_path' => 'public',
|
||||
'sslmode' => 'prefer',
|
||||
],
|
||||
|
||||
'sqlsrv' => [
|
||||
'driver' => 'sqlsrv',
|
||||
'url' => env('DATABASE_URL'),
|
||||
'host' => env('DB_HOST', 'localhost'),
|
||||
'port' => env('DB_PORT', '1433'),
|
||||
'database' => env('DB_DATABASE', 'forge'),
|
||||
'username' => env('DB_USERNAME', 'forge'),
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'charset' => 'utf8',
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
// 'encrypt' => env('DB_ENCRYPT', 'yes'),
|
||||
// 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'),
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Migration Repository Table
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This table keeps track of all the migrations that have already run for
|
||||
| your application. Using this information, we can determine which of
|
||||
| the migrations on disk haven't actually been run in the database.
|
||||
|
|
||||
*/
|
||||
|
||||
'migrations' => 'migrations',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Redis Databases
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Redis is an open source, fast, and advanced key-value store that also
|
||||
| provides a richer body of commands than a typical key-value system
|
||||
| such as APC or Memcached. Laravel makes it easy to dig right in.
|
||||
|
|
||||
*/
|
||||
|
||||
'redis' => [
|
||||
'client' => env('REDIS_CLIENT', 'phpredis'),
|
||||
|
||||
'options' => [
|
||||
'cluster' => env('REDIS_CLUSTER', 'redis'),
|
||||
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_') . '_database_'),
|
||||
],
|
||||
|
||||
'default' => [
|
||||
'url' => env('REDIS_URL'),
|
||||
'host' => env('REDIS_HOST', '127.0.0.1'),
|
||||
'username' => env('REDIS_USERNAME'),
|
||||
'password' => env('REDIS_PASSWORD'),
|
||||
'port' => env('REDIS_PORT', '6379'),
|
||||
'database' => env('REDIS_DB', '1'),
|
||||
],
|
||||
|
||||
'cache' => [
|
||||
'url' => env('REDIS_URL'),
|
||||
'host' => env('REDIS_HOST', '127.0.0.1'),
|
||||
'username' => env('REDIS_USERNAME'),
|
||||
'password' => env('REDIS_PASSWORD'),
|
||||
'port' => env('REDIS_PORT', '6379'),
|
||||
'database' => env('REDIS_CACHE_DB', '1'),
|
||||
],
|
||||
],
|
||||
];
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user