Explorar o código

卸货导入功能

ajun %!s(int64=4) %!d(string=hai) anos
pai
achega
81841be395

+ 12 - 4
app/Http/Controllers/DischargeTaskController.php

@@ -14,6 +14,7 @@ use App\Services\OwnerService;
 use App\Warehouse;
 use Carbon\Carbon;
 use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Cache;
 use Illuminate\Support\Facades\Gate;
 use Maatwebsite\Excel\Facades\Excel;
 use function Sodium\compare;
@@ -147,13 +148,20 @@ class DischargeTaskController extends Controller
         return view('personnel.discharge.task.receipt',compact('task'));
     }
 
-    public function importApi(Request $request)
+    public function importApi(Request $request): array
     {
-
         $extension=$request->file()['file']->getClientOriginalExtension();
         $extension[0] = strtoupper($extension[0]);
-        Excel::import(new DischargeTaskImport(), $request->file()['file']->path(),null,$extension);
-
+        try {
+            Excel::import(new DischargeTaskImport(), $request->file()['file']->path(), null, $extension);
+        } catch (\Exception $e) {
+            dd($e->getMessage());
+            return ['success'=>false,'message' => ['请检查导入文件是否符合要求']];
+        }
+        if(Cache::has('exception')){
+            return ['success' => false,'errors' => Cache::get('exception')];
+        }
+        return ['success' => true];
     }
 
 

+ 64 - 6
app/Imports/DischargeTaskImport.php

@@ -2,22 +2,80 @@
 
 namespace App\Imports;
 
+use App\DischargeTask;
+use App\Owner;
+use App\Services\DischargeTaskService;
+use App\Warehouse;
+use Illuminate\Support\Carbon;
 use Illuminate\Support\Collection;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Str;
 use Maatwebsite\Excel\Concerns\ToCollection;
 use Maatwebsite\Excel\Concerns\WithHeadingRow;
 use Maatwebsite\Excel\Imports\HeadingRowFormatter;
+use PhpMyAdmin\Plugins\Export\ExportExcel;
 
 HeadingRowFormatter::default('none');
-class DischargeTaskImport implements ToCollection,WithHeadingRow
+
+class DischargeTaskImport implements ToCollection, WithHeadingRow
 {
     /**
-    * @param Collection $collection
-    */
+     * @param Collection $collection
+     */
     public function collection(Collection $collection)
     {
-        dd($collection->first());
-//        foreach ($collection as $item) {
+        /** @var DischargeTaskService $service */
+        $service = app(DischargeTaskService::class);
+        $exception = [];
+        $numbers = [];
+        foreach ($collection as $row => $item) {
+            $index = $row + 1;
+            $message = '';
+            $owner = Owner::query()->where('name', trim($item['货主']))->first();
+            $waveHouse = Warehouse::query()->where('name', trim($item['仓库']))->first();
+            $type = array_search(trim($item['作业名称']), DischargeTask::types);
+
+            if (array_search(trim($item['入库单']), $numbers)) $message .= '入库单号重复;';
+
+            if (!$owner) $message .= '对应货主不存在;';
+
+            if (!$waveHouse) $message .= '对应仓库不存在;';
+
+            if (!$item['入库单'] || strlen(trim('入库单')) == 0) $message .= '未输入入库单;';
+
+            if (!$item['数量'] || strlen(trim('数量')) == 0) $message .= '未输入数量;';
+
+            if (!$item['单价'] || strlen(trim('单价')) == 0) $message .= '未输入单价;';
+
+            if (isset($type) && $type != 0) $message .= '指定作业类型错误;';
+
+            if (!$item['作业名称']) $message .= '未指定作业类型';
+
+            if (DischargeTask::query()->where('numbers',$item['入库单'])->exists()) $message .= '入库单号已存在;';
 
-//        }
+            if (strlen($message) > 0) {
+                $exception[] = "第{$index}行卸货任务创建失败:" . $message;
+                continue;
+            }
+            $params = [
+                'owner_id' => $owner->id,
+                'warehouse_id' => $waveHouse->id,
+                'type' => $type,
+                'numbers' => trim($item['入库单']),
+                'income_amount' => $item['数量'],
+                'income_unit_price' => $item['单价'],
+                'income_total_cost' => $item['数量'] * $item['单价'],
+                'status' => 0,
+                'income_remark' => $item['备注'],
+                'income_at' => $item['预约日期'] ?formatExcelDateTime($item['预约日期']): Carbon::now()->format(Carbon::DEFAULT_TO_STRING_FORMAT)
+            ];
+            try {
+                $service->createTask($params, false);
+                $numbers[] = trim($item['入库单']);
+            } catch (\Exception $e) {
+                $exception[] = "第{$index}行创建失败:创建异常";
+            }
+        }
+        Cache::put('exception', $exception, 86400);
     }
 }

+ 2 - 2
app/Services/DischargeTaskService.php

@@ -72,7 +72,7 @@ class DischargeTaskService
     }
 
     // 创建卸货任务
-    public function createTask(array $param): array
+    public function createTask(array $param,bool $loadMissing = true): array
     {
         if (isset($param['id'])) unset($param['id']);
         if (empty($param['income_total_cost'])) $param['income_total_cost'] = $param['income_unit_price'] * $param['income_amount'];
@@ -80,7 +80,7 @@ class DischargeTaskService
         if (empty($param['status'])) $param['status'] = 0;
 
         $dischargeTask = DischargeTask::query()->create($param);
-        $dischargeTask->loadMissing('facilitator', 'owner','warehouse');
+        if($loadMissing)$dischargeTask->loadMissing('facilitator', 'owner','warehouse');
 
         return ['success' => true, 'data' => $dischargeTask];
     }

