Filing expenses into Australian financial years

From your noodle to other noodles. Talk about ways to get the most from Hazel. Even exchange recipes for the cool rules you've thought up. DO NOT POST YOUR QUESTIONS HERE.

Moderators: Mr_Noodle, Moderators

The Australian financial year goes from 1 July through to 30 June. This makes it somewhat complicated to use Hazel to file into those years.

I noticed I could use an embedded AppleScript as a condition in Hazel and started fooling around.

The script is:

Code: Select all
set savedDelimiters to AppleScript's text item delimiters
set AppleScript's text item delimiters to {"-"}

tell application "Finder"
   set filename to name of theFile
end tell

set expenseYear to (first text item of filename) as number
set expenseMonth to (second text item of filename) as number

-- Get the last two characters of the Year
set AppleScript's text item delimiters to savedDelimiters
set lastTwoCharactersOfYear to (characters 3 thru 4 of (expenseYear as text))
set financialYear to (lastTwoCharactersOfYear as text) as number


if expenseMonth ≥ 7 then
   set financialYear to financialYear + 1
end if


set returnText to "FY" & financialYear

-- Note: the order of the hazelOutputAttributes list needs to match the order of the outputAttributes in Hazel
return {hazelOutputAttributes:{returnText}, hazelPassesScript:true}


I also set up an output attribute on the embedded script called financialYear.

The script passes back the financial year to Hazel and then uses that to sort into subfolders with the form "FYXX"
deanpribetic
 
Posts: 3
Joined: Wed Jul 06, 2016 10:12 pm

I'm wondering if you can get the same effect by adjusting the date by -6 months (or is it +6 months?). Something to play with anyways.
Mr_Noodle
Site Admin
 
Posts: 9427
Joined: Sun Sep 03, 2006 1:30 am
Location: New York City

Mr_Noodle wrote:I'm wondering if you can get the same effect by adjusting the date by -6 months (or is it +6 months?). Something to play with anyways.


Oh wow! You are totally right…Date Adjust the matched date by +6 months and then use the last two digits of the date concatenated after the string "FY".

So much easier…thanks!
deanpribetic
 
Posts: 3
Joined: Wed Jul 06, 2016 10:12 pm

I just found this and it is something that I am currently looking it.

I was wondering what you meant by "adjusting the date"? Do you mean within Hazel or within the AppleScript?
Rug664
 
Posts: 8
Joined: Sun Aug 18, 2013 7:20 am

Within Hazel. When you include a date in your pattern, you can click on it. A menu will appear with different options, including one to adjust the date.
Mr_Noodle
Site Admin
 
Posts: 9427
Joined: Sun Sep 03, 2006 1:30 am
Location: New York City

Hi
Thank you for helpful script, I have tried to modify the script to sort files in folders based on Financial year
Folder name pattern FY 2018-19, FY 2019-20
Files are name pattern : 2019-07-26_Tesco_stationary
Financial year is between 6th April to 5th April each year.

My first aim is get month right, then wud try dates;
the Output for Script
File 2019-07-26_Tesco_stationary -> FY 2020 ( expected FY 2019-20)
File 2019-03-15_Sainsbury -> FY 2019 ( expected FY 2018-19)
Please advise, also any pointers to add date in sorting wud be helpful
Thank you


Code: Select all
set savedDelimiters to AppleScript's text item delimiters
set AppleScript's text item delimiters to {"-"}

tell application "Finder"
   set filename to name of theFile
end tell

set expenseYear to (first text item of filename) as number
set expenseMonth to (second text item of filename) as number
set expenseDate to (third text item of filename) as number

-- Get the last two characters of the Year
set AppleScript's text item delimiters to savedDelimiters
set lastTwoCharactersOfYear to (characters 3 thru 4 of (expenseYear as text))
set RoundedExpYear to (lastTwoCharactersOfYear as text) as number


if expenseMonth ≥ 4 then
   set LongString to expenseYear
   set ShortString to RoundedExpYear + 1
else
   set LongString to expenseYear - 1
   set ShortString to RoundedExpYear
end if


set returnText to "FY" & " " & LongString & "-" & ShortString

-- Note: the order of the hazelOutputAttributes list needs to match the order of the outputAttributes in Hazel
return {hazelOutputAttributes:{returnText}, hazelPassesScript:true}
Lucky
 
Posts: 4
Joined: Mon Oct 21, 2019 2:25 am

