Search code examples
modelcontrolleryii2yii2-advanced-appyii2-model

Yii2 - Updating single field of another model from update form


Longtime passive user of StackExchange and I am at a loss here. It's probably super simple, but I'm stuck. I've used gii-enhanced to build the models and CRUD.

  • I have two models: ordenes and facturas.

  • When I'm updating a facturas model I can link it to an already existing ordenes model.

  • A facturas model can be linked to an ordenes model.

  • Ordenes has an amount field and so does facturas.

What I currently have: I can link a facturas model to an already existing ordenes model. One facturas model can have only one ordenes model, while an ordenes model can have more than one facturas model linked to it.

What I'd like to achieve is that when I link a facturas model to an ordenes model the amount from the facturas model is subtracted from the amount of the ordenes model and the new value saved to the ordenes table. So, if I already have a ordenes model with an amount of, say $200000, and link to it a facturas model with an amount of $150000, the updated ordenes model should have an amount of $50000.

The relevant code in facturasController:

public function actionUpdate($id)
    {
        $model = $this->findModel($id);

        if ($model->loadAll(Yii::$app->request->post()) && $model->saveAll()) {
            return $this->redirect(['view', 'id' => $model->idfacturas]);
        } else {
            return $this->render('update', [
                'model' => $model,
            ]);
        }
    }

The relevant field in the view:

<?= $form->field($model, 'ordenes_idordenes')->widget(\kartik\widgets\Select2::classname(), [
        'data' => \yii\helpers\ArrayHelper::map(\frontend\models\Ordenes::find()->orderBy('idordenes')->asArray()->all(), 'idordenes', 'numero'),
        'options' => ['placeholder' => Yii::t('app', 'Vincular Orden de Compra')],
        'pluginOptions' => [
            'allowClear' => true
        ],
    ]); ?>

The relevant parts of the facturas Model:

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getOrdenesIdordenes()
    {
        return $this->hasOne(\frontend\models\Ordenes::className(), ['idordenes' => 'ordenes_idordenes'])->inverseOf('facturas');
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getProveedoresIdproveedores()
    {
        return $this->hasOne(\frontend\models\Proveedores::className(), ['idproveedores' => 'proveedores_idproveedores'])->inverseOf('facturas');
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    /*public function getUserIduser()
    {
        return $this->hasOne(\frontend\models\User::className(), ['id' => 'user_iduser'])->inverseOf('facturas');
    }*/
    public function getUserIduser()
    {
        return $this->hasOne(\backend\models\User::className(), ['id' => 'user_iduser'])->inverseOf('facturas');
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getOrdenes()
    {
        return $this->hasMany(\frontend\models\Ordenes::className(), ['facturas_idfacturas' => 'idfacturas'])->inverseOf('facturasIdfacturas');
    }

     /**
    * @return \yii\db\ActiveQuery
    */
   public function getEstadosContab()
   {
       return $this->hasOne(\frontend\models\EstadosContab::className(), ['idcontab' => 'estados_contab'])->inverseOf('facturas');
   }

/**
     * @inheritdoc
     * @return array mixed
     */ 
    public function behaviors()
    {
        return [
            'blameable' => [
                'class' => BlameableBehavior::className(),
                'createdByAttribute' => 'user_crea',
                'updatedByAttribute' => 'user_modif',
            ],
            'uuid' => [
                'class' => UUIDBehavior::className(),
                'column' => 'idfacturas',
            ],
        ];
    }

    /**
     * @inheritdoc
     * @return \frontend\models\FacturasQuery the active query used by this AR class.
     */
    public static function find()
    {
        return new \frontend\models\FacturasQuery(get_called_class());
    }
}

And the relevant parts of the Ordenes Model:

 /**
     * @return \yii\db\ActiveQuery
     */
    public function getFacturas()
    {
        return $this->hasMany(\frontend\models\Facturas::className(), ['ordenes_idordenes' => 'idordenes'])->inverseOf('ordenesIdordenes');
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getNotas()
    {
        return $this->hasMany(\frontend\models\Notas::className(), ['ordenes_idordenes' => 'idordenes'])->inverseOf('ordenesIdordenes');
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getEstado()
    {
        return $this->hasOne(\frontend\models\Estados::className(), ['idestados' => 'estado_id'])->inverseOf('ordenes');
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getNotasIdnotas()
    {
        return $this->hasOne(\frontend\models\Notas::className(), ['idnotas' => 'notas_idnotas'])->inverseOf('ordenes');
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getFacturasIdfacturas()
    {
        return $this->hasOne(\frontend\models\Facturas::className(), ['idfacturas' => 'facturas_idfacturas'])->inverseOf('ordenes');
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getProveedoresIdproveedores()
    {
        return $this->hasOne(\frontend\models\Proveedores::className(), ['idproveedores' => 'proveedores_idproveedores'])->inverseOf('ordenes');
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getTipocompra()
    {
        return $this->hasOne(\frontend\models\TipoCompra::className(), ['category_id' => 'tipocompra_id'])->inverseOf('ordenes');
    }

/**
     * @inheritdoc
     * @return array mixed
     */ 
    public function behaviors()
    {
        return [
            'blameable' => [
                'class' => BlameableBehavior::className(),
                'createdByAttribute' => 'created_by',
                'updatedByAttribute' => 'updated_by',
            ],
            'uuid' => [
                'class' => UUIDBehavior::className(),
                'column' => 'idordenes',
            ],
        ];
    }

    /**
     * @inheritdoc
     * @return \frontend\models\OrdenesQuery the active query used by this AR class.
     */
    public static function find()
    {
        return new \frontend\models\OrdenesQuery(get_called_class());
    }
}

Solution

  • This is just a suggestion
    you should populate model Facturas retriving the facturas related to this orders and then assign properly the value you need to the facturas model

    use common\models\Facturas;
    
    public function actionUpdate($id)
        {
            $model = $this->findModel($id);
    
    
            if ($model->loadAll(Yii::$app->request->post()){
               $modelFacturas = Facturas::find()
                 ->(['your_id_fatcuras' => $model->your_id_facturas ])->one();
               $modelFacturas->you_field_to_change =  $model->value1 - $modelFacturas->value2;
               $model->save();
               $modelFacturas->save();
    
               return $this->redirect(['view', 'id' => $model->idfacturas]);
            } else {
                return $this->render('update', [
                    'model' => $model,
                ]);
            }
        }
    

    based on your last comment this could be a more precise answer to your question

    Assuming you Orders Model is name Orders and in Facturas you have a field named fk_orders where you pass the value selectd by user in the view and that can link the related order

    Then in Facturas Controller you can

    use common\models\Orders;
    
    public function actionUpdate($id)
        {
            $model = $this->findModel($id); // retrive the Factursa model
    
    
            if ($model->loadAll(Yii::$app->request->post()){
               $modelOrders = Orders::find()
                 ->(['id_orders' => $model->fk_orders ])->one();
               $modelOrders->amount  =  $modelOrders->amount - $model->value_to_subtract;
               $model->save();
               $modelOrders->save();
    
               return $this->redirect(['view', 'id' => $model->idfacturas]);
            } else {
                return $this->render('update', [
                    'model' => $model,
                ]);
            }
        }