[Solved] Save In Aftersave()

My situation is like this, I have a master detail relation on Sales and SalesDetail. Where Sales store info about date, customer name and so on and SalesDetail store info about quantity, product and unitPrice + discount, also isPrintable field to distinguish that this line will be printed or not (it is there for simplify the stock calculation).

The product can be virtual or physical. If physical then we just add that detail with isPrintable = 1 but if it is virtual, I add the virtual product with isPrintable = 1, also all the members ( I have MemberProduct table to store if the product is virtual then, it consists of which physical product) with the isPrintable = 0.

Create new detail is ok since I can just put a database transaction in one transaction to save the the virtual product and physical products member.

On delete is also easy since I can just deleteAll

But, I have a problem in update. I tried to use afterSave() but always do nothing (seems error in the save() line_




protected function afterSave() {

        if ($this->product->type == Product::VIRTUAL) {

            $criteria = new CDbCriteria;

            $criteria->condition = 'salesFk = :salesFk AND parentProduct = :pProd';

            $criteria->params = array(':salesFk' => $this->salesFk, ':pProd' => $this->productFk);

            

            $children = SalesDetail::model()->findAll($criteria);

            $memo = "";

            foreach ($children as $child) {

                $memo .= $child->id . " ";

            }

            

            $this->memoLine = $memo;

            $this->save();

        }


        parent::afterSave();

    }



Anyone can help?

Thanks in advance.

try this




$this->save(false);



i am not sure it’s work or not…

What you mean by this

You are getting any specific exception there or you want to say your afterSave() method was not executed here. ??

Yes,

A SalesDetail object can have either virtual or physical product. Whenever I save a virtual product, I want to update some value of the correspond physical product. My solution to this is to use an afterSave() method. However, the code failed to update any record:




protected function afterSave() {

        if ($this->product->type == Product::VIRTUAL) {

            $criteria = new CDbCriteria;

            $criteria->condition = 'salesFk = :salesFk AND parentProduct = :pProd';

            $criteria->params = array(':salesFk' => $this->salesFk, ':pProd' => $this->productFk);

            

            $children = SalesDetail::model()->findAll($criteria);

            $memo = "";

            foreach ($children as $child) {

                $memo .= $child->id . " ";

            }

            

            $this->memoLine = $memo;

            $this->save();  // <- not save the row, it gave an error message

        }


        parent::afterSave();

    }



Any help?

Pls try print_r($this->getErrors()); after save() function to get error.

Doesn’t calling ->save() within the afterSave() recall the afterSave() again?

Anyway…

Instead of


$this->save();

try


$this->updateAttribute('memoLine', $memo);

I might also move parent::afterSave(); to start of the function, but I’m still confussed about these parent::… calls :)

seems like an endless loop

save() calls afterSave(), which calls save()?

Thanks a lot to all of you.

I fixed it as your suggestions and now it is work




public function afterSave() {

        parent::afterSave();


        if ($this->product->type == Product::VIRTUAL) {

            $criteria = new CDbCriteria;

            $criteria->condition = 'salesFk = :salesFk AND parentProduct = :pProd AND productFk <> :prodFk';

            $criteria->params = array(':salesFk' => $this->salesFk, ':pProd' => $this->productFk, ':prodFk' => $this->productFk);


            $children = SalesDetail::model()->findAll($criteria);

            foreach ($children as $child) {

                $child->unitPrice = is_nan($this->unitPrice / $child->quantity) ? 0 : $this->unitPrice / $child->quantity;

                $child->discOne = $this->discOne * 100;

                $child->discTwo = $this->discTwo * 100;

                $child->discThree = $this->discThree * 100;

                

                $child->save(false);

            }

        }

    }



I do apologise that in the beginning of this thread, I put the testing code, not the actual code. Above is the actual code.

It does not loop forever since the children is product with type physical, so the if clause will not let them in.

Once again, thanks a lot to all of you.