Retrieve all subscriptions Stripe with an end date of certain day - c#

Trying to pull in all subscriptions where the end date equals a certain date not including the Hours, Minutes, or Seconds
So if I have two subscriptions where the end date is on today so 3/15/2021 I would like to pull in the following subscriptions
-3/15/2021 4:27:13 PM
-3/15/2021 5:27:13 PM
var options = new SubscriptionListOptions
{
CurrentPeriodEnd = DateTime.Now,
};
var service = new SubscriptionService();
StripeList<Subscription> subscriptions = service.List(options);
foreach (Subscription sub in subscriptions)
{
string customerId = sub.CustomerId;
}
This is what I have so far. I was thinking about doing a CurrentPeriodEnd is between today at 12:00AM and 11:59 PM but it has to be an equals inside to pass the parameter
Any help is greatly appreciated. Thanks!

After further looking into the Current Period End it is actually a
AnyOf<DateTime?, DateRangeOptions>
So my new line of code is
CurrentPeriodEnd = new DateRangeOptions() { GreaterThanOrEqual = DateTime.Today, LessThan = DateTime.Today.AddDays(1)},

As the docs say:
The value can be a string with an integer Unix timestamp, or it can be a dictionary with the following options...
For this you can use that dictionary of options to provide both gte and lte to bound the day you're looking for, borrowing an example from the library repository:
var CurrentPeriodEndOptions = new DateRangeOptions
{
LessThanOrEqual = DateTime.Parse("2021-03-16T00:00:00.0000000Z"),
GreaterThanOrEqual = DateTime.Parse("2021-03-15T00:00:00.0000000Z"),
},
var options = new SubscriptionListOptions
{
CurrentPeriodEnd = CurrentPeriodEndOptions,
};
var service = new SubscriptionService();
StripeList<Subscription> subscriptions = service.List(
options
);
Any further filtering you would need to apply in code on the results returned.

Related

Stripe: Update subscription or cancel and create new one?

We have one product with 4 different prices(basic, middle etc). Let's say user bought basic package (payment session is created after payment completion subscription created),but after a while, user decided to change his package and upgrade to advanced package. In that case should i use update subscription ?
This actually updates from X$ to the Y$ package
var service = new SubscriptionService();
Subscription subscription = service.Get("sub_49ty4767H20z6a");
var items = new List<SubscriptionItemOptions> {
new SubscriptionItemOptions {
Id = subscription.Items.Data[0].Id,
Price = "price_CBb6IXqvTLXp3f",
},
};
var options = new SubscriptionUpdateOptions {
CancelAtPeriodEnd = false,
ProrationBehavior = "create_prorations",
Items = items,
};
subscription = service.Update("sub_49ty4767H20z6a", options);
or just cancel current subscription and create new one ? Why am i asking this, because i chatted with support guys from Stripe, and got two different answers. One of them told me that i need to use update_subscripton, the another one told that i need to attach new subscription. I am confused.
The way that you've described this here, the update to upgrade the subscription makes more sense to me. Pay careful attention to the intended proration behaviour (do you want to credit the time left on the current plan) and whether you want to shift the billing period.
I'd also point out that you should consider switching to separate Products. A Product is a single good/service that you sell, while Prices represent different billing intervals and currencies. If you imagine some service with Silver, Gold and Platinum access levels, each of those is a different product -- they get more features! The Product is what gets shown on the invoice, too. So unless you use separate Products, the invoices would be indistinguishable aside from the rate paid.
Most of the time doing what you've done doesn't present any specific obsdtacles, but the Customer Portal enforces one price per product per interval. If you had two annual prices for the "same product" but different amount, why would anybody pay the higher price? It's because they're paying for something different, a different product.
Quick Answer
Upgrade (From Basic to Pro)
Remove Basic
Add Pro
Prorate (Do not change billing cycle)
// subscriptionId -> your subscription id
// additionalStripePriceIds -> stripe price id you are going to add
// removalStripePriceIds -> stripe price id you are going to remove
var getService = new SubscriptionService();
var getServiceResult = await getService.GetAsync(subscriptionId);
var items = new List<SubscriptionItemOptions>();
if (removalStripePriceIds != null && removalStripePriceIds.Any())
{
foreach (var removalStripePriceId in removalStripePriceIds)
{
var item = getServiceResult.Items.Data.FirstOrDefault(i => i.Price.Id == removalStripePriceId);
if (item != null)
{
var subscriptionItemOption = new SubscriptionItemOptions
{
Id = item.Id,
Deleted = true,
};
items.Add(subscriptionItemOption);
}
}
}
foreach (var additionalStripePriceId in additionalStripePriceIds)
{
var subscriptionItemOption = new SubscriptionItemOptions
{
Price = additionalStripePriceId,
};
items.Add(subscriptionItemOption);
}
var updateService = new SubscriptionService();
var updateOptions = new SubscriptionUpdateOptions
{
CancelAtPeriodEnd = false,
ProrationBehavior = "create_prorations",
Items = items,
};
await updateService.UpdateAsync(subscriptionId, updateOptions);

