Compare commits

...

8 Commits

28 changed files with 3877 additions and 3292 deletions

View File

@ -26,15 +26,15 @@ class ConstFlowController extends AdminController
])
->filter(
$this->baseFilter()->body([
amisMake()->TextControl('name', '')->size('md'),
amisMake()->TextControl('name', '名')->size('md'),
amisMake()->TextControl('card_no', '身份证')->size('md'),
amisMake()->TextControl('sn', '单据编号')->size('md'),
amisMake()->TextControl('idsn', '单据编号')->size('md'),
amis('button')->label(__('admin.reset'))->actionType('clear-and-submit'),
amis('submit')->label(__('admin.search'))->level('primary'),
])->actions([])
)
->columns([
amisMake()->TableColumn('sn', '单据编号')->copyable(true),
amisMake()->TableColumn('idsn', '单据编号')->copyable(true),
amisMake()->TableColumn('oldman.name', '客人'),
amisMake()->TableColumn('const_type', '缴费类型')->type('mapping')->map(ConstFlow::typeMapLabel())->className('text-primary'),
amisMake()->TableColumn('money', '金额'),

View File

@ -24,7 +24,7 @@ class LiveContinueController extends AdminController
])
->filter(
$this->baseFilter()->body([
amisMake()->TextControl('name', '')->size('md'),
amisMake()->TextControl('name', '名')->size('md'),
amisMake()->TextControl('card_no', '身份证')->size('md'),
amisMake()->TextControl('floor_name', '楼栋')->size('md'),
amisMake()->SelectControl('nurse_lv', '护理等级')->options(Keyword::getByParentKey('nurse_lv')->pluck('name', 'value'))->checkAll(true)->multiple(true)->size('md'),
@ -64,13 +64,18 @@ class LiveContinueController extends AdminController
$feeKeys['del_extends'] = '${del_extends}';
$feeKeys['continue_fee'] = '${continue_fee}';
foreach(Keyword::getByParentKey('continue_fee') as $fee){
$continueArr[] = Components::make()->decimalControl('continue_fee['.$fee->key.']', $fee->name)->description(amis('tpl')->tpl('根据当前护理等级,建议费用为:${'.$fee->key.'_tmp}'));
// $feeKeys[$fee->key.'_tmp'] = '${'.$fee->key.'_tmp}';
}
$page = $this->basePage()->body([
amisMake()->Card()->className('border-0')->body(
amisMake()->Wrapper()->className('p-0')->body(
amisMake()->Grid()->className('relative')->columns([
amisMake()->Wrapper()->sm(8)->body([
amisMake()->Panel()->title('续住表单')->body(
amisMake()->form()->title('')->panelClassName('border-0')->mode('horizontal')->name('base_form')
amisMake()->form()->title('')->panelClassName('border-0')->mode('horizontal')->name('base_form')->preventEnterSubmit(true)
->api(admin_url('live-continue-do'))
->body([
amisMake()->FieldSetControl()->title('续住人信息')->collapsable(true)->body([
@ -144,10 +149,16 @@ class LiveContinueController extends AdminController
amisMake()->FieldSetControl()->className('mt-10')->title('费用明细')->collapsable(true)->body([
amisMake()->FieldSetControl()->title('基础费用')->className('mt-5')->collapsable(true)->size('base')->body(
amisMake()->Service()->schemaApi([
amisMake()->Service()
// ->schemaApi([
// "method"=>'get',
// "url" => admin_url('live-fee-form').'?nurse_lv=${nurse_lv}&start_at=${start_at}&end_at=${end_at}&type=continue_fee',
// ])
->api([
"method"=>'get',
"url" => admin_url('live-fee-form').'?nurse_lv=${nurse_lv}&start_at=${start_at}&end_at=${end_at}&type=continue_fee',
"url" => admin_url('live-fee-form-data').'?nurse_lv=${nurse_lv}&start_at=${start_at}&end_at=${end_at}&type=continue_fee',
])
->body($continueArr),
),
]),

View File

@ -36,7 +36,7 @@ class LiveExitController extends AdminController
amisMake()->Grid()->className('relative')->columns([
amisMake()->Wrapper()->sm(8)->body([
amisMake()->Panel()->title('结算表单')->body(
amisMake()->form()->title('')->panelClassName('border-0')->mode('horizontal')->name('base_form')
amisMake()->form()->title('')->panelClassName('border-0')->mode('horizontal')->name('base_form')->preventEnterSubmit(true)
->api(admin_url('live-exit-do'))
->body([
amisMake()->FieldSetControl()->title('客人信息')->collapsable(true)->body([

View File

@ -24,7 +24,7 @@ class LiveInController extends AdminController
])
->filter(
$this->baseFilter()->body([
amisMake()->TextControl('name', '')->size('md'),
amisMake()->TextControl('name', '名')->size('md'),
amisMake()->TextControl('card_no', '身份证')->size('md'),
amisMake()->TextControl('floor_name', '楼栋')->size('md'),
amisMake()->SelectControl('nurse_lv', '护理等级')->options(Keyword::getByParentKey('nurse_lv')->pluck('name', 'value'))->checkAll(true)->multiple(true)->size('md'),
@ -66,19 +66,20 @@ class LiveInController extends AdminController
$feeKeys['live_fee'] = '${live_fee}';
$feeKeys['bonds_fee'] = '${bonds_fee}';
// foreach(Keyword::getByParentKey('live_fee') as $fee){
// $feeKeys[$fee->key] = '${'.$fee->key.'}';
// }
// foreach(Keyword::getByParentKey('bonds_fee') as $fee){
// $feeKeys[$fee->key] = '${'.$fee->key.'}';
// }
foreach(Keyword::getByParentKey('live_fee') as $fee){
$liveArr[] = Components::make()->decimalControl('live_fee['.$fee->key.']', $fee->name)->description(amis('tpl')->tpl('根据当前护理等级,建议费用为:${'.$fee->key.'_tmp}'));
// $feeKeys[$fee->key.'_tmp'] = '${'.$fee->key.'_tmp}';
}
foreach(Keyword::getByParentKey('bonds_fee') as $fee){
$bondsArr[] = Components::make()->decimalControl('bonds_fee['.$fee->key.']', $fee->name)->description(amis('tpl')->tpl('根据当前护理等级,建议费用为:${'.$fee->key.'_tmp}'));
}
$page = $this->basePage()->body([
amisMake()->Card()->className('border-0')->body(
amisMake()->Wrapper()->className('p-0')->body(
amisMake()->Grid()->className('relative')->columns([
amisMake()->Wrapper()->sm(8)->body([
amisMake()->Panel()->title('入住表单')->body(
amisMake()->form()->title('')->panelClassName('border-0')->mode('horizontal')->name('base_form')
amisMake()->form()->title('')->panelClassName('border-0')->mode('horizontal')->name('base_form')->preventEnterSubmit(true)
->api(admin_url('live-in-do'))
->body([
amisMake()->FieldSetControl()->title('入住人信息')->collapsable(true)->body([
@ -147,16 +148,28 @@ class LiveInController extends AdminController
amisMake()->FieldSetControl()->className('mt-10')->title('费用明细')->collapsable(true)->body([
amisMake()->FieldSetControl()->title('基础费用')->className('mt-5')->collapsable(true)->size('base')->body(
amisMake()->Service()->schemaApi([
amisMake()->Service()
// ->schemaApi([
// "method"=>'get',
// "url" => admin_url('live-fee-form').'?nurse_lv=${nurse_lv}&live_in_date=${live_in_date}&type=live_fee',
// ])
->api([
"method"=>'get',
"url" => admin_url('live-fee-form').'?nurse_lv=${nurse_lv}&live_in_date=${live_in_date}&type=live_fee',
"url" => admin_url('live-fee-form-data').'?nurse_lv=${nurse_lv}&live_in_date=${live_in_date}&type=live_fee',
])
->body($liveArr),
),
amisMake()->FieldSetControl()->title('保证金')->className('mt-5')->collapsable(true)->size('base')->body(
amisMake()->Service()->schemaApi([
amisMake()->Service()
// ->schemaApi([
// "method"=>'get',
// "url" => admin_url('live-fee-form').'?nurse_lv=${nurse_lv}&live_in_date=${live_in_date}&type=bonds_fee',
// ])
->api([
"method"=>'get',
"url" => admin_url('live-fee-form').'?nurse_lv=${nurse_lv}&live_in_date=${live_in_date}&type=bonds_fee',
"url" => admin_url('live-fee-form-data').'?nurse_lv=${nurse_lv}&live_in_date=${live_in_date}&type=bonds_fee',
])
->body($bondsArr),
),
]),

View File

@ -7,7 +7,6 @@ use Slowlyo\OwlAdmin\Models\AdminSetting;
use Slowlyo\OwlAdmin\Renderers\Page;
use Slowlyo\OwlAdmin\Renderers\Form;
use Slowlyo\OwlAdmin\Renderers\TableColumn;
use Slowlyo\OwlAdmin\Renderers\TextControl;
use Slowlyo\OwlAdmin\Controllers\AdminController;
use App\Services\Admin\OldmenService;
use Illuminate\Http\Request;
@ -15,6 +14,9 @@ use App\Admin\Components;
use App\Models\ConstFlow;
use App\Models\Oldmen;
use Carbon\Carbon;
use App\Services\Admin\ImportService;
use App\Models\ImportJob;
use App\Imports\Oldmen as OldmenImport;
/**
* @property OldmenService $service
@ -37,10 +39,20 @@ class OldmenController extends AdminController
->filterTogglable(false)
->headerToolbar([
$this->createButton(true, 'lg'),
amisMake()->DialogAction()->dialog(
amisMake()->Dialog()->title('导入客人信息')->body([
amisMake()->Form()->title('')
->api(admin_url('oldmen-import'))//处理实际上传逻辑
->body([
amisMake()->FileControl('file', '导入文件')->accept('.xlsx')->receiver('/upload_file'),//文件上传地址待处理
]),
])->size('md')
)->label('导入')->icon('fa fa-upload')->level('light'),
amisMake()->Button()->actionType('saveAs')->label('下载导入模板')->api('../tmp/客人信息导入模板.xlsx'),
])
->filter(
$this->baseFilter()->body([
amisMake()->TextControl('name', '名称')->size('md'),
amisMake()->TextControl('name', '名')->size('md'),
amisMake()->TextControl('card_no', '身份证')->size('md'),
amisMake()->TextControl('floor_name', '楼栋')->size('md'),
amisMake()->SelectControl('nurse_lv', '护理等级')->options(Keyword::getByParentKey('nurse_lv')->pluck('name', 'value'))->checkAll(true)->multiple(true)->size('md'),
@ -92,7 +104,7 @@ class OldmenController extends AdminController
->body([
amisMake()->FieldSetControl()->title('居住人信息')->collapsable(true)->body([
amisMake()->GroupControl()->body([
amisMake()->TextControl('name', ''),
amisMake()->TextControl('name', '名'),
amisMake()->RadiosControl('sex', '性别')->options([
1=>'男',2=>'女'
]),
@ -124,7 +136,7 @@ class OldmenController extends AdminController
]),
amisMake()->FieldSetControl()->title('委托人信息')->className('mt-10')->collapsable(true)->body([
amisMake()->GroupControl()->body([
amisMake()->TextControl('client_name', ''),
amisMake()->TextControl('client_name', '名'),
amisMake()->TextControl('client_phone', '手机号'),
]),
amisMake()->GroupControl()->body([
@ -264,7 +276,7 @@ class OldmenController extends AdminController
}
/**
* 费用表单
* 推荐费用表单
*
*/
public function liveSchemaForm(Request $request)
@ -276,16 +288,19 @@ class OldmenController extends AdminController
$endDay = $dateRange ? explode(',', $dateRange)[1].' 23:59:59' : $request->input('end_at', null);
if($startDay && $endDay){
$diffYears = Carbon::parse($startDay)->diffInYears($endDay);
$diffMonths = Carbon::parse($startDay)->addYears($diffYears)->diffInMonths($endDay);
$diffAbMonths = Carbon::parse($startDay)->diffInMonths($endDay);
$diffDays = Carbon::parse($startDay)->addYears($diffYears)->addMonths($diffMonths)->diffInDays($endDay);
$diffAbDays = Carbon::parse($startDay)->diffInDays($endDay);
$startDay = Carbon::parse($startDay);
$endDay = Carbon::parse($endDay)->addSecond(1);
$diffYears = $startDay->diffInYears($endDay);
$diffMonths = $startDay->addYears($diffYears)->diffInMonths($endDay);
$diffAbMonths = $startDay->diffInMonths($endDay);
$diffDays = $startDay->addYears($diffYears)->addMonths($diffMonths)->diffInDays($endDay);
$diffAbDays = $startDay->diffInDays($endDay);
}
$lv = $request->input('nurse_lv', 1);
$feeKey = Keyword::getByParentKey($type);
$feeKeyHelp = AdminSetting::whereIn('key', $feeKey?->pluck('key')->toArray())->pluck('values','key')->toArray();
$feeData = $feeArr = [];
foreach(Keyword::getByParentKey($type) as $fee)
{
$_feeValue = 0;
@ -297,6 +312,7 @@ class OldmenController extends AdminController
}, $feeKeyHelp[$fee->key]['values']);
if(isset($_feeValues[$lv]['day'])){
//判断是否有设置年份
if(isset($_feeValues[$lv]['year'])){
$_feeValue += bcmul($diffYears, $_feeValues[$lv]['year'], 2);
@ -309,6 +325,7 @@ class OldmenController extends AdminController
}else{
if(isset($_feeValues[$lv]['month'])){
$_feeValue += bcmul($diffAbMonths, $_feeValues[$lv]['month'], 2);
$_feeValue += bcmul($diffDays, $_feeValues[$lv]['day'], 2);
}else{
$_feeValue += bcmul($diffAbDays, $_feeValues[$lv]['day'], 2);
}
@ -322,6 +339,78 @@ class OldmenController extends AdminController
$feeArr[] = Components::make()->decimalControl($type.'['.$fee->key.']', $fee->name)->description(amis('tpl')->tpl('根据当前护理等级,建议费用为:'.$_feeValue));
}
$resData['body'] = $feeArr;
return $this->response()->success($resData);
}
/**
* 推荐费用表单
*
*/
public function liveSchemaFormData(Request $request)
{
$type = $request->input('type', 'live_fee');
$dateRange = $request->input('live_in_date', null);
//处理续住时间传递
$startDay = $dateRange ? explode(',', $dateRange)[0] : $request->input('start_at', null);
$endDay = $dateRange ? explode(',', $dateRange)[1] : $request->input('end_at', null);
if($startDay && $endDay){
$startDay = Carbon::parse($startDay.' 00:00:00');
$endDay = Carbon::parse($endDay.' 23:59:59')->addSecond(1);
$diffYears = $startDay->diffInYears($endDay);
$diffMonths = $startDay->addYears($diffYears)->diffInMonths($endDay);
$diffAbMonths = $startDay->diffInMonths($endDay);
$diffDays = $startDay->addYears($diffYears)->addMonths($diffMonths)->diffInDays($endDay);
$diffAbDays = $startDay->diffInDays($endDay);
}
$lv = $request->input('nurse_lv', 1);
$feeKey = Keyword::getByParentKey($type);
$feeKeyHelp = AdminSetting::whereIn('key', $feeKey?->pluck('key')->toArray())->pluck('values','key')->toArray();
$feeData = $feeArr = [];
foreach(Keyword::getByParentKey($type) as $fee)
{
$_feeValue = 0;
if(isset($feeKeyHelp[$fee->key])){
$_feeValues = [];
if($feeKeyHelp[$fee->key]['has_time'] == 2 && !empty($startDay) && !empty($endDay)){
array_map(function($item) use(&$_feeValues){
$_feeValues[$item['lv']][$item['time_type']] = $item['fee'];
}, $feeKeyHelp[$fee->key]['values']);
if(isset($_feeValues[$lv]['day'])){
//判断是否有设置年份
if(isset($_feeValues[$lv]['year'])){
$_feeValue += bcmul($diffYears, $_feeValues[$lv]['year'], 2);
if(isset($_feeValues[$lv]['month'])){
$_feeValue += bcmul($diffMonths, $_feeValues[$lv]['month'], 2);
$_feeValue += bcmul($diffDays, $_feeValues[$lv]['day'], 2);
}else{
$_feeValue += bcmul($diffAbDays, $_feeValues[$lv]['day'], 2);
}
}else{
if(isset($_feeValues[$lv]['month'])){
$_feeValue += bcmul($diffAbMonths, $_feeValues[$lv]['month'], 2);
$_feeValue += bcmul($diffDays, $_feeValues[$lv]['day'], 2);
}else{
$_feeValue += bcmul($diffAbDays, $_feeValues[$lv]['day'], 2);
}
}
}
}else{
$_feeValues = collect($feeKeyHelp[$fee->key]['values'] ?? [])->keyBy('lv')->toArray();
$_feeValue = $_feeValues[$lv]['fee'] ?? 0;
}
}
$feeArr[$type][$fee->key] = $_feeValue;
$feeArr[$fee->key.'_tmp'] = $_feeValue;
}
return $this->response()->success($feeArr);
}
@ -337,7 +426,7 @@ class OldmenController extends AdminController
->whereIn('const_type', [ConstFlow::TYPE_IN, ConstFlow::TYPE_CONTINUE])
->where('state', 0)
->whereBetween('start_at', [$oldMan->live_in_at, $oldMan->avliable_at])//开始时间在用户这段时间内的清单
->get();
->orderBy('created_at', 'desc')->limit(3)->get();//调整为最近3条
$tableList = [];
foreach($flowList as $flow){
$_feeInfo = $_bonusInfo = $_addInfo = $_delInfo = '';
@ -415,4 +504,19 @@ class OldmenController extends AdminController
}
return $this->response()->success($page);
}
public function import(Request $request){
$job = new ImportJob();
$job->name = '客人基础信息导入【'.now()->toDateTimeString().'】';
$job->file = $request->input('file');
$job->type = OldmenImport::class;
$job->status = 1;
$job->save();
$importService = new ImportService();
$importService->import($job);
return $this->response()->success();
}
}

View File

@ -25,9 +25,12 @@ Route::group([
//客人管理
$router->resource('oldmen', \App\Admin\Controllers\OldmenController::class)->names('oldmen');
$router->post('oldmen-import', '\App\Admin\Controllers\OldmenController@import');
$router->get('live-feelist', '\App\Admin\Controllers\OldmenController@liveFeelist');
$router->get('exit-feelist', '\App\Admin\Controllers\OldmenController@exitFeelist');
$router->get('live-fee-form', '\App\Admin\Controllers\OldmenController@liveSchemaForm');
$router->get('live-fee-form-data', '\App\Admin\Controllers\OldmenController@liveSchemaFormData');
$router->get('live-const-flow', '\App\Admin\Controllers\OldmenController@liveConstFlow');
//客人-入住
$router->get('live-in', '\App\Admin\Controllers\LiveInController@index');

View File

@ -14,8 +14,8 @@ class Kernel extends ConsoleKernel
{
// $schedule->command('inspire')->hourly();
$schedule->command('app:verify-need-pay-continue')->dailyAt('00:01');//更新续费列表
$schedule->command('app:verify-need-pay-arrear')->dailyAt('01:01');//更新欠费状态
$schedule->command('app:verify-need-pay-continue')->dailyAt('12:01');//更新续费列表
$schedule->command('app:verify-need-pay-arrear')->dailyAt('13:01');//更新欠费状态
}
/**

View File

@ -0,0 +1,37 @@
<?php
namespace App\Exceptions;
use Exception;
class BizException extends Exception
{
/**
* 用于响应的 HTTP 状态代码
*
* @var int
*/
public $status = 400;
/**
* 设置用于响应的 HTTP 状态代码
*
* @param int $status
* @return $this
*/
public function status(int $status)
{
$this->status = $status;
return $this;
}
/**
* 报告异常
*
* @return mixed
*/
public function report()
{
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace App\Exceptions;
class ImportException extends BizException
{
public function __construct(string $message = '导入出错')
{
parent::__construct($message);
}
}

View File

@ -17,6 +17,11 @@ class ConstFlowFilter extends ModelFilter
return $this->where('sn', $sn);
}
public function idsn($idsn){
$id = 0+$idsn;
return $this->where('id', $id);
}
/**
* 名称
*/

View File

@ -26,7 +26,7 @@ class PrintController extends Controller
$flow->load(['oldman', 'adminuser']);
$name = $flow->oldman->name;
$time = $flow->created_at->format('Y-m-d H:i:s');
$sn = $flow->sn;
$idsn = $flow->idsn;
$ukeys = explode(',', $request->input('ukeys', ''));
$i = 0;
foreach($rows as $item){
@ -61,7 +61,7 @@ class PrintController extends Controller
$timeZone = substr($flow->start_at, 0, 10).'至'.substr($flow->end_at, 0, 10);
}
return view('print-const', compact('name', 'time', 'sn', 'list', 'total', 'bigTotal', 'timeZone', 'adminName'));
return view('print-const', compact('name', 'time', 'idsn', 'list', 'total', 'bigTotal', 'timeZone', 'adminName'));
}

View File

@ -0,0 +1,75 @@
<?php
namespace App\Imports;
use App\Exceptions\ImportException;
use Box\Spout\Reader\Common\Creator\ReaderEntityFactory;
use Illuminate\Http\File;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Throwable;
class ImportBase
{
public function readFileByUrl($url)
{
$file_name = substr($url, strrpos($url, '/') + 1);
$path = DIRECTORY_SEPARATOR.'import'.DIRECTORY_SEPARATOR.date('Y-m-d').DIRECTORY_SEPARATOR.'import'.$file_name;
Storage::disk('local')->put($path, file_get_contents(str_replace(config('filesystems.disks.aliyun.domain'), config('filesystems.disks.aliyun.bucket').'.'.config('filesystems.disks.aliyun.endpoint'), $url)));
$file = new File(storage_path('app'.$path));
return $this->readFile($file);
}
public function readFile($file)
{
$reader = ReaderEntityFactory::createXLSXReader();
$reader->open($file);
$success = 0;
$fails = 0;
$errors = [];
foreach ($reader->getSheetIterator() as $sheet) {
foreach ($sheet->getRowIterator() as $num => $row) {
if ($num === 1) {
continue;
}
try {
DB::beginTransaction();
$this->loadRow($row);
$success++;
DB::commit();
} catch (ImportException $e) {
DB::rollBack();
$fails++;
$errors[] = [
'row'=>$num,
'reason'=>$e->getMessage(),
];
} catch (Throwable $e) {
DB::rollBack();
$fails++;
$errors[] = [
'row'=>$num,
'reason'=>$e->getMessage(),
];
}
}
break;
}
$reader->close();
return [
'success'=>$success,
'fails'=>$fails,
'errors'=>$errors,
];
}
public function loadRow($row)
{
return;
}
}

View File

@ -0,0 +1,60 @@
<?php
namespace App\Imports;
use App\Exceptions\ImportException;
use App\Models\Keyword;
use App\Models\Oldmen as ModelsOldmen;
use App\Models\Zone;
use Carbon\Carbon;
class Oldmen extends ImportBase
{
public function loadRow($row)
{
$cardNo = $row->getCellAtIndex(0)?->getValue() ?? throw new ImportException('未填写身份证号码');//身份证号
$name = $row->getCellAtIndex(1)?->getValue() ?? throw new ImportException('未填写姓名');//姓名
$sex = $row->getCellAtIndex(2)?->getValue() ?? throw new ImportException('未填写性别');//性别
$birthDate = $row->getCellAtIndex(3)?->getValue() ?? throw new ImportException('未填写生日');//生日
$cardCity = $row->getCellAtIndex(4)?->getValue() ?? throw new ImportException('未填写地址省份');//省
$cardProvince = $row->getCellAtIndex(5)?->getValue() ?? throw new ImportException('未填写地址-市');//市
$cardArea = $row->getCellAtIndex(6)?->getValue() ?? throw new ImportException('未填写地址-区');//区
$cardAddress = $row->getCellAtIndex(7)?->getValue() ?? throw new ImportException('未填写详细地址');//详细地址
$agreementNo = $row->getCellAtIndex(8)?->getValue() ?? '';//协议号码
$nurseLvName = $row->getCellAtIndex(9)?->getValue() ?? throw new ImportException('未填写护理等级');//护理等级
$clientName = $row->getCellAtIndex(10)?->getValue() ?? throw new ImportException('未填写监护人姓名');//监护人姓名
$clientPhone = $row->getCellAtIndex(11)?->getValue() ?? throw new ImportException('未填写监护人手机号码');//监护人手机号
$clientCity = $row->getCellAtIndex(12)?->getValue() ?? throw new ImportException('未填写监护人地址省份');
$clientProvince = $row->getCellAtIndex(13)?->getValue() ?? throw new ImportException('未填写监护人地址-市');//市
$clientArea = $row->getCellAtIndex(14)?->getValue() ?? throw new ImportException('未填写监护人地址-区');//区
$clientAddress = $row->getCellAtIndex(15)?->getValue() ?? throw new ImportException('未填写监护人详细地址');//详细地址
if(ModelsOldmen::where('card_no', $cardNo)->exists()){//如果已存在,则为更新
$oldman = ModelsOldmen::where('card_no', $cardNo)->first();
$newLv = Keyword::where(['type_key'=>'nurse_lv', 'name'=>$nurseLvName])->value('value');
if($oldman->nurse_lv !== $newLv && $oldman->live_in > 0){
throw new ImportException('当前入住状态无法直接变更护理等级');
}K;
}else{
$oldman = new ModelsOldmen();
$oldman->card_no = $cardNo;
$oldman->nurse_lv = Keyword::where(['type_key'=>'nurse_lv', 'name'=>$nurseLvName])->value('value');
}
$oldman->name = $name;
$sexArr = [
'未知'=>0,
'男'=>1,
'女'=>2
];
$oldman->sex = $sexArr[$sex];
$oldman->birthday = Carbon::parse($birthDate);
$oldman->card_city_code = Zone::where(['name' => $cardArea, 'type'=>'area'])->value('code') ?? '';
$oldman->card_address = $cardAddress;
$oldman->agreement_no = $agreementNo;
$oldman->client_name = $clientName;
$oldman->client_phone = $clientPhone;
$oldman->client_city_code = Zone::where(['name' => $clientArea, 'type'=>'area'])->value('code') ?? '';
$oldman->client_address = $clientAddress;
$oldman->save();
}
}

View File

@ -0,0 +1,41 @@
<?php
namespace App\Jobs;
use App\Models\ImportJob as ImportJobModel;
use Illuminate\Bus\Queueable;
use App\Admin\Services\ImportService;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
class ImportJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $importJob;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct(ImportJobModel $job)
{
//
$this->importJob = $job;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
if(env('APP_DEBUG')){
\Log::info('执行文件导入');
}
(new ImportService())->import($this->importJob);
}
}

View File

@ -6,6 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use EloquentFilter\Filterable;
use Slowlyo\OwlAdmin\Models\AdminUser;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Casts\Attribute;
class ConstFlow extends Model
{
@ -34,6 +35,8 @@ class ConstFlow extends Model
];
}
protected $appends = ['idsn'];
protected $casts = [
'extends' => 'array',
];
@ -53,6 +56,13 @@ class ConstFlow extends Model
});
}
public function idsn():Attribute
{
return Attribute::make(
get: fn($value) => str_pad($this->id, 6, '0',STR_PAD_LEFT),
);
}
public function oldman(){
return $this->belongsTo(Oldmen::class, 'oldman_id');
}

View File

@ -0,0 +1,19 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class ImportJob extends Model
{
use HasFactory;
protected $fillable = [
'status',
'success',
'fails',
'created_at',
'updated_at',
];
}

View File

@ -0,0 +1,24 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ImportJobLog extends Model
{
use HasFactory;
public const STATUS_FAILED = 0;
public const STATUS_SUCCESS = 1;
public static $statusTexts = [
self::STATUS_FAILED=>'失败',
self::STATUS_SUCCESS=>'成功',
];
public function job()
{
return $this->belongsTo(ImportJob::class);
}
}

View File

@ -22,6 +22,7 @@ class Oldmen extends Model
protected $casts = [
'birthday' => 'datetime:Y-m-d',
'bonds' => 'array',
];
protected $appends = ['age'];

View File

@ -0,0 +1,47 @@
<?php
namespace App\Services\Admin;
use App\Models\ImportJob;
use App\Models\ImportJobLog;
use Illuminate\Http\File;
class ImportService
{
protected $driver;
public function import(ImportJob $job)
{
if ($job->status == 1) {
$this->driver = new $job->type();
if(strpos($job->file, 'http') !== false) {
$res = $this->driver->readFileByUrl($job->file);
}else{
$file = new File(public_path('storage/'.$job->file));
$res = $this->driver->readFile($file);
}
if ($res) {
$job->update([
'status'=>2,
'success' => $res['success']??0,
'fails'=> $res['fails']??0,
]);
}
if (isset($res['errors']) && count($res['errors']) > 0) {
$this->createErrorLogs($job, $res['errors']);
}
}
}
public function createErrorLogs(ImportJob $job, array $errors)
{
ImportJobLog::insert(array_map(function ($value) use ($job) {
return array_merge($value, [
'job_id'=>$job->id,
'created_at' => now(),
'updated_at' => now(),
]);
}, $errors));
}
}

View File

@ -44,6 +44,8 @@ class LiveContinueService extends OldmenService
if(Carbon::parse($oldMan->avliable_at)->diffInSeconds($startAt) != 1){
return $this->setError('续住开始时间异常,请刷新重试!');
}
//调整结束时间
$endAt .= ' 23:59:59';
$flow = new ConstFlow();
$flow->oldman_id = $oldMan->id;

View File

@ -23,17 +23,18 @@ class LiveExitService extends OldmenService
if($oldMan->live_in != Oldmen::STATUS_LIVE){
return $this->setError('客人状态异常,请刷新后重试!');
}
$flowList = ConstFlow::where('oldman_id', $oldMan->id)
->whereIn('const_type', [ConstFlow::TYPE_IN, ConstFlow::TYPE_CONTINUE])
->where('state', 0)
->whereBetween('start_at', [$oldMan->live_in_at, $oldMan->avliable_at])//开始时间在用户这段时间内的清单
->get();
$flowMoney = 0;
foreach($flowList as $flow){
$flowMoney = bcsub($flowMoney, $flow->money, 2);
}
//取消计算历史费用
// $flowList = ConstFlow::where('oldman_id', $oldMan->id)
// ->whereIn('const_type', [ConstFlow::TYPE_IN, ConstFlow::TYPE_CONTINUE])
// ->where('state', 0)
// ->whereBetween('start_at', [$oldMan->live_in_at, $oldMan->avliable_at])//开始时间在用户这段时间内的清单
// ->get();
// foreach($flowList as $flow){
// $flowMoney = bcsub($flowMoney, $flow->money, 2);
// }
$flow = new ConstFlow();
$flow->oldman_id = $oldMan->id;
@ -63,7 +64,7 @@ class LiveExitService extends OldmenService
'need_pay' => Oldmen::PAY_NORMAL,
'live_in_at' => null,
'avliable_at' => null,
'bonds' => 0,//保证金归零
'bonds' => [],//保证金归零
]);
DB::commit();
}catch(Throwable $th){

View File

@ -110,29 +110,30 @@ class OldmenService extends BaseService
switch($type){
case ConstFlow::TYPE_EXIT:
if($oldMan){
if(isset($extends['live_in_at']) && $extends['avliable_at']){
$startAt = $extends['live_in_at'];
$endAt = $extends['avliable_at'];
}else{
$startAt = $oldMan->live_in_at;
$endAt = $oldMan->avliable_at;
}
//取消缴费记录计算
// if($oldMan){
// if(isset($extends['live_in_at']) && $extends['avliable_at']){
// $startAt = $extends['live_in_at'];
// $endAt = $extends['avliable_at'];
// }else{
// $startAt = $oldMan->live_in_at;
// $endAt = $oldMan->avliable_at;
// }
$flowList = ConstFlow::where('oldman_id', $oldMan->id)
->whereIn('const_type', [ConstFlow::TYPE_IN, ConstFlow::TYPE_CONTINUE])
->where('state', 0)
->whereBetween('start_at', [$startAt, $endAt])//开始时间在用户这段时间内的清单
->get();
foreach($flowList as $flow){
$rows[] = [
'ukey' => 'history_'.$flow->id,
'name' => '缴费记录',
'fee_name' => ConstFlow::typeMap()[$flow->const_type].'【'.$flow->created_at->format('m-d H:i:s').'】',
'fee_value' => 0-$flow->money,
];
}
}
// $flowList = ConstFlow::where('oldman_id', $oldMan->id)
// ->whereIn('const_type', [ConstFlow::TYPE_IN, ConstFlow::TYPE_CONTINUE])
// ->where('state', 0)
// ->whereBetween('start_at', [$startAt, $endAt])//开始时间在用户这段时间内的清单
// ->get();
// foreach($flowList as $flow){
// $rows[] = [
// 'ukey' => 'history_'.$flow->id,
// 'name' => '缴费记录',
// 'fee_name' => ConstFlow::typeMap()[$flow->const_type].'【'.$flow->created_at->format('m-d H:i:s').'】',
// 'fee_value' => 0-$flow->money,
// ];
// }
// }
$addFee = Arr::get($extends, 'add_extends', []);
if(!$addFee){

View File

@ -6,6 +6,7 @@
"license": "MIT",
"require": {
"php": "^8.1",
"box/spout": "^3.3",
"guzzlehttp/guzzle": "^7.2",
"laravel/framework": "^10.10",
"laravel/sanctum": "^3.2",

77
composer.lock generated
View File

@ -4,8 +4,83 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "a483aafe1cb9cc540a4db897e1c35ac4",
"content-hash": "4a5297a88397d5f65572b83c55b33701",
"packages": [
{
"name": "box/spout",
"version": "v3.3.0",
"source": {
"type": "git",
"url": "https://github.com/box/spout.git",
"reference": "9bdb027d312b732515b884a341c0ad70372c6295"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/box/spout/zipball/9bdb027d312b732515b884a341c0ad70372c6295",
"reference": "9bdb027d312b732515b884a341c0ad70372c6295",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-xmlreader": "*",
"ext-zip": "*",
"php": ">=7.2.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2",
"phpunit/phpunit": "^8"
},
"suggest": {
"ext-iconv": "To handle non UTF-8 CSV files (if \"php-intl\" is not already installed or is too limited)",
"ext-intl": "To handle non UTF-8 CSV files (if \"iconv\" is not already installed)"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1.x-dev"
}
},
"autoload": {
"psr-4": {
"Box\\Spout\\": "src/Spout"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Adrien Loison",
"email": "adrien@box.com"
}
],
"description": "PHP Library to read and write spreadsheet files (CSV, XLSX and ODS), in a fast and scalable way",
"homepage": "https://www.github.com/box/spout",
"keywords": [
"OOXML",
"csv",
"excel",
"memory",
"odf",
"ods",
"office",
"open",
"php",
"read",
"scale",
"spreadsheet",
"stream",
"write",
"xlsx"
],
"support": {
"issues": "https://github.com/box/spout/issues",
"source": "https://github.com/box/spout/tree/v3.3.0"
},
"abandoned": true,
"time": "2021-05-14T21:18:09+00:00"
},
{
"name": "brick/math",
"version": "0.11.0",

View File

@ -0,0 +1,44 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('import_jobs', function (Blueprint $table) {
$table->id();
$table->string('name')->nullable()->comment('名称');
$table->string('file')->comment('导入的文件路径');
$table->string('type')->comment('导入执行类');
$table->unsignedTinyInteger('status')->default(0)->comment('状态0未开始1导入中2完成');
$table->unsignedInteger('success')->default(0)->comment('成功条数');
$table->unsignedInteger('fails')->default(0)->comment('失败条数');
// $table->unsignedBigInteger('')
$table->timestamps();
});
Schema::create('import_job_logs', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('job_id')->comment('任务ID');
$table->unsignedInteger('row')->default(0)->comment('行数');
$table->unsignedTinyInteger('status')->default(0)->comment('状态1成功');
$table->text('reason')->nullable()->comment('原因');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('import_jobs');
Schema::dropIfExists('import_job_logs');
}
};

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -55,7 +55,7 @@
<p class="tag" style="font-size:20px;">
<span class="left">客户姓名 {{$name}}</span>
<span class="middle">日期 {{$time}}</span>
<span class="right">单据编号 {{$sn}}</span>
<span class="right">单据编号 {{$idsn}}</span>
</p>
<table class="print-table">
<tr>