::namespace eval ::qw::payrun { ::proc ::qw::payrun::debug_puts {Src} { ::if {$::qw::verbose(payrun)} {::puts "(payrun) $Src";} } } ::if {$::qw::control(has_tk)} { itcl::class ::QW::NV2::PAYROLL::PROCESS { inherit itk::Toplevel; itk_option define -font font Font {-family Arial -size 11 -weight bold}; protected variable _payList ""; protected variable _payrunObject ""; protected variable _payrollObject ""; protected variable _database ""; protected variable _status ""; protected variable _options ""; protected variable _table; protected variable _payrunAccounts ""; protected variable _process_status ""; protected variable _debugLogIsOn 1; protected variable _afterId ""; protected variable _payrollCountry ""; protected variable _indentLevel 0; protected variable _indentDepth 4; protected variable _errors 0; protected variable _warnings 0; protected variable _employee ""; protected variable _employee_structure ""; protected variable _error_list ""; protected variable _chequeWord "check"; protected variable _is_destroyed 0; protected variable _date 0; ;#// Date of cash or accrual payroll check protected variable _ppBeginDate 0; ;#// Pay-period begin date protected variable _ppEndDate 0; ;#// Pay-period end date protected variable _ppNumber 0; protected variable _ppYear 0; protected variable _log; ;#// Tax calc procs write append details to this protected variable _pay_frequency ""; ;#// Pay Periods protected variable _records ""; protected variable _savedVariables ""; protected variable _total_net_pay 0.0; protected variable _yearBeginDate; ;#// January 1 of year _date protected variable _yearEndDate; ;#// December 31 of year _date protected variable _toplevel_title ""; protected variable _employeePayChecksInPayPeriod ""; protected variable _warning_list ""; protected variable _employee_detail_list ""; protected variable _view "summary"; protected variable _tablesStartDate ""; protected variable _tablesEndDate ""; protected variable _version ""; protected variable _patch_level "1"; protected variable _version_country ""; protected variable _patch_level_country "" protected variable _employee_notes ""; protected variable _payrun_notes ""; protected variable _allocation_partitions ""; protected variable _TQuantity 0.0; protected variable _TAmount 0.0; protected variable _vacation_pay_earned_account ""; protected variable _vacation_pay_earned_amount 0.0; protected variable _vacation_pay_withheld_account ""; protected variable _vacation_pay_withheld_amount 0.0; public method constructor {args} { ::array set Args $args; ::set _payrunObject ""; ::set _afterId ""; ::set _version "20080101"; ::set _patch_level "0"; ::set _log ""; ::if {![::info exists Args(-version_information)]} { debugLogStart; ::qw::assert {[::info exists Args(-odb_object)]}; ::set _payrunObject $Args(-odb_object); ::qw::assert {$_payrunObject ne ""}; $_payrunObject odb_cache_detach; ::set _database [$_payrunObject odb_database]; ::set _options [::sargs::+= $::qw::widget::default [::subst { /header {} /table {} /status {} /button {} }]]; ::array set _table { employees-description "Employees" } ::set _table(names) ""; ::lappend _table(names) "employees"; ::foreach Name $_table(names) { ::set _table($Name-processed) 0; ::set _table($Name-target) 0; ::set _table($Name-checks_above_maximum) 0; ::set _table($Name-checks_below_minimum) 0; } ::set _table(checks-posted) 0; ::set _error_list ""; ::set _warning_list ""; ::set _detail_list ""; ::set _employee_detail_list ""; ::set _view "summary"; ::unset Args(-odb_object); ::eval display_1 [::array get Args]; ::if {[::qw::command_exists $_payrunObject]} { [[[$_payrunObject .payroll] odb_get] odb_master] is_processing_a_payrun [::sargs .operation set .value 1]; ;#//::incr 1 } } } public method destructor {} { ::if {[::qw::command_exists $_payrunObject]} { [[[$_payrunObject .payroll] odb_get] odb_master] is_processing_a_payrun [::sargs .operation set .value 0]; ;#//::incr -1 $_payrunObject odb_cache_attach; } ::if {$_afterId ne ""} {::after cancel $_afterId;} } public method version_information {} { ::set Base ""; ::sargs::var::set Base ".version" $_version; ::sargs::var::set Base ".patch_level" $_patch_level; ::set Derived ""; ::sargs::var::set Derived ".country" $_payrollCountry; ::sargs::var::set Derived ".version" $_version_country; ::sargs::var::set Derived ".patch_level" $_patch_level_country; ::sargs::var::set Derived ".tables_start_date" $_tablesStartDate; ::sargs::var::set Derived ".tables_end_date" $_tablesEndDate; ::sargs::var::set Derived ".other_information" [version_information_other]; ::return [::sargs::set $Base "/$_payrollCountry" $Derived]; } public method version_information_other {} { ::return ""; } public method help {} { ::qw::htmlhelp [::sargs .chm_path $::qw_manual_file .id "/857720041230140547.htm"]; } public method option {Path} {::return [::sargs::get_poly $_options $Path];} public method options {Options} { ::set _options [::sargs::+= $_options $Options]; ::return $this; } public method tableNames {} {::return $_table(names);} public method copy_to_clipboard {{s_args ""}} { ::clipboard clear; ::if {$_view eq "detail"} { ::set Text [$itk_interior.details get 1.0 end]; } else { ::set Text [$itk_interior.summary get 1.0 end]; } ::clipboard append -displayof . -format STRING -type STRING -- $Text; } public method display_1 {args} { ::set LabelBorderWidth 0.5m; ::set ControlPadding 0.5m; ::set Me $itk_interior; ::qw::toplevel_add [::sargs .path $Me]; ::frame $Me.controls -height 2 -borderwidth 1m -relief sunken; ::button $Me.controls.action -borderwidth $ControlPadding -font [option /button.font]; ::button $Me.controls.abort -borderwidth $ControlPadding -font [option /button.font]; ::button $Me.controls.view -borderwidth $ControlPadding -font [option /button.font]; ::button $Me.controls.clipboard -text "Copy to Clipboard" -borderwidth $ControlPadding -command [::itcl::code $this copy_to_clipboard] -font [option /button.font]; ::button $Me.controls.help -text Help -borderwidth $ControlPadding -command [::itcl::code $this help] -font [option /button.font]; ::label $Me.status -textvariable [::itcl::scope _status] -relief sunken -borderwidth $LabelBorderWidth -anchor w -font [option /status.font]; ::frame $Me.table; ::pack $Me.table -expand 0 -fill both -padx 4 -pady 4; itk_component add details { ::iwidgets::scrolledtext $itk_interior.details -borderwidth $ControlPadding; } { usual } $Me.details configure -textfont {Courier 10} -wrap none; $Me.details tag configure warning -foreground "dark orange" -font {Courier 10 bold}; $Me.details tag configure error -foreground red -font {Courier 10 bold}; $Me.details tag configure title -foreground black -font {Courier 10 bold underline}; itk_component add summary { ::iwidgets::scrolledtext $itk_interior.summary -borderwidth $ControlPadding; } { usual } $Me.summary configure -textfont {Courier 10} -wrap none; $Me.summary tag configure warning -foreground "dark orange" -font {Courier 10 bold}; $Me.summary tag configure error -foreground red -font {Courier 10 bold}; $Me.summary tag configure title -foreground black -font {Courier 10 bold underline}; ::pack $Me.summary -fill both -expand true -padx 4 -pady 4; ::pack $Me.controls -expand no -fill x -padx $ControlPadding -pady $ControlPadding; ::pack $Me.controls.abort -side left -expand yes -fill x -padx $ControlPadding -pady $ControlPadding; ::pack $Me.controls.clipboard -side left -expand yes -fill x -padx $ControlPadding -pady $ControlPadding; ::pack $Me.controls.help -side left -expand yes -fill x -padx $ControlPadding -pady $ControlPadding; ::pack $Me.controls.view -side left -expand yes -fill x -padx $ControlPadding -pady $ControlPadding; ::pack $Me.status -fill x -padx 4 -pady 4; ::wm group $itk_component(hull) .; ::label $Me.table._titlelabel -text "Type" -font [option /header.font] -relief raised -borderwidth $LabelBorderWidth -width 22 -anchor c ::label $Me.table._titletarget -text "Count" -font [option /header.font] -relief raised -borderwidth $LabelBorderWidth -width 11 -anchor c ::label $Me.table._titleitems -text "Done" -font [option /header.font] -relief raised -borderwidth $LabelBorderWidth -width 11 -anchor c ::label $Me.table._titlecompletion -text "Percent Done" -font [option /header.font] -relief raised -borderwidth $LabelBorderWidth -width 30 -anchor c ::set Row 0; ::set Column 0; ::grid $Me.table._titlelabel -row $Row -column $Column -sticky ewns;::incr Column; ::grid $Me.table._titletarget -row $Row -column $Column -sticky ewns;::incr Column; ::grid $Me.table._titleitems -row $Row -column $Column -sticky ewns;::incr Column; ::grid $Me.table._titlecompletion -row $Row -column $Column -sticky ewns;::incr Column; ::incr Row; ::foreach Name [tableNames] { ::label $Me.table.${Name}label -text [::set [::itcl::scope _table($Name-description)]] -font [option /table.font] -relief sunken -borderwidth $LabelBorderWidth -width 22 -anchor e; ::label $Me.table.${Name}target -textvariable [::itcl::scope _table($Name-target)] -font [option /table.font] -relief sunken -borderwidth $LabelBorderWidth -width 11 -anchor e; ::label $Me.table.${Name}items -textvariable [::itcl::scope _table($Name-processed)] -font [option /table.font] -relief sunken -borderwidth $LabelBorderWidth -width 11 -anchor e; ::QW::WIDGET::COMPLETION_PERCENTAGE $Me.table.${Name}completion -limitvariable [::itcl::scope _table($Name-target)] -valuevariable [::itcl::scope _table($Name-processed)]; ::set Column 0; ::grid $Me.table.${Name}label -row $Row -column $Column -sticky ewns;::incr Column; ::grid $Me.table.${Name}target -row $Row -column $Column -sticky ewns;::incr Column; ::grid $Me.table.${Name}items -row $Row -column $Column -sticky ewns;::incr Column; ::grid $Me.table.${Name}completion -row $Row -column $Column -sticky ewns;::incr Column; ::grid rowconfigure $Me.table $Row -weight 1; ::incr Row; } ::grid columnconfigure $Me.table 0 -weight 1; ::grid columnconfigure $Me.table 1 -weight 1; ::grid columnconfigure $Me.table 2 -weight 1; ::grid columnconfigure $Me.table 3 -weight 1; $Me.controls.abort configure -text "Abort" -command [::itcl::code $this confirmAbort]; $Me.controls.view configure -text "Details" -command [::itcl::code $this switch_view]; configure -title $_toplevel_title; ::wm protocol $itk_component(hull) WM_DELETE_WINDOW [::itcl::code $this confirmAbort]; ::set _afterId [::after idle [::itcl::code $this centerOnScreen]]; ::eval itk_initialize $args; ::return $this; } public method display_2 {args} { set LabelBorderWidth 0.5m; set ControlPadding 0.5m; ::set Me $itk_interior; ::pack forget $Me.controls.abort; ::pack forget $Me.controls.clipboard; ::pack forget $Me.controls.help; ::pack forget $Me.controls.view; $Me.controls.action configure -text "Post Pay [::string totitle $_chequeWord]s" -command [::itcl::code $this post_paychecks]; ::bind $Me.controls.action [::itcl::code $this post_paychecks]; ::pack $Me.controls.action -side left -expand yes -fill x -padx $ControlPadding -pady $ControlPadding; ::pack $Me.controls.abort -side left -expand yes -fill x -padx $ControlPadding -pady $ControlPadding; ::pack $Me.controls.clipboard -side left -expand yes -fill x -padx $ControlPadding -pady $ControlPadding; ::pack $Me.controls.help -side left -expand yes -fill x -padx $ControlPadding -pady $ControlPadding; ::pack $Me.controls.view -side left -expand yes -fill x -padx $ControlPadding -pady $ControlPadding; $Me.details configure -state disabled; $Me.summary configure -state disabled; ::focus $Me.controls.action; status "Ready to post pay ${_chequeWord}s"; } public method display_3 {args} { ::wm protocol $itk_component(hull) WM_DELETE_WINDOW [::itcl::code $this window_destroy]; ::set Me $itk_interior; ::pack forget $Me.controls.abort; ::pack forget $Me.controls.help; ::pack forget $Me.controls.view; ::pack forget $Me.controls.action; ::pack forget $Me.controls; $Me.details configure -state normal; $Me.summary configure -state normal; status ""; } public method switch_view {} { ::if {$_view eq "summary"} { ::pack forget $itk_interior.summary; ::pack $itk_interior.details -fill both -expand true -padx 4 -pady 4 -before $itk_interior.controls; $itk_interior.controls.view configure -text "Summary"; ::set _view "detail"; ::return; } ::pack forget $itk_interior.details; ::pack $itk_interior.summary -fill both -expand true -padx 4 -pady 4 -before $itk_interior.controls; $itk_interior.controls.view configure -text "Details"; ::set _view "summary"; } public method status {args} { ::switch -- [::llength $args] { 0 { QW::ASSERT::expr {0} ::return $_status; } 1 { ::set _status [::lindex $args 0]; ::update ::return $this; } } ::qw::bug "907020050401052523" "Wrong number of args to status method."; } method increment {VarName {Increment 1}} { ::incr _table($VarName) $Increment; ::update; } public method details {Src {Tag {}}} { ::if {$_process_status ne "active"} {::return $this;} ::if {$Tag eq ""} { $itk_component(details) insert end "$Src\n"; } else { $itk_component(details) insert end "$Src\n" $Tag; } $itk_component(details) see end; } public method summary {Src {Tag {}}} { ::if {$_process_status ne "active"} {::return $this;} ::if {$Tag eq ""} { $itk_component(details) insert end "$Src\n"; $itk_component(summary) insert end "$Src\n"; } else { $itk_component(details) insert end "$Src\n" $Tag; $itk_component(summary) insert end "$Src\n" $Tag; } $itk_component(summary) see end; } public method payrun_error {Src} { summary $Src; ::lappend _error_list $Src; } public method window_destroy {} { ::if {$_process_status eq "aborted"} { ::return; } confirmAbort; ::if {$_process_status eq "aborted"} { ::set _is_destroyed 1; } } public method dialog_position {} { ::set Offset 50; ::set Geometry [::regsub -all \[^0-9\] [::winfo geometry $itk_component(hull)] " "]; ::set X [::lindex $Geometry 2]; ::set Y [::lindex $Geometry 3]; ::set Result ""; ::lappend Result [::expr $X+$Offset]; ::lappend Result $Y; ::lappend Result $Offset; ::lappend Result $Offset; ::return $Result; } public method confirmAbort {} { ::set BBox [::eval [::itcl::code $this dialog_position]]; ::set Result [::qw::dialog::confirm [::qw::list { .bbox $BBox .title "Abort payrun processing?" .text "Confirm that you want to abort the payrun processing." /button { /ok { .text "Abort Processing" } /cancel { .text "Continue Processing" } } }]]; ::if {$Result} { status "Processing aborted." ::set _process_status "aborted"; terminate; } else { ::set _process_status "active"; } } protected method centerOnScreen {} { ::set _afterId ""; ::set xyPosition [::sargs .x 100 .y 100]; ::set Fwindow [::qw::winutil::find_window_with_focus]; ::if {$Fwindow ne ""} { ::set xyPosition [::QW::GUI::POINT::+ [[[$Fwindow nv_toplevel] .frame] positionInScreen] $xyPosition]; } ::wm geometry $itk_component(hull) +[::sargs::get $xyPosition .x]+[::sargs::get $xyPosition .y]; ::return $this; } public method payrunNotesAppend {Src} { ::append _payrun_notes "$Src\n"; } public method employeeNotesAppend {Src} { ::append _employee_notes "$Src\n"; } public method indentIncrement {} { ::incr _indentLevel 1; } public method indentDecrement {} { ::if {$_indentLevel<1} {::return;} ::incr _indentLevel -1; } public method debugLogClear {} { ::set _log ""; ::return $this; } public method debugLogStart {} { ::set _debugLogIsOn 1; ::return $this; } public method debugLogStop {} { ::set _debugLogIsOn 0; ::return $this; } public method debugLogWrite {} { ::if {!$_debugLogIsOn} {::return $this;} [$_payrunObject ".notes"] odb_set $_log; ::sargs::var::set _payList ".notes" $_payrun_notes; ::return $this; } public method debugLog {Desc {Code {}} {Symbol {}} {Amount {}} args} { ::if {!$_debugLogIsOn} {::return $this;} ::set Line [::string repeat " " [::expr $_indentLevel*$_indentDepth]]; ::if {$Code eq ""&&$Symbol eq ""&&$Amount eq ""} { ::append Line $Desc; } else { ::append Line [padRight $Desc 30 { }]; ::append Line [padRight $Code 6 { }]; ::append Line [padRight $Symbol 5 { }]; ::if {$Amount ne ""} { ::set FAmount [::format %.4f $Amount]; ::if {$FAmount!=$Amount} {::set FAmount $Amount;} ::append Line [::format %10.4f $Amount]; } ::foreach Arg $args { ::if {$Arg eq ""} {::continue;} ::if {[::string is double $Arg]} { ::set Arg [::format %10.4f $Arg] } else { ::if {[::string is integer $Arg]} { ::set Arg [::format %10.4f $Arg] } else { ::set Arg [padRight $Arg 6 { }]; } } ::append Line $Arg; } } ::append _log "$Line\n"; ::return $Line; } public method process {args} { ::array set Args $args; ::set _errors 0; ::set _warnings 0; ::set _payrollObject [[[$_payrunObject ".payroll"] odb_get] odb_master]; ::set _date [[$_payrunObject ".check_date"] odb_get]; ::set _ppBeginDate [[$_payrunObject ".pay_period_start"] odb_get]; ::set _ppEndDate [[$_payrunObject ".pay_period_end"] odb_get]; ::set _payrunAccounts [[$_payrunObject ".accounts"] odb_get]; ::set _ppNumber [[$_payrunObject ".pay_period_number"] odb_get]; ::set _ppYear [[$_payrunObject ".pay_period_year"] odb_get]; ::set _payrun_notes ""; ::set PayFrequency [[$_payrollObject ".pay_frequency"] odb_get] ::set PayPeriods [$_payrollObject pay_periods_in_year [::qw::date::get $_ppEndDate "year"]]; debugLog "Check date: [::string range $_date 0 7] Pay Period: [::string range $_ppBeginDate 0 7] - [::string range $_ppEndDate 0 7] Year: $_ppYear Number: $_ppNumber of $PayFrequency"; ::if {$PayFrequency!=$PayPeriods} { debugLog "Note: There are $PayPeriods pay periods in $_ppYear"; } check_version_date; ::set _yearBeginDate ""; ::set _yearBeginDate [::qw::date::set $_yearBeginDate "year" [::qw::date::get $_date "year"]]; ::set _yearBeginDate [::qw::date::set $_yearBeginDate "month" "1"]; ::set _yearBeginDate [::qw::date::set $_yearBeginDate "day" "1"]; ::set _yearEndDate ""; ::set _yearEndDate [::qw::date::set $_yearBeginDate "month" "12"]; ::set _yearEndDate [::qw::date::set $_yearEndDate "day" "31"]; ::set _payList [[$_payrunObject ".paylist"] odb_get]; ::set _payList [::sargs::get $_payList ".paylist"]; ::set _table(employees-target) [::llength [::sargs::subs .structure $_payList]]; ::set _total_net_pay 0.0; ::set _process_status "active"; init_payroll; ::set _indentLevel 0; ::qw::try { ::foreach Sub [::sargs::subs .structure $_payList] { ::if {$_process_status eq "aborted"} { status "Aborting ..."; ::qw::throw ".text {Processing aborted by user} .priority abort"; } ::sargs::var::set _payList $Sub [employee_pay_calculate [::sargs::get $_payList $Sub]]; increment employees-processed; } ::if {[::llength $_error_list]>0} { ::set Notes [[$_payrunObject ".notes"] odb_get]; ::set _error_list [::join $_error_list \n]; ::append Notes "\n$_error_list"; [$_payrunObject ".notes"] odb_set $Notes; ::qw::throw [::sargs \ .text "[::llength $_error_list] errors encountered. Payrun can not be processed.\n$_error_list" \ .help_id 907020050401052918 \ ]; } } catch Exception { ::if {[::sargs::find_field_value .structure $Exception .field ".priority" .value "abort"]} { ::qw::dialog::notify [::qw::list { .title "Processing Aborted" .text "The PAYRUN processing has been aborted." /button { /cancel { .text "Dismiss" } /help { .command {::qw::help::window .page {.id 314120030503122203}} } } }]; ::return 0; } ::qw::throw $Exception; } summary ""; ::set Details "\t[padRight {Total Net Pay} 55 { }]"; ::append Details [format %10.2f $_total_net_pay]; summary $Details; ::set MaxErrors $_table(employees-checks_above_maximum); ::set MinErrors $_table(employees-checks_below_minimum); ::set TotalErrors [::expr $MaxErrors+$MinErrors]; ::if {$TotalErrors} { ::set Minimum [employeeInfoGet ".minimum_check_amount"]; ::set Maximum [employeeInfoGet ".maximum_check_amount"]; summary "\tNotice:\n" "warning"; ::if {$MaxErrors} { ::set Plural1 ""; ::set Plural2 "is"; ::if {$MaxErrors>1} {::set Plural1 "s";::set Plural2 "are";} summary "\t$MaxErrors $_chequeWord$Plural1 $Plural2 above the maximum of [::string trim [::format %10.2f $Maximum]] and will not be posted." "warning"; } ::if {$MinErrors} { ::set Plural1 ""; ::set Plural2 "is"; ::if {$MinErrors>1} {::set Plural1 "s";::set Plural2 "are";} summary "\t$MinErrors $_chequeWord$Plural1 $Plural2 below the minimum of [::string trim [::format %10.2f $Minimum]] and will not be posted." "warning"; } } debugLogWrite; display_2; ::return 1; } public method post_paychecks {} { ::foreach Sub [::sargs::subs .structure $_payList] { ::set EmployeeStructure [::sargs::get $_payList $Sub]; ::sargs::var::set _payList $Sub [employee_pay_record $EmployeeStructure]; } ::qw::try { $_payrunObject post_paychecks $_payList; } catch Exception { ::qw::itcl_delete_object $this; ::qw::throw [::qw::exception::parent $Exception "Could not post pay checks."]; } ::qw::itcl_delete_object $this; ;#// presumably memory leak free - qw.qw_tcl implementation is rename to empty ::set Message [::subst { .message_type feature_stats .message_type_value post_paychecks .message_data { .feature_used post_paychecks .employee_count [::llength [::sargs::subs .structure $_payList]] .timecards_paid [[[$_payrunObject .timecards] odb_primary] odb_items] } }]; ::qw::babyship::singleton asynch_post_to_mothership .message $Message; } public method terminate {} { ::if {$_payrunObject ne ""&&[::qw::command_exists $_payrunObject]} { $_payrunObject processing_aborted; } ::if {!$_is_destroyed} {::qw::itcl_delete_object $this;} } public method signal_receive_database_destroyed {} { ::qw::itcl_delete_object $this; } public method active {} { ::if {$_process_status eq "active"} {::return 1;} ::return 0; } public method employee_pay_record {Src} { ::set _employee_structure [::sargs::get $Src ".result"] ::set _employee [::sargs::get $Src ".odb_address"]; ::for {::set Sub 1} {$Sub<=[::sargs::get $_employee_structure ".number_of_accounts"]} {::incr Sub;} { employeeInfoSet ".current_sub" $Sub; ::set CodeList [accountInfoGet ".set_paycodes"]; ::if {$CodeList eq ""} { ::continue; } ::set Account [accountInfoGet ".account.address"]; ::set NormalBalance [accountInfoGet ".account.normal_balance"]; ::set Paycodes [[$Account ".paycodes"] odb_get]; ::set PayCodes [::sargs::get $Paycodes "/$NormalBalance"]; ::foreach Code $CodeList { ::sargs::var::set PayCodes $Code [payCodeValueGet $Code]; } ::sargs::var::set Paycodes "/$NormalBalance" $PayCodes; [$Account ".paycodes"] odb_set $Paycodes; $Account odb_commit; } ::return $Src; } public method check_version_date {} { ::set VersionInfo [version_information]; debugLog "$_payrollCountry payroll version: [::sargs::get $VersionInfo /$_payrollCountry.version] Patch level [::sargs::get $VersionInfo /$_payrollCountry.patch_level]"; ::set Message ""; ::if {[::qw::date::difference $_tablesStartDate $_date "day"]>0} { ::set Message "This payroll version does not contain tax table information for dates prior to [::qw::date::format $_tablesStartDate {%d %b %Y}]."; } ::if {[::qw::date::difference $_date $_tablesEndDate "day"]>0} { ::set Message "This payroll version does not contain tax table information for dates after [::qw::date::format $_tablesEndDate {%d %b %Y}]."; } ::if {$Message eq ""} {::return;} ::qw::throw [::sargs \ .text $Message \ .help_id 907020050401053232 \ ]; } public method init_payroll {} { init_payroll_country; ::return $this; } public method init_payroll_country {} { ::return $this; } public method init_employee {} { ::set _employee_detail_list ""; init_employee_country; ::return $this; } public method init_employee_country {} { ::return $this; } public method employee_pay_calculate {Src} { ::if {$_process_status ne "active"} { ::return ""; } ::set _employee [::sargs::get $Src ".odb_address"]; ::set _employee_notes ""; ::set _employeePayChecksInPayPeriod [employeePayChecksByPayPeriod [::sargs ".year" $_ppYear ".period" $_ppNumber]]; build_employee_structure $_employee [::sargs::get $Src ".item"]; debugLog ""; debugLog "Employee: [employeeInfoGet .employee_id] [employeeInfoGet .employee_name.print_as]"; ::if {[employeeInfoGet ".number_of_accounts"]==0} { ::return ""; } ::if {[employeeInfoGet ".accrued_wages_account"] ne ""} { ::return ""; } indentIncrement; ::unset -nocomplain _records;::array set _records {}; ::unset -nocomplain _savedVariables;::array set _savedVariables {}; init_employee; ::if {$::qw::control(accrual_payroll)} { ::set Range [::qw::odb::factory range]; ::set Index [$_employee ".timecards.index/date"]; ::set RangeBegin ".tag financial .date [::qw::date::extend_begin [[$_payrunObject .pay_period_start] odb_get]]"; ::set RangeEnd ".tag financial .date [::qw::date::extend_end [[$_payrunObject .pay_period_end] odb_get]]"; $Range cpp_configure -index $Index -begin $RangeBegin -end $RangeEnd; ::set References [$Range odb_references ".order_is_kept 1"]; ;#// there are duplicates, we must get references rwb_??? $Range cpp_destroy; ::set DebitList ""; ::foreach Ref $References { ::if {[[[$Ref odb_master] ".paycheck"] odb_get] ne ""} { ::continue; } ::set Items [[[$Ref odb_master] ".odb_deriveds.index/id"] odb_references]; ::foreach Item $Items { ::set AccountRef [[[$Item odb_master] ".posting/debit.account"] odb_get]; ::if {$AccountRef eq ""} { ::continue; ;#// a text line } ::set AccountMaster [$AccountRef odb_master]; ::set Quantity [[[$Item odb_master] ".posting/debit.quantity"] odb_get]; ::set Amount [[[$Item odb_master] ".posting/debit.amount"] odb_get]; ::lappend DebitList [::list $AccountMaster $Quantity $Amount]; } } ::set DebitList [::lsort -index 0 $DebitList]; ::set Partitions ""; ::set Partition 0; ::set Quantity 0.0; ::set Amount 0.0; ::set TQuantity 0.0; ::set TAmount 0.0; ::set DebitAccount [::lindex [::lindex $DebitList 0] 0]; ::foreach DebitItem $DebitList { ::set Account [::lindex $DebitItem 0]; ::if {$Account ne $DebitAccount} { ::incr Partition; ::lappend Partitions [::list $DebitAccount $Quantity $Amount]; ::set DebitAccount $Account; ::set Quantity 0.0; ::set Amount 0.0; } ::qw::number::var::add Quantity [::lindex $DebitItem 1]; ::qw::number::var::add Amount [::lindex $DebitItem 2]; ::qw::number::var::add TQuantity [::lindex $DebitItem 1]; ::qw::number::var::add TAmount [::lindex $DebitItem 2]; } ::if {[::llength $DebitList]} { ::incr Partition; ::lappend Partitions [::list $DebitAccount $Quantity $Amount]; } ::set _allocation_partitions $Partitions; ;#// for details preview and debugLog ::set _TQuantity $TQuantity; ::set _TAmount $TAmount; } ::set _pay_frequency [[[[[$_employee ".payroll"] odb_get] odb_master] ".pay_frequency"] odb_get]; ::for {::set Sub 1} {$Sub<=[::sargs::get $_employee_structure ".number_of_accounts"]} {::incr Sub;} { employeeInfoSet ".current_sub" $Sub; DETAILS; ;#// posting info? DOLINE; ;#// preview? } ::set Details "\t[padRight {Net Pay} 55 { }]"; ::append Details [::format %10.2f [employeeInfoGet .net_pay]]; summary $Details; ::set Process 1; ::set NetPay [employeeInfoGet ".net_pay"]; ::set Minimum [employeeInfoGet ".minimum_check_amount"] ::set Maximum [employeeInfoGet ".maximum_check_amount"] ::if {$NetPay<$Minimum} { summary "\n\tNotice: Net pay [::string trim [::format %10.2f $NetPay]] is below the minimum $_chequeWord amount of [::string trim [::format %10.2f $Minimum]]." "warning"; summary "\t\tThis $_chequeWord will not be posted.\n" "warning"; ::lappend _warning_list "Employee: [employeeInfoGet .employee_id] net pay [::string trim [::format %10.2f $NetPay]] is below the minimum $_chequeWord amount of [::string trim [::format %10.2f $Minimum]]."; ::set Process 0; increment employees-checks_below_minimum; } ::if {$NetPay>$Maximum} { summary "\n\tNotice: Net pay [::string trim [::format %10.2f $NetPay]] is above the maximum $_chequeWord amount of [::string trim [::format %10.2f $Maximum]]." "warning"; summary "\t\tThis $_chequeWord will not be posted.\n" "warning"; ::lappend _warning_list "Employee: [employeeInfoGet .employee_id] net pay [::string trim [::format %10.2f $NetPay]] is above the maximum $_chequeWord amount of [::string trim [::format %10.2f $Maximum]]"; ::set Process 0; increment employees-checks_above_maximum; } ::sargs::var::set _employee_structure ".process" $Process; ::if {$Process} { ::set _total_net_pay [::qw::number::add $_total_net_pay $NetPay]; ::set Sub [append_account_structure]; accountInfoSet ".result.description" "--- Details not on Paycheck Stub ---" $Sub; accountInfoSet ".result.line_type" "text_line" $Sub; accountInfoSet ".account.address" "" $Sub; accountInfoSet ".result.amount" 0.0 $Sub; record_unallocated_earnings; ;#// including (especially) vacation pay record_employer_contributions; ;#// Add employer contributions } ::sargs::var::set _employee_structure ".notes" $_employee_notes; ::sargs::var::set Src ".result" $_employee_structure; employee_end; ;#// finish off the preview indentDecrement; ::return $Src; } public method DETAILS {} { debugLog "[accountInfoGet .account.name] Type: [payCodeValueGet .type]"; indentIncrement; ::set Amount [round2 [calculate_pay]]; ::set Limit [payCodeValueNumber ".annual_limit"]; ::set Percent [payCodeValueNumber ".percent"]; ::set Limit2 [round2 [::qw::number::multiply [::qw::number::divide $Percent 100.0] $Limit]]; ::if {$Limit2<$Limit} { ::set Limit $Limit2; } ::if {$Limit>0.0&&[::qw::number::add [accountInfoGet ".amount/year_to_date"] $Amount]>$Limit} { ::if {[accountInfoGet ".amount/year_to_date"]<$Limit} { ::set Amount [::qw::number::subtract $Limit [accountInfoGet ".amount/year_to_date"]]; } else { ::set Amount 0.0; } debugLog "Annual limit $Limit exceeded, amount now $Amount"; } indentDecrement; debugLog "[accountInfoGet .account.name] Result: $Amount"; accountInfoSet ".result.amount" $Amount; accountInfoSet ".amount/year_to_date" [::qw::number::add [accountInfoGet ".amount/year_to_date"] $Amount]; ::return $this; } public method calculate_pay {} { ::set Type [payCodeValueGet ".type"]; ::qw::payrun::debug_puts "BASE calculate_pay Type==$Type"; ::if {[accountInfoGet ".account.normal_balance"] eq "debit"} { ::switch $Type { "ADVANCE" {::return [ADVANCE];} "VACATIONEARNED" {::return [VACATIONEARNED];} "VACATIONPAID" {::return [VACATIONPAID];} "REGULAR" {::return [REGULAR];} } ::return [UNKNOWNEARNING $Type]; } ::switch $Type { "VACATIONACCRUED" {::return [VACATIONACCRUED];} "REIMBURSEMENT" {::return [REIMBURSEMENT];} "CUSTOM" { ::set Tmp1 "~D[payCodeValueGet .type].U2"; ::set Result 0; ::if {[::info commands $Tmp1] eq $Tmp1} { ::return [$Tmp1]; # Call user exit routine } } } ::return [UNKNOWNDEDUCTION $Type]; } public method DOLINE {} { ::set Amount [accountInfoGet ".result.amount"]; ::if {[accountInfoGet ".account.normal_balance"] eq "credit"} { ::qw::number::var::negative Amount; } ::set Description [payCodeValueGet ".description"]; ::if {$Description eq ""} { ::set Description [accountInfoGet ".result.description"]; } ::set Description [~AYRUN.U1 $Description]; ;#// User exit routine, sets up YTD printing accountInfoSet ".result.description" $Description; employeeInfoSet ".net_pay" [::qw::number::add [employeeInfoGet ".net_pay"] $Amount]; ::set Details "\t"; ::append Details "[padRight $Description 35 { }]"; ::append Details [::format %10.2f $Amount]; ::append Details " "; ::append Details [::format %10.2f [employeeInfoGet ".net_pay"]]; summary $Details; } public method UNKNOWNEARNING {Type} { ::set Result [percent_or_time_amount_get]; accountInfoSet ".result.description" "$Type earning"; ::return $Result; } public method UNKNOWNDEDUCTION {Type} { ::set Result [percent_or_time_amount_get]; accountInfoSet ".result.description" "$Type deduction"; ::return $Result; } public method REGULAR {} { accountInfoSet ".result.description" "Regular YTD = @Y" ::set Result [percent_or_time_amount_get]; ::return $Result; } public method percent_or_time_amount_get {} { ::qw::payrun::debug_puts "BASE percent_or_time_amount_get 1 .percent==\"[payCodeValueGet .percent]\""; ::if {[payCodeValueGet ".percent"] ne ""} { ::if {[payCodeValueGet ".percent"] != 0.0} { ::qw::payrun::debug_puts "BASE percent_or_time_amount_get 3 .percent==\"[payCodeValueGet .percent]\""; ::return [PER]; } } ::return [TIME]; } public method TIME {} { ::set Quantity [payCodeValueGet ".quantity"]; ::set Rate [payCodeValueGet ".rate"]; ::if {![::string is integer $Rate]&&![::string is double $Rate]} {::set Rate 0;} ::if {$Rate eq ""} {::set Rate 0;} ::if {$Quantity ne ""} { ::if {![::string is integer $Quantity]&&![::string is double $Quantity]} {::set Quantity 0;} ::if {$Quantity eq ""} {::set Quantity 0;} ::if {$::qw::control(accrual_payroll)} {} accountInfoSet ".result.description" "[accountInfoGet .account.suffix] $Quantity hrs * \$$Rate"; ::set Result [round2 [::qw::number::multiply $Rate $Quantity]]; payCodeValueSet ".quantity" $Quantity; } else { accountInfoSet ".result.description" [accountInfoGet ".account.suffix"]; ::set Result [payCodeValueNumber ".rate"]; } debugLog "Quantity: $Quantity Rate: $Rate, Amount: $Result"; accountInfoSet ".result.quantity" $Quantity; accountInfoSet ".result.rate" $Rate; ::return $Result; } public method PER {} { ::set Result 0.0; ::if {[payCodeValueGet ".percent"] eq ""} { ::return $Result; } ::set Percentage [::qw::number::divide [payCodeValueGet ".percent"] 100.0]; ::set PercentageBase [payCodeValueGet ".percentage_base"]; ::if {$PercentageBase ne ""} { ::set Amount [percentage_base [::sargs ".expression" $PercentageBase]]; ::set Text "Percentage base: $PercentageBase"; } else { ::set Amount [taxable_income]; ::set Text "Percentage base is taxable income"; } ::set Result [round2 [::qw::number::multiply $Amount $Percentage]]; ::append Text " Base: $Amount Rate: $Percentage, Result: $Result"; debugLog $Text; accountInfoSet ".result.description" "[round2 $Amount] [accountInfoGet .account.suffix] @ [payCodeValueGet .percent] %"; ::if {$Amount eq ""} {::set Amount 0.0;} ::if {$Percentage eq ""} {::set Percentage 0.0;} accountInfoSet ".result.percentage_base" $Amount; accountInfoSet ".result.percent" $Percentage; ::return $Result; } public method taxable_income {} { ::return 0.0; } public method RATE {} { ::return [payCodeValueNumber ".rate"]; } public method ADVANCE {} { accountInfoSet ".result.description" "Advance"; ::return [ADVREIMB]; } public method REIMBURSEMENT {} { accountInfoSet ".result.description" "Reimbursement"; ::return [ADVREIMB]; } public method ADVREIMB {} { ::set Result 0; ::set Account [accountInfoGet ".account.address"] ::set Name [accountInfoGet ".account.name"] ::set BeginDate [::qw::date::extend_begin "19030101"]; ::set EndDate [::qw::date::extend_end $_date]; ::set AccountBalance [history $Account $BeginDate $EndDate ".amount"]; ::set NormalBalance [accountInfoGet ".account.normal_balance"]; ::if {$AccountBalance==0.0} { debugLog "Account balance is 0.00, nothing to do"; ::return 0.0; } ::if {$NormalBalance eq "debit" && $AccountBalance<0.0} { debugLog "Advance receivable balance $AccountBalance is negative, nothing to do"; ::return 0.0; } ::if {$NormalBalance eq "credit" && $AccountBalance>0.0} { debugLog "Reimbursement payable balance -$AccountBalance is negative, nothing to do"; ::return 0.0; } debugLog "Account balance: $AccountBalance"; ::set Result $AccountBalance; ::if {[payCodeValueGet ".percent"] ne ""} { ::set Result [PER]; ::if {$NormalBalance eq "credit"} { ::set Result [::qw::number::negative $Result]; } } else { ::if {[payCodeValueGet ".rate"] ne ""} { ::set Result [RATE]; ::if {$NormalBalance eq "credit"} { ::set Result [::qw::number::negative $Result]; } } } ::if {$Result==0.0} { debugLog "No rate or percentage amount, nothing to do"; ::return 0.0; } debugLog "Rate or percentage to process: $Result"; ::if {$NormalBalance eq "debit"} { ::if {$Result<0.0} { debugLog "Advance receivable amount is a credit, nothing to do"; ::return 0.0; } ::if {$Result>$AccountBalance} { debugLog "Advance receivable amount capped at account balance $AccountBalance"; ::set Result $AccountBalance; } ::return [::qw::number::negative $Result]; } ::if {$NormalBalance eq "credit"} { ::if {$Result>0.0} { debugLog "Reimbursement payable amount is a debit, nothing to do"; ::return 0.0; } ::if {$Result<$AccountBalance} { debugLog "Reimbursement payable amount capped at account balance $AccountBalance"; ::set Result $AccountBalance; } ::return $Result; } ::return 0.0; } public method VACATIONEARNED {} { ::if {$::qw::control(accrual_payroll)} {} ::set _vacation_pay_earned_account [accountInfoGet ".account.address"]; accountInfoSet ".result.description" "Vacation pay earned"; ::set Vacation_Pay_Earnings [earningsSubjectTo ".vacation_pay"]; ::if {[payCodeValueGet ".percent"] ne ""} { ::set _vacation_pay_earned_amount [round2 [::qw::number::multiply [::qw::number::multiply [payCodeValueNumber ".percent"] $Vacation_Pay_Earnings] .01]]; ::return $_vacation_pay_earned_amount; } ::set _vacation_pay_earned_amount [RATE]; ::return $_vacation_pay_earned_amount; } public method VACATIONACCRUED {} { ::if {$::qw::control(accrual_payroll)} {} ::set _vacation_pay_withheld_account [accountInfoGet ".account.address"]; accountInfoSet ".result.description" "Vacation pay withheld"; ::set Vacation_Pay_Earnings [earningsSubjectTo ".vacation_pay"]; ::if {[payCodeValueGet ".percent"] ne ""} { ::set _vacation_pay_withheld_amount [round2 [::qw::number::multiply [::qw::number::multiply [payCodeValueNumber ".percent"] $Vacation_Pay_Earnings] .01]]; ::return $_vacation_pay_withheld_amount; } ::set _vacation_pay_withheld_amount [RATE]; ::return $_vacation_pay_withheld_amount; } public method vacation_owed {} { ::set VacationAmounts [$_employee vacation_amounts]; ::set Result [::sargs::get $VacationAmounts ".owed/perpetual"]; ::set EarnedThisCheck 0.0; ::set Sub [::expr [employeeInfoGet ".current_sub"]-1]; ::while {$Sub>=1} { ::if {[payCodeValueGet ".type" $Sub] eq "VACATIONEARNED"} { ::set EarnedThisCheck [accountInfoGet ".result.amount" $Sub]; ::break; } ::incr Sub -1; } ::return [::qw::number::add $Result $EarnedThisCheck]; } public method VACATIONPAID {} { ::set Result 0.0; ::set Rate [::string tolower [payCodeValueGet ".rate"]]; ::if {$Rate eq "all"||[payCodeValueNumber ".rate"]!=0.0} { ::set VacOwed [vacation_owed]; ::if {$Rate eq "all"} { ::set Result $VacOwed; payCodeValueSet ".rate" "0"; ::set Codes [accountInfoGet ".set_paycodes"]; ::if {[::lsearch -exact $Codes ".rate"]<0} {::lappend Codes ".rate";} accountInfoSet ".set_paycodes" $Codes; } else { ::set Result [TIME]; ::if {$Result>$VacOwed} { ::set Result $VacOwed; } } } accountInfoSet ".result.description" "Vacation pay paid"; ::return $Result; } public method varListSave {Src} { ::foreach Var $Src {::set _savedVariables($Var) [::set $Var];} } public method varListRestore {Src} { ::foreach Var $Src {::set $Var _savedVariables($Var);} } public method payrunAccount {Type} { ::return [::sargs::get $_payrunAccounts $Type]; } public method employee_end {} { ::if {$::qw::control(accrual_payroll)} { preview_unallocated_earnings; } ::foreach Item $_employee_detail_list { details "\t$Item"; } } public method preview_unallocated_earnings {} { ::foreach Sub [::sargs::subs .structure [::sargs::get $_employee_structure ".accounts"]] { ::if {[::sargs::get $_employee_structure ".accounts$Sub.account.normal_balance"] ne "debit"} { ::continue; } ::if {[::sargs::boolean_get $_employee_structure ".accounts$Sub.account.pay_codes.quantity_is_from_timecard"]} { ::continue; } ::set Aname [::sargs::get $_employee_structure ".accounts$Sub.account.name"]; ::set EqualName [::string map "- =" $Aname]; ::set Reference [[$_employee ".accounts.index/name"] odb_find_key ".name" $EqualName]; ::if {$Reference eq ""} { ::continue; } ::set EqualAccount [$Reference odb_master]; ::set HyphenName [::sargs::get $_employee_structure ".accounts$Sub.account.name"]; ::set Desc "$HyphenName Wage Allocation"; ::lappend _employee_detail_list \ "[padRight $Desc 35 { }][::format %10.2f [::sargs::get $_employee_structure .accounts$Sub.result.amount]]"; ::if {[::llength $_allocation_partitions]==0} { ::set ExpenseAccount [::sargs::get $_payrunAccounts "/unallocated_wage_expense"]; ::if {$ExpenseAccount eq ""} { ::qw::throw [::sargs \ .text "The unallocated wage expense account has not been set." \ .help_id 271820070817141911 \ ]; } ::set Desc "Unallocated $HyphenName Wage Expense"; ::lappend _employee_detail_list "[padRight $Desc 35 { }][::format %10.2f [::sargs::get $_employee_structure .accounts$Sub.result.amount]]"; } else { ::set Count 0; ::set FinalAllocation [::expr {[::llength $_allocation_partitions]-1}]; ::set AllocationSum 0.0; ::foreach Partition $_allocation_partitions { ::set PName [[[::lindex $Partition 0] ".name"] odb_get]; ::set PDescription [[[::lindex $Partition 0] ".description"] odb_get]; ::append PName " $PDescription"; ::if {$Count==$FinalAllocation} { ::set PNumber [::qw::number::subtract [::sargs::get $_employee_structure ".accounts$Sub.result.amount"] $AllocationSum]; } else { ::set Allocation [::expr {$_TAmount==0.0?0.0:[::qw::number::divide [::lindex $Partition 2] $_TAmount]}]; ::set PNumber [round2 [::qw::number::multiply [::sargs::get $_employee_structure ".accounts$Sub.result.amount"] $Allocation]]; ::qw::number::var::add AllocationSum $PNumber; } ::lappend _employee_detail_list "..[padRight $PName 25 { }][::format %10.2f $PNumber]"; indentIncrement; debugLog "Unallocated wages $PName ==$PNumber"; indentDecrement; ::incr Count; } } } ::return $this; } public method record_unallocated_earnings {} { ::foreach Sub [::sargs::subs .structure [::sargs::get $_employee_structure ".accounts"]] { ::if {[::sargs::get $_employee_structure ".accounts$Sub.account.normal_balance"] ne "debit"} { ::continue; } ::if {[::sargs::boolean_get $_employee_structure ".accounts$Sub.account.pay_codes.quantity_is_from_timecard"]} { ::continue; } ::set Aname [::sargs::get $_employee_structure ".accounts$Sub.account.name"]; ::set EqualName [::string map "- =" $Aname]; ::set Reference [[$_employee ".accounts.index/name"] odb_find_key ".name" $EqualName]; ::if {$Reference eq ""} { ::continue; } ::set EqualAccount [$Reference odb_master]; ::set HyphenName [::sargs::get $_employee_structure ".accounts$Sub.account.name"]; ::if {[::llength $_allocation_partitions]==0} { ::set ExpenseAccount [::sargs::get $_payrunAccounts "/unallocated_wage_expense"]; ::set NewSub [append_account_structure]; accountInfoSet ".result.description" "Unallocated $HyphenName Wages Expense" $NewSub; accountInfoSet ".account.address" $ExpenseAccount $NewSub; accountInfoSet ".result.quantity" [::sargs::get $_employee_structure ".accounts$Sub.result.quantity"] $NewSub; accountInfoSet ".result.amount" [::sargs::get $_employee_structure ".accounts$Sub.result.amount"] $NewSub; } else { ::set Count 0; ::set FinalAllocation [::expr {[::llength $_allocation_partitions]-1}]; ::set AllocationSum 0.0; ::foreach Partition $_allocation_partitions { ::set NewSub [append_account_structure]; accountInfoSet ".result.description" "$HyphenName Wage Allocation" $NewSub; accountInfoSet ".account.address" [::lindex $Partition 0] $NewSub; ::if {$Count==$FinalAllocation} { ::set PNumber [::qw::number::subtract [::sargs::get $_employee_structure ".accounts$Sub.result.amount"] $AllocationSum]; } else { ::set Allocation [::expr {$_TAmount==0.0?0.0:[::qw::number::divide [::lindex $Partition 2] $_TAmount]}]; ::set PNumber [round2 [::qw::number::multiply [::sargs::get $_employee_structure ".accounts$Sub.result.amount"] $Allocation]]; ::qw::number::var::add AllocationSum $PNumber; } accountInfoSet ".result.amount" $PNumber $NewSub; ::incr Count; } } ::set NewSub [append_account_structure]; accountInfoSet ".result.description" "$HyphenName Wage Allocation" $NewSub; accountInfoSet ".account.address" $EqualAccount $NewSub; accountInfoSet ".result.amount" [::qw::number::negative [::sargs::get $_employee_structure ".accounts$Sub.result.amount"]] $NewSub; } ::return $this; } public method record_employer_contributions {} { ~AYRUN.U2; ;#// User exit routine ::return $this; } method codeValidate {Src List Default} { ::if {[::lsearch -exact $List $Src]>=0} {::return $Src;} ::if {$Default eq ""} {::return [::lindex $List 0];} ::if {[::lsearch -exact $List $Default]<0} { ::qw::bug "907020050401053429" "Invalid default arg \"$Default\", default must be one of $List"; } ::return $Default; } public method ~AYRUN.15 {} { ::set ProcName "~AYRUN.15"; ::set RegAcct [recRead "PROCN" $ProcName "0"]; ::set BegDate [recRead "PROCN" $ProcName "1"]; ::set EndDate [recRead "PROCN" $ProcName "2"]; ::for {::set i 3} {$i<=17} {::incr i} { ::recWrite "" "PROCN" $ProcName $i; } ::array set Args {-Account "" -Code "" -BegDate $BegDate -EndDate $EndDate -ProcName $ProcName}; ::foreach Item $_employeeAccountList { ::unset -nocomplain PayCodes; ::set Account $Item(-account); ::array set PayCodes [::string toupper $Item(-paycodes)]; ::if {[::info exists PayCodes(.type)]} { ::set Args(-Account) $Account; ::if {[$Account normal_balance_get] eq "debit"} { ::if {$PayCodes(.type) eq "VACATIONPAID"} { ::set Args(-Code) "P"; ~AYRUN.15.1 [::array get Args]; } else { ::if {$PayCodes(.type) eq "VACATIONEARNED"} { ::set Args(-Code) "E"; ~AYRUN.15.1 [::array get Args]; } } } else { ::if {$PayCodes(.type) eq "VACATIONACCRUED"} { ::set Args(-Code) "W"; ~AYRUN.15.1 [::array get Args]; } } } } ::set Amount1 [recRead "PROCN" $ProcName "4"]; # Paid amount ::set Amount2 [recRead "PROCN" $ProcName "5"]; # Withheld amount ::set Amount3 0; ::if {$Amount2>0} {::set Amount3 [::expr $Amount2-$Amount1];} recWrite $Amount3 "PROCN" $ProcName "6"; ::set Amount1 [recRead "PROCN" $ProcName "8"]; # Paid amount ::set Amount2 [recRead "PROCN" $ProcName "9"]; # Withheld amount ::set Amount3 0; ::if {$Amount2>0} {::set Amount3 [::expr $Amount2-$Amount1];} recWrite $Amount3 "PROCN" $ProcName "10"; ::set Amount1 [recRead "PROCN" $ProcName "12"]; # Paid amount ::set Amount2 [recRead "PROCN" $ProcName "13"]; # Withheld amount ::set Amount3 0; ::if {$Amount2>0} {::set Amount3 [::expr $Amount2-$Amount1];} recWrite $Amount3 "PROCN" $ProcName "14"; } public method ~AYRUN.15.1 {args} { ::array set Args $args ::set Account $Args(-Account); ::set BegDate $Args(-BegDate); ::set EndDate $Args(-EndDate); ::set Code $Args(-Code); ::set Amount1 [history $Account "" $EndDate ".amount"]; ::set Amount2 [history $Account "" $Tmp1 ".amount"]; ::set Amount3 [history $Account $BegDate $EndDate ".amount"]; ::switch $Code { "E" {::set Tmp2 "3";} "P" {::set Tmp2 "4";} "W" {::set Tmp2 "5";} } recWrite $Account "PROCN" $ProcName [::expr $Tmp2+12]; ::set Tmp1 [recRead "PROCN" $ProcName $Tmp2]; ::set Tmp1 [::expr $Tmp1+$Amount1]; recWrite $Tmp1 "PROCN" $ProcName $Tmp2; ::incr Tmp2 4; ::set Tmp1 [recRead "PROCN" $ProcName $Tmp2]; ::set Tmp1 [::expr $Tmp1+$Amount2]; recWrite $Tmp1 "PROCN" $ProcName $Tmp2; ::incr Tmp2 4; ::set Tmp2 [recRead "PROCN" $ProcName $Tmp2]; ::set Tmp1 [::expr $Tmp1+$Amount3]; recWrite $Tmp1 "PROCN" $ProcName $Tmp2; } public method ~AYRUN.U1 {Src} { ::set Src [searchReplace $Src "@D" [payCodeValueGet ".quantity"]]; ::set Src [searchReplace $Src "@T" [payCodeValueGet ".quantity"]]; ::set Rate [payCodeValueGet ".rate"]; ::if {$Rate ne ""} { ::set Rate [::string trim [::format %10.2f $Rate]]; } ::set Src [searchReplace $Src "@R" $Rate]; ::set Src [searchReplace $Src "@Y" [::format %10.2f [accountInfoGet ".amount/year_to_date"]]]; ::set Src [searchReplace $Src "@P" [::format %10.2f [::expr [accountInfoGet ".amount/perpetual"]+[accountInfoGet ".result.amount"]]]]; ::if {[::string first "@B" $Src]>=0} { ::set Src [searchReplace $Src "@B" [::format %.2f [accountInfoGet ".result.percentage_base"]]]; ::set Src [searchReplace $Src "@%" [::format %.2f [accountInfoGet ".result.percent"]]]; } ::return $Src; } public method ~AYRUN.U2 {args} { } public method searchReplace {Src Search Replace} { ::set Index [::string first $Search $Src]; ::if {$Index==-1} {::return $Src;} ::set Last [::expr $Index+[::string length $Search]-1]; ::return [::string replace $Src $Index $Last $Replace]; } public method ~AYRUN.U5 {args} { } public method employeePayChecksByDate {s_args} { ::qw::payrun::debug_puts "employeePayChecksByDate $s_args"; ::set Range [::qw::odb::factory range]; $Range cpp_configure -index [[$_employee ".paychecks"] ".index/date"] \ -begin [::list .tag financial .date [::sargs::get $s_args ".begin"]] \ -end [::list .tag financial .date [::sargs::get $s_args ".end"]] \ ; ::set Result [$Range odb_masters]; $Range cpp_destroy; ::qw::payrun::debug_puts "employeePayChecksByDate Result==$Result"; ::return $Result; } public method employeeDeductionEarningsByDate {s_args} { ::qw::payrun::debug_puts "employeeDeductionEarningsByDate $s_args"; ::if {![::sargs::exists $s_args ".begin"]} {::sargs::var::set s_args ".begin" $_yearBeginDate;} ::if {![::sargs::exists $s_args ".end"]} {::sargs::var::set s_args ".end" $_yearEndDate;} ::set Checks [employeePayChecksByDate $s_args]; ::set Result 0.0; ::set Type [::sargs::get $s_args ".type"]; ::foreach Check $Checks { ::set Result [::expr $Result+[[$Check $Type] odb_get]]; } ::qw::payrun::debug_puts "employeeDeductionEarningsByDate Result==$Result"; ::return $Result; } public method employeePayChecksByPayPeriod_double_tag_bug {s_args} { ::qw::payrun::debug_puts "employeePayChecksByPayPeriod $s_args"; ::if {![::sargs::exists $s_args ".year"]} {::qw::bug "907020040602110823 employeePayChecksByPayPeriod called with missing arg .year";} ::if {![::sargs::exists $s_args ".period"]} {::qw::bug "907020040602110824 employeePayChecksByPayPeriod called with missing arg .period";} ::set Result ""; ::set Year [::sargs::get $s_args ".year"]; ::set Period [::sargs::get $s_args ".period"]; ::set Index [[$_employee ".paychecks"] ".index/date"]; ::for {::set Ref [$Index odb_first];} {$Ref ne ""} {::set Ref [$Index odb_next $Ref];} { ::set Item [$Ref odb_master]; ::set Payrun [[[$Item ".payrun"] odb_get] odb_master]; ::set PayPeriodYear [[$Payrun ".pay_period_year"] odb_get]; ::if {$PayPeriodYear<$Year} {::continue;} ::if {$PayPeriodYear>$Year} {::break;} ::set PayPeriodNumber [[$Payrun ".pay_period_number"] odb_get]; ::if {$PayPeriodNumber<$Period} {::continue;} ::if {$PayPeriodNumber>$Period} {::break;} ::lappend Result $Item; } ::qw::payrun::debug_puts "employeePayChecksByPayPeriod Result==$Result"; ::return $Result; } public method employeePayChecksByPayPeriod_double_tag_fix {s_args} { ::set StopWatch [::itcl::local ::QW::STOPWATCH #auto]; ::qw::payrun::debug_puts "employeePayChecksByPayPeriod $s_args"; ::if {![::sargs::exists $s_args ".year"]} {::qw::bug "907020040602110823 employeePayChecksByPayPeriod called with missing arg .year";} ::if {![::sargs::exists $s_args ".period"]} {::qw::bug "907020040602110824 employeePayChecksByPayPeriod called with missing arg .period";} ::set Result [::list]; ::set Year [::sargs::get $s_args ".year"]; ::set Period [::sargs::get $s_args ".period"]; ::set Range [::qw::odb::factory range]; ::qw::finally [::list $Range cpp_destroy]; $Range cpp_configure \ -index [$_employee .paychecks.index/date] \ -begin ".tag financial" \ -end ".tag financial" \ ; ::set Count 0; ::set References [$Range odb_references ".order_is_kept 1"]; ::for {::set Pos [::expr {[::llength $References]-1}];} {$Pos>=0} {::set Pos [::expr {$Pos-1}];} { ::set Item [[::lindex $References $Pos] odb_master]; ::set Payrun [[[$Item ".payrun"] odb_get] odb_master]; ::set PayPeriodYear [[$Payrun ".pay_period_year"] odb_get]; ::if {$PayPeriodYear<$Year} {::break;} ::if {$PayPeriodYear>$Year} {::continue;} ::set PayPeriodNumber [[$Payrun ".pay_period_number"] odb_get]; ::if {$PayPeriodNumber<$Period} {::break;} ::if {$PayPeriodNumber>$Period} {::continue;} ::lappend Result $Item; } ::return $Result; } public method employeePayChecksByPayPeriod {s_args} { ::set Debug [employeePayChecksByPayPeriod_double_tag_fix $s_args]; ::return $Debug; ::qw::payrun::debug_puts "employeePayChecksByPayPeriod $s_args"; ::if {![::sargs::exists $s_args ".year"]} {::qw::bug "907020040602110823 employeePayChecksByPayPeriod called with missing arg .year";} ::if {![::sargs::exists $s_args ".period"]} {::qw::bug "907020040602110824 employeePayChecksByPayPeriod called with missing arg .period";} ::set Result ""; ::set Year [::sargs::get $s_args ".year"]; ::set Period [::sargs::get $s_args ".period"]; ::set ObjectId [$_employee odb_object_id]; ::set ClassPath [$_employee odb_class_path]; ::set ReferenceList [[$_employee odb_database] cpp_file_odb_references \ .path /odb/index$ClassPath.paychecks.index/date \ .range.begin [::list string $ObjectId tag XXXfinancial] \ .range.end [::list string $ObjectId tag XXXfinancial] \ .order_is_kept 1 \ ]; ::foreach Ref $ReferenceList { ::set Item [$Ref odb_master]; ::set Payrun [[[$Item ".payrun"] odb_get] odb_master]; ::set PayPeriodYear [[$Payrun ".pay_period_year"] odb_get]; ::if {$PayPeriodYear<$Year} { ::continue; } ::if {$PayPeriodYear>$Year} { ::break; } ::set PayPeriodNumber [[$Payrun ".pay_period_number"] odb_get]; ::if {$PayPeriodNumber<$Period} { ::continue; } ::if {$PayPeriodNumber>$Period} { ::break; } ::lappend Result $Item; } ::qw::payrun::debug_puts "employeePayChecksByPayPeriod Result==$Result"; ::return $Result; } public method accountTotalByPayPeriod {s_args} { ::if {![::sargs::exists $s_args ".year"]} {::sargs::var::set s_args ".year" $_ppYear;} ::if {![::sargs::exists $s_args ".period"]} {::sargs::var::set s_args ".period" $_ppNumber;} ::if {[::sargs::get $s_args ".year"]!=$_ppYear||[::sargs::get $s_args ".period"]!=$_ppNumber} { ::set Checks [employeePayChecksByPayPeriod $s_args]; } else { ::set Checks $_employeePayChecksInPayPeriod; } ::set Result 0.0; ::set Account [::sargs::get $s_args ".account"]; ::set Range [::qw::odb::factory range]; ::qw::finally [::list $Range cpp_destroy]; ::foreach Check $Checks { ::set Index [[$Check ".odb_deriveds"] odb_primary]; $Range cpp_configure -index $Index; ::set References [$Range odb_references ".order_is_kept 1"]; ::foreach Ref $References { ::set Posting [$Ref odb_master]; ::foreach Sign {debit credit} { ::if {[[$Posting .posting/$Sign.account] odb_get] eq ""} { ::continue; } ::if {[[[$Posting .posting/$Sign.account] odb_get] odb_master] eq $Account} { ::set Result [::qw::number::add $Result [[$Posting .posting/$Sign.amount] odb_get]]; ::break; } } } } ::if {[$Account normal_balance_get] eq "credit"} {::qw::number::var::negative Result;} ::return $Result; } public method employeeDeductionEarningsPayPeriod {s_args} { ::qw::payrun::debug_puts "employeeDeductionEarningsByPayPeriod s_args==[::sargs::format .structure $s_args]"; ::if {![::sargs::exists $s_args ".year"]} {::sargs::var::set s_args ".year" $_ppYear;} ::if {![::sargs::exists $s_args ".period"]} {::sargs::var::set s_args ".period" $_ppNumber;} ::if {[::sargs::get $s_args ".year"]!=$_ppYear||[::sargs::get $s_args ".period"]!=$_ppNumber} { ::set Checks [employeePayChecksByPayPeriod $s_args]; } else { ::set Checks $_employeePayChecksInPayPeriod; } ::set Result 0.0; ::foreach Check $Checks { ::set Result [::expr $Result+[[$Check [::sargs::get $s_args ".type"]] odb_get]]; } ::qw::payrun::debug_puts "employeeDeductionEarningsPayPeriod Result==$Result"; ::return $Result; } public method employeeInfoSet {Name Value} { ::sargs::var::set _employee_structure $Name $Value; ::return $this; } method employeeInfoGetDump {} { } public method employeeInfoGet {Name} { ::return [::sargs::get $_employee_structure $Name]; } public method employeeInfoGetNumber {Name} { ::set Result [employeeInfoGet $Name]; ::if {$Result eq ""} {::return 0;} ::if {![::string is double $Result]} {::return 0;} ::return $Result; } public method employeeInfoGetBoolean {Name} { ::set Result [employeeInfoGet $Name]; ::set Result [::string trim $Result]; ::if {$Result eq ""} {::return 0;} ::if {![::string is boolean $Result]} {::set Result 0;} ::if {$Result} {::return 1;} ::return 0; } public method employeeInfoIncrement {Name Value} { ::set Amount [employeeInfoGet $Name]; ::set Amount [::expr $Amount+$Value]; employeeInfoSet $Name $Value; } public method accountInfoSet {args} { ::set Name [::lindex $args 0]; ::set Value [::lindex $args 1]; ::set Sub [::lindex $args 2]; ::if {$Sub eq ""} {::set Sub [employeeInfoGet ".current_sub"];} ::set AccountInfo [employeeInfoGet ".accounts/$Sub"]; ::sargs::var::set AccountInfo $Name $Value; employeeInfoSet ".accounts/$Sub" $AccountInfo; ::return $this; } public method accountInfoGet {args} { ::set Name [::lindex $args 0]; ::set Sub [::lindex $args 1]; ::if {$Sub eq ""} { ::set Sub [employeeInfoGet ".current_sub"]; } ::set AccountInfo [employeeInfoGet ".accounts/$Sub"]; ::return [::sargs::get $AccountInfo $Name]; } public method payCodeValueSet {Name Value {Sub {}}} { ::qw::payrun::debug_puts "payCodeValueSet Name==$Name Value==$Value Sub==$Sub"; ::if {$Sub eq ""} { ::set Sub [employeeInfoGet ".current_sub"]; } ::set PayCodes [employeeInfoGet ".accounts/$Sub.account.pay_codes"]; ::sargs::var::set PayCodes $Name $Value; employeeInfoSet ".accounts/$Sub.account.pay_codes" $PayCodes; ::return $this; } public method payCodeValueGet {args} { ::set Name [::lindex $args 0]; ::set Sub [::lindex $args 1]; ::if {$Sub eq ""} { ::set Sub [employeeInfoGet ".current_sub"]; } ::set PayCodes [employeeInfoGet ".accounts/$Sub.account.pay_codes"]; ::return [::sargs::get $PayCodes $Name]; } public method payCodeValueUcase {args} { ::return [::string toupper [::eval payCodeValueGet $args]]; } public method payCodeValueNumber {args} { ::set Result [::eval payCodeValueGet $args]; ::if {$Result eq ""} {::return 0;} ::if {![::string is double $Result]} {::return 0;} ::return $Result; } public method payCodeValueBoolean {args} { ::set Result [::eval payCodeValueGet $args]; ::set Result [::string trim $Result]; ::if {$Result eq ""} {::return 0;} ::if {$Result} {::return 1;} ::return 0; } public method payCodeExists {args} { ::set Name [::lindex $args 0]; ::set Sub [::lindex $args 2]; ::if {$Sub eq ""} {::set Sub [employeeInfoGet ".current_sub"];} ::set PayCodes [employeeInfoGet ".accounts/$Sub.account.pay_codes"]; ::return [::sargs::exists $PayCodes $Name]; } public method earningsSubjectTo {Src} { ::set Result 0.0; ::for {::set Sub 1} {$Sub<=[employeeInfoGet ".number_of_accounts"]} {::incr Sub;} { ::if {![payCodeValueBoolean $Src $Sub]} {::continue;} ::set Amount [accountInfoGet ".result.amount" $Sub]; ::if {[accountInfoGet ".account.normal_balance" $Sub] eq "credit"} {::set Amount [::expr 0.0-$Amount];} ::set Result [::expr $Result+$Amount]; } ::qw::payrun::debug_puts "earningsSubjectTo $Src Result==$Result"; ::return $Result; } public method earningsOfType {Src args} { ::array set Args $args; ::set AmountType ".result.amount"; ::if {[::info exists Args(-amount)]} {::set AmountType $Args(-amount);} ::set Result 0.0; ::for {::set Sub 1} {$Sub<=[employeeInfoGet ".number_of_accounts"]} {::incr Sub;} { ::if {[payCodeValueGet ".type" $Sub] ne $Src} {::continue;} ::set Amount [accountInfoGet $AmountType $Sub]; ::if {$Amount==0.0} {::continue;} ::if {[accountInfoGet ".account.normal_balance" $Sub] eq "credit"} {::set Amount [::expr 0.0-$Amount];} ::set Result [::expr $Result+$Amount]; } ::return $Result; } public method earningsOfTypeXSubjectToY {Type SubjectTo} { ::set Result 0.0; ::for {::set Sub 1} {$Sub<=[employeeInfoGet ".number_of_accounts"]} {::incr Sub;} { ::if {[payCodeValueGet ".type" $Sub] ne $Type} {::continue;} ::if {![payCodeValueBoolean $SubjectTo $Sub]} {::continue;} ::set Amount [accountInfoGet ".result.amount" $Sub]; ::if {$Amount==0.0} {::continue;} ::if {[accountInfoGet ".account.normal_balance" $Sub] eq "credit"} {::set Amount [::expr 0.0-$Amount];} ::set Result [::expr $Result+$Amount]; } ::return $Result; } public method accountsOfTypeXSubjectToY {s_args} { ::set Type [::sargs::get $s_args ".type"]; ::set SubjectTo [::sargs::get $s_args ".subject_to"]; ::set NormalBalance [::sargs::get $s_args ".normal_balance"]; ::set Result ""; ::for {::set Sub 1} {$Sub<=[employeeInfoGet ".number_of_accounts"]} {::incr Sub;} { ::if {$NormalBalance ne ""} { ::if {[accountInfoGet ".account.normal_balance" $Sub] ne $NormalBalance} {::continue;} } ::if {[payCodeValueGet ".type" $Sub] ne $Type} {::continue;} ::if {![payCodeValueBoolean $SubjectTo $Sub]} {::continue;} ::lappend Result $Sub; } ::qw::payrun::debug_puts "accountsOfTypeXSubjectToY $Type $SubjectTo Result==$Result"; ::return $Result; } public method accountsOfTypeX {Type} { ::set Result ""; ::for {::set Sub 1} {$Sub<=[employeeInfoGet ".number_of_accounts"]} {::incr Sub;} { ::if {[payCodeValueGet ".type" $Sub] ne $Type} {::continue;} ::lappend Result $Sub; } ::return $Result; } public method accountsEarningsTotal {AccountSubs Period} { ::qw::payrun::debug_puts "accountsEarningsTotal $AccountSubs $Period"; ::set Result 0.0; ::foreach Sub $AccountSubs { ::switch $Period { "perpetual" {::set Amount [accountInfoGet ".amount/perpetual" $Sub];} "pay_period_to_date" {::set Amount [accountInfoGet ".amount/pay_period_to_date" $Sub];} "year_to_date" {::set Amount [accountInfoGet ".amount/year_to_date" $Sub];} "month_to_date" {::set Amount [accountInfoGet ".amount/month_to_date" $Sub];} "now" {::set Amount [accountInfoGet ".result.amount" $Sub];} default {::qw::bug "907020050401053513" "Invalid Period specifier \"$Period\" to accountEarningsTotal method.";} } ::qw::payrun::debug_puts "\t[accountInfoGet .account.name $Sub] Amount==$Amount"; ::if {$Amount==0.0} { ::continue; } ::if {[accountInfoGet ".account.normal_balance" $Sub] eq "credit"} { ::set Amount [::expr 0.0-$Amount]; } ::set Result [::expr $Result+$Amount]; ::qw::payrun::debug_puts "accountsEarningsTotal Amount==$Amount Result==$Result"; } ::qw::payrun::debug_puts "accountsEarningsTotal Result===$Result"; ::return $Result; } public method append_account_structure {} { ::set Sub [employeeInfoGet ".number_of_accounts"] ::incr Sub; ::set AccountStructure [new_account_structure]; ::sargs::var::set AccountStructure ".sub" $Sub; employeeInfoSet ".accounts/$Sub" $AccountStructure; employeeInfoSet ".number_of_accounts" $Sub; employeeInfoSet ".current_sub" $Sub; ::return $Sub; } public method new_account_structure {} { ::return { .sub {} .account { .address {} .name {} .normal_balance {} .odb_address {} .suffix {} .description {} .pay_codes {} } .amount { /perpetual 0.0 /year_to_date 0.0 /month_to_date 0.0 /pay_period_to_date 0.0 } .result { .rate {} .amount 0.0 .quantity 0.0 .description {} } } } public method employee_fields {} { ::return [::concat [employee_fields_country] { .accrued_wages_account .employee_id .name .date_of_birth .first_day_worked .last_day_worked .marital_status .employee_name.print_as .minimum_check_amount .maximum_check_amount }]; } public method employee_fields_country {} { ::return ""; } public method build_test_employee_structure {} { ::set _employee_structure ""; ::foreach FieldName [employee_fields] {employeeInfoSet $FieldName "";} employeeInfoSet ".number_of_accounts" 0; ::sargs::var::set _employee_structure ".accounts" {}; employeeInfoSet ".net_pay" 0.0; employeeInfoSet ".current_sub" 0; build_employee_structure_country; normalize_employee_structure_country; } public method test_employee_add_account {s_args} { ::set Sub [append_account_structure]; accountInfoSet ".account.name" [::sargs::get $s_args ".name"]; accountInfoSet ".account.normal_balance" [::sargs::get $s_args ".normal_balance"]; accountInfoSet ".account.suffix" [::lindex [splitAccountName [::sargs::get $s_args ".name"]] 2]; accountInfoSet ".account.description" [::sargs::get $s_args ".description"]; ::if {[accountInfoGet ".account.normal_balance"] eq "debit"} {::set Sign 1;} else {::set Sign -1;} ::foreach Period { perpetual year_to_date pay_period_to_date month_to_date } { ::set Amount [::sargs::get $s_args ".amount/$Period"]; ::if {$Amount eq ""} {::set Amount 0.0;} accountInfoSet ".amount/$Period" [::expr $Amount*$Sign]; } accountInfoSet ".result.amount" 0.0; accountInfoSet ".result.quantity" 0; accountInfoSet ".result.rate" ""; accountInfoSet ".result.description" ""; accountInfoSet ".account.pay_codes" [::sargs::get $s_args ".paycodes"]; } public method build_employee_structure {Employee PayList} { ::set _employee_structure ""; ::foreach FieldName [employee_fields] { employeeInfoSet $FieldName [[$Employee $FieldName] odb_get]; } ::if {$_table(employees-processed)} {summary "";} summary [employeeInfoGet ".employee_name.print_as"] title; status [employeeInfoGet ".employee_name.print_as"]; employeeInfoSet ".number_of_accounts" 0; ::sargs::var::set _employee_structure ".accounts" {}; ::set Masters [[[$Employee ".accounts"] ".index/interactive"] odb_masters ".order_is_kept 1"]; ::foreach Account $Masters { ::if {[::string first "/OBJECT/NEWVIEWS/ACCOUNT/PAYROLL" [$Account odb_path]]!=0} { ::continue; } ::if {$::qw::control(accrual_payroll)} { ::if {[::lindex [splitAccountName [[$Account ".name"] odb_get]] 1] eq "="} { ::continue; } } ::if {[[$Account ".total.kids"] odb_items]!=0} {::continue;} ::if {[::string tolower [[$Account ".active"] odb_get]] ne "active"} {::continue;} ::set NormalBalance [$Account normal_balance_get]; ::if {[[$Account ".name"] odb_get] eq ""} {::continue;} ::if {$NormalBalance eq ""} {::continue;} ::set PayCodes ""; ::foreach {Name Value} [::sargs::get [[$Account ".paycodes"] odb_get] "/$NormalBalance"] { ::sargs::var::set PayCodes $Name $Value; } ::foreach PaySub [::sargs::subs .structure $PayList] { ::if {[::sargs::get $PayList $PaySub.odb_address] ne [$Account odb_address]} { ::continue; } ::if {$::qw::control(accrual_payroll)} {} ::foreach Name {"quantity" "rate" "insurable_hours" "quantity_is_from_timecard" "rate_timecard" "amount_timecard"} { ::if {![::sargs::exists $PayList $PaySub.$Name]} { ::continue; } ::sargs::var::set PayCodes ".$Name" [::sargs::get $PayList $PaySub.$Name]; } ::break; } ::set Type [::sargs::get $PayCodes ".type"]; ::set Sub [append_account_structure]; accountInfoSet ".account.address" [$Account odb_address]; accountInfoSet ".account.name" [[$Account ".name"] odb_get]; accountInfoSet ".account.odb_address" [$Account odb_address]; accountInfoSet ".account.normal_balance" $NormalBalance; accountInfoSet ".account.suffix" [::lindex [splitAccountName [[$Account ".name"] odb_get]] 2]; accountInfoSet ".account.description" [[$Account ".description"] odb_get]; ::if {[accountInfoGet ".account.normal_balance"] eq "debit"} {::set Sign 1;} else {::set Sign -1;} accountInfoSet ".amount/perpetual" [::expr [history $Account "" "" ".amount"]*$Sign]; accountInfoSet ".amount/year_to_date" [::expr [history $Account $_yearBeginDate $_yearEndDate ".amount"]*$Sign]; accountInfoSet ".amount/pay_period_to_date" [accountTotalByPayPeriod [::sargs ".account" $Account]]; ::set MonthBeginDate [::qw::date::set $_ppEndDate day 1]; ::set MonthEndDate [::qw::date::set $_ppEndDate day [::qw::date::get $_ppEndDate "days_in_month"]]; accountInfoSet ".amount/month_to_date" [::expr [history $Account $MonthBeginDate $MonthEndDate ".amount"]*$Sign]; accountInfoSet ".result.amount" 0.0; accountInfoSet ".result.quantity" 0.0; accountInfoSet ".result.rate" ""; accountInfoSet ".result.description" ""; ::if {$::qw::control(accrual_payroll)} { accountInfoSet ".result.quantity_is_from_timecard" 0.0; accountInfoSet ".result.rate_timecard" ""; accountInfoSet ".result.amount_timecard" 0.0; } ::if {$Type ne ""} { ::sargs::var::set PayCodes ".type" [$Account type_description_to_name $Type]; } accountInfoSet ".account.pay_codes" $PayCodes; accountInfoSet ".set_paycodes" ""; } employeeInfoSet ".net_pay" 0.0; employeeInfoSet ".current_sub" 0; ::if {$::qw::control(accrual_payroll)} { employeeInfoSet ".allocated_earnings" 0.0; employeeInfoSet ".unallocated_earnings" 0.0; } build_employee_structure_country; normalize_employee_structure_country; ::return $this; } public method build_employee_structure_country {} { ::return $this; } public method normalize_employee_structure_country {} { ::return $this; } public method percentage_base {s_args} { ::set Period [::sargs::get $s_args ".period"]; ::if {$Period eq ""} {::set Period "now";} ::set Expression [::sargs::get $s_args ".expression"]; ::if {$Expression eq ""} {::return 0.0;} ::set Expression [::string map {" " ""} $Expression]; ::set Expression [::string map {+ " + " - " - " * " * " / " / " ( " ( " ) " ) "} $Expression]; ::for {::set Sub 1} {$Sub<[employeeInfoGet ".current_sub"]} {::incr Sub;} { ::set Suffix [accountInfoGet ".account.suffix" $Sub]; ::for {::set i 0;} {$i<[::llength $Expression]} {::incr i} { ::set Term [::lindex $Expression $i]; ::if {[::string first $Term "+-*/()"]>=0} {::continue;} ::if {$Suffix ne $Term&&"${Suffix}.Q" ne $Term} {::continue;} ::set ValueType ".amount"; ::if {[::string first ".Q" $Term]>0} { ::set ValueType ".quantity"; } ::switch $Period { "perpetual" {::set Amount [accountInfoGet "$ValueType/perpetual" $Sub];} "pay_period_to_date" {::set Amount [accountInfoGet "$ValueType/pay_period_to_date" $Sub];} "year_to_date" {::set Amount [accountInfoGet "$ValueType/year_to_date" $Sub];} "month_to_date" {::set Amount [accountInfoGet "$ValueType/month_to_date" $Sub];} "now" {::set Amount [accountInfoGet ".result$ValueType" $Sub];} default {::qw::bug "907020050401053536" "Invalid Period specifier \"$Period\" in call to percentage_base method.";} } ::set Expression [::lreplace $Expression $i $i $Amount]; } } ::for {::set i 0;} {$i<[::llength $Expression]} {::incr i} { ::set Term [::lindex $Expression $i]; ::if {[::string first $Term "+-*/()"]>=0} {::continue;} ::if {[::string is double $Term]} {::continue;} ::if {$Term eq "NET"} { ::set Expression [::lreplace $Expression $i $i [employeeInfoGet ".net_pay"]]; } else { ::set Expression [::lreplace $Expression $i $i 0.0]; } } debugLog "Percentage base expression: $Expression"; ::if {[::catch {::set Result [::expr $Expression]} Error]} { ::set Result 0.0 accountInfoSet ".warning" "Error in percentage base \"$Expression\""; debugLog "Error in percentage base: \"$Error\""; } ::return $Result; } public method history {Account Begin End Type} { ::if {$Type ne ".amount"} { puts_rth "history method can't handle Type \"$Type\" yet."; ::return 0; } ::set Index [$Account ".postings.index/date"]; ::set Range [::qw::odb::factory range]; ::qw::finally [::list $Range cpp_destroy]; ::set RangeBegin ".tag financial"; ::if {$Begin ne ""} { ::append RangeBegin " .date [::qw::date::extend_begin $Begin]"; } ::set RangeEnd ".tag financial"; ::if {$End ne ""} { ::append RangeEnd " .date [::qw::date::extend_end $End]"; } $Range cpp_configure -index $Index -begin $RangeBegin -end $RangeEnd; ::return [[$Range odb_master] history_file_odb_total [::sargs .range $Range .rb_name $Type .priority foreground]]; } public method recRead {Type Name Record} { ::if {![::info exists _records($Type-$Name-$Record)]} {::return "";} ::return $_records($Type-$Name-$Record); } public method recWrite {Value Type Name Record} { ::set _records($Type-$Name-$Record) $Value; ::if {[recRead $Type $Name $Record] ne $Value} {::error "read ne write";} ::return $this; } public method padRight {Src Length Char} { ::if {[::string length $Src]==$Length} {::return $Src;} ::if {[::string length $Src]>$Length} {::return [::string range $Src 0 [::expr $Length - 1]];} ::return $Src[::string repeat $Char [::expr $Length - [::string length $Src]]]; } public method padLeft {Src Length Char} { ::if {[::string length $Src]==$Length} {::return $Src;} ::if {[::string length $Src]>$Length} {::return [::string range $Src [::expr [::string length $Src]-$Length] end];} ::return [::string repeat $Char [::expr $Length - [::string length $Src]]]$Src; } method splitAccountName {Src} { ::set Position -1; ::foreach Char {"." "-" "~" "="} { ::set i [::string last $Char $Src]; ::if {$i<$Position} {::continue;} ::set Position $i; ::set Separator $Char; } ::if {$Position<=0} {::return "";} ::if {$Position>=[::expr [::string length $Src]-1]} {::return "";} ::set Prefix [::string range $Src 0 [::expr $Position-1]]; ::set Suffix [::string range $Src [::expr $Position+1] end]; ::return [::list $Prefix $Separator $Suffix]; } public method stringToNumber {Src} { ::if {$Src==""} {::return 0;} ::if {[::string is double $Src]} {::return $Src;} ::return 0; } private variable _number_format { .decimal "." .group "" .group_size 0 .left { .text "" .minimum 1 .maximum -1 } .right { .text "" .minimum 0 .maximum -1 } /null { } /zero { } /positive { } /negative { .left { .text "-" } } } public method round {Src Digits} { ::return [::qw::number::format $Src [::sargs::set $_number_format ".right.maximum" $Digits]]; } public method round2 {Src} { ::if {$Src>-0.005&&$Src<0.005} {::set Src 0.0;} ::return [round $Src 2]; } proc truncate {Src Decimals} { ::set M [::expr pow(10,$Decimals)]; ::return [::expr [::expr int([::expr $Src*$M])]/$M]; } public method truncate2 {Src} { ::return [truncate $Src 2]; } public method substr {SubString String Index} { ::return [::string replace $String $Index [::expr $Index+[::string length $SubString]-1] $SubString]; } } } ::if {$::qw::control(has_tk)} { itcl::class ::QW::NV2::EFT_PREVIEW { inherit itk::Toplevel; itk_option define -font font Font {-family Arial -size 11 -weight bold}; protected variable _payrunObject ""; protected variable _database ""; protected variable _status ""; protected variable _options ""; protected variable _table; protected variable _process_status ""; protected variable _afterId ""; protected variable _is_destroyed 0; protected variable _toplevel_title ""; protected variable _view "summary"; protected variable _manual_page_id ""; public method constructor {args} { ::array set Args $args; ::set _toplevel_title "Direct Deposit Preview"; ::set _payrunObject ""; ::set _afterId ""; ::qw::assert {[::info exists Args(-odb_object)]}; ::set _payrunObject $Args(-odb_object); ::unset Args(-odb_object); ::qw::assert {$_payrunObject ne ""}; ::set _database [$_payrunObject odb_database]; ::set _options [::sargs::+= $::qw::widget::default [::subst { /header {} /table {} /status {} /button {} }]]; ::if {[::info exists Args(-progress_description)]} { ::array set _table [::list paychecks-description $Args(-progress_description)]; ::unset Args(-progress_description); } else { ::array set _table [::list paychecks-description "Transactions"]; } ::if {[::info exists Args(-manual_page_id)]} { ::set _manual_page_id $Args(-manual_page_id); ::unset Args(-manual_page_id); } ::if {[::info exists Args(-title)]} { ::set _toplevel_title $Args(-title); ::unset Args(-title); } ::set _table(names) ""; ::lappend _table(names) "paychecks"; ::foreach Name $_table(names) { ::set _table($Name-processed) 0; ::set _table($Name-target) 0; } ::set _table(checks-posted) 0; ::set _error_list ""; ::set _warning_list ""; ::set _detail_list ""; ::set _view "summary"; ::eval display_startup [::array get Args]; ::set ::QW::NEWVIEWS::271820150126153715 1; } public method destructor {} { ::if {$_afterId ne ""} {::after cancel $_afterId;} ::unset -nocomplain ::QW::NEWVIEWS::271820150126153715; } public method help {} { ::qw::htmlhelp [::sargs .chm_path $::qw_manual_file .id "$_manual_page_id.htm"]; } public method option {Path} {::return [::sargs::get_poly $_options $Path];} public method options {Options} { ::set _options [::sargs::+= $_options $Options]; ::return $this; } public method tableNames {} {::return $_table(names);} public method copy_to_clipboard {{s_args ""}} { ::clipboard clear; ::if {$_view eq "detail"} { ::set Text [$itk_interior.details get 1.0 end]; } else { ::set Text [$itk_interior.summary get 1.0 end]; } ::clipboard append -displayof . -format STRING -type STRING -- $Text; } public method display_startup {args} { ::set LabelBorderWidth 0.5m; ::set ControlPadding 0.5m; ::set Me $itk_interior; ::qw::toplevel_add [::sargs .path $Me]; ::frame $Me.controls -height 2 -borderwidth 0.5m -relief sunken; ::button $Me.controls.action -borderwidth $ControlPadding -font [option /button.font]; ::button $Me.controls.abort -borderwidth $ControlPadding -font [option /button.font]; ::button $Me.controls.view -borderwidth $ControlPadding -font [option /button.font]; ::button $Me.controls.clipboard -text "Copy to Clipboard" -borderwidth $ControlPadding -command [::itcl::code $this copy_to_clipboard] -font [option /button.font]; ::button $Me.controls.help -text Help -borderwidth $ControlPadding -command [::itcl::code $this help] -font [option /button.font]; ::bind $Me.controls.action [::itcl::code $_payrunObject eft_file_create]; ::bind $Me.controls.abort [::itcl::code $this confirmAbort]; ::label $Me.status -textvariable [::itcl::scope _status] -relief sunken -borderwidth $LabelBorderWidth -anchor w -font [option /status.font]; ::frame $Me.table; ::pack $Me.table -expand 0 -fill both -padx 4 -pady 4; itk_component add details { ::iwidgets::scrolledtext $itk_interior.details -borderwidth $ControlPadding; } { usual } $Me.details configure -textfont {Courier 20 bold} -wrap none; $Me.details tag configure warning -foreground "dark orange" -font {Courier 10 bold}; $Me.details tag configure error -foreground red -font {Courier 10 bold}; $Me.details tag configure title -foreground black -font {Courier 10 bold underline}; $Me.details tag configure header -foreground black -font {Courier 10 bold}; $Me.details tag configure detail -foreground black -font {Courier 10}; itk_component add summary { ::iwidgets::scrolledtext $itk_interior.summary -borderwidth $ControlPadding; } { usual } $Me.summary configure -textfont {Courier 20 bold} -wrap none; $Me.summary tag configure warning -foreground "dark orange" -font {Courier 10 bold}; $Me.summary tag configure error -foreground red -font {Courier 10 bold}; $Me.summary tag configure title -foreground black -font {Courier 10 bold underline}; $Me.summary tag configure header -foreground black -font {Courier 10 bold}; $Me.summary tag configure detail -foreground black -font {Courier 10}; ::pack $Me.summary -fill both -expand true -padx 4 -pady 4; ::pack $Me.controls -expand no -fill x -padx $ControlPadding -pady $ControlPadding; ::pack $Me.controls.abort -side left -expand yes -fill x -padx $ControlPadding -pady $ControlPadding; ::pack $Me.controls.clipboard -side left -expand yes -fill x -padx $ControlPadding -pady $ControlPadding; ::pack $Me.controls.help -side left -expand yes -fill x -padx $ControlPadding -pady $ControlPadding; ::pack $Me.controls.view -side left -expand yes -fill x -padx $ControlPadding -pady $ControlPadding; ::pack $Me.status -fill x -padx 4 -pady 4; ::wm group $itk_component(hull) .; ::label $Me.table._titlelabel -text "Type" -font [option /header.font] -relief raised -borderwidth $LabelBorderWidth -width 22 -anchor c ::label $Me.table._titletarget -text "Count" -font [option /header.font] -relief raised -borderwidth $LabelBorderWidth -width 11 -anchor c ::label $Me.table._titleitems -text "Done" -font [option /header.font] -relief raised -borderwidth $LabelBorderWidth -width 11 -anchor c ::label $Me.table._titlecompletion -text "Percent Done" -font [option /header.font] -relief raised -borderwidth $LabelBorderWidth -width 30 -anchor c ::set Row 0; ::set Column 0; ::grid $Me.table._titlelabel -row $Row -column $Column -sticky ewns;::incr Column; ::grid $Me.table._titletarget -row $Row -column $Column -sticky ewns;::incr Column; ::grid $Me.table._titleitems -row $Row -column $Column -sticky ewns;::incr Column; ::grid $Me.table._titlecompletion -row $Row -column $Column -sticky ewns;::incr Column; ::incr Row; ::foreach Name [tableNames] { ::label $Me.table.${Name}label -text [::set [::itcl::scope _table($Name-description)]] -font [option /table.font] -relief sunken -borderwidth $LabelBorderWidth -width 22 -anchor e; ::label $Me.table.${Name}target -textvariable [::itcl::scope _table($Name-target)] -font [option /table.font] -relief sunken -borderwidth $LabelBorderWidth -width 11 -anchor e; ::label $Me.table.${Name}items -textvariable [::itcl::scope _table($Name-processed)] -font [option /table.font] -relief sunken -borderwidth $LabelBorderWidth -width 11 -anchor e; ::QW::WIDGET::COMPLETION_PERCENTAGE $Me.table.${Name}completion -limitvariable [::itcl::scope _table($Name-target)] -valuevariable [::itcl::scope _table($Name-processed)]; ::set Column 0; ::grid $Me.table.${Name}label -row $Row -column $Column -sticky ewns;::incr Column; ::grid $Me.table.${Name}target -row $Row -column $Column -sticky ewns;::incr Column; ::grid $Me.table.${Name}items -row $Row -column $Column -sticky ewns;::incr Column; ::grid $Me.table.${Name}completion -row $Row -column $Column -sticky ewns;::incr Column; ::grid rowconfigure $Me.table $Row -weight 1; ::incr Row; } ::grid columnconfigure $Me.table 0 -weight 1; ::grid columnconfigure $Me.table 1 -weight 1; ::grid columnconfigure $Me.table 2 -weight 1; ::grid columnconfigure $Me.table 3 -weight 1; $Me.controls.abort configure -text "Abort" -command [::itcl::code $this confirmAbort]; $Me.controls.view configure -text "Details" -command [::itcl::code $this switch_view]; configure -title $_toplevel_title; ::wm protocol $itk_component(hull) WM_DELETE_WINDOW [::itcl::code $this confirmAbort]; ::eval itk_initialize $args; ::eval [::itcl::code $this centerOnScreen]; ;#// no help, BUT with current fizbin order, we are centered in a topleft position sense, not a center of groavity ::return $this; } public method display_preview_accept_or_cancel {args} { ::set LabelBorderWidth 0.5m; ::set ControlPadding 0.5m; ::set Me $itk_interior; ::pack forget $Me.controls.abort; ::pack forget $Me.controls.clipboard; ::pack forget $Me.controls.help; ::pack forget $Me.controls.view; $Me.controls.action configure -text "Create File" -command [::itcl::code $_payrunObject eft_file_create]; ::pack $Me.controls.action -side left -expand yes -fill x -padx $ControlPadding -pady $ControlPadding; ::pack $Me.controls.abort -side left -expand yes -fill x -padx $ControlPadding -pady $ControlPadding; ::pack $Me.controls.clipboard -side left -expand yes -fill x -padx $ControlPadding -pady $ControlPadding; ::pack $Me.controls.help -side left -expand yes -fill x -padx $ControlPadding -pady $ControlPadding; ::pack $Me.controls.view -side left -expand yes -fill x -padx $ControlPadding -pady $ControlPadding; ::qw::after idle "::focus $Me.controls.action"; status "Ready to create Direct Deposit file(s)"; } public method display_preview_abort_only {args} { ::wm protocol $itk_component(hull) WM_DELETE_WINDOW [::itcl::code $this window_destroy]; ::set Me $itk_interior; ::pack forget $Me.controls.action; ::focus $Me.controls.abort; status ""; } public method switch_view {} { ::if {$_view eq "summary"} { ::pack forget $itk_interior.summary; ::pack $itk_interior.details -fill both -expand true -padx 4 -pady 4 -before $itk_interior.controls; $itk_interior.controls.view configure -text "Summary"; ::set _view "detail"; ::return; } ::pack forget $itk_interior.details; ::pack $itk_interior.summary -fill both -expand true -padx 4 -pady 4 -before $itk_interior.controls; $itk_interior.controls.view configure -text "Details"; ::set _view "summary"; } public method status {args} { ::switch -- [::llength $args] { 0 { QW::ASSERT::expr {0} ::return $_status; } 1 { ::set _status [::lindex $args 0]; ::update; ::return $this; } } ::qw::bug "907020050401052523" "Wrong number of args to status method."; } method increment {VarName {Increment 1}} { ::incr _table($VarName) $Increment; ::update; } public method details {Src {Tag {}}} { ::if {$Tag eq ""} { $itk_component(details) insert end "$Src\n"; } else { $itk_component(details) insert end "$Src\n" $Tag; } $itk_component(details) see end; } public method summary {Src {Tag {}}} { ::if {$Tag eq ""} { $itk_component(details) insert end "$Src\n"; $itk_component(summary) insert end "$Src\n"; } else { $itk_component(details) insert end "$Src\n" $Tag; $itk_component(summary) insert end "$Src\n" $Tag; } $itk_component(summary) see end; } public method payrun_error {Src} { summary $Src; ::lappend _error_list $Src; } public method window_destroy {} { ::if {$_process_status eq "aborted"} { ::return; } confirmAbort; ::if {$_process_status eq "aborted"} { ::set _is_destroyed 1; } } public method dialog_position {} { ::set Offset 50; ::set Geometry [::regsub -all \[^0-9\] [::winfo geometry $itk_component(hull)] " "]; ::set X [::lindex $Geometry 2]; ::set Y [::lindex $Geometry 3]; ::set Result ""; ::lappend Result [::expr $X+$Offset]; ::lappend Result $Y; ::lappend Result $Offset; ::lappend Result $Offset; ::return $Result; } public method confirmAbort {} { ::set BBox [::eval [::itcl::code $this dialog_position]]; ::set Result [::qw::dialog::confirm [::qw::list { .bbox $BBox .title "Abort Direct Deposit?" .text "Confirm that you want to abort Direct Deposit processing." /button { /ok { .text "Abort Processing" } /cancel { .text "Continue Processing" } } }]]; ::if {$Result} { status "Processing aborted." ::set _process_status "aborted"; terminate; } else { ::set _process_status "active"; } } protected method centerOnScreen {} { ::set _afterId ""; ::set xyPosition [::sargs .x 100 .y 100]; ::set Fwindow [::qw::winutil::find_window_with_focus]; ::if {$Fwindow ne ""} { ::set xyPosition [::QW::GUI::POINT::+ [[[$Fwindow nv_toplevel] .frame] positionInScreen] $xyPosition]; } ::wm geometry $itk_component(hull) +[::sargs::get $xyPosition .x]+[::sargs::get $xyPosition .y]; ::return $this; } public method target_set {Src} { ::set _table(paychecks-target) $Src; } public method terminate {} { ::if {!$_is_destroyed} {::qw::itcl_delete_object $this;} } } }