How to make PayPal Agreement start_date valid in PayPal SDK for ASP.NET

As PayPal docs says:
...start date must be no less than 24 hours after the current date...
Furthermore, judging by PayPal Source code repository start_should looks like "2016-02-19T00:37:04Z"
What is I did is:
var agreement = new Agreement() {
name = Plan.name,
description = $"Agreement for {Plan.description}",
start_date = DateTime.Now.AddHours(25).ToUniversalTime().ToString("yyyy-MM-ddTHH:mmZ"),
payer = payer,
plan = new Plan() { id = Plan.id },
};
agreement.Create(myAPIContext);
And here is the result. My start_date seems right.
But after that I immediately catch an Exception:
So, what's the problem?
As per the Paypal documentation the start_date parameter accepts string formatted ISO 8601 datetime. In this case it is of format yyyy-MM-ddTHH:mm:ssZ(as per the sample code) . Hence your code should be like this
var agreement = new Agreement() {
name = Plan.name,
description = $"Agreement for {Plan.description}",
start_date = DateTime.UtcNow.AddHours(25).ToString("yyyy-MM-ddTHH:mm:ssZ"),
payer = payer,
plan = new Plan() { id = Plan.id },
};
agreement.Create(myAPIContext);

How to use Next and previous Uri in Docusign using Rest Recipes

I want to fetch 20 records/request for envelope information using Rest Recipes.
My requirement is:
When 20 records are dumped to database, I want hit another batch which will fetch me records from 21 to 40 then in the third call from 41 to 60 and so on...
I have used code below, but not getting any idea, how to get information like paging. // call the Login() API which sets the user's baseUrl and returns their accountId
string accountId = loginApi(USER_NAME, PASSWORD);
// Set the Start Date (to limit the results returned)
DateTime fromDate = new DateTime(2016, 09, 15);
string fromDateStr = fromDate.ToString("o");
DateTime toDate = new DateTime(2016, 09, 16);
string toDateStr = toDate.ToString("o");
// set a filter for the envelopes we want returned using the
// fromDate and count properties
// Here I want to use paging like functionality.
EnvelopesApi.ListStatusChangesOptions options = new EnvelopesApi.ListStatusChangesOptions()
{
count = "20",// How to increase this counter for next request?
fromDate = fromDateStr,
toDate = toDateStr
};
EnvelopesApi envelopesApi = new EnvelopesApi();
EnvelopesInformation envelopes = envelopesApi.ListStatusChanges(accountId, options);
What are you trying to solve? DocuSign has a call that allows you to get a list of envelope IDs over a date/time/status range. There wouldn't be a specific number or limit to what is returned in this scenario, but I don't understand why you want to limit it to 20 (as your example states).

C# + Deedle: Creating a Data Series with Continuous DateTime Keys from Another with Date Gaps using LINQ

