Cron Timer Progress

For each purchase, when the first general information is entered, a new record is recorded and the STATUS FIELD becomes "START"
On the next page, quantities are chosen based on existing availability and by confirming THE CRON STARTS and at the same time the STATUS FIELD becomes "PROCESSING" and the TIMER FIELD becomes "MINUTES and SECONDS" of the current data time
At the same time, the CRON starts, which only serves to block the procedure and restore the availability at the end of the count
The procedure then continues ..........if you stay on schedule..... .....until you reach the bank checkout
This already works perfectly, regardless of the possibility of displaying a timer

The action of the CRON foresees a minimum of 5 minutes and a maximum of 10 minutes. If I understood correctly, everything depends on the value (MINUTES and SECONDS) of the moment the cron started
In practice, if I'm not dramatically mistaken, to give an example:
If at the starting moment of the CRON the current value is 3 minutes and 10 seconds the end of the CRON count should be 1 minute and 50 seconds + 5 minutes
Therefore the counting duration = 6 minutes and 50 seconds

Having recorded the TIMER FIELD with the values ​​of the moment in which the CRON starts, I thought I could exploit this data to calculate a TIMER that continuously decreases from the value up to zero, which should be the moment in which the CRON blocks the purchase, cancels it and restores availability

Maybe I'm wrong, but I'll do some tests to see if I'm right or wrong

Then there remains the problem of displaying the TIMER, so perhaps I will leave everything as it is and give up the Timer

In practice I have included a field in the database (timer_start) which updates with the datetime of the moment when the Cron starts
If I take into account only the minutes and seconds, I think the calculation of the term of the Cron can be calculated and saved in another field (timer_secondi):

If timer_start (minutes and seconds) = <05:00 (minutes and seconds)
then timer_secondi = (timer_start + 05:00) * 60
or if
If timer_start (minutes and seconds)> 05:00 (minutes and seconds)
then timer_secondi = timer_start * 60

Example: timer_start = 01:24 (minutes and seconds)
timer_secondi = 01:24 + 05:00 * 60 == 384 seconds

Example: timer_start = 08:36 (minutes and seconds)
timer_secondi = 08:36 * 60 == 516 seconds

It's correct?

Hello @Marzio,

I thought you would figured it but i saw you still have dissiculties...

Anyway, I haven't understood how you list and triggering is working and when the purchase is finilized.
BUT, I still don't find the reason you need to set a crom job.

I think the only think you need is a DateTime field/column in your purchases (as you said, you already have this field)
Then all you have to do is show a counter in your page's purchases list.
And finally, prevent the user to finalize a purchase if more thatn 10minutes (600 seconds) have passed.

Please take a look at a new version of it:

  • The green button is triggering the start_counter.
    It's a form that submits the current purchase_id and updates the prh_StartedAt column of purchases table

  • The red button is finilizing the purchase.
    Again another form that submits the purchase_id and check if the elapsed time is more than 600seconds and then execute the purchase finalization (important step)
    In my new example, in my purchase list I have included the form that sublimts the purchase finalization inside a Conditional Region and is rendered only if the elapsed time is less than 600s (10minutes).

I have include all these fields for you to understand how this works...
You can remove or modify them as you wish and perhaps add more columns that you need

