This heavily depends on Ubercart. We could use another solution and we need to abstract away the quota system (see #533330: Quota API for that) but basically, Ubercart is the cleanest solution we have found and we have had multiple discussions with the UC folks so we're likely to go that way.

In a sense, most of the logic will therefore be in Ubercart more than Aegir, but I'm writing this down here anyways to keep track of it somewhere.

Comments

anarcat’s picture

19:14:55 <@anarcat> mikejoconnor: basically, we'll need UC support to be generic enough so that people can be billed on different packages, both in terms of bandwidth, disk space, number of sites, which profiles/platforms available, etfc
19:15:15 <@anarcat> mikejoconnor: basically, UC would become one implementation of our quota system (which has yet to be written)
19:15:35 <@anarcat> http://drupal.org/node/533330
19:15:39 <mikejoconnor> anarcat: so basically we need to associate recurring, with quota's
19:15:45 <@Vertice> yeah
19:15:50 <@Vertice> also. aegir has the concept of clients
19:15:56 <@anarcat> which are nodes
19:16:04 <@anarcat> to which users are connected, through an ACL system
19:17:03 <mikejoconnor> anarcat: how long before you have a working quota system?
19:17:29 <@anarcat> mikejoconnor: the issue above has a pretty good basis for discussion, but not much more... short answer: i don't know
19:17:47 <@anarcat> mikejoconnor: kind of chicken and egg here: i'm not sure how far we can go without knowing how UC works
19:27:26 <mikejoconnor> anarcat: I think it might be semi-simple.  Here's how I think it would work out of the box.  1. we have a quota module, which keeps track of stats per site node.  2. we have a client(already supported?)
19:27:30 <mikejoconnor> is a client a node?
19:27:37 <@anarcat> i have a "Drupal" package with attributes like "Type (aquia, managing news, open atrium, ubercart)", "Bandwidth (500G, 1TB, etc)", "Disk space (...)", "Number of allowed sites (N)" that would affect pricing
19:27:41 <@anarcat> mikejoconnor: yes, a client is a node
19:28:09 <mikejoconnor> anarcat: would you be selling client types, or would you be selling sites?
19:28:17 <@anarcat> we would be selling site packages
19:28:24 <@anarcat> like "you are allowed to have N sites"
19:28:38 <@anarcat> and "you have 500GB bandwidth in your monthly quota for all your sites"
19:28:44 <@anarcat> we could also have quotas like "N domains"
19:28:52 <@anarcat> or "N email addrs"
19:28:54 <mikejoconnor> anarcat: so what we need to do is add support to uc_recurring, to do grouping by customer
19:29:05 <@anarcat> ah
19:29:06 <mikejoconnor> and add prorated support
19:29:16 <@anarcat> i don't actually know what that means :)
19:29:20 <@anarcat> but i kinda guess
19:29:24 <@anarcat> as for quotas
19:30:00 <@anarcat> we need to have a separate "statistics" module that would collect stats from various sources (disk quotas, logfiles, aegir database counters, etc) and then the quota module would compare that with
19:30:14 <@anarcat> either hardcoded quotas or quotas "bought" by the user through ubercart (if that is installed)
19:30:15 <mikejoconnor> currently, as far as I know, recurring works per order. We don't want to charge a customer 42 separate transactions if they have 42 sites
19:30:23 <@anarcat> that's the basis of my quota spec, the way i see it
19:30:32 <psynaptic> we need to be able to sell single sites, just thought I'd mention that
19:30:46 <@anarcat> psynaptic: that's easy: it's a "one site package"
19:30:53 <psynaptic> cool
19:31:08 <@anarcat> mikejoconnor: basically, if a user has 42 sites, he needs the "50 sites" package
19:31:11 <@anarcat> that costs X$
19:31:19 <@anarcat> the issue is how to switch packages
19:32:09 <mikejoconnor> so the idea is you would sell a site, and it would add it to the users subscription list, and bill them a prorated amount when they add the new site.  At the end of the billing cycle, it looks at all the sites they have ordered, and does one order, with a line item for the cost of reach site they ordered, and does one transaction
19:32:13 <@Vertice> the immaturity of uc_recurring is what stopped us before
19:32:40 <@Vertice> mikejoconnor: that's basically how it needs to work
19:32:42 <mikejoconnor> Vertice: we moved uc_recurring out of core so it could mature a bit faster
19:32:46 <@Vertice> yeah
19:32:49 <@Vertice> good stuff
19:32:49 <@Vertice> =)
19:33:00 <@anarcat> what is the "users subscription list"?
19:33:09 <@anarcat> but yeah, i think it makes sense
19:33:27 <mikejoconnor> anarcat: something that doesn't exist right now, but should
19:33:29 <psynaptic> well, this is the bit that needs creating to make it all work
19:33:49 <@anarcat> sell one to N site, then add billing if site usage (M) goes beyond N then at the end of the billing cycle, consolidate on M sites
19:34:17 <@anarcat> i'm not sure i understand the users subscription list concept
19:34:22 <@anarcat> would it sit in UC or aegir?
19:34:26 <mikejoconnor> anarcat: in ubercart
19:34:29 <@anarcat> i see
19:34:42 <@anarcat> 19:33:49 <@anarcat> sell one to N site, then add billing if site usage (M) goes beyond N then at the end of the billing cycle, consolidate on M sites
19:34:52 <@anarcat> site can also be bandwidth, disk space, emails, etc
19:35:01 <mikejoconnor> basically a subscription list would integrate into uc_recurring, basically grouping all of your monthly subscriptions into one transaction
19:35:15 <@anarcat> oh i see
19:35:18 <mikejoconnor> anarcat: so then the uc/aegir integration would be something like this.
19:36:10 <mikejoconnor> we would integrate with the quota system to add a price field for each item we monitor.
19:37:08 <mikejoconnor> and every month we would iterate over the subscriptions, gathering the quota info to determine the total cost of each site.  Group it on one order, and do one transaction
19:38:09 <mikejoconnor> anarcat: this is actually a really good use case for uc_recuring
19:38:55 <mikejoconnor> anarcat: it would be much easier in ubercore
19:40:17 <mikejoconnor> or at least with the theoritical concept of what a product is in ubercore
19:40:45 <mikejoconnor> univate: any thoughts?
19:41:05 <mikejoconnor> anarcat: univate is the current maintainer of uc_recurring
19:41:51 <univate> trying to read back to understand questions....
19:42:48 <@anarcat> ubercore?
19:43:15 <@anarcat> so that makes sense
19:43:42 <@anarcat> it's flexible enough to allow both for "quota-based" systems (where you pay for N sites and can be limited to it) or "usage-based" systems
19:43:58 <mikejoconnor> anarcat: we are basically looking back at everything we have learned since we started ubercart, and looking to create a core api for ubercart
19:44:18 <@anarcat> basically, every P period (month, by default) you would look at the quota Q for the resource R
19:44:34 <univate> there is already support in uc_recurring to setup a recurring payment and then at each recurring payment there are hooks that other modules can use to adjust the order that gets charge (ie: it could sum up resources and 
                   charge that or bill based on product select somewhere)
