How do I store a toggleable duration in a database - mysql

I want to give users of my Laravel Application the option to track the time they spend on different tasks. On clicking a "start" button, I want to create a new instance of a "tracking" object, which has an id and a reference to the task it is tracking the time for as a foreign key. Also, I want to store a timestamp from the second it was created on. Later, the user is supposed to stop the tracking with another button click.
I need to store the duration of the tracking somehow, because I want to give reports of what task had how many trackings, what was the total time of all summed up, etc. It would be an option to calculate the duration by subtracting start from stop, as soon as the tracking is being stopped and save it to the object.
However, I want the user to be able to continue a tracking later, so that it starts counting again. If I would then set the timestamp on ending again, it would calculate the entire duration, even though it could have been disabled inbetween.
Another idea was to have a last_started and a total_duration column. When the user (re-)starts a tracking, the timestamp is included. As soon as he closes it, the duration is added to the current total_duration and and last_started is set to null again. This feels like a dirty workaround and I am sure there are better options out there, which I would love to hear.
Thanks in advance!

Your question is a bit vague to me, but if I understand correctly, you just want ONE tracking record per task per user. I don't see why you can't make it a bit easier.
Create a model TaskTimeTrack with
user_id
task_id
starttime
endtime
then in your controller, you should probably have a method start and stop
In your start method check if you have a TaskTimeTrack record for the user and the task and endtime IS NULL; if so, he shouldn't be able to start a new tracking, as he is still on an active tracking; just return the existing TaskTimeTrack (if you want to return anything)
If you don't find such record, just create a new one then.
In your stop method, just search for the TaskTimeTRack for the user and task where endtime IS NULL, and update the endtime to NOW.
there is no reason why you would want to limit just 1 record per user / task. You just calculate the total time by sum(endtime - starttime) of all the TaskTimeTRack for a particular user or task or combination of both.

Related

Auto edit MySQL data after a given time

We have a form which is stored in draft mode. That means editing any data or deleting the entire form is possible. The beginning to end process is as follows
When a person tries to submit the form for the first time, that is stored in draft. (the isDraft column is set to 0)
The user is redirected to another page where s/he can view the Form id (a generated number), name, a few other details and Edit/Delete options.
The user can click edit button to edit anything, or even delete the form.
However this will be allowed till a given date (say 15 days from the first submission date). Once that date is passed, the form can no longer be edited or deleted. In case the form isn't deleted, the isDraft column is set to 1.
Thousands of people can submit the form . So ,it is not possible to do it manually.
Our project is done using Laravel v6.2, but I want a general idea as well .
I can use a trait or ajax on the master page, but that is too risky and also, server inaccessibility can delay the process, and some users may get an advantage.
How to do it?
If there is no concrete answer, but rather only discussion , I will remove this post
Just store the date (time component depends on how accurate you want to be when you check the 15 day interval) when the form is created as draft.
When a user wants to edit it (display the edit form) or save an edit, compare the current date (and time) with the stored creation date + 15 days. If the current date is less than the creation date + 15 days, then allow the display of the edit form or save the form, otherwise display an error message.
Not sure if I understand it correctly, but I think you like to update the updated_at timestamp automatically. You can run through the Eloquent Models by create a command and just call the save Method on them.
$model->save()

Summing a ledger over long period of time. (reconciliation, snapshots, rolling sum?)

We are building a warehouse stock management system and have a stock movements table that records stock into, through and out of the system, for each product and each location it is stored. i.e.
10 units of Product A is received into Location A
10 units Product A are moved to Location B and removed from Location A.
1 unit is removed (sold) from Location B
... and so on.
This means that over to work out how much of each product is stored in each location we would;
"SELECT SUM('qty') FROM stock_movements GROUP BY location, product"
(we actually use Eloquent but I have used SQL for an example)
Over time, this will mean our stock movements table will grow to millions of rows and I am wondering the way to best manage this. The options I can think of:
Sum the rows as grouped above and accept it may get slow over time. Im not sure how many rows it will take before it actually starts to cause any performance issues. When requesting a whole inventory log via our API each row would have to be summed for every product, so this will compile to a fairly large calculation.
Create a snapshot of the summed rows every day/week/month etc. on a cron and then just add the sum of the most recent rows on the fly.
Create a separate table with a live stock level which is added to and subtracted with every stock movement. The stock movements table shows an entire history of all movements while the new table just shows the live amounts. We would use database transactions here to ensure they keep in sync.
Is there a defined and best practice way to handle this kind of thing already? Would love to hear your thoughts!
The good news is that your system is already where a lot of people say the database world should be moving: event sourcing. ES just stores every event against an object, in this case your location, and in order to get the current state you have to start with an empty object and replay all of that objects events.
Of course, this can be time-consuming, and your last two bullet points are the standard ways of dealing with it. First, you can create regular snapshots with the current-as-of-then totals for that location, and then when someone asks for the current-as-of-now totals you only need to replay events since the last snapshot. Second, you can have a separate table of current values, and whenever you insert a record into your event store you also update the current value. If they ever get out-of-sync, you can always start fresh and replay the entire event series again.
Both of these scenarios are typically managed through an intermediary queue service, like SQL's Service Broker, RabbitMQ, or Amazon's SQS: instead of inserting an event directly into your event store, you send the change into a queue and the code that processes the queue will update your snapshot.
Good luck!

