ソースを参照

问题件导入 问提件导入新增【订单管理-订单问题件生成-文本导入】权限及对应功能 需执行迁移文件添加权限

ajun 5 年 前
コミット
ec1553625f

+ 79 - 0
app/Http/Controllers/OrderIssueController.php

@@ -477,4 +477,83 @@ class OrderIssueController extends Controller
             return ['success'=>false,$e->getMessage()];
         }
     }
+    public function importPasteDataApi(Request $request)
+    {
+        if (!Gate::allows('订单管理-订单问题件生成'))
+            return ['success'=>false,'fail_info'=>'没有对应权限'];
+        $rows = $request->input('rows');
+        $logistic_numbers = [];
+        $types = [];
+        $maps = [];
+        $errors = [];
+        $orderIssueTypes = OrderIssueType::all();
+        $orderIssueType_map = [];
+        foreach ($orderIssueTypes as $orderIssueType) {
+            $orderIssueType_map[$orderIssueType->name] = $orderIssueType;
+        }
+        $array = explode("\n",$request->input('pasteDataText')); //拆分行
+        /** @var OrderIssueService $service */
+        $service =  app(OrderIssueService::class);
+        foreach ($array as $i => $str) {
+            $items = explode("\t",$str);
+             $head = '第'.($i+1).'行';
+            if(count($items)<count($rows)){
+                $errors[$head] = ['数据不完整'];
+                unset($items);
+                continue;
+            }
+            $map = [];
+
+            foreach ($rows as $index=>$row) {
+                if($row === '原始运单号'){
+                    if(!$items[$index]){
+                        $errors[$head][]='快递单号为空';
+                        $map =[];
+                    }
+                    $exist_logistic =  $service->校验问题件是否存在_快递单号_返回存在的快递单号([$items[$index]]);
+                    if(count($exist_logistic) > 0){
+                        $errors[$head][]='快递单号存在对应的问题件';
+                        $map =[];
+                    }
+                    $logistic_numbers[] = $items[$index];
+                    $map['logistic_number'] = $items[$index];
+                }
+                if($row==='情况说明'){
+                    if(!$items[$index]){
+                        $errors[$head][]='情况说明为空';
+                        $map =[];
+                    }
+                    $map['result_explain'] = $items[$index];
+                }
+                if($row==='问题类别'){
+                    if(!$items[$index]){
+                        $errors[$head][]='问题类别为空';
+                        $map = [];
+                    }else{
+                        $type =  $orderIssueType_map[$items[$index]] ?? null;
+                        if(!$type){
+                            $errors[$head][]='问题类型不存在';
+                            $map = [];
+                        }
+                    }
+                    $types[] =$items[$index];
+                    $map['type'] = $items[$index];
+                }
+            }
+            if(count($map)!==0)$maps[] = $map;
+        }
+        if(count($errors)>0) return ['success'=>false,'fail_info'=>$errors];
+        try {
+            foreach ($maps as $map) {
+                $logistic_number = $map['logistic_number'];
+                $result_explain = $map['result_explain'];
+                $type = $map['type'];
+                $service->createOrderIssue($logistic_number, $type, $result_explain);
+            }
+            return ['success'=>true];
+        } catch (Exception $e) {
+            LogService::log(__METHOD__,__FUNCTION__,'文本导入问题件失败'.json_encode($request->getContent().$e->getMessage().$e->getTraceAsString()));
+            return ['success'=>false,'fail_info'=>$e->getMessage()];
+        }
+    }
 }

+ 30 - 0
app/Services/OrderIssueService.php

@@ -6,6 +6,7 @@ use App\OracleDOCASNHeader;
 use App\OracleDOCOrderHeader;
 use App\OrderIssue;
 use App\OrderIssueProcessLog;
+use App\OrderIssueType;
 use App\OrderPackage;
 use App\Order;
 use App\RejectedBill;
@@ -448,4 +449,33 @@ class OrderIssueService
             ->where('id',$order->id)->first();
         return ['success' => true,'order' =>$order];
     }
