How to model the opening times of shops in an object oriented way? - oop

What I need
I want to build an application that has a model "shop" in it. Each shop has opening times. These opening times can be quite complex. I think the complexity is best demonstrated by examples:
A shop is open on Monday to Friday, from 10 to 18 o'clock.
A shop is open on Monday to Wednesday from 10 to 18 o'clock, on Thursday from 14 to 18 o'clock, and from 10 to 14 o'clock on Friday.
A shop is open on Monday to Sunday, from 10 to 18 o'clock, but only in a given time span, say from 18th April 2014 to 30th of May 2014
A shop is open on the second Saturday of each month, from 10 to 16 o'clock.
A shop is open all year from Monday to Saturday between 8 and 20 o'clock, but not on a couple of special days, e.g. 24th to 26th December and on easter Monday.
As you can see, there are many complex combinations.
The resulting data structure should support three things:
Return a list of all time spans in which a shop is open for the next half year (or something in that order of magnitude)
Return a human readable representation of the opening times which is shown to end users.
The opening times of a shop will be entered by end users, which should be easily able to specify any of the above possibilities with a form (without training, its on a website).
My approach
I have tried to model this into an object structure. My current idea is this:
Each opening time is an object implementing a common interface.
For each case there is a class implementing it, for example:
One class is a "weekly opening time", which models opening times like #1 (opening and closing time for each day of the week)
One class for specific single dates (24th of December)
One class for recurring times each month (each second Saturday of a month)
One class for bigger time spans (18th April 2014 to 30th of May 2014)
More, if the need occurs.
Each shop has a list of opening times.
Each of these opening times has a list of exceptions to it, where each exception is an opening time itself, which may in turn itself have exceptions.
Problems I see
My greatest concern is usability: How do I print the opening times modeled like this, and how do the users enter them?
I'm open to other approaches. Nothing is implemented yet, and my stomach aches when thinking about the approach above...

(As far as the data-modeling tag is concerned) One single entity :
OpeningPeriod(CalendarDay, OpeningHour, ClosingHour)
or
OpeningPeriod(OpeningTimeStamp, ClosingTimeStamp).
A full opening/closing schedule for any shop/org is a set of such opening periods.
Don't try to capture some sort of "generic all-encompassing predicative way" to describe any possible opening/closing schedule "in full", all exceptions and exceptions-to-the-exceptions included. You will fail because there is no end to the nature of the "exceptions". Also you will be hitting serious problems very quickly when you start trying to "prioritise" between rules that overlap.
Just try to build as much "standard" rule-based facilities in the UI as possible, plus a facility to manage the schedule at the lowest detail of OpeningPeriod, for handling any possible "exception left unhandled by the provided rules".

Related

Group data by weeks since the start of event in sql

I’m a data analyst in the insurance industry and we currently have a program in SAS EG that tracks catastrophe development week by week since the start of the event for all of the catastrophic events that are reported.
(I.E week 1 is catastrophe start date + 7 days, week 2 would be end of week 1 + 7 days and so on) then all transaction amounts (dollars) for the specific catastrophes would be grouped into the respective weeks based on the date each transaction was made.
Problem that we’re faced with is we are moving away from SAS EG to GCP big query and the current process of calculating those weeks is a manually read in list which isn’t very efficient and not easily translated to BigQuery.
Curious if anybody has an idea that would allow me to calculate each week number in periods of 7 days since the start of an event in SQL or has an idea specific for BigQuery? There would be different start dates for each event.
It is complex, I know and I’m willing to give more explanation as needed. Open to any ideas for this as I haven’t been able to find anything.

Organizing per-week and daily data in SQL