I am new to both Deedle and C#.
I have loaded futures data from Quandl in JSON format using QuandlCS.Connection, -.Interfaces, -.Requests, -.Types, and NewtonSoft.Json, -.Json.Linq, and thereafter transformed it into a Deedle data series:
QuandlDownloadRequest requestNG1 = new QuandlDownloadRequest();
requestNG1.APIKey = "myAPIKey";
requestNG1.Datacode = new Datacode("Chris", "CME_NG1");
requestNG1.Format = FileFormats.JSON;
requestNG1.Frequency = Frequencies.Daily;
requestNG1.Sort = SortOrders.Ascending;
requestNG1.StartDate = new Datetime(2010, 01, 01);
requestNG1.EndDate = DateTime.Now.Date;
IQuandlConnection connectionNG1 = new QuandlConnection();
string dataNG1 = connectionNG1.Request(requestNG1);
dynamic jasonNG1 = JsonConvert.DeserializeObject(dataNG1);
//create data series
var datePriceDS = new SeriesBuilder<DateTime, double>();
for each(var item in jsonNG1.dataNG1)
{
datePriceDS.Add(Convert.ToDateTime(item[0]), Convert.ToDouble(item[6]) );
}
var dataSeriesNG1 = datePriceDS.Series;
The keys of 'dataSeriesNG1' are comprised of only those dates upon which the contract was traded. I need to create another data series using all calendar dates between 1/1/2010 and DateTime.Now, with NA values assigned to the date keys where no price data exists. Is there a way to do this using LINQ? Many thanks in advance!
If you can generate IEnumerable<DateTime> with the dates that you are interested in, then you can use the Realign method on the series object. This will perform a lookup for each of the new keys and treat all other values as missing.
var newKeys = /* Some C# trick to generate date range */;
var dailySeries = dataSeriesNG1.Realign(newKeys);

While loop difficulty

