remp/crm-upgrades-module

3.4.0 2024-08-12 12:46 UTC

README

Translation status @ Weblate

模块提供了一种升级用户订阅的方法。它利用当前的订阅价格、目标订阅价格和用户订阅剩余的天数来计算“信用”,用于提供不同的升级方式。

安装

我们推荐使用Composer进行安装和更新管理。要将CRM升级扩展添加到您的REMP CRM应用程序,请使用以下命令

composer require remp/crm-upgrades-module

在您的app/config/config.neon文件中启用已安装的扩展

extensions:
	# ...
	- Crm\UpgradesModule\DI\UpgradesModuleExtension

配置

先决条件

升级需要您为每种内容访问和订阅长度的组合配置默认订阅类型。这样模块就知道,如果您想升级到具有内容访问content_access_AA的订阅类型,它是默认的。

该设置在UI中不可用,因此您需要手动设置。您可以使用以下片段来确保每个内容访问/长度组合只有一个默认订阅类型。

验证片段
private function validateDefaultSubscriptionTypes()
{
    $defaultSubscriptionTypes = $this->subscriptionTypesRepository->getTable()
        ->where(['default' => true])
        ->fetchAll();

    $contentAccessCheck = [];
    foreach ($defaultSubscriptionTypes as $subscriptionType) {
        $contentAccess = [];
        foreach ($subscriptionType->related('subscription_type_content_access') as $stca) {
            $contentAccess[$stca->content_access->name] = $stca->content_access->name;
        }
        sort($contentAccess);
        $hash = md5(implode('', $contentAccess) . $subscriptionType->length);
        $contentAccessCheck[$hash][] = $subscriptionType->code;
    }

    $duplicates = [];
    foreach ($contentAccessCheck as $hash => $subscriptionTypes) {
        if (count($subscriptionTypes) > 1) {
            $duplicates[] = $subscriptionTypes;
        }
    }
    return $duplicates;
}

或者,您可以在upgrade_options.subscription_type列中显式设置目标订阅类型,但这会导致大量重复,通常不建议这样做。

升级器

模块目前提供4个默认升级器供使用

  • paid_recurrent。计算用户升级到更好的订阅所需支付的费用,而不会更改账单周期。费用直接收取。
  • free_recurrent。更改周期性支付上配置的订阅类型。在升级时免费,下一个账单周期将收取更高金额的费用。
  • paid_extend。计算全新订阅的折扣。忽略原始订阅的结束时间,原始订阅被停止,剩余天数作为信用来折扣升级的订阅价格。
  • short。计算用户可用的信用,并使用它来计算用户可以获得的更高级别订阅的天数。升级“缩短”原始订阅并升级它。

您可以通过遵循Crm\UpgradesModule\Upgrade\UpgraderInterface并然后在应用程序配置中注册它来实现自己的升级器

services:
	upgraderFactory:
		setup:
			- registerUpgrader(\Crm\FooModule\Models\Upgrades\FooUpgrade())

后续升级

CRM 提供了支持按照当前已升级的订阅进行升级的订阅。后续升级允许升级具有以下条件的订阅

  • 在升级之前与原始订阅具有相同的订阅类型。
  • 在升级后与订阅具有相同的订阅类型。

后续升级目前不支持跨订阅类型升级。这意味着,如果用户有一个月度订阅,接着是年度订阅,那么年度订阅仍然不会被升级。

此功能仍然是实验性的,默认情况下已禁用。要启用它,请在您的配置中添加以下内容

services:
	upgraderFactory:
		setup:
			- setSubsequentUpgrader(\Crm\UpgradesModule\Upgrade\ShortUpgrade())

此配置表示,为了执行后续升级,CRM应使用short升级器。即使用户使用paid_recurrent升级来执行实际升级,所有后续的订阅都将缩短。这是为了简化流程并提供通用的后续升级方式。

升级场景

目前CRM管理员中没有用于配置升级的UI。您需要从您内部模块中设置您的配置。

升级选项

选项定义了哪些升级器可以用于哪些基于内容访问的升级类型。两个重要的列是

  • type。这引用了UpgraderInterface::getType()的返回值。
  • config。定义升级条件的对象(下面描述)。
    {
      /*
       * Required. Array of strings. Content access you want to upgrade to. UpgradesModule will search for the default
       * subscription type with the same length, and content access of:
       *
       *   - currently active subscription type, and
       *   - content_access_CC (or whatever is set within "require_content" property
       * 
       * When module finds all available options, it calculates profitability of upgrade to each one of them. The most
       * profitable is offered to user as an option to upgrade.
       */
      "require_content": ["content_access_CC"],
    
      /*
       * Optional. Array of strings. Content access you don't want to upgrade to. UpgradesModule will find the default
       * subscription type with the same length, and content access defined by the "require_content" property, but
       * without ones defined within this property ("content_access_BB").
       * 
       * Since upgrades module always tries to find subscription types with the same content access (plus the ones required)
       * as the current subscription, you can use this property to achieve following:
       *
       *   - Current subscription content access: ["content_access_AA, "content_access_BB"]
       *   - Content access we want to upgrade to: ["content_access_AA", "content_access_CC"]
       */
      "omit_content": ["content_access_BB"],
    
      /*
       * Optional. Number. Defines fixed amount of monthly price raise. By default the module uses price of the target
       * subscription type as a variable for calculations. You can override that and set a monthly fixed raise of price
       * instead. If user is paying 10eur/month and want's to upgrade to 20eur/month subscription, this setting would
       * force all calculations to "see" that the price of upgraded subscription type is 15eur/month (10+5), not 20eur.
       */  
      "monthly_fix": 5,
    
      /*
       * Optional. Some upgrade options (like the one with "monthly_fix") probably shouldn't be available for everyone.
       * You may enforce the limitation by requiring special tags at the landing page for this special offer.
       * The upgrade option will only be available if you request the list of available upgraders with this special tag:
       *
       *   $this->availableUpgraders->all($this->getUser()->id, $contentAccess, ["foo"]);
       */
      "require_tags": ["foo"]
    }

升级方案

方案只有一个目的:将多个升级选项逻辑地组合在一起。

模块需要将每种订阅类型与其可以使用的升级选项相关联。为了避免将每种订阅类型与N个升级选项相关联,选项被分组在方案中,订阅类型被链接到该单个方案。

链接在subscription_type_upgrade_schemas表中创建,并且需要为每个想要升级的订阅类型明确定义。

示例

如果您想通过缩短订阅来允许升级到内容访问foo,您会

  • 插入新的upgrade_option记录,带有以下值
    • type: short
    • config: {"require_content": ["foo"]}
  • 将其链接到某个upgrade_schema记录。
  • 将所有想要允许升级的订阅类型链接到这个upgrade_schema记录。
  • 确保对于每种订阅类型的标准长度,都有一个具有内容访问foo的单个订阅类型。

使用模块

模块有一个默认的表示层,在:Upgrades:Upgrade:default路由中显示当前登录用户可用的所有默认升级场景。

由于使用了require_tags配置选项,建议为特殊优惠升级实现自定义的表示层。