I use stripe subscriptions for my users with one plan for, say, $10 per month for 100 API requests and that's a standard price. However, if the user has used 150 API requests, I charge them $10 + $3. For 200 and more requests it's $10 + $7.
Say, I've subscribed the user on October 9th. On November 9th the webhook event invoice.created will be called by stripe. So if the user has used 150 API requests, I have to add $3 more to the basic price (I can do that only within 1 hours according to Stripe documentation https://support.stripe.com/questions/metered-subscription-billing).
if even.type == 'invoice.created'
Stripe::InvoiceItem.create(
customer: stripe_customer_id,
invoice: event.data.object.invoice
amount: 300,
currency: 'usd',
description: 'additional price'
)
The questions:
Will the event invoice.created, indeed, be called on November 9th for the first time?
Will that additional price of $3 be added to the current invoice of $10 for October 9th-November 9th or will it be added to the future invoice for November 9th-December 9th? From the documentation it's not clear.
How do I add metadata to the original invoice of $10? I can add metadata to the additional invoice but in case the user has used less 100 API request I don't have to create the additional invoice at all, so I can't rely to the additional invoice.
It says
Create any invoice items before your customer is subscribed to the
plan, and then create the subscription via an update customer
subscription call.
but I subscribe the user once and forever on October 9th! How can I create an InvoiceItem before or on that (on October 9th) date if one month hasn't passed yet, and thus it's not known how many API calls the user makes (on October 9th the user has made, obviously, zero API calls)? I can only create InvoiceItems in 30 days because it's when I know how much to charge them on top on the $10! On October 9th I don't know that. Don't I understand anything?
Each time an invoice is created, you get the event invoice.created on your webhook. So when you subscribe a customer to a monthly plan on the 9th of November, you will get this event on the 9th of November, on the 9th of December, on the 9th of January, etc.
The first invoice for a subscription (generated when you create a subscription) is always closed immediately, so it is not possible to add an invoice item at that point. If that's something you want to do (for a setup fee for example) you need to create the invoice item before creating the subscription. That way it would get added automatically to the first invoice created when subscribing your customer.
In your case, you want to add fees to the next invoice based on the number of API requests your customer made during the month that just ended. So in the invoice.created event you need to detect whether it's a new month starting or the first one. If it's a new month, you then need to decide whether you have to add an Invoice Item to the user or not (based on the number of API requests).
You can't add metadata to the previous invoice from the month before. You just need to add the invoice item to the current invoice (for the month that is starting) and put a description indicating that the extra line item is for the consumption for the previous month.
Related
Description of functionality:
So I have a subscription based website that has two plans: Monthly and yearly. A monthly subscription is charged a monthly fee every month, while a yearly subscription is charged a one-time cumulative fee of 10 months, each year. ($29/mo and $290/yr)
I have 10% recurring referral discounts that are applied each month, for every active member who was referred (100% max). So if Bob signs up for a monthly subscription in October, and throughout the next month refers 5 people who sign up, he should have a 50% discount accumulated. This will be applied to his subscription fee in November, which will result in $14.50 for that month. But assume one of his referrals cancels in November. This will drop his discount for December by 10%, which will give him a 40% discount, with 4 active referrals, resulting in $17.40 for December.
Example of working code:
If every one of Bob's referrals is monthly, this is fairly simple to apply with webhooks. An amount is just deducted from Bob's current balance every time a successful payment goes through, if the user connected to that payment is one of Bob's referrals.
# Webhooks Controller
def payment_success
referred_user = User.find_by_customer_id(#subscription.customer.reference)
if referring_user = User.find_by_affiliate_code(referred_user.referral_code)
balance = referring_user.subscription.balance_in_cents
referring_user.subscription.adjustment({"amount_in_cents"=>"-290","memo"=>"Balance adjusted for referring #{referred_user.email}. Payment for referral was successful."})
referring_user.subscription.save
end
head :ok
end
This sends a request to Chargify, the payment processor I'm using, to adjust the balance accordingly.
My real problem:
It isn't this straightforward, though, when one of Bob's referrals is a yearly user.
Since the yearly subscription is a one-time payment, the payment_success webhooks aren't coming through every month, which means 10% of Bob's subscription can't be deducted each month from this yearly user's active referral.
I thought of just setting Bob's plan price to 10% less than standard, instead of adjusting the balance each month. This would require 9 different plans, though, since the plan price directly refers to a Plan object on Chargify, which points to its price attribute. That means that there would need to be a 90%_monthly_plan, a 80%_monthly_plan, and so on, which all live on the Chargify servers. This seems overly complex, and I also wouldn't be surprised if it caused other issues I'm not even considering at this point.
My current (unsatisfactory) solution:
So instead I decided to just create a scheduler on my server that is created when a yearly user signs up, and it fires every month.
I'm using rufus-scheduler for this. One important thing to note - Schedules are destroyed when the server is restarted, so I'm creating schedule records, and an initializer goes through these records and creates these schedules every time the server restarts.
# modified Webhooks Controller
def payment_success
referred_user = User.find_by_customer_id(#subscription.customer.reference)
if referring_user = User.find_by_affiliate_code(referred_user.referral_code)
balance = referring_user.subscription.balance_in_cents
referring_user.subscription.adjustment({"amount_in_cents"=>"-290","memo"=>"Balance adjusted for referring #{referred_user.email}. Payment for referral was successful."})
referring_user.subscription.save
if #subscription.product.handle == 'yearly'
schedule = ReferralSchedule.create(
type_of: "yearly discount",
referred_user_id: referred_user.id,
referring_user_id: referring_user.id,
time_to_execute: "30.41d"
)
ReferralScheduler::create_yearly_discounts_schedule(schedule)
end
end
head :ok
end
And the module handling the schedule creation:
module ReferralScheduler
def self.create_yearly_discounts_schedule(schedule)
referred_user = User.find(schedule.referred_user_id)
referring_user = User.find(schedule.referring_user_id)
# first_date is calculated to be the first date in the future, that the scheduler should run.
first_date = Time.now + (30.41-(DateTime.now - schedule.created_at.to_datetime).fdiv(30.41)%1*30.41).days
scheduler = Rufus::Scheduler.new
scheduler.every schedule.time_to_execute, first: first_date , last_at: (schedule.created_at+12.months) do
if referring_user && referred_user.subscription_status == :active
balance = referring_user.subscription.balance_in_cents
referring_user.subscription.adjustment({"amount_in_cents"=>"-290","memo"=>"Balance adjusted for referring #{referred_user.email}. Referral is still active."})
referring_user.subscription.save
end
end
scheduler.at (schedule.created_at+12.months) do
schedule.destroy!
end
end
end
And the initializer:
require 'rufus-scheduler'
ReferralSchedule.where(type_of: "yearly discount").each do |schedule|
ReferralScheduler::create_yearly_discounts_schedule(schedule)
end
I really hate using this method, as it doesn't seem very clean. It has also already screwed up my local server when I tried to run it at shorter intervals.
I also thought about using rake tasks and/or Grunt to perform this, but I have very limited knowledge on each of these, and I'm not sure if they will necessarily be easier/better solutions.
Any ideas?
One option might be to use the upcoming_renewal_notice webhook on Bob's subscription as a trigger to go see how many referrals he has made that are on annual plans, and apply any additional discounts.
https://docs.chargify.com/webhooks
upcoming_renewal_notice - A subscription set to renew within 3 days
So I am in charge of office hours for a class at my University. I have to send out a google form every week for the students to sign up. The way the form is sent back, the data is grouped by Name, and the times they are available are grouped by days.
To make it easier on myself, I want to group it by times. Basically, I want it so that each day/time will have its own row, and the names of the people who want the time slot would be grouped together in the adjacent column.
I already separated the groups of times so that each time has its own cell, but I cannot figure out how to regroup the data by time.
I should also mention that each session of OH is 30 minutes and that each student can only receive one session of office hours a week because of limited availability. I also need to group the sessions into blocks so that the teachers won't have idle time (basically a teacher will have office hours from 5:00-6:30 PM on Tuesday, instead of 5:00-5:30 PM and 6:00-6:30 PM on Tuesday and 8:00-8:30 PM on Thursday). Grouping the names of the people who want office hours by the times that they are available would make it a lot easier to set up that week's office hours schedule.
Here's a link to an example:
https://docs.google.com/spreadsheets/d/1fRYYNUoEcgynU9cDMoXzsyjtIir4hsRlfFYJau36a78/edit?usp=sharing
have a look at this sheet ( i have only turned on sharing temporarily, co copy this to your own drive)
Look at the "matrix choices" sheet.
I created a Matrix of students and times (which I think is better), but there is also a list of names for each timeslot on the end too.
have a play changing some of the 1's (sessions applied for) to "G" (short for Granted). Ive set up some conditional formatting and data validation.
When I want to generate an invoice to an order following error is displayed:
"There has been an error:
An Invoice could not be generated. The purchase order does not have any applicable periods to be invoiced.
Verify the data of the purchase order or contact customer service to review your business rules."
I disabled pro-rating and I set following settings to plug-ins:
Invoice presentation
com.sapienter.jbilling.server.pluggableTask.InvoiceCompositionTask
Billing process: order periods calculation
com.sapienter.jbilling.server.pluggableTask.OrderPeriodTask
It is not working yet. Any Idea? help me quickly please.
Thanks a lot.
when you create order, you will see period filed on order screen which is one time or monthly.
select one time and try to create order. if you select monthly then only one invoice will create for that order because it is recurring order and then next bill set to next month.
if you want to create invoice again for same order then try to manage billing proces to next invoice date or update next bill date to curent month in purchase order table.
We have a client site who is having gold jewelery magento shop. In that the jewel prices are daily changing,so he have to update each jewel items price often.
(The logic we have here is 1 gram price today is Rs. 1200 and tomorrow it may became RS. 1220 and client is selling 10 gram item as one jewel and 18 gram item as one jewel and so on, so he have to update the price daily for each jewel item based on its weight).
What we are doing now is having a script that checks and updates price daily based on one input field value from admin config section and cron job.
But what i am looking for is(Well truly its not me, but clients wants better than this solution) a way to automatic price change as like % price based on one gram value(Which can be updated by admin daily in configuration section as like now) daily basis. Is there anyway in magento for this? Please advice me.
Thanks
Ela
In my application I have a provider that has a schedule and clients that book appointment from the schedule. I need the following features.
Provider:
- Be able to specify reoccurring availability. For example Mon 9-5, Tues 10-3, etc.
- Be able to black out datas. For example - not available on this Mon.
- Be able to add single, not reoccurring dates/times slots. For example - This Sat 9-5.
Customer:
- Be able to book single appointments.
- Be able to book reoccurring appointments. (Every Mon 9-4).
So far I came up with 3 options:
Divide the schedule into 30 min intervals and create a database entry for each interval/provider pair. Each interval can be either free or booked. When a customer books an appointment we mark the intervals as booked. The problem with this approach is that it wastes a lot of space, and I am not sure how good the search performance would be for a reoccurring booking.
Save each availability period as an "event". If it is reoccurring, duplicate the event. When searching for free slots search the booking table to make sure that there is no over lapping booking. In this case, searching for reoccurring slots seems a bit awkward. To find all the providers that are available on Mon 9-5 for the next year we will have to search for all the matching 'events' and find all the providers that have 52 matched events.
Save each availability period as an "event". Add a flag if it is reoccurring.When searching for free slots search the booking table to make sure that there is no over lapping booking. It makes it easier to search for reoccurring appointments. To "black out" slot that are suppose to be reoccurring we can just insert a fake booking.
1.Create a event table:
a) With the basic columns eventdate, starttime, endtime, with other details for the event - these are the busy times so are what you block out on the calendar
b) Recurring Events - add columns:
- isrecurring - defaults to 0
- recurrencetype (daily, weekly, monthly)
- recurevery (a count of when the recurrence will occur)
- mon, tue, wed, thur, fri, sat, sun - days of the week for weekly recurrence
- month and dayofmonth - for monthly recurrence
2.The challenge comes when creating the recurring events on the calendar:
- if you create all of them at once (say for the next 6 months), whenever you edit one the others have to be updated
- If you only create an event when the previous one has passed then you need complex logic to display the calendars for future dates
3.You also need rules to take care of whether events are allowed to overlap each other, what resources are to be used, how far ahead the events can be scheduled