+ 10 - 1
app/Utils/helpers.php

@@ -3,6 +3,8 @@
 use Carbon\Carbon;
 use Illuminate\Database\Eloquent\Model;
 
+const DAY_TO_MILLI_SECONDS  = 1000*60*60*24;
+
 function formatExcelDate(int $timestamp)
 {
     $diff = intval($timestamp);
@@ -11,6 +13,13 @@ function formatExcelDate(int $timestamp)
     return $day->toDateString();
 }
 
+function formatExcelDateTime(float $timestamp): string
+{
+    $today = new Carbon('1900-01-01');
+    $day = $today->addMilliseconds(intval($timestamp*DAY_TO_MILLI_SECONDS))->subDays(2);
+    return $day->toDateTimeString();
+}
+
 function diff($array1,$array2,string $identification,array $mapping,bool $intactDetached = false):array
 {
     $changes = [
@@ -48,4 +57,4 @@ function diff($array1,$array2,string $identification,array $mapping,bool $intact
         }else $changes['detached'][] = array_keys($map);
     }
     return $changes;
-}
+}

+ 10 - 6
resources/views/personnel/discharge/task/_import.blade.php

@@ -13,21 +13,25 @@
                 <form>
                     <div class="form-group">
                         <label for="importFile">导入文件</label>
-                        <input type="file" ref="file" name="file" :class="uploadError.length >0 ? 'is-invalid' :''" id="importFile">
-                        <div class="invalid-feedback">
-                            @{{ uploadError ? uploadError[0] :'' }}
-                        </div>
+                        <input type="file" ref="file" name="file"  id="importFile">
                     </div>
                     <div class="form-group">
                         <small>文件大小不能超过10MB</small>
                     </div>
                     <div class="form-group">
-                        <small>字段:*货主,*预约日期,*作业名称,*仓库,*入库单,*数量,*单位,*单价,备注(非必填)</small>
+                        <small>字段:*货主,*预约日期,*作业名称,*仓库,*入库单,*数量,*单位,*单价,备注(非必填)</small>
+                    </div>
+                    <div class="form-group" v-if="uploadErrors.length > 0">
+                        <p class="text-danger">导入异常明细</p>
+                        <ul class="list-group" v-if="uploadErrors">
+                            <li class="list-group-item" v-for="error in uploadErrors">@{{ error }}</li>
+                        </ul>
                     </div>
                 </form>
             </div>
             <div class="modal-footer">
-                <button class="btn btn-success" @click="importTask">导入</button>
+                <button class="btn btn-success" @click="cancelImport">关闭</button>
+                <button class="btn btn-success" @click="importDischarge">导入</button>
             </div>
         </div>
     </div>

+ 14 - 4
resources/views/personnel/discharge/task/index.blade.php

@@ -62,7 +62,7 @@
                 addTask: {income_at:null},
                 executingTack: {},
                 taskError:{},
-                uploadError:[],
+                uploadErrors:[],
                 taskTypes: [
                     {name: 0, value: "装车"},
                     {name: 1, value: "卸车"},
@@ -363,23 +363,27 @@
                 showReceipt(task){
                     window.open(this.getReceiptUrl(task.id));
                 },
-                // 文件上传
+                // 批量导入
                 importDischarge(){
                     window.tempTip.setIndex(1999);
 
                     let formData = new FormData();
-                    let file = document.querySelector('#importFile').file[0];
+                    let file = document.querySelector('#importFile').files[0];
                     if(file==null){
                         window.tempTip.show('请选择上传文件');
                     }
                     formData.append('file',file);
-                    let url = '{{url('apiLocal/personnel/discharge/import')}}';
+                    let url = '{{url('apiLocal/personnel/discharge/task/import')}}';
                     window.axios.post(url,formData,{
                         'Content-Type': 'multipart/form-data'
                     }).then(res=>{
                         if(res.data.success){
                             window.tempTip.showSuccess(res.data.message ? res.data.message : '导入成功!刷新页面显示');
                             return ;
+                        }else if(res.data.errors){
+                            window.tempTip.show('导入创建卸货任务失败!,详情请看列表')
+                            this.uploadErrors = res.data.errors;
+                            return ;
                         }
                         window.tempTip.show('导入失败!'+(res.data.message ? res.data.message : ''));
                     }).catch(err=>{
@@ -389,8 +393,14 @@
                 importModal(){
                     document.querySelector('#importFile').file = [];
                     $('#importModal').modal('show');
+                },
+                cancelImport(){
+                    this.uploadErrors = [];
+                    $('#importModal').modal('hide');
+                    document.querySelector('#importFile').value = null;
                 }
 
+
             }
         })
     </script>

+ 1 - 1
routes/apiLocal.php

@@ -47,7 +47,7 @@ Route::group(['prefix' => 'personnel'], function () {
             Route::put('update', 'DischargeTaskController@updateApi')->name('discharge.updateApi');
             Route::put('updateFacilitator', 'DischargeTaskController@updateTaskFacilitatorApi')->name('discharge.updateTaskFacilitatorApi');
             Route::put('updateColumn', 'DischargeTaskController@updateApi')->name('facilitator.updateColumnApi');
-            Route::put('import', 'DischargeTaskController@importApi')->name('discharge.importApi');
+            Route::post('import', 'DischargeTaskController@importApi')->name('discharge.importApi');
         });
     });
 });