Manejo de suscripciones, saldos y cambios en el plan de precios [cerrado]

11

Preámbulo
Mi objetivo es crear código reutilizable para múltiples proyectos (y también publicarlo en github) para administrar suscripciones. Sé acerca de los proveedores de stripe y facturación recurrente, pero ese no es el objetivo de este módulo. Solo debe ser un contenedor / ayuda para calcular el saldo de la cuenta, notificaciones fáciles para renovar una suscripción y manejar los cálculos de precios.

Hay países en los que no puede utilizar la facturación recurrente debido a que los proveedores o las posibilidades de pago tienen poco o ningún soporte o son demasiado caros (micropagos). Y hay personas que no quieren usar la facturación recurrente, sino que pagan su factura manualmente / esperando una factura al final del año. Por lo tanto, no sugiera la facturación recurrente de PayPal, servicios recurrentes o similares.

Situación
Supongamos que tiene un modelo que puede suscribirse a un plan de suscripción (por ejemplo User). Este modelo tiene un campo que almacena el identificador de un plan de suscripción al que está suscrito actualmente. Entonces, en cada cambio de plan, se registra el cambio.

Hay un modelo (por ejemplo SubscriptionPlanChanges) con los siguientes campos que registran los cambios mencionados:

  • subscriberrelacionado con el modelo de suscripción ( Useren este caso)
  • from_plan Definir el identificador del plan que tenía el modelo antes del cambio
  • to_plan definiendo el identificador de plan que el modelo ha seleccionado ahora
  • created_at es un campo de fecha y hora que almacena el cambio
  • valid_until almacena la fecha hasta que la suscripción real sea válida
  • paid_at también es un campo de fecha y hora que define si (y cuándo) se pagó la suscripción

Por supuesto, ese diseño es discutible.

Pregunta sobre el saldo de la cuenta
Cuando un Usuario cambia su plan de suscripción, necesito comparar los campos del plan, obtener los precios y calcular la deducción para el nuevo plan en función del plan actual valid_untily su precio. Diga: Se suscribió por un año del plan A pero después de 6 meses, se actualiza al plan B, por lo que obtiene una deducción de la mitad del precio pagado por los 6 meses del plan A.

Lo que me pregunto: si un usuario, por ejemplo, cambia al plan gratuito, tiene un crédito que puede deducirse si el usuario desea cambiar nuevamente. ¿Guardaría ese valor en un campo adicional o calcularía todos los registros relacionados con ese usuario cada vez? ¿Agregarías / cambiarías algo sobre el diseño de la tabla?

Cuestión de fácil comprensión
Cuando llega el final de un período de suscripción, el usuario recibe una notificación y tiene la posibilidad de renovar su suscripción pagando nuevamente. La forma más fácil sería simplemente actualizar paid_aty valid_untilcon nuevas opciones de suscripción. Sin embargo, no estoy seguro de si almacena todos los datos que alguien pueda necesitar, como un historial de pagos / suscripciones.

Otra opción sería crear un registro adicional para esto, donde from_plany to_planestén teniendo el mismo identificador (simbolizando así "sin cambio"). ¿Pero eso no interferiría con el cálculo del saldo de la cuenta de alguna manera?

Si alguien pudiera señalarme en la dirección correcta sobre las lógicas que manejan tales suscripciones, lo agradecería mucho.


ACTUALIZACIÓN
Gracias por la ayuda por ahora. Creo que mi pregunta era demasiado vaga, así que intentaré ser más preciso usando menos abstracción. Desafortunadamente, no pude resolver mi problema todavía.

El caso A
User puede seleccionar Subscription Plan A. Actualmente almacena un SubscriptionPlanChangepara realizar un seguimiento. Después de, por ejemplo, 5 meses, Useractualiza su suscripción a Subscription Plan B. Entonces paga el precio de su nueva suscripción, deduciendo el precio del plan a por los 7 meses no utilizados.

Caso B
Después de 3 meses, Userregresa al suyo Subscription Plan A. No tiene que pagar, pero recibe un saldo para que, al final de la suscripción, obtenga ese saldo deducido por su nueva suscripción.

El Caso C
User puede seleccionar un plan de suscripción para un subservicio que tenga planes de suscripción independientes. Lo mismo Case Ay Case Bpuede solicitar esa suscripción de sub-servicio.

_Case D_ El usuario cancela una de sus suscripciones. Esto resulta en una recarga de su saldo.

Mi pregunta (actualmente, al menos) depende principalmente de cómo almacenar esos datos correctamente para poder reproducir un historial de suscripciones para análisis de negocios y calcular saldos, obtener pagos pendientes basados ​​en las suscripciones, etc.

Tampoco estoy seguro de si la balanza debe almacenarse, por ejemplo, en el modelo del usuario, o si no está almacenada, pero puede calcularse en cualquier momento en función de los datos / historial almacenados.