+
+    /**
+     * @param string $logisticNumber
+     * @param string $type
+     * @param string $result_explain
+     */
+    public function createOrderIssue($logisticNumber,$type,$result_explain)
+    {
+        $orderHeaders = OracleDOCOrderHeader::query()->with(['oracleDOCOrderDetails', 'actAllocationDetails','oracleBASCode'])
+            ->whereHas('actAllocationDetails',function($query)use($logisticNumber){
+                $query->where('picktotraceid',$logisticNumber);
+            })->get();
+        $orderIssueType = OrderIssueType::query()->where('name',$type)->first();
+        $this->createOrderIssueByWmsOrder($orderHeaders,$orderIssueType->id,$result_explain);
+    }
+
+    /**
+     * @param array $logisticNumbers
+     * @return array
+     */
+    public function 校验问题件是否存在_快递单号_返回存在的快递单号($logisticNumbers)
+    {
+        $orderIssues = OrderIssue::query()->with('order.packages')->whereHas('order.packages',function($query)use($logisticNumbers){
+            $query->whereIn('logistic_number',$logisticNumbers);
+        })->get();
+        $exits_logistic_number = array_diff(array_unique(data_get($orderIssues,'*.order.packages.*.logistic_number')),['',null]);
+        return array_intersect($exits_logistic_number,$logisticNumbers);
+    }
+
 }

+ 31 - 0
database/migrations/2020_10_26_091851_add_order_issue_text_import_authorities.php

@@ -0,0 +1,31 @@
+<?php
+
+use App\Authority;
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddOrderIssueTextImportAuthorities extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        //
+        (new Authority(['name'=>'订单管理-订单问题件生成-文本导入','alias_name'=>'订单管理-订单问题件生成-文本导入']))->save();
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        //
+        Authority::query()->where('name','订单管理-订单问题件生成-文本导入')->delete();
+    }
+}

+ 122 - 8
resources/views/order/issue/import.blade.php

@@ -7,19 +7,37 @@
     <div class="container-fluid" id="issue_import_div">
         <div class="card col-md-8 offset-md-2">
             <div class="card-body">
-                <form action="{{url('order/issue/batchImport')}}" method="post" enctype="multipart/form-data" class="form"  target="_blank">
-                    @csrf
+
+                <div class="form-group row text-center">
+                    <div class="col-12 text-danger">
+                        注意:请保证表第一行有以下对应的字段名<br><span class="text-muted">(可不按顺序):</span><br>
+                        原始运单号,情况说明,问题类别<br>
+                        <span class="text-muted" style="opacity:0.7"> 订单问题类别:('拦截', '快递异常', '信息更改', '联系不上', '其他', '错漏发', '仓库问题', '快递丢件', '破损', '撤销丢件', '二次加工', '全检问题', '系统问题', '延迟发货', '仓库丢件', )<br></span>
+                    </div>
+                    <div class="col-12 text-info ">
+                        导入时间随文件大小可能达数十分钟以上,请耐心等候
+                        <hr>
+                    </div>
+                </div>
+                @can('订单管理-订单问题件生成-文本导入')
                     <div class="form-group row text-center">
                         <div class="col-12 text-danger">
-                            注意:请保证表第一行有以下对应的字段名<br><span class="text-muted">(可不按顺序):</span><br>
-                            原始运单号,情况说明,问题类别<br>
-                            <span class="text-muted" style="opacity:0.7"> 订单问题类别:('拦截', '快递异常', '信息更改', '联系不上', '其他', '错漏发', '仓库问题', '快递丢件', '破损', '撤销丢件', '二次加工', '全检问题', '系统问题', '延迟发货', '仓库丢件', )<br></span>
+                            订单问题类别:同Excel文件导入所要求的订单问题类别一致<br/>
+                            注意:文本导入的问题件只有全部符合条件的才能生成问题件<br/>
+                            <span class="text-muted" style="opacity:0.7">
+                                如果在导入后出现部分数据导入失败,修改对应错误的数据继续导入即可
+                            </span>
                         </div>
-                        <div class="col-12 text-info ">
-                            导入时间随文件大小可能达数十分钟以上,请耐心等候
-                            <hr>
+                    </div>
+                    <div class="form-group row">
+                        <div class="col-8 offset-2">
+                            <button type="button" class="btn form-control btn-primary"  @click="showPasteDataModal">文本导入</button>
                         </div>
                     </div>
+                    <hr/>
+                @endcan
+                <form action="{{url('order/issue/batchImport')}}" method="post" enctype="multipart/form-data" class="form"  target="_blank">
+                    @csrf
                     <div class="form-group row">
                         <label for="sku" class="col-2 col-form-label text-right">选择EXCEL</label>
                         <div class="col-8">
@@ -42,10 +60,106 @@
                 </form>
             </div>
         </div>
