Showing posts with label TTS. Show all posts
Showing posts with label TTS. Show all posts

Sunday, 28 September 2025

Running COSTING automatically

From a financial/inventory point of view, the external program COSTING is one of the most important programs under the Priority umbrella. For those that don't know, this program calculates the value of every part stored in a given 'accumulator', that in itself stores the inventory of each part in every warehouse at a given date (the program can also calculate for previous accumulators). Unlike the daily costing program, this program saves its data forever and so is extremely useful when wanting to know the value of inventory at a given date (normally the last day of a month). 

There is a parameter (ARG) passed to COSTING that determines whether it will be a daily run (deleting previous values) or a monthly run (saving values). In the first case, ARG will equal 4, whereas in the second case, ARG will equal 1.

Until not so very long ago, one could schedule COSTING and it would run automatically, using the most current accumulator. Unfortunately, this behaviour changed a few versions ago, when a scheduled run would fail because it didn't have a date for the accumulator. As this program runs for 14-16 hours on my server, this meant that I would have to get up at 4:15 on a Friday morning, stumble to the computer, connect to the server and start the program.

Eventually I got fed up with this and tried to determine what would be needed to run COSTING automatically on the last accumulator only. Basically a two step procedure is required, but I added a third step to send me email that the procedure has completed. This code does indeed run COSTING automatically, creating a monthly costing.

Stage 10 - SQLI /* TEST_COSTINGACC - No'am, 25/09/25 A cut-down version of COSTINGACC that calculates for the last tzovar only - automatically. Parameters: DAT, type LINE */ :LASTDATE = 0; #include func/FashionCosting SELECT CURDATE INTO :LASTDATE FROM ACCDATES ORIG WHERE COSTFLAG <> 'Y' AND NOT EXISTS (SELECT 'X' FROM ACCDATES ORIG2 WHERE ORIG2.COSTFLAG = 'Y' AND ORIG2.CURDATE > ORIG.CURDATE) ORDER BY CURDATE DESC; /* My stuff */ :CURDATE = 01/01/88; SELECT MAX (CURDATE) INTO :CURDATE FROM ACCDATES; LINK ACCDATES TO :$.DAT; GENMSG 1001 WHERE :RETVAL <= 0; INSERT INTO ACCDATES SELECT * FROM ACCDATES ORIG WHERE CURDATE = :CURDATE; UNLINK ACCDATES; /* Input stage */ SELECT VALUE INTO :STARTDATE FROM LASTS WHERE NAME='COSTSTARTDATE'; :CURDATE = :FIRSTDATE = 0; :COUNT = 0; LINK ACCDATES TO :$.DAT; SELECT MIN(CURDATE), COUNT(*) INTO :CURDATE, :COUNT FROM ACCDATES WHERE CURDATE > 0; UNLINK ACCDATES; SELECT CURDATE INTO :FIRSTDATE FROM ACCDATES WHERE CURDATE > 0 AND COSTFLAG = 'Y' ORDER BY CURDATE; SELECT DTOA(0+:STARTDATE, 'XX/XX/XX') INTO :PAR1 FROM DUMMY; ERRMSG 1 WHERE :FIRSTDATE = 0 AND 0+:STARTDATE <> :CURDATE AND :STARTDATE <> 0; :ENAME = 'COSTINGACC'; :DATE = 0 + :CURDATE; #include func/CostingLog ----------------------------------------------------------------- STAGE 20: COSTING Parameters: ARG, type INT, value 1 MSG, type ASCII DAT, type LINE /* The parameters have to be in this order */ ----------------------------------------------------------------- STAGE 30: SQLI #include func/CostingMpart :PAR1 = '$'; MAILMSG 40 TO EMAIL 'tabula@gmail.com';

Monday, 28 April 2025

Refresh parameters for TTS task

My company has 260 tasks defined to run automatically by means of the task scheduler (TTS); the vast majority of these tasks are procedures that look for specific situations (e.g. open orders that should have been supplied) and assuming that there is output, send the report by email to a user group. These procedures have their parameters defined within their code. 

One procedure - not mine - that does not have its parameters defined internally is MRP. This procedure can of course be run manually, and there are over ten parameters that the user can change, not including several system constants that generally do not change. In order to run MRP successfully by the TTS, this task has an entry in the field 'run according to the input of user'. I have always understood that an automatic invocation of MRP will run using the parameters of a given user, and that if I want to change the parameters for the automatic run, then first I would have to run MRP manually and in doing so, change the parameters to their new values. Or so I thought.

Until now, the value of the parameter 'open work orders until' has been 'the end of the next quarter'; this currently would be 30/09/25. As unusually we have some orders with a supply date in October, no work orders were being created for these lines. The production manager wanted to know the reason for this; I explained, and we agreed that the value of this parameter would be changed to 'the end of the next year', at the moment 31/12/26. I ran MRP manually, entering this value, and indeed work orders were created for those orders with an October supply date from this run. 

I was thus surprised to see that in the next automatic run of MRP, the 'open work orders until' parameter had reverted to 30/09/25. My understanding of how to change parameters for automatic invocation was flawed. It turns out that there is a simple, but rarely used, fix for this situation: one can run a procedure (by direct invocation) called TTSUSERINPUT, 'Refresh Task Input by User'. It transpires that the task has its own set of parameters and these are updated from the user's values by means of this procedure. And indeed, the next automatic run of MRP after running this procedure was run according to the updated parameters.

File under  'Learn something new every day' ....