<div class="container" id="purchasesTimer">
        <div class="row mt-3">
            <div class="col">
                <button id="btn_addPurchase" class="btn btn-info" data-bs-toggle="modal" data-bs-target="#modal_upsPurchase">New purchase</button>
            </div>
        </div>
        <div class="row mt-4">
            <div class="col">
                <table class="table table-bordered table-sm">
                    <thead>
                        <tr class="text-center">
                            <th>Prh</th>
                            <th class="w-100">Prh name</th>
                            <th class="text-nowrap">Prh started at</th>
                            <th class="text-nowrap">Passed time</th>
                            <th class="text-nowrap">Passed time</th>
                            <th class="text-nowrap">Symbol</th>
                            <th class="text-nowrap">Start</th>
                            <th class="text-nowrap">Start</th>
                        </tr>
                    </thead>
                    <tbody is="dmx-repeat" dmx-generator="bs5table" dmx-bind:repeat="srvc_getPurchases.data.query" id="tableRepeat1">
                        <tr class="align-middle">
                            <td dmx-text="prh_id"></td>
                            <td dmx-text="prh_Name"></td>
                            <td dmx-text="prh_StartedAt.formatDate('H:mm:ss')" class="text-center"></td>
                            <td dmx-text="prh_StartedAt?(prh_StartedAt.secondsUntil(var_DateTime.datetime)+'s'):''" class="text-center"></td>
                            <td dmx-text="prh_StartedAt.secondsUntil(var_DateTime.datetime)&lt;=600?(((prh_StartedAt.secondsUntil(var_DateTime.datetime)/60)%60).floor()+'m'+(prh_StartedAt.secondsUntil(var_DateTime.datetime)%60).floor()+'s'):''" class="text-center"></td>
                            <td class="text-center align-middle">
                                <i class="fas fa-spinner fa-lg" dmx-class:text-success="prh_StartedAt.secondsUntil(var_DateTime.datetime)&lt;300" dmx-class:text-warning="(prh_StartedAt.secondsUntil(var_DateTime.datetime)&gt;=300)&amp;&amp;(prh_StartedAt.secondsUntil(var_DateTime.datetime)&lt;600)" dmx-class:fa-spin="prh_StartedAt.secondsUntil(var_DateTime.datetime)&lt;600" dmx-class:text-danger="prh_StartedAt.secondsUntil(var_DateTime.datetime)&gt;=600" dmx-show="prh_StartedAt"></i>
                            </td>
                            <td>
                                <form id="frm_purchase_Start" is="dmx-serverconnect-form" method="post" action="/api/test/purchase_start" dmx-on:success="notifies1.info('Started...');srvc_getPurchases.load({})">
                                    <input id="ins_prh_id" name="prh_id" class="form-control" dmx-bind:value="prh_id" type="hidden">
                                    <button id="btn_startPurchase" class="btn text-nowrap btn-success" type="submit" dmx-bind:disabled="state.executing" dmx-on:click="cookies1.set('accept','a_Value',{expires: 30})">Start Counter</button>
                                </form>

                            </td>
                            <td>
                                <form id="frm_purchase_Finalize" is="dmx-serverconnect-form" method="post" action="/api/test/purchase_finalize" dmx-on:success="notifies1.info('Started...');srvc_getPurchases.load({})">
                                    <input id="ins_prhFinalize_id" name="prhFinalize_id" class="form-control" dmx-bind:value="prh_id" type="hidden">
                                    <div id="conditional2" is="dmx-if" dmx-bind:condition="!prh_StartedAt||(prh_StartedAt.secondsUntil(var_DateTime.datetime)&lt;=600)">
                                        <button id="btn_startPurchase1" class="btn btn-primary" type="submit" dmx-bind:disabled="state.executing" dmx-on:click="cookies1.set('accept','a_Value',{expires: 30})">Buy</button>
                                    </div>
                                </form>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </div>
    </div>

Here is the api that triggers the start of the counter (updates the prh_StartedAt column of purchases table with the current time - NOW() )

Here is the api for the finilization of the purchase (chech if the elapsed time is <=600seconds)

IN CASE THAT YOUR WORKFLOW IS DIFFERENT please share a small video or screenshots explaining what happens and when it is happenning in order to understand what you need

Hi @famousmag
The Cron is necessary and works well, because automatically checks at regular intervals of 5 minutes if there are records with state == "processing" and in the case of the next check it changes the state == "canceled" and to restore the various availability that temporarily had been awarded to the record

Thank you for your suggestions that in any case will be able to serve me in the future, but I have changed my mind and now I am trying to make a real counter work. It works, even if I have to solve some problems to make it perfect

This is the code suggested by @TMR TMR (How To Create a Countdown Timer)

Now I am trying to optimize it for my need

1 Like

The timer works well but I have two problems to solve
1
How to save the dynamic datetime value (Server Connect Query database) in the var present in the script
2
The exact count should also continue on the next two pages

Anyone know anything?

I'm trying to import the date into javascript by taking it from the ServerConnect (date field present in the database with 2024-06-26 00:19:40 format)
I tried to replace the date with TEXT DATA BINDING - Insert App Connect Binding, but it doesn't work

I don't know if it's the right method and in any case I don't know how to format the date to adapt it to the one entered in javascript

Do you know how?

Schermata 2024-06-27 alle 18.04.04

@Marzio you can check:

If you need to use some dynamic value inside a javascript script:

image

<dmx-value id="var1" dmx-bind:value="'hola'"> </dmx-value>
   
<script>
 function mostrarvar1() {
  var var1 = dmx.parse('var1.value');
  console.log(var1);
}
</script>

Then you'll see:
image


Get a value from a script:

<script>
 function hello() {
  var hola = 'hola2';
  dmx.app.set('valor', hola);
}		
</script>
    <p>{{valor}}</p>

Then:
image

Remember timing is important on javascript and values, you can use a flow with no auto load and use a dynamic success event of a server connect, then the flow can execute your function with the values correctly "loaded".

Thanks, but I still have a problem
The script, as is, with the date entered manually, works fine
I created the variable and populated it with the dynamic data.
But where should I insert it in the script? And above all I can't format the date as it is now in the script

Schermata 2024-06-28 alle 09.00.47

At this point I lost myself

@Marzio maybe It's a timing issue.
The server connect loads after varcrono is declared.

Can you envolve that into a function?
Also add console.log(varcrono);
Then, wait a few seconds, go to console and hit: functionName() and check

I've tried several times but I can't get it to work
Note that the parse statement appears not to be displayed correctly
Furthermore, if I use a manual value (currently disabled) it works correctly, while with the varcrono variable the result is null

Schermata 2024-06-29 alle 11.17.32

Like @franse said...

