Index: openacs-4/packages/accounts-finance/tcl/finance-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/accounts-finance/tcl/finance-procs.tcl,v diff -u -N -r1.8 -r1.9 --- openacs-4/packages/accounts-finance/tcl/finance-procs.tcl 25 May 2010 06:26:44 -0000 1.8 +++ openacs-4/packages/accounts-finance/tcl/finance-procs.tcl 26 May 2010 23:53:27 -0000 1.9 @@ -118,7 +118,7 @@ set npv_test_value($test_nbr) [acc_fin::qaf_npv $net_period_list [list $i] $intervals_per_year ] if { $test_nbr > 1 } { - if { [expr { [acc_fin::qaf_sign $npv_test_value($test_nbr)] * [acc_fin::qaf_sign $npv_test_value($prev_nbr)] } ] < 0 } { + if { [expr { [qaf_sign $npv_test_value($test_nbr)] * [qaf_sign $npv_test_value($prev_nbr)] } ] < 0 } { incr sign_change_count lappend start_range $prev_nbr } @@ -142,7 +142,7 @@ set p0_npv $npv_test_value($i_begin) # first point analysis (for iteration) set abs_p0_npv [expr { abs( $p0_npv ) } ] - set sign_p0_npv [acc_fin::qaf_sign $p0_npv] + set sign_p0_npv [qaf_sign $p0_npv] # set interation at a fraction of dx to get a second point within the range set discount_incr [expr { ( $npv_test_discount($i_end) - $p0_discount ) / 3. } ] @@ -161,7 +161,7 @@ # points are f(p0_discount), f(p1_discount) # analyse new point - set sign_p1_npv [acc_fin::qaf_sign $p1_npv] + set sign_p1_npv [qaf_sign $p1_npv] set sign_change [expr { $sign_p0_npv * $sign_p1_npv } ] # is new point getting closer or did we pass NPV=0? @@ -514,3 +514,4 @@ return $depreciation_list } } + Index: openacs-4/packages/accounts-finance/tcl/modeling-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/accounts-finance/tcl/modeling-procs.tcl,v diff -u -N -r1.1 -r1.2 --- openacs-4/packages/accounts-finance/tcl/modeling-procs.tcl 20 May 2010 18:07:12 -0000 1.1 +++ openacs-4/packages/accounts-finance/tcl/modeling-procs.tcl 26 May 2010 23:53:27 -0000 1.2 @@ -7,7 +7,7 @@ namespace eval acc_fin {} -ad_proc -public acc_fin::fp { +ad_proc -public qaf_fp { number } { returns a floating point version a number, if the number is an integer (no decimal point). @@ -16,13 +16,17 @@ } { if { [string first "." $number] < 0 } { # append number ".0" - set number [expr { double( $number ) } ] + catch { + set number [expr { double( $number ) } ] + } else { + # do nothing. $number is not a recognized number + } } return $number } -ad_proc -private acc_fin::qaf_sign { +ad_proc -public qaf_sign { number } { Returns the sign of the number represented as -1, 0, or 1 @@ -31,8 +35,30 @@ return $sign } +ad_proc -private acc_fin::template_model { + template_number +} { + returns a template for financial modelling + 0 is for testing +} { + switch -exact -- $template_number { + 0 { set template " +period = 0 +periods_per_year = 12 +total_periods = 20 +# +period = i +year = int( ( period + ( periods_per_year - 1 ) / periods_per_year ) ) +# +i period year periods_per_year total_periods +" -ad_proc -private acc_fin::qaf_compile_model { + } +} + return $template +} + +ad_proc -private acc_fin::model_compile { model } { returns calculation friendly list of lists from model represented in shorthand @@ -99,11 +125,10 @@ set calc_line "set ${calc_line} \} \]" set varname [trim [string range ${calc_line} 5 [string first expr $calc_line]-2]] if { ![info exists $varname_list] } { - # create list and array history for each variable + # create list and array history for each variable for logging values of each iteration (for post run analysis etc.) set ${varname}_list [list] array set ${varname}_arr [list] - } if { [string length $calc_line ] > 0 } { lappend new_section_list $calc_line @@ -188,4 +213,342 @@ } -# when processing, if default_arr(0) exists and var_arr(0) does not exist, set var_arr(0) to $default_arr(0) +ad_proc -private acc_fin::model_compute { + model + {number} + {arg1} + {arg2} + {arg3} +} { + Loop through model N (number) iterations. + arg1, arg2, arg3 are passed to the model, a feature for adding variances to model computations, such as interval_duration and parameter ranges +} { + # given: variable default for iteration 0: default_arr(0) + # a variable supplied by user is {var} + # each {var} gets a {var}_arr($i) and {var}_list which log values through iterations ($i). + # If default_arr(0) exists and {var}_arr(0) does not exist, set {var}_arr(0) to $default_arr(0) + # this is a quick way to set a default value for all variables instead of explicitly naming all of the variables. + +} + +ad_proc -private acc_fin::gl_array_create { + array_name + {gl_type "capbug"} +} { + creates an array of general ledger (and supporting arrays) with some predefined accounts, with default values of 0. +gl_type choices are: + "capbug" for capital budgeting (project/program forecasting) + "general" for general accounts ledger + "mfg" for manufacturing based GL + "service" for service based GL +} { + upvar $array_name gl + # a predefined list of accounts. account number is acc_ref + # gl_sorted(sort_key) account number. This allows quick iterating in sorted order. + # + # gl_title(acc_ref) for pretty names, + # gl_element(acc_ref) for group type, example: asset, liability, income, expense, capital; see http://en.wikipedia.org/wiki/General_ledger + # gl_nature(acc_ref) for type, example: real,entity,nominal; see http://en.wikipedia.org/wiki/Double-entry_bookkeeping_system + switch -exact -- $gl_type { + capbug { +1000 "ASSETS" +2000 "LIABILITIES" +3000 "EQUITY" +4000 "REVENUES" +5000 "COGS" +6000 "EXPENSES" +7000 other + + } + + general { + array set gl { +1000 "CURRENT ASSETS" +1060 "Checking Account" +1065 "Petty Cash" +1200 "Accounts Receivables" +1205 "Allowance for doubtful accounts" +1500 "INVENTORY ASSETS" +1510 "Inventory" +1520 "Inventory / General" +1530 "Inventory / Aftermarket Parts" +1800 "CAPITAL ASSETS" +1820 "Office Furniture & Equipment" +1825 "Accum. Amort. -Furn. & Equip." +1840 "Vehicle" +1845 "Accum. Amort. -Vehicle" +2000 "CURRENT LIABILITIES" +2100 "Accounts Payable" +2110 "Accrued Income Tax - Federal" +2120 "Accrued Income Tax - State" +2130 "Accrued Franchise Tax" +2140 "Accrued Real & Personal Prop Tax" +2150 "Sales Tax" +2160 "Accrued Use Tax Payable" +2160 "Corporate Taxes Payable" +2190 "Federal Income Tax Payable" +2210 "Accrued Wages" +2212 "Workers Comp Payable" +2220 "Accrued Comp Time" +2240 "Accrued Vacation Pay" +2250 "Pension Plan Payable" +2260 "Employment Insurance Payable" +2280 "Payroll Taxes Payable" +2310 "Accr. Benefits - 401K" +2390 "VAT (10%)" +2320 "Accr. Benefits - Stock Purchase" +2395 "VAT (14%)" +2330 "Accr. Benefits - Med, Den" +2400 "VAT (30%)" +2340 "Accr. Benefits - Payroll Taxes" +2350 "Accr. Benefits - Credit Union" +2360 "Accr. Benefits - Savings Bond" +2370 "Accr. Benefits - Garnish" +2380 "Accr. Benefits - Charity Cont." +2600 "LONG TERM LIABILITIES" +2620 "Bank Loans" +2680 "Loans from Shareholders" +3300 "SHARE CAPITAL" +3350 "Common Shares" +3500 "RETAINED EARNINGS" +3590 "Retained Earnings - prior years" +4000 "SALES REVENUE" +4010 "Sales" +4020 "Sales / General" +4030 "Sales / Aftermarket Parts" +4300 "CONSULTING REVENUE" +4320 "Consulting" +4400 "OTHER REVENUE" +4430 "Shipping & Handling" +4440 "Interest" +4450 "Foreign Exchange Gain" +5000 "COST OF GOODS SOLD" +5010 "Purchases" +5020 "COGS / General" +5030 "COGS / Aftermarket Parts" +5100 "Freight" +5400 "PAYROLL EXPENSES" +5410 "Wages & Salaries" +5420 "Employment Insurance Expense" +5424 "Wages - Overtime" +5430 "Benefits - Comp Time" +5434 "Pension Plan Expense" +5440 "Benefits - Payroll Taxes" +5444 "Workers Comp Expense" +5450 "Benefits - Workers Comp" +5460 "Benefits - Pension" +5470 "Benefits - General Benefits" +5474 "Employee Benefits" +5510 "Inc Tax Exp - Federal" +5520 "Inc Tax Exp - State" +5530 "Taxes - Real Estate" +5540 "Taxes - Personal Property" +5550 "Taxes - Franchise" +5560 "Taxes - Foreign Withholding" +5600 "GENERAL & ADMINISTRATIVE EXPENSES" +5610 "Accounting & Legal" +5615 "Advertising & Promotions" +5620 "Bad Debts" +5650 "Capital Cost Allowance Expense" +5660 "Amortization Expense" +5680 "Income Taxes" +5685 "Insurance" +5690 "Interest & Bank Charges" +5700 "Office Supplies" +5760 "Rent" +5765 "Repair & Maintenance" +5780 "Telephone" +5785 "Travel & Entertainment" +5790 "Utilities" +5795 "Registrations" +5800 "Licenses" +5810 "Foreign Exchange Loss" + } + } +mfg { + array set gl { +1000 "CURRENT ASSETS" +1060 "Checking Account" +1065 "Petty Cash" +1200 "Accounts Receivables" +1205 "Allowance for doubtful accounts" +1500 "INVENTORY ASSETS" +1520 "Inventory / General" +1530 "Inventory / Raw Materials" +1540 "Inventory / Work in process" +1550 "Inventory / Finished Goods" +1800 "CAPITAL ASSETS" +1820 "Office Furniture & Equipment" +1825 "Accum. Amort. -Furn. & Equip." +1840 "Vehicle" +1845 "Accum. Amort. -Vehicle" +2000 "CURRENT LIABILITIES" +2100 "Accounts Payable" +2600 "LONG TERM LIABILITIES" +2620 "Bank Loans" +2680 "Loans from Shareholders" +3300 "SHARE CAPITAL" +3350 "Common Shares" +3500 "RETAINED EARNINGS" +3590 "Retained Earnings - prior years" +4000 "SALES REVENUE" +4020 "Sales / General" +4030 "Sales / Manufactured Goods" +4040 "Sales / Aftermarket Parts" +4400 "OTHER REVENUE" +4430 "Shipping & Handling" +4440 "Interest" +4450 "Foreign Exchange Gain" +5000 "COST OF GOODS SOLD" +5010 "Purchases" +5020 "COGS / General" +5030 "COGS / Raw Materials" +5040 "COGS / Direct Labor" +5050 "COGS / Overhead" +5100 "Freight" +5400 "PAYROLL EXPENSES" +5410 "Wages & Salaries" +5600 "GENERAL & ADMINISTRATIVE EXPENSES" +5610 "Accounting & Legal" +5615 "Advertising & Promotions" +5620 "Bad Debts" +5660 "Amortization Expense" +5685 "Insurance" +5690 "Interest & Bank Charges" +5700 "Office Supplies" +5760 "Rent" +5765 "Repair & Maintenance" +5780 "Telephone" +5785 "Travel & Entertainment" +5790 "Utilities" +5795 "Registrations" +5800 "Licenses" +5810 "Foreign Exchange Loss" +2110 "Accrued Income Tax - Federal" +2120 "Accrued Income Tax - State" +2130 "Accrued Franchise Tax" +2140 "Accrued Real & Personal Prop Tax" +2150 "Sales Tax" +2210 "Accrued Wages" +5510 "Inc Tax Exp - Federal" +5520 "Inc Tax Exp - State" +5530 "Taxes - Real Estate" +5540 "Taxes - Personal Property" +5550 "Taxes - Franchise" +5560 "Taxes - Foreign Withholding" + } +} + service { + array set gl { +1000 "CURRENT ASSETS" +1060 "Checking Account" +1065 "Petty Cash" +1200 "Accounts Receivables" +1205 "Allowance for doubtful accounts" +1500 "INVENTORY ASSETS" +1520 "Inventory" +1800 "CAPITAL ASSETS" +1820 "Office Furniture & Equipment" +1825 "Accum. Amort. -Furn. & Equip." +1840 "Vehicle" +1845 "Accum. Amort. -Vehicle" +2000 "CURRENT LIABILITIES" +2100 "Accounts Payable" +2600 "LONG TERM LIABILITIES" +2620 "Bank Loans" +2680 "Loans from Shareholders" +3300 "SHARE CAPITAL" +3350 "Common Shares" +3500 "RETAINED EARNINGS" +3590 "Retained Earnings - prior years" +4000 "CONSULTING REVENUE" +4020 "Consulting" +4400 "OTHER REVENUE" +4410 "General Sales" +4440 "Interest" +4450 "Foreign Exchange Gain" +5000 "EXPENSES" +5020 "Purchases" +5400 "PAYROLL EXPENSES" +5410 "Wages & Salaries" +5600 "GENERAL & ADMINISTRATIVE EXPENSES" +5610 "Accounting & Legal" +5615 "Advertising & Promotions" +5620 "Bad Debts" +5660 "Amortization Expense" +5685 "Insurance" +5690 "Interest & Bank Charges" +5700 "Office Supplies" +5760 "Rent" +5765 "Repair & Maintenance" +5780 "Telephone" +5785 "Travel & Entertainment" +5790 "Utilities" +5795 "Registrations" +5800 "Licenses" +5810 "Foreign Exchange Loss" +2110 "Accrued Income Tax - Federal" +2120 "Accrued Income Tax - State" +2130 "Accrued Franchise Tax" +2140 "Accrued Real & Personal Prop Tax" +2150 "Sales Tax" +2210 "Accrued Wages" +5510 "Inc Tax Exp - Federal" +5520 "Inc Tax Exp - State" +5530 "Taxes - Real Estate" +5540 "Taxes - Personal Property" +5550 "Taxes - Franchise" +5560 "Taxes - Foreign Withholding" + } + } +} + +} + + +ad_proc -private acc_fin::gl_tx_balanced { + transaction_list +} { + Returns 1 for True, or 0 for False to Question: Is supplied GL transaction balanced? + transaction_list is a list of list pairs {account_number amount} + checks total sum, not the relevance of a particular account to it's placement in the accounting equation. +} { + set sum 0. + set errors 0 + foreach list_pair $transaction_list { + set term [lindex $list_pair 1] + if { [ad_var_type_check_number_p $term] } { + set sum [expr { $sum + $term } ] + } else { + set errors 1 + } + set balanced [expr { $sum == 0. && $errors == 0 } ] + return $balanced +} + +ad_proc -private acc_fin::gl_tx { + general_ledger_array_name + transaction_actnbr_amount_pairs_list +} { + processes a GL transaction of multiple columns +} { + upvar $general_ledger_array_name gl + set success [acc_fin::gl_tx_balanced $transaction_actnbr_amount_pairs_list] + if { $success } { + foreach tx_pair $transaction_actnbr_amount_pairs_list { + set account [lindex $tx_pair 0] + set amount [lindex $tx_pair 1] + if { [info exists gl($account) ] } { + set gl($account) [expr { $gl($account) + $amount } ] + } else { + set gl($account) $amount + } + } + } + return $success +} + + +# create proc gl_tx that accepts pairs of account debit/credit, where debits = credits +# create procs to mimmic AR/Transaction, AP/transaction, and other common transactions to reduce model complexity. +# create proce that shows balance sheet etc for any period or difference between two or more periods