19:44:35 <@anarcat> resource usage is U
19:44:45 <@anarcat> if U < Q then bill price P for Q
19:44:58 <@anarcat> if U > Q then bill price P plus overquota O
19:45:06 <@anarcat> if Q is 0, then it's completely usage-based
19:45:21 <@anarcat> mikejoconnor: a rewrite?
19:45:49 <univate> anarcat, that can be done via the uc_recurring_renewal_pending() hook
19:46:24 <mikejoconnor> anarcat: more or less, but more a change in process/approach.  Currently ubercart tries to do the job of a install profile, module, theme, as well as provide api's
19:46:27 <univate> you need to be using a gateway where uc_recurring as full control over what amount is charge - auth.net CIM works this way
19:46:56 <@anarcat> univate: and not paypal (or maybe payflow would work...)
19:46:58 <mikejoconnor> anarcat: on top of that, we try to make it support everything out of the box.  The result is a lot of code, that is very difficult to maintain.
19:47:05 <@anarcat> mikejoconnor: indeed
19:47:51 <univate> anarcat, you need to be using a gateway where you can change the amount on each recurring billing
19:48:09 <@anarcat> univate: yeah, basically, you need to be able to charge arbitrary amounts
19:48:25 <mikejoconnor> anarcat: so the idea is to change the approach(small core, good api's), change the process(clear goals, with a clear path/roadmap) to encourage community participation, and change the future of ubercart(possible 
                        it's better as an install profile)
19:48:34 <@anarcat> auth.net doesn't require you to keep the credit card number on your site for that, am i correct?
19:48:50 <mikejoconnor> anarcat: correct.  you store a reference to the account info
19:48:56 <mikejoconnor> anarcat: but not the info itself
19:49:12 <mikejoconnor> anarcat: that reference can only be used from you, so if someone breaks in, they don't have anything useful
19:49:27 <univate> exactly, uc_recurring just billings that profile what every the amount is
19:50:18 <mikejoconnor> univate: so if I place 3 separate orders, for 3 separate subscriptions, will uc_recurring run 3 transactions every month, or can it group them to one?
19:51:09 <@anarcat> univate: okay, nevermind, i understand
19:51:21 <@anarcat> (uc_rec just bills the user whatever everything amounts to)
19:51:43 <univate> uc_recurring will run a transaction for each recurring fee
19:52:17 <@anarcat> can we consolidate those transactions?
19:52:42 <@anarcat> i mean
19:52:46 <@anarcat> can we consolidate the recurring fees?
19:52:56 <@anarcat> anyways, i think we have an understanding
19:53:03 <@anarcat> i'm still unsure as to where to go from here
19:53:05 <univate> You could have some logic on top of uc_recurring that detects an existing order for that customer and instead of creating a new order it just updates the recurring fee
19:54:09 <mikejoconnor> univate: what happens if you place 5 recurring fee items on one order?
19:54:18 <@anarcat> you guys mind if i file all this in this issue? http://drupal.org/node/630336
19:54:21 <Druplicon> http://drupal.org/node/630336 => billing support => Hosting, User interface, normal, active, 0 comments, 1 IRC mention
19:54:34 <mikejoconnor> anarcat: have @ it
19:54:35 <univate> at the moment it creates 5 recurring fees
19:54:53 <@anarcat> mikejoconnor: what?
19:54:55 <mikejoconnor> univate: would you be open to modifying that?
19:55:11 <univate> I was taking to someone recently about creating a uc_recurring_order module
19:55:12 <mikejoconnor> anarcat: have at it, filing all this in the issue
19:56:07 <univate> which you wouldn't add recurring fees to products but instead have a recurring options at checkout that would create a recurring order
19:56:07 <univate> which you wouldn't add recurring fees to products but instead have a recurring options at checkout that would create a recurring order
19:56:18 <mikejoconnor> anarcat: sorry.  have at it is equivalent to yes, please do
19:56:48 <mikejoconnor> univate: what about this.
19:57:37 <mikejoconnor> univate: instead of having recurring orders, or recurring fees as individual items, you have a recurring account.
19:58:21 <mikejoconnor> univate: when ever you place an order with a one or more recurring items on it, or when ever you create a "recurring order", it adds an additional item to your account
19:58:46 <mikejoconnor> univate: and starts the monthly process of billing your account total
19:58:48 <univate> no exactly, at the moment the reason uc_rec doesn't try and combine items into the one recurring fee is items can have different billing schedules
19:59:12 <mikejoconnor> univate: yep
19:59:49 <univate> instead the idea was add items to the cart and then when you checkout you can have the option to make this a recurring order, so purchase this same order every month, 3months etc....
20:00:46 <mikejoconnor> univate: however it seems like it might be better to approach the issue as a billing scheduler.
20:01:49 <mikejoconnor> univate: so uc_recurring could hold information for recurring fees.  each recurring fee could have the option of being billed individually, or it could be grouped into a monthly billing cycle
20:02:39 <mikejoconnor> univate: if you decide to place a recurring order, it would simply add a recurring fee to the table, with a "bill separately" indicator.  You could specify an amount, and frequency
20:03:32 <mikejoconnor> univate: doing it that way would allow a site admin to do all sorts of cool things
20:03:52 <mikejoconnor> univate: I should probably sketch out what's in my head.
20:04:33 <mikejoconnor> univate: btw, the recurring order would be really useful for one of my current clients.
20:04:54 <univate> it seems like you are adding an extra level of complexity that isn't needed, since you are not really grouping recurring fees into the one order you are needing to group products into the one recurring fee
20:05:06 <univate> products is what you are purchasing...
20:06:15 <mikejoconnor> depends on how you look at it.  For this usecase, yes, it's a bit more abstracted than it would need to be, however I'm thinking that it would be more useful in the end than writing an individual implementation of  uc_recurring for simple usecase
20:08:00 <mikejoconnor> usecases that is.
20:08:33 <mikejoconnor> i.e. yes, more engineering up front, but it would also be a bit easier to extend.  however I am not nearly as experienced with the uc_recurring module as you are
20:09:12 <mikejoconnor> univate: I should probably familiarize myself with it a bit more, and then make suggestions
20:10:50 <univate> to me what would make sense from a billing application is that you add items to the clients account as they incur them and then trigger a bill to happen on a certain date which would sum up those items and charge them  the total
20:11:13 <mikejoconnor> univate: exactly
20:11:41 <mikejoconnor> univate: so you can schedule billing events, and you can add charges to an account
20:13:16 <mikejoconnor> univate: it also seems like a billing event should be able to support a specific charge, incase someone wants to stick to a separate monthly transactions per order schedule, rather than a monthly grouping
anarcat’s picture

So this chat was a good occasion for me to reflect on our requirements and on our side of the implementation. Basically, what we need on our side is:

* a quota system - maybe #533330: Quota API is a good basis
* a statistics system - this will be necessary to collect information that is outside of aegir (bandwidth, disk usage and so on). this would work by collecting information from the outside and file it in the Aegir database. then that information (and information that is already in Aegir like the number of sites or which platforms/profiles are available) would be available through hooks.
* a billing system that would regularly check the quotas (Ubercart, for now)

It would look something like this:

                               Aegir                                                              
                 -----------------------------------                                              
                /                                   \                      +--------------+       
                +-----+                       +-----+                      | Ubercart     |       
                |stats+-----------------------+quota+----------------------+ uc_recurring |       
                /-+---\                       +-----+                      | ...          |       
               /  |    \                         |                         +--------------+       
           hook_hosting_stats()              hook|hosting_quota()                                 
             /    |      \                   hook|hosting_quota_set()                             
            /     |       \                  hook|hosting_quota_check()                           
+----------/ +----+----+ +-\-------------+       |                                                
|disk space| |bandwidth| |number of sites|      ... same as stats                                 
+---+------+ +---+-----+ +-------+-------+                                                        
    |            |               |                                                                
hook_hosting_stats_update()   (direct)                                                            
    |            |               |                                                                
+---+------+ +---+----+  +-------+-----+                                                          
|filesystem| |logfiles|  |   aegir db  |                                                          
+----------+ +--------+  +-------------+                                                          

Some explanations on the hooks declared above:

* hook_hosting_stats() declares the resources available in a module
* hook_hosting_stats_update() is fired regularly to update the current usage (probably by running a task or something, on some modules, like hosting_site, it's a null operation because it's already in the DB)
* hook_hosting_quota() would return the current quota usage based on the collected stats
* hook_hosting_quota_set() is fired when the current limit for a given resource is set (could fire up a task to set the quota on a disk, for example)
* hook_hosting_quota_check() compares the stats against the current limit

I'm unsure, at this point, if it's relevant to have a separate "stats" module from the quota system. I don't see the gain in keeping this separate. But I drew this nice graph so I wanted to put it forward. We can probably all fold this into the quota system that would manage resources.

So this would fold into:

* hook_hosting_quota() declares the resources available in a module
* hook_hosting_quota_update() is fired regularly to update the current usage (probably by running a task or something, on some modules, like hosting_site, it's a null operation because it's already in the DB)
* hook_hosting_quota_get() would return the current quota usage based on the collected stats
* hook_hosting_quota_set_limit() is fired when the current limit for a given resource is set (could fire up a task to set the quota on a disk, for example)
* hook_hosting_quota_check() compares the stats against the current limit (return false if the limit is reached)

The algorithm for checking the quotas would be:

* quotas are checked every P period (e.g. a month)
* R is the resource, with a Q quota and a U usage this month
* A is the amount paid for the monthly Q quota, O is the overquota charged when the quota is exceeded
* the the amount charged every month is: A + (U-Q)*O

If A == 0, then the scheme is usage-based: that is, people only pay for what they use.

If A > 0, then the scheme is quota-based: that is, people pay a regular fee and (optionnally, if O > 0) an extra when they overrun their quota.

I believe that system is flexible enough to accomodate all needs and is extensible enough to accomodate new ones.

anarcat’s picture

Let's move the quota system discussions back into #533330: Quota API and keep this here for Ubercart interoperability.

bgm’s picture

subscribing

kvvnn’s picture

Wow. Awesome ascii map man! Haha, awesome discussion here.

I am very close to offering a serious bounty on this work. Will update after some more research / discussion.

sfyn’s picture

sub

sfyn’s picture

Assigned: Unassigned » sfyn

Hey folks, I'm taking this on for a while, since we are going ahead with this at Koumbit to have a system that is open to clients in the next couple months.

hadsie’s picture

I've done a bit of work on some basic integration between the two (pretty much all the code is just implementing ubercart hooks).

I've posted the code on github: http://github.com/hadsie/UC-Aegir

Note that this doesn't have a frontend to actually purchase sites at this point since I'm using a custom interface for my users to do that. Basically what I had planned was to add a theme_uc_aegir_add_to_cart function that could be added to site nodes.

It works by adding an ubercart product feature and a conditional action. The product feature allows you to assign an install profile to a product (so different install profiles could be different prices). I haven't tried it with product classes, so I don't think it will work with those. The add to cart form needs a hidden variable that sets the aegir_site_nid (this is what theme_uc_aegir_add_to_cart would do). This way when you go through the purchase it will assign a site nid to a order product.

The conditional action is quite simple. It simply runs a given hosting task on all sites that were contained in the order.

I've tested it with uc_recurring enabled and it's working fine as all this does is associate the site with an order item, and everything else in ubercart flows the same.

It's clearly not as robust as what's discussed above but I needed to get something working by the end of the month and this is doing the trick for me for now.

If there's anything in particular I can start working on with the api quota related UC stuff let me know. I'd be happy to move any relevant code to that project.

sfyn’s picture

Awesome, thanks!

I have done my own work programtically defining a class for aegir products, but not much more. I'll take a look at your stuff and see how I can go about getting the two streams talking to each other.

univate’s picture

What would be good is a ubercart product feature to add 'quota' items - #533330: Quota API

That way you can build products that have something like "1 site with 1GB of storage and 10GB Bandwidth" or use attributes to allow your clients to custom build a plan they want.

I may even have a go at building this now that the quota stuff has been committed.

sfyn’s picture

I was thinking about this, and I would like to see the quotas appear as attributes, allowing price changes depending on quota choices at the time of purchase. Later on, we can allow folks to change their attributes, thereby changing their recurring price.

I notice that the module from #8 associates an install profile to an aegir product, hadsie mentions this is to allow pricing by install profile. I think quota based pricing makes more sense - I don't know, to be honest. We can have both, too.

sfyn’s picture

So some clearer reflection now that I have had a chance to look at this.

Hadsie's module implements sites as the product.

The model I am working with at Koumbit implements the hosting client as the product. Clients then have quotas applied to them, including number of sites.

They are a little different.

The implementation I am working towards right now, as a first phase is:

  • An ubercart feature associates a product to hosting, and creates a client once the order is completed.
  • This feature allows the creation of attributes for each quota entered using hosting_quota (To some degree automatic, but admins must make choices about what choices they will offer customers)
  • This feature also allows admins to choose to expose install profiles as options on an install profile attribute.

I have ten days left to accomplish this, which is why it is such a restrained set of initial features.

In subsequent phases we would include:

  • The ability for clients to modify their initial hosting package and be billed appropriately.
  • A feature to allow automatic billing on certain quotas (this is quite nebulous right now)

I am going to go ahead with my first phase, because it's what we need for our work. I would like to incorporate the concept of sites as a product into it eventually, my ideal being that the two approaches live side by side with as much of a shared api as possible while allowing folks to make choices about how to market their aegir services.

adrian’s picture

i think the client as the product makes a lot of sense. =)