Algunas cosas a tener en cuenta, aunque no creo que deban introducir problemas:

  • No tiene que ser un User, podría ser cualquier cosa, es por eso que Subscriberes polimórfico
  • Plansno necesariamente tiene que ser un plan, pero podría ser, por ejemplo, Magazinescomo se menciona. Eso es lo que he descrito con el asunto C y Caso D .
pduersteler
fuente
1
Una cosa que sin duda podría hacer sería asignar un precio a cada emisión (que puede depender del plan de manera que la combinación [plan, emisión] se asigne a [precio de emisión]), y luego simplemente realizar un seguimiento del saldo de cada suscriptor por revista (o la terminología que prefiera).
un CVn
Gracias a todos, necesitaba actualizar la pregunta porque aún no podía resolver mi problema.
pduersteler
1
¿Puedo preguntar cómo terminaste implementando esto?
JCM

Respuestas:

6

Lamentablemente, la respuesta a un problema complicado suele ser complicada. Mi consejo para usted sería guardar solo la información relevante, luego usar un modelo para construir una imagen más grande.

En otras palabras, su tabla SubscriptionPlanChanges tendría la siguiente información para su clave:

  • abonado
  • plan
  • válida desde

De esta manera, permite múltiples planes para el mismo suscriptor que pueden superponerse. Otros campos incluyen:

  • válido hasta
  • pagado hasta
  • tasa (también 0 si es gratis)

Tenga en cuenta que no hay un "plan de" o "plan de". Aunque podría tenerlos, la información es superflua y puede calcularse por su cuenta (almacenar dicha información significa que tiene la tarea adicional de mantenerla consistente). Cuando comienza un nuevo plan, en lugar de tener que modificar los planes existentes, los deja y simplemente agrega un nuevo registro. Si existe otro plan superpuesto después del nuevo plan nuevo, puede decidir que desea eliminarlo (más intuitivo de esta manera). Cuando carga estos planes para un suscriptor, los ordena por su fecha "válida desde".

Una vez que obtenga esto, calcular el crédito de un usuario es relativamente simple. Si dos planes no pueden superponerse, simplemente tome la menor de dos fechas entre la fecha "válida hasta" del plan anterior y la "válida desde" del plan actual para determinar la fecha de finalización. La fecha de inicio es la mayor de las dos fechas entre la fecha "válida desde" y la fecha "pagado hasta" (si está definida). El pago (o crédito) se puede calcular sobre la tasa multiplicada por el intervalo de tiempo entre las fechas de inicio y finalización mencionadas anteriormente de ese plan.

De esta manera, en teoría puedes calcular lo que necesites saber. Aconsejaría que no intente guardar los valores calculados, ya que cambiaría cuando se modifique, agregue o elimine un registro existente.

Las variaciones de cómo calcularía estos valores se pueden administrar agregando un campo de tipo adicional. En su código, puede crear controladores especiales para administrar la lógica de cálculo de planes particulares a fin de mantener su algoritmo principal relativamente libre de cálculos complicados. Mejor aún si logra crear un controlador para el caso en el que no se especifica ningún tipo, por lo que todo lo que tiene que hacer es llamar al controlador apropiado de acuerdo con su tipo para realizar cualquier tipo de cálculo que necesite.

Espero haber respondido a tu pregunta.

Neil
fuente
Muchas gracias, que arrojan algo de luz! Aunque siento que no estaba claro sobre el campo "válido". valid_untilfue mi terminología tuya paid_until. No hay una longitud máxima de un plan para suscribirse.
pduersteler
@pduersteler Ah, mi error, entonces. Eso solo hace el cálculo mucho más fácil, ya que la fecha de "finalización" es solo el comienzo del nuevo plan.
Neil
1
Tasa es la cantidad pagada? En caso afirmativo, esta podría ser otra entidad, una factura, por ejemplo, ¿estoy en lo cierto?
JCM
3

Además de la respuesta anterior, crearía una tabla con créditos, donde un crédito sería igual a la moneda actual. Cada vez que el usuario cambia de plan a una alternativa más barata, el saldo no utilizado ingresa como créditos. Siempre que el usuario tenga algo que pagar, primero usará los créditos y solo solicitará el pago si los créditos se agotan o no existen. Si usa esta alternativa, cree la tabla como una lista de transacciones para poder reproducir el escenario de uso si alguna vez se produce una disputa. Ejemplo:

ID, UserId, TransactionDate, Credit (positivo cuando le da créditos al usuario y negativo cuando el usuario usa el crédito)

Simplemente sume los créditos para que el usuario le muestre el saldo.

Espero que esto sea de alguna utilidad para ti ...

Lars Hofvander
fuente