5

I am working on yii2. I have a master table called sims in my DB and all the records are saved and updated in it. In my GUI these records are maintained in SIM List. Now, there is a use-case in which I am issuing the sims to a person. The issuance is done by two ways

  1. Using create form
  2. Via excel file

Both cases are running perfectly. Now, issuing sims via excel file, I want to check imsi number(s) whether they are available in the master record or not.

Bellow is my Import controller

 public function actionImport(){
    $file_name = $_POST['file_name'];
    $header_index = $_POST['header_index'];
    $fieldSet = $_POST['field'];


    $data = \moonland\phpexcel\Excel::widget([
        'mode' => 'import',
        'fileName' => 'uploads/' . $file_name,
        'setFirstRecordAsKeys' => false, // if you want to set the keys of record column with first record, if it not set, the header with use the alphabet column on excel.
        'setIndexSheetByName' => false, // set this if your excel data with multiple worksheet, the index of array will be set with the sheet name. If this not set, the index will use numeric.
        'getOnlySheet' => 0, // you can set this property if you want to get the specified sheet from the excel data with multiple worksheet.
    ]);

    //loop therogh first sheet
    $ok_count = 0;
    $status_arr = [];
    $final_data = isset($data[0]) ? $data[0] : $data;
    foreach($final_data as $key=>$value)
    {
        if($key <= $header_index) continue;
        $sims = new SimIssueanceTransaction();

        foreach($value as $k=>$v){


            $v = preg_replace('/\s+/', ' ', trim($v));
            if(isset($fieldSet[0]['imsi']) && $fieldSet[0]['imsi']==$k){
                $sims->sim_id = Sims::imsiToidexcel($v);
                $sims->imsi =$v."";

            }

            if(isset($fieldSet[0]['issued_to']) && $fieldSet[0]['issued_to']==$k){
                $sims->issued_to = $v;
            }

            if (isset($fieldSet[0]['purpose']) && $fieldSet[0]['purpose'] == $k) {
                $sims->purpose = $v;
            }

        }
        $sims->issued_at = date('Y-m-d H:i:s');
        $sims->issued_by = Yii::$app->user->id;
        $sims->historic =1;

        if($sims->purpose=='Local SIM Issue')
        {
            $sims->status = Sims::$status_titles[1];
            Sims::change_status($sims->sim_id,Sims::$status_titles[1]);
        }
        else
        {
            $sims->status = Sims::$status_titles[2];
            Sims::change_status($sims->sim_id,Sims::$status_titles[2]);
        }


        if($sims->save())
        {
            $ok_count++;
        }
        else
        {
            $status_arr[] = $sims->errors;
        }


    }

    return $this->render('excel_finish', ['records_saved' => $ok_count,'status_arr'=>$status_arr]);
}

I want to add a check in bellow condition

if(isset($fieldSet[0]['imsi']) && $fieldSet[0]['imsi']==$k){
                $sims->sim_id = Sims::imsiToidexcel($v);
                $sims->imsi =$v."";

            }

Update 1

My Sims model is below