Problem overview
I'm working on a simple app for reminding the user of weekly goals. Let's say the goal is to do 30 minutes of exercise on specific days of the week.
Sample goal: do exercise on Mon, Wed, Fri.
The app also needs to track past record, i.e. dates when the user did exercise. It could be just dates, e.g.: 2019-09-02, 2019-09-05, 2019-09-11 means the user did exercise on these days and did not on the others (doesn't need to be on "exercise goal" days of the week).
The goal can change in time. Let's say today is 2019-09-11 and the goal for this week ([2019-09-09, 2019-09-15]) is Mon, Wed, Fri but from 2019-08-05 to 2019-09-08 it was Mon, Thu (repeatedly for all these weeks).
I need to store these week-oriented goals and historic exercise of data and be able to retrieve the following:
The goal days for the current week (or any week, let's say I can compute start and end day for any week given a date).
Exercise history for a larger range of days together with goal days for that range (e.g. to show when the user was supposed to exercise and when they actually did in the last month).
Question
How to best store this data in SQL.
This is a little bit academic because I'm working on a small Android app and the data is just for a single user. So there will be little data and I can successfully use any approach, even a very clumsy one will be efficient enough.
However, I'd like to explore the topic and maybe learn a thing or two.
Possible solutions
Here are two approaches that come to my mind.
In both cases I would store exercise history as a table of dates. If there is an entry for that date it means the user did exercise on that day.
It's the goal storage that is interesting.
Approach 1
Store the goals per-week (it's SQLite so dates are stored as strings - all dates are just 'YEAR-MONTH-DAY'):
CREATE TABLE goals (
start_date TEXT,
exercise_days TEXT);
"start_date" is the first day of the week,
"exercise_days" is a comma-separated list of weekdays (let's say numbers 1-7).
So for the example above we might have two rows:
'2019-08-05', '1,4'
'2019-09-09', '1,3,5'
meaning that since 2019-08-05 the goal is Mon, Thu for all weeks until 2019-09-09, when the goal becomes Mon, Wed, Fri. So there is a gap in the data. I wouldn't want to generate data for weeks starting on 2019-08-12, 2019-08-19, 2019-08-26.
With this approach it is easy to work with the data week-wise. The current goal is the one with MAX('start_date'). The goal for a week for a given date is MAX('start_date') WHERE 'start_date' <= :date.
However it gets cumbersome when I want to get data for the last 3 months and show the user their progress.
Or maybe I want to show the user the percentage of actual exercise days to what they set as their goal in a year.
In this case it seems the best approach is to fetch the data separately and merge it in the application (or maybe write some complex queries), processing week by week. This is ok performance-wise because the amount of data is small and I rarely need more than a handful of weeks.
Approach 2
Store goals in such a way that each goal day is a record:
CREATE TABLE goals (
day TEXT,
);
"day" is a day when the user should exercise. So for the week starting 2019-09-09 (Mon, Wed, Fri) we would have:
'2019-09-09'
'2019-09-11'
'2019-09-13'
and for the week starting 2019-08-05 (Mon, Thu) we would have:
'2019-08-05'
'2019-08-09'
but what for the weeks in-between?
If my app could fill all the weeks in-between then it would be easy to merge this data with the exercise history and display days when the user was supposed to exercise and when they actually did. Extracting the goal for any given week would also be easy.
The problem is: this requires the app to generate data for the "gap" weeks even if the user doesn't tweak the goal. This can be implemented as a transaction that is run each time the app process starts. In some cases it could take noticeable time for occasional users of the app (think progress bar for a second).
Maybe there a smart way to generate the data in-between when making a SELECT query?
I don't like the fact that it requires generating data. I do like the fact that I can just join the tables and then process that (e.g. compute how many exercise days there were supposed to be in August and how many days the user did actually exercise and then show them percentage like "you did 85% of your goal" - in fact I can do this without joining the tables).
Also, it seems this approach gives me more flexibility for analysis in the future.
But is there a third way? Or maybe I am overthinking this? :)
(I am asking mostly for the way of organizing the data, there's no need for exact SQL queries)
Perhaps I'm over-thinking this, but if a goal can have multiple components to it, and can change over time I'd have a goal header record, with the ID, name and other data about the goal as a whole, and then a separate table linked with the components of that goal which are time-boxed, for example:
CREATE TABLE goal_days (goal_day_ID INT,
goal_ID INT,
day_ID INT,
target_minutes INT,
start_date TEXT,
end_date TEXT)
I'd have thought that allows you to easily check against the history to map against each day of the goal - e.g. they got 100% of the Mondays, but kept missing Thursday - however when the goal was changed to Friday instead they got better.

Using SQL for an auto scheduler?

I had a question regarding SQL and if you could code it properly to do auto scheduling.
Example
A shipment could come to a store Monday-Friday, but there could only be a certain amount of shipments during this week and it depends which worker was available. I'll run down things in order that way it's not too confusing.
A) A shipment can only stop twice a day, but it cannot stop on a day that has any shipments the day before or the day after. So if Monday had 2 shipments, there would be no stops on Tuesday. If Wednesday has 2 shipments, you could not have any stops Tuesday/Thursday.
B) A shipment can only be so big on these days. If two shipments are both UNDER 1000 pounds, then we can schedule both, but if a shipment is OVER 1000 pounds, then we can only schedule one for that day.
C) One of the two workers must unload each shipment. So lets say that A already has 1 shipment on Monday, I need it to go to B for the 2nd shipment on that Monday.
I understand that SQL cannot accept user input directly, so don't worry about this. Using getdate() would be sufficient enough.
I started on this code and got a little bit in, but the while loop was running for forever (>30 seconds) and I thought it was almost impractical at that point.
Curious if this is doable and the best approach to do this. I'm assuming that C# or something would be loads easier to do with, but wondering about SQL.
Thanks in advance.

How to Extend the End Date in a SQL Calendar Table?

I have a report that, according to users, started miscalculating dates in one field in November 2015. After some digging around, I found that one of the tables the field referenced seemed to have an end date on 2015-10-31.
The "D" field seems to represent the day of the week, with Sunday being day 1 and Saturday being 7.
Is there a way to extend the calendar so that it ends further into the future, for example 2049-12-31?
Our calendar table, for a variety of reasons, goes the the end of the current year. We have written a query that adds a new year to this table. This query takes care of most of the fields in that table. It does not touch the holiday field. That is updated manually through a web page.
We send ourselves reminders. Starting in March, we send monthly reminders that we should think about adding another year. After ensuring that the database segment has space, and that none of the definitions, such as fiscal periods, have changed, we run the query that adds a year.
Later in the year we start mailing ourselves reminders about the holidays. Then we check to see if HR has declared them, and if so, update the records accordingly.
This meets our business requirements. Yours will be different of course.

how to model (mvc) an abstract time period for employe shift management

I've started thinking about an employee shift management application to handle the shifts (who works when, trading, etc) at my current workplace (that uses pen and paper and hasn't got anyway for us employees to communicate about changes without going through the boss and be on site).
Currently the shifts are modeled loosely as:
There is a recurring 4 week period (from Monday week 1 to Sunday week 4)
There is a template for placing employees in this 4 week period
Every 4 months (ie 3 times a year) the 4 week template is projected over the next 4 month period
The shifts have been the same for a long time and it seems many employees would prefer to have them changed (I can say this by the requests for change that come in every time a new 4 month is set).
What I'm aiming at are the models:
Shift_group_tpl (the 4 week period above)
Shift_tpl (a single shift in the 4 week period, including info on who defaults to work this shift)
Shift_group (a set period of time whit actual shifts)
Shift (a set shift whit a real time period and an employee - and the possibility to be changed both in start_time, end_time and employee)
I've thought of a way to do this with recurring iCalendar events: Creating RRULE's (without an endtime) and then calculate (using temporary start and end times) if that specific Shift_group_tpl could be used within a real Shift_group. (The problem with this approach is that I can't figure out how to trim the Shift_group_tpl's to fit into the start or end of a Shift_group.)
What I'm looking for are some other perspectives or ways of doing it or even just a pat on the shoulder letting me know that I'm on the right track (and then giving advice on the trimming problem).
/iole1
What I'm aiming at are the models:
Shift_group_tpl (the 4 week period above)
Shift_tpl (a single shift in the 4 week period, including info on who defaults to work this shift)
Shift_group (a set period of time whit actual shifts)
Shift (a set shift whit a real time period and an employee - and the possibility to be changed both in start_time, end_time and employee)
You have "sql" as a tag for this post? So im guessing you want these as SQL tables?
By the sounds, the problem is that your considering the data you have, rather than the abstract concepts you need to store that data. Which is what you'd need to do to create an application. (Most likely a "Shifts" table, rather than the four tables above).
There is little information here to help, Consider refining your thoughts and ask another question.