you pay for your account.

sfyn’s picture

Hi folks,

Here is my update with a git repo of my work up to date on the module.

http://git.koumbit.net/?p=aegir_kt/uc_hosting.git;a=summary

I am presently working on exposing an admin interface to manipulate the quota-linked attributes. After that I will do a once-over for comments and documentation, and then submit this to drupal.org.

The module depends on at least aegir0.4alpha9

sfyn’s picture

Version: 6.x-0.4-alpha2 » 6.x-0.4-alpha3

Bumping the version on this. uc_hosting depends on the quota api, which is only available as of 0.4alpha8

sfyn’s picture

Hi folks, for those of you following this I will be working on the module today, and it would be great to have some help.

sfyn’s picture

Status: Active » Closed (won't fix)

Hey folks.

uc_hosting is up on drupal.org, though by no means finished.

I will need folks for lots of stuff, and will be outlining my rationale a little more fully than it is on here in the aegir discussions on groups.

For the time being I am marking this as needs review and invite you to start using the module's issues queue. If you really want to get your hands on it soon, since the first snapshot won't be showing up right away, I invite you to check it out with git through the repo linked as the project homepage

sfyn’s picture

Status: Closed (won't fix) » Needs review
omega8cc’s picture

Please keep this thread open. We will test uc_hosting for sure and will report all issues there, but this thread in the Hosting project open will help to drive the traffic to uc_hosting :)

Thanks!

Pls’s picture

Great stuff. Definetely will give it a try and report any issues.

wik’s picture

wow, subscribing

anarcat’s picture

Status: Needs review » Fixed

I don't think we should leave this as needs review. People that want to try the module should try it out and submit issues in the other queue. This has been clobbering this queue for too long, sorry. :)

I'm sure it's got the publicity it needed by now. ;)

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.