Skip to content

Commit 841a2a2

Browse files
author
Ivo Salmre
committed
Added ability to export a CSV of reservations details
1 parent 3474b83 commit 841a2a2

10 files changed

+400
-23
lines changed

CloudbedsApp/CloudbedsDailyOperationsReportManager.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ public ICollection<DailyReport> DailyReports
2222
}
2323

2424
private ReadOnlyCollection<DailyReport> _dailyReports;
25+
26+
/// <summary>
27+
/// Constructor
28+
/// </summary>
29+
/// <param name="dateStart"></param>
30+
/// <param name="dateEnd"></param>
31+
/// <param name="reservationSet"></param>
2532
public CloudbedsDailyOperationsReportManager(DateTime dateStart, DateTime dateEnd,
2633
ICollection<CloudbedsReservationWithRooms> reservationSet)
2734
{
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+

2+
using System;
3+
using System.IO;
4+
using System.Text;
5+
using System.Threading;
6+
using System.Web;
7+
using System.Collections.Generic;
8+
9+
/// <summary>
10+
/// </summary>
11+
internal partial class CloudbedsDailyOperationsReportManager_ResRoomDetails
12+
{
13+
14+
/// <summary>
15+
/// Daily report for operations
16+
/// </summary>
17+
public class DailyReportSet
18+
{
19+
public readonly DateTime Date;
20+
21+
/// <summary>
22+
/// The sub reservations active on this date
23+
/// </summary>
24+
readonly IReadOnlyCollection<CloudbedsReservationRoom> _resRoomsForDate;
25+
26+
27+
/// <summary>
28+
/// All the sub reservations that intersect with this date
29+
/// </summary>
30+
public IReadOnlyCollection<CloudbedsReservationRoom> SubReservations
31+
{
32+
get
33+
{
34+
return _resRoomsForDate;
35+
}
36+
}
37+
38+
/// <summary>
39+
/// Constructor
40+
/// </summary>
41+
/// <param name="date"></param>
42+
/// <param name="reservationRoomsForDate"></param>
43+
public DailyReportSet(
44+
DateTime date,
45+
ICollection<CloudbedsReservationRoom> reservationRoomsForDate)
46+
{
47+
this.Date = date;
48+
_resRoomsForDate = new List<CloudbedsReservationRoom>(reservationRoomsForDate).AsReadOnly();
49+
}
50+
}
51+
}
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+

2+
using System;
3+
using System.Collections;
4+
using System.Collections.Generic;
5+
using System.Collections.ObjectModel;
6+
using System.Globalization;
7+
using System.IO;
8+
using System.Linq;
9+
using System.Text;
10+
using System.Threading;
11+
using System.Web;
12+
using static CloudbedsDailyOperationsReportManager;
13+
14+
/// <summary>
15+
/// Produces a more detailed report showing every reservation that intersects with a given date
16+
/// Has a row for every [date]x[sub-reservation]
17+
/// </summary>
18+
internal partial class CloudbedsDailyOperationsReportManager_ResRoomDetails
19+
{
20+
private readonly ReadOnlyCollection<DailyReportSet> _dateRangeReportSet;
21+
22+
23+
/// <summary>
24+
/// Constructor
25+
/// </summary>
26+
/// <param name="dateStart"></param>
27+
/// <param name="dateEnd"></param>
28+
/// <param name="reservationSet"></param>
29+
public CloudbedsDailyOperationsReportManager_ResRoomDetails(DateTime dateStart, DateTime dateEnd,
30+
ICollection<CloudbedsReservationWithRooms> reservationSet)
31+
{
32+
_dateRangeReportSet = GenerateDateRangeReportSet(dateStart, dateEnd, reservationSet).AsReadOnly();
33+
}
34+
35+
/// <summary>
36+
/// Generate a CSV report with a row for each day
37+
/// </summary>
38+
/// <param name="prefixResValues">Because Excel will by default parse these large numbers into scientific notation, we may want to make them strings</param>
39+
/// <param name="prefixSubResValues">Because Excel will by default parse these large numbers into scientific notation, we may want to make them strings</param>
40+
/// <returns></returns>
41+
public CsvDataGenerator GenerateCsvReport(string prefixResValues = "res:", string prefixSubResValues = "subres:")
42+
{
43+
var csvManager = new CsvDataGenerator();
44+
prefixResValues = StringHelpers.CannonicalizeBlankString(prefixResValues);
45+
prefixSubResValues = StringHelpers.CannonicalizeBlankString(prefixSubResValues);
46+
47+
48+
string[] keys = {
49+
"DATE" //[0]
50+
, "RESERVATION-ID" //[1]
51+
, "SUB-RESERVATION-ID" //[2]
52+
, "IN-STAY-STATE" //[3]
53+
, "GUEST-ID" //[4]
54+
, "GUEST-NAME" //[5]
55+
, "ROOM-ID" //[6]
56+
, "ROOM-NAME" //[7]
57+
, "ROOM-TYPE" //[8]
58+
, "CHECK-IN" //[9]
59+
, "CHECK-OUT" //[10]
60+
, "RESERVATION-STATUS" //[11]
61+
};
62+
63+
64+
//Add a CSV row for each of the days
65+
foreach(var singleDayReport in _dateRangeReportSet)
66+
{
67+
foreach(var subReservation in singleDayReport.SubReservations)
68+
{
69+
70+
string stayStateForDate = helper_GenerateStateStateForDate(singleDayReport.Date, subReservation);
71+
72+
string[] values = new string[keys.Length];
73+
values[0] = singleDayReport.Date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
74+
values[1] = prefixResValues + subReservation.ParentReservationId;
75+
values[2] = prefixSubResValues+ subReservation.SubReservationId;
76+
values[3] = stayStateForDate;
77+
values[4] = subReservation.Guest_Id;
78+
values[5] = subReservation.Guest_Name;
79+
values[6] = subReservation.Room_Id;
80+
values[7] = subReservation.Room_Name;
81+
values[8] = subReservation.Room_TypeName;
82+
values[9] = subReservation.Room_CheckIn.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
83+
values[10] = subReservation.Room_CheckOut.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
84+
values[11] = subReservation.Room_Status;
85+
86+
csvManager.AddKeyValuePairs(keys, values);
87+
88+
}
89+
}
90+
91+
return csvManager;
92+
}
93+
94+
/// <summary>
95+
///
96+
/// </summary>
97+
/// <param name="date"></param>
98+
/// <param name="subReservation"></param>
99+
/// <returns></returns>
100+
private static string helper_GenerateStateStateForDate(DateTime date, CloudbedsReservationRoom subReservation)
101+
{
102+
if (date < subReservation.Room_CheckIn)
103+
{
104+
return "error: before check in date";
105+
}
106+
107+
if (date > subReservation.Room_CheckOut)
108+
{
109+
return "error: past check out date";
110+
}
111+
112+
if (date == subReservation.Room_CheckIn)
113+
{
114+
return "check-in today";
115+
}
116+
117+
if (date == subReservation.Room_CheckOut)
118+
{
119+
return "check-out today";
120+
}
121+
122+
return "middle of stay";
123+
}
124+
125+
/// <summary>
126+
/// Builds reports for the range of dates
127+
/// </summary>
128+
/// <param name="dateStart"></param>
129+
/// <param name="dateEnd"></param>
130+
/// <param name="reservationSet"></param>
131+
/// <returns></returns>
132+
private List<DailyReportSet> GenerateDateRangeReportSet(DateTime dateStart, DateTime dateEnd, ICollection<CloudbedsReservationWithRooms> reservationSet)
133+
{
134+
var outSet = new List<DailyReportSet>();
135+
var dateCurrent = dateStart.Date;
136+
while (dateCurrent <= dateEnd)
137+
{
138+
var reportForDate = GenerateDailyReportSet_SingleDate(dateCurrent, reservationSet);
139+
140+
if (reportForDate != null)
141+
{
142+
outSet.Add(reportForDate);
143+
}
144+
145+
//Advance 1 day
146+
dateCurrent = dateCurrent.AddDays(1);
147+
}
148+
149+
return outSet;
150+
}
151+
152+
153+
/// <summary>
154+
/// Deternates a daily operational report object for a SINGLE day
155+
/// </summary>
156+
/// <param name="dateCurrent"></param>
157+
/// <param name="reservationSet"></param>
158+
/// <returns></returns>
159+
private DailyReportSet GenerateDailyReportSet_SingleDate(DateTime dateTarget, ICollection<CloudbedsReservationWithRooms> reservationSet)
160+
{
161+
List<CloudbedsReservationRoom> outputSetOfSubReservation = new List<CloudbedsReservationRoom>();
162+
//============================================================================
163+
//Look at each reservation in the set and see if it effects this date.
164+
//Reservations may have multiple rooms with different check in/out dates
165+
//============================================================================
166+
foreach (var thisReservation in reservationSet)
167+
{
168+
if (thisReservation.Reservation_Status != CloudbedsReservationStatus.STATUS_CANCELED)
169+
{
170+
171+
helper_addSubReservationsWithIntersectingDates(dateTarget, outputSetOfSubReservation, thisReservation);
172+
}
173+
}
174+
175+
return new DailyReportSet(dateTarget, outputSetOfSubReservation);
176+
}
177+
178+
/// <summary>
179+
/// Add any sub-reservation with an intersecting date into the set
180+
/// </summary>
181+
/// <param name="dateTarget"></param>
182+
/// <param name="appendTo_subReservations"></param>
183+
/// <param name="thisReservation"></param>
184+
/// <exception cref="NotImplementedException"></exception>
185+
private void helper_addSubReservationsWithIntersectingDates(DateTime dateTarget, List<CloudbedsReservationRoom> appendTo_subReservations, CloudbedsReservationWithRooms thisReservation)
186+
{
187+
foreach(var thisSubReservation in thisReservation.ReservationRooms)
188+
{
189+
helper_addSubReservationsWithIntersectingDates_subReservation(dateTarget, thisSubReservation, appendTo_subReservations);
190+
}
191+
}
192+
193+
/// <summary>
194+
/// Look at an individual sub-reservation and see if it needs to get added to the set
195+
/// </summary>
196+
/// <param name="dateTarget"></param>
197+
/// <param name="thisSubReservation"></param>
198+
/// <param name="appendTo_subReservations"></param>
199+
private void helper_addSubReservationsWithIntersectingDates_subReservation(DateTime dateTarget, CloudbedsReservationRoom thisSubReservation, List<CloudbedsReservationRoom> appendTo_subReservations)
200+
{
201+
//If sub reservation is BEFORE the date, do nothing
202+
if(dateTarget < thisSubReservation.Room_CheckIn)
203+
{
204+
return;
205+
}
206+
207+
//If sub reservation is AFTER the date, do nothing
208+
if (dateTarget > thisSubReservation.Room_CheckOut)
209+
{
210+
return;
211+
}
212+
213+
//Add it to the set that intersects today
214+
appendTo_subReservations.Add(thisSubReservation);
215+
}
216+
}
217+

CloudbedsApp/CloudbedsSessionState.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,28 @@ public CloudbedsDailyOperationsReportManager GenerateDailyOperationsReports()
7070
return new CloudbedsDailyOperationsReportManager(dateReportStart, dateReportEnd, reservationsSet);
7171
}
7272