public function rules()
{
    return [
        [['imsi','operator_name','data_details','sms_details','status'], 'required'],
        [['created_by', 'updated_by', 'sim_stauts', 'issued_to', 'returned_by', 'historic'], 'integer'],
        [['created_at', 'updated_at','returned_at'], 'safe'],
        [['imsi', 'operator_name', 'data_details', 'sms_details','bill_date'], 'string', 'max' => 20],
        [['sim_number', 'status','credit_limit','plan_name'], 'string', 'max' => 50],
        [['monthly_bill'], 'string', 'max' => 100],
        //[['imsi'], 'unique'],
        [['created_by'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['created_by' => 'id']],
    ];
}
public function attributeLabels()
{
    return [
        'id' => 'ID',
        'imsi' => 'Imsi',
        'sim_number' => 'Sim Number',
        'operator_name' => 'Operator Name',
        'data_details' => 'Data Details',
        'sms_details' => 'Sms Details',
        'monthly_bill' => 'Monthly Bill',
        'created_by' => 'Created By',
        'created_at' => 'Created At',
        'updated_at' => 'Updated At',
        'status' => 'Status',
        'updated_by' => 'Updated By',
        'sim_stauts' => 'Sim Stauts',
        'issued_to' => 'Issued To',
        'returned_by' => 'Returned By',
        'historic' => 'Version',
        'returned_at'=>'Returned At',
        'bill_date' => 'Billing Date',
        'credit_limit' => 'Credit Limit',
        'plan_name'=> 'Plan Name'
    ];
}

Update 2

As per suggestion I have created a function

 protected function findImsi($imsi){

    if(($model=Sims::findOne(['imsi'=>$imsi]))!== null){
        return true;
    }
    else{
        return false;
    }


}

Then in my import controller

foreach($final_data as $key=>$value)
    {
        if($key <= $header_index) continue;
        $sims = new SimIssueanceTransaction();

        foreach($value as $k=>$v){

            $v = preg_replace('/\s+/', ' ', trim($v));
            $imsiValid = isset($fieldSet[0]['imsi']) && $fieldSet[0]['imsi'] == $k && $this->findImsi($v);

            if ($imsiValid) {
                $sims->sim_id = Sims::imsiToidexcel($v);
                $sims->imsi = $v . "";
            }
            else
            {

                \Yii::$app->getSession()->setFlash('error', '
 <div class="alert alert-error alert-dismissable">
 <button aria-hidden="true" data-dismiss="alert" class="close" type="button">×</button>
 <strong>Error!!! No Record is inserted..</strong> IMSI must be wrong </div>');
                return $this->redirect(['simissueancetransaction/excel']);
            }
.
.
.
}
.
.
.
}

While uploading an excel file with correct values in it, the $imsiValid is true but still it's not entering the if condition

By doing var_dump($final_data); I got the following result

array(3) { [1]=> array(4) { ["A"]=> string(4) "imsi" ["B"]=> string(9) "issued to" ["C"]=> string(7) "purpose" ["D"]=> NULL } [2]=> array(4) { ["A"]=> string(18) "899204031015192575" ["B"]=> float(134) ["C"]=> string(20) "Production SIM Issue" ["D"]=> NULL } [3]=> array(4) { ["A"]=> string(18) "899204031015192576" ["B"]=> float(134) ["C"]=> string(20) "Production SIM Issue"} }

Update 3

Below are the other two action controller functions for upload excel file.

  public function actionExcel(){

    $file_name = "excel_" . Yii::$app->user->id . ".xlsx";

    $error = "";
    if(isset($_FILES['file'])) {
        $path_parts = pathinfo($_FILES["file"]["name"]);
        $extension = $path_parts['extension'];

        if(!in_array($extension,['xlsx','xls'])){

            $error = "Invalid file";
        }else {
            if (move_uploaded_file($_FILES['file']['tmp_name'], 'uploads/' . $file_name)) {

                $this->redirect(Url::to('process?file_name=' . $file_name . "&header_no=" . $_POST['header_no']));
            }
        }
    }
    return $this->render("excel",['error'=>$error]);
}
public function actionProcess(){

    $file_name = $_GET['file_name'];

    // $data = \moonland\phpexcel\Excel::import("uploads/test.xlsx"); // $config is an optional

    try {
        $header_index = $_GET['header_no'];

        $data = \moonland\phpexcel\Excel::widget([
            'mode' => 'import',
            'fileName' => 'uploads/' . $file_name,
            'setFirstRecordAsKeys' => false, // if you want to set the keys of record column with first record, if it not set, the header with use the alphabet column on excel.
            'setIndexSheetByName' => false, // set this if your excel data with multiple worksheet, the index of array will be set with the sheet name. If this not set, the index will use numeric.
            'getOnlySheet' => 0, // you can set this property if you want to get the specified sheet from the excel data with multiple worksheet.
        ]);
        if (isset($data[0])) {
            $headers = $data[0][$header_index];
        } else {
            $headers = $data[$header_index];
        }

    }catch (Exception $x){
        die("Error");
    }

    return $this->render('excel_options',['headers'=>$headers,'file_name'=>$file_name,'header_index'=>$header_index]);

}

After these two function the import function is called

The model in which all the records are saved and updated is Sims.

How can I match the IMSI number with the master record?

Any help would be highly appreciated.

Panda
  • 6,955
  • 6
  • 40
  • 55
Moeez
  • 494
  • 9
  • 55
  • 147
  • `sims` have the `imsi` number saved in it and you want to check against that table first if it exists there or not? – Muhammad Omer Aslam Mar 09 '18 at 11:28
  • added an answer see if it works – Muhammad Omer Aslam Mar 09 '18 at 11:39
  • @MuhammadOmerAslam yes exactly I want to check the `imsi` and if any of the `imsi` is not available then it would not be inserted. – Moeez Mar 10 '18 at 03:12
  • considering the sample data you provided what is the expected value of the `$header_index` and how does this `if($key <= $header_index)` condition evaluates, what would you post for the header_index – Muhammad Omer Aslam Mar 14 '18 at 21:21
  • @MuhammadOmerAslam kindly check my `update 3`. You'll get a clearer picture – Moeez Mar 15 '18 at 06:19
  • this is not what i was asking for i was asking that what do you have in the `$header_index = $_POST['header_index'];` inside your import action – Muhammad Omer Aslam Mar 15 '18 at 23:49
  • The row value. it can be up to 8 – Moeez Mar 16 '18 at 03:12
  • this is strange i am unable to replicate it at my end the only condition the `imsiValid` is false is when the `fieldSet` indexes do not match you should verify the data coming from excel is in the correct order or not otherwise it is not the case it is simple as suggested in the answer below which is verify the sim number before insertion and return `true` or `false` in either case. – Muhammad Omer Aslam Mar 18 '18 at 00:05
  • @MuhammadOmerAslam I am also not sure what is the main issue. As without this check, I am able to upload the data. – Moeez Mar 18 '18 at 11:40
  • try moving `if($this->findModel($v))` inside the `if ($imsiValid) {` and remove `$this->findModel($v)` from the prevoious line. – Muhammad Omer Aslam Mar 20 '18 at 23:21
  • i have updated the answer see the replace section to understand what i am asking to do – Muhammad Omer Aslam Mar 21 '18 at 00:58

1 Answers1

5

What i have understood from your question is that you have Sims model in which you have saved all the sims along with the imsi and before you insert any record into the SimIssueanceTransaction you want to verify if it exists in the Sims or not.

If this is correct then take the following steps

Add a method to your controller

protected function findModel($imsi){
    if(($model=Sims::findOne(['imsi'=>$imsi])) !== null){
        return true;
    }
    return false;
}

and then replace these lines

$v = preg_replace('/\s+/', ' ', trim($v));
if (isset($fieldSet[0]['imsi']) && $fieldSet[0]['imsi'] == $k) {
    $sims->sim_id = Sims::imsiToidexcel($v);
    $sims->imsi = $v . "";
}

with the following

$v = preg_replace('/\s+/', ' ', trim($v));
$imsiValid = isset($fieldSet[0]['imsi']) && $fieldSet[0]['imsi'] == $k;

if ($imsiValid) {
  if($this->findModel($v)){
    $sims->sim_id = Sims::imsiToidexcel($v);
    $sims->imsi = $v . "";
  }
}

Note :I assume that $v will have the imsi when $fieldSet[0]['imsi']==$k as you are setting $sims->imsi = $v inside the condition, other wise change $this->findModel($v) accordingly

Muhammad Omer Aslam
  • 22,976
  • 9
  • 42
  • 68
  • I have tried your answer. In either way, it's not entering inside the `if ($imsiValid)`. I have checked the value of `imsiValid` and it's `bool(true)` whether the imsi is correct or not – Moeez Mar 10 '18 at 03:35
  • Also `$v` have imsi # – Moeez Mar 10 '18 at 03:37
  • that is strange can you add the model code for `SIM` how can it return true if the `imsi` is incorrect the record wont be found and the `->one()` returns `null` which will skip to the last statement `return false`. @MrFaisal – Muhammad Omer Aslam Mar 11 '18 at 03:46
  • i replaced the `find()->where()->one() ` with `findOne()` although it is just a short-hand but try once and confirm when the `imsi` is incorrect does it really returns true although it cant be, check if your column names are correct – Muhammad Omer Aslam Mar 11 '18 at 03:53
  • Now it's giving me `false` whether the `imsi` is correct or not. The field name is same for both models – Moeez Mar 12 '18 at 03:42
  • @MrOmer, I have added my `sim` model. – Moeez Mar 12 '18 at 03:48
  • this is strange ...? can you `var_dump()` inside the findModel and see what it prints against the `imsi` number searched @MrFaisal – Muhammad Omer Aslam Mar 12 '18 at 08:27
  • By doing ` var_dump($imsi); exit();` inside my `findImsi` function. The output I am getting is `string(18) "899204031015192577"` @MrOmer – Moeez Mar 12 '18 at 08:51
  • and what does the model info show does it show any record – Muhammad Omer Aslam Mar 12 '18 at 09:19
  • ` var_dump($model);` is giving me `NULL` – Moeez Mar 12 '18 at 09:42
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/166671/discussion-between-muhammad-omer-aslam-and-mr-faisal). @MrFaisal – Muhammad Omer Aslam Mar 12 '18 at 09:45
  • @MrOmer, My bad I was trying to upload excel file while I don't have anything in my master table so that's why I was getting `NULL` and `false`. But now I have inserted some data into my master table and then try to issue sims via excel file. Though it's returning me `true` but still it's not going inside `if ($imsiValid)`. Don't know why it's happening – Moeez Mar 13 '18 at 04:25
  • By checking `var_dump($imsiValid);` before the condition it's giving `bool(true)` but when I check same in `else` condition it's giving me `bool(false)`. It's very strange. – Moeez Mar 13 '18 at 04:31
  • how could this be is it has `true` it should go inside the if anyhow? – Muhammad Omer Aslam Mar 13 '18 at 09:42
  • That's where i am also confused – Moeez Mar 13 '18 at 10:40
  • you must be doing something wrong it doesnot work that way, look at all the values at the point when a imsi is available in the `fieldset` variable try `var_dump` with the `$fieldset` too to see what they are having otherwise if the value is Boolean true/false it should act accordingly if the value is `true` it will go inside `if` and if `false` thenit will go inside `else` and how come you are saying that it is not going inside the if have you tried to echo any string inside if – Muhammad Omer Aslam Mar 13 '18 at 10:45
  • Yes I have tried `echo` inside `if` but it's not going inside – Moeez Mar 13 '18 at 11:21
  • by `var_dump($fieldSet);` I got the following result `array(1) { [0]=> array(3) { ["imsi"]=> string(1) "A" ["issued_to"]=> string(1) "B" ["purpose"]=> string(1) "C" } }` – Moeez Mar 13 '18 at 11:23
  • how many records are there in `finaldata` array that you are iterating print_r and paste in question all resultset – Muhammad Omer Aslam Mar 13 '18 at 11:23
  • why are you using 2 foreach loops for the finaldata array there isnt any array inside the name=>value paris in the `finaldata` – Muhammad Omer Aslam Mar 13 '18 at 11:50
  • `$value` includes the data `array(3) { ["A"]=> string(18) "899204031015192575" ["B"]=> float(134) ["C"]=> string(20) "Production SIM Issue" }` – Moeez Mar 13 '18 at 14:14
  • @MrOmer, I have tried your updated code, I want to add something. Actually, I want to check 2 things `1`. The `SIM` be issued whether it is in the `sims` table `2`. That SIM should be already issued. – Moeez Mar 21 '18 at 03:47
  • For this, I have changed the `findImsi($imsi)` function a bit. `($model=Sims::find()->where(['imsi'=>$imsi])->andWhere(['status'=>'Inventory Stored SIM'])` The status `Inventory Stored SIM` is the initial status of the SIM and If any of the SIM is not in `sims` and not have `Inventory Stored SIM` status, then it won't be issued – Moeez Mar 21 '18 at 03:50
  • I tried to import `6` records out of them one IMSI # is not in the `sims` table. So whether the SIM status is `Inventory Stored SIM` or not the other `5` records are still issued again as I have already issued them. – Moeez Mar 21 '18 at 03:53
  • 1
    There was an issue in the `if` condition so I updated it `if(($model=Sims::find()->where(['imsi'=>$imsi])->andWhere(['status'=>'Inventory Stored SIM']) ->orWhere(['status'=>'SIM Returned'])->one())!== null)` and now all the things are working. Thank you for your help :) – Moeez Mar 21 '18 at 06:02