I am trying to compare a list AAA that contain Date with a range of dates. I want to see if any of the range of date is present in the list or not. If the date is present I copy the list items to another list BBB else I add empty values to the list BBB.
The problem I am having is that with my actual code, is I don`t know how not pass through the false statement of the while loop, till it reaches the end of the comparison.
With the code below, it is passing both the true and false in the while loop, which is falsifying the required result. The result I am obtaining is for every time that is present, I am having the same time as false. In short, lets say the list contains the date 6/5/2010, and the range of date is 4/5/2010 to 7/5/2010. so I will have an item created in the true part and AN ITEM CREATED INTHE FALSE PART, which is wrong. The date present can either be in true or false part. Not both, such that I have two items bing created!
How can I achieve the right result? Any other method or suggetsion please.
My code is as follows:
DateTime StartDate;
DateTime EndDate;
Datetime tempDate = StartDate;
List<DateTime> dateToEvaluate;
bool TimeIsPresent = false;
foreach (var tempItem in TaskList)
{
while (EndDate.AddDays(1) != tempDate)
{
if (tempItem.Date[0] == tempDate)
{
TimeIsPresent = True;
break;
}
else
{
if (TimeIsPresent == False)
{
if (!(tempDate.DayOfWeek == DayOfWeek.Sunday)
{
dateToEvaluate = new List<DateTime>();
dateToEvaluate.Add(tempDate);
tempTask.Add(new GroupedTask { ID = null,
TaskID = null,
Date = dateToEvaluate });
}
}
}
tempDate = tempDate.AddDays(1);
}
if (TimeIsPresent == True)
{
tempTask.Add(new GroupedTask { ID = tempItem.ID,
TaskID = tempItem.TaskID,
Date = tempItem.Date });
TimeIsPresent = false;
}
}
let me give you an example. My range of date is as follows: Mon 8 Aug - Sunday 14 Aug.
Now my tasklist is as follows: item1: Date 9Aug, item2: Date 11Aug.
So my tempTask must be as follows:
item1: Date 8 Aug, taskID: null, ID: null,
item2: Date 9 Aug, taskID: 678, ID: 7,
item3: Date 10Aug, taskID: null, ID: null,
item4: Date11 Aug, taskID:890, ID: 34,
item5: Date 12 Aug, taskID: null, ID: null,
item6: Date 13 Aug, taskID: null, ID: null
Second example:
My range of date is as follows: Mon 8 Aug - Sunday 14 Aug.
Now my tasklist is as follows: item1: Date 9Aug, item2: Date 11Aug, item3: Date 14Aug
So my tempTask must be as follows:
item1: Date 8 Aug, taskID: null, ID: null,
item2: Date 9 Aug, taskID: 678, ID: 7,
item3: Date 10Aug, taskID: null, ID: null,
item4: Date11 Aug, taskID:890, ID: 34,
item5: Date 12 Aug, taskID: null, ID: null,
item6: Date 13 Aug, taskID: null, ID: null,
item4: Date14 Aug, taskID:894, ID: 74,
I think you're making things more difficult than they really are. As I understand it, you're taking each item in TaskList and seeing if the date falls in a certain range. If it does, you add it to another List and go to the next item, otherwise you add a blank entry to the other list and keep checking.
If my understanding is correct, try this:
EDITED based on OP's comment
The code now goes through the entire range for each item in TaskList, and adds either an empty object with the date or the corresponding task for the date.
No need to use a bool to determine if the date is present in this scenario.
// Note that you'll have to assign values to StartDate and EndDate, otherwise you'll get
// a Null Reference Exception
DateTime StartDate;
DateTime EndDate;
Datetime tempDate = StartDate;
List<DateTime> dateToEvaluate;
foreach (var tempItem in TaskList)
{
// Reset tempDate to the starting date before each loop
tempDate = StartDate;
while (EndDate.AddDays(1) != tempDate)
{
if (tempDate.DayOfWeek != DayOfWeek.Sunday)
{
if (tempItem.Date[0] == tempDate)
{
tempTask.Add(new GroupedTask { ID = tempItem.ID,
TaskID = tempItem.TaskID,
Date = tempItem.Date });
}
else
{
dateToEvaluate = new List<DateTime>();
dateToEvaluate.Add(tempDate);
tempTask.Add(new GroupedTask { ID = null,
TaskID = null,
Date = dateToEvaluate });
}
}
tempDate = tempDate.AddDays(1);
}
}
EDITED to add
Assume a 2 week range, with 7/1 starting on a Monday going through 7/14. Assume two tasks - task 1 with a date of 7/3 and task 2 with a date of 7/12. I would expect the following in tempTask:
26 elements (13 dates for each of the two task items), with all elements having a null ID except for one each for the two tasks.
Are you actually wanting a consolidated list with no repeats? I.e., with my example, there would be 13 elements, and 2 would have non-null IDs? What happens if two or more tasks have the same date?
I did find one error, in that I wasn't resetting the tempDate to the start before each loop.
EDIT Based on new understanding
Ok, so you're attempting to get a second list that has all the dates in a given range, and the GroupedTask object will either be an existing GroupedTask for that date, or a null GroupedTask for that date, if there is no match.
I suggest you take a look at Enigmativity's answer, as that may be a more elegant solution (I haven't looked at it in detail), but here's another approach. The biggest change is that I flipped the while loop and foreach loops.
// Note that you'll have to assign values to StartDate and EndDate, otherwise you'll get
// a Null Reference Exception
DateTime StartDate;
DateTime EndDate;
// Declare an instance of GroupedTask for use in the while loop
GroupedTask newTask;
Datetime tempDate = StartDate;
// Loop through the entire range of dates
while (EndDate.AddDays(1) != tempDate)
{
// You included Sundays in your example, but had earlier indicated they
// weren't needed. If you do want Sundays, you can remove this outer if
// block
if (tempDate.DayOfWeek != DayOfWeek.Sunday)
{
// Create a "null" GroupedTask object
// The Date property in GroupedTask appears to be a List<DateTime>,
// so I chose to initialize it along with the other properties.
newTask = new GroupedTask() { ID = null,
TaskID = null,
Date = new List<DateTime>() { tempDate }};
// For each date in the range, check to see if there are any tasks in the TaskList
foreach (var tempItem in TaskList)
{
// If the current item's date matches the current date in the range,
// update the newTask object with the current item's values.
// NOTE: If more than one item has the current date, the last one in
// will win as this code is written.
if (tempItem.Date[0] == tempDate)
{
newTask.ID = tempItem.ID;
newTask.TaskID = tempItem.TaskID;
newTask.Date = tempItem.Date;
}
}
// Add the newTask object to the second list
tempTask.Add(newTask);
}
}
I'm not sure what is EndDate, tempDate and some other things in your example. But if you are trying to loop through a DateRange and checking the existence of a particular date, then you could consider the following example:
static void yourFunction()
{
//
//Some Stuffs
//
foreach (var tempItem in TaskList)
{
if (DateRange.Contains(tempItem.Date[0]))
{
//Do Task
}
else
{
//Do Task
}
}
//
//Some Stuffs
//
}
public static IEnumerable<DateTime> DateRange
{
get
{
for (DateTime day = startDate; day < EndDate; day = day.AddDays(1))
{
yield return day;
}
}
}
Encapsulating a range of dates on a property is the idea of Jon Skeet, I learned it from his book C# in Depth
I found your code a little confusing, but if I understand your intent then I have a solution for you using LINQ. My approach might be a bit confusing to start with, but I'm happy to help you work through it.
My understanding is that you have a range of dates that you want to create a matching list of GroupedTask objects where you will take the object(s) from an existing TaskList for each matching date in the range or create a "dummy" instance if there isn't a match.
I assume that you have defined a StartDate variable along with the EndDate variable you used in your question.
My solution (which I have tested) looks like this:
var query =
from d in dates
from t in getTasksForDate(d)
where (t.ID != null) || (d.DayOfWeek != DayOfWeek.Sunday)
select t;
tempTask.AddRange(query);
Ignoring for the moment the two parts that need to be defined (dates & getTasksForDate) the query works by running through each date from the start to the end and selecting the tasks for that date (either from the TaskList or a "dummy" task if none exist for the date) and then filtering out any "dummy" tasks that fall on a Sunday. The tasks are then added to the tempTask list.
Now for the missing parts.
To get the dates list, just do this:
var days = EndDate.Date.Subtract(StartDate.Date).Days + 1;
var dates =
Enumerable
.Range(1 - days, days)
.Select(d => EndDate.AddDays(d));
As long as StartDate is on or before EndDate you will now have a list of dates that starts on StartDate and ends on EndDate.
The getTasksForDate is the trickier part.
You need to first turn the TaskList list into a lookup function that turns any date into a list of GroupedTask objects for that date. With LINQ it's easy:
var lookup = TaskList.ToLookup(x => x.Date[0].Date, x => new GroupedTask()
{
ID = x.ID,
TaskID = x.TaskID,
Date = x.Date,
});
Next you need to create the getTasksForDate function that will take a date and return either the list of GroupedTask from the lookup for the date or a single "dummy" GroupedTask object if there were no tasks for the date.
Func<DateTime, IEnumerable<GroupedTask>> getTasksForDate = d =>
{
return lookup[d].DefaultIfEmpty(new GroupedTask()
{
ID = null,
TaskID = null,
Date = new List<DateTime>() { d, },
});
};
That's it.
If you want to define StartDate and/or EndDate based on actual values from TaskList you can use this code:
var StartDate = TaskList.Select(t => t.Date[0].Date).Min();
var EndDate = TaskList.Select(t => t.Date[0].Date).Max();
I've used .Date after most of the DateTime references to ensure that there is no time component to the date.
Yell out if you'd like any further explanation.
If I understand what you are trying to do, I would change the way you are doing it in this way. First I would find all the dates in your range that have one or mor associated tasks (and put themn in a Dictionary in order to be able to get them knowing the date), then I would create tempTask. Something like this:
DateTime StartDate;
DateTime EndDate;
DateTime tempDate = StartDate;
List<DateTime> dateToEvaluate;
Dictionary<DateTime, List<Task>> dateTaskDict = new Dictionary<DateTime, List<Task>>();
bool TimeIsPresent = false;
foreach (Task tempItem in TaskList)
{
while (EndDate.AddDays(1) != tempDate)
{
if (tempItem.Date[0] == tempDate)
{
List<Task> tasksForDate;
if (!dateTaskDict.TryGetValue(tempDate, out tasksForDate))
{
tasksForDate = new List<Task>();
dateTaskDict[tempDate] = tasksForDate;
}
tasksForDate.Add(tempItem);
break;
}
tempDate = tempDate.AddDays(1);
}
}
tempDate = StartDate;
while (EndDate.AddDays(1) != tempDate)
{
List<Task> tasks;
if (dateTaskDict.TryGetValue(tempDate, out tasks))
{
foreach (Task aTask in tasks)
tempTask.Add(new GroupedTask { ID = aTask.ID,
TaskID = aTask.TaskID,
Date = tempDate });
}
else
{
if (tempDate.DayOfWeek != DayOfWeek.Sunday)
{
tempTask.Add(new GroupedTask { ID = null
TaskID = null,
Date = tempDate });
}
}
}

Categories

Resources