73+
/// <summary>
74+
/// Genrate the daily operations report
75+
/// </summary>
76+
/// <returns></returns>
77+
public CloudbedsDailyOperationsReportManager_ResRoomDetails GenerateDailyOperationsReports_ResRoomDetails()
78+
{
79+
var reservationsManager = EnsureReservationWithRoomsManager();
80+
reservationsManager.EnsureCachedData();
81+
82+
//=============================================================
83+
//UNDONE: We will want this function to take a DATE-RANGE in
84+
//to ensure we have data for the known dates.
85+
//=============================================================
86+
DateTime dateReportStart = DateTime.Today;
87+
DateTime dateReportEnd = dateReportStart.AddDays(60);
88+
89+
90+
var reservationsSet = reservationsManager.Reservations;
91+
92+
return new CloudbedsDailyOperationsReportManager_ResRoomDetails(dateReportStart, dateReportEnd, reservationsSet);
93+
}
94+
7395
/*
7496
/// <summary>
7597
/// Refresh scheduler

CloudbedsApp/CloudbedsSingletons.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,17 @@ public static CloudbedsDailyOperationsReportManager GenerateDailyOperationsRepor
6262
return s_selectedCBSessionState.GenerateDailyOperationsReports();
6363
}
6464

65+
66+
/// <summary>
67+
/// Genrate the daily operations report
68+
/// </summary>
69+
/// <returns></returns>
70+
public static CloudbedsDailyOperationsReportManager_ResRoomDetails GenerateDailyOperationsReports_ResRoomDetails()
71+
{
72+
EnsureServerInfo();
73+
74+
return s_selectedCBSessionState.GenerateDailyOperationsReports_ResRoomDetails();
75+
}
6576
/// <summary>
6677
/// Refresh scheduler
6778
/// </summary>

0 commit comments

Comments
 (0)