How to schedule an event in Mysql on table update?

I want to initiate an action after 7 days from the day a specific field in my database table is updated.
I can use trigger to trigger an event on update of field in the database table. But how can I make it wait for 7 days. I was looking for scheduling an Event but that can only be scheduled for specific time. Is there any way to dynamically set the schedule time?
There are 2 ways to do it:
You store in a timestamp field when the record was last updated. You schedule a regular event to be run every couple of hours. The event's code scans the table in question and does whatever needs to be done for those records those timestamp is between the lust run of the even and the current time.
If you have lots of records you need to handle such events, then this is the recommended approach. The drawback is that timing of the event may not be fully accurate, depending on how often you schedule this event to run.
Every time you update the record you create an event specifically for that record in a trigger or stored procedure that triggers in 7 days time.
This approach gives you absolute accuracy over when an event is triggered, however, if you have a large number of changes, then this solution does not scale well.
An alternative solution could be to record the time when the change was done, but instead of event triggering base your code on user interaction. So, if the user, whose data has been updated logs on then you notify him about what you want regarding those updates that were done more than 7 days ago and the events were not seen by the user.

Retrieving sql database records based on time continuously

I have an online database CUSTOMERINFO with more than 100k details stored like following format Cust Id, Customer name, Addr, Phone,.......,Call back time
I want to retrieve data when call back time equals current time automatically.
I have designed front end with Java and currently 10 employees working with the database and now they are manually retrieving the data by ID,..
I know select command is very useful to retrieve but I want it to do automatically instead of calling each time manually.
Edited:
When the customer data is retrieved from table, either we will set another call back time or no call back and then pushed into table again.. In the next time if no call back is set in the place of call back time that row no need to be retrieved.
I'm likely missing something here, but:
Something like SELECT ... FROM table WHERE 'Call back time' >= NOW()
I'd recommend not using simply equals, as has been said in the comments, because you might miss items.
If you update the callback time after you have retrieved the callback items, that should work as long as you do not do the query to get callbacks more than once every few seconds.
As was mentioned in the comments, this is just the start though. There are going to be other issues you'll have to deal with.

How to calculate the difference between times and store the result in a mySQL database (VB.NET)?

I'm quite new to VB and i'm working on a project to record the details of employees clocking in and clocking out. I want to know how to make it so when the 'clock in' button is clicked the time will start recording and when the 'clock out' button is pressed the time will stop recording. Also once clock out is clicked the hours in between clock in and clock out will be recorded and stored into a mySQL database.
This information will be outputted onto a DataGrid showing the time and date of when the employee has clocked in.
Then the amount of hours will be multiplied by a pre-written hourly wage .. which is already stored inside one of the tables in my mySQL database.
Any help would be appreciated.
You should store the event instead of the result.
Store the clock-in time as well as a row for the clock-out time.
Then you will need a procedure either on your database or in the application that will iterate over the rows and match clock-ins to clock-outs.
This approach will let the application crash/terminate and restart without losing data.
Alternatively you could put the clock-in and out in the same record (different columns), and just insert the clock-out into the first row that matched employee and null clock-out.
I would have the clock In button fire an event in the program that created a record for the employee ID I'm assuming you have at that time.
Then once the clock out button is clicked you would fire an event that would go out to your database and pull in the first record it found with the employee ID you are looking for, a valid clock in time and a null for the clock out time. If the program didn't find something that matched all that criteria you would have to handle that however you wanted (I would do the lookup when the employee logged in or whatever and only allow them access to the clock in button if there was no record present and only allow them to use the clock out button if there was a record found for their ID).
Once you have that record in memory you should set the clock out time and calculate the difference using the clock in time that was written to the database earlier.
I would use a stored procedure in the database to handle adding/updating/managing the record and do all the calculations and whatever else you want to do at the time of the clock in/out inside the program itself. But I think its all just preference as far as where the actual processing takes place is concerned.
The most obvious reason for this is that the program can be shut down in between clock in's and clock out's without losing anything at all. If you try to keep track of it all in memory you will lose all your clock in's once the program is shut down for whatever reason(closed manually/"End Task"ed through task manager/unhandled error).