+        <div class="modal fade" id="pasteData" role="dialog" tabindex="-1" aria-labelledby="pasteDataTetlie" aria-hidden="true">
+            <div class="modal-dialog modal-dialog-centered modal-lg" role="document">
+                <div class="modal-content">
+                    <div class="modal-header">
+                        <div class="row modal-title font-weight-bold w-100 text-nowrap ml-1 noselect" id="pasteDataTitle">
+                            <span v-for="(row,i) in rows" draggable="true"
+                                  @drop="drop($event,i)" @dragover="dragover($event)" @dragstart="dragstart($event,i)"
+                                  class="col-4 border" style="cursor: move"
+                                  :class="requiredRows.includes(row)?'text-danger':''">@{{ row }}</span>
+                        </div>
+                    </div>
+                    <div class="modal-body text-center">
+                        <button type="button" id="popover" class="btn btn-danger" v-if="popoverContent"
+                                data-container="body" data-toggle="popover" data-placement="bottom"
+                                :data-content="popoverContent" data-html="true">
+                            部分数据导入失败
+                        </button>
+                        <textarea id="pasteDataText" class="w-100" style="height: 400px" v-model="pasteDataText"
+                                  @keydown.tab="forbidTab($event)" @keyup.tab="replaceSpacing()"
+                                  placeholder="内容可为EXCEL复制,也可手动输入使用“TAB”缩进符区分列,请注意表头顺序,可拖拽表头字段调整顺序,以该顺序为准"></textarea>
+                    </div>
+                    <div class="modal-footer">
+                        <button class="btn btn-primary" @click="importPasteData">开始导入</button>
+                    </div>
+                </div>
+            </div>
+        </div>
     </div>
 @endsection
 
 @section('lastScript')
+    <script>
+        let listVue = new Vue({
+            el:'#issue_import_div',
+            data:{
+                rows:['原始运单号','情况说明','问题类别'],
+                requiredRows:['原始运单号','情况说明','问题类别'],
+                popoverContent:'',
+                pasteDataText: '',
+            },
+            mounted:function(){
+                $('[data-toggle="popover"]').popover();
+            },
+            methods:{
+                showPasteDataModal(){
+                    $('#popover').attr('hidden','hidden')
+                    $('#pasteData').modal('show')
+                },
+                drop(e,index){
+                    e.preventDefault();
+                    if (this.dom !== e.target.innerHTML){
+                        this.dom.innerHTML = e.target.innerHTML;
+                        let temp=JSON.parse(JSON.stringify(this.rows[index]));
+                        this.$set(this.rows,index,this.rows[e.dataTransfer.getData('text/html')]);
+                        this.$set(this.rows,Number(e.dataTransfer.getData('text/html')),temp);
+                    }
+                },
+                dragover(e){
+                    e.preventDefault();
+                },
+                dragstart(e,index){
+                    this.dom = e.target.innerHTML;
+                    e.dataTransfer.setData("text/html",index);
+                },
+                importPasteData(){
+                    if(!this.pasteDataText){
+                        tempTip.setDuration(2000)
+                        tempTip.show('导入文本不能为空')
+                    }
+                    let _this = this
+                    let data = {rows:this.rows,pasteDataText:this.pasteDataText}
+                    axios.post('{{url('apiLocal/order/issue/importPasteData')}}',data).then(function (response) {
+                        if(response.data.success){
+                            $('#pasteData').modal('hide')
+                            tempTip.setDuration(2000)
+                            tempTip.showSuccess('导入完毕')
+                        }else{
+                            let content = '';
+                            for (const key in response.data.fail_info) {
+                                content+=key+':'+response.data.fail_info[key] + "</br>"
+                            }
+                            _this.popoverContent = content
+                            setTimeout(function () {
+                                $("#popover").removeAttr('hidden').popover('show')
+                            },1);
+                        }
+                    }).catch(function(error){
+                        tempTip.setDuration(2000)
+                        tempTip.show('导入失败'+error)
+                    })
+                },
+                forbidTab(e){
+                    e.preventDefault();
+                },
+                replaceSpacing(){
+                    this.pasteDataText += "\t";
+                },
 
+            }
+        });
+    </script>
 @endsection
 

+ 1 - 0
routes/apiLocal.php

@@ -50,6 +50,7 @@ Route::group(['prefix' => 'order'], function () {
         Route::post('editSecondClientNo','OrderIssueController@editSecondClientNoApi');
         Route::post('endOrderIssues','OrderIssueController@endOrderIssuesApi');
         Route::post('editSecondLogisticNumber','OrderIssueController@editSecondLogisticNumberApi');
+        Route::post('importPasteData','OrderIssueController@importPasteDataApi');
 
          Route::group(['prefix'=>'onTop'],function(){
             Route::post('/store', 'OrderIssueOnTopController@apiStore');