Stripe: How to provide access during grace period - ruby

I have a couple of monthly plans where user can cancel at any moment. Whats the recommended way to handle a grace period where a user still gets access to the application. For example. If the users signup on 1st July and cancels on 15th July, I would like the provide the user access till 30th July.
i am storing the following columns, current_period_start, current_period_end, canceled_at & ended_at.
should grace period check be something like
def grace_period?
return status == 'canceled' && Time.zone.now < current_period_end
end
any clarification on this would be really helpful. thanks.

You should not "cancel" subscription.
Just update with parameter "cancel_at_period_end: true"

Related

Yahoo Finance - Historical Intraday Download

does anybody know why the code below does not bring data after 16:55hr? The market actually closes at 18:00 in Brazil. This happens for all tickers ending in ".SA" in Yahoo Finance.
import yfinance as yf
data = yf.download("PETR4.SA", group_by="Ticker", period='1mo', interval='5m',prepost = True)
data['ticker'] = "PETR4.SA"
data
Thanks!
This is kind of an interesting question. I checked the code. I've been working with several providers, including Yahoo Finance, and I believe it could be more a "pre definition" on the API than a programming/requisition mistake.
As the stock negotiations at B3 normally take place until 17:00 pm (-3 UTC, São Paulo Timezone), the function is returning the last valid computed value i.e. 16:55 pm.
As an exercise I tried to change the time in-between the data from "5m" to "2m" and I spotted the last value at 16:58 pm (same logic). I don't know how to bypass that.
It appears to be the way it works.

Without proration enabled, any changes made to a customer’s subscription mid-cycle goes into effect immediately

