deman4ik / cpz_web

0 stars 0 forks source link

Billing #554

Closed deman4ik closed 3 years ago

deman4ik commented 3 years ago

На бэкенде пока не до конца все готово и будут вводиться изменения, но пока ориентируемся на то что есть.

Прием платежей мы будем внедрять с помощью https://commerce.coinbase.com/ Документация https://commerce.coinbase.com/docs/ Документация API https://commerce.coinbase.com/docs/api/#introduction

Тарифные планы (в месяц): FREE - торговые сигналы 15$ - 3 автоматических робота 30$ - 10 роботов 50$ - неограниченное количество роботов

Скидки и бонусы: -20% - при оплате 6 месяцев -30% - при оплате 1 года -50% - при оплате 2 лет

В graphql схеме это реализовано с помощью трех основных таблиц

Поля можно посмотреть в схеме или вот предварительно такая типизация на бэкенде (тут используется camelCase)

import { UnitType } from "@cryptuoso/dayjs";
import { resources } from "coinbase-commerce-node";

export type SubscriptionOptionKey = "1m" | "6m" | "1y" | "2y";

export interface SubscriptionOption {
    price: number;
    discount: number;
    amount: number;
    unit: UnitType;
}

export interface SubscriptionLimits {
    trialNetProfit?: number;
    maxRobots?: number;
}

export interface Subscription {
    id?: string;
    name: string;
    available: number;
    description?: string;
    options: {
        [key: string]: SubscriptionOption;
    };
    limits?: SubscriptionLimits;
}

export interface UserSub {
    id: string;
    userId: string;
    subscriptionId: string;
    subscriptionOption: SubscriptionOptionKey;
    status: "active" | "trial" | "expired" | "pending" | "canceled";
    activeFrom?: string;
    activeTo?: string;
    trialStarted?: string;
    trialEnded?: string;
    data?: { [key: string]: any };
    subscription?: Subscription;
    payments?: UserPayment[];
}

export interface UserPayment {
    id: string;
    userId: string;
    userSubId: string;
    provider: "coinbase.commerce";
    code: string;
    status: "NEW" | "PENDING" | "COMPLETED" | "UNRESOLVED" | "RESOLVED" | "EXPIRED" | "CANCELED";
    price: number;
    createdAt: string;
    expiresAt?: string;
    addresses?: resources.Charge["addresses"];
    exchangeRates?: { [key: string]: string };
    pricing?: resources.Charge["pricing"];
    info?: resources.Charge;
}

Также будут доступны следующие мутации:

Первый этап - оформление подписки

  1. При добавлении робота на страницах /robots/search и /robots/robot перед открытием формы добавления (или как дополнительный первый шаг самой формы) необходимо проверять есть ли у пользователя какая либо подписка - пока просто запрос к user_subs по user_id
  2. Если подписка есть - продолжаем дальше выбор API ключа, ввод торгового объема...
  3. Если же подписки нет, то по аналогии с лендингом необходимо отобразить список доступных тарифных планов построив запрос к subscriptions.
  4. Вывести name, description и цены из options. Где хранится объект с различными ценами за разные периоды.
  5. Пользователь выбирает период и тарифный план.
  6. В зависимости от его выбора отправляется мутация createUserSub где subscriptionId это id строки подписки из таблицы subscriptions, а subscriptionOption это ключ из объекта options указывающий на период подписки. Например 1y
deman4ik commented 3 years ago

Поменялся принцип тарифов и способ хранения информации Принято решение предоставлять единый тариф со всем доступным функционалом и стараться замотивировать пользователя на длительную подписку. Поэтому в subscriptions хранятся базовые тарифы - сейчас там 1 тариф с автоматическими торговыми роботами и в дальнейшем появится другой с дополнительным функционалом в виде портфелей роботов. Колонка options переехала в отдельную таблицу subscription_options

    code -- кодовое обозначение времени подписки  "1m" | "6m" | "1y"
    subscription_id -- id подписки из subscriptions
    name -- имя опции (по сути имя тарифного плана)
    description -- дополнительное описание опции (например 1 месяц бесплатно)
    sort_order -- порядок сортировки при отображении
    price_month -- цена в месяц
    price_total -- цена за весь период
    discount -- скидка в %
    highlight -- признак выделения именно этой опции для привлечения внимания
    amount -- количество времени подписки в ед. измерения
    unit -- ед. измерения подписка "month" | "year" |
    available -- ограничение прав доступа

Поэтому нужно внести следующие изменения:

deman4ik commented 3 years ago
deman4ik commented 3 years ago

Страница Profile

3 кнопки в линию Change plan - dimmed - иконка шестеренка, Pay - primary - иконка mdiBitcoin, Cancel - dimmed - иконка крестик

По стилистике ориентируемся на карточку My Exchange API Keys

Новая страница Subscription History

/profile/subscription-history

Выводится вся доступная информация из user_subs с отбором по user_id + по связям user_payments По стилистике ориентируемся на страницы /open-positions/

deman4ik commented 3 years ago

Status: Active

кнопкаSTART FREE TRIAL - primary - открывает форму выбора тарифного плана.


Когда тарифный план уже выбран:

krupibox commented 3 years ago
  • user_payments массив выводится пустой, мой запрос по связям неверный?
deman4ik commented 3 years ago

нужно создать платеж через checkoutUserSub

deman4ik commented 3 years ago

Choose Plan

Cryptuoso Subscription

Checkout

Notifications

Добавляется 3 новых типа нотификаций, которые нужно правильно вывести на странице /notifications пока в упрощенном варианте вот так:

krupibox commented 3 years ago
* A.  Если тариф еще не выбран кнопку у который признак `subscription_options.highlight === true` сделать нажатой по умолчанию
* B.  Если тариф уже выбран нажатой по умолчанию делать кнопку с текущей опцией
  1. image

Речь идет о кнопках 1 или 2 ? Если об 1, то нужна ли 2?

  1. Когда тарифный план еще не выбран, по какому полю смотреть условие? Например в user_subs.status - если "trial", то тариф не выбран, "active"- выбран

или

name -- имя опции (по сути имя тарифного плана)

Если в user_subs.subscriptionOption.name указано имя, то тарифный план выбран, а если нет, то что поле содержит?

или

в user_subs.subscriptionOption.subscription.name - указан TRADER PLAN - тариф выбран, FREE PLAN - тариф не выбран?

  1. Карточка на скриншоте похожа на то что планировалось сделать в первую очередь?
deman4ik commented 3 years ago
  1. Речь идет о 1ой группе кнопок. Условия по кнопке subscribe я пропишу позже, пока оставляем всегда доступной
  2. user_subs.subscription_option определяет выбранную по умолчанию кнопку
  3. Да, вопрос к description. В базе хранится с переносом строк ‘/n’, хотелось бы и тут их применить
deman4ik commented 3 years ago

Тарифные планы

Мобильные экраны

krupibox commented 3 years ago

Адаптация для мобильных завтра.

https://user-images.githubusercontent.com/46923587/108552431-5a79e980-7302-11eb-9813-bc783aedfd8c.mov

deman4ik commented 3 years ago
krupibox commented 3 years ago

как определить что тарифный план еще не выбран?