austax: Spread income tax expense out across 12 months
This commit is contained in:
parent
1a5167acf5
commit
ff7af2f06e
@ -15,6 +15,16 @@
|
|||||||
-- You should have received a copy of the GNU Affero General Public License
|
-- You should have received a copy of the GNU Affero General Public License
|
||||||
-- along with this program. If not, see <https://www.gnu.org/licenses/>.
|
-- along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-----------------
|
||||||
|
-- Flags
|
||||||
|
|
||||||
|
-- true = Spread income tax expense over monthly transactions
|
||||||
|
-- false = Charge income tax expense in one transaction at end of financial year
|
||||||
|
local charge_tax_monthly = true
|
||||||
|
|
||||||
|
-----------------
|
||||||
|
-- Reporting code
|
||||||
|
|
||||||
local libdrcr = require('../libdrcr')
|
local libdrcr = require('../libdrcr')
|
||||||
local account_kinds = require('../austax/account_kinds')
|
local account_kinds = require('../austax/account_kinds')
|
||||||
local calc = require('../austax/calc')
|
local calc = require('../austax/calc')
|
||||||
@ -377,9 +387,68 @@ function reporting.CalculateIncomeTax.execute(args, context, kinds_for_account,
|
|||||||
}})
|
}})
|
||||||
|
|
||||||
-- Generate income tax transactions
|
-- Generate income tax transactions
|
||||||
local transactions: {libdrcr.Transaction} = {
|
local transactions: {libdrcr.Transaction} = {}
|
||||||
{
|
|
||||||
-- # Estimated tax payable
|
-- Estimated tax payable
|
||||||
|
if charge_tax_monthly then
|
||||||
|
-- Charge income tax expense in parts, one per month
|
||||||
|
local monthly_tax = math.floor((tax_total - offset_total) / 12)
|
||||||
|
local last_month_tax = (tax_total - offset_total) - 11 * monthly_tax -- To account for rounding errors
|
||||||
|
|
||||||
|
-- Some ad hoc calendar code
|
||||||
|
local eofy_year, eofy_month, _ = libdrcr.parse_date(context.eofy_date)
|
||||||
|
local last_day_of_month = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } -- Leap years handled below
|
||||||
|
|
||||||
|
for month = 1, 12 do
|
||||||
|
local this_year, this_month_tax
|
||||||
|
if month == eofy_month then
|
||||||
|
this_year = eofy_year
|
||||||
|
this_month_tax = last_month_tax
|
||||||
|
elseif month < eofy_month then
|
||||||
|
this_year = eofy_year
|
||||||
|
this_month_tax = monthly_tax
|
||||||
|
else
|
||||||
|
this_year = eofy_year - 1
|
||||||
|
this_month_tax = monthly_tax
|
||||||
|
end
|
||||||
|
|
||||||
|
local this_day = last_day_of_month[month]
|
||||||
|
|
||||||
|
-- Check for leap year
|
||||||
|
if month == 2 and (this_year % 4 == 0) and (this_year % 100 ~= 0 or this_year % 400 == 0) then
|
||||||
|
this_day = 29
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Charge monthly tax
|
||||||
|
table.insert(transactions, {
|
||||||
|
id = nil,
|
||||||
|
dt = libdrcr.date_to_dt(libdrcr.format_date(this_year, month, this_day)),
|
||||||
|
description = 'Estimated income tax',
|
||||||
|
postings = {
|
||||||
|
{
|
||||||
|
id = nil,
|
||||||
|
transaction_id = nil,
|
||||||
|
description = nil,
|
||||||
|
account = INCOME_TAX,
|
||||||
|
quantity = this_month_tax,
|
||||||
|
commodity = context.reporting_commodity,
|
||||||
|
quantity_ascost = this_month_tax,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id = nil,
|
||||||
|
transaction_id = nil,
|
||||||
|
description = nil,
|
||||||
|
account = INCOME_TAX_CONTROL,
|
||||||
|
quantity = -this_month_tax,
|
||||||
|
commodity = context.reporting_commodity,
|
||||||
|
quantity_ascost = -this_month_tax,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- Charge income tax expense in one transaction at EOFY
|
||||||
|
table.insert(transactions, {
|
||||||
id = nil,
|
id = nil,
|
||||||
dt = libdrcr.date_to_dt(context.eofy_date),
|
dt = libdrcr.date_to_dt(context.eofy_date),
|
||||||
description = 'Estimated income tax',
|
description = 'Estimated income tax',
|
||||||
@ -403,34 +472,35 @@ function reporting.CalculateIncomeTax.execute(args, context, kinds_for_account,
|
|||||||
quantity_ascost = -(tax_total - offset_total),
|
quantity_ascost = -(tax_total - offset_total),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
{
|
end
|
||||||
-- Mandatory study loan repayment
|
|
||||||
id = nil,
|
-- Mandatory study loan repayment
|
||||||
dt = libdrcr.date_to_dt(context.eofy_date),
|
table.insert(transactions, {
|
||||||
description = 'Mandatory study loan repayment payable',
|
id = nil,
|
||||||
postings = {
|
dt = libdrcr.date_to_dt(context.eofy_date),
|
||||||
{
|
description = 'Mandatory study loan repayment payable',
|
||||||
id = nil,
|
postings = {
|
||||||
transaction_id = nil,
|
{
|
||||||
description = nil,
|
id = nil,
|
||||||
account = HELP,
|
transaction_id = nil,
|
||||||
quantity = study_loan_repayment,
|
description = nil,
|
||||||
commodity = context.reporting_commodity,
|
account = HELP,
|
||||||
quantity_ascost = study_loan_repayment,
|
quantity = study_loan_repayment,
|
||||||
},
|
commodity = context.reporting_commodity,
|
||||||
{
|
quantity_ascost = study_loan_repayment,
|
||||||
id = nil,
|
|
||||||
transaction_id = nil,
|
|
||||||
description = nil,
|
|
||||||
account = INCOME_TAX_CONTROL,
|
|
||||||
quantity = -study_loan_repayment,
|
|
||||||
commodity = context.reporting_commodity,
|
|
||||||
quantity_ascost = -study_loan_repayment,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
{
|
||||||
}
|
id = nil,
|
||||||
|
transaction_id = nil,
|
||||||
|
description = nil,
|
||||||
|
account = INCOME_TAX_CONTROL,
|
||||||
|
quantity = -study_loan_repayment,
|
||||||
|
commodity = context.reporting_commodity,
|
||||||
|
quantity_ascost = -study_loan_repayment,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
-- Transfer PAYGW balances to Income Tax Control
|
-- Transfer PAYGW balances to Income Tax Control
|
||||||
for account, kinds in pairs(kinds_for_account) do
|
for account, kinds in pairs(kinds_for_account) do
|
||||||
|
@ -149,6 +149,7 @@ export type MultipleDateStartDateEndArgs = { dates: {DateStartDateEndArgs} }
|
|||||||
|
|
||||||
local libdrcr = {}
|
local libdrcr = {}
|
||||||
|
|
||||||
|
-- Returns true if array haystack contains needle
|
||||||
function libdrcr.arr_contains(haystack: {any}, needle: any): boolean
|
function libdrcr.arr_contains(haystack: {any}, needle: any): boolean
|
||||||
for _, element in ipairs(haystack) do
|
for _, element in ipairs(haystack) do
|
||||||
if element == needle then
|
if element == needle then
|
||||||
@ -158,10 +159,17 @@ function libdrcr.arr_contains(haystack: {any}, needle: any): boolean
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Converts a date string (YYYY-MM-DD) into datetime string (YYYY-MM-DD HH:MM:SS.xxxxxx) for database
|
||||||
function libdrcr.date_to_dt(date: string): string
|
function libdrcr.date_to_dt(date: string): string
|
||||||
return date .. ' 00:00:00.000000'
|
return date .. ' 00:00:00.000000'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Formats the date as date string (YYYY-MM-DD)
|
||||||
|
function libdrcr.format_date(year: number, month: number, day: number): string
|
||||||
|
return string.format('%04d-%02d-%02d', year, month, day)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Parses the date string (YYYY-MM-DD) into components
|
||||||
function libdrcr.parse_date(date: string): (number, number, number)
|
function libdrcr.parse_date(date: string): (number, number, number)
|
||||||
local year_str, month_str, day_str = string.match(date, '(%d%d%d%d)-(%d%d)-(%d%d)')
|
local year_str, month_str, day_str = string.match(date, '(%d%d%d%d)-(%d%d)-(%d%d)')
|
||||||
|
|
||||||
@ -176,6 +184,7 @@ function libdrcr.parse_date(date: string): (number, number, number)
|
|||||||
return year, month, day
|
return year, month, day
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Convert the Lua value to string recursively
|
||||||
function libdrcr.repr(value: any): string
|
function libdrcr.repr(value: any): string
|
||||||
local result = ''
|
local result = ''
|
||||||
if type(value) == 'table' then
|
if type(value) == 'table' then
|
||||||
|
Loading…
x
Reference in New Issue
Block a user