public function createOrUpdate(
        $code,
        $title,
        array $effects,
        $type,
        $isRemovingPostage,
        $shortDescription,
        $description,
        $isEnabled,
        $expirationDate,
        $isAvailableOnSpecialOffers,
        $isCumulative,
        $maxUsage,
        $defaultSerializedRule,
        $locale,
        $freeShippingForCountries,
        $freeShippingForMethods,
        $perCustomerUsageCount,
        $startDate = null
    ) {
        $con = Propel::getWriteConnection(CouponTableMap::DATABASE_NAME);

        $con->beginTransaction();

        try {
            $this
                ->setCode($code)
                ->setType($type)
                ->setEffects($effects)
                ->setIsRemovingPostage($isRemovingPostage)
                ->setIsEnabled($isEnabled)
                ->setStartDate($startDate)
                ->setExpirationDate($expirationDate)
                ->setIsAvailableOnSpecialOffers($isAvailableOnSpecialOffers)
                ->setIsCumulative($isCumulative)
                ->setMaxUsage($maxUsage)
                ->setPerCustomerUsageCount($perCustomerUsageCount)
                ->setLocale($locale)
                ->setTitle($title)
                ->setShortDescription($shortDescription)
                ->setDescription($description)
            ;

            // If no rule given, set default rule
            if (null === $this->getSerializedConditions()) {
                $this->setSerializedConditions($defaultSerializedRule);
            }

            $this->save();

            // Update countries and modules relation for free shipping
            CouponCountryQuery::create()->filterByCouponId($this->id)->delete();
            CouponModuleQuery::create()->filterByCouponId($this->id)->delete();

            foreach ($freeShippingForCountries as $countryId) {
                if ($countryId <= 0) {
                    continue;
                }

                $couponCountry = new CouponCountry();

                $couponCountry
                    ->setCouponId($this->getId())
                    ->setCountryId($countryId)
                    ->save();
                ;
            }

            foreach ($freeShippingForMethods as $moduleId) {
                if ($moduleId <= 0) {
                    continue;
                }

                $couponModule = new CouponModule();

                $couponModule
                    ->setCouponId($this->getId())
                    ->setModuleId($moduleId)
                    ->save()
                ;
            }

            $con->commit();
        } catch (\Exception $ex) {
            $con->rollback();

            throw $ex;
        }
    }