By the time you call the var in javascript it doesn't have a value because your query hasn't data yet...

So you better add a success event on the above serveraction and then run javascript (function mostravarcrono)
this way you run the function AFTER the query has been executed and return values

(excuse me but I still can't understand why you created a function instead of just using the dateTime component to show the counter...)

Excuse me but what do you mean by using DateTime to display the counter?

I'm just looking for the best solution.
Each database record has a datetime field, where the final time of the timer count is saved (starting from the current moment)
I can't understand how inserting a DateTime can be useful to me

DateTime component is what I have used in my examples (previous posts) to get the current time.

Then we just use the formatter to calculate the time differnece (elapsed time) from the "cronTime":
td dmx-text="prh_StartedAt.secondsUntil(var_DateTime.datetime)&lt;=600?(((prh_StartedAt.secondsUntil(var_DateTime.datetime)/60)%60).floor()+'m'+(prh_StartedAt.secondsUntil(var_DateTime.datetime)%60).floor()+'s'):''" class="text-center"></td>
In case you need to show the remaining time instead of the elapsed time again you can do that with the same way but with different calculation...
Please copy my last example and set your query as a datasourse of the table.
Just bind the column with the "cronTime" instead of prh_StartedAt that I have called in mine example.

I'm a little confused, because I'm starting from a different assumption
I'll explain:
1 STEP
At the beginning of the purchase procedure, the first two pages do not include the use of the timer
2 STEP
Based on availability, the quantities are chosen on the second page and by confirming the quantities the availability is saved and recalculated. At the same time, the "PROCESSING" status is changed and the datetime field is saved by adding 5 minutes to the current date. This data (final time of the timer) is therefore already available in the database
The calculation of the timer then starts from the exact moment of activation and ends at the exact moment of the final time recorded in the database.

The CRON has nothing to do with the Timer, because it travels on its own and only serves to stop the procedure, change the status to "CANCELLED" and restore the availability no longer used.

I really want to help you but I'm confused by the information you give us...

I don't understand the "first 2 steps" you reffer to but you have a right to keep it secret...

Anyway I assume we have a product list:

  1. [page-1], the product list contains all the products with an "add to list" button beside each product to select each one he wants
    The user can select a few of them and make a "purscahse list" (no timer)
    At the top/bottom of the page there is a button that forwards the user to the next step/page

  2. [page-2], the list is limited only to the selected products of the "purchase list" that has been refreshed/reloaded from the database (updated prices, availability/stock etc)
    At this page, beside each product there is a "purchase" button.
    By clicking that button, the product is flagged as "purchased" and the usr have 5 minutes to submit the whole "purchase list".
    It means that the user must submit the whole list af selected products within 5 minutes from the time clicked the first one in the list?
    Example: the user has 5 products in his purchase list and selected all:

  • product-A , selected on 11:14:15
  • product-B , selected on 11:14:35
  • product-C , selected on 11:15:50
  • product-D , selected on 11:16:50
  • product-E , selected on 11:18:15
    If the user click the 'submit list" button at 11:18:50 the above list will be all valid and succesfully submitted.

BUT if the user click the "submit list" button at 11:19:45 product-A and product-B will not be submitted becaused 5 minutes have passed from the time they were selected.

Am I on the correct path?

Sorry but two things here:

image

  1. What is var varcrono.value?, it should be: varcrono.value
  2. You don't need to call mostravarcrono(); like that (last line)
    You need to enter mostravarcrono() on the console and hit enter:
1 Like

Also note:

image

This will run separated, I mean, var countDownDate will be defined with the var value.
But it's for sure, that there's no var value yet, because it's a sc value.
Probably you need to group all your script into a function and call it on a server connect success with a flow.

Like on success of: sc_biglietto_populate run flow (run javascript mostravarcrono)

1 Like

Sorry, but everything is much simpler
In fact I didn't want to confuse things and instead I got the opposite effect, but I didn't want to keep secrets.
I would like to point out that apart from the possibility of inserting a timer, the whole procedure already works wonderfully and does not need to be modified
This is because the functionality of the site is not the sale of generic products, but rather the booking and purchase of trips (BUS Transfer)
The important thing is that the CRON starts automatically when the trip is chosen, with a pre-booking of seats based on availability, thus guaranteeing a time frame of approximately 5/10 minutes
Once the deadline has expired, the procedure is blocked and canceled and the availability of places is updated.
I repeat that all of this is fully functional and does not require modification.


What I'm trying to achieve instead is the possibility of displaying a timer (minutes and seconds), but without the need for
For this reason, in each database record, when the Cron starts, a datetime is also saved at this moment
In Server connect this datetime is added to 5 minutes and serves as a stop time.

I hope I have clarified better

Hi Marzio,

Are you looking at stopping the user to resubmit the booking form before a specified time has elapsed, plus show a countdown timer?

I have a similar setup on the login page. Once a user has requested an OTP Code, the code cannot be resent before 60 seconds from the 1st request have elapsed. If this is what you are thinking of as a process, then I will add the code here.