2012-09-13 12:08:26 +00:00
openerp . account = function ( instance ) {
2012-11-12 09:36:09 +00:00
openerp . account . quickadd ( instance ) ;
2012-09-13 12:08:26 +00:00
var _t = instance . web . _t ,
_lt = instance . web . _lt ;
2012-09-14 13:06:30 +00:00
var QWeb = instance . web . qweb ;
2012-09-13 16:09:48 +00:00
2012-11-12 09:36:09 +00:00
instance . web . account = instance . web . account || { } ;
2012-09-13 16:09:48 +00:00
2014-05-30 16:47:50 +00:00
instance . web . client _actions . add ( 'bank_statement_reconciliation_view' , 'instance.web.account.bankStatementReconciliation' ) ;
instance . web . account . bankStatementReconciliation = instance . web . Widget . extend ( {
className : 'oe_bank_statement_reconciliation' ,
2014-09-10 12:07:27 +00:00
events : {
"click .statement_name span" : "statementNameClickHandler" ,
"keyup .change_statement_name_field" : "changeStatementNameFieldHandler" ,
"click .change_statement_name_button" : "changeStatementButtonClickHandler" ,
2015-01-06 10:50:49 +00:00
"click .show_more" : "showMoreButtonClickHandler" ,
2014-09-10 12:07:27 +00:00
} ,
2014-05-30 16:47:50 +00:00
init : function ( parent , context ) {
this . _super ( parent ) ;
2015-01-06 10:50:49 +00:00
// Number of reconciliations loaded initially and by clicking 'show more'
this . num _reconciliations _fetched _in _batch = 10 ;
2014-09-04 09:32:16 +00:00
if ( context . context . statement _id ) this . statement _ids = [ context . context . statement _id ] ;
if ( context . context . statement _ids ) this . statement _ids = context . context . statement _ids ;
2014-09-11 10:46:56 +00:00
this . single _statement = this . statement _ids !== undefined && this . statement _ids . length === 1 ;
this . multiple _statements = this . statement _ids !== undefined && this . statement _ids . length > 1 ;
2014-05-30 16:47:50 +00:00
this . title = context . context . title || _t ( "Reconciliation" ) ;
this . st _lines = [ ] ;
this . last _displayed _reconciliation _index = undefined ; // Flow control
this . reconciled _lines = 0 ; // idem
this . already _reconciled _lines = 0 ; // Number of lines of the statement which were already reconciled
this . model _bank _statement = new instance . web . Model ( "account.bank.statement" ) ;
this . model _bank _statement _line = new instance . web . Model ( "account.bank.statement.line" ) ;
this . reconciliation _menu _id = false ; // Used to update the needaction badge
this . formatCurrency ; // Method that formats the currency ; loaded from the server
// Only for statistical purposes
this . lines _reconciled _with _ctrl _enter = 0 ;
this . time _widget _loaded = Date . now ( ) ;
// Stuff used by the children bankStatementReconciliationLine
2014-06-23 09:47:41 +00:00
this . max _move _lines _displayed = 5 ;
2014-05-30 16:47:50 +00:00
this . animation _speed = 100 ; // "Blocking" animations
this . aestetic _animation _speed = 300 ; // eye candy
2014-10-03 13:25:53 +00:00
this . map _currency _id _rounding = { } ;
2014-05-30 16:47:50 +00:00
this . map _tax _id _amount = { } ;
this . presets = { } ;
// We'll need to get the code of an account selected in a many2one (whose value is the id)
this . map _account _id _code = { } ;
// The same move line cannot be selected for multiple resolutions
2014-09-04 09:32:16 +00:00
this . excluded _move _lines _ids = { } ;
2014-05-30 16:47:50 +00:00
// Description of the fields to initialize in the "create new line" form
// NB : for presets to work correctly, a field id must be the same string as a preset field
this . create _form _fields = {
account _id : {
id : "account_id" ,
index : 0 ,
corresponding _property : "account_id" , // a account.move field name
label : _t ( "Account" ) ,
required : true ,
tabindex : 10 ,
constructor : instance . web . form . FieldMany2One ,
field _properties : {
relation : "account.account" ,
string : _t ( "Account" ) ,
type : "many2one" ,
2014-07-11 15:15:34 +00:00
domain : [ [ 'type' , 'not in' , [ 'view' , 'closed' , 'consolidation' ] ] ] ,
2014-05-30 16:47:50 +00:00
} ,
} ,
label : {
id : "label" ,
index : 1 ,
corresponding _property : "label" ,
label : _t ( "Label" ) ,
required : true ,
tabindex : 11 ,
constructor : instance . web . form . FieldChar ,
field _properties : {
string : _t ( "Label" ) ,
type : "char" ,
} ,
} ,
tax _id : {
id : "tax_id" ,
index : 2 ,
corresponding _property : "tax_id" ,
label : _t ( "Tax" ) ,
required : false ,
tabindex : 12 ,
constructor : instance . web . form . FieldMany2One ,
field _properties : {
relation : "account.tax" ,
string : _t ( "Tax" ) ,
type : "many2one" ,
2014-07-11 15:15:34 +00:00
domain : [ [ 'type_tax_use' , 'in' , [ 'purchase' , 'all' ] ] , [ 'parent_id' , '=' , false ] ] ,
2014-05-30 16:47:50 +00:00
} ,
} ,
amount : {
id : "amount" ,
index : 3 ,
corresponding _property : "amount" ,
label : _t ( "Amount" ) ,
required : true ,
tabindex : 13 ,
constructor : instance . web . form . FieldFloat ,
field _properties : {
string : _t ( "Amount" ) ,
type : "float" ,
} ,
} ,
analytic _account _id : {
id : "analytic_account_id" ,
index : 4 ,
corresponding _property : "analytic_account_id" ,
label : _t ( "Analytic Acc." ) ,
required : false ,
tabindex : 14 ,
group : "analytic.group_analytic_accounting" ,
constructor : instance . web . form . FieldMany2One ,
field _properties : {
relation : "account.analytic.account" ,
string : _t ( "Analytic Acc." ) ,
type : "many2one" ,
2014-11-27 11:18:21 +00:00
domain : [ [ 'type' , '!=' , 'view' ] , [ 'state' , 'not in' , [ 'close' , 'cancelled' ] ] ] ,
2014-05-30 16:47:50 +00:00
} ,
} ,
} ;
} ,
start : function ( ) {
this . _super ( ) ;
var self = this ;
// Retreive statement infos and reconciliation data from the model
2014-07-18 13:43:00 +00:00
var lines _filter = [ [ 'journal_entry_id' , '=' , false ] , [ 'account_id' , '=' , false ] ] ;
2014-05-30 16:47:50 +00:00
var deferred _promises = [ ] ;
2014-09-04 09:32:16 +00:00
// Working on specified statement(s)
if ( self . statement _ids && self . statement _ids . length > 0 ) {
lines _filter . push ( [ 'statement_id' , 'in' , self . statement _ids ] ) ;
2014-09-10 12:07:27 +00:00
// If only one statement, display its name as title and allow to modify it
2014-09-11 10:46:56 +00:00
if ( self . single _statement ) {
2014-09-04 09:32:16 +00:00
deferred _promises . push ( self . model _bank _statement
. query ( [ "name" ] )
. filter ( [ [ 'id' , '=' , self . statement _ids [ 0 ] ] ] )
. first ( )
. then ( function ( title ) {
self . title = title . name ;
} )
) ;
}
// Anyway, find out how many statement lines are reconciled (for the progressbar)
2014-05-30 16:47:50 +00:00
deferred _promises . push ( self . model _bank _statement
2014-09-04 09:32:16 +00:00
. call ( "number_of_lines_reconciled" , [ self . statement _ids ] )
2014-05-30 16:47:50 +00:00
. then ( function ( num ) {
self . already _reconciled _lines = num ;
} )
) ;
}
2014-09-04 09:32:16 +00:00
// Get operation templates
2014-05-30 16:47:50 +00:00
deferred _promises . push ( new instance . web . Model ( "account.statement.operation.template" )
. query ( [ 'id' , 'name' , 'account_id' , 'label' , 'amount_type' , 'amount' , 'tax_id' , 'analytic_account_id' ] )
. all ( ) . then ( function ( data ) {
_ ( data ) . each ( function ( preset ) {
self . presets [ preset . id ] = preset ;
} ) ;
} )
) ;
2014-09-04 09:32:16 +00:00
// Get the function to format currencies
deferred _promises . push ( new instance . web . Model ( "res.currency" )
. call ( "get_format_currencies_js_function" )
. then ( function ( data ) {
2014-06-02 00:28:15 +00:00
self . formatCurrency = new Function ( "amount, currency_id" , data ) ;
2014-05-30 16:47:50 +00:00
} )
) ;
2014-09-04 09:32:16 +00:00
// Get statement lines
2014-05-30 16:47:50 +00:00
deferred _promises . push ( self . model _bank _statement _line
. query ( [ 'id' ] )
. filter ( lines _filter )
2014-09-04 09:32:16 +00:00
. order _by ( 'statement_id, id' )
2014-05-30 16:47:50 +00:00
. all ( ) . then ( function ( data ) {
self . st _lines = _ ( data ) . map ( function ( o ) { return o . id } ) ;
} )
) ;
// When queries are done, render template and reconciliation lines
return $ . when . apply ( $ , deferred _promises ) . then ( function ( ) {
// If there is no statement line to reconcile, stop here
if ( self . st _lines . length === 0 ) {
self . $el . prepend ( QWeb . render ( "bank_statement_nothing_to_reconcile" ) ) ;
return ;
}
// Create a dict account id -> account code for display facilities
new instance . web . Model ( "account.account" )
. query ( [ 'id' , 'code' ] )
. all ( ) . then ( function ( data ) {
_ . each ( data , function ( o ) { self . map _account _id _code [ o . id ] = o . code } ) ;
} ) ;
2014-09-04 09:32:16 +00:00
2014-10-03 13:25:53 +00:00
// Create a dict currency id -> rounding factor
new instance . web . Model ( "res.currency" )
. query ( [ 'id' , 'rounding' ] )
. all ( ) . then ( function ( data ) {
_ . each ( data , function ( o ) { self . map _currency _id _rounding [ o . id ] = o . rounding } ) ;
} ) ;
2014-05-30 16:47:50 +00:00
// Create a dict tax id -> amount
new instance . web . Model ( "account.tax" )
. query ( [ 'id' , 'amount' ] )
. all ( ) . then ( function ( data ) {
_ . each ( data , function ( o ) { self . map _tax _id _amount [ o . id ] = o . amount } ) ;
} ) ;
2014-09-04 09:32:16 +00:00
2014-05-30 16:47:50 +00:00
new instance . web . Model ( "ir.model.data" )
. call ( "xmlid_to_res_id" , [ "account.menu_bank_reconcile_bank_statements" ] )
. then ( function ( data ) {
self . reconciliation _menu _id = data ;
self . doReloadMenuReconciliation ( ) ;
} ) ;
2014-09-04 09:32:16 +00:00
2014-05-30 16:47:50 +00:00
// Bind keyboard events TODO : méthode standard ?
$ ( "body" ) . on ( "keypress" , function ( e ) {
self . keyboardShortcutsHandler ( e ) ;
} ) ;
// Render and display
2014-09-10 12:07:27 +00:00
self . $el . prepend ( QWeb . render ( "bank_statement_reconciliation" , {
title : self . title ,
2014-09-11 10:46:56 +00:00
single _statement : self . single _statement ,
2014-09-10 12:07:27 +00:00
total _lines : self . already _reconciled _lines + self . st _lines . length
} ) ) ;
2014-05-30 16:47:50 +00:00
self . updateProgressbar ( ) ;
2015-01-06 10:50:49 +00:00
var reconciliations _to _show = self . st _lines . slice ( 0 , self . num _reconciliations _fetched _in _batch ) ;
2014-05-30 16:47:50 +00:00
self . last _displayed _reconciliation _index = reconciliations _to _show . length ;
self . $ ( ".reconciliation_lines_container" ) . css ( "opacity" , 0 ) ;
// Display the reconciliations
return self . model _bank _statement _line
. call ( "get_data_for_reconciliations" , [ reconciliations _to _show ] )
. then ( function ( data ) {
var child _promises = [ ] ;
2014-09-11 11:08:59 +00:00
while ( ( datum = data . shift ( ) ) !== undefined )
child _promises . push ( self . displayReconciliation ( datum . st _line . id , 'inactive' , false , true , datum . st _line , datum . reconciliation _proposition ) ) ;
2014-05-30 16:47:50 +00:00
$ . when . apply ( $ , child _promises ) . then ( function ( ) {
self . $ ( ".reconciliation_lines_container" ) . animate ( { opacity : 1 } , self . aestetic _animation _speed ) ;
2014-09-17 11:16:46 +00:00
self . getChildren ( ) [ 0 ] . set ( "mode" , "match" ) ;
2015-01-06 10:50:49 +00:00
self . updateShowMoreButton ( ) ;
2014-05-30 16:47:50 +00:00
} ) ;
} ) ;
} ) ;
} ,
2014-09-10 12:07:27 +00:00
statementNameClickHandler : function ( ) {
2014-09-11 10:46:56 +00:00
if ( ! this . single _statement ) return ;
2014-09-10 12:07:27 +00:00
this . $ ( ".statement_name span" ) . hide ( ) ;
this . $ ( ".change_statement_name_field" ) . attr ( "value" , this . title ) ;
this . $ ( ".change_statement_name_container" ) . show ( ) ;
2014-09-10 13:01:13 +00:00
this . $ ( ".change_statement_name_field" ) . focus ( ) ;
2014-09-10 12:07:27 +00:00
} ,
changeStatementNameFieldHandler : function ( e ) {
var name = this . $ ( ".change_statement_name_field" ) . val ( ) ;
if ( name === "" ) this . $ ( ".change_statement_name_button" ) . attr ( "disabled" , "disabled" ) ;
else this . $ ( ".change_statement_name_button" ) . removeAttr ( "disabled" ) ;
2014-09-10 13:01:13 +00:00
if ( name !== "" && e . which === 13 ) // Enter
this . $ ( ".change_statement_name_button" ) . trigger ( "click" ) ;
if ( e . which === 27 ) { // Escape
this . $ ( ".statement_name span" ) . show ( ) ;
this . $ ( ".change_statement_name_container" ) . hide ( ) ;
}
2014-09-10 12:07:27 +00:00
} ,
changeStatementButtonClickHandler : function ( ) {
var self = this ;
2014-09-11 10:46:56 +00:00
if ( ! self . single _statement ) return ;
2014-09-10 12:07:27 +00:00
var name = self . $ ( ".change_statement_name_field" ) . val ( ) ;
if ( name === "" ) return ;
2014-11-26 08:44:50 +00:00
self . $ ( ".change_statement_name_button" ) . attr ( "disabled" , "disabled" ) ;
2014-09-10 12:07:27 +00:00
return self . model _bank _statement
. call ( "write" , [ [ self . statement _ids [ 0 ] ] , { 'name' : name } ] )
2014-11-26 08:44:50 +00:00
. done ( function ( ) {
2014-09-10 12:07:27 +00:00
self . title = name ;
self . $ ( ".statement_name span" ) . text ( name ) . show ( ) ;
self . $ ( ".change_statement_name_container" ) . hide ( ) ;
2014-11-26 08:44:50 +00:00
} ) . always ( function ( ) {
self . $ ( ".change_statement_name_button" ) . removeAttr ( "disabled" ) ;
2014-09-10 12:07:27 +00:00
} ) ;
} ,
2014-05-30 16:47:50 +00:00
keyboardShortcutsHandler : function ( e ) {
var self = this ;
2014-06-17 09:29:27 +00:00
if ( ( e . which === 13 || e . which === 10 ) && ( e . ctrlKey || e . metaKey ) ) {
2014-09-16 15:15:54 +00:00
self . persistReconciliations ( _ . filter ( self . getChildren ( ) , function ( o ) { return o . is _valid ; } ) ) ;
}
} ,
persistReconciliations : function ( reconciliations ) {
if ( reconciliations . length === 0 ) return ;
var self = this ;
// Prepare data
var data = [ ] ;
for ( var i = 0 ; i < reconciliations . length ; i ++ ) {
var child = reconciliations [ i ] ;
data . push ( [ child . st _line _id , child . makeMoveLineDicts ( ) ] ) ;
}
2015-01-06 10:50:49 +00:00
var deferred _animation = self . $ ( ".reconciliation_lines_container, .show_more_container" ) . fadeOut ( self . aestetic _animation _speed ) ;
2014-09-16 15:15:54 +00:00
deferred _rpc = self . model _bank _statement _line . call ( "process_reconciliations" , [ data ] ) ;
return $ . when ( deferred _animation , deferred _rpc )
. done ( function ( ) {
// Remove children
for ( var i = 0 ; i < reconciliations . length ; i ++ ) {
var child = reconciliations [ i ] ;
self . unexcludeMoveLines ( child , child . partner _id , child . get ( "mv_lines_selected" ) ) ;
$ . each ( child . $ ( ".bootstrap_popover" ) , function ( ) { $ ( this ) . popover ( 'destroy' ) } ) ;
child . destroy ( ) ;
2014-05-30 16:47:50 +00:00
}
2014-09-16 15:15:54 +00:00
// Update interface
self . lines _reconciled _with _ctrl _enter += reconciliations . length ;
self . reconciled _lines += reconciliations . length ;
self . updateProgressbar ( ) ;
self . doReloadMenuReconciliation ( ) ;
// Display new line if there are left
if ( self . last _displayed _reconciliation _index < self . st _lines . length ) {
2015-01-06 10:50:49 +00:00
return self . displayReconciliations ( self . num _reconciliations _fetched _in _batch ) . then ( function ( ) {
// Put the first line in match mode
if ( self . reconciled _lines !== self . st _lines . length ) {
var first _child = self . getChildren ( ) [ 0 ] ;
if ( first _child . get ( "mode" ) === "inactive" ) {
first _child . set ( "mode" , "match" ) ;
2014-09-16 15:15:54 +00:00
}
2015-01-06 10:50:49 +00:00
}
self . $ ( ".reconciliation_lines_container, .show_more_container" ) . fadeIn ( self . aestetic _animation _speed ) ;
} ) ;
2014-09-19 14:25:18 +00:00
} else if ( self . reconciled _lines === self . st _lines . length ) {
// Congratulate the user if the work is done
2014-09-16 15:15:54 +00:00
self . displayDoneMessage ( ) ;
2014-09-19 14:25:18 +00:00
} else {
// Some lines weren't persisted because they were't valid
2015-01-06 10:50:49 +00:00
self . $ ( ".reconciliation_lines_container, .show_more_container" ) . fadeIn ( self . aestetic _animation _speed ) ;
2014-09-16 15:15:54 +00:00
}
} ) . fail ( function ( ) {
2015-01-06 10:50:49 +00:00
self . $ ( ".reconciliation_lines_container, .show_more_container" ) . fadeIn ( self . aestetic _animation _speed ) ;
2014-05-30 16:47:50 +00:00
} ) ;
} ,
2014-06-20 13:35:46 +00:00
2014-09-04 09:32:16 +00:00
// Adds move line ids to the list of move lines not to fetch for a given partner
// This is required because the same move line cannot be selected for multiple reconciliation
2014-09-12 13:28:50 +00:00
// and because for a partial reconciliation only one line can be fetched)
2014-09-10 14:58:31 +00:00
excludeMoveLines : function ( source _child , partner _id , lines ) {
2014-05-30 16:47:50 +00:00
var self = this ;
2014-09-12 13:28:50 +00:00
var line _ids = _ . collect ( lines , function ( o ) { return o . id } ) ;
2014-09-04 09:32:16 +00:00
var excluded _ids = this . excluded _move _lines _ids [ partner _id ] ;
var excluded _move _lines _changed = false ;
2014-05-30 16:47:50 +00:00
_ . each ( line _ids , function ( line _id ) {
2014-09-04 09:32:16 +00:00
if ( excluded _ids . indexOf ( line _id ) === - 1 ) {
excluded _ids . push ( line _id ) ;
excluded _move _lines _changed = true ;
2014-05-30 16:47:50 +00:00
}
} ) ;
2014-09-04 09:32:16 +00:00
if ( ! excluded _move _lines _changed )
return ;
// Function that finds if an array of line objects contains at least a line identified by its id
var contains _lines = function ( lines _array , line _ids ) {
for ( var i = 0 ; i < lines _array . length ; i ++ )
for ( var j = 0 ; j < line _ids . length ; j ++ )
if ( lines _array [ i ] . id === line _ids [ j ] )
return true ;
return false ;
} ;
// Update children if needed
2014-05-30 16:47:50 +00:00
_ . each ( self . getChildren ( ) , function ( child ) {
2015-01-06 10:50:49 +00:00
if ( child === source _child || child . st _line === undefined ) return ;
if ( child . partner _id === partner _id || child . st _line . has _no _partner ) {
2014-09-04 09:32:16 +00:00
if ( contains _lines ( child . get ( "mv_lines_selected" ) , line _ids ) ) {
child . set ( "mv_lines_selected" , _ . filter ( child . get ( "mv_lines_selected" ) , function ( o ) { return line _ids . indexOf ( o . id ) === - 1 } ) ) ;
} else if ( contains _lines ( child . mv _lines _deselected , line _ids ) ) {
child . mv _lines _deselected = _ . filter ( child . mv _lines _deselected , function ( o ) { return line _ids . indexOf ( o . id ) === - 1 } ) ;
child . updateMatches ( ) ;
} else if ( contains _lines ( child . get ( "mv_lines" ) , line _ids ) ) {
child . updateMatches ( ) ;
}
}
2014-05-30 16:47:50 +00:00
} ) ;
} ,
2014-09-04 09:32:16 +00:00
2014-09-10 14:58:31 +00:00
unexcludeMoveLines : function ( source _child , partner _id , lines ) {
2014-05-30 16:47:50 +00:00
var self = this ;
2014-09-12 13:28:50 +00:00
var line _ids = _ . collect ( lines , function ( o ) { return o . id } ) ;
2014-09-10 14:58:31 +00:00
2014-09-04 09:32:16 +00:00
var initial _excluded _lines _num = this . excluded _move _lines _ids [ partner _id ] . length ;
this . excluded _move _lines _ids [ partner _id ] = _ . difference ( this . excluded _move _lines _ids [ partner _id ] , line _ids ) ;
if ( this . excluded _move _lines _ids [ partner _id ] . length === initial _excluded _lines _num )
return ;
// Update children if needed
2014-05-30 16:47:50 +00:00
_ . each ( self . getChildren ( ) , function ( child ) {
2015-01-06 10:50:49 +00:00
if ( child . st _line === undefined ) return ;
2014-09-04 09:32:16 +00:00
if ( child . partner _id === partner _id && child !== source _child && ( child . get ( "mode" ) === "match" || child . $el . hasClass ( "no_match" ) ) )
child . updateMatches ( ) ;
2014-09-19 14:25:18 +00:00
if ( child . st _line . has _no _partner && child . get ( "mode" ) === "match" || child . $el . hasClass ( "no_match" ) )
child . updateMatches ( ) ;
2014-05-30 16:47:50 +00:00
} ) ;
} ,
2015-01-06 10:50:49 +00:00
displayReconciliations : function ( number ) {
var self = this ;
var begin = self . last _displayed _reconciliation _index ;
var end = Math . min ( ( begin + number ) , self . st _lines . length ) ;
var reconciliations _to _show = self . st _lines . slice ( begin , end ) ;
// Get ids of selected move lines (to exclude them from reconciliation proposition)
var excluded _move _lines _ids = [ ] ;
_ . each ( self . excluded _move _lines _ids , function ( o ) {
excluded _move _lines _ids = excluded _move _lines _ids . concat ( o ) ;
} ) ;
return self . model _bank _statement _line
. call ( "get_data_for_reconciliations" , [ reconciliations _to _show , excluded _move _lines _ids ] )
. then ( function ( data ) {
var child _promises = [ ] ;
var datum ;
while ( ( datum = data . shift ( ) ) !== undefined ) {
var context = {
st _line _id : datum . st _line . id ,
mode : 'inactive' ,
animate _entrance : false ,
initial _data _provided : true ,
st _line : datum . st _line ,
reconciliation _proposition : datum . reconciliation _proposition ,
} ;
var widget = new instance . web . account . bankStatementReconciliationLine ( self , context ) ;
child _promises . push ( widget . appendTo ( self . $ ( ".reconciliation_lines_container" ) ) ) ;
}
self . last _displayed _reconciliation _index += reconciliations _to _show . length ;
return $ . when . apply ( $ , child _promises ) . then ( function ( ) {
self . updateShowMoreButton ( ) ;
} ) ;
} ) ;
} ,
2014-05-30 16:47:50 +00:00
displayReconciliation : function ( st _line _id , mode , animate _entrance , initial _data _provided , st _line , reconciliation _proposition ) {
var self = this ;
animate _entrance = ( animate _entrance === undefined ? true : animate _entrance ) ;
initial _data _provided = ( initial _data _provided === undefined ? false : initial _data _provided ) ;
var context = {
st _line _id : st _line _id ,
mode : mode ,
animate _entrance : animate _entrance ,
initial _data _provided : initial _data _provided ,
st _line : initial _data _provided ? st _line : undefined ,
reconciliation _proposition : initial _data _provided ? reconciliation _proposition : undefined ,
} ;
var widget = new instance . web . account . bankStatementReconciliationLine ( self , context ) ;
return widget . appendTo ( self . $ ( ".reconciliation_lines_container" ) ) ;
} ,
childValidated : function ( child ) {
var self = this ;
self . reconciled _lines ++ ;
self . updateProgressbar ( ) ;
self . doReloadMenuReconciliation ( ) ;
// Display new line if there are left
2015-01-06 10:50:49 +00:00
if ( self . last _displayed _reconciliation _index < self . st _lines . length && self . getChildren ( ) . length < self . num _reconciliations _fetched _in _batch ) {
2014-05-30 16:47:50 +00:00
self . displayReconciliation ( self . st _lines [ self . last _displayed _reconciliation _index ++ ] , 'inactive' ) ;
}
2014-09-04 09:32:16 +00:00
// Congratulate the user if the work is done
if ( self . reconciled _lines === self . st _lines . length ) {
self . displayDoneMessage ( ) ;
}
2014-05-30 16:47:50 +00:00
// Put the first line in match mode
if ( self . reconciled _lines !== self . st _lines . length ) {
var first _child = self . getChildren ( ) [ 0 ] ;
if ( first _child . get ( "mode" ) === "inactive" ) {
first _child . set ( "mode" , "match" ) ;
}
}
2015-01-06 10:50:49 +00:00
self . updateShowMoreButton ( ) ;
2014-05-30 16:47:50 +00:00
} ,
2014-09-11 10:46:56 +00:00
goBackToStatementsTreeView : function ( ) {
var self = this ;
new instance . web . Model ( "ir.model.data" )
. call ( "get_object_reference" , [ 'account' , 'action_bank_statement_tree' ] )
. then ( function ( result ) {
var action _id = result [ 1 ] ;
// Warning : altough I don't see why this widget wouldn't be directly instanciated by the
// action manager, if it wasn't, this code wouldn't work. You'd have to do something like :
// var action_manager = self;
// while (! action_manager instanceof ActionManager)
// action_manager = action_manager.getParent();
var action _manager = self . getParent ( ) ;
var breadcrumbs = action _manager . breadcrumbs ;
var found = false ;
for ( var i = breadcrumbs . length - 1 ; i >= 0 ; i -- ) {
if ( breadcrumbs [ i ] . action && breadcrumbs [ i ] . action . id === action _id ) {
var title = breadcrumbs [ i ] . get _title ( ) ;
action _manager . select _breadcrumb ( i , _ . isArray ( title ) ? i : undefined ) ;
found = true ;
}
}
if ( ! found )
instance . web . Home ( self ) ;
} ) ;
} ,
2014-05-30 16:47:50 +00:00
displayDoneMessage : function ( ) {
var self = this ;
var sec _taken = Math . round ( ( Date . now ( ) - self . time _widget _loaded ) / 1000 ) ;
var sec _per _item = Math . round ( sec _taken / self . reconciled _lines ) ;
var achievements = [ ] ;
var time _taken ;
if ( sec _taken / 60 >= 1 ) time _taken = Math . floor ( sec _taken / 60 ) + "' " + sec _taken % 60 + "''" ;
else time _taken = sec _taken % 60 + " seconds" ;
var title ;
if ( sec _per _item < 5 ) title = _t ( "Whew, that was fast !" ) + " <i class='fa fa-trophy congrats_icon'></i>" ;
else title = _t ( "Congrats, you're all done !" ) + " <i class='fa fa-thumbs-o-up congrats_icon'></i>" ;
if ( self . lines _reconciled _with _ctrl _enter === self . reconciled _lines )
achievements . push ( {
title : _t ( "Efficiency at its finest" ) ,
desc : _t ( "Only use the ctrl-enter shortcut to validate reconciliations." ) ,
icon : "fa-keyboard-o" }
) ;
if ( sec _per _item < 5 )
achievements . push ( {
title : _t ( "Fast reconciler" ) ,
desc : _t ( "Take on average less than 5 seconds to reconcile a transaction." ) ,
icon : "fa-bolt" }
) ;
// Render it
self . $ ( ".protip" ) . hide ( ) ;
2015-01-06 10:50:49 +00:00
self . updateShowMoreButton ( ) ;
2014-05-30 16:47:50 +00:00
self . $ ( ".oe_form_sheet" ) . append ( QWeb . render ( "bank_statement_reconciliation_done_message" , {
title : title ,
time _taken : time _taken ,
sec _per _item : sec _per _item ,
transactions _done : self . reconciled _lines ,
done _with _ctrl _enter : self . lines _reconciled _with _ctrl _enter ,
achievements : achievements ,
2014-09-11 10:46:56 +00:00
single _statement : self . single _statement ,
multiple _statements : self . multiple _statements ,
2014-05-30 16:47:50 +00:00
} ) ) ;
// Animate it
var container = $ ( "<div style='overflow: hidden;' />" ) ;
self . $ ( ".done_message" ) . wrap ( container ) . css ( "opacity" , 0 ) . css ( "position" , "relative" ) . css ( "left" , "-50%" ) ;
self . $ ( ".done_message" ) . animate ( { opacity : 1 , left : 0 } , self . aestetic _animation _speed * 2 , "easeOutCubic" ) ;
self . $ ( ".done_message" ) . animate ( { opacity : 1 } , self . aestetic _animation _speed * 3 , "easeOutCubic" ) ;
// Make it interactive
self . $ ( ".achievement" ) . popover ( { 'placement' : 'top' , 'container' : self . el , 'trigger' : 'hover' } ) ;
2014-09-11 10:46:56 +00:00
if ( self . $ ( ".button_back_to_statement" ) . length !== 0 ) {
self . $ ( ".button_back_to_statement" ) . click ( function ( ) {
self . goBackToStatementsTreeView ( ) ;
2014-05-30 16:47:50 +00:00
} ) ;
2014-09-11 10:46:56 +00:00
}
2014-05-30 16:47:50 +00:00
2014-09-11 10:46:56 +00:00
if ( self . $ ( ".button_close_statement" ) . length !== 0 ) {
2014-05-30 16:47:50 +00:00
self . $ ( ".button_close_statement" ) . hide ( ) ;
self . model _bank _statement
. query ( [ "balance_end_real" , "balance_end" ] )
2014-09-11 10:46:56 +00:00
. filter ( [ [ 'id' , 'in' , self . statement _ids ] ] )
. all ( )
2014-05-30 16:47:50 +00:00
. then ( function ( data ) {
2014-09-11 10:46:56 +00:00
if ( _ . all ( data , function ( o ) { return o . balance _end _real === o . balance _end } ) ) {
2014-05-30 16:47:50 +00:00
self . $ ( ".button_close_statement" ) . show ( ) ;
self . $ ( ".button_close_statement" ) . click ( function ( ) {
self . $ ( ".button_close_statement" ) . attr ( "disabled" , "disabled" ) ;
self . model _bank _statement
2014-09-11 10:46:56 +00:00
. call ( "button_confirm_bank" , [ self . statement _ids ] )
2014-05-30 16:47:50 +00:00
. then ( function ( ) {
2014-09-11 10:46:56 +00:00
self . goBackToStatementsTreeView ( ) ;
2014-05-30 16:47:50 +00:00
} , function ( ) {
self . $ ( ".button_close_statement" ) . removeAttr ( "disabled" ) ;
} ) ;
} ) ;
}
} ) ;
}
} ,
2015-01-06 10:50:49 +00:00
showMoreButtonClickHandler : function ( ) {
this . displayReconciliations ( this . num _reconciliations _fetched _in _batch ) ;
} ,
2014-05-30 16:47:50 +00:00
2015-01-06 10:50:49 +00:00
updateShowMoreButton : function ( ) {
var items _remaining = this . st _lines . length - this . last _displayed _reconciliation _index ;
if ( items _remaining > 0 )
this . $ ( ".show_more" ) . show ( ) . find ( ".num_items_remaining" ) . text ( items _remaining ) ;
else
this . $ ( ".show_more" ) . hide ( ) ;
} ,
2014-05-30 16:47:50 +00:00
updateProgressbar : function ( ) {
var self = this ;
var done = self . already _reconciled _lines + self . reconciled _lines ;
var total = self . already _reconciled _lines + self . st _lines . length ;
var prog _bar = self . $ ( ".progress .progress-bar" ) ;
prog _bar . attr ( "aria-valuenow" , done ) ;
prog _bar . css ( "width" , ( done / total * 100 ) + "%" ) ;
self . $ ( ".progress .progress-text .valuenow" ) . text ( done ) ;
} ,
/* reloads the needaction badge */
doReloadMenuReconciliation : function ( ) {
var menu = instance . webclient . menu ;
if ( ! menu || ! this . reconciliation _menu _id ) {
return $ . when ( ) ;
}
return menu . rpc ( "/web/menu/load_needaction" , { 'menu_ids' : [ this . reconciliation _menu _id ] } ) . done ( function ( r ) {
menu . on _needaction _loaded ( r ) ;
} ) . then ( function ( ) {
menu . trigger ( "need_action_reloaded" ) ;
} ) ;
} ,
} ) ;
instance . web . account . bankStatementReconciliationLine = instance . web . Widget . extend ( {
className : 'oe_bank_statement_reconciliation_line' ,
events : {
2014-09-16 09:01:06 +00:00
"click .change_partner" : "changePartnerClickHandler" ,
2014-05-30 16:47:50 +00:00
"click .button_ok" : "persistAndDestroy" ,
"click .mv_line" : "moveLineClickHandler" ,
"click .initial_line" : "initialLineClickHandler" ,
"click .line_open_balance" : "lineOpenBalanceClickHandler" ,
"click .pager_control_left:not(.disabled)" : "pagerControlLeftHandler" ,
"click .pager_control_right:not(.disabled)" : "pagerControlRightHandler" ,
"keyup .filter" : "filterHandler" ,
"click .line_info_button" : function ( e ) { e . stopPropagation ( ) } , // small usability hack
"click .add_line" : "addLineBeingEdited" ,
"click .preset" : "presetClickHandler" ,
"click .do_partial_reconcile_button" : "doPartialReconcileButtonClickHandler" ,
"click .undo_partial_reconcile_button" : "undoPartialReconcileButtonClickHandler" ,
} ,
init : function ( parent , context ) {
this . _super ( parent ) ;
2014-09-04 09:32:16 +00:00
this . formatCurrency = this . getParent ( ) . formatCurrency ;
2014-05-30 16:47:50 +00:00
if ( context . initial _data _provided ) {
// Process data
2014-09-04 09:32:16 +00:00
_ . each ( context . reconciliation _proposition , function ( line ) {
this . decorateMoveLine ( line , context . st _line . currency _id ) ;
} , this ) ;
2014-05-30 16:47:50 +00:00
this . set ( "mv_lines_selected" , context . reconciliation _proposition ) ;
this . st _line = context . st _line ;
this . partner _id = context . st _line . partner _id ;
this . decorateStatementLine ( this . st _line ) ;
// Exclude selected move lines
2014-09-04 09:32:16 +00:00
if ( this . getParent ( ) . excluded _move _lines _ids [ this . partner _id ] === undefined )
this . getParent ( ) . excluded _move _lines _ids [ this . partner _id ] = [ ] ;
2014-09-10 14:58:31 +00:00
this . getParent ( ) . excludeMoveLines ( this , this . partner _id , context . reconciliation _proposition ) ;
2014-05-30 16:47:50 +00:00
} else {
this . set ( "mv_lines_selected" , [ ] ) ;
this . st _line = undefined ;
this . partner _id = undefined ;
}
this . context = context ;
this . st _line _id = context . st _line _id ;
this . max _move _lines _displayed = this . getParent ( ) . max _move _lines _displayed ;
this . animation _speed = this . getParent ( ) . animation _speed ;
this . aestetic _animation _speed = this . getParent ( ) . aestetic _animation _speed ;
this . model _bank _statement _line = new instance . web . Model ( "account.bank.statement.line" ) ;
this . model _res _users = new instance . web . Model ( "res.users" ) ;
this . model _tax = new instance . web . Model ( "account.tax" ) ;
2014-10-03 13:25:53 +00:00
this . map _currency _id _rounding = this . getParent ( ) . map _currency _id _rounding ;
2014-05-30 16:47:50 +00:00
this . map _account _id _code = this . getParent ( ) . map _account _id _code ;
this . map _tax _id _amount = this . getParent ( ) . map _tax _id _amount ;
this . presets = this . getParent ( ) . presets ;
this . is _valid = true ;
this . is _consistent = true ; // Used to prevent bad server requests
2014-09-19 14:25:18 +00:00
this . can _fetch _more _move _lines ; // Tell if we can show more move lines
2014-05-30 16:47:50 +00:00
this . filter = "" ;
2014-09-04 09:32:16 +00:00
// In rare cases like when deleting a statement line's partner we don't want the server to
// look for a reconciliation proposition (in this particular case it might find a move line
// matching the statement line and decide to set the statement line's partner accordingly)
this . do _load _reconciliation _proposition = true ;
2014-05-30 16:47:50 +00:00
this . set ( "mode" , undefined ) ;
this . on ( "change:mode" , this , this . modeChanged ) ;
2014-09-04 09:32:16 +00:00
this . set ( "balance" , undefined ) ; // Debit is +, credit is -
this . on ( "change:balance" , this , this . balanceChanged ) ;
2014-05-30 16:47:50 +00:00
this . set ( "pager_index" , 0 ) ;
this . on ( "change:pager_index" , this , this . pagerChanged ) ;
// NB : mv_lines represent the counterpart that will be created to reconcile existing move lines, so debit and credit are inverted
this . set ( "mv_lines" , [ ] ) ;
this . on ( "change:mv_lines" , this , this . mvLinesChanged ) ;
2014-09-04 09:32:16 +00:00
this . mv _lines _deselected = [ ] ; // deselected lines are displayed on top of the match table
2014-05-30 16:47:50 +00:00
this . on ( "change:mv_lines_selected" , this , this . mvLinesSelectedChanged ) ;
this . set ( "lines_created" , [ ] ) ;
this . set ( "line_created_being_edited" , [ { 'id' : 0 } ] ) ;
this . on ( "change:lines_created" , this , this . createdLinesChanged ) ;
this . on ( "change:line_created_being_edited" , this , this . createdLinesChanged ) ;
} ,
start : function ( ) {
var self = this ;
return self . _super ( ) . then ( function ( ) {
// no animation while loading
self . animation _speed = 0 ;
self . aestetic _animation _speed = 0 ;
self . is _consistent = false ;
2014-09-04 09:32:16 +00:00
if ( self . context . animate _entrance ) {
self . $el . fadeOut ( 0 ) ;
self . $el . slideUp ( 0 ) ;
2014-05-30 16:47:50 +00:00
}
2014-09-04 09:32:16 +00:00
return $ . when ( self . loadData ( ) ) . then ( function ( ) {
return $ . when ( self . render ( ) ) . then ( function ( ) {
2014-05-30 16:47:50 +00:00
self . is _consistent = true ;
// Make an entrance
self . animation _speed = self . getParent ( ) . animation _speed ;
self . aestetic _animation _speed = self . getParent ( ) . aestetic _animation _speed ;
2014-09-04 09:32:16 +00:00
if ( self . context . animate _entrance ) {
return self . $el . stop ( true , true ) . fadeIn ( { duration : self . aestetic _animation _speed , queue : false } ) . css ( 'display' , 'none' ) . slideDown ( self . aestetic _animation _speed ) ;
}
2014-05-30 16:47:50 +00:00
} ) ;
} ) ;
} ) ;
} ,
2014-09-04 09:32:16 +00:00
loadData : function ( ) {
var self = this ;
if ( self . context . initial _data _provided )
return ;
// Get ids of selected move lines (to exclude them from reconciliation proposition)
var excluded _move _lines _ids = [ ] ;
if ( self . do _load _reconciliation _proposition ) {
_ . each ( self . getParent ( ) . excluded _move _lines _ids , function ( o ) {
excluded _move _lines _ids = excluded _move _lines _ids . concat ( o ) ;
} ) ;
}
// Load statement line
return self . model _bank _statement _line
. call ( "get_data_for_reconciliations" , [ [ self . st _line _id ] , excluded _move _lines _ids , self . do _load _reconciliation _proposition ] )
. then ( function ( data ) {
self . st _line = data [ 0 ] . st _line ;
self . decorateStatementLine ( self . st _line ) ;
self . partner _id = data [ 0 ] . st _line . partner _id ;
if ( self . getParent ( ) . excluded _move _lines _ids [ self . partner _id ] === undefined )
self . getParent ( ) . excluded _move _lines _ids [ self . partner _id ] = [ ] ;
var mv _lines = [ ] ;
_ . each ( data [ 0 ] . reconciliation _proposition , function ( line ) {
self . decorateMoveLine ( line , self . st _line . currency _id ) ;
mv _lines . push ( line ) ;
} , self ) ;
self . set ( "mv_lines_selected" , self . get ( "mv_lines_selected" ) . concat ( mv _lines ) ) ;
} ) ;
} ,
render : function ( ) {
var self = this ;
var presets _array = [ ] ;
for ( var id in self . presets )
if ( self . presets . hasOwnProperty ( id ) )
presets _array . push ( self . presets [ id ] ) ;
self . $el . prepend ( QWeb . render ( "bank_statement_reconciliation_line" , {
line : self . st _line ,
mode : self . context . mode ,
presets : presets _array
} ) ) ;
// Stuff that require the template to be rendered
self . $ ( ".match" ) . slideUp ( 0 ) ;
self . $ ( ".create" ) . slideUp ( 0 ) ;
if ( self . st _line . no _match ) self . $el . addClass ( "no_match" ) ;
self . bindPopoverTo ( self . $ ( ".line_info_button" ) ) ;
self . createFormWidgets ( ) ;
// Special case hack : no identified partner
if ( self . st _line . has _no _partner ) {
self . $el . css ( "opacity" , "0" ) ;
self . updateBalance ( ) ;
self . $ ( ".change_partner_container" ) . show ( 0 ) ;
self . $ ( ".match" ) . slideUp ( 0 ) ;
self . $el . addClass ( "no_partner" ) ;
self . set ( "mode" , self . context . mode ) ;
self . balanceChanged ( ) ;
self . updateAccountingViewMatchedLines ( ) ;
self . animation _speed = self . getParent ( ) . animation _speed ;
self . aestetic _animation _speed = self . getParent ( ) . aestetic _animation _speed ;
self . $el . animate ( { opacity : 1 } , self . aestetic _animation _speed ) ;
return ;
}
// TODO : the .on handler's returned deferred is lost
return $ . when ( self . set ( "mode" , self . context . mode ) ) . then ( function ( ) {
// Make sure the display is OK
self . balanceChanged ( ) ;
self . createdLinesChanged ( ) ;
self . updateAccountingViewMatchedLines ( ) ;
} ) ;
} ,
2014-05-30 16:47:50 +00:00
restart : function ( mode ) {
var self = this ;
mode = ( mode === undefined ? 'inactive' : mode ) ;
2014-09-11 11:08:59 +00:00
self . context . animate _entrance = false ;
2014-05-30 16:47:50 +00:00
self . $el . css ( "height" , self . $el . outerHeight ( ) ) ;
// Destroy everything
_ . each ( self . getChildren ( ) , function ( o ) { o . destroy ( ) } ) ;
self . is _consistent = false ;
return $ . when ( self . $el . animate ( { opacity : 0 } , self . animation _speed ) ) . then ( function ( ) {
2014-09-10 14:58:31 +00:00
self . getParent ( ) . unexcludeMoveLines ( self , self . partner _id , self . get ( "mv_lines_selected" ) ) ;
2014-05-30 16:47:50 +00:00
$ . each ( self . $ ( ".bootstrap_popover" ) , function ( ) { $ ( this ) . popover ( 'destroy' ) } ) ;
self . $el . empty ( ) ;
self . $el . removeClass ( "no_partner" ) ;
self . context . mode = mode ;
self . context . initial _data _provided = false ;
self . is _valid = true ;
self . is _consistent = true ;
self . filter = "" ;
self . set ( "balance" , undefined , { silent : true } ) ;
self . set ( "mode" , undefined , { silent : true } ) ;
self . set ( "pager_index" , 0 , { silent : true } ) ;
self . set ( "mv_lines" , [ ] , { silent : true } ) ;
self . set ( "mv_lines_selected" , [ ] , { silent : true } ) ;
2014-09-04 09:32:16 +00:00
self . mv _lines _deselected = [ ] ;
2014-05-30 16:47:50 +00:00
self . set ( "lines_created" , [ ] , { silent : true } ) ;
self . set ( "line_created_being_edited" , [ { 'id' : 0 } ] , { silent : true } ) ;
// Rebirth
return $ . when ( self . start ( ) ) . then ( function ( ) {
self . $el . css ( "height" , "auto" ) ;
self . is _consistent = true ;
self . $el . animate ( { opacity : 1 } , self . animation _speed ) ;
} ) ;
} ) ;
} ,
/* create form widgets, append them to the dom and bind their events handlers */
createFormWidgets : function ( ) {
var self = this ;
var create _form _fields = self . getParent ( ) . create _form _fields ;
var create _form _fields _arr = [ ] ;
for ( var key in create _form _fields )
if ( create _form _fields . hasOwnProperty ( key ) )
create _form _fields _arr . push ( create _form _fields [ key ] ) ;
create _form _fields _arr . sort ( function ( a , b ) { return b . index - a . index } ) ;
// field_manager
var dataset = new instance . web . DataSet ( this , "account.account" , self . context ) ;
dataset . ids = [ ] ;
dataset . arch = {
attrs : { string : "Stéphanie de Monaco" , version : "7.0" , class : "oe_form_container" } ,
children : [ ] ,
tag : "form"
} ;
var field _manager = new instance . web . FormView (
this , dataset , false , {
initial _mode : 'edit' ,
disable _autofocus : false ,
$buttons : $ ( ) ,
$pager : $ ( )
} ) ;
field _manager . load _form ( dataset ) ;
// fields default properties
var Default _field = function ( ) {
this . context = { } ;
this . domain = [ ] ;
this . help = "" ;
this . readonly = false ;
this . required = true ;
this . selectable = true ;
this . states = { } ;
this . views = { } ;
} ;
var Default _node = function ( field _name ) {
this . tag = "field" ;
this . children = [ ] ;
this . required = true ;
this . attrs = {
invisible : "False" ,
modifiers : '{"required":true}' ,
name : field _name ,
nolabel : "True" ,
} ;
} ;
// Append fields to the field_manager
field _manager . fields _view . fields = { } ;
for ( var i = 0 ; i < create _form _fields _arr . length ; i ++ ) {
field _manager . fields _view . fields [ create _form _fields _arr [ i ] . id ] = _ . extend ( new Default _field ( ) , create _form _fields _arr [ i ] . field _properties ) ;
}
field _manager . fields _view . fields [ "change_partner" ] = _ . extend ( new Default _field ( ) , {
relation : "res.partner" ,
string : _t ( "Partner" ) ,
type : "many2one" ,
domain : [ [ 'parent_id' , '=' , false ] , '|' , [ 'customer' , '=' , true ] , [ 'supplier' , '=' , true ] ] ,
} ) ;
// Returns a function that serves as a xhr response handler
var hideGroupResponseClosureFactory = function ( field _widget , $container , obj _key ) {
return function ( has _group ) {
if ( has _group ) $container . show ( ) ;
else {
field _widget . destroy ( ) ;
$container . remove ( ) ;
delete self [ obj _key ] ;
}
} ;
} ;
// generate the create "form"
self . create _form = [ ] ;
for ( var i = 0 ; i < create _form _fields _arr . length ; i ++ ) {
var field _data = create _form _fields _arr [ i ] ;
// create widgets
var node = new Default _node ( field _data . id ) ;
if ( ! field _data . required ) node . attrs . modifiers = "" ;
var field = new field _data . constructor ( field _manager , node ) ;
self [ field _data . id + "_field" ] = field ;
self . create _form . push ( field ) ;
// on update : change the last created line
field . corresponding _property = field _data . corresponding _property ;
field . on ( "change:value" , self , self . formCreateInputChanged ) ;
// append to DOM
var $field _container = $ ( QWeb . render ( "form_create_field" , { id : field _data . id , label : field _data . label } ) ) ;
field . appendTo ( $field _container . find ( "td" ) ) ;
self . $ ( ".create_form" ) . prepend ( $field _container ) ;
// now that widget's dom has been created (appendTo does that), bind events and adds tabindex
if ( field _data . field _properties . type != "many2one" ) {
// Triggers change:value TODO : moche bind ?
field . $el . find ( "input" ) . keyup ( function ( e , field ) { field . commit _value ( ) ; } . bind ( null , null , field ) ) ;
}
field . $el . find ( "input" ) . attr ( "tabindex" , field _data . tabindex ) ;
// Hide the field if group not OK
if ( field _data . group !== undefined ) {
var target = $field _container ;
target . hide ( ) ;
self . model _res _users
. call ( "has_group" , [ field _data . group ] )
. then ( hideGroupResponseClosureFactory ( field , target , ( field _data . id + "_field" ) ) ) ;
}
}
// generate the change partner "form"
var change _partner _node = new Default _node ( "change_partner" ) ; change _partner _node . attrs . modifiers = "" ;
self . change _partner _field = new instance . web . form . FieldMany2One ( field _manager , change _partner _node ) ;
self . change _partner _field . appendTo ( self . $ ( ".change_partner_container" ) ) ;
self . change _partner _field . on ( "change:value" , self . change _partner _field , function ( ) {
self . changePartner ( this . get _value ( ) ) ;
} ) ;
2014-09-16 09:01:06 +00:00
self . change _partner _field . $el . find ( "input" ) . attr ( "placeholder" , self . st _line . communication _partner _name || _t ( "Select Partner" ) ) ;
2014-05-30 16:47:50 +00:00
field _manager . do _show ( ) ;
} ,
/** Utils */
/* TODO : if t-call for attr, all in qweb */
decorateStatementLine : function ( line ) {
line . q _popover = QWeb . render ( "bank_statement_reconciliation_line_details" , { line : line } ) ;
} ,
// adds fields, prefixed with q_, to the move line for qweb rendering
2014-09-04 09:32:16 +00:00
decorateMoveLine : function ( line , currency _id ) {
2014-05-30 16:47:50 +00:00
line . partial _reconcile = false ;
line . propose _partial _reconcile = false ;
2014-09-04 09:32:16 +00:00
line [ 'credit' ] = [ line [ 'debit' ] , line [ 'debit' ] = line [ 'credit' ] ] [ 0 ] ;
2014-05-30 16:47:50 +00:00
line . q _due _date = ( line . date _maturity === false ? line . date : line . date _maturity ) ;
line . q _amount = ( line . debit !== 0 ? "- " + line . q _debit : "" ) + ( line . credit !== 0 ? line . q _credit : "" ) ;
line . q _label = line . name ;
2014-09-04 09:32:16 +00:00
line . debit _str = this . formatCurrency ( line . debit , currency _id ) ;
line . credit _str = this . formatCurrency ( line . credit , currency _id ) ;
line . q _popover = QWeb . render ( "bank_statement_reconciliation_move_line_details" , { line : line } ) ;
if ( line . has _no _partner )
line . q _label = line . partner _name + ': ' + line . q _label ;
if ( line . ref && line . ref !== line . name )
2014-05-30 16:47:50 +00:00
line . q _label += " : " + line . ref ;
} ,
bindPopoverTo : function ( el ) {
var self = this ;
$ ( el ) . addClass ( "bootstrap_popover" ) ;
el . popover ( {
'placement' : 'left' ,
'container' : self . el ,
'html' : true ,
'trigger' : 'hover' ,
'animation' : false ,
'toggle' : 'popover'
} ) ;
} ,
islineCreatedBeingEditedValid : function ( ) {
var line = this . get ( "line_created_being_edited" ) [ 0 ] ;
return line . amount // must be defined and not 0
&& line . account _id // must be defined (and will never be 0)
&& line . label ; // must be defined and not empty
} ,
/* returns the created lines, plus the ones being edited if valid */
getCreatedLines : function ( ) {
var self = this ;
var created _lines = self . get ( "lines_created" ) . slice ( ) ;
if ( self . islineCreatedBeingEditedValid ( ) )
return created _lines . concat ( self . get ( "line_created_being_edited" ) ) ;
else
return created _lines ;
} ,
/** Matching */
moveLineClickHandler : function ( e ) {
var self = this ;
if ( e . currentTarget . dataset . selected === "true" ) self . deselectMoveLine ( e . currentTarget ) ;
else self . selectMoveLine ( e . currentTarget ) ;
} ,
2014-06-20 13:35:46 +00:00
2014-05-30 16:47:50 +00:00
selectMoveLine : function ( mv _line ) {
var self = this ;
var line _id = mv _line . dataset . lineid ;
2014-09-04 09:32:16 +00:00
// find the line in mv_lines or mv_lines_deselected
var line = _ . find ( self . get ( "mv_lines" ) , function ( o ) { return o . id == line _id } ) ;
if ( ! line ) {
line = _ . find ( self . mv _lines _deselected , function ( o ) { return o . id == line _id } ) ;
self . mv _lines _deselected = _ . filter ( self . mv _lines _deselected , function ( o ) { return o . id != line _id } ) ;
}
if ( ! line ) return ; // If no line found, we've got a syncing problem (let's turn a deaf ear)
// Warn the user if he's selecting lines from both a payable and a receivable account
var last _selected _line = _ . last ( self . get ( "mv_lines_selected" ) ) ;
if ( last _selected _line && last _selected _line . account _type != line . account _type ) {
new instance . web . Dialog ( this , {
title : _t ( "Warning" ) ,
size : 'medium' ,
} , $ ( "<div />" ) . text ( _ . str . sprintf ( _t ( "You are selecting transactions from both a payable and a receivable account.\n\nIn order to proceed, you first need to deselect the %s transactions." ) , last _selected _line . account _type ) ) ) . open ( ) ;
return ;
}
2014-09-17 10:26:19 +00:00
self . set ( "mv_lines_selected" , self . get ( "mv_lines_selected" ) . concat ( line ) ) ;
2014-05-30 16:47:50 +00:00
} ,
2014-06-20 13:35:46 +00:00
2014-05-30 16:47:50 +00:00
deselectMoveLine : function ( mv _line ) {
var self = this ;
var line _id = mv _line . dataset . lineid ;
2014-09-04 09:32:16 +00:00
var line = _ . find ( self . get ( "mv_lines_selected" ) , function ( o ) { return o . id == line _id } ) ;
if ( ! line ) return ; // If no line found, we've got a syncing problem (let's turn a deaf ear)
// add the line to mv_lines_deselected and remove it from mv_lines_selected
self . mv _lines _deselected . unshift ( line ) ;
var mv _lines _selected = _ . filter ( self . get ( "mv_lines_selected" ) , function ( o ) { return o . id != line _id } ) ;
// remove partial reconciliation stuff if necessary
if ( line . partial _reconcile === true ) self . unpartialReconcileLine ( line ) ;
if ( line . propose _partial _reconcile === true ) line . propose _partial _reconcile = false ;
self . $el . removeClass ( "no_match" ) ;
self . set ( "mode" , "match" ) ;
self . set ( "mv_lines_selected" , mv _lines _selected ) ;
2014-05-30 16:47:50 +00:00
} ,
/** Matches pagination */
pagerControlLeftHandler : function ( ) {
var self = this ;
2014-09-04 09:32:16 +00:00
if ( self . $ ( ".pager_control_left" ) . hasClass ( "disabled" ) ) { return ; /* shouldn't happen, anyway*/ }
2014-09-19 14:25:18 +00:00
if ( self . get ( "pager_index" ) === 0 ) { return ; }
2014-05-30 16:47:50 +00:00
self . set ( "pager_index" , self . get ( "pager_index" ) - 1 ) ;
} ,
2014-09-04 09:32:16 +00:00
2014-05-30 16:47:50 +00:00
pagerControlRightHandler : function ( ) {
var self = this ;
2014-09-04 09:32:16 +00:00
if ( self . $ ( ".pager_control_right" ) . hasClass ( "disabled" ) ) { return ; /* shouldn't happen, anyway*/ }
2014-09-19 14:25:18 +00:00
if ( ! self . can _fetch _more _move _lines ) { return ; }
self . set ( "pager_index" , self . get ( "pager_index" ) + 1 ) ;
2014-05-30 16:47:50 +00:00
} ,
filterHandler : function ( ) {
var self = this ;
self . set ( "pager_index" , 0 ) ;
self . filter = self . $ ( ".filter" ) . val ( ) ;
2014-09-04 09:32:16 +00:00
window . clearTimeout ( self . apply _filter _timeout ) ;
self . apply _filter _timeout = window . setTimeout ( self . proxy ( 'updateMatches' ) , 200 ) ;
2014-05-30 16:47:50 +00:00
} ,
2014-09-04 09:32:16 +00:00
2014-05-30 16:47:50 +00:00
/** Creating */
initializeCreateForm : function ( ) {
var self = this ;
_ . each ( self . create _form , function ( field ) {
field . set ( "value" , false ) ;
} ) ;
2014-09-04 09:32:16 +00:00
self . label _field . set ( "value" , self . st _line . name ) ;
2014-05-30 16:47:50 +00:00
self . amount _field . set ( "value" , - 1 * self . get ( "balance" ) ) ;
self . account _id _field . focus ( ) ;
} ,
addLineBeingEdited : function ( ) {
var self = this ;
if ( ! self . islineCreatedBeingEditedValid ( ) ) return ;
self . set ( "lines_created" , self . get ( "lines_created" ) . concat ( self . get ( "line_created_being_edited" ) ) ) ;
// Add empty created line
var new _id = self . get ( "line_created_being_edited" ) [ 0 ] . id + 1 ;
self . set ( "line_created_being_edited" , [ { 'id' : new _id } ] ) ;
self . initializeCreateForm ( ) ;
} ,
removeLine : function ( $line ) {
var self = this ;
var line _id = $line . data ( "lineid" ) ;
// if deleting the created line that is being edited, validate it before
if ( line _id === self . get ( "line_created_being_edited" ) [ 0 ] . id ) {
self . addLineBeingEdited ( ) ;
}
self . set ( "lines_created" , _ . filter ( self . get ( "lines_created" ) , function ( o ) { return o . id != line _id } ) ) ;
self . amount _field . set ( "value" , - 1 * self . get ( "balance" ) ) ;
} ,
presetClickHandler : function ( e ) {
var self = this ;
self . initializeCreateForm ( ) ;
var preset = self . presets [ e . currentTarget . dataset . presetid ] ;
2014-09-04 09:32:16 +00:00
// Hack : set_value of a field calls a handler that returns a deferred because it could make a RPC call
// to compute the tax before it updates the line being edited. Unfortunately this deferred is lost.
// Hence this ugly hack to avoid concurrency problem that arose when setting amount (in initializeCreateForm), then tax, then another amount
if ( preset . tax && self . tax _field ) self . tax _field . set _value ( false ) ;
if ( preset . amount && self . amount _field ) self . amount _field . set _value ( false ) ;
2014-05-30 16:47:50 +00:00
for ( var key in preset ) {
if ( ! preset . hasOwnProperty ( key ) || key === "amount" ) continue ;
2014-09-04 09:32:16 +00:00
if ( preset [ key ] && self . hasOwnProperty ( key + "_field" ) )
2014-05-30 16:47:50 +00:00
self [ key + "_field" ] . set _value ( preset [ key ] ) ;
}
if ( preset . amount && self . amount _field ) {
if ( preset . amount _type === "fixed" )
2014-09-04 09:32:16 +00:00
self . amount _field . set _value ( preset . amount ) ;
2014-05-30 16:47:50 +00:00
else if ( preset . amount _type === "percentage_of_total" )
2014-09-04 09:32:16 +00:00
self . amount _field . set _value ( self . st _line . amount * preset . amount / 100 ) ;
2014-05-30 16:47:50 +00:00
else if ( preset . amount _type === "percentage_of_balance" ) {
self . amount _field . set _value ( 0 ) ;
self . updateBalance ( ) ;
2014-09-04 09:32:16 +00:00
self . amount _field . set _value ( - 1 * self . get ( "balance" ) * preset . amount / 100 ) ;
2014-05-30 16:47:50 +00:00
}
}
} ,
2014-09-04 09:32:16 +00:00
2014-05-30 16:47:50 +00:00
/** Display */
initialLineClickHandler : function ( ) {
var self = this ;
if ( self . get ( "mode" ) === "match" ) {
self . set ( "mode" , "inactive" ) ;
} else {
2014-09-17 10:10:01 +00:00
self . set ( "mode" , "match" ) ;
2014-05-30 16:47:50 +00:00
}
} ,
lineOpenBalanceClickHandler : function ( ) {
var self = this ;
if ( self . get ( "mode" ) === "create" ) {
2014-09-17 10:10:01 +00:00
self . set ( "mode" , "match" ) ;
2014-05-30 16:47:50 +00:00
} else {
self . set ( "mode" , "create" ) ;
}
} ,
2014-09-16 09:01:06 +00:00
changePartnerClickHandler : function ( ) {
2014-05-30 16:47:50 +00:00
var self = this ;
2014-09-16 09:01:06 +00:00
self . $ ( ".change_partner_container" ) . find ( "input" ) . attr ( "placeholder" , self . st _line . partner _name ) ;
self . $ ( ".change_partner_container" ) . show ( ) ;
self . $ ( ".partner_name" ) . hide ( ) ;
self . change _partner _field . $drop _down . trigger ( "click" ) ;
2014-05-30 16:47:50 +00:00
} ,
/** Views updating */
updateAccountingViewMatchedLines : function ( ) {
var self = this ;
$ . each ( self . $ ( ".tbody_matched_lines .bootstrap_popover" ) , function ( ) { $ ( this ) . popover ( 'destroy' ) } ) ;
self . $ ( ".tbody_matched_lines" ) . empty ( ) ;
2014-12-05 14:07:01 +00:00
2014-05-30 16:47:50 +00:00
_ ( self . get ( "mv_lines_selected" ) ) . each ( function ( line ) {
var $line = $ ( QWeb . render ( "bank_statement_reconciliation_move_line" , { line : line , selected : true } ) ) ;
self . bindPopoverTo ( $line . find ( ".line_info_button" ) ) ;
if ( line . propose _partial _reconcile ) self . bindPopoverTo ( $line . find ( ".do_partial_reconcile_button" ) ) ;
if ( line . partial _reconcile ) self . bindPopoverTo ( $line . find ( ".undo_partial_reconcile_button" ) ) ;
self . $ ( ".tbody_matched_lines" ) . append ( $line ) ;
} ) ;
} ,
updateAccountingViewCreatedLines : function ( ) {
var self = this ;
$ . each ( self . $ ( ".tbody_created_lines .bootstrap_popover" ) , function ( ) { $ ( this ) . popover ( 'destroy' ) } ) ;
self . $ ( ".tbody_created_lines" ) . empty ( ) ;
_ ( self . getCreatedLines ( ) ) . each ( function ( line ) {
var $line = $ ( QWeb . render ( "bank_statement_reconciliation_created_line" , { line : line } ) ) ;
2014-12-05 14:07:01 +00:00
$line . click ( function ( ) { self . removeLine ( $ ( this ) ) } ) ;
2014-05-30 16:47:50 +00:00
self . $ ( ".tbody_created_lines" ) . append ( $line ) ;
if ( line . no _remove _action ) {
// Then the previous line's remove button deletes this line too
$line . hover ( function ( ) { $ ( this ) . prev ( ) . addClass ( "active" ) } , function ( ) { $ ( this ) . prev ( ) . removeClass ( "active" ) } ) ;
}
} ) ;
} ,
updateMatchView : function ( ) {
var self = this ;
var table = self . $ ( ".match table" ) ;
var nothing _displayed = true ;
2014-09-04 09:32:16 +00:00
2014-05-30 16:47:50 +00:00
// Display move lines
$ . each ( self . $ ( ".match table .bootstrap_popover" ) , function ( ) { $ ( this ) . popover ( 'destroy' ) } ) ;
table . empty ( ) ;
var slice _start = self . get ( "pager_index" ) * self . max _move _lines _displayed ;
var slice _end = ( self . get ( "pager_index" ) + 1 ) * self . max _move _lines _displayed ;
2014-09-04 09:32:16 +00:00
_ ( _ . filter ( self . mv _lines _deselected , function ( o ) {
return o . name . indexOf ( self . filter ) !== - 1 || o . ref . indexOf ( self . filter ) !== - 1 } )
. slice ( slice _start , slice _end ) ) . each ( function ( line ) {
var $line = $ ( QWeb . render ( "bank_statement_reconciliation_move_line" , { line : line , selected : false } ) ) ;
self . bindPopoverTo ( $line . find ( ".line_info_button" ) ) ;
table . append ( $line ) ;
nothing _displayed = false ;
} ) ;
2014-05-30 16:47:50 +00:00
_ ( self . get ( "mv_lines" ) ) . each ( function ( line ) {
2014-09-04 09:32:16 +00:00
var $line = $ ( QWeb . render ( "bank_statement_reconciliation_move_line" , { line : line , selected : false } ) ) ;
self . bindPopoverTo ( $line . find ( ".line_info_button" ) ) ;
table . append ( $line ) ;
nothing _displayed = false ;
2014-05-30 16:47:50 +00:00
} ) ;
2014-09-04 09:32:16 +00:00
if ( nothing _displayed && this . filter !== "" )
2014-05-30 16:47:50 +00:00
table . append ( QWeb . render ( "filter_no_match" , { filter _str : self . filter } ) ) ;
} ,
updatePagerControls : function ( ) {
var self = this ;
2014-09-04 09:32:16 +00:00
2014-05-30 16:47:50 +00:00
if ( self . get ( "pager_index" ) === 0 )
self . $ ( ".pager_control_left" ) . addClass ( "disabled" ) ;
else
self . $ ( ".pager_control_left" ) . removeClass ( "disabled" ) ;
2014-09-19 14:25:18 +00:00
if ( ! self . can _fetch _more _move _lines )
2014-05-30 16:47:50 +00:00
self . $ ( ".pager_control_right" ) . addClass ( "disabled" ) ;
else
self . $ ( ".pager_control_right" ) . removeClass ( "disabled" ) ;
} ,
/** Properties changed */
2014-12-05 14:10:32 +00:00
// Updates the validation button, the "open balance" line and the partial reconciliation sign
2014-05-30 16:47:50 +00:00
balanceChanged : function ( ) {
var self = this ;
2014-12-05 14:10:32 +00:00
// 'reset' the widget to invalid state
self . is _valid = false ;
self . $ ( ".tip_reconciliation_not_balanced" ) . show ( ) ;
2014-06-17 09:29:27 +00:00
self . $ ( ".tbody_open_balance" ) . empty ( ) ;
2014-12-05 14:10:32 +00:00
self . $ ( ".button_ok" ) . text ( "OK" ) . removeClass ( "oe_highlight" ) . attr ( "disabled" , "disabled" ) ;
// Find out if the counterpart is lower than, equal or greater than the transaction being reconciled
var balance _type = undefined ;
if ( Math . abs ( self . get ( "balance" ) ) . toFixed ( 3 ) === "0.000" ) balance _type = "equal" ;
else if ( self . get ( "balance" ) * self . st _line . amount > 0 ) balance _type = "greater" ;
else if ( self . get ( "balance" ) * self . st _line . amount < 0 ) balance _type = "lower" ;
// Adjust to different cases
if ( balance _type === "equal" ) {
displayValidState ( true ) ;
} else if ( balance _type === "greater" ) {
createOpenBalance ( "Create Write-off" ) ;
} else if ( balance _type === "lower" ) {
if ( self . st _line . has _no _partner ) {
createOpenBalance ( "Choose counterpart" ) ;
2014-05-30 16:47:50 +00:00
} else {
2014-12-05 14:10:32 +00:00
displayValidState ( false , "Keep open" ) ;
createOpenBalance ( "Open balance" ) ;
2014-05-30 16:47:50 +00:00
}
}
2014-12-05 14:10:32 +00:00
// Show or hide partial reconciliation
if ( self . get ( "mv_lines_selected" ) . length > 0 ) {
var propose _partial = self . getCreatedLines ( ) . length === 0 && self . get ( "mv_lines_selected" ) . length === 1 && balance _type === "greater" && ! self . get ( "mv_lines_selected" ) [ 0 ] . partial _reconcile ;
self . get ( "mv_lines_selected" ) [ 0 ] . propose _partial _reconcile = propose _partial ;
self . updateAccountingViewMatchedLines ( ) ;
}
function displayValidState ( higlight _ok _button , ok _button _text ) {
self . is _valid = true ;
self . $ ( ".tip_reconciliation_not_balanced" ) . hide ( ) ;
self . $ ( ".button_ok" ) . removeAttr ( "disabled" ) ;
if ( higlight _ok _button ) self . $ ( ".button_ok" ) . addClass ( "oe_highlight" ) ;
if ( ok _button _text !== undefined ) self . $ ( ".button_ok" ) . text ( ok _button _text )
}
function createOpenBalance ( name ) {
var balance = self . get ( "balance" ) ;
var amount = self . formatCurrency ( Math . abs ( balance ) , self . st _line . currency _id ) ;
2014-09-04 09:32:16 +00:00
var $line = $ ( QWeb . render ( "bank_statement_reconciliation_line_open_balance" , {
2014-12-05 14:10:32 +00:00
debit : balance > 0 ? amount : "" ,
credit : balance < 0 ? amount : "" ,
2014-09-04 09:32:16 +00:00
account _code : self . map _account _id _code [ self . st _line . open _balance _account _id ]
} ) ) ;
2014-12-05 14:10:32 +00:00
if ( name !== undefined )
$line . find ( ".cell_label" ) . text ( name ) ;
self . $ ( ".tbody_open_balance" ) . empty ( ) . append ( $line ) ;
2014-05-30 16:47:50 +00:00
}
} ,
2014-09-16 10:55:02 +00:00
modeChanged : function ( o , val ) {
2014-05-30 16:47:50 +00:00
var self = this ;
self . $ ( ".action_pane.active" ) . removeClass ( "active" ) ;
2014-09-16 10:46:26 +00:00
2014-09-16 10:55:02 +00:00
if ( val . oldValue === "create" )
self . addLineBeingEdited ( ) ;
2014-05-30 16:47:50 +00:00
if ( self . get ( "mode" ) === "inactive" ) {
self . $ ( ".match" ) . slideUp ( self . animation _speed ) ;
self . $ ( ".create" ) . slideUp ( self . animation _speed ) ;
self . el . dataset . mode = "inactive" ;
} else if ( self . get ( "mode" ) === "match" ) {
2014-09-11 11:08:59 +00:00
// TODO : remove this old_animation_speed / new_animation_speed hack
// when .on handler's returned deferred's no longer lost
var old _animation _speed = self . animation _speed ;
2014-09-04 09:32:16 +00:00
return $ . when ( self . updateMatches ( ) ) . then ( function ( ) {
2014-09-11 11:08:59 +00:00
var new _animation _speed = self . animation _speed ;
self . animation _speed = old _animation _speed ;
2014-09-16 10:46:26 +00:00
if ( self . $el . hasClass ( "no_match" ) ) {
self . animation _speed = 0 ;
2014-09-11 11:08:59 +00:00
self . set ( "mode" , "create" ) ;
2014-05-30 16:47:50 +00:00
return ;
}
self . $ ( ".match" ) . slideDown ( self . animation _speed ) ;
self . $ ( ".create" ) . slideUp ( self . animation _speed ) ;
self . el . dataset . mode = "match" ;
2014-09-11 11:08:59 +00:00
self . animation _speed = new _animation _speed ;
2014-05-30 16:47:50 +00:00
} ) ;
} else if ( self . get ( "mode" ) === "create" ) {
self . initializeCreateForm ( ) ;
self . $ ( ".match" ) . slideUp ( self . animation _speed ) ;
self . $ ( ".create" ) . slideDown ( self . animation _speed ) ;
self . el . dataset . mode = "create" ;
}
} ,
pagerChanged : function ( ) {
2014-09-04 09:32:16 +00:00
this . updateMatches ( ) ;
2014-05-30 16:47:50 +00:00
} ,
mvLinesChanged : function ( ) {
var self = this ;
2014-09-04 09:32:16 +00:00
// If pager_index is out of range, set it to display the last page
2014-09-19 14:25:18 +00:00
if ( self . get ( "pager_index" ) !== 0 && self . get ( "mv_lines" ) . length === 0 && ! self . can _fetch _more _move _lines ) {
self . set ( "pager_index" , 0 ) ;
2014-09-04 09:32:16 +00:00
}
2014-05-30 16:47:50 +00:00
// If there is no match to display, disable match view and pass in mode inactive
2014-09-19 14:25:18 +00:00
if ( self . get ( "mv_lines" ) . length + self . mv _lines _deselected . length === 0 && ! self . can _fetch _more _move _lines && self . filter === "" ) {
2014-05-30 16:47:50 +00:00
self . $el . addClass ( "no_match" ) ;
if ( self . get ( "mode" ) === "match" ) {
self . set ( "mode" , "inactive" ) ;
}
} else {
self . $el . removeClass ( "no_match" ) ;
}
2014-09-12 13:28:50 +00:00
_ . each ( self . get ( "mv_lines" ) , function ( line ) {
if ( line . partial _reconciliation _siblings _ids . length > 0 ) {
var correct _format = _ . collect ( line . partial _reconciliation _siblings _ids , function ( o ) { return { 'id' : o } } ) ;
self . getParent ( ) . excludeMoveLines ( self , self . partner _id , correct _format ) ;
}
} ) ;
2014-05-30 16:47:50 +00:00
self . updateMatchView ( ) ;
self . updatePagerControls ( ) ;
} ,
mvLinesSelectedChanged : function ( elt , val ) {
var self = this ;
2014-09-04 09:32:16 +00:00
2014-09-10 14:58:31 +00:00
var added _lines = _ . difference ( val . newValue , val . oldValue ) ;
var removed _lines = _ . difference ( val . oldValue , val . newValue ) ;
2014-09-04 09:32:16 +00:00
2014-09-10 14:58:31 +00:00
self . getParent ( ) . excludeMoveLines ( self , self . partner _id , added _lines ) ;
self . getParent ( ) . unexcludeMoveLines ( self , self . partner _id , removed _lines ) ;
2014-09-04 09:32:16 +00:00
$ . when ( self . updateMatches ( ) ) . then ( function ( ) {
self . updateAccountingViewMatchedLines ( ) ;
self . updateBalance ( ) ;
} ) ;
2014-05-30 16:47:50 +00:00
} ,
2014-09-04 09:32:16 +00:00
2014-05-30 16:47:50 +00:00
// Generic function for updating the line_created_being_edited
formCreateInputChanged : function ( elt , val ) {
var self = this ;
var line _created _being _edited = self . get ( "line_created_being_edited" ) ;
line _created _being _edited [ 0 ] [ elt . corresponding _property ] = val . newValue ;
2014-06-02 00:28:15 +00:00
line _created _being _edited [ 0 ] . currency _id = self . st _line . currency _id ;
2014-05-30 16:47:50 +00:00
// Specific cases
if ( elt === self . account _id _field )
line _created _being _edited [ 0 ] . account _num = self . map _account _id _code [ elt . get ( "value" ) ] ;
// Update tax line
var deferred _tax = new $ . Deferred ( ) ;
if ( elt === self . tax _id _field || elt === self . amount _field ) {
var amount = self . amount _field . get ( "value" ) ;
var tax = self . map _tax _id _amount [ self . tax _id _field . get ( "value" ) ] ;
if ( amount && tax ) {
deferred _tax = $ . when ( self . model _tax
. call ( "compute_for_bank_reconciliation" , [ self . tax _id _field . get ( "value" ) , amount ] ) )
. then ( function ( data ) {
2014-07-11 15:15:34 +00:00
line _created _being _edited [ 0 ] . amount _with _tax = line _created _being _edited [ 0 ] . amount ;
2014-05-30 16:47:50 +00:00
line _created _being _edited [ 0 ] . amount = ( data . total . toFixed ( 3 ) === amount . toFixed ( 3 ) ? amount : data . total ) ;
2014-07-11 15:15:34 +00:00
var current _line _cursor = 1 ;
$ . each ( data . taxes , function ( index , tax ) {
if ( tax . amount !== 0.0 ) {
2014-09-04 09:32:16 +00:00
var tax _account _id = ( amount > 0 ? tax . account _collected _id : tax . account _paid _id ) ;
tax _account _id = tax _account _id !== false ? tax _account _id : line _created _being _edited [ 0 ] . account _id ;
line _created _being _edited [ current _line _cursor ] = {
id : line _created _being _edited [ 0 ] . id ,
account _id : tax _account _id ,
account _num : self . map _account _id _code [ tax _account _id ] ,
label : tax . name ,
amount : tax . amount ,
no _remove _action : true ,
currency _id : self . st _line . currency _id ,
is _tax _line : true
} ;
2014-07-11 15:15:34 +00:00
current _line _cursor = current _line _cursor + 1 ;
2014-09-04 09:32:16 +00:00
}
2014-07-11 15:15:34 +00:00
} ) ;
2014-05-30 16:47:50 +00:00
}
) ;
} else {
2014-09-04 09:32:16 +00:00
line _created _being _edited . length = 1 ;
2014-05-30 16:47:50 +00:00
deferred _tax . resolve ( ) ;
}
} else { deferred _tax . resolve ( ) ; }
$ . when ( deferred _tax ) . then ( function ( ) {
// Format amounts
2014-10-03 13:25:53 +00:00
var rounding = 1 / self . map _currency _id _rounding [ self . st _line . currency _id ] ;
2014-07-11 15:15:34 +00:00
$ . each ( line _created _being _edited , function ( index , val ) {
2014-10-03 13:25:53 +00:00
if ( val . amount ) {
line _created _being _edited [ index ] . amount = Math . round ( val . amount * rounding ) / rounding ;
2014-07-11 15:15:34 +00:00
line _created _being _edited [ index ] . amount _str = self . formatCurrency ( Math . abs ( val . amount ) , val . currency _id ) ;
2014-10-03 13:25:53 +00:00
}
2015-01-05 14:13:20 +00:00
if ( val . amount _with _tax )
line _created _being _edited [ index ] . amount _with _tax = Math . round ( val . amount _with _tax * rounding ) / rounding ;
2014-07-11 15:15:34 +00:00
} ) ;
2014-05-30 16:47:50 +00:00
self . set ( "line_created_being_edited" , line _created _being _edited ) ;
self . createdLinesChanged ( ) ; // TODO For some reason, previous line doesn't trigger change handler
} ) ;
} ,
createdLinesChanged : function ( ) {
var self = this ;
self . updateAccountingViewCreatedLines ( ) ;
self . updateBalance ( ) ;
if ( self . islineCreatedBeingEditedValid ( ) ) self . $ ( ".add_line" ) . show ( ) ;
else self . $ ( ".add_line" ) . hide ( ) ;
} ,
/** Model */
doPartialReconcileButtonClickHandler : function ( e ) {
var self = this ;
var line _id = $ ( e . currentTarget ) . closest ( "tr" ) . data ( "lineid" ) ;
var line = _ . find ( self . get ( "mv_lines_selected" ) , function ( o ) { return o . id == line _id } ) ;
self . partialReconcileLine ( line ) ;
$ ( e . currentTarget ) . popover ( 'destroy' ) ;
self . updateAccountingViewMatchedLines ( ) ;
self . updateBalance ( ) ;
e . stopPropagation ( ) ;
} ,
partialReconcileLine : function ( line ) {
var self = this ;
var balance = self . get ( "balance" ) ;
line . initial _amount = line . debit !== 0 ? line . debit : - 1 * line . credit ;
if ( balance < 0 ) {
2014-09-04 09:32:16 +00:00
line . debit += balance ;
2014-06-02 00:28:15 +00:00
line . debit _str = self . formatCurrency ( line . debit , self . st _line . currency _id ) ;
2014-05-30 16:47:50 +00:00
} else {
line . credit -= balance ;
2014-06-02 00:28:15 +00:00
line . credit _str = self . formatCurrency ( line . credit , self . st _line . currency _id ) ;
2014-05-30 16:47:50 +00:00
}
line . propose _partial _reconcile = false ;
line . partial _reconcile = true ;
} ,
undoPartialReconcileButtonClickHandler : function ( e ) {
var self = this ;
var line _id = $ ( e . currentTarget ) . closest ( "tr" ) . data ( "lineid" ) ;
var line = _ . find ( self . get ( "mv_lines_selected" ) , function ( o ) { return o . id == line _id } ) ;
self . unpartialReconcileLine ( line ) ;
$ ( e . currentTarget ) . popover ( 'destroy' ) ;
self . updateAccountingViewMatchedLines ( ) ;
self . updateBalance ( ) ;
e . stopPropagation ( ) ;
} ,
unpartialReconcileLine : function ( line ) {
2014-06-02 00:28:15 +00:00
var self = this ;
2014-05-30 16:47:50 +00:00
if ( line . initial _amount > 0 ) {
line . debit = line . initial _amount ;
2014-06-02 00:28:15 +00:00
line . debit _str = self . formatCurrency ( line . debit , self . st _line . currency _id ) ;
2014-05-30 16:47:50 +00:00
} else {
line . credit = - 1 * line . initial _amount ;
2014-06-02 00:28:15 +00:00
line . credit _str = self . formatCurrency ( line . credit , self . st _line . currency _id ) ;
2014-05-30 16:47:50 +00:00
}
line . propose _partial _reconcile = true ;
line . partial _reconcile = false ;
} ,
updateBalance : function ( ) {
var self = this ;
var mv _lines _selected = self . get ( "mv_lines_selected" ) ;
2014-09-04 09:32:16 +00:00
var lines _selected _num = mv _lines _selected . length ;
// Undo partial reconciliation if necessary
2014-09-10 09:41:00 +00:00
if ( lines _selected _num !== 1 ) {
2014-09-04 09:32:16 +00:00
_ . each ( mv _lines _selected , function ( line ) {
if ( line . partial _reconcile === true ) self . unpartialReconcileLine ( line ) ;
if ( line . propose _partial _reconcile === true ) line . propose _partial _reconcile = false ;
} ) ;
self . updateAccountingViewMatchedLines ( ) ;
}
// Compute balance
2014-05-30 16:47:50 +00:00
var balance = 0 ;
balance -= self . st _line . amount ;
_ . each ( mv _lines _selected , function ( o ) {
balance = balance - o . debit + o . credit ;
} ) ;
_ . each ( self . getCreatedLines ( ) , function ( o ) {
balance += o . amount ;
} ) ;
2014-09-10 09:41:00 +00:00
// Dealing with floating-point
2014-09-04 09:32:16 +00:00
balance = Math . round ( balance * 1000 ) / 1000 ;
2014-12-05 14:10:32 +00:00
2014-05-30 16:47:50 +00:00
self . set ( "balance" , balance ) ;
} ,
2014-06-20 13:35:46 +00:00
2014-09-04 09:32:16 +00:00
// Loads move lines according to the widget's state
updateMatches : function ( ) {
2014-05-30 16:47:50 +00:00
var self = this ;
2014-09-04 09:32:16 +00:00
var deselected _lines _num = self . mv _lines _deselected . length ;
var offset = self . get ( "pager_index" ) * self . max _move _lines _displayed - deselected _lines _num ;
if ( offset < 0 ) offset = 0 ;
var limit = ( self . get ( "pager_index" ) + 1 ) * self . max _move _lines _displayed - deselected _lines _num ;
if ( limit > self . max _move _lines _displayed ) limit = self . max _move _lines _displayed ;
2014-09-12 13:28:50 +00:00
var excluded _ids = _ . collect ( self . get ( "mv_lines_selected" ) . concat ( self . mv _lines _deselected ) , function ( o ) { return o . id ; } ) ;
2014-09-19 14:25:18 +00:00
var globally _excluded _ids = [ ] ;
if ( self . st _line . has _no _partner )
_ . each ( self . getParent ( ) . excluded _move _lines _ids , function ( o ) { globally _excluded _ids = globally _excluded _ids . concat ( o ) } ) ;
else
globally _excluded _ids = self . getParent ( ) . excluded _move _lines _ids [ self . partner _id ] ;
2014-09-12 13:28:50 +00:00
if ( globally _excluded _ids !== undefined )
for ( var i = 0 ; i < globally _excluded _ids . length ; i ++ )
if ( excluded _ids . indexOf ( globally _excluded _ids [ i ] ) === - 1 )
excluded _ids . push ( globally _excluded _ids [ i ] ) ;
2014-09-04 09:32:16 +00:00
2014-09-19 14:25:18 +00:00
limit += 1 ; // Let's fetch 1 more item than requested
2014-09-04 09:32:16 +00:00
if ( limit > 0 ) {
2014-09-19 14:25:18 +00:00
return self . model _bank _statement _line
2014-09-04 09:32:16 +00:00
. call ( "get_move_lines_for_reconciliation_by_statement_line_id" , [ self . st _line . id , excluded _ids , self . filter , offset , limit ] )
. then ( function ( lines ) {
2014-09-19 14:25:18 +00:00
_ . each ( lines , function ( line ) { self . decorateMoveLine ( line , self . st _line . currency _id ) } , self ) ;
// If we could fetch 1 more item than what we'll display, that means there are move lines left to be displayed (so we enable the pager)
self . can _fetch _more _move _lines = ( lines . length === limit ) ;
self . set ( "mv_lines" , lines . slice ( 0 , limit - 1 ) ) ;
2014-09-04 09:32:16 +00:00
} ) ;
2014-09-19 14:25:18 +00:00
} else {
self . set ( "mv_lines" , [ ] ) ;
2014-09-04 09:32:16 +00:00
}
2014-05-30 16:47:50 +00:00
} ,
2014-09-04 09:32:16 +00:00
2014-05-30 16:47:50 +00:00
// Changes the partner_id of the statement_line in the DB and reloads the widget
2014-09-19 14:25:18 +00:00
changePartner : function ( partner _id ) {
2014-05-30 16:47:50 +00:00
var self = this ;
self . is _consistent = false ;
return self . model _bank _statement _line
// Update model
. call ( "write" , [ [ self . st _line _id ] , { 'partner_id' : partner _id } ] )
. then ( function ( ) {
2014-09-04 09:32:16 +00:00
self . do _load _reconciliation _proposition = false ; // of the server might set the statement line's partner
2014-09-16 15:15:54 +00:00
self . animation _speed = 0 ;
2014-05-30 16:47:50 +00:00
return $ . when ( self . restart ( self . get ( "mode" ) ) ) . then ( function ( ) {
2014-09-04 09:32:16 +00:00
self . do _load _reconciliation _proposition = true ;
2014-05-30 16:47:50 +00:00
self . is _consistent = true ;
2014-09-04 09:32:16 +00:00
self . set ( "mode" , "match" ) ;
2014-05-30 16:47:50 +00:00
} ) ;
} ) ;
} ,
// Returns an object that can be passed to process_reconciliation()
prepareSelectedMoveLineForPersisting : function ( line ) {
return {
name : line . name ,
debit : line . debit ,
credit : line . credit ,
counterpart _move _line _id : line . id ,
} ;
} ,
// idem
prepareCreatedMoveLineForPersisting : function ( line ) {
var dict = { } ;
if ( dict [ 'account_id' ] === undefined )
dict [ 'account_id' ] = line . account _id ;
dict [ 'name' ] = line . label ;
2014-07-11 15:15:34 +00:00
var amount = line . tax _id ? line . amount _with _tax : line . amount ;
if ( amount > 0 ) dict [ 'credit' ] = amount ;
if ( amount < 0 ) dict [ 'debit' ] = - 1 * amount ;
if ( line . tax _id ) dict [ 'account_tax_id' ] = line . tax _id ;
if ( line . is _tax _line ) dict [ 'is_tax_line' ] = line . is _tax _line ;
2014-05-30 16:47:50 +00:00
if ( line . analytic _account _id ) dict [ 'analytic_account_id' ] = line . analytic _account _id ;
return dict ;
} ,
// idem
prepareOpenBalanceForPersisting : function ( ) {
var balance = this . get ( "balance" ) ;
var dict = { } ;
dict [ 'account_id' ] = this . st _line . open _balance _account _id ;
2014-12-17 11:36:20 +00:00
dict [ 'name' ] = this . st _line . name + ' : ' + _t ( "Open balance" ) ;
2014-05-30 16:47:50 +00:00
if ( balance > 0 ) dict [ 'debit' ] = balance ;
if ( balance < 0 ) dict [ 'credit' ] = - 1 * balance ;
return dict ;
} ,
2014-09-16 15:15:54 +00:00
makeMoveLineDicts : function ( ) {
var self = this ;
var mv _line _dicts = [ ] ;
_ . each ( self . get ( "mv_lines_selected" ) , function ( o ) { mv _line _dicts . push ( self . prepareSelectedMoveLineForPersisting ( o ) ) } ) ;
_ . each ( self . getCreatedLines ( ) , function ( o ) { mv _line _dicts . push ( self . prepareCreatedMoveLineForPersisting ( o ) ) } ) ;
if ( Math . abs ( self . get ( "balance" ) ) . toFixed ( 3 ) !== "0.000" ) mv _line _dicts . push ( self . prepareOpenBalanceForPersisting ( ) ) ;
return mv _line _dicts ;
} ,
2014-05-30 16:47:50 +00:00
// Persist data, notify parent view and terminate widget
2014-09-04 09:32:16 +00:00
persistAndDestroy : function ( speed ) {
2014-05-30 16:47:50 +00:00
var self = this ;
2014-09-04 09:32:16 +00:00
speed = ( isNaN ( speed ) ? self . animation _speed : speed ) ;
2014-05-30 16:47:50 +00:00
if ( ! self . is _consistent ) return ;
2014-09-04 09:32:16 +00:00
2014-05-30 16:47:50 +00:00
// Sliding animation
var height = self . $el . outerHeight ( ) ;
var container = $ ( "<div />" ) ;
container . css ( "height" , height )
. css ( "marginTop" , self . $el . css ( "marginTop" ) )
. css ( "marginBottom" , self . $el . css ( "marginBottom" ) ) ;
self . $el . wrap ( container ) ;
2014-09-04 09:32:16 +00:00
var deferred _animation = self . $el . parent ( ) . slideUp ( speed * height / 150 ) ;
2014-05-30 16:47:50 +00:00
// RPC
2014-11-26 08:44:50 +00:00
self . $ ( ".button_ok" ) . attr ( "disabled" , "disabled" ) ;
2014-09-16 15:15:54 +00:00
return self . model _bank _statement _line
. call ( "process_reconciliation" , [ self . st _line _id , self . makeMoveLineDicts ( ) ] )
2014-11-26 08:44:50 +00:00
. done ( function ( ) {
2014-09-17 10:10:01 +00:00
self . getParent ( ) . unexcludeMoveLines ( self , self . partner _id , self . get ( "mv_lines_selected" ) ) ;
2014-05-30 16:47:50 +00:00
$ . each ( self . $ ( ".bootstrap_popover" ) , function ( ) { $ ( this ) . popover ( 'destroy' ) } ) ;
return $ . when ( deferred _animation ) . then ( function ( ) {
self . $el . parent ( ) . remove ( ) ;
var parent = self . getParent ( ) ;
return $ . when ( self . destroy ( ) ) . then ( function ( ) {
parent . childValidated ( self ) ;
} ) ;
} ) ;
2014-11-26 08:44:50 +00:00
} ) . fail ( function ( ) {
2014-09-04 09:32:16 +00:00
self . $el . parent ( ) . slideDown ( speed * height / 150 , function ( ) {
2014-05-30 16:47:50 +00:00
self . $el . unwrap ( ) ;
} ) ;
2014-11-26 08:44:50 +00:00
} ) . always ( function ( ) {
self . $ ( ".button_ok" ) . removeAttr ( "disabled" ) ;
2014-05-30 16:47:50 +00:00
} ) ;
2014-09-04 09:32:16 +00:00
} ,
2014-05-30 16:47:50 +00:00
} ) ;
2012-10-15 15:33:39 +00:00
instance . web . views . add ( 'tree_account_reconciliation' , 'instance.web.account.ReconciliationListView' ) ;
2012-09-13 16:09:48 +00:00
instance . web . account . ReconciliationListView = instance . web . ListView . extend ( {
init : function ( ) {
this . _super . apply ( this , arguments ) ;
2012-09-21 10:11:22 +00:00
var self = this ;
2012-09-17 09:55:18 +00:00
this . current _partner = null ;
2012-10-22 10:39:15 +00:00
this . on ( 'record_selected' , this , function ( ) {
2012-09-21 10:11:22 +00:00
if ( self . get _selected _ids ( ) . length === 0 ) {
self . $ ( ".oe_account_recon_reconcile" ) . attr ( "disabled" , "" ) ;
} else {
self . $ ( ".oe_account_recon_reconcile" ) . removeAttr ( "disabled" ) ;
}
} ) ;
2012-09-14 13:06:30 +00:00
} ,
2012-10-19 10:53:04 +00:00
load _list : function ( ) {
2012-09-17 12:53:09 +00:00
var self = this ;
2012-09-14 13:06:30 +00:00
var tmp = this . _super . apply ( this , arguments ) ;
2012-09-17 12:53:09 +00:00
if ( this . partners ) {
2012-09-17 12:04:42 +00:00
this . $el . prepend ( QWeb . render ( "AccountReconciliation" , { widget : this } ) ) ;
2012-09-17 13:49:57 +00:00
this . $ ( ".oe_account_recon_previous" ) . click ( function ( ) {
2013-04-18 15:13:53 +00:00
self . current _partner = ( ( ( self . current _partner - 1 ) % self . partners . length ) + self . partners . length ) % self . partners . length ;
2012-09-17 12:53:09 +00:00
self . search _by _partner ( ) ;
} ) ;
2012-09-17 13:49:57 +00:00
this . $ ( ".oe_account_recon_next" ) . click ( function ( ) {
2012-09-17 12:53:09 +00:00
self . current _partner = ( self . current _partner + 1 ) % self . partners . length ;
self . search _by _partner ( ) ;
} ) ;
2012-09-17 13:49:57 +00:00
this . $ ( ".oe_account_recon_reconcile" ) . click ( function ( ) {
2012-09-17 12:53:09 +00:00
self . reconcile ( ) ;
} ) ;
2012-09-20 16:22:57 +00:00
this . $ ( ".oe_account_recom_mark_as_reconciled" ) . click ( function ( ) {
self . mark _as _reconciled ( ) ;
} ) ;
2012-09-17 12:53:09 +00:00
}
2012-09-14 13:06:30 +00:00
return tmp ;
} ,
2012-09-14 15:31:33 +00:00
do _search : function ( domain , context , group _by ) {
2012-09-17 08:41:30 +00:00
var self = this ;
this . last _domain = domain ;
this . last _context = context ;
this . last _group _by = group _by ;
this . old _search = _ . bind ( this . _super , this ) ;
2012-09-20 12:20:53 +00:00
var mod = new instance . web . Model ( "account.move.line" , context , domain ) ;
2012-11-12 09:36:09 +00:00
return mod . call ( "list_partners_to_reconcile" , [ ] ) . then ( function ( result ) {
2012-09-17 13:49:57 +00:00
var current = self . current _partner !== null ? self . partners [ self . current _partner ] [ 0 ] : null ;
2012-09-20 12:20:53 +00:00
self . partners = result ;
2012-09-17 12:53:09 +00:00
var index = _ . find ( _ . range ( self . partners . length ) , function ( el ) {
if ( current === self . partners [ el ] [ 0 ] )
return true ;
} ) ;
if ( index !== undefined )
self . current _partner = index ;
else
self . current _partner = self . partners . length == 0 ? null : 0 ;
2012-09-17 09:55:18 +00:00
self . search _by _partner ( ) ;
2012-09-14 15:31:33 +00:00
} ) ;
} ,
2012-09-17 09:55:18 +00:00
search _by _partner : function ( ) {
2012-09-21 12:59:17 +00:00
var self = this ;
2012-09-21 13:08:16 +00:00
var fct = function ( ) {
2012-09-21 12:59:17 +00:00
return self . old _search ( new instance . web . CompoundDomain ( self . last _domain ,
[ [ "partner_id" , "in" , self . current _partner === null ? [ ] :
[ self . partners [ self . current _partner ] [ 0 ] ] ] ] ) , self . last _context , self . last _group _by ) ;
2012-09-21 13:08:16 +00:00
} ;
if ( self . current _partner === null ) {
self . last _reconciliation _date = _t ( "Never" ) ;
return fct ( ) ;
} else {
return new instance . web . Model ( "res.partner" ) . call ( "read" ,
2012-11-12 09:36:09 +00:00
[ self . partners [ self . current _partner ] [ 0 ] , [ "last_reconciliation_date" ] ] ) . then ( function ( res ) {
2012-09-21 13:08:16 +00:00
self . last _reconciliation _date =
instance . web . format _value ( res . last _reconciliation _date , { "type" : "datetime" } , _t ( "Never" ) ) ;
return fct ( ) ;
} ) ;
}
2012-09-17 09:55:18 +00:00
} ,
2012-09-17 12:53:09 +00:00
reconcile : function ( ) {
var self = this ;
var ids = this . get _selected _ids ( ) ;
2012-09-17 13:49:57 +00:00
if ( ids . length === 0 ) {
2014-04-10 15:50:22 +00:00
new instance . web . Dialog ( this , {
2012-09-17 13:49:57 +00:00
title : _t ( "Warning" ) ,
2014-04-11 12:28:40 +00:00
size : 'medium' ,
2014-04-10 15:50:22 +00:00
} , $ ( "<div />" ) . text ( _t ( "You must choose at least one record." ) ) ) . open ( ) ;
2012-09-17 13:49:57 +00:00
return false ;
}
2012-11-12 09:36:09 +00:00
new instance . web . Model ( "ir.model.data" ) . call ( "get_object_reference" , [ "account" , "action_view_account_move_line_reconcile" ] ) . then ( function ( result ) {
2012-09-17 13:49:57 +00:00
var additional _context = _ . extend ( {
active _id : ids [ 0 ] ,
active _ids : ids ,
active _model : self . model
} ) ;
return self . rpc ( "/web/action/load" , {
action _id : result [ 1 ] ,
context : additional _context
2012-11-12 09:36:09 +00:00
} ) . done ( function ( result ) {
2012-12-19 17:40:09 +00:00
result . context = instance . web . pyeval . eval ( 'contexts' , [ result . context , additional _context ] ) ;
2012-09-17 13:49:57 +00:00
result . flags = result . flags || { } ;
result . flags . new _window = true ;
2012-10-17 14:56:39 +00:00
return self . do _action ( result , {
on _close : function ( ) {
self . do _search ( self . last _domain , self . last _context , self . last _group _by ) ;
}
2012-09-17 13:49:57 +00:00
} ) ;
} ) ;
} ) ;
2012-09-17 12:53:09 +00:00
} ,
2012-09-20 16:22:57 +00:00
mark _as _reconciled : function ( ) {
var self = this ;
var id = self . partners [ self . current _partner ] [ 0 ] ;
2012-11-12 09:36:09 +00:00
new instance . web . Model ( "res.partner" ) . call ( "mark_as_reconciled" , [ [ id ] ] ) . then ( function ( ) {
2012-09-20 16:22:57 +00:00
self . do _search ( self . last _domain , self . last _context , self . last _group _by ) ;
} ) ;
} ,
2012-10-19 10:53:04 +00:00
do _select : function ( ids , records ) {
2012-10-22 10:39:15 +00:00
this . trigger ( 'record_selected' )
2012-10-19 10:53:04 +00:00
this . _super . apply ( this , arguments ) ;
} ,
2012-09-13 16:09:48 +00:00
} ) ;
2012-11-12 09:36:09 +00:00
2012-09-20 13:00:28 +00:00
} ;