Hey Guys, further tweeked the script
It works, expect that file name 2006-09-21, gets sorted in folder FY 2006-7, instead of FY 2006-7
Any Suggestions ?
Also if I add date as logic
Code: Select all
set expenseDate to (third text item of filename) as number

It gives error, any suggestions wud be welcome
working Code
Code: Select all
set savedDelimiters to AppleScript's text item delimiters

set AppleScript's text item delimiters to {"-"}



tell application "Finder"

   

   set filename to name of theFile

   

end tell





set expenseYear to (first text item of filename) as number

set expenseMonth to (second text item of filename) as number





-- Get the last two characters of the Year

set AppleScript's text item delimiters to savedDelimiters

set lastTwoCharactersOfYear to (characters 3 thru 4 of (expenseYear as text))

set RoundedExpYear to (lastTwoCharactersOfYear as text) as number

set longString to expenseYear - 1

set shortString to RoundedExpYear



if expenseMonth ≥ 4 then

   set longString to longString + 1

   set shortString to RoundedExpYear +1

   

end if



set returnText to "FY" & " " & longString & "-" & shortString



-- Note: the order of the hazelOutputAttributes list needs to match the order of the outputAttributes in Hazel

return {hazelOutputAttributes:{returnText}, hazelPassesScript:true}
Lucky
 
Posts: 4
Joined: Mon Oct 21, 2019 2:25 am

Follow up, got it going, it as issue with delimitters, now can define date as criteria to sort folder, works perfect in Applescript editor and hazel too ( did change to filename as thefile)
made a automator action for folder!
new code
Code: Select all
set savedDelimiters to AppleScript's text item delimiters
set AppleScript's text item delimiters to {"_"}

tell application "Finder"
   
   set filename to "2020-04-05_onetwo"
   
end tell

set dateString to (first text item of filename) as text
set AppleScript's text item delimiters to savedDelimiters
set savedDelimiters to AppleScript's text item delimiters
set AppleScript's text item delimiters to {"-"}

set expenseYear to (first text item of dateString) as number
set expenseMonth to (second text item of dateString) as number
set expenseDate to (third text item of dateString) as number


-- Get the last two characters of the Year
set AppleScript's text item delimiters to savedDelimiters
set lastTwoCharactersOfYear to (characters 3 thru 4 of (expenseYear as text))
set RoundedExpYear to (lastTwoCharactersOfYear as text) as number
set longString to expenseYear - 1
set shortString to RoundedExpYear

if expenseMonth ≥ 4 and expenseDate ≥ 6 then
   set longString to longString + 1
   set shortString to RoundedExpYear + 1
   
end if

set returnText to "FY" & " " & longString & "-" & shortString

-- Note: the order of the hazelOutputAttributes list needs to match the order of the outputAttributes in Hazel
return {hazelOutputAttributes:{returnText}, hazelPassesScript:true}
Lucky
 
Posts: 4
Joined: Mon Oct 21, 2019 2:25 am

External JavaScript is not valid Wed Mar 03, 2021 12:54 am • by ScottDellar
Independent of this forum, I developed a solution in JavaScript for formatting a given date as an Australian Financial Year in the format "FY2020-21". :D

I'll post code below, but my question is around JavaScript in Rule Actions when using an external file. I consulted the AppleScript/JavaScript in Rule Actions section in the Hazel User Guide: https://www.noodlesoft.com/manual/hazel/attributes-actions/using-applescript-or-javascript/.

Here is the code:
Code: Select all
function hazelProcessFile(theFile, inputAttributes)
{
  var myDate = new Date(inputAttributes[0]);

  // Get current year for usage below
  var yearNumber = myDate.getFullYear();
  var thisYearYYYY = yearNumber.toString();

  // Construct YYYY-YY Australian Financial Year
  var australianFinancialYear = "";

  // Month is from 0 to 11
  if (myDate.getMonth() + 1 > 6) {
    var nextYearYYYY = (yearNumber + 1).toString();
    var nextYearYY = nextYearYYYY.substr(
      nextYearYYYY.length - 2,
      nextYearYYYY.length
    );
    australianFinancialYear = "FY" + thisYearYYYY + "-" + nextYearYY;
  } else {
    var lastYearYYYY = (yearNumber - 1).toString();
    var thisYearYY = thisYearYYYY.substr(
      thisYearYYYY.length - 2,
      thisYearYYYY.length
    );
    australianFinancialYear = "FY" + lastYearYYYY + "-" + thisYearYY;
  }
  return { hazelOutputAttributes: [australianFinancialYear] };
}