During the implementation of recurring payments using Braintree I encountered a problem.
In documentation I can read: “Without proration enabled, any changes made to a customer’s subscription mid-cycle will go into effect at the beginning of the next cycle.” (https://articles.braintreepayments.com/guides/recurring-billing/recurring-advanced-settings#proration)
But if I edit the subscription to a lower dollar amount in the middle of a billing cycle (without proration on downgrades enabled) e.g. from $100 to $80 and then I edit the subscription to a higher dollar amount (with proration on upgrades enabled) e.g. to $90, the gateway will immediately charge me some amount.
In this situation, I would expect that gateway will not generate any transaction, because downgrade should be effective at the beginning of the next cycle and new subscription price ($90) is lower than initial subscription price (100$).
How can I then reach scenario when transaction on proration upgrade will be generated only if new subscription price is higher than maximum subscription price at the current billing cycle?
I'm a developer at Braintree.
If you kept proration on for both price decreases and increases, in the example you give you would see a credit applied to the subscription balance for the decrease, and then a charge applied against the balance for the increase. If the charge exceeds the subscription balance credit, then your customer would be charged.
A subscription will not be charged in the middle of a billing cycle unless you choose to prorate charges. You could create the scenario you want with logic similar to below. Code snippets are in Ruby since you didn't specify what client library you were using.
First look up the subscription you want to update and find the start date of the current billing period:
subscription = Braintree::Subscription.find("subscription_id")
billing_period_start_date = Date.parse(subscription.billing_period_start_date) # convert String to Date
Then iterate over the status_history events of the subscription, and update the billing_period_max_price if the history event took place after the beginning of this billing cycle and the billing_period_max_price is greater than the previous one:
billing_period_max_price = 0.0
subscription.status_history.each do |history_event|
event_date = Date.parse(history_event.timestamp.strftime('%Y/%m/%d')) # convert Time to Date
event_price = history_event.price.to_f
if event_date >= billing_period_start_date && billing_period_max_price < event_price
billing_period_max_price = event_price
end
end
Finally, if the billing_period_max_price is less than what you want to change the subscription price to, prorate the charges:
Subscription.update(
"subscription_id",
:price => "yourHigherPrice",
:options => { :prorate_charges => true }
)
If you have additional questions, feel free to reach out to Braintree support.

how do I enable recurring reminders for different users in ruby?

Currently, the users for my app set a specific date and time for a single reminder (using the Chronic gem).
I have a cron job which runs every 10 minutes and checks if the time in the reminder is < Time.now at which point, it sends the reminder and marks that reminder as sent.
However, I want them to be able to specify recurring reminders. The customer should be able to say, "Every other day at 10am".
I can use ice_cube for the recurring part it seems. Then I use Chronic to come up with the start time which will have the day and recurring time.
But I don't have a good way to make it recurring since these are not separate events in the data base.
Here is what I have tried:
```
reminder = response.body['results'] #array of recurring reminders with start_epoch and 'via'
d {reminder}
reminder.count.times do |i|
schedule = IceCube::Schedule.new(now = Time.at(reminder[i]['value']['start_epoch'])) # get the initial start day and time
schedule.add_recurrence_rule(IceCube::Rule.daily) #makes this a daily recurring, but how can I allow this to be customizable?
if schedule.next_occurrence(Chronic.parse('today at 12:01AM')) < Time.now # Check if today's occurence has happened yet
bot_response = BotResponse.get_bot_response(bot_client_id, reminder[i]['value']['bot_input_keyword'])
if reminder[i]['value']['via'] == 'slack'
slack_response = BotMessage.send_slack(reminder[i]['value']['slack_channel'],
bot_response[:bot_response])
d {slack_response}
end #if
end #if
end #do
```
Questions:
Is there a way to tell when a reminder has been sent without writing each specific daily reminder to a database?
Is there a more elegant way for the user in a text string to define the recurrence?
Have you considered trying the whenever gem to implement recurring tasks through cron jobs? I think you should be able to set the schedule times dynamically in the whenever schedule.rb file, see related issue here: Rails - Whenever gem - Dynamic values

How to get all message history from Hipchat for a room via the API?

I was using the Hipchat API (v2) a bit today and ran into an odd issue where I was not able to really pull up all of the history for a room. It seemed as though when I queried a specific date, for example, it would only retrieve a fraction of the history for that date given. I had had plans to simply iterate across all of the dates for a Room to extract the history in a format that I could use, but ended up hitting this and am now unsure if it is really possible to pull out the history fully.
I realize that this is a bit clunky. It is pulling the JSON as a string and then I have to form it into a hash so I know I'm not doing this as good as it could be done, but here is roughly what I quickly did just to test out the history method for the API:
api_token = "MY_TOKEN"
client = HipChat::Client.new(api_token, :api_version => 'v2')
history = client['ROOM_NAME'].history
history = JSON.parse(history)
history.each do |key, history|
if history.is_a? Array
history.each do |message|
if message.is_a? Hash
puts "#{message['from']['name']}: #{message['message']}"
end
end
end
end
Obviously then the extension to that was to just curse through the dates in the desired range (using: client['ROOM_NAME'].history(:date => '2010-11-19', :timezone => 'PST')), but again, I was only getting a fraction of the history for the room. Are there some additional parameters that I'm missing for this to make it work as expected?
I got this working but it was a big pain.
Start by sending a query with the current time, in UTC, but without including the time zone, as the start date:
https://internal-hipchat-server/v2/room/2/history?reverse=false&date=2015-06-25T20:42:18.658439&max-results=1000&auth_token=XXX
This is very fiddly:
If you specify just the current date, without a timezone, as documented in the API, it is interpreted as midnight last night and you only get messages from yesterday or older.
If you try specifying tomorrow’s date instead, the response is 400 Bad Request This day has not yet come to pass.
If you specify the time as 2015-06-25T20:42:18.658439+00:00, which is the format that times come in HipChat API responses, HipChat’s parser seems to fail and interpret it as midnight last night.
When you get the response back, take the oldest items.date property, strip the timezone, and resubmit the above URL with an updated date parameter:
https://internal-hipchat-server/v2/room/2/history?reverse=false&date=2015-06-17T19:56:34.533182&max-results=1000&auth_token=XXX
Be sure to include the microseconds, in case a notification posted multiple messages to the same room in the same second.
This will get you the next page of messages. Keep doing this until you get fewer than max-results messages back.
There is a start-index parameter I tried passing before I got the above working, and it will give you a few pages of results, with responses lacking a links.next property, but it won’t give you the full history. On a chatroom with 9166 messages in the history according to statistics.messages_sent, it only returned 3217 messages. So don’t use it. You can use statistics.messages_sent as a sanity check for whether you get all messages.
Oh yeah, and the last_active property in the /v2/room call cannot be trusted because it doesn’t update when notification messages are posted to the room.

VBScript: Reminder for office workers and personal use

My program asks the user for any events that he will be having later on (eg. meeting/special lunch event/submit report/pay bills/birthday) and will remind the user when the time comes.
Here is my code:
Dim remind
re=MsgBox("Do you want me to remind you anything later on?", vbYesNo, "Reminder")
If re=6 then call main
Sub main
' Ask for the time that the user wanted to be reminded
remind=InputBox("At what time?" & vbNewLine &
"Please use this format {H:MM:SS AM/PM}" & vbNewLine &
"Note: H is in 12h format")
' Description eg. "Lunch with boss"
reminder=InputBox("Any discription you want to add in?")
Do Until check=remind
check=Time
If check=remind Then MsgBox reminder
Loop
End Sub
For example, I put in 12:30:00 PM and Lunch with boss. Even when the time comes nothing happens, no popup. And when I check my TaskManager it is still running.
I'm using wscript.exe to run this script. It's the do until check=remind part that doesn't work. If I put do until check="12:30:00 PM" then it will work.
PS: I know we can use the Microsoft Outlook for the reminder or even use our phones. But this is well suited for workers that are 24h infront of the computer and lazy to use their phones and update their outlook.
Convert to Date data type
The issue seems to be that the remind variable is a String data type, and the check variable is a Date data type. When you try to compare them, they'll always fail to be equal, even if the actual date inside both types is the same.
You can solve the problem by using the CDate function to convert remind to a Date before entering the loop.
remind = CDate(remind)
Validation
Because you're now using CDate to convert the user's input, if they make a typo and enter an invalid date, its going to bring up an error box and end the program. You may want to use IsDate to ensure it is a valid time before converting it, then gracefully ask the user to enter the time again if they made a typo.
CPU Usage
Your loop will sit there taking up 100% CPU usage of one core of the machine its running on. This can slow down your user's computer, among other side effects.
To fix this issue, you want to slow down the loop, such that its only checking a few times a second, rather than a few hundred times a second. Insert this statement inside the loop to have it sleep for 500 milliseconds before trying again.
WScript.Sleep 500

Resources