Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!

Warn X days before report due

Oct
364
17
Problem:
  1. Certain reports are due on 1st and 15th of month.
  2. Certain preparations have to be done 1 business day before.
  3. The user needs a warning 2 business days before (i.e., "Need to prep tomorrow. Report due on 15th.)
  4. But if the 1st or 15th falls on a weekend the reports are sent the next business day. (E.g., report sent Monday 17th.)
  5. The warnings have to be on business days--a warning on Saturday the 15th won't be seen.
Assumptions:
  1. "Business" day means Monday-Friday. The function wouldn't handle holidays.
  2. Reports might have to be filed on or before the 1st and 15th rather than the next business day after.
  3. January (e.g.) and February would cause problems--you can't just pop up on the 27th, 28th, etc., "1st of Month report due." Users would get annoyed having the "2 day" warning pop up for 4 days and some would start ignoring it.

    On the other hand, if the 1st is a Monday, then having it pop up on the 27th might not have it seen for 4 days.
 
Code:
:: check-comments.btm
::
:: Checks the date specified and warns X days before
:: report is due.  This can be called from another
:: program: check-comments.btm 2017-05-01

@echo off

Set OrigDueDate=%1
IFF "%OrigDueDate" NE "" THEN
    Set DueDate=%OrigDueDate
ELSE
    Set DueDate=%_isodate
ENDIFF

    :: Output format: 4=iso
    :: %@Inlieu[date, output format, bef/aft]
        :: 0=nearest, 1=prev Friday, 2=following Monday, 3=Sun>Mon
    :: %@DatePlus[date, add/sub, output format]

    :: Number of days before the due date that the report must be prepared
    Set PrepDays=2

    :: Number of days before the prep date that the reminder must be shown.
    Set PrepWarnDays=3

:: Starting with theoretical due date (1st or 15th) then
:: return actual due date
    Set DueDate=%@INLIEU[%DueDate, 4, 2]

    :: PrepDate is 1 day before DueDate
    Set PrepDate=%@DATEPLUS[%DueDate,-%PrepDays,4]
    :: If PrepDate is a weekend, move to Friday
    Set PrepDate=%@INLIEU[%PrepDate, 4, 1]

    :: WarnDate is 1 day before PrepDate
    Set WarnDate=%@DATEPLUS[%PrepDate,-%PrepWarnDays,4]
    :: If WarnDate is a weekend, move to Friday
    Set WarnDate=%@INLIEU[%WarnDate, 4, 1]

    :: Just for test purposes
    IFF 1 EQ 1 THEN
        Echo.
        Echo Due  Date: %DueDate  (%@DOWF[%DueDate])
        Echo Prep Date: %PrepDate  (%@DOWF[%PrepDate])  (%PrepDays days)
        Echo Warn Date: %WarnDate  (%@DOWF[%WarnDate])  (%PrepWarnDays days)
        Echo.
    ENDIFF

PAUSE
QUIT
 
When using a plugin in a .BTM file, it is best to make sure that the plugin is loaded, example;
Code:
if not plugin iso8601 plugin /l c:\users\jlc\utils\iso8601-x64.dll

To make sure that the plugin has the required variable, function, or command;
Code:
if isplugin @inlieu echo Yes

Finally, a comment in the .BTM with a link to where the plugin can be downloaded from;
Code:
::http://prospero.unm.edu/plugins/iso8601.html

This makes things easier when modifying the .BTM in the future, and also for others who will be using the .BTM

Joe
 
Sometimes, it can be easier to just have a pre-loaded list of dates. In your example you need 24 dates for an entire year.
 
Here's the working version. This requires Charles Dye's plug-in.

Note that you can test any date by adding it in isodate format as a command-line parameter.

Code:
:: check-comments.btm
::
:: Checks the current date and warns X days before
:: comments are due.
::
:: FOR TESTING you can include a date in isodate format:
:: check-comments 2016-03-29

@echo off

SETLOCAL

    Set Iso_Fmt=4

    Set PrepDays=1
    Set PrepWarnDays=1

    :: Get "today"
    Set Iso_Today=%_isodate

    :: *********************
    :: **      Test       **
    :: *********************
    IF "%1" NE "" Set Iso_Today=%1
    ::    For test purposes, if check-comments.btm is called with an
    ::    ISO-date parameter that date will be used instead.

:: goto TEST_SET_DATE_INFO

::    Return "theoretical" date: 1st or 15th in Comments_Due_Date
    GOSUB GET_THEORETICAL_DUE_DATE

::    Calculate actual DueDate, PrepDate, and Warning Date
    GOSUB CALCULATE_DATES %Comments_Due_Date
    unset Comments_Due_Date

::    Check "today" against the dates, show applicable warnings
    GOSUB SHOW_WARNINGS %Iso_Today

ENDLOCAL
QUIT


::******************************************************
:GET_THEORETICAL_DUE_DATE
::
::    Creates and sets Comments_Due_Date to the next
::    theoretical due date (1st or 15th) based on "today's" date.
::
::    This gets fed to the routines that calculate the actual
::    dates for warning, prep and due
::
::******************************************************

    Set today_DOM=%@Day[%Iso_Today]

    :: Default to 15th of THIS month
    Set Comments_Due_Date=%@left[7,%Iso_Today]-15

    :: If today is 1st, change to 1st
    IFF %today_DOM EQ 1 THEN
        Set Comments_Due_Date=%Iso_Today

    ELSEIFF %today_DOM GT 15 THEN
        :: If today is after the 15th
        :: Add 20 days, to kick into next month
        Set Comments_Due_Date=%@DatePlus[%Iso_Today,20,%Iso_Fmt]
        :: Set date to 1st of next month
        Set Comments_Due_Date=%@left[7,%Comments_Due_Date]-01
    ENDIFF

    UNSET today_DOM
RETURN
:: End of GET_THEORETICAL_DUE_DATE


::******************************************************
:CALCULATE_DATES [in_date]
::
::    Calculate actual DueDate, PrepDate, and Warning Date for
::    PrepDate.  Adjust for weekends.
::
::    DueDate must be contain an isodate
::
::    Sets DueDate, PrepDate and WarnDate
::
::******************************************************

:: Starting with theoretical due date (1st or 15th) return
:: actual due date
    Set DueDate=%@INLIEU[%in_date, %Iso_Fmt, 2]

    :: PrepDate is 1 day before DueDate
    Set PrepDate=%@DATEPLUS[%DueDate,-%PrepDays,%Iso_Fmt]
    :: If PrepDate is a weekend, move to Friday
    Set PrepDate=%@INLIEU[%PrepDate, %Iso_Fmt, 1]

    :: WarnDate is 1 day before PrepDate
    Set WarnDate=%@DATEPLUS[%PrepDate,-%PrepWarnDays,%Iso_Fmt]
    :: If WarnDate is a weekend, move to Friday
    Set WarnDate=%@INLIEU[%WarnDate, %Iso_Fmt, 1]

RETURN
:: End of CALCULATE_DATES


::******************************************************
:SHOW_DATE_INFO
::
::    Display DueDate, PrepDate and WarnDates
::    ONLY FOR TEST AND DEVELOPMENT
::******************************************************

    Echo.
    Echo Due  Date: %DueDate   (%@DOWF[%DueDate])
    Echo Prep Date: %PrepDate  (%@DOWF[%PrepDate])  (%PrepDays days)
    Echo Warn Date: %WarnDate  (%@DOWF[%WarnDate])  (%PrepWarnDays days)
    Echo.

    PAUSE
RETURN
:: End of SHOW_DATE_INFO


::******************************************************
:SHOW_WARNINGS [in_date]
::
::    in_date should always be "today" unless testing
::
::    Displays warnings for the various days.
::
::******************************************************

:: GOSUB SHOW_DATE_INFO

    Set Show_Pause=Yes
    COLOR BRIGHT RED ON BRIGHT WHITE
    IFF %in_date EQ %WarnDate THEN
        Echo.
        Echo    COMMENTS ARE DUE %@DateConv[%DueDate,%Iso_Fmt,17]
        Echo.
        Echo    THEY MUST BE PREPARED ON %@DateConv[%PrepDate,%Iso_Fmt,17]

    ELSEIFF %in_date EQ %PrepDate THEN
        Echo.
        Echo    COMMENTS ARE DUE %@DateConv[%DueDate,%Iso_Fmt,17]
        Echo.
        Echo    THEY MUST BE PREPARED TODAY %@DateConv[%PrepDate,%Iso_Fmt,17]

    ELSEIFF %in_date EQ %DueDate THEN
        Echo.
        Echo    COMMENTS ARE DUE TODAY %@DateConv[%DueDate,%Iso_Fmt,17]

    ELSE
        Set Show_Pause=No
    ENDIFF

    COLOR BLUE ON BRIGHT WHITE
    IFF %Show_Pause EQ Yes THEN
        Echo.
        PAUSE
        Echo.
    ENDIFF
    unset Show_Pause

RETURN
:: End of SHOW_WARNINGS [in_date]
 
There are some problems with the code that I haven't looked into in detail:

Try it with the dates (Sat) 2017-07-15, (Sun) 2017-07-16 and (Mon) 2017-07-17. It won't show anything, because it will calculate the due date as 2017-08-01.

On the 16th it will calculate the theoretical due date as the 1st of the following month. What if the 15th is a Saturday, meaning the comments are actually due on the 17th?

In GET_THEORETICAL_DUE_DATE it seems better to change GT 15 to GT 18 (or maybe GT 17).

But, basically, this is intended to check every business day and warn in advance.
 
Sometimes, it can be easier to just have a pre-loaded list of dates. In your example you need 24 dates for an entire year.

The problem with pre-loaded dates is that it would require manually calculating 72 dates per year and changing the software every year--the "Need to Prepare tomorrow" date, the "Need to Prepare today" date and the "Due Today" date for 2 due dates per month.
 
Last edited:
Just an observation: This application seems to be stretching the btm beyond it's current features.

Would this function/application be worth adding to the Suggestions as a TCC internal cmd/function/variable?

I do not think I can describe this in general enough terms, with options etc. to add it myself.

Perhaps between the thread contributors and/or Rex a description could be put together that will solve the OP and also provide a more general application to the TCMD/TCC world.
 
I do not think I can describe this in general enough terms, with options etc. to add it myself.

I've been following this thread somewhat haphazardly, but it seems that what's wanted is not very well defined.

How are the alerts to be made ... message box, text in the console. Who will make the alerts? Given the nature of this thread I suppose TCC or TCMD will do that. But that means TCC or TCMD will have to be running all the time. Imagining I had such a need. the first thing that comes to mind is this.

1. Create a plain-text structured database (file) of reminders (with all their peculiarities)
2. Write a BTM to process the database and make alerts as necessary
3. Create a scheduled task to have TCC (as current user, interact with desktop, only when logged in) process the database at regular intervals.
4. Instead of 3, if you start TCC often (as I do) just process the database in TCSTART.BTM
 
I've been following this thread somewhat haphazardly, but it seems that what's wanted is not very well defined.

How are the alerts to be made ... message box, text in the console. Who will make the alerts? Given the nature of this thread I suppose TCC or TCMD will do that. But that means TCC or TCMD will have to be running all the time. Imagining I had such a need. the first thing that comes to mind is this.

1. Create a plain-text structured database (file) of reminders (with all their peculiarities)
2. Write a BTM to process the database and make alerts as necessary
3. Create a scheduled task to have TCC (as current user, interact with desktop, only when logged in) process the database at regular intervals.
4. Instead of 3, if you start TCC often (as I do) just process the database in TCSTART.BTM


The idea would be to create a function that returns -1 or a date. Then the user can decide what to do with the returned dates.

Parameters would be:

DueDates: A list of day of month dates, e.g., due on the 1st and 15th or a specified date, e.g., 2017-07-04.
(My program doesn't handle "specified date".)

PrepDays: This is the number of days before DueDate the preparation needs to start.

WarnDays: How many days in advance of PrepDays warnings start.

SoonerOrLater: (Sorry -- I just couldn't resist the pun!)
If the Warn Date or the Prep Date or the Due Date falls on a weekend, does the function return the nearest earlier date, i.e., Friday, or the nearest later, i.e., Monday?


This is not intended as a "general background" program, so TCC doesn't need to run continuously. We run a program manually each business day (actually a set of .btm programs). We have to send reports on the 1st and 15th or the nearest business day after. Sometimes we don't notice the date and suddenly we realize, "The report is due today!"

The "check-comments" program is called from the main program each time that is run, and pops up warnings if needed, with "Press any key to continue ...."

Anything like Task Scheduler wouldn't work because that wouldn't pop up the message as part of the main program specifically while the user is running that particular program, and if it's popping up a different looking warning (i.e., Windows window rather than TCC text) the user is likely to ignore it or forget it.

(I don't use Task Scheduler, so I don't know what would be involved in getting it to consider a Warn Date and a Prep Date and a Due Date, calculate a substitute SoonerOrLater date and then pop up a message stating multiple upcoming dates.)
 
Just an additional follow-up. It's Friday May 11th and, as it should, the program just popped up that comments are due Tuesday May 15th. I'm still using GT 18.

Actually, once the Library system is fleshed out with a standard way to return values from Library functions, this sounds like an excellent project to do using Library.
 
Back
Top