I have tested this code, it is valid JavaScript and returns the desired result. The below was attained by showing the browser console by hitting F12, pasting the function into the browser console and hitting return, so it is instantiated there, and then it was called it as follows:
Code: Select all
hazelProcessFile("file",[new Date("2021-03-03")])
hazelOutputAttributes: ["FY2020-21"]

The problem is that when I put this exact code into a file called getAustralianFinancialYear.scpt, then in Hazel create a "Run JavaScript" Action, select "Other...", navigate to that file and click Open, Hazel displays a dialog with

Script is not valid
Please fix the script or try another one.

Note that I can also embed this script in Hazel, without the function wrapper, and it works. The input attribute is date-type, and my script handles that. The output attribute is text and exactly what is required. I had the idea of using getAustralianFinancialYear.scpt in more than one Hazel rule, so it would be handy to be able to store it externally. How does Hazel validate JavaScript and why is it invalid in this instance? Is returning hazelPassesScript: true a requirement? This issue should be reproducible given the details above.
ScottDellar
 
Posts: 5
Joined: Tue Apr 21, 2020 2:08 am

Note that when you use "Run JavaScript", as opposed to "Run shellscript" specifying a Java interpreter, you are actually creating an OSA script. Instead of a raw text file with your JS code, you need to compile it into an OSA script using a program like Script Editor. It's basically another language like AppleScript which compiles down to the same type of binary. It's the compiled versions you need to reference from Hazel.
Mr_Noodle
Site Admin
 
Posts: 9427
Joined: Sun Sep 03, 2006 1:30 am
Location: New York City

Re: External JavaScript is not valid Wed Mar 03, 2021 11:33 pm • by ScottDellar
Here is a reliable repeatable method for external JavaScript execution for the benefit of this forum.

Using a single external (as opposed to embedded) JavaScript → OSA script across multiple Hazel rules

The command line utility "osacompile" compiles AppleScript or JavaScript into OSA script: https://learning.oreilly.com/library/vi ... re319.html

The command needed to compile JavaScript (noting the -l language flag) into OSA script is
Code: Select all
osacompile -o myCode.scpt -l JavaScript myCode.js

The goal is to have a folder that contains both .js JavaScript files (that can be maintained using Visual Studio Code to get all the benefits of syntax highlighting and linting) and a generated .scpt OSA script that Hazel requires. Create a Hazel rule to pick up any .js file and convert it to .scpt. Set up a Code folder that Hazel monitors with a single rule called "Convert Js to Scpt" that monitors for "Extension is js". Create a single "Run shell script" action to run the following embedded script.
Code: Select all
# Get elements of filename: path, filename, extension
a=$1
xpath=${a%/*}
xbase=${a##*/}
xfext=${xbase##*.}
xpref=${xbase%.*}

inputJsFilename="$1"
outputScptFilename="${xpath}/${xpref}.scpt"

osacompile -o "${outputScptFilename}" -l JavaScript "${inputJsFilename}"

To use the .scpt file that was just created, in Hazel create a rule with a "Run JavaScript" Action, select "Other...", navigate to the .scpt file and click Open - its filename will then appear in the action. Click "Options" on that action and set up the import and export attributes as usual.

Could something like the above please be documented in the AppleScript/JavaScript in Rule Actions section in the Hazel User Guide?: https://www.noodlesoft.com/manual/hazel ... avascript/.

I assume that Hazel is doing something very similar to the above before it executes embedded JavaScript for the first time (perhaps upon saving the rule). May I humbly suggest that Hazel could perform this .js to .scpt conversion for the user (as Hazel already does for embedded code)? Granted, it may not be as efficient, but it should be invisible for the user, who should be able to either embed the code or just put it (with a function wrapper) into an external file. Perhaps "Run JavaScript" is a little misleading for external scripts, when it requires JavaScript that has been converted into OSA .scpt format.
ScottDellar
 
Posts: 5
Joined: Tue Apr 21, 2020 2:08 am

This might be better as its own thread but I'll consider the option to use an js file though the problem is that not any js will work.
Mr_Noodle
Site Admin
 
Posts: 9427
Joined: Sun Sep 03, 2006 1:30 am
Location: New York City


Return to Tips & Tricks - DO NOT POST QUESTIONS