Merge lp:~openerp-dev/openobject-addons/trunk-bank-reconciliation-ama into lp:openobject-addons

Proposed by Martin Trigaux (OpenERP)
Status: Work in progress
Proposed branch: lp:~openerp-dev/openobject-addons/trunk-bank-reconciliation-ama
Merge into: lp:openobject-addons
Diff against target: 5080 lines (+3418/-810)
38 files modified
account/__openerp__.py (+3/-0)
account/account.py (+5/-0)
account/account_bank_statement.py (+370/-197)
account/account_invoice.py (+1/-1)
account/account_move_line.py (+7/-5)
account/account_unit_test.xml (+2/-2)
account/account_view.xml (+126/-42)
account/demo/account_bank_statement.xml (+85/-0)
account/demo/account_invoice_demo.xml (+130/-0)
account/security/ir.model.access.csv (+101/-100)
account/static/src/css/account_bank_statement_reconciliation.css (+264/-0)
account/static/src/css/account_bank_statement_reconciliation.scss (+447/-0)
account/static/src/js/account_widgets.js (+1468/-0)
account/static/src/xml/account_bank_statement_reconciliation.xml (+194/-0)
account/views/account.xml (+2/-1)
account/wizard/__init__.py (+2/-4)
account/wizard/account_statement_from_invoice.py (+4/-43)
account/wizard/pos_box.py (+0/-2)
account_analytic_plans/__openerp__.py (+1/-0)
account_analytic_plans/account_analytic_plans_view.xml (+20/-52)
account_analytic_plans/static/src/js/account_bank_reconciliation.js (+35/-0)
account_analytic_plans/views/account_analytic_plans.xml (+12/-0)
account_bank_statement_extensions/account_bank_statement_view.xml (+2/-10)
account_payment/wizard/account_payment_populate_statement.py (+0/-3)
account_voucher/__init__.py (+0/-1)
account_voucher/__openerp__.py (+0/-1)
account_voucher/account_voucher.py (+0/-110)
account_voucher/account_voucher_view.xml (+1/-53)
account_voucher/wizard/__init__.py (+0/-24)
l10n_be_coda/__openerp__.py (+29/-29)
l10n_be_coda/l10n_be_coda_demo.xml (+36/-0)
l10n_be_coda/l10n_be_coda_view.xml (+1/-9)
l10n_be_coda/l10n_be_coda_wizard.xml (+0/-1)
l10n_be_coda/wizard/account_coda_import.py (+51/-77)
point_of_sale/point_of_sale.py (+1/-19)
point_of_sale/point_of_sale_view.xml (+0/-7)
point_of_sale/test/account_statement_reports.yml (+16/-15)
stock/stock.py (+2/-2)
To merge this branch: bzr merge lp:~openerp-dev/openobject-addons/trunk-bank-reconciliation-ama
Reviewer Review Type Date Requested Status
OpenERP Core Team Pending
Review via email: mp+218970@code.launchpad.net
To post a comment you must log in.
9282. By Arthur Maniet

[FIX] reconciliation persistance logic

9283. By Arthur Maniet

[MERGE] with trunk

9284. By Arthur Maniet

[IMP] the form in bankStatementReconciliationLine is now fully extensible

9285. By Arthur Maniet

[add] partial reconciliation

9286. By Arthur Maniet

[ADD] to account_analytic_plans files to extend account.bankStatementReconciliationLine widget
[FIX] temporary account in coda import wizard removed
[IMP] move lines unicity in reconciliation more gracefully enforced

9287. By Arthur Maniet

merged with self, somehow

9288. By Arthur Maniet

a

9289. By Arthur Maniet

[IMP] fields in the create line form can be hidden depending on group ; account_analytic_plans correctly updates the form

9290. By Arthur Maniet

[FIX] bank statement can be closed
[FIX] tests depending on bank statement (line)

9291. By Arthur Maniet

[FIX] point_of_sale/test/account_statement_reports.yml

9292. By Arthur Maniet

idem

9293. By Arthur Maniet

bis repetita

9294. By Arthur Maniet

ad nauseam

9295. By Arthur Maniet

nauseam

9296. By Arthur Maniet

a

9297. By Arthur Maniet

a

9298. By Arthur Maniet

a

9299. By Arthur Maniet

a

9300. By Arthur Maniet

a

9301. By Arthur Maniet

a

9302. By Arthur Maniet

[IMP] first batch of reconciliations now fetched in one request

9303. By Arthur Maniet

a

9304. By Arthur Maniet

a

9305. By Arthur Maniet

[FIX] point_of_sale/test/account_statement_reports.yml seems to be ok now, finally

9306. By Arthur Maniet

a

9307. By Arthur Maniet

a

9308. By Arthur Maniet

a

9309. By Arthur Maniet

[FIX] partner change went buggy

9310. By Arthur Maniet

[FIX] field Analytic Distribution added to reconciliation widget by account_analytic_plan

9311. By Arthur Maniet

[IMP] progress bar includes previous reconciliations

9312. By Arthur Maniet

[ADD] class account_bank_reconciliation_move_preset
[IMP] form to create line and presets are totally extensible

9313. By Arthur Maniet

[ADD] Tax on a created line now appears as a separate line

9314. By Arthur Maniet

[ADD]ed a menu to edit presets ; accessible with technical features

9315. By Arthur Maniet

[IMP] needaction badge updated whichever menu item is selected
[ADD] multicurrency fields to bank statement lines form
[FIX] javascript float precision === 0 fail
[FIX] widget consistency about no_match

9316. By Arthur Maniet

[IMP] account_bank_reconciliation_move_preset and many misc improvements

9317. By Arthur Maniet

[IMP] account.bank.reconciliation.move.preset usage

9318. By Arthur Maniet

[ADD] access rights
[FIX] bak.statement.move.preset renamed in statement.operation.template

9319. By Arthur Maniet

[IMP] account_statement_operation_template's form view
[FIX] misc

9320. By Arthur Maniet

[ADD] demo data

9321. By Quentin (OpenERP) <email address hidden>

[MERGE] trunk

9322. By Quentin (OpenERP) <email address hidden>

[FIX/IMP] fixes/improvements made during the code review

9323. By Arthur Maniet

[FIX] small stuff

9324. By Quentin (OpenERP) <email address hidden>

[FIX] fixed error in statement form view

9325. By Quentin (OpenERP) <email address hidden>

[FIX] import invoice button in bank statement

9326. By Quentin (OpenERP) <email address hidden>

[REF] moved the wizard to import invoices on bank statements in account from account_voucher because it doesn't need the vouchers anymore for the reconciliation process

9327. By Quentin (OpenERP) <email address hidden>

[REF] merged account_move_reconciliation.js and account_bank_statement_reconciliation.js into accont_widgets.js as they both were defining openerp.account (which lead to overriding and only the last was succesfully loaded)

9328. By Quentin (OpenERP) <email address hidden>

[FIX] installation of account module

9329. By Quentin (OpenERP) <email address hidden>

[IMP] account: invoice order improved

9330. By Quentin (OpenERP) <email address hidden>

[FIX] account: error in unit_test data

9331. By Quentin (OpenERP) <email address hidden>

[REF] account: reordered demo data + fixed error in bank statement balance

9332. By Quentin (OpenERP) <email address hidden>

[FIX] account: set the good group on analytic field

9333. By Quentin (OpenERP) <email address hidden>

[IMP] account: formated the monetary field accordingly to the currency symbol and position for initial and counterpart lines (created and open balance lines are still to do)

9334. By Quentin (OpenERP) <email address hidden>

[FIX] account, bank statement reconciliation: display the amount of proposed counterparts in the statement currency

9335. By Quentin (OpenERP) <email address hidden>

[REF] account, bank statement reconciliation: refactoring on accounting entries creation

9336. By Quentin (OpenERP) <email address hidden>

[REF] account: removed uneeded code

9337. By Quentin (OpenERP) <email address hidden>

[IMP] l10n_be_coda: added demo data in order to be able to import the coda test file embedded in the module

9338. By Arthur Maniet

[FIX] currency format in the widget

9339. By Quentin (OpenERP) <email address hidden>

[FIX] account: tax computation doesn't accept context (hu?)

9340. By Quentin (OpenERP) <email address hidden>

[FIX] account: mising arguments

9341. By Arthur Maniet

[IMP] success message

9342. By Quentin (OpenERP) <email address hidden>

[FIX] account, reconciliation on bank statement process: accounting entries creation in multi-currency + do not filter lines created by previous bank statement

9343. By Arthur Maniet

[FIX] partial reconciliation showing when there are created lines

9344. By Arthur Maniet

[FIX] stupidity

9345. By Quentin (OpenERP) <email address hidden>

[IMP] account

9346. By Quentin (OpenERP) <email address hidden>

[FIX] account: bug introduced in previous revision

9347. By Arthur Maniet

[FIX] popover (hopefully) don't stay freezed when their originator is destroyed
      amount formatting
      use correct account for tax move lines
      (probably fixed) : open balance rounding error

9348. By Arthur Maniet

[FIX] event handlers on UI that went buggy when the UI was not up to date to the model because of async calls (tested on raspberry pi ; experienced pain).

9349. By Arthur Maniet

[FIX] do not use a value where a list is expected
      removed empty account_bank_statement_reconciliation.js
   can't validate a reconciliation while changing the partner

9350. By Arthur Maniet

[FIX] when changing a reconciliation line's partner, the move lines selected weren't freed for other reconciliations

9351. By Quentin (OpenERP) <email address hidden>

[FIX] account: preserve sign of amounts when applying presets

9352. By Quentin (OpenERP) <email address hidden>

[IMP] account: usabiltiy in bank statement form view

9353. By Quentin (OpenERP) <email address hidden>

[FIX] account, bank statement reconciliation: multi currency issue fixed

9354. By Quentin (OpenERP) <email address hidden>

[FIX] account, bank statement reconciliation: fixed filter on change partner field

9355. By Quentin (OpenERP) <email address hidden>

[IMP] account, bank statement reconciliation: improved demo data for operation templates

9356. By Quentin (OpenERP) <email address hidden>

[FIX] account, bank statement reconciliation: display only one of the lines that are already partially reconciled together

9357. By Quentin (OpenERP) <email address hidden>

[FIX] account, bank statement reconciliation: hopefully, the last fix related to muli-currency issues

Unmerged revisions

9357. By Quentin (OpenERP) <email address hidden>

[FIX] account, bank statement reconciliation: hopefully, the last fix related to muli-currency issues

9356. By Quentin (OpenERP) <email address hidden>

[FIX] account, bank statement reconciliation: display only one of the lines that are already partially reconciled together

9355. By Quentin (OpenERP) <email address hidden>

[IMP] account, bank statement reconciliation: improved demo data for operation templates

9354. By Quentin (OpenERP) <email address hidden>

[FIX] account, bank statement reconciliation: fixed filter on change partner field

9353. By Quentin (OpenERP) <email address hidden>

[FIX] account, bank statement reconciliation: multi currency issue fixed

9352. By Quentin (OpenERP) <email address hidden>

[IMP] account: usabiltiy in bank statement form view

9351. By Quentin (OpenERP) <email address hidden>

[FIX] account: preserve sign of amounts when applying presets

9350. By Arthur Maniet

[FIX] when changing a reconciliation line's partner, the move lines selected weren't freed for other reconciliations

9349. By Arthur Maniet

[FIX] do not use a value where a list is expected
      removed empty account_bank_statement_reconciliation.js
   can't validate a reconciliation while changing the partner

9348. By Arthur Maniet

[FIX] event handlers on UI that went buggy when the UI was not up to date to the model because of async calls (tested on raspberry pi ; experienced pain).

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'account/__openerp__.py'
--- account/__openerp__.py 2014-04-29 15:41:04 +0000
+++ account/__openerp__.py 2014-05-30 16:18:57 +0000
@@ -65,6 +65,7 @@
65 'wizard/account_period_close_view.xml',65 'wizard/account_period_close_view.xml',
66 'wizard/account_reconcile_view.xml',66 'wizard/account_reconcile_view.xml',
67 'wizard/account_unreconcile_view.xml',67 'wizard/account_unreconcile_view.xml',
68 'wizard/account_statement_from_invoice_view.xml',
68 'account_view.xml',69 'account_view.xml',
69 'account_report.xml',70 'account_report.xml',
70 'account_financial_report_data.xml',71 'account_financial_report_data.xml',
@@ -144,6 +145,7 @@
144 'qweb' : [145 'qweb' : [
145 "static/src/xml/account_move_reconciliation.xml",146 "static/src/xml/account_move_reconciliation.xml",
146 "static/src/xml/account_move_line_quickadd.xml",147 "static/src/xml/account_move_line_quickadd.xml",
148 "static/src/xml/account_bank_statement_reconciliation.xml",
147 ],149 ],
148 'demo': [150 'demo': [
149 'demo/account_demo.xml',151 'demo/account_demo.xml',
@@ -151,6 +153,7 @@
151 'project/analytic_account_demo.xml',153 'project/analytic_account_demo.xml',
152 'demo/account_minimal.xml',154 'demo/account_minimal.xml',
153 'demo/account_invoice_demo.xml',155 'demo/account_invoice_demo.xml',
156 'demo/account_bank_statement.xml',
154 'account_unit_test.xml',157 'account_unit_test.xml',
155 ],158 ],
156 'test': [159 'test': [
157160
=== modified file 'account/account.py'
--- account/account.py 2014-04-24 13:45:33 +0000
+++ account/account.py 2014-05-30 16:18:57 +0000
@@ -2073,6 +2073,11 @@
2073 cur_price_unit+=amount22073 cur_price_unit+=amount2
2074 return res2074 return res
20752075
2076 def compute_for_bank_reconciliation(self, cr, uid, tax_id, amount, context=None):
2077 """ Called by RPC by the bank statement reconciliation widget """
2078 tax = self.browse(cr, uid, tax_id, context=context)
2079 return self.compute_all(cr, uid, [tax], amount, 1) # TOCHECK may use force_exclude parameter
2080
2076 def compute_all(self, cr, uid, taxes, price_unit, quantity, product=None, partner=None, force_excluded=False):2081 def compute_all(self, cr, uid, taxes, price_unit, quantity, product=None, partner=None, force_excluded=False):
2077 """2082 """
2078 :param force_excluded: boolean used to say that we don't want to consider the value of field price_include of2083 :param force_excluded: boolean used to say that we don't want to consider the value of field price_include of
20792084
=== modified file 'account/account_bank_statement.py'
--- account/account_bank_statement.py 2014-02-10 06:46:42 +0000
+++ account/account_bank_statement.py 2014-05-30 16:18:57 +0000
@@ -19,11 +19,10 @@
19#19#
20##############################################################################20##############################################################################
2121
22import time
23
24from openerp.osv import fields, osv22from openerp.osv import fields, osv
25from openerp.tools.translate import _23from openerp.tools.translate import _
26import openerp.addons.decimal_precision as dp24import openerp.addons.decimal_precision as dp
25from openerp.report import report_sxw
2726
28class account_bank_statement(osv.osv):27class account_bank_statement(osv.osv):
29 def create(self, cr, uid, vals, context=None):28 def create(self, cr, uid, vals, context=None):
@@ -66,6 +65,18 @@
66 return periods[0]65 return periods[0]
67 return False66 return False
6867
68 def _compute_default_statement_name(self, cr, uid, context=None):
69 if context is None:
70 context = {}
71 obj_seq = self.pool.get('ir.sequence')
72 default_journal_id = self._default_journal_id(cr, uid, context=context)
73 if default_journal_id != False:
74 period = self.pool.get('account.period').browse(cr, uid, self._get_period(cr, uid, context=context), context=context)
75 context['fiscalyear_id'] = period.fiscalyear_id.id
76 journal = self.pool.get('account.journal').browse(cr, uid, default_journal_id, None)
77 return obj_seq.next_by_id(cr, uid, journal.sequence_id.id, context=context)
78 return obj_seq.next_by_code(cr, uid, 'account.bank.statement', context=context)
79
69 def _currency(self, cursor, user, ids, name, args, context=None):80 def _currency(self, cursor, user, ids, name, args, context=None):
70 res = {}81 res = {}
71 res_currency_obj = self.pool.get('res.currency')82 res_currency_obj = self.pool.get('res.currency')
@@ -92,12 +103,18 @@
92 result[line.statement_id.id] = True103 result[line.statement_id.id] = True
93 return result.keys()104 return result.keys()
94105
106 def _all_lines_reconciled(self, cr, uid, ids, name, args, context=None):
107 res = {}
108 for statement in self.browse(cr, uid, ids, context=context):
109 res[statement.id] = all([line.journal_entry_id.id for line in statement.line_ids])
110 return res
111
95 _order = "date desc, id desc"112 _order = "date desc, id desc"
96 _name = "account.bank.statement"113 _name = "account.bank.statement"
97 _description = "Bank Statement"114 _description = "Bank Statement"
98 _inherit = ['mail.thread']115 _inherit = ['mail.thread']
99 _columns = {116 _columns = {
100 'name': fields.char('Reference', size=64, required=True, states={'draft': [('readonly', False)]}, readonly=True, help='if you give the Name other then /, its created Accounting Entries Move will be with same name as statement name. This allows the statement entries to have the same references than the statement itself'), # readonly for account_cash_statement117 'name': fields.char('Reference', size=64, states={'draft': [('readonly', False)]}, readonly=True, help='if you give the Name other then /, its created Accounting Entries Move will be with same name as statement name. This allows the statement entries to have the same references than the statement itself'), # readonly for account_cash_statement
101 'date': fields.date('Date', required=True, states={'confirm': [('readonly', True)]}, select=True),118 'date': fields.date('Date', required=True, states={'confirm': [('readonly', True)]}, select=True),
102 'journal_id': fields.many2one('account.journal', 'Journal', required=True,119 'journal_id': fields.many2one('account.journal', 'Journal', required=True,
103 readonly=True, states={'draft':[('readonly',False)]}),120 readonly=True, states={'draft':[('readonly',False)]}),
@@ -129,10 +146,11 @@
129 type='many2one', relation='res.currency'),146 type='many2one', relation='res.currency'),
130 'account_id': fields.related('journal_id', 'default_debit_account_id', type='many2one', relation='account.account', string='Account used in this journal', readonly=True, help='used in statement reconciliation domain, but shouldn\'t be used elswhere.'),147 'account_id': fields.related('journal_id', 'default_debit_account_id', type='many2one', relation='account.account', string='Account used in this journal', readonly=True, help='used in statement reconciliation domain, but shouldn\'t be used elswhere.'),
131 'cash_control': fields.related('journal_id', 'cash_control' , type='boolean', relation='account.journal',string='Cash control'),148 'cash_control': fields.related('journal_id', 'cash_control' , type='boolean', relation='account.journal',string='Cash control'),
149 'all_lines_reconciled': fields.function(_all_lines_reconciled, string='All lines reconciled', type='boolean'),
132 }150 }
133151
134 _defaults = {152 _defaults = {
135 'name': "/",153 'name': _compute_default_statement_name,
136 'date': fields.date.context_today,154 'date': fields.date.context_today,
137 'state': 'draft',155 'state': 'draft',
138 'journal_id': _default_journal_id,156 'journal_id': _default_journal_id,
@@ -193,37 +211,6 @@
193 'ref': st_line.ref,211 'ref': st_line.ref,
194 }212 }
195213
196 def _prepare_bank_move_line(self, cr, uid, st_line, move_id, amount, company_currency_id,
197 context=None):
198 """Compute the args to build the dict of values to create the bank move line from a
199 statement line by calling the _prepare_move_line_vals. This method may be
200 overridden to implement custom move generation (making sure to call super() to
201 establish a clean extension chain).
202
203 :param browse_record st_line: account.bank.statement.line record to
204 create the move from.
205 :param int/long move_id: ID of the account.move to link the move line
206 :param float amount: amount of the move line
207 :param int/long company_currency_id: ID of currency of the concerned company
208 :return: dict of value to create() the bank account.move.line
209 """
210 anl_id = st_line.analytic_account_id and st_line.analytic_account_id.id or False
211 debit = ((amount<0) and -amount) or 0.0
212 credit = ((amount>0) and amount) or 0.0
213 cur_id = False
214 amt_cur = False
215 if st_line.statement_id.currency.id <> company_currency_id:
216 cur_id = st_line.statement_id.currency.id
217 if st_line.account_id and st_line.account_id.currency_id and st_line.account_id.currency_id.id <> company_currency_id:
218 cur_id = st_line.account_id.currency_id.id
219 if cur_id:
220 res_currency_obj = self.pool.get('res.currency')
221 amt_cur = -res_currency_obj.compute(cr, uid, company_currency_id, cur_id, amount, context=context)
222
223 res = self._prepare_move_line_vals(cr, uid, st_line, move_id, debit, credit,
224 amount_currency=amt_cur, currency_id=cur_id, analytic_id=anl_id, context=context)
225 return res
226
227 def _get_counter_part_account(sefl, cr, uid, st_line, context=None):214 def _get_counter_part_account(sefl, cr, uid, st_line, context=None):
228 """Retrieve the account to use in the counterpart move.215 """Retrieve the account to use in the counterpart move.
229 This method may be overridden to implement custom move generation (making sure to216 This method may be overridden to implement custom move generation (making sure to
@@ -248,8 +235,7 @@
248 """235 """
249 return st_line.partner_id and st_line.partner_id.id or False236 return st_line.partner_id and st_line.partner_id.id or False
250237
251 def _prepare_counterpart_move_line(self, cr, uid, st_line, move_id, amount, company_currency_id,238 def _prepare_bank_move_line(self, cr, uid, st_line, move_id, amount, company_currency_id, context=None):
252 context=None):
253 """Compute the args to build the dict of values to create the counter part move line from a239 """Compute the args to build the dict of values to create the counter part move line from a
254 statement line by calling the _prepare_move_line_vals. This method may be240 statement line by calling the _prepare_move_line_vals. This method may be
255 overridden to implement custom move generation (making sure to call super() to241 overridden to implement custom move generation (making sure to call super() to
@@ -266,19 +252,22 @@
266 account_id = self._get_counter_part_account(cr, uid, st_line, context=context)252 account_id = self._get_counter_part_account(cr, uid, st_line, context=context)
267 partner_id = self._get_counter_part_partner(cr, uid, st_line, context=context)253 partner_id = self._get_counter_part_partner(cr, uid, st_line, context=context)
268 debit = ((amount > 0) and amount) or 0.0254 debit = ((amount > 0) and amount) or 0.0
269 credit = ((amount < 0) and -amount) or 0.0255 credit = ((amount < 0) and -amount) or 0.0
270 cur_id = False256 cur_id = False
271 amt_cur = False257 amt_cur = False
272 if st_line.statement_id.currency.id <> company_currency_id:258 if st_line.statement_id.currency.id != company_currency_id:
273 amt_cur = st_line.amount259 amt_cur = st_line.amount
274 cur_id = st_line.statement_id.currency.id260 cur_id = st_line.currency_id or st_line.statement_id.currency.id
261 # TODO : FIXME the amount should be in the journal currency
262 if st_line.currency_id and st_line.amount_currency:
263 amt_cur = st_line.amount_currency
264 cur_id = st_line.currency_id.id
275 return self._prepare_move_line_vals(cr, uid, st_line, move_id, debit, credit,265 return self._prepare_move_line_vals(cr, uid, st_line, move_id, debit, credit,
276 amount_currency = amt_cur, currency_id = cur_id, account_id = account_id,266 amount_currency=amt_cur, currency_id=cur_id, account_id=account_id,
277 partner_id = partner_id, context=context)267 partner_id=partner_id, context=context)
278268
279 def _prepare_move_line_vals(self, cr, uid, st_line, move_id, debit, credit, currency_id = False,269 def _prepare_move_line_vals(self, cr, uid, st_line, move_id, debit, credit, currency_id=False,
280 amount_currency= False, account_id = False, analytic_id = False,270 amount_currency=False, account_id=False, partner_id=False, context=None):
281 partner_id = False, context=None):
282 """Prepare the dict of values to create the move line from a271 """Prepare the dict of values to create the move line from a
283 statement line. All non-mandatory args will replace the default computed one.272 statement line. All non-mandatory args will replace the default computed one.
284 This method may be overridden to implement custom move generation (making sure to273 This method may be overridden to implement custom move generation (making sure to
@@ -293,7 +282,6 @@
293 :param float amount_currency: amount of the debit/credit expressed in the currency_id282 :param float amount_currency: amount of the debit/credit expressed in the currency_id
294 :param int/long account_id: ID of the account to use in the move line if different283 :param int/long account_id: ID of the account to use in the move line if different
295 from the statement line account ID284 from the statement line account ID
296 :param int/long analytic_id: ID of analytic account to put on the move line
297 :param int/long partner_id: ID of the partner to put on the move line285 :param int/long partner_id: ID of the partner to put on the move line
298 :return: dict of value to create() the account.move.line286 :return: dict of value to create() the account.move.line
299 """287 """
@@ -314,67 +302,8 @@
314 'period_id': st_line.statement_id.period_id.id,302 'period_id': st_line.statement_id.period_id.id,
315 'currency_id': amount_currency and cur_id,303 'currency_id': amount_currency and cur_id,
316 'amount_currency': amount_currency,304 'amount_currency': amount_currency,
317 'analytic_account_id': analytic_id,
318 }305 }
319306
320 def create_move_from_st_line(self, cr, uid, st_line_id, company_currency_id, st_line_number, context=None):
321 """Create the account move from the statement line.
322
323 :param int/long st_line_id: ID of the account.bank.statement.line to create the move from.
324 :param int/long company_currency_id: ID of the res.currency of the company
325 :param char st_line_number: will be used as the name of the generated account move
326 :return: ID of the account.move created
327 """
328
329 if context is None:
330 context = {}
331 res_currency_obj = self.pool.get('res.currency')
332 account_move_obj = self.pool.get('account.move')
333 account_move_line_obj = self.pool.get('account.move.line')
334 account_bank_statement_line_obj = self.pool.get('account.bank.statement.line')
335 st_line = account_bank_statement_line_obj.browse(cr, uid, st_line_id, context=context)
336 st = st_line.statement_id
337
338 context.update({'date': st_line.date})
339
340 move_vals = self._prepare_move(cr, uid, st_line, st_line_number, context=context)
341 move_id = account_move_obj.create(cr, uid, move_vals, context=context)
342 account_bank_statement_line_obj.write(cr, uid, [st_line.id], {
343 'move_ids': [(4, move_id, False)]
344 })
345 torec = []
346 acc_cur = ((st_line.amount<=0) and st.journal_id.default_debit_account_id) or st_line.account_id
347
348 context.update({
349 'res.currency.compute.account': acc_cur,
350 })
351 amount = res_currency_obj.compute(cr, uid, st.currency.id,
352 company_currency_id, st_line.amount, context=context)
353
354 bank_move_vals = self._prepare_bank_move_line(cr, uid, st_line, move_id, amount,
355 company_currency_id, context=context)
356 move_line_id = account_move_line_obj.create(cr, uid, bank_move_vals, context=context)
357 torec.append(move_line_id)
358
359 counterpart_move_vals = self._prepare_counterpart_move_line(cr, uid, st_line, move_id,
360 amount, company_currency_id, context=context)
361 account_move_line_obj.create(cr, uid, counterpart_move_vals, context=context)
362
363 for line in account_move_line_obj.browse(cr, uid, [x.id for x in
364 account_move_obj.browse(cr, uid, move_id,
365 context=context).line_id],
366 context=context):
367 if line.state <> 'valid':
368 raise osv.except_osv(_('Error!'),
369 _('Journal item "%s" is not valid.') % line.name)
370
371 # Bank statements will not consider boolean on journal entry_posted
372 account_move_obj.post(cr, uid, [move_id], context=context)
373 return move_id
374
375 def get_next_st_line_number(self, cr, uid, st_number, st_line, context=None):
376 return st_number + '/' + str(st_line.sequence)
377
378 def balance_check(self, cr, uid, st_id, journal_type='bank', context=None):307 def balance_check(self, cr, uid, st_id, journal_type='bank', context=None):
379 st = self.browse(cr, uid, st_id, context=context)308 st = self.browse(cr, uid, st_id, context=context)
380 if not ((abs((st.balance_end or 0.0) - st.balance_end_real) < 0.0001) or (abs((st.balance_end or 0.0) - st.balance_end_real) < 0.0001)):309 if not ((abs((st.balance_end or 0.0) - st.balance_end_real) < 0.0001) or (abs((st.balance_end or 0.0) - st.balance_end_real) < 0.0001)):
@@ -389,49 +318,30 @@
389 return state in ('draft','open')318 return state in ('draft','open')
390319
391 def button_confirm_bank(self, cr, uid, ids, context=None):320 def button_confirm_bank(self, cr, uid, ids, context=None):
392 obj_seq = self.pool.get('ir.sequence')
393 if context is None:321 if context is None:
394 context = {}322 context = {}
395323
396 for st in self.browse(cr, uid, ids, context=context):324 for st in self.browse(cr, uid, ids, context=context):
397 j_type = st.journal_id.type325 j_type = st.journal_id.type
398 company_currency_id = st.journal_id.company_id.currency_id.id
399 if not self.check_status_condition(cr, uid, st.state, journal_type=j_type):326 if not self.check_status_condition(cr, uid, st.state, journal_type=j_type):
400 continue327 continue
401328
402 self.balance_check(cr, uid, st.id, journal_type=j_type, context=context)329 self.balance_check(cr, uid, st.id, journal_type=j_type, context=context)
403 if (not st.journal_id.default_credit_account_id) \330 if (not st.journal_id.default_credit_account_id) \
404 or (not st.journal_id.default_debit_account_id):331 or (not st.journal_id.default_debit_account_id):
405 raise osv.except_osv(_('Configuration Error!'),332 raise osv.except_osv(_('Configuration Error!'), _('Please verify that an account is defined in the journal.'))
406 _('Please verify that an account is defined in the journal.'))
407
408 if not st.name == '/':
409 st_number = st.name
410 else:
411 c = {'fiscalyear_id': st.period_id.fiscalyear_id.id}
412 if st.journal_id.sequence_id:
413 st_number = obj_seq.next_by_id(cr, uid, st.journal_id.sequence_id.id, context=c)
414 else:
415 st_number = obj_seq.next_by_code(cr, uid, 'account.bank.statement', context=c)
416
417 for line in st.move_line_ids:333 for line in st.move_line_ids:
418 if line.state <> 'valid':334 if line.state <> 'valid':
419 raise osv.except_osv(_('Error!'),335 raise osv.except_osv(_('Error!'), _('The account entries lines are not in valid state.'))
420 _('The account entries lines are not in valid state.'))336 move_ids = []
421 for st_line in st.line_ids:337 for st_line in st.line_ids:
422 if st_line.analytic_account_id:
423 if not st.journal_id.analytic_journal_id:
424 raise osv.except_osv(_('No Analytic Journal!'),_("You have to assign an analytic journal on the '%s' journal!") % (st.journal_id.name,))
425 if not st_line.amount:338 if not st_line.amount:
426 continue339 continue
427 st_line_number = self.get_next_st_line_number(cr, uid, st_number, st_line, context)340 if not st_line.journal_entry_id.id:
428 self.create_move_from_st_line(cr, uid, st_line.id, company_currency_id, st_line_number, context)341 raise osv.except_osv(_('Error!'), _('All the account entries lines must be processed in order to close the statement.'))
429342 move_ids.append(st_line.journal_entry_id.id)
430 self.write(cr, uid, [st.id], {343 self.pool.get('account.move').post(cr, uid, move_ids, context=context)
431 'name': st_number,344 self.message_post(cr, uid, [st.id], body=_('Statement %s confirmed, journal items were created.') % (st.name,), context=context)
432 'balance_end_real': st.balance_end
433 }, context=context)
434 self.message_post(cr, uid, [st.id], body=_('Statement %s confirmed, journal items were created.') % (st_number,), context=context)
435 return self.write(cr, uid, ids, {'state':'confirm'}, context=context)345 return self.write(cr, uid, ids, {'state':'confirm'}, context=context)
436346
437 def button_cancel(self, cr, uid, ids, context=None):347 def button_cancel(self, cr, uid, ids, context=None):
@@ -492,93 +402,356 @@
492 return super(account_bank_statement, self).copy(cr, uid, id, default, context=context)402 return super(account_bank_statement, self).copy(cr, uid, id, default, context=context)
493403
494 def button_journal_entries(self, cr, uid, ids, context=None):404 def button_journal_entries(self, cr, uid, ids, context=None):
495 ctx = (context or {}).copy()405 ctx = (context or {}).copy()
496 ctx['journal_id'] = self.browse(cr, uid, ids[0], context=context).journal_id.id406 ctx['journal_id'] = self.browse(cr, uid, ids[0], context=context).journal_id.id
497 return {407 return {
498 'name': _('Journal Items'),408 'name': _('Journal Items'),
499 'view_type':'form',409 'view_type':'form',
500 'view_mode':'tree',410 'view_mode':'tree',
501 'res_model':'account.move.line',411 'res_model':'account.move.line',
502 'view_id':False,412 'view_id':False,
503 'type':'ir.actions.act_window',413 'type':'ir.actions.act_window',
504 'domain':[('statement_id','in',ids)],414 'domain':[('statement_id','in',ids)],
505 'context':ctx,415 'context':ctx,
506 }416 }
507417
418 def number_of_lines_reconciled(self, cr, uid, id, context=None):
419 bsl_obj = self.pool.get('account.bank.statement.line')
420 return bsl_obj.search_count(cr, uid, [('statement_id','=',id), ('journal_entry_id','!=',False)], context=context)
421
422 def get_format_currency_js_function(self, cr, uid, id, context=None):
423 """ Returns a string that can be used to instanciate a javascript function.
424 That function formats a number according to the statement's journal currency """
425 company_currency = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id
426 currency_obj = id and self.browse(cr, uid, id, context=context).journal_id.currency or company_currency
427 digits = 2 # TODO : from currency_obj
428 if currency_obj.position == 'after':
429 return "return amount.toFixed("+str(digits)+") + ' "+currency_obj.symbol+"';"
430 elif currency_obj.position == 'before':
431 return "return '"+currency_obj.symbol+" ' + amount.toFixed("+str(digits)+");"
508432
509class account_bank_statement_line(osv.osv):433class account_bank_statement_line(osv.osv):
510434
511 def onchange_partner_id(self, cr, uid, ids, partner_id, context=None):435 def get_data_for_reconciliations(self, cr, uid, ids, context=None):
512 obj_partner = self.pool.get('res.partner')436 """ Used to instanciate a batch of reconciliations in a single request """
513 if context is None:437 # Build a list of reconciliations data
514 context = {}438 ret = []
515 if not partner_id:439 mv_line_ids_selected = []
516 return {}440 for st_line_id in ids:
517 part = obj_partner.browse(cr, uid, partner_id, context=context)441 reconciliation_data = {
518 if not part.supplier and not part.customer:442 'st_line': self.get_statement_line_for_reconciliation(cr, uid, st_line_id, context),
519 type = 'general'443 'reconciliation_proposition': self.get_reconciliation_proposition(cr, uid, st_line_id, mv_line_ids_selected, context)
520 elif part.supplier and part.customer:444 }
521 type = 'general'445 for mv_line in reconciliation_data['reconciliation_proposition']:
522 else:446 mv_line_ids_selected.append(mv_line['id'])
523 if part.supplier == True:447 ret.append(reconciliation_data);
524 type = 'supplier'448
525 if part.customer == True:449 # Check if, now that 'candidate' move lines were selected, there are moves left for statement lines
526 type = 'customer'450 for reconciliation_data in ret:
527 res_type = self.onchange_type(cr, uid, ids, partner_id=partner_id, type=type, context=context)451 if not reconciliation_data['st_line']['has_no_partner']:
528 if res_type['value'] and res_type['value'].get('account_id', False):452 if self.get_move_lines_counterparts(cr, uid, reconciliation_data['st_line']['id'], excluded_ids=mv_line_ids_selected, count=True, context=context) == 0:
529 return {'value': {'type': type, 'account_id': res_type['value']['account_id']}}453 reconciliation_data['st_line']['no_match'] = True
530 return {'value': {'type': type}}454 return ret
531455
532 def onchange_type(self, cr, uid, line_id, partner_id, type, context=None):456 def get_statement_line_for_reconciliation(self, cr, uid, id, context=None):
533 res = {'value': {}}457 """ Returns the data required by the bank statement reconciliation use case """
534 obj_partner = self.pool.get('res.partner')458 line = self.browse(cr, uid, id, context=context)
535 if context is None:459 statement_currency = line.journal_id.currency or line.journal_id.company_id.currency_id
536 context = {}460 rml_parser = report_sxw.rml_parse(cr, uid, 'statement_line_widget', context=context)
537 if not partner_id:461 amount_str = line.amount > 0 and line.amount or -line.amount
538 return res462 amount_str = rml_parser.formatLang(amount_str, currency_obj=statement_currency)
539 account_id = False463 amount_currency_str = ""
540 line = self.browse(cr, uid, line_id, context=context)464 if line.amount_currency and line.currency_id:
541 if not line or (line and not line[0].account_id):465 amount_currency_str = rml_parser.formatLang(line.amount_currency, currency_obj=line.currency_id)
542 part = obj_partner.browse(cr, uid, partner_id, context=context)466
543 if type == 'supplier':467 dict = {
544 account_id = part.property_account_payable.id468 'id': line.id,
545 else:469 'ref': line.ref,
546 account_id = part.property_account_receivable.id470 'note': line.note or "",
547 res['value']['account_id'] = account_id471 'name': line.name,
548 return res472 'date': line.date,
473 'amount': line.amount,
474 'amount_str': amount_str,
475 'no_match': self.get_move_lines_counterparts(cr, uid, id, count=True, context=context) == 0 and line.partner_id.id,
476 'partner_id': line.partner_id.id,
477 'statement_id': line.statement_id.id,
478 'account_code': line.journal_id.default_debit_account_id.code,
479 'account_name': line.journal_id.default_debit_account_id.name,
480 'partner_name': line.partner_id.name,
481 'amount_currency_str': amount_currency_str,
482 'has_no_partner': not line.partner_id.id,
483 }
484 if line.partner_id.id:
485 if line.amount > 0:
486 dict['open_balance_account_id'] = line.partner_id.property_account_receivable.id
487 else:
488 dict['open_balance_account_id'] = line.partner_id.property_account_payable.id
489 return dict
490
491 def get_reconciliation_proposition(self, cr, uid, id, excluded_ids=[], context=None):
492 """ Returns move lines that constitute the best guess to reconcile a statement line. """
493 st_line = self.browse(cr, uid, id, context=context)
494 company_currency = st_line.journal_id.company_id.currency_id.id
495 statement_currency = st_line.journal_id.currency.id or company_currency
496
497 # either use the unsigned debit/credit fields or the signed amount_currency field
498 sign = 1
499 if statement_currency == company_currency:
500 if st_line.amount > 0:
501 amount_field = 'debit'
502 else:
503 amount_field = 'credit'
504 else:
505 amount_field = 'amount_currency'
506 if st_line.amount < 0:
507 sign = -1
508
509 # look for exact match
510 exact_match_id = self.get_move_lines_counterparts(cr, uid, id, excluded_ids=excluded_ids, limit=1, additional_domain=[(amount_field,'=',(sign*st_line.amount))])
511 if exact_match_id:
512 return exact_match_id
513
514 # select oldest move lines
515 if sign == -1:
516 mv_lines = self.get_move_lines_counterparts(cr, uid, id, excluded_ids=excluded_ids, limit=50, additional_domain=[(amount_field,'<',0)])
517 else:
518 mv_lines = self.get_move_lines_counterparts(cr, uid, id, excluded_ids=excluded_ids, limit=50, additional_domain=[(amount_field,'>',0)])
519 ret = []
520 total = 0
521 # get_move_lines_counterparts inverts debit and credit
522 amount_field = 'debit' if amount_field == 'credit' else 'credit'
523 for line in mv_lines:
524 if total + line[amount_field] <= st_line.amount:
525 ret.append(line)
526 total += line[amount_field]
527 else:
528 break
529
530 return ret
531
532 def get_move_lines_counterparts(self, cr, uid, id, excluded_ids=[], str="", offset=0, limit=None, count=False, additional_domain=[], context=None):
533 """ Find the move lines that could be used to reconcile a statement line and returns the counterpart that could be created to reconcile them
534 If count is true, only returns the count.
535
536 :param integer id: the id of the statement line
537 :param integers list excluded_ids: ids of move lines that should not be fetched
538 :param string str: string to filter lines
539 :param integer offset: offset of the request
540 :param integer limit: number of lines to fetch
541 :param boolean count: just return the number of records
542 :param tuples list domain: additional domain restrictions
543 """
544 if context is None:
545 context = {}
546
547 rml_parser = report_sxw.rml_parse(cr, uid, 'statement_line_counterpart_widget', context=context)
548 st_line = self.browse(cr, uid, id, context=context)
549 company_currency = st_line.journal_id.company_id.currency_id
550 statement_currency = st_line.journal_id.currency or company_currency
551 mv_line_pool = self.pool.get('account.move.line')
552 currency_obj = self.pool.get('res.currency')
553
554 domain = additional_domain + [
555 ('partner_id', '=', st_line.partner_id.id),
556 ('reconcile_id', '=', False),
557 ('state','=','valid'),
558 '|',('account_id.type', '=', 'receivable'),
559 ('account_id.type', '=', 'payable'), #Let the front-end warn the user if he tries to mix payable and receivable in the same reconciliation
560 ]
561 if excluded_ids:
562 domain.append(('id', 'not in', excluded_ids))
563 if str:
564 domain += ['|', ('move_id.name', 'ilike', str), ('move_id.ref', 'ilike', str)]
565 #partially reconciled lines can be displayed only once
566 reconcile_partial_ids = []
567 ids = mv_line_pool.search(cr, uid, domain, offset=offset, limit=limit, order="date_maturity asc, id asc", context=context)
568
569 if count:
570 nb_lines = 0
571 for line in mv_line_pool.browse(cr, uid, ids, context=context):
572 if line.reconcile_partial_id and line.reconcile_partial_id.id in reconcile_partial_ids:
573 continue
574 nb_lines += 1
575 if line.reconcile_partial_id:
576 reconcile_partial_ids.append(line.reconcile_partial_id.id)
577 return nb_lines
578 else:
579 ret = []
580 for line in mv_line_pool.browse(cr, uid, ids, context=context):
581 if line.reconcile_partial_id and line.reconcile_partial_id.id in reconcile_partial_ids:
582 continue
583 amount_currency_str = ""
584 if line.currency_id and line.amount_currency:
585 amount_currency_str = rml_parser.formatLang(line.amount_currency, currency_obj=line.currency_id)
586 ret_line = {
587 'id': line.id,
588 'name': line.move_id.name,
589 'ref': line.move_id.ref,
590 'account_code': line.account_id.code,
591 'account_name': line.account_id.name,
592 'account_type': line.account_id.type,
593 'date_maturity': line.date_maturity,
594 'date': line.date,
595 'period_name': line.period_id.name,
596 'journal_name': line.journal_id.name,
597 'amount_currency_str': amount_currency_str,
598 }
599 if statement_currency.id != company_currency.id and line.currency_id and line.currency_id.id == statement_currency.id:
600 if line.amount_residual_currency < 0:
601 ret_line['debit'] = 0
602 ret_line['credit'] = -line.amount_residual_currency
603 else:
604 ret_line['debit'] = line.amount_residual_currency if line.credit != 0 else 0
605 ret_line['credit'] = line.amount_residual_currency if line.debit != 0 else 0
606 ret_line['amount_currency_str'] = rml_parser.formatLang(line.amount_residual, currency_obj=company_currency)
607 else:
608 if line.amount_residual < 0:
609 ret_line['debit'] = 0
610 ret_line['credit'] = -line.amount_residual
611 else:
612 ret_line['debit'] = line.amount_residual if line.credit != 0 else 0
613 ret_line['credit'] = line.amount_residual if line.debit != 0 else 0
614 ctx = context.copy()
615 ctx.update({'date': st_line.date})
616 ret_line['debit'] = currency_obj.compute(cr, uid, statement_currency.id, company_currency.id, ret_line['debit'], context=ctx)
617 ret_line['credit'] = currency_obj.compute(cr, uid, statement_currency.id, company_currency.id, ret_line['credit'], context=ctx)
618 ret_line['debit_str'] = rml_parser.formatLang(ret_line['debit'], currency_obj=statement_currency)
619 ret_line['credit_str'] = rml_parser.formatLang(ret_line['credit'], currency_obj=statement_currency)
620 ret.append(ret_line)
621 if line.reconcile_partial_id:
622 reconcile_partial_ids.append(line.reconcile_partial_id.id)
623 return ret
624
625 def process_reconciliation(self, cr, uid, id, mv_line_dicts, context=None):
626 """ Creates a move line for each item of mv_line_dicts and for the statement line. Reconcile a new move line with its counterpart_move_line_id if specified. Finally, mark the statement line as reconciled by putting the newly created move id in the column journal_entry_id.
627
628 :param int id: id of the bank statement line
629 :param list of dicts mv_line_dicts: move lines to create. If counterpart_move_line_id is specified, reconcile with it
630 """
631 st_line = self.browse(cr, uid, id, context=context)
632 company_currency = st_line.journal_id.company_id.currency_id
633 statement_currency = st_line.journal_id.currency or company_currency
634 bs_obj = self.pool.get('account.bank.statement')
635 am_obj = self.pool.get('account.move')
636 aml_obj = self.pool.get('account.move.line')
637 currency_obj = self.pool.get('res.currency')
638
639 # Checks
640 if st_line.journal_entry_id.id != False:
641 raise osv.except_osv(_('Error!'), _('The bank statement line was already reconciled.'))
642 for mv_line_dict in mv_line_dicts:
643 for field in ['debit', 'credit', 'amount_currency']:
644 if field not in mv_line_dict:
645 mv_line_dict[field] = 0.0
646 if mv_line_dict.get('counterpart_move_line_id'):
647 mv_line = aml_obj.browse(cr, uid, mv_line_dict.get('counterpart_move_line_id'), context=context)
648 if mv_line.reconcile_id:
649 raise osv.except_osv(_('Error!'), _('A selected move line was already reconciled.'))
650
651 # Create the move
652 move_name = st_line.statement_id.name + "/" + str(st_line.sequence)
653 move_vals = bs_obj._prepare_move(cr, uid, st_line, move_name, context=context)
654 move_id = am_obj.create(cr, uid, move_vals, context=context)
655
656 # Create the move line for the statement line
657 amount = currency_obj.compute(cr, uid, st_line.statement_id.currency.id, company_currency.id, st_line.amount, context=context)
658 bank_st_move_vals = bs_obj._prepare_bank_move_line(cr, uid, st_line, move_id, amount, company_currency.id, context=context)
659 aml_obj.create(cr, uid, bank_st_move_vals, context=context)
660 st_line_currency_rate = bank_st_move_vals['amount_currency'] and statement_currency.id == company_currency.id and (bank_st_move_vals['amount_currency'] / st_line.amount) or False
661 st_line_currency = bank_st_move_vals['currency_id']
662 # Complete the dicts
663 st_line_statement_id = st_line.statement_id.id
664 st_line_journal_id = st_line.journal_id.id
665 st_line_partner_id = st_line.partner_id.id
666 st_line_company_id = st_line.company_id.id
667 st_line_period_id = st_line.statement_id.period_id.id
668 for mv_line_dict in mv_line_dicts:
669 mv_line_dict['ref'] = move_name
670 mv_line_dict['move_id'] = move_id
671 mv_line_dict['period_id'] = st_line_period_id
672 mv_line_dict['journal_id'] = st_line_journal_id
673 mv_line_dict['partner_id'] = st_line_partner_id
674 mv_line_dict['company_id'] = st_line_company_id
675 mv_line_dict['statement_id'] = st_line_statement_id
676 if mv_line_dict.get('counterpart_move_line_id'):
677 mv_line = aml_obj.browse(cr, uid, mv_line_dict['counterpart_move_line_id'], context=context)
678 mv_line_dict['account_id'] = mv_line.account_id.id
679 if statement_currency.id != company_currency.id:
680 mv_line_dict['amount_currency'] = mv_line_dict['debit'] - mv_line_dict['credit']
681 mv_line_dict['currency_id'] = statement_currency.id
682 mv_line_dict['debit'] = currency_obj.compute(cr, uid, statement_currency.id, company_currency.id, mv_line_dict['debit'])
683 mv_line_dict['credit'] = currency_obj.compute(cr, uid, statement_currency.id, company_currency.id, mv_line_dict['credit'])
684 elif st_line_currency and st_line_currency_rate:
685 mv_line_dict['amount_currency'] = self.pool.get('res.currency').round(cr, uid, st_line.currency_id, (mv_line_dict['debit'] - mv_line_dict['credit']) * st_line_currency_rate)
686 mv_line_dict['currency_id'] = st_line_currency
687
688 # Create move lines
689 move_line_pairs_to_reconcile = []
690 for mv_line_dict in mv_line_dicts:
691 counterpart_move_line_id = None # NB : this attribute is irrelevant for aml_obj.create() and needs to be removed from the dict
692 if mv_line_dict.get('counterpart_move_line_id'):
693 counterpart_move_line_id = mv_line_dict['counterpart_move_line_id']
694 del mv_line_dict['counterpart_move_line_id']
695 new_aml_id = aml_obj.create(cr, uid, mv_line_dict, context=context)
696 if counterpart_move_line_id != None:
697 move_line_pairs_to_reconcile.append([new_aml_id, counterpart_move_line_id])
698
699 # Reconcile
700 for pair in move_line_pairs_to_reconcile:
701 # TODO : too slow
702 aml_obj.reconcile_partial(cr, uid, pair, context=context)
703
704 # Mark the statement line as reconciled
705 self.write(cr, uid, id, {'journal_entry_id': move_id}, context=context)
706
707 # FIXME : if it wasn't for the multicompany security settings in account_security.xml, the method would just
708 # return [('journal_entry_id', '=', False)]
709 # Unfortunately, that spawns a "no access rights" error ; it shouldn't.
710 def _needaction_domain_get(self, cr, uid, context=None):
711 user = self.pool.get("res.users").browse(cr, uid, uid)
712 return ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id]),('journal_entry_id', '=', False)]
549713
550 _order = "statement_id desc, sequence"714 _order = "statement_id desc, sequence"
551 _name = "account.bank.statement.line"715 _name = "account.bank.statement.line"
552 _description = "Bank Statement Line"716 _description = "Bank Statement Line"
717 _inherit = ['ir.needaction_mixin']
553 _columns = {718 _columns = {
554 'name': fields.char('Description', required=True),719 'name': fields.char('Description', required=True),
555 'date': fields.date('Date', required=True),720 'date': fields.date('Date', required=True),
556 'amount': fields.float('Amount', digits_compute=dp.get_precision('Account')),721 'amount': fields.float('Amount', digits_compute=dp.get_precision('Account')),
557 'type': fields.selection([
558 ('supplier','Supplier'),
559 ('customer','Customer'),
560 ('general','General')
561 ], 'Type', required=True),
562 'partner_id': fields.many2one('res.partner', 'Partner'),722 'partner_id': fields.many2one('res.partner', 'Partner'),
563 'account_id': fields.many2one('account.account','Account',723 'bank_account_id': fields.many2one('res.partner.bank','Bank Account'),
564 required=True),724 'statement_id': fields.many2one('account.bank.statement', 'Statement', select=True, required=True, ondelete='cascade'),
565 'statement_id': fields.many2one('account.bank.statement', 'Statement',
566 select=True, required=True, ondelete='cascade'),
567 'journal_id': fields.related('statement_id', 'journal_id', type='many2one', relation='account.journal', string='Journal', store=True, readonly=True),725 'journal_id': fields.related('statement_id', 'journal_id', type='many2one', relation='account.journal', string='Journal', store=True, readonly=True),
568 'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account'),
569 'move_ids': fields.many2many('account.move',
570 'account_bank_statement_line_move_rel', 'statement_line_id','move_id',
571 'Moves'),
572 'ref': fields.char('Reference', size=32),726 'ref': fields.char('Reference', size=32),
573 'note': fields.text('Notes'),727 'note': fields.text('Notes'),
574 'sequence': fields.integer('Sequence', select=True, help="Gives the sequence order when displaying a list of bank statement lines."),728 'sequence': fields.integer('Sequence', select=True, help="Gives the sequence order when displaying a list of bank statement lines."),
575 'company_id': fields.related('statement_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True),729 'company_id': fields.related('statement_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True),
730 'journal_entry_id': fields.many2one('account.move', 'Journal Entry'),
731 'amount_currency': fields.float('Amount Currency', help="The amount expressed in an optional other currency if it is a multi-currency entry.", digits_compute=dp.get_precision('Account')),
732 'currency_id': fields.many2one('res.currency', 'Currency', help="The optional other currency if it is a multi-currency entry."),
576 }733 }
577 _defaults = {734 _defaults = {
578 'name': lambda self,cr,uid,context={}: self.pool.get('ir.sequence').get(cr, uid, 'account.bank.statement.line'),735 'name': lambda self,cr,uid,context={}: self.pool.get('ir.sequence').get(cr, uid, 'account.bank.statement.line'),
579 'date': lambda self,cr,uid,context={}: context.get('date', fields.date.context_today(self,cr,uid,context=context)),736 'date': lambda self,cr,uid,context={}: context.get('date', fields.date.context_today(self,cr,uid,context=context)),
580 'type': 'general',
581 }737 }
582738
739class account_statement_operation_template(osv.osv):
740 _name = "account.statement.operation.template"
741 _description = "Preset for the lines that can be created in a bank statement reconciliation"
742 _columns = {
743 'name': fields.char('Button Label', required=True),
744 'account_id': fields.many2one('account.account', 'Account', ondelete='cascade', domain=[('type','!=','view')]),
745 'label': fields.char('Label'),
746 'amount_type': fields.selection([('fixed', 'Fixed'),('percentage_of_total','Percentage of total amount'),('percentage_of_balance', 'Percentage of open balance')],
747 'Amount type', required=True),
748 'amount': fields.float('Amount', digits_compute=dp.get_precision('Account'), help="Leave to 0 to ignore."),
749 'tax_id': fields.many2one('account.tax', 'Tax', ondelete='cascade'),
750 'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account', ondelete='cascade'),
751 }
752 _defaults = {
753 'amount_type': 'fixed',
754 'amount': 0.0
755 }
583756
584# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:757# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
585758
=== modified file 'account/account_invoice.py'
--- account/account_invoice.py 2014-05-07 17:01:12 +0000
+++ account/account_invoice.py 2014-05-30 16:18:57 +0000
@@ -216,7 +216,7 @@
216 _name = "account.invoice"216 _name = "account.invoice"
217 _inherit = ['mail.thread']217 _inherit = ['mail.thread']
218 _description = 'Invoice'218 _description = 'Invoice'
219 _order = "id desc"219 _order = "number desc, id desc"
220 _track = {220 _track = {
221 'type': {221 'type': {
222 },222 },
223223
=== modified file 'account/account_move_line.py'
--- account/account_move_line.py 2014-05-07 17:01:12 +0000
+++ account/account_move_line.py 2014-05-30 16:18:57 +0000
@@ -430,7 +430,7 @@
430 elif line.reconcile_partial_id:430 elif line.reconcile_partial_id:
431 res[line.id] = str(line.reconcile_partial_id.name)431 res[line.id] = str(line.reconcile_partial_id.name)
432 return res432 return res
433 433
434 def _get_move_from_reconcile(self, cr, uid, ids, context=None):434 def _get_move_from_reconcile(self, cr, uid, ids, context=None):
435 move = {}435 move = {}
436 for r in self.pool.get('account.move.reconcile').browse(cr, uid, ids, context=context):436 for r in self.pool.get('account.move.reconcile').browse(cr, uid, ids, context=context):
@@ -491,7 +491,7 @@
491 type='many2one', relation='account.invoice', fnct_search=_invoice_search),491 type='many2one', relation='account.invoice', fnct_search=_invoice_search),
492 'account_tax_id':fields.many2one('account.tax', 'Tax'),492 'account_tax_id':fields.many2one('account.tax', 'Tax'),
493 'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account'),493 'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account'),
494 'company_id': fields.related('account_id', 'company_id', type='many2one', relation='res.company', 494 'company_id': fields.related('account_id', 'company_id', type='many2one', relation='res.company',
495 string='Company', store=True, readonly=True)495 string='Company', store=True, readonly=True)
496 }496 }
497497
@@ -765,7 +765,7 @@
765 WHERE debit > 0 AND credit > 0 AND (last_reconciliation_date IS NULL OR max_date > last_reconciliation_date)765 WHERE debit > 0 AND credit > 0 AND (last_reconciliation_date IS NULL OR max_date > last_reconciliation_date)
766 ORDER BY last_reconciliation_date""")766 ORDER BY last_reconciliation_date""")
767 ids = [x[0] for x in cr.fetchall()]767 ids = [x[0] for x in cr.fetchall()]
768 if not ids: 768 if not ids:
769 return []769 return []
770770
771 # To apply the ir_rules771 # To apply the ir_rules
@@ -793,9 +793,11 @@
793 else:793 else:
794 currency_id = line.company_id.currency_id794 currency_id = line.company_id.currency_id
795 if line.reconcile_id:795 if line.reconcile_id:
796 raise osv.except_osv(_('Warning'), _("Journal Item '%s' (id: %s), Move '%s' is already reconciled!") % (line.name, line.id, line.move_id.name)) 796 raise osv.except_osv(_('Warning'), _("Journal Item '%s' (id: %s), Move '%s' is already reconciled!") % (line.name, line.id, line.move_id.name))
797 if line.reconcile_partial_id:797 if line.reconcile_partial_id:
798 for line2 in line.reconcile_partial_id.line_partial_ids:798 for line2 in line.reconcile_partial_id.line_partial_ids:
799 if line2.state != 'valid':
800 raise osv.except_osv(_('Warning'), _("Journal Item '%s' (id: %s) cannot be used in a reconciliation as it is not balanced!") % (line2.name, line2.id))
799 if not line2.reconcile_id:801 if not line2.reconcile_id:
800 if line2.id not in merges:802 if line2.id not in merges:
801 merges.append(line2.id)803 merges.append(line2.id)
@@ -1119,7 +1121,7 @@
1119 period = period_obj.browse(cr, uid, period_id, context=context)1121 period = period_obj.browse(cr, uid, period_id, context=context)
1120 for (state,) in result:1122 for (state,) in result:
1121 if state == 'done':1123 if state == 'done':
1122 raise osv.except_osv(_('Error!'), _('You can not add/modify entries in a closed period %s of journal %s.' % (period.name,journal.name))) 1124 raise osv.except_osv(_('Error!'), _('You can not add/modify entries in a closed period %s of journal %s.' % (period.name,journal.name)))
1123 if not result:1125 if not result:
1124 jour_period_obj.create(cr, uid, {1126 jour_period_obj.create(cr, uid, {
1125 'name': (journal.code or journal.name)+':'+(period.name or ''),1127 'name': (journal.code or journal.name)+':'+(period.name or ''),
11261128
=== modified file 'account/account_unit_test.xml'
--- account/account_unit_test.xml 2013-11-13 13:01:07 +0000
+++ account/account_unit_test.xml 2014-05-30 16:18:57 +0000
@@ -6,10 +6,10 @@
6 <field name="currency_id" ref="base.EUR"/>6 <field name="currency_id" ref="base.EUR"/>
7 <field name="company_id" ref="base.main_company"/>7 <field name="company_id" ref="base.main_company"/>
8 <field name="partner_id" ref="base.res_partner_1"/>8 <field name="partner_id" ref="base.res_partner_1"/>
9 <field name="journal_id" ref="account.sales_journal"/>9 <field name="journal_id" ref="account.expenses_journal"/>
10 <field name="state">draft</field>10 <field name="state">draft</field>
11 <field name="type">in_invoice</field>11 <field name="type">in_invoice</field>
12 <field name="account_id" ref="account.a_recv"/>12 <field name="account_id" ref="account.a_pay"/>
13 <field name="name">Test invoice 1</field>13 <field name="name">Test invoice 1</field>
14 </record>14 </record>
15 <record id="test_tax_line" model="account.invoice.tax">15 <record id="test_tax_line" model="account.invoice.tax">
1616
=== modified file 'account/account_view.xml'
--- account/account_view.xml 2014-05-02 13:07:53 +0000
+++ account/account_view.xml 2014-05-30 16:18:57 +0000
@@ -489,6 +489,13 @@
489 src_model="account.journal"/>489 src_model="account.journal"/>
490490
491 <!-- Bank statement -->491 <!-- Bank statement -->
492
493 <record id="action_bank_reconcile_bank_statements" model="ir.actions.client">
494 <field name="name">Reconciliation on Bank Statements</field>
495 <field name="tag">bank_statement_reconciliation_view</field>
496 <field name="context">{'statement_id': active_id}</field>
497 </record>
498
492 <record id="view_account_bank_statement_filter" model="ir.ui.view">499 <record id="view_account_bank_statement_filter" model="ir.ui.view">
493 <field name="name">account.cash.statement.select</field>500 <field name="name">account.cash.statement.select</field>
494 <field name="model">account.bank.statement</field>501 <field name="model">account.bank.statement</field>
@@ -525,6 +532,7 @@
525 </tree>532 </tree>
526 </field>533 </field>
527 </record>534 </record>
535
528 <record id="view_bank_statement_search" model="ir.ui.view">536 <record id="view_bank_statement_search" model="ir.ui.view">
529 <field name="name">account.bank.statement.search</field>537 <field name="name">account.bank.statement.search</field>
530 <field name="model">account.bank.statement</field>538 <field name="model">account.bank.statement</field>
@@ -544,6 +552,7 @@
544 </search>552 </search>
545 </field>553 </field>
546 </record>554 </record>
555
547 <record id="view_bank_statement_form" model="ir.ui.view">556 <record id="view_bank_statement_form" model="ir.ui.view">
548 <field name="name">account.bank.statement.form</field>557 <field name="name">account.bank.statement.form</field>
549 <field name="model">account.bank.statement</field>558 <field name="model">account.bank.statement</field>
@@ -551,14 +560,21 @@
551 <field name="arch" type="xml">560 <field name="arch" type="xml">
552 <form string="Bank Statement" version="7.0">561 <form string="Bank Statement" version="7.0">
553 <header>562 <header>
554 <button name="button_confirm_bank" states="draft" string="Confirm" type="object" class="oe_highlight"/>563 <field name="all_lines_reconciled" invisible="1" />
555 <button name="button_dummy" states="draft" string="Compute" type="object" class="oe_highlight"/>564 <span attrs="{'invisible':['|',('all_lines_reconciled','=',True),('line_ids','=',[])]}">
565 <button name="%(action_bank_reconcile_bank_statements)d" states="draft" string="Reconcile" type="action" class="oe_highlight"/>
566 </span>
567 <span attrs="{'invisible':[('all_lines_reconciled','=',False)]}">
568 <button name="button_confirm_bank" states="draft" string="Close" type="object" class="oe_highlight"/>
569 </span>
556 <button name="button_cancel" states="confirm" string="Cancel Statement" type="object"/>570 <button name="button_cancel" states="confirm" string="Cancel Statement" type="object"/>
557 <field name="state" widget="statusbar" statusbar_visible="draft,confirm"/>571 <field name="state" widget="statusbar" statusbar_visible="draft,confirm"/>
558 </header>572 </header>
559 <sheet>573 <sheet>
560 <div class="oe_right oe_button_box" name="import_buttons">574 <div class="oe_right oe_button_box" name="import_buttons">
561 <!-- Put here related buttons -->575 <button class="oe_inline oe_stat_button" name="%(action_view_account_statement_from_invoice_lines)d"
576 string="Import Invoice" type="action"
577 attrs="{'invisible':[('state','=','confirm')]}" widget="statinfo" icon="fa-pencil-square-o"/>
562 </div>578 </div>
563 <label for="name" class="oe_edit_only"/>579 <label for="name" class="oe_edit_only"/>
564 <h1><field name="name"/></h1>580 <h1><field name="name"/></h1>
@@ -581,41 +597,30 @@
581 <notebook>597 <notebook>
582 <page string="Transactions" name="statement_line_ids">598 <page string="Transactions" name="statement_line_ids">
583 <field name="line_ids" context="{'date':date}">599 <field name="line_ids" context="{'date':date}">
584 <tree editable="bottom" string="Statement lines">600 <tree editable="bottom" string="Statement lines" colors="grey:journal_entry_id!=False">
585 <field name="sequence" readonly="1" invisible="1"/>601 <field name="sequence" readonly="1" invisible="1"/>
586 <field name="date"/>602 <field name="journal_entry_id" invisible="1"/>
587 <field name="name"/>603 <field name="date" attrs="{'readonly' : [('journal_entry_id', '!=', False)] }"/>
588 <field name="ref"/>604 <field name="name" attrs="{'readonly' : [('journal_entry_id', '!=', False)] }"/>
589 <field name="partner_id" on_change="onchange_partner_id(partner_id)" domain="[605 <field name="ref" attrs="{'readonly' : [('journal_entry_id', '!=', False)] }"/>
606 <field name="partner_id" domain="[
590 '&amp;',607 '&amp;',
591 '|',('parent_id','=',False),('is_company','=',True),608 '|',('parent_id','=',False),('is_company','=',True),
592 '|',('customer','=',True),('supplier','=',True)]" context="{'default_supplier': 1}"/>609 '|',('customer','=',True),('supplier','=',True)]"
593 <field name="type" on_change="onchange_type(partner_id, type)"/>610 context="{'default_supplier': 1}"
594 <field name="account_id" options='{"no_open":True}' domain="[('journal_id','=',parent.journal_id), ('company_id', '=', parent.company_id)]"/>611 attrs="{'readonly' : [('journal_entry_id', '!=', False)] }"/>
595 <field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('company_id', '=', parent.company_id), ('type', '&lt;&gt;', 'view')]"/>612 <field name="amount" attrs="{'readonly' : [('journal_entry_id', '!=', False)] }"/>
596 <field name="amount"/>613 <field name="amount_currency" groups="base.group_multi_currency" attrs="{'readonly' : [('journal_entry_id', '!=', False)] }"/>
614 <field name="currency_id" groups="base.group_multi_currency" attrs="{'readonly' : [('journal_entry_id', '!=', False)] }"/>
615 <field name="bank_account_id" groups="base.group_no_one"/>
597 </tree>616 </tree>
598 <form string="Statement lines" version="7.0">
599 <group col="4">
600 <field name="date"/>
601 <field name="name"/>
602 <field name="ref"/>
603 <field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
604 <field name="type" on_change="onchange_type(partner_id, type)"/>
605 <field name="account_id" domain="[('journal_id', '=', parent.journal_id), ('type', '&lt;&gt;', 'view'), ('company_id', '=', parent.company_id)]"/>
606 <field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('company_id', '=', parent.company_id), ('type', '&lt;&gt;', 'view')]"/>
607 <field name="amount"/>
608 <field name="sequence" readonly="0"/>
609 </group>
610 <separator string="Notes"/>
611 <field name="note"/>
612 </form>
613 </field>617 </field>
614 </page>618 </page>
615 </notebook>619 </notebook>
616 <group class="oe_subtotal_footer oe_right" colspan="2" name="sale_total">620 <group class="oe_subtotal_footer oe_right" colspan="2" name="sale_total">
617 <div class="oe_subtotal_footer_separator oe_inline">621 <div class="oe_subtotal_footer_separator oe_inline">
618 <label for="balance_end" />622 <label for="balance_end" />
623 <button name="button_dummy" states="draft" string="(update)" type="object" class="oe_edit_only oe_link"/>
619 </div>624 </div>
620 <field name="balance_end" nolabel="1" class="oe_subtotal_footer_separator" widget='monetary' options="{'currency_field': 'currency_id'}"/>625 <field name="balance_end" nolabel="1" class="oe_subtotal_footer_separator" widget='monetary' options="{'currency_field': 'currency_id'}"/>
621 </group>626 </group>
@@ -682,6 +687,85 @@
682 <field name="domain">[('state','=','draft')]</field>687 <field name="domain">[('state','=','draft')]</field>
683 <field name="filter" eval="True"/>688 <field name="filter" eval="True"/>
684 </record>689 </record>
690
691 <record id="action_bank_reconcile" model="ir.actions.client">
692 <field name="name">Reconciliation on Bank Statements</field>
693 <field name="res_model">account.bank.statement.line</field>
694 <field name="tag">bank_statement_reconciliation_view</field>
695 </record>
696
697 <!-- because of the needaction badge, groups needs to be specified -->
698 <menuitem id="menu_bank_reconcile_bank_statements" name="Reconciliation on Bank Statements" parent="account.periodical_processing_reconciliation" groups="group_account_user" action="action_bank_reconcile" sequence="20"/>
699
700 <record id="view_account_statement_operation_template_form" model="ir.ui.view">
701 <field name="name">account.statement.operation.template.form</field>
702 <field name="model">account.statement.operation.template</field>
703 <field name="arch" type="xml">
704 <form string="Statement Operation Templates" version="7.0">
705 <sheet>
706 <div class="oe_title">
707 <label for="name" class="oe_edit_only"/>
708 <h1>
709 <field name="name"/>
710 </h1>
711 </div>
712 <group>
713 <group>
714 <field name="account_id"/>
715 <field name="amount_type"/>
716 <field name="tax_id"/>
717 </group>
718 <group>
719 <field name="label"/>
720 <label for="amount"/>
721 <div>
722 <field name="amount" class="oe_inline" />
723 <label string="%" class="oe_inline" attrs="{'invisible':[('amount_type','not in',('percentage_of_total', 'percentage_of_balance'))]}" />
724 </div>
725 <field name="analytic_account_id" groups="analytic.group_analytic_accounting"/>
726 </group>
727 </group>
728 </sheet>
729 </form>
730 </field>
731 </record>
732 <record id="view_account_statement_operation_template_tree" model="ir.ui.view">
733 <field name="name">account.statement.operation.template.tree</field>
734 <field name="model">account.statement.operation.template</field>
735 <field name="arch" type="xml">
736 <tree string="Bank Reconciliation Move Presets">
737 <field name="name"/>
738 <field name="account_id"/>
739 <field name="amount_type"/>
740 </tree>
741 </field>
742 </record>
743 <record id="view_account_statement_operation_template_search" model="ir.ui.view">
744 <field name="name">account.statement.operation.template.search</field>
745 <field name="model">account.statement.operation.template</field>
746 <field name="arch" type="xml">
747 <search string="Bank Reconciliation Move preset">
748 <filter string="With tax" domain="[('tax_id','!=',False)]"/>
749 <field name="amount_type"/>
750 </search>
751 </field>
752 </record>
753 <record id="action_account_statement_operation_template" model="ir.actions.act_window">
754 <field name="name">Statement Operation Templates</field>
755 <field name="res_model">account.statement.operation.template</field>
756 <field name="view_type">form</field>
757 <field name="view_mode">tree,form</field>
758 <field name="search_view_id" ref="view_account_statement_operation_template_search"/>
759 <field name="help" type="html">
760 <p class="oe_view_nocontent_create">
761 Click to create a statement operation template.
762 </p><p>
763 Those can be used to quickly create a move line when reconciling
764 your bank statements.
765 </p>
766 </field>
767 </record>
768 <menuitem action="action_account_statement_operation_template" id="menu_action_account_statement_operation_template" parent="menu_configuration_misc" name="Statement Operation Templates" sequence="22"/>
685769
686 <!-- Account Types -->770 <!-- Account Types -->
687 <record id="view_account_type_search" model="ir.ui.view">771 <record id="view_account_type_search" model="ir.ui.view">
@@ -1603,11 +1687,11 @@
1603 <form string="Payment Term" version="7.0">1687 <form string="Payment Term" version="7.0">
1604 <group>1688 <group>
1605 <group string="Amount Computation">1689 <group string="Amount Computation">
1606 <field name="value"/>1690 <field name="value"/>
1607 <label for="value_amount" string="Amount To Pay" attrs="{'invisible':[('value','=','balance')]}"/>1691 <label for="value_amount" string="Amount To Pay" attrs="{'invisible':[('value','=','balance')]}"/>
1608 <div attrs="{'invisible':[('value','=','balance')]}">1692 <div attrs="{'invisible':[('value','=','balance')]}">
1609 <field name="value_amount" class="oe_inline"/>1693 <field name="value_amount" class="oe_inline"/>
1610 </div>1694 </div>
1611 </group>1695 </group>
1612 <group string="Due Date Computation">1696 <group string="Due Date Computation">
1613 <field name="days"/>1697 <field name="days"/>
@@ -2259,7 +2343,13 @@
2259 <field name="arch" type="xml">2343 <field name="arch" type="xml">
2260 <form string="Statement" version="7.0">2344 <form string="Statement" version="7.0">
2261 <header>2345 <header>
2262 <button name="button_confirm_cash" states="open" string="Close CashBox" type="object" class="oe_highlight"/>2346 <field name="all_lines_reconciled" invisible="1" />
2347 <span attrs="{'invisible':['|',('all_lines_reconciled','=',True),('line_ids','=',[])]}">
2348 <button name="%(action_bank_reconcile_bank_statements)d" states="open" string="Reconcile" type="action" class="oe_highlight"/>
2349 </span>
2350 <span attrs="{'invisible':[('all_lines_reconciled','=',False)]}">
2351 <button name="button_confirm_cash" states="open" string="Close CashBox" type="object" class="oe_highlight"/>
2352 </span>
2263 <button name="button_open" states="draft" string="Open CashBox" type="object" class="oe_highlight"/>2353 <button name="button_open" states="draft" string="Open CashBox" type="object" class="oe_highlight"/>
2264 <button name="button_cancel" states="confirm,open" string="Cancel CashBox" type="object"/>2354 <button name="button_cancel" states="confirm,open" string="Cancel CashBox" type="object"/>
2265 <field name="state" widget="statusbar" nolabel="1" statusbar_visible="draft,confirm"/>2355 <field name="state" widget="statusbar" nolabel="1" statusbar_visible="draft,confirm"/>
@@ -2289,10 +2379,7 @@
2289 <field name="date"/>2379 <field name="date"/>
2290 <field name="name"/>2380 <field name="name"/>
2291 <field name="ref"/>2381 <field name="ref"/>
2292 <field name="partner_id" on_change="onchange_partner_id(partner_id)"/>2382 <field name="partner_id"/>
2293 <field name="type" on_change="onchange_type(partner_id, type)"/>
2294 <field domain="[('journal_id','=',parent.journal_id), ('company_id', '=', parent.company_id)]" name="account_id"/>
2295 <field name="analytic_account_id" domain="[('company_id', '=', parent.company_id), ('type', '&lt;&gt;', 'view')]" groups="analytic.group_analytic_accounting" />
2296 <field name="amount"/>2383 <field name="amount"/>
2297 </tree>2384 </tree>
2298 <form string="Statement lines" version="7.0">2385 <form string="Statement lines" version="7.0">
@@ -2300,10 +2387,7 @@
2300 <field name="date"/>2387 <field name="date"/>
2301 <field name="name"/>2388 <field name="name"/>
2302 <field name="ref"/>2389 <field name="ref"/>
2303 <field name="partner_id" on_change="onchange_partner_id(partner_id)"/>2390 <field name="partner_id"/>
2304 <field name="type" on_change="onchange_type(partner_id, type)"/>
2305 <field domain="[('journal_id', '=', parent.journal_id), ('type', '&lt;&gt;', 'view'), ('company_id', '=', parent.company_id)]" name="account_id"/>
2306 <field name="analytic_account_id" domain="[('company_id', '=', parent.company_id), ('type', '&lt;&gt;', 'view')]" groups="analytic.group_analytic_accounting" />
2307 <field name="amount"/>2391 <field name="amount"/>
2308 <field name="sequence"/>2392 <field name="sequence"/>
2309 </group>2393 </group>
23102394
=== added file 'account/demo/account_bank_statement.xml'
--- account/demo/account_bank_statement.xml 1970-01-01 00:00:00 +0000
+++ account/demo/account_bank_statement.xml 2014-05-30 16:18:57 +0000
@@ -0,0 +1,85 @@
1<?xml version="1.0" encoding="utf-8"?>
2<openerp>
3 <data>
4 <!-- A bank statement -->
5 <record id="demo_bank_statement_1" model="account.bank.statement">
6 <field name="journal_id" ref="account.bank_journal"/>
7 <field name="period_id" ref="account.period_5"/>
8 <field name="date" eval="time.strftime('%Y')+'-01-01'"/>
9 <field name="user_id" ref="base.user_demo"/>
10 <field name="reference_type">none</field>
11 <field name="name">BNK/2014/001</field>
12 <field name="balance_end" eval="2040.0"/>
13 <field name="company_id" ref="base.main_company"/>
14 <field name="state">draft</field>
15 <field name="balance_start" eval="0.0"/>
16 <field name="balance_end_real" eval="3707.58"/>
17 </record>
18 <record id="demo_bank_statement_line_1" model="account.bank.statement.line">
19 <field name="ref">001</field>
20 <field name="statement_id" ref="demo_bank_statement_1"/>
21 <field name="sequence" eval="1"/>
22 <field name="company_id" ref="base.main_company"/>
23 <field name="name">First 2000 € of SAJ/2014/001</field>
24 <field name="journal_id" ref="account.bank_journal"/>
25 <field name="amount" eval="2000.0"/>
26 <field name="date" eval="time.strftime('%Y')+'-01-01'"/>
27 <field name="partner_id" ref="base.res_partner_9"/>
28 </record>
29 <record id="demo_bank_statement_line_2" model="account.bank.statement.line">
30 <field name="ref">002</field>
31 <field name="statement_id" ref="demo_bank_statement_1"/>
32 <field name="sequence" eval="2"/>
33 <field name="company_id" ref="base.main_company"/>
34 <field name="name">SAJ/2014/002</field>
35 <field name="journal_id" ref="account.bank_journal"/>
36 <field name="amount" eval="650.0"/>
37 <field name="date" eval="time.strftime('%Y')+'-01-01'"/>
38 <field name="partner_id" ref="base.res_partner_9"/>
39 </record>
40 <record id="demo_bank_statement_line_3" model="account.bank.statement.line">
41 <field name="ref">003</field>
42 <field name="statement_id" ref="demo_bank_statement_1"/>
43 <field name="sequence" eval="3"/>
44 <field name="company_id" ref="base.main_company"/>
45 <field name="name">Bank fees</field>
46 <field name="journal_id" ref="account.bank_journal"/>
47 <field name="amount" eval="32.58"/>
48 <field name="date" eval="time.strftime('%Y')+'-01-01'"/>
49 </record>
50 <record id="demo_bank_statement_line_4" model="account.bank.statement.line">
51 <field name="ref">004</field>
52 <field name="statement_id" ref="demo_bank_statement_1"/>
53 <field name="sequence" eval="4"/>
54 <field name="company_id" ref="base.main_company"/>
55 <field name="name">SAJ/2014/003 and SAJ/2014/004</field>
56 <field name="journal_id" ref="account.bank_journal"/>
57 <field name="amount" eval="1025.0"/>
58 <field name="date" eval="time.strftime('%Y')+'-01-01'"/>
59 <field name="partner_id" ref="base.res_partner_2"/>
60 </record>
61
62 <!-- Statement operation templates -->
63 <record id="statement_operation_template_1" model="account.statement.operation.template">
64 <field name="name">Discount For Early Payment</field>
65 <field name="account_id" ref="a_expense"></field>
66 <field name="label">Discount</field>
67 <field name="amount_type">percentage_of_total</field>
68 <field name="amount">-7</field>
69 </record>
70 <record id="statement_operation_template_2" model="account.statement.operation.template">
71 <field name="name">Bank Fees</field>
72 <field name="account_id" ref="a_expense"></field>
73 <field name="label">Bank Fees</field>
74 <field name="amount_type">fixed</field>
75 <field name="amount"></field>
76 </record>
77 <record id="statement_operation_template_3" model="account.statement.operation.template">
78 <field name="name">Profit / Loss</field>
79 <field name="account_id" ref="a_sale"></field>
80 <field name="label">Profit / Loss</field>
81 <field name="amount_type">fixed</field>
82 <field name="amount"></field>
83 </record>
84 </data>
85</openerp>
086
=== modified file 'account/demo/account_invoice_demo.xml'
--- account/demo/account_invoice_demo.xml 2012-11-29 22:26:45 +0000
+++ account/demo/account_invoice_demo.xml 2014-05-30 16:18:57 +0000
@@ -44,5 +44,135 @@
44 <field name="partner_id" ref="base.res_partner_17"/>44 <field name="partner_id" ref="base.res_partner_17"/>
45 <field name="name">Zed+ Antivirus</field>45 <field name="name">Zed+ Antivirus</field>
46 </record>46 </record>
47
48 <!-- Some customer invoices used to show the reconciliation process on the bank statement -->
49 <record id="invoice_1" model="account.invoice">
50 <field name="currency_id" ref="base.EUR"/>
51 <field name="company_id" ref="base.main_company"/>
52 <field name="journal_id" ref="account.sales_journal"/>
53 <field name="state">draft</field>
54 <field name="type">out_invoice</field>
55 <field name="account_id" ref="a_recv"/>
56 <field name="partner_id" ref="base.res_partner_9"/>
57 </record>
58 <record id="invoice_1_line_1" model="account.invoice.line">
59 <field name="name">Otpez Laptop without OS</field>
60 <field name="invoice_id" ref="invoice_1"/>
61 <field name="price_unit">642</field>
62 <field name="quantity">5</field>
63 <field name="account_id" ref="a_sale"/>
64 </record>
65 <record id="invoice_1_line_2" model="account.invoice.line">
66 <field name="name">Linutop</field>
67 <field name="invoice_id" ref="invoice_1"/>
68 <field name="price_unit">280</field>
69 <field name="quantity">5</field>
70 <field name="account_id" ref="a_sale"/>
71 </record>
72 <workflow action="invoice_open" model="account.invoice" ref="invoice_1"/>
73
74 <record id="invoice_2" model="account.invoice">
75 <field name="currency_id" ref="base.EUR"/>
76 <field name="company_id" ref="base.main_company"/>
77 <field name="journal_id" ref="account.sales_journal"/>
78 <field name="state">draft</field>
79 <field name="type">out_invoice</field>
80 <field name="account_id" ref="a_recv"/>
81 <field name="partner_id" ref="base.res_partner_9"/>
82 <field eval="time.strftime('%Y-%m') + '-01'" name="date_invoice"/>
83 </record>
84 <record id="invoice_2_line_1" model="account.invoice.line">
85 <field name="name">8-port Switch</field>
86 <field name="invoice_id" ref="invoice_2"/>
87 <field name="price_unit">50</field>
88 <field name="quantity">3</field>
89 <field name="account_id" ref="a_sale"/>
90 </record>
91 <record id="invoice_2_line_2" model="account.invoice.line">
92 <field name="name">30m RJ45 wire</field>
93 <field name="invoice_id" ref="invoice_2"/>
94 <field name="price_unit">25</field>
95 <field name="quantity">20</field>
96 <field name="account_id" ref="a_sale"/>
97 </record>
98 <workflow action="invoice_open" model="account.invoice" ref="invoice_2"/>
99
100 <record id="invoice_3" model="account.invoice">
101 <field name="currency_id" ref="base.EUR"/>
102 <field name="company_id" ref="base.main_company"/>
103 <field name="journal_id" ref="account.sales_journal"/>
104 <field name="state">draft</field>
105 <field name="type">out_invoice</field>
106 <field name="account_id" ref="a_recv"/>
107 <field name="partner_id" ref="base.res_partner_2"/>
108 <field eval="time.strftime('%Y-%m') + '-08'" name="date_invoice"/>
109 </record>
110 <record id="invoice_3_line_1" model="account.invoice.line">
111 <field name="name">TypeMatrix Dvorak Keyboard</field>
112 <field name="invoice_id" ref="invoice_3"/>
113 <field name="price_unit">90</field>
114 <field name="quantity">5</field>
115 <field name="account_id" ref="a_sale"/>
116 </record>
117 <record id="invoice_3_line_2" model="account.invoice.line">
118 <field name="name">Ergonomic Mouse</field>
119 <field name="invoice_id" ref="invoice_3"/>
120 <field name="price_unit">15</field>
121 <field name="quantity">5</field>
122 <field name="account_id" ref="a_sale"/>
123 </record>
124 <workflow action="invoice_open" model="account.invoice" ref="invoice_3"/>
125
126 <record id="invoice_4" model="account.invoice">
127 <field name="currency_id" ref="base.EUR"/>
128 <field name="company_id" ref="base.main_company"/>
129 <field name="journal_id" ref="account.sales_journal"/>
130 <field name="state">draft</field>
131 <field name="type">out_invoice</field>
132 <field name="account_id" ref="a_recv"/>
133 <field name="partner_id" ref="base.res_partner_2"/>
134 <field eval="time.strftime('%Y-%m') + '-15'" name="date_invoice"/>
135 </record>
136 <record id="invoice_4_line_1" model="account.invoice.line">
137 <field name="name">Desktop Computer Table</field>
138 <field name="invoice_id" ref="invoice_4"/>
139 <field name="price_unit">80</field>
140 <field name="quantity">5</field>
141 <field name="account_id" ref="a_sale"/>
142 </record>
143 <record id="invoice_4_line_2" model="account.invoice.line">
144 <field name="name">Desktop Lamp</field>
145 <field name="invoice_id" ref="invoice_4"/>
146 <field name="price_unit">20</field>
147 <field name="quantity">5</field>
148 <field name="account_id" ref="a_sale"/>
149 </record>
150 <workflow action="invoice_open" model="account.invoice" ref="invoice_4"/>
151
152 <record id="invoice_5" model="account.invoice">
153 <field name="currency_id" ref="base.EUR"/>
154 <field name="company_id" ref="base.main_company"/>
155 <field name="journal_id" ref="account.sales_journal"/>
156 <field name="state">draft</field>
157 <field name="type">out_invoice</field>
158 <field name="account_id" ref="a_recv"/>
159 <field name="partner_id" ref="base.res_partner_9"/>
160 <field eval="time.strftime('%Y-%m') + '-08'" name="date_invoice"/>
161 </record>
162 <record id="invoice_5_line_1" model="account.invoice.line">
163 <field name="name">TypeMatrix Dvorak Keyboard</field>
164 <field name="invoice_id" ref="invoice_5"/>
165 <field name="price_unit">90</field>
166 <field name="quantity">5</field>
167 <field name="account_id" ref="a_sale"/>
168 </record>
169 <record id="invoice_5_line_2" model="account.invoice.line">
170 <field name="name">Ergonomic Mouse</field>
171 <field name="invoice_id" ref="invoice_5"/>
172 <field name="price_unit">15</field>
173 <field name="quantity">5</field>
174 <field name="account_id" ref="a_sale"/>
175 </record>
176 <workflow action="invoice_open" model="account.invoice" ref="invoice_5"/>
47 </data>177 </data>
48</openerp>178</openerp>
49179
=== modified file 'account/security/ir.model.access.csv'
--- account/security/ir.model.access.csv 2013-10-27 12:31:04 +0000
+++ account/security/ir.model.access.csv 2014-05-30 16:18:57 +0000
@@ -1,100 +1,101 @@
1id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink1id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
2access_product_product_account_user,product.product.account.user,product.model_product_product,group_account_user,1,0,0,02access_product_product_account_user,product.product.account.user,product.model_product_product,group_account_user,1,0,0,0
3access_account_payment_term,account.payment.term,model_account_payment_term,account.group_account_user,1,0,0,03access_account_payment_term,account.payment.term,model_account_payment_term,account.group_account_user,1,0,0,0
4access_account_payment_term_line,account.payment.term.line,model_account_payment_term_line,account.group_account_user,1,0,0,04access_account_payment_term_line,account.payment.term.line,model_account_payment_term_line,account.group_account_user,1,0,0,0
5access_account_account_type,account.account.type,model_account_account_type,account.group_account_user,1,0,0,05access_account_account_type,account.account.type,model_account_account_type,account.group_account_user,1,0,0,0
6access_account_tax_internal_user,account.tax internal user,model_account_tax,base.group_user,1,0,0,06access_account_tax_internal_user,account.tax internal user,model_account_tax,base.group_user,1,0,0,0
7access_account_account,account.account,model_account_account,account.group_account_user,1,0,0,07access_account_account,account.account,model_account_account,account.group_account_user,1,0,0,0
8access_account_account_user,account.account user,model_account_account,base.group_user,1,0,0,08access_account_account_user,account.account user,model_account_account,base.group_user,1,0,0,0
9access_account_account_partner_manager,account.account partner manager,model_account_account,base.group_partner_manager,1,0,0,09access_account_account_partner_manager,account.account partner manager,model_account_account,base.group_partner_manager,1,0,0,0
10access_account_journal_period_manager,account.journal.period manager,model_account_journal_period,account.group_account_manager,1,0,0,010access_account_journal_period_manager,account.journal.period manager,model_account_journal_period,account.group_account_manager,1,0,0,0
11access_account_tax_code,account.tax.code,model_account_tax_code,account.group_account_invoice,1,0,0,011access_account_tax_code,account.tax.code,model_account_tax_code,account.group_account_invoice,1,0,0,0
12access_account_tax,account.tax,model_account_tax,account.group_account_invoice,1,0,0,012access_account_tax,account.tax,model_account_tax,account.group_account_invoice,1,0,0,0
13access_account_model,account.model,model_account_model,account.group_account_user,1,1,1,113access_account_model,account.model,model_account_model,account.group_account_user,1,1,1,1
14access_account_model_line,account.model.line,model_account_model_line,account.group_account_user,1,1,1,114access_account_model_line,account.model.line,model_account_model_line,account.group_account_user,1,1,1,1
15access_account_subscription,account.subscription,model_account_subscription,account.group_account_user,1,1,1,115access_account_subscription,account.subscription,model_account_subscription,account.group_account_user,1,1,1,1
16access_account_subscription_line,account.subscription.line,model_account_subscription_line,account.group_account_user,1,1,1,116access_account_subscription_line,account.subscription.line,model_account_subscription_line,account.group_account_user,1,1,1,1
17access_account_subscription_manager,account.subscription manager,model_account_subscription,account.group_account_manager,1,0,0,017access_account_subscription_manager,account.subscription manager,model_account_subscription,account.group_account_manager,1,0,0,0
18access_account_subscription_line_manager,account.subscription.line manager,model_account_subscription_line,account.group_account_manager,1,0,0,018access_account_subscription_line_manager,account.subscription.line manager,model_account_subscription_line,account.group_account_manager,1,0,0,0
19access_account_account_template,account.account.template,model_account_account_template,account.group_account_manager,1,1,1,119access_account_account_template,account.account.template,model_account_account_template,account.group_account_manager,1,1,1,1
20access_account_tax_code_template,account.tax.code.template,model_account_tax_code_template,account.group_account_manager,1,1,1,120access_account_tax_code_template,account.tax.code.template,model_account_tax_code_template,account.group_account_manager,1,1,1,1
21access_account_chart_template,account.chart.template,model_account_chart_template,account.group_account_manager,1,1,1,121access_account_chart_template,account.chart.template,model_account_chart_template,account.group_account_manager,1,1,1,1
22access_account_tax_template,account.tax.template,model_account_tax_template,account.group_account_manager,1,1,1,122access_account_tax_template,account.tax.template,model_account_tax_template,account.group_account_manager,1,1,1,1
23access_account_bank_statement,account.bank.statement,model_account_bank_statement,account.group_account_user,1,1,1,123access_account_bank_statement,account.bank.statement,model_account_bank_statement,account.group_account_user,1,1,1,1
24access_account_bank_statement_line,account.bank.statement.line,model_account_bank_statement_line,account.group_account_user,1,1,1,124access_account_bank_statement_line,account.bank.statement.line,model_account_bank_statement_line,account.group_account_user,1,1,1,1
25access_account_analytic_line_manager,account.analytic.line manager,model_account_analytic_line,account.group_account_manager,1,0,0,025access_account_analytic_line_manager,account.analytic.line manager,model_account_analytic_line,account.group_account_manager,1,0,0,0
26access_account_analytic_account,account.analytic.account,analytic.model_account_analytic_account,base.group_user,1,0,0,026access_account_analytic_account,account.analytic.account,analytic.model_account_analytic_account,base.group_user,1,0,0,0
27access_account_analytic_journal,account.analytic.journal,model_account_analytic_journal,account.group_account_user,1,0,0,027access_account_analytic_journal,account.analytic.journal,model_account_analytic_journal,account.group_account_user,1,0,0,0
28access_account_analytic_journal_user,account.analytic.journal,model_account_analytic_journal,base.group_user,1,1,1,028access_account_analytic_journal_user,account.analytic.journal,model_account_analytic_journal,base.group_user,1,1,1,0
29access_account_invoice_uinvoice,account.invoice,model_account_invoice,account.group_account_invoice,1,1,1,129access_account_invoice_uinvoice,account.invoice,model_account_invoice,account.group_account_invoice,1,1,1,1
30access_account_invoice_line_uinvoice,account.invoice.line,model_account_invoice_line,account.group_account_invoice,1,1,1,130access_account_invoice_line_uinvoice,account.invoice.line,model_account_invoice_line,account.group_account_invoice,1,1,1,1
31access_account_invoice_tax_uinvoice,account.invoice.tax,model_account_invoice_tax,account.group_account_invoice,1,1,1,131access_account_invoice_tax_uinvoice,account.invoice.tax,model_account_invoice_tax,account.group_account_invoice,1,1,1,1
32access_account_move_uinvoice,account.move,model_account_move,account.group_account_invoice,1,1,1,132access_account_move_uinvoice,account.move,model_account_move,account.group_account_invoice,1,1,1,1
33access_account_move_line_uinvoice,account.move.line invoice,model_account_move_line,account.group_account_invoice,1,1,1,133access_account_move_line_uinvoice,account.move.line invoice,model_account_move_line,account.group_account_invoice,1,1,1,1
34access_account_move_reconcile_uinvoice,account.move.reconcile,model_account_move_reconcile,account.group_account_invoice,1,1,1,134access_account_move_reconcile_uinvoice,account.move.reconcile,model_account_move_reconcile,account.group_account_invoice,1,1,1,1
35access_account_journal_period_uinvoice,account.journal.period,model_account_journal_period,account.group_account_invoice,1,1,1,135access_account_journal_period_uinvoice,account.journal.period,model_account_journal_period,account.group_account_invoice,1,1,1,1
36access_account_payment_term_manager,account.payment.term,model_account_payment_term,account.group_account_manager,1,1,1,136access_account_payment_term_manager,account.payment.term,model_account_payment_term,account.group_account_manager,1,1,1,1
37access_account_payment_term_line_manager,account.payment.term.line,model_account_payment_term_line,account.group_account_manager,1,1,1,137access_account_payment_term_line_manager,account.payment.term.line,model_account_payment_term_line,account.group_account_manager,1,1,1,1
38access_account_tax_manager,account.tax,model_account_tax,account.group_account_manager,1,1,1,138access_account_tax_manager,account.tax,model_account_tax,account.group_account_manager,1,1,1,1
39access_account_journal_manager,account.journal,model_account_journal,account.group_account_manager,1,1,1,139access_account_journal_manager,account.journal,model_account_journal,account.group_account_manager,1,1,1,1
40access_account_journal_invoice,account.journal invoice,model_account_journal,account.group_account_invoice,1,0,0,040access_account_journal_invoice,account.journal invoice,model_account_journal,account.group_account_invoice,1,0,0,0
41access_account_period_manager,account.period,model_account_period,account.group_account_manager,1,1,1,141access_account_period_manager,account.period,model_account_period,account.group_account_manager,1,1,1,1
42access_account_period_invoice,account.period invoice,model_account_period,account.group_account_invoice,1,0,0,042access_account_period_invoice,account.period invoice,model_account_period,account.group_account_invoice,1,0,0,0
43access_account_invoice_group_invoice,account.invoice group invoice,model_account_invoice,account.group_account_invoice,1,1,1,143access_account_invoice_group_invoice,account.invoice group invoice,model_account_invoice,account.group_account_invoice,1,1,1,1
44access_account_analytic_journal_manager,account.analytic.journal,model_account_analytic_journal,account.group_account_manager,1,1,1,144access_account_analytic_journal_manager,account.analytic.journal,model_account_analytic_journal,account.group_account_manager,1,1,1,1
45access_account_fiscalyear,account.fiscalyear,model_account_fiscalyear,account.group_account_manager,1,1,1,145access_account_fiscalyear,account.fiscalyear,model_account_fiscalyear,account.group_account_manager,1,1,1,1
46access_account_fiscalyear_invoice,account.fiscalyear.invoice,model_account_fiscalyear,account.group_account_invoice,1,0,0,046access_account_fiscalyear_invoice,account.fiscalyear.invoice,model_account_fiscalyear,account.group_account_invoice,1,0,0,0
47access_account_fiscalyear_partner_manager,account.fiscalyear.partnermanager,model_account_fiscalyear,base.group_partner_manager,1,0,0,047access_account_fiscalyear_partner_manager,account.fiscalyear.partnermanager,model_account_fiscalyear,base.group_partner_manager,1,0,0,0
48access_account_fiscalyear_employee,account.fiscalyear employee,model_account_fiscalyear,base.group_user,1,0,0,048access_account_fiscalyear_employee,account.fiscalyear employee,model_account_fiscalyear,base.group_user,1,0,0,0
49access_res_currency_account_manager,res.currency account manager,base.model_res_currency,group_account_manager,1,1,1,149access_res_currency_account_manager,res.currency account manager,base.model_res_currency,group_account_manager,1,1,1,1
50access_res_currency_rate_account_manager,res.currency.rate account manager,base.model_res_currency_rate,group_account_manager,1,1,1,150access_res_currency_rate_account_manager,res.currency.rate account manager,base.model_res_currency_rate,group_account_manager,1,1,1,1
51access_res_currency_rate_type_account_manager,res.currency.rate.type account manager,base.model_res_currency_rate_type,group_account_manager,1,1,1,151access_res_currency_rate_type_account_manager,res.currency.rate.type account manager,base.model_res_currency_rate_type,group_account_manager,1,1,1,1
52access_account_invoice_user,account.invoice user,model_account_invoice,base.group_user,1,0,0,052access_account_invoice_user,account.invoice user,model_account_invoice,base.group_user,1,0,0,0
53access_account_invoice_user,account.invoice.line user,model_account_invoice_line,base.group_user,1,0,0,053access_account_invoice_user,account.invoice.line user,model_account_invoice_line,base.group_user,1,0,0,0
54access_account_payment_term_partner_manager,account.payment.term partner manager,model_account_payment_term,base.group_user,1,0,0,054access_account_payment_term_partner_manager,account.payment.term partner manager,model_account_payment_term,base.group_user,1,0,0,0
55access_account_payment_term_line_partner_manager,account.payment.term.line partner manager,model_account_payment_term_line,base.group_user,1,0,0,055access_account_payment_term_line_partner_manager,account.payment.term.line partner manager,model_account_payment_term_line,base.group_user,1,0,0,0
56access_account_account_sale_manager,account.account sale manager,model_account_account,base.group_sale_manager,1,0,0,056access_account_account_sale_manager,account.account sale manager,model_account_account,base.group_sale_manager,1,0,0,0
57access_account_fiscal_position_product_manager,account.fiscal.position account.manager,model_account_fiscal_position,account.group_account_manager,1,1,1,157access_account_fiscal_position_product_manager,account.fiscal.position account.manager,model_account_fiscal_position,account.group_account_manager,1,1,1,1
58access_account_fiscal_position_tax_product_manager,account.fiscal.position.tax account.manager,model_account_fiscal_position_tax,account.group_account_manager,1,1,1,158access_account_fiscal_position_tax_product_manager,account.fiscal.position.tax account.manager,model_account_fiscal_position_tax,account.group_account_manager,1,1,1,1
59access_account_fiscal_position_account_product_manager,account.fiscal.position account.manager,model_account_fiscal_position_account,account.group_account_manager,1,1,1,159access_account_fiscal_position_account_product_manager,account.fiscal.position account.manager,model_account_fiscal_position_account,account.group_account_manager,1,1,1,1
60access_account_fiscal_position,account.fiscal.position all,model_account_fiscal_position,base.group_user,1,0,0,060access_account_fiscal_position,account.fiscal.position all,model_account_fiscal_position,base.group_user,1,0,0,0
61access_account_fiscal_position_tax,account.fiscal.position.tax all,model_account_fiscal_position_tax,base.group_user,1,0,0,061access_account_fiscal_position_tax,account.fiscal.position.tax all,model_account_fiscal_position_tax,base.group_user,1,0,0,0
62access_account_fiscal_position_account,account.fiscal.position all,model_account_fiscal_position_account,base.group_user,1,0,0,062access_account_fiscal_position_account,account.fiscal.position all,model_account_fiscal_position_account,base.group_user,1,0,0,0
63access_account_fiscal_position_template,account.fiscal.position.template,model_account_fiscal_position_template,account.group_account_manager,1,1,1,163access_account_fiscal_position_template,account.fiscal.position.template,model_account_fiscal_position_template,account.group_account_manager,1,1,1,1
64access_account_fiscal_position_tax_template,account.fiscal.position.tax.template,model_account_fiscal_position_tax_template,account.group_account_manager,1,1,1,164access_account_fiscal_position_tax_template,account.fiscal.position.tax.template,model_account_fiscal_position_tax_template,account.group_account_manager,1,1,1,1
65access_account_fiscal_position_account_template,account.fiscal.position.account.template,model_account_fiscal_position_account_template,account.group_account_manager,1,1,1,165access_account_fiscal_position_account_template,account.fiscal.position.account.template,model_account_fiscal_position_account_template,account.group_account_manager,1,1,1,1
66access_account_sequence_fiscal_year_user,account.sequence.fiscalyear user,model_account_sequence_fiscalyear,base.group_user,1,0,0,066access_account_sequence_fiscal_year_user,account.sequence.fiscalyear user,model_account_sequence_fiscalyear,base.group_user,1,0,0,0
67access_temp_range,temp.range,model_temp_range,account.group_account_manager,1,0,0,067access_temp_range,temp.range,model_temp_range,account.group_account_manager,1,0,0,0
68access_report_aged_receivable,report.aged.receivable,model_report_aged_receivable,account.group_account_manager,1,1,1,168access_report_aged_receivable,report.aged.receivable,model_report_aged_receivable,account.group_account_manager,1,1,1,1
69access_report_invoice_created,report.invoice.created,model_report_invoice_created,account.group_account_manager,1,1,1,169access_report_invoice_created,report.invoice.created,model_report_invoice_created,account.group_account_manager,1,1,1,1
70access_report_account_type_sales,report.account_type.sales,model_report_account_type_sales,account.group_account_manager,1,1,1,170access_report_account_type_sales,report.account_type.sales,model_report_account_type_sales,account.group_account_manager,1,1,1,1
71access_report_account_sales,report.account.sales,model_report_account_sales,account.group_account_manager,1,1,1,171access_report_account_sales,report.account.sales,model_report_account_sales,account.group_account_manager,1,1,1,1
72access_account_invoice_report,account.invoice.report,model_account_invoice_report,account.group_account_manager,1,1,1,172access_account_invoice_report,account.invoice.report,model_account_invoice_report,account.group_account_manager,1,1,1,1
73access_res_partner_group_account_manager,res_partner group_account_manager,model_res_partner,account.group_account_manager,1,0,0,073access_res_partner_group_account_manager,res_partner group_account_manager,model_res_partner,account.group_account_manager,1,0,0,0
74access_account_invoice_accountant,account.invoice accountant,model_account_invoice,account.group_account_user,1,0,0,074access_account_invoice_accountant,account.invoice accountant,model_account_invoice,account.group_account_user,1,0,0,0
75access_account_tax_code_accountant,account.tax.code accountant,model_account_tax_code,account.group_account_user,1,1,1,175access_account_tax_code_accountant,account.tax.code accountant,model_account_tax_code,account.group_account_user,1,1,1,1
76access_account_move_line_manager,account.move.line manager,model_account_move_line,account.group_account_manager,1,0,0,076access_account_move_line_manager,account.move.line manager,model_account_move_line,account.group_account_manager,1,0,0,0
77access_account_move_manager,account.move manager,model_account_move,account.group_account_manager,1,0,0,077access_account_move_manager,account.move manager,model_account_move,account.group_account_manager,1,0,0,0
78access_account_entries_report_manager,account.entries.report,model_account_entries_report,account.group_account_manager,1,1,1,178access_account_entries_report_manager,account.entries.report,model_account_entries_report,account.group_account_manager,1,1,1,1
79access_account_entries_report_invoice,account.entries.report,model_account_entries_report,account.group_account_invoice,1,0,0,079access_account_entries_report_invoice,account.entries.report,model_account_entries_report,account.group_account_invoice,1,0,0,0
80access_account_entries_report_employee,account.entries.report employee,model_account_entries_report,base.group_user,1,0,0,080access_account_entries_report_employee,account.entries.report employee,model_account_entries_report,base.group_user,1,0,0,0
81access_analytic_entries_report_manager,analytic.entries.report,model_analytic_entries_report,account.group_account_manager,1,0,0,081access_analytic_entries_report_manager,analytic.entries.report,model_analytic_entries_report,account.group_account_manager,1,0,0,0
82access_account_cashbox_line,account.cashbox.line,model_account_cashbox_line,account.group_account_user,1,1,1,182access_account_cashbox_line,account.cashbox.line,model_account_cashbox_line,account.group_account_user,1,1,1,1
83access_account_journal_cashbox_line,account.journal.cashbox.line,model_account_journal_cashbox_line,account.group_account_user,1,1,1,083access_account_journal_cashbox_line,account.journal.cashbox.line,model_account_journal_cashbox_line,account.group_account_user,1,1,1,0
84access_account_invoice_tax_accountant,account.invoice.tax accountant,model_account_invoice_tax,account.group_account_user,1,0,0,084access_account_invoice_tax_accountant,account.invoice.tax accountant,model_account_invoice_tax,account.group_account_user,1,0,0,0
85access_account_move_reconcile_manager,account.move.reconcile manager,model_account_move_reconcile,account.group_account_manager,1,0,0,085access_account_move_reconcile_manager,account.move.reconcile manager,model_account_move_reconcile,account.group_account_manager,1,0,0,0
86access_account_analytic_line_invoice,account.analytic.line invoice,model_account_analytic_line,account.group_account_invoice,1,1,1,186access_account_analytic_line_invoice,account.analytic.line invoice,model_account_analytic_line,account.group_account_invoice,1,1,1,1
87access_account_invoice_line_accountant,account.invoice.line accountant,model_account_invoice_line,account.group_account_user,1,0,0,087access_account_invoice_line_accountant,account.invoice.line accountant,model_account_invoice_line,account.group_account_user,1,0,0,0
88access_account_account_invoice,account.account invoice,model_account_account,account.group_account_invoice,1,1,1,188access_account_account_invoice,account.account invoice,model_account_account,account.group_account_invoice,1,1,1,1
89access_account_analytic_accountant,account.analytic.account accountant,analytic.model_account_analytic_account,account.group_account_user,1,1,1,189access_account_analytic_accountant,account.analytic.account accountant,analytic.model_account_analytic_account,account.group_account_user,1,1,1,1
90access_account_account_type_invoice,account.account.type invoice,model_account_account_type,account.group_account_invoice,1,1,1,190access_account_account_type_invoice,account.account.type invoice,model_account_account_type,account.group_account_invoice,1,1,1,1
91access_report_account_receivable_invoice,report.account.receivable.invoice,model_report_account_receivable,account.group_account_invoice,1,1,1,191access_report_account_receivable_invoice,report.account.receivable.invoice,model_report_account_receivable,account.group_account_invoice,1,1,1,1
92access_account_sequence_fiscal_year_invoice,account.sequence.fiscalyear invoice,model_account_sequence_fiscalyear,account.group_account_invoice,1,1,1,192access_account_sequence_fiscal_year_invoice,account.sequence.fiscalyear invoice,model_account_sequence_fiscalyear,account.group_account_invoice,1,1,1,1
93access_account_tax_sale_manager,account.tax sale manager,model_account_tax,base.group_sale_salesman,1,0,0,093access_account_tax_sale_manager,account.tax sale manager,model_account_tax,base.group_sale_salesman,1,0,0,0
94access_account_journal_sale_manager,account.journal sale manager,model_account_journal,base.group_sale_salesman,1,0,0,094access_account_journal_sale_manager,account.journal sale manager,model_account_journal,base.group_sale_salesman,1,0,0,0
95access_account_invoice_tax_sale_manager,account.invoice.tax sale manager,model_account_invoice_tax,base.group_sale_salesman,1,0,0,095access_account_invoice_tax_sale_manager,account.invoice.tax sale manager,model_account_invoice_tax,base.group_sale_salesman,1,0,0,0
96access_account_sequence_fiscal_year_sale_user,account.sequence.fiscalyear.sale.user,model_account_sequence_fiscalyear,base.group_sale_salesman,1,1,1,096access_account_sequence_fiscal_year_sale_user,account.sequence.fiscalyear.sale.user,model_account_sequence_fiscalyear,base.group_sale_salesman,1,1,1,0
97access_account_sequence_fiscal_year_sale_manager,account.sequence.fiscalyear.sale.manager,model_account_sequence_fiscalyear,base.group_sale_manager,1,1,1,197access_account_sequence_fiscal_year_sale_manager,account.sequence.fiscalyear.sale.manager,model_account_sequence_fiscalyear,base.group_sale_manager,1,1,1,1
98access_account_treasury_report_manager,account.treasury.report.manager,model_account_treasury_report,account.group_account_manager,1,0,0,098access_account_treasury_report_manager,account.treasury.report.manager,model_account_treasury_report,account.group_account_manager,1,0,0,0
99access_account_financial_report,account.financial.report,model_account_financial_report,account.group_account_user,1,1,1,199access_account_financial_report,account.financial.report,model_account_financial_report,account.group_account_user,1,1,1,1
100access_account_financial_report_invoice,account.financial.report invoice,model_account_financial_report,account.group_account_invoice,1,0,0,0100access_account_financial_report_invoice,account.financial.report invoice,model_account_financial_report,account.group_account_invoice,1,0,0,0
101access_account_statement_operation_template,account.statement.operation.template,model_account_statement_operation_template,account.group_account_user,1,1,1,1
101102
=== added file 'account/static/src/css/account_bank_statement_reconciliation.css'
--- account/static/src/css/account_bank_statement_reconciliation.css 1970-01-01 00:00:00 +0000
+++ account/static/src/css/account_bank_statement_reconciliation.css 2014-05-30 16:18:57 +0000
@@ -0,0 +1,264 @@
1.openerp .oe_bank_statement_reconciliation {
2 font-size: 12px;
3 -webkit-user-select: none;
4 -moz-user-select: none;
5 -ms-user-select: none;
6 -o-user-select: none;
7 user-select: none;
8 cursor: default;
9 /* icons */ }
10 .openerp .oe_bank_statement_reconciliation h1 {
11 width: 48%;
12 padding: 0 0 0 15px;
13 margin: 0 0 35px 0;
14 float: left;
15 font-size: 2.3em; }
16 .openerp .oe_bank_statement_reconciliation h2 {
17 font-size: 1.8em; }
18 .openerp .oe_bank_statement_reconciliation .progress {
19 width: 49%;
20 margin: 6px 15px 0 0;
21 float: right;
22 position: relative;
23 display: inline-block; }
24 .openerp .oe_bank_statement_reconciliation .progress .progress-text {
25 text-align: center;
26 position: absolute;
27 width: 100%;
28 left: 0;
29 top: 2px;
30 z-index: 10;
31 text-shadow: -1px -1px 0 #f5f5f5, 1px -1px 0 #f5f5f5, -1px 1px 0 #f5f5f5, 1px 1px 0 #f5f5f5; }
32 .openerp .oe_bank_statement_reconciliation .oe_form_sheet {
33 position: relative;
34 padding-bottom: 30px; }
35 .openerp .oe_bank_statement_reconciliation .protip {
36 margin: 0;
37 position: absolute;
38 bottom: 7px;
39 right: 15px;
40 text-align: right;
41 color: #bbb; }
42 .openerp .oe_bank_statement_reconciliation .done_message {
43 width: 100%;
44 padding: 0 20%;
45 margin-top: 50px;
46 margin-bottom: 50px; }
47 .openerp .oe_bank_statement_reconciliation .done_message h2 {
48 margin-bottom: 30px; }
49 .openerp .oe_bank_statement_reconciliation .done_message h2 .congrats_icon {
50 float: right;
51 font-size: 2em;
52 position: relative;
53 top: -0.25em; }
54 .openerp .oe_bank_statement_reconciliation .done_message .achievements {
55 margin-top: 30px;
56 text-align: center;
57 position: relative; }
58 .openerp .oe_bank_statement_reconciliation .done_message .achievements .achievement {
59 font-size: 4em;
60 margin: 0 0.3em;
61 position: relative;
62 vertical-align: middle;
63 text-shadow: 2px 2px 0px rgba(0, 0, 0, 0.2); }
64 .openerp .oe_bank_statement_reconciliation .done_message .achievements .achievement i {
65 font-size: 0.5em;
66 color: white;
67 position: absolute;
68 top: 50%;
69 margin-top: -0.55em;
70 left: 0;
71 width: 100%;
72 text-align: center; }
73 .openerp .oe_bank_statement_reconciliation .done_message .action_buttons {
74 text-align: center; }
75 .openerp .oe_bank_statement_reconciliation .glyphicon {
76 font-size: 12px !important; }
77 .openerp .oe_bank_statement_reconciliation .glyphicon.line_info_button {
78 color: #ccc !important; }
79 .openerp .oe_bank_statement_reconciliation .accounting_view .glyphicon-add-remove:before {
80 content: "\2212"; }
81 .openerp .oe_bank_statement_reconciliation .match .glyphicon-add-remove:before {
82 content: "\2b"; }
83 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line {
84 margin-bottom: 30px;
85 /* gap between accounting_view and action view */
86 /* popover */
87 /* arrays of move lines */
88 /* Partie infos */
89 /* Match view */
90 /* Action create */ }
91 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line table {
92 width: 100%; }
93 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .toggle_match, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .toggle_create {
94 -webkit-transition-property: -webkit-transform;
95 -moz-transition-property: -moz-transform;
96 -ms-transition-property: -ms-transform;
97 -o-transition-property: -o-transform;
98 transition-property: transform;
99 -webkit-transform: rotate(0deg);
100 -moz-transform: rotate(0deg);
101 -ms-transform: rotate(0deg);
102 -o-transform: rotate(0deg);
103 transform: rotate(0deg); }
104 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .visible_toggle, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line[data-mode="match"] .toggle_match, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line[data-mode="create"] .toggle_create {
105 visibility: visible !important;
106 -webkit-transform: rotate(90deg);
107 -moz-transform: rotate(90deg);
108 -ms-transform: rotate(90deg);
109 -o-transform: rotate(90deg);
110 transform: rotate(90deg); }
111 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .change_partner_container {
112 width: 200px;
113 display: none;
114 position: relative !important; }
115 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line[data-mode="inactive"] .initial_line > td {
116 background-color: #f8f8f8 !important; }
117 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line.no_match:not(.no_partner) .initial_line {
118 cursor: default !important; }
119 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line.no_match:not(.no_partner) .initial_line .line_info_button {
120 cursor: pointer; }
121 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line.no_match:not(.no_partner) .toggle_match {
122 visibility: hidden !important; }
123 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line.no_partner .partner_name, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line.no_partner .line_open_balance {
124 display: none !important; }
125 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line > table > tbody > tr:nth-child(1) > td table {
126 margin-bottom: 10px; }
127 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line table.details td:first-child {
128 padding-right: 10px;
129 font-weight: bold; }
130 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table {
131 width: 100%; }
132 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view tr, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table tr {
133 cursor: pointer; }
134 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view tr.created_line, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table tr.created_line {
135 cursor: default !important; }
136 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view tr.created_line .line_remove_button, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table tr.created_line .line_remove_button {
137 cursor: pointer; }
138 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view td, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table td {
139 padding: 1px 8px;
140 vertical-align: middle; }
141 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view td:nth-child(1), .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view td:nth-child(7), .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table td:nth-child(1), .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table td:nth-child(7) {
142 width: 15px;
143 padding: 0; }
144 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view td:nth-child(1), .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table td:nth-child(1) {
145 text-align: left; }
146 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view td:nth-child(2), .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table td:nth-child(2) {
147 width: 80px;
148 padding-left: 3px; }
149 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view td:nth-child(3), .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table td:nth-child(3) {
150 width: 100px; }
151 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view td:nth-child(5), .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table td:nth-child(5) {
152 text-align: right;
153 width: 15%; }
154 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view td:nth-child(6), .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table td:nth-child(6) {
155 width: 15%;
156 text-align: right;
157 padding-right: 3px; }
158 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view td:nth-child(7), .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table td:nth-child(7) {
159 text-align: right; }
160 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view tr.line_open_balance, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table tr.line_open_balance {
161 color: #bbb; }
162 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view tr .glyphicon:not(.line_info_button), .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table tr .glyphicon:not(.line_info_button) {
163 visibility: hidden;
164 color: #555; }
165 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view tr:hover .glyphicon, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view tr.active .glyphicon, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table tr:hover .glyphicon, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table tr.active .glyphicon {
166 visibility: visible; }
167 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view tr .do_partial_reconcile_button, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table tr .do_partial_reconcile_button {
168 color: #f0ad4e;
169 padding-right: 5px; }
170 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view tr .undo_partial_reconcile_button, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table tr .undo_partial_reconcile_button {
171 color: #555;
172 padding-right: 5px; }
173 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view .initial_line > td {
174 border-top: 1px solid #bbbbbb;
175 padding-top: 4px;
176 padding-bottom: 5px;
177 background-color: #f0f0f0;
178 -webkit-transition-property: background-color;
179 -moz-transition-property: background-color;
180 -ms-transition-property: background-color;
181 transition-property: background-color; }
182 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view .initial_line > td:nth-child(1), .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view .initial_line > td:nth-child(7) {
183 border-top: none;
184 background: white !important;
185 padding-top: 6px;
186 padding-bottom: 3px; }
187 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view caption {
188 text-align: left;
189 font-size: 1.1em;
190 font-weight: bold;
191 height: 26px;
192 margin: 0 15px 4px 15px; }
193 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view caption .button_ok {
194 float: right; }
195 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view caption .button_ok:disabled {
196 opacity: 0.5; }
197 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view caption > span, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view caption > input {
198 position: relative;
199 top: 7px;
200 /* meh */
201 font-weight: bold;
202 cursor: pointer; }
203 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view td:nth-child(6) {
204 border-left: 1px solid black; }
205 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view tr.initial_line > td:nth-child(5) {
206 border-top: 1px solid black; }
207 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view tr.initial_line > td:nth-child(6) {
208 border-top: 1px solid black; }
209 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match .match_controls {
210 padding: 0 0 5px 18px; }
211 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match .match_controls .filter {
212 width: 240px; }
213 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match .match_controls .pager_control_left, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match .match_controls .pager_control_right {
214 display: inline-block;
215 cursor: pointer; }
216 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match .match_controls .pager_control_left {
217 margin-right: 10px; }
218 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match .match_controls .pager_control_left.disabled, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match .match_controls .pager_control_right.disabled {
219 color: #ddd;
220 cursor: default; }
221 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match .show_more {
222 display: inline-block;
223 margin-left: 18px;
224 margin-top: 5px; }
225 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create {
226 margin: 0 15px;
227 border: 1px solid #d5d5d5;
228 border-radius: 5px;
229 padding: 10px; }
230 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .quick_add {
231 margin-bottom: 10px;
232 clear: both; }
233 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .quick_add:empty {
234 display: none; }
235 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .quick_add:empty {
236 display: none; }
237 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .oe_form > table {
238 width: 49%;
239 height: 26px; }
240 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .oe_form > table:nth-child(2n+1) {
241 float: left; }
242 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .oe_form > table:nth-child(2n) {
243 float: right; }
244 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .oe_form > table th {
245 font-weight: bold;
246 line-height: 26px;
247 padding-right: 8px;
248 min-width: 100px;
249 border-right: 1px solid #ddd;
250 white-space: nowrap;
251 width: 1%; }
252 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .oe_form > table td {
253 width: 99%;
254 padding-left: 8px; }
255 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .oe_form > table input, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .oe_form > table select {
256 width: 100%; }
257 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .oe_form > table.add_line_container:nth-child(2n+1) {
258 width: 98%;
259 float: none;
260 margin: auto; }
261 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .oe_form > table.add_line_container td {
262 text-align: center; }
263 .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .oe_form > table.add_line_container .add_line {
264 line-height: 26px; }
0265
=== added file 'account/static/src/css/account_bank_statement_reconciliation.scss'
--- account/static/src/css/account_bank_statement_reconciliation.scss 1970-01-01 00:00:00 +0000
+++ account/static/src/css/account_bank_statement_reconciliation.scss 2014-05-30 16:18:57 +0000
@@ -0,0 +1,447 @@
1$actionColWidth: 15px;
2$mainTableBordersPadding: 3px;
3$lightBorder: 1px solid #bbb;
4$accountingBorder: 1px solid #000;
5$initialLineBackground: #f0f0f0;
6
7
8.openerp .oe_bank_statement_reconciliation {
9 font-size: 12px;
10 -webkit-user-select: none;
11 -moz-user-select: none;
12 -ms-user-select: none;
13 -o-user-select: none;
14 user-select: none;
15 cursor: default;
16
17 h1 {
18 width: 48%;
19 padding: 0 0 0 $actionColWidth;
20 margin: 0 0 35px 0;
21 float: left;
22 font-size: 2.3em;
23 }
24
25 h2 {
26 font-size: 1.8em;
27 }
28
29 .progress {
30 width: 49%;
31 margin: 6px $actionColWidth 0 0;
32 float: right;
33 position: relative;
34 display: inline-block;
35
36 .progress-text {
37 text-align: center;
38 position: absolute;
39 width: 100%;
40 left: 0;
41 top: 2px;
42 z-index: 10;
43 text-shadow:
44 -1px -1px 0 #f5f5f5,
45 1px -1px 0 #f5f5f5,
46 -1px 1px 0 #f5f5f5,
47 1px 1px 0 #f5f5f5;
48 }
49 }
50
51 .oe_form_sheet {
52 position: relative;
53 padding-bottom: 30px;
54 }
55
56 .protip {
57 margin: 0;
58 position: absolute;
59 bottom: 7px;
60 right: 15px;
61 text-align: right;
62 color: #bbb;
63 }
64
65 .done_message {
66 width: 100%;
67 padding: 0 20%;
68 margin-top: 50px;
69 margin-bottom: 50px;
70
71 h2 {
72 margin-bottom: 30px;
73
74 .congrats_icon {
75 float: right;
76 font-size: 2em;
77 position: relative;
78 top: -0.25em;
79 }
80 }
81
82 .achievements {
83 margin-top: 30px;
84 text-align: center;
85 position: relative;
86
87 .achievement {
88 font-size: 4em;
89 margin: 0 0.3em;
90 position: relative;
91 vertical-align: middle;
92 text-shadow: 2px 2px 0px rgba(0,0,0,0.2);
93
94 i {
95 font-size: 0.5em;
96 color: white;
97 position: absolute;
98 top: 50%;
99 margin-top: -0.55em;
100 left: 0;
101 width: 100%;
102 text-align: center;
103 //text-shadow: 1px 1px 0 black;
104 }
105 }
106 }
107
108 .action_buttons {
109 text-align: center;
110 }
111 }
112
113 /* icons */
114 .glyphicon {
115 font-size: 12px !important;
116
117 &.line_info_button {
118 color: #ccc !important;
119 }
120 }
121 .accounting_view .glyphicon-add-remove:before {
122 content: "\2212";
123 }
124 .match .glyphicon-add-remove:before {
125 content: "\2b";
126 }
127
128 // bankStatementReconciliationLine widget
129 .oe_bank_statement_reconciliation_line {
130 margin-bottom: 30px;
131
132 table {
133 width: 100%;
134 }
135
136 // modes : default
137 .toggle_match, .toggle_create {
138 -webkit-transition-property: -webkit-transform;
139 -moz-transition-property: -moz-transform;
140 -ms-transition-property: -ms-transform;
141 -o-transition-property: -o-transform;
142 transition-property: transform;
143 -webkit-transform: rotate(0deg);
144 -moz-transform: rotate(0deg);
145 -ms-transform: rotate(0deg);
146 -o-transform: rotate(0deg);
147 transform: rotate(0deg);
148 }
149
150 .visible_toggle {
151 visibility: visible !important;
152 -webkit-transform: rotate(90deg);
153 -moz-transform: rotate(90deg);
154 -ms-transform: rotate(90deg);
155 -o-transform: rotate(90deg);
156 transform: rotate(90deg);
157 }
158
159 .change_partner_container {
160 width: 200px;
161 display: none;
162 position: relative !important;
163 }
164
165 // modes : specific
166 &[data-mode="match"] {
167 .toggle_match {
168 @extend .visible_toggle;
169 }
170 }
171
172 &[data-mode="create"] {
173 .toggle_create {
174 @extend .visible_toggle;
175 }
176 }
177
178 &[data-mode="inactive"] {
179 .initial_line > td {
180 background-color: ($initialLineBackground + #080808) !important;
181 }
182 }
183
184 &.no_match:not(.no_partner) {
185 .initial_line {
186 cursor: default !important;
187
188 .line_info_button {
189 cursor: pointer;
190 }
191 }
192 .toggle_match {
193 visibility: hidden !important;
194 }
195 }
196
197 &.no_partner {
198 .partner_name, .line_open_balance {
199 display: none !important;
200 }
201 }
202
203 /* gap between accounting_view and action view */
204 > table > tbody > tr:nth-child(1) > td table {
205 margin-bottom: 10px;
206 }
207
208 /* popover */
209 table.details {
210 td:first-child {
211 padding-right: 10px;
212 font-weight: bold;
213 }
214 }
215
216 /* arrays of move lines */
217 .accounting_view, .match table {
218 width: 100%;
219
220 tr {
221 cursor: pointer;
222
223 &.created_line {
224 cursor: default !important;
225
226 .line_remove_button {
227 cursor: pointer;
228 }
229 }
230 }
231
232 td {
233 padding: 1px 8px;
234 vertical-align: middle;
235 }
236
237 td:nth-child(1), td:nth-child(7) {
238 width: $actionColWidth;
239 padding: 0;
240 }
241
242 td:nth-child(1) {
243 text-align: left;
244 }
245
246 td:nth-child(2) {
247 width: 80px;
248 padding-left: $mainTableBordersPadding;
249 }
250
251 td:nth-child(3) {
252 width: 100px;
253 }
254
255 td:nth-child(4) {
256
257 }
258
259 td:nth-child(5) {
260 text-align: right;
261 width: 15%;
262 }
263
264 td:nth-child(6) {
265 width: 15%;
266 text-align: right;
267 padding-right: $mainTableBordersPadding;
268 }
269
270 td:nth-child(7) {
271 text-align: right;
272 }
273
274 tr.line_open_balance {
275 color: #bbb;
276 }
277
278 tr .glyphicon:not(.line_info_button) {
279 visibility: hidden;
280 color: #555;
281 }
282
283 tr:hover .glyphicon, tr.active .glyphicon {
284 visibility: visible;
285 }
286
287 tr .do_partial_reconcile_button {
288 color: #f0ad4e;
289 padding-right: 5px;
290 }
291
292 tr .undo_partial_reconcile_button {
293 color: #555;
294 padding-right: 5px;
295 }
296 }
297
298 /* Partie infos */
299 .accounting_view {
300
301 .initial_line > td {
302 border-top: $lightBorder;
303 padding-top: 4px;
304 padding-bottom: 5px;
305 background-color: $initialLineBackground;
306 -webkit-transition-property: background-color;
307 -moz-transition-property: background-color;
308 -ms-transition-property: background-color;
309 transition-property: background-color;
310
311 &:nth-child(1), &:nth-child(7) {
312 border-top: none;
313 background: white !important;
314 // Hack pour l'alignement au px près
315 padding-top: 6px;
316 padding-bottom: 3px;
317 }
318 }
319
320 caption {
321 text-align: left;
322 font-size: 1.1em;
323 font-weight: bold;
324 height: 26px;
325 margin: 0 $actionColWidth 4px $actionColWidth;
326
327 .button_ok {
328 float: right;
329
330 &:disabled {
331 opacity: 0.5;
332 }
333 }
334
335 > span, > input {
336 position: relative; top: 7px; /* meh */
337 font-weight: bold;
338 cursor: pointer;
339 }
340 }
341
342 // accounting "T"
343 td:nth-child(6) { border-left: $accountingBorder; }
344 tr.initial_line > td {
345 &:nth-child(5) { border-top: $accountingBorder; }
346 &:nth-child(6) { border-top: $accountingBorder; }
347 }
348 }
349
350
351 /* Match view */
352 .match {
353
354 .match_controls {
355 padding: 0 0 5px ($actionColWidth+$mainTableBordersPadding);
356
357 .filter {
358 width: 240px;
359 }
360
361 .pager_control_left, .pager_control_right {
362 display: inline-block;
363 cursor: pointer;
364 }
365
366 .pager_control_left {
367 margin-right: 10px;
368 }
369
370 .pager_control_left.disabled, .pager_control_right.disabled {
371 color: #ddd;
372 cursor: default;
373 }
374 }
375
376 .show_more {
377 display: inline-block;
378 margin-left: ($actionColWidth+$mainTableBordersPadding);
379 margin-top: 5px;
380 }
381 }
382
383
384 /* Action create */
385 .create {
386 margin: 0 $actionColWidth;
387 border: 1px solid #d5d5d5;
388 border-radius: 5px;
389 padding: 10px;
390
391 .quick_add {
392 margin-bottom: 10px;
393 clear: both;
394
395 &:empty {
396 display: none;
397 }
398 }
399 .quick_add:empty {
400 display: none;
401 }
402
403 .oe_form > table {
404 width: 49%;
405 height: 26px;
406
407 &:nth-child(2n+1) { float: left; }
408 &:nth-child(2n) { float: right; }
409
410 th {
411 font-weight: bold;
412 line-height: 26px;
413 padding-right: 8px;
414 min-width: 100px;
415 border-right: 1px solid #ddd;
416 white-space: nowrap;
417 width: 1%;
418 }
419
420 td {
421 width: 99%;
422 padding-left: 8px;
423 }
424
425 input, select {
426 width: 100%;
427 }
428
429 &.add_line_container {
430 &:nth-child(2n+1) {
431 width: 98%;
432 float: none;
433 margin: auto;
434 }
435
436 td {
437 text-align: center;
438 }
439
440 .add_line {
441 line-height: 26px;
442 }
443 }
444 }
445 }
446 }
447}
0448
=== renamed file 'account/static/src/js/account_move_reconciliation.js' => 'account/static/src/js/account_widgets.js'
--- account/static/src/js/account_move_reconciliation.js 2014-04-11 12:28:40 +0000
+++ account/static/src/js/account_widgets.js 2014-05-30 16:18:57 +0000
@@ -6,6 +6,1474 @@
6 6
7 instance.web.account = instance.web.account || {};7 instance.web.account = instance.web.account || {};
8 8
9 instance.web.client_actions.add('bank_statement_reconciliation_view', 'instance.web.account.bankStatementReconciliation');
10 instance.web.account.bankStatementReconciliation = instance.web.Widget.extend({
11 className: 'oe_bank_statement_reconciliation',
12
13 init: function(parent, context) {
14 this._super(parent);
15 this.max_reconciliations_displayed = 10;
16 this.statement_id = context.context.statement_id;
17 this.title = context.context.title || _t("Reconciliation");
18 this.st_lines = [];
19 this.last_displayed_reconciliation_index = undefined; // Flow control
20 this.reconciled_lines = 0; // idem
21 this.already_reconciled_lines = 0; // Number of lines of the statement which were already reconciled
22 this.model_bank_statement = new instance.web.Model("account.bank.statement");
23 this.model_bank_statement_line = new instance.web.Model("account.bank.statement.line");
24 this.reconciliation_menu_id = false; // Used to update the needaction badge
25 this.formatCurrency; // Method that formats the currency ; loaded from the server
26
27 // Only for statistical purposes
28 this.lines_reconciled_with_ctrl_enter = 0;
29 this.time_widget_loaded = Date.now();
30
31 // Stuff used by the children bankStatementReconciliationLine
32 this.max_move_lines_displayed = 5;
33 this.animation_speed = 100; // "Blocking" animations
34 this.aestetic_animation_speed = 300; // eye candy
35 this.map_tax_id_amount = {};
36 this.presets = {};
37 // We'll need to get the code of an account selected in a many2one (whose value is the id)
38 this.map_account_id_code = {};
39 // The same move line cannot be selected for multiple resolutions
40 this.excluded_move_lines_ids = {};
41 // Description of the fields to initialize in the "create new line" form
42 // NB : for presets to work correctly, a field id must be the same string as a preset field
43 this.create_form_fields = {
44 account_id: {
45 id: "account_id",
46 index: 0,
47 corresponding_property: "account_id", // a account.move field name
48 label: _t("Account"),
49 required: true,
50 tabindex: 10,
51 constructor: instance.web.form.FieldMany2One,
52 field_properties: {
53 relation: "account.account",
54 string: _t("Account"),
55 type: "many2one",
56 domain: [['type','!=','view']],
57 },
58 },
59 label: {
60 id: "label",
61 index: 1,
62 corresponding_property: "label",
63 label: _t("Label"),
64 required: true,
65 tabindex: 11,
66 constructor: instance.web.form.FieldChar,
67 field_properties: {
68 string: _t("Label"),
69 type: "char",
70 },
71 },
72 tax_id: {
73 id: "tax_id",
74 index: 2,
75 corresponding_property: "tax_id",
76 label: _t("Tax"),
77 required: false,
78 tabindex: 12,
79 constructor: instance.web.form.FieldMany2One,
80 field_properties: {
81 relation: "account.tax",
82 string: _t("Tax"),
83 type: "many2one",
84 },
85 },
86 amount: {
87 id: "amount",
88 index: 3,
89 corresponding_property: "amount",
90 label: _t("Amount"),
91 required: true,
92 tabindex: 13,
93 constructor: instance.web.form.FieldFloat,
94 field_properties: {
95 string: _t("Amount"),
96 type: "float",
97 },
98 },
99 analytic_account_id: {
100 id: "analytic_account_id",
101 index: 4,
102 corresponding_property: "analytic_account_id",
103 label: _t("Analytic Acc."),
104 required: false,
105 tabindex: 14,
106 group:"analytic.group_analytic_accounting",
107 constructor: instance.web.form.FieldMany2One,
108 field_properties: {
109 relation: "account.analytic.account",
110 string: _t("Analytic Acc."),
111 type: "many2one",
112 },
113 },
114 };
115 },
116
117 start: function() {
118 this._super();
119 var self = this;
120
121 // Inject variable styles
122 var style = document.createElement("style");
123 style.appendChild(document.createTextNode(""));
124 document.head.appendChild(style);
125 var css_selector = ".oe_bank_statement_reconciliation_line .toggle_match, .oe_bank_statement_reconciliation_line .toggle_create, .oe_bank_statement_reconciliation_line .initial_line > td";
126 if(style.sheet.insertRule) {
127 style.sheet.insertRule(css_selector + " { -webkit-transition-duration: "+self.aestetic_animation_speed+"ms; }", 0);
128 style.sheet.insertRule(css_selector + " { -moz-transition-duration: "+self.aestetic_animation_speed+"ms; }", 0);
129 style.sheet.insertRule(css_selector + " { -ms-transition-duration: "+self.aestetic_animation_speed+"ms; }", 0);
130 style.sheet.insertRule(css_selector + " { -o-transition-duration: "+self.aestetic_animation_speed+"ms; }", 0);
131 style.sheet.insertRule(css_selector + " { transition-duration: "+self.aestetic_animation_speed+"ms; }", 0);
132 } else {
133 style.sheet.addRule(css_selector, "-webkit-transition-duration: "+self.aestetic_animation_speed+"ms;");
134 style.sheet.addRule(css_selector, "-moz-transition-duration: "+self.aestetic_animation_speed+"ms;");
135 style.sheet.addRule(css_selector, "-ms-transition-duration: "+self.aestetic_animation_speed+"ms;");
136 style.sheet.addRule(css_selector, "-o-transition-duration: "+self.aestetic_animation_speed+"ms;");
137 style.sheet.addRule(css_selector, "-webkit-transition-duration: "+self.aestetic_animation_speed+"ms;");
138 }
139
140 // Retreive statement infos and reconciliation data from the model
141 var lines_filter = [['journal_entry_id', '=', false]];
142 var deferred_promises = [];
143
144 if (self.statement_id) {
145 lines_filter.push(['statement_id', '=', self.statement_id]);
146 deferred_promises.push(self.model_bank_statement
147 .query(["name"])
148 .filter([['id', '=', self.statement_id]])
149 .first()
150 .then(function(title){
151 self.title = title.name;
152 })
153 );
154 deferred_promises.push(self.model_bank_statement
155 .call("number_of_lines_reconciled", [self.statement_id])
156 .then(function(num) {
157 self.already_reconciled_lines = num;
158 })
159 );
160 }
161
162 deferred_promises.push(new instance.web.Model("account.statement.operation.template")
163 .query(['id','name','account_id','label','amount_type','amount','tax_id','analytic_account_id'])
164 .all().then(function (data) {
165 _(data).each(function(preset){
166 self.presets[preset.id] = preset;
167 });
168 })
169 );
170
171 deferred_promises.push(self.model_bank_statement
172 .call("get_format_currency_js_function", [self.statement_id])
173 .then(function(data){
174 self.formatCurrency = new Function("amount", data);
175 })
176 );
177
178 deferred_promises.push(self.model_bank_statement_line
179 .query(['id'])
180 .filter(lines_filter)
181 .order_by('id')
182 .all().then(function (data) {
183 self.st_lines = _(data).map(function(o){ return o.id });
184 })
185 );
186
187 // When queries are done, render template and reconciliation lines
188 return $.when.apply($, deferred_promises).then(function(){
189
190 // If there is no statement line to reconcile, stop here
191 if (self.st_lines.length === 0) {
192 self.$el.prepend(QWeb.render("bank_statement_nothing_to_reconcile"));
193 return;
194 }
195
196 // Create a dict account id -> account code for display facilities
197 new instance.web.Model("account.account")
198 .query(['id', 'code'])
199 .all().then(function(data) {
200 _.each(data, function(o) { self.map_account_id_code[o.id] = o.code });
201 });
202
203 // Create a dict tax id -> amount
204 new instance.web.Model("account.tax")
205 .query(['id', 'amount'])
206 .all().then(function(data) {
207 _.each(data, function(o) { self.map_tax_id_amount[o.id] = o.amount });
208 });
209
210 new instance.web.Model("ir.model.data")
211 .call("xmlid_to_res_id", ["account.menu_bank_reconcile_bank_statements"])
212 .then(function(data) {
213 self.reconciliation_menu_id = data;
214 self.doReloadMenuReconciliation();
215 });
216
217 // Bind keyboard events TODO : méthode standard ?
218 $("body").on("keypress", function (e) {
219 self.keyboardShortcutsHandler(e);
220 });
221
222 // Render and display
223 self.$el.prepend(QWeb.render("bank_statement_reconciliation", {title: self.title, total_lines: self.already_reconciled_lines+self.st_lines.length}));
224 self.updateProgressbar();
225 var reconciliations_to_show = self.st_lines.slice(0, self.max_reconciliations_displayed);
226 self.last_displayed_reconciliation_index = reconciliations_to_show.length;
227 self.$(".reconciliation_lines_container").css("opacity", 0);
228
229 // Display the reconciliations
230 return self.model_bank_statement_line
231 .call("get_data_for_reconciliations", [reconciliations_to_show])
232 .then(function (data) {
233 var child_promises = [];
234 _.each(reconciliations_to_show, function(st_line_id){
235 var datum = data.shift();
236 child_promises.push(self.displayReconciliation(st_line_id, 'inactive', false, true, datum.st_line, datum.reconciliation_proposition));
237 });
238 $.when.apply($, child_promises).then(function(){
239 self.getChildren()[0].set("mode", "match");
240 self.$(".reconciliation_lines_container").animate({opacity: 1}, self.aestetic_animation_speed);
241 });
242 });
243 });
244 },
245
246 keyboardShortcutsHandler: function(e) {
247 var self = this;
248 if (e.which === 13 && (e.ctrlKey || e.metaKey)) {
249 $.each(self.getChildren(), function(i, o){
250 if (o.is_valid && o.persistAndDestroy()) {
251 self.lines_reconciled_with_ctrl_enter++;
252 }
253 });
254 }
255 },
256
257 // Adds move line ids to the list of move lines not to fetch for a given partner
258 // This is required because the same move line cannot be selected for multiple reconciliation
259 excludeMoveLines: function(source_child, partner_id, line_ids) {
260 var self = this;
261
262 var excluded_ids = this.excluded_move_lines_ids[partner_id];
263 var excluded_move_lines_changed = false;
264 _.each(line_ids, function(line_id){
265 if (excluded_ids.indexOf(line_id) === -1) {
266 excluded_ids.push(line_id);
267 excluded_move_lines_changed = true;
268 }
269 });
270 if (! excluded_move_lines_changed)
271 return;
272
273 // Function that finds if an array of line objects contains at least a line identified by its id
274 var contains_lines = function(lines_array, line_ids) {
275 for (var i = 0; i < lines_array.length; i++)
276 for (var j = 0; j < line_ids.length; j++)
277 if (lines_array[i].id === line_ids[j])
278 return true;
279 return false;
280 };
281
282 // Update children if needed
283 _.each(self.getChildren(), function(child){
284 if (child.partner_id === partner_id && child !== source_child) {
285 if (contains_lines(child.get("mv_lines_selected"), line_ids)) {
286 child.set("mv_lines_selected", _.filter(child.get("mv_lines_selected"), function(o){ return line_ids.indexOf(o.id) === -1 }));
287 } else if (contains_lines(child.mv_lines_deselected, line_ids)) {
288 child.mv_lines_deselected = _.filter(child.mv_lines_deselected, function(o){ return line_ids.indexOf(o.id) === -1 });
289 child.updateMatches();
290 } else if (contains_lines(child.get("mv_lines"), line_ids)) {
291 child.updateMatches();
292 }
293 }
294 });
295 },
296
297 unexcludeMoveLines: function(source_child, partner_id, line_ids) {
298 var self = this;
299
300 var initial_excluded_lines_num = this.excluded_move_lines_ids[partner_id].length;
301 this.excluded_move_lines_ids[partner_id] = _.difference(this.excluded_move_lines_ids[partner_id], line_ids);
302 if (this.excluded_move_lines_ids[partner_id].length === initial_excluded_lines_num)
303 return;
304
305 // Update children if needed
306 _.each(self.getChildren(), function(child){
307 if (child.partner_id === partner_id && child !== source_child && (child.get("mode") === "match" || child.$el.hasClass("no_match")))
308 child.updateMatches();
309 });
310 },
311
312 displayReconciliation: function(st_line_id, mode, animate_entrance, initial_data_provided, st_line, reconciliation_proposition) {
313 var self = this;
314 animate_entrance = (animate_entrance === undefined ? true : animate_entrance);
315 initial_data_provided = (initial_data_provided === undefined ? false : initial_data_provided);
316
317 var context = {
318 st_line_id: st_line_id,
319 mode: mode,
320 animate_entrance: animate_entrance,
321 initial_data_provided: initial_data_provided,
322 st_line: initial_data_provided ? st_line : undefined,
323 reconciliation_proposition: initial_data_provided ? reconciliation_proposition : undefined,
324 };
325 var widget = new instance.web.account.bankStatementReconciliationLine(self, context);
326 return widget.appendTo(self.$(".reconciliation_lines_container"));
327 },
328
329 childValidated: function(child) {
330 var self = this;
331
332 self.reconciled_lines++;
333 self.updateProgressbar();
334 self.doReloadMenuReconciliation();
335
336 // Display new line if there are left
337 if (self.last_displayed_reconciliation_index < self.st_lines.length) {
338 self.displayReconciliation(self.st_lines[self.last_displayed_reconciliation_index++], 'inactive');
339 }
340 // Put the first line in match mode
341 if (self.reconciled_lines !== self.st_lines.length) {
342 var first_child = self.getChildren()[0];
343 if (first_child.get("mode") === "inactive") {
344 first_child.set("mode", "match");
345 }
346 }
347 // Congratulate the user if the work is done
348 if (self.reconciled_lines === self.st_lines.length) {
349 self.displayDoneMessage();
350 }
351 },
352
353 displayDoneMessage: function() {
354 var self = this;
355
356 var sec_taken = Math.round((Date.now()-self.time_widget_loaded)/1000);
357 var sec_per_item = Math.round(sec_taken/self.reconciled_lines);
358 var achievements = [];
359
360 var time_taken;
361 if (sec_taken/60 >= 1) time_taken = Math.floor(sec_taken/60) +"' "+ sec_taken%60 +"''";
362 else time_taken = sec_taken%60 +" seconds";
363
364 var title;
365 if (sec_per_item < 5) title = _t("Whew, that was fast !") + " <i class='fa fa-trophy congrats_icon'></i>";
366 else title = _t("Congrats, you're all done !") + " <i class='fa fa-thumbs-o-up congrats_icon'></i>";
367
368 if (self.lines_reconciled_with_ctrl_enter === self.reconciled_lines)
369 achievements.push({
370 title: _t("Efficiency at its finest"),
371 desc: _t("Only use the ctrl-enter shortcut to validate reconciliations."),
372 icon: "fa-keyboard-o"}
373 );
374
375 if (sec_per_item < 5)
376 achievements.push({
377 title: _t("Fast reconciler"),
378 desc: _t("Take on average less than 5 seconds to reconcile a transaction."),
379 icon: "fa-bolt"}
380 );
381
382 // Render it
383 self.$(".protip").hide();
384 self.$(".oe_form_sheet").append(QWeb.render("bank_statement_reconciliation_done_message", {
385 title: title,
386 time_taken: time_taken,
387 sec_per_item: sec_per_item,
388 transactions_done: self.reconciled_lines,
389 done_with_ctrl_enter: self.lines_reconciled_with_ctrl_enter,
390 achievements: achievements,
391 has_statement_id: self.statement_id !== undefined,
392 }));
393
394 // Animate it
395 var container = $("<div style='overflow: hidden;' />");
396 self.$(".done_message").wrap(container).css("opacity", 0).css("position", "relative").css("left", "-50%");
397 self.$(".done_message").animate({opacity: 1, left: 0}, self.aestetic_animation_speed*2, "easeOutCubic");
398 self.$(".done_message").animate({opacity: 1}, self.aestetic_animation_speed*3, "easeOutCubic");
399
400 // Make it interactive
401 self.$(".achievement").popover({'placement': 'top', 'container': self.el, 'trigger': 'hover'});
402
403 self.$(".button_back_to_statement").click(function() {
404 self.do_action({
405 type: 'ir.actions.client',
406 tag: 'history_back',
407 });
408 });
409
410 if (self.$(".button_close_statement").length !== 0) {
411 self.$(".button_close_statement").hide();
412 self.model_bank_statement
413 .query(["balance_end_real", "balance_end"])
414 .filter([['id', '=', self.statement_id]])
415 .first()
416 .then(function(data){
417 if (data.balance_end_real === data.balance_end) {
418 self.$(".button_close_statement").show();
419 self.$(".button_close_statement").click(function() {
420 self.$(".button_close_statement").attr("disabled", "disabled");
421 self.model_bank_statement
422 .call("button_confirm_bank", [[self.statement_id]])
423 .then(function () {
424 self.do_action({
425 type: 'ir.actions.client',
426 tag: 'history_back',
427 });
428 }, function() {
429 self.$(".button_close_statement").removeAttr("disabled");
430 });
431 });
432 }
433 });
434 }
435 },
436
437 updateProgressbar: function() {
438 var self = this;
439 var done = self.already_reconciled_lines + self.reconciled_lines;
440 var total = self.already_reconciled_lines + self.st_lines.length;
441 var prog_bar = self.$(".progress .progress-bar");
442 prog_bar.attr("aria-valuenow", done);
443 prog_bar.css("width", (done/total*100)+"%");
444 self.$(".progress .progress-text .valuenow").text(done);
445 },
446
447 /* reloads the needaction badge */
448 doReloadMenuReconciliation: function () {
449 var menu = instance.webclient.menu;
450 if (!menu || !this.reconciliation_menu_id) {
451 return $.when();
452 }
453 return menu.rpc("/web/menu/load_needaction", {'menu_ids': [this.reconciliation_menu_id]}).done(function(r) {
454 menu.on_needaction_loaded(r);
455 }).then(function () {
456 menu.trigger("need_action_reloaded");
457 });
458 },
459 });
460
461 instance.web.account.bankStatementReconciliationLine = instance.web.Widget.extend({
462 className: 'oe_bank_statement_reconciliation_line',
463
464 events: {
465 "click .partner_name": "partnerNameClickHandler",
466 "click .button_ok": "persistAndDestroy",
467 "click .mv_line": "moveLineClickHandler",
468 "click .initial_line": "initialLineClickHandler",
469 "click .line_open_balance": "lineOpenBalanceClickHandler",
470 "click .pager_control_left:not(.disabled)": "pagerControlLeftHandler",
471 "click .pager_control_right:not(.disabled)": "pagerControlRightHandler",
472 "keyup .filter": "filterHandler",
473 "click .line_info_button": function(e){e.stopPropagation()}, // small usability hack
474 "click .add_line": "addLineBeingEdited",
475 "click .preset": "presetClickHandler",
476 "click .do_partial_reconcile_button": "doPartialReconcileButtonClickHandler",
477 "click .undo_partial_reconcile_button": "undoPartialReconcileButtonClickHandler",
478 },
479
480 init: function(parent, context) {
481 this._super(parent);
482
483 if (context.initial_data_provided) {
484 // Process data
485 _(context.reconciliation_proposition).each(this.decorateMoveLine.bind(this));
486 this.set("mv_lines_selected", context.reconciliation_proposition);
487 this.st_line = context.st_line;
488 this.partner_id = context.st_line.partner_id;
489 this.decorateStatementLine(this.st_line);
490
491 // Exclude selected move lines
492 var selected_line_ids = _(context.reconciliation_proposition).map(function(o){ return o.id });
493 if (this.getParent().excluded_move_lines_ids[this.partner_id] === undefined)
494 this.getParent().excluded_move_lines_ids[this.partner_id] = [];
495 this.getParent().excludeMoveLines(this, this.partner_id, selected_line_ids);
496 } else {
497 this.set("mv_lines_selected", []);
498 this.st_line = undefined;
499 this.partner_id = undefined;
500 }
501
502 this.context = context;
503 this.st_line_id = context.st_line_id;
504 this.max_move_lines_displayed = this.getParent().max_move_lines_displayed;
505 this.animation_speed = this.getParent().animation_speed;
506 this.aestetic_animation_speed = this.getParent().aestetic_animation_speed;
507 this.model_bank_statement_line = new instance.web.Model("account.bank.statement.line");
508 this.model_res_users = new instance.web.Model("res.users");
509 this.model_tax = new instance.web.Model("account.tax");
510 this.map_account_id_code = this.getParent().map_account_id_code;
511 this.map_tax_id_amount = this.getParent().map_tax_id_amount;
512 this.formatCurrency = this.getParent().formatCurrency;
513 this.presets = this.getParent().presets;
514 this.is_valid = true;
515 this.is_consistent = true; // Used to prevent bad server requests
516 this.total_move_lines_num = undefined; // Used for pagers
517 this.filter = "";
518
519 this.set("balance", undefined); // Debit is +, credit is -
520 this.on("change:balance", this, this.balanceChanged);
521 this.set("mode", undefined);
522 this.on("change:mode", this, this.modeChanged);
523 this.set("pager_index", 0);
524 this.on("change:pager_index", this, this.pagerChanged);
525 // NB : mv_lines represent the counterpart that will be created to reconcile existing move lines, so debit and credit are inverted
526 this.set("mv_lines", []);
527 this.on("change:mv_lines", this, this.mvLinesChanged);
528 this.mv_lines_deselected = []; // deselected lines are displayed on top of the match table
529 this.on("change:mv_lines_selected", this, this.mvLinesSelectedChanged);
530 this.set("lines_created", []);
531 this.set("line_created_being_edited", [{'id': 0}]);
532 this.on("change:lines_created", this, this.createdLinesChanged);
533 this.on("change:line_created_being_edited", this, this.createdLinesChanged);
534 },
535
536 start: function() {
537 var self = this;
538 return self._super().then(function() {
539 // no animation while loading
540 self.animation_speed = 0;
541 self.aestetic_animation_speed = 0;
542
543 self.is_consistent = false;
544 if (self.context.animate_entrance) self.$el.css("opacity", "0");
545
546 // Fetch data
547 var deferred_fetch_data = new $.Deferred();
548 if (! self.context.initial_data_provided) {
549 // Load statement line
550 self.model_bank_statement_line
551 .call("get_statement_line_for_reconciliation", [self.st_line_id])
552 .then(function (data) {
553 self.st_line = data;
554 self.decorateStatementLine(self.st_line);
555 self.partner_id = data.partner_id;
556 if (self.getParent().excluded_move_lines_ids[self.partner_id] === undefined)
557 self.getParent().excluded_move_lines_ids[self.partner_id] = [];
558 // load and display move lines
559 $.when(self.loadReconciliationProposition()).then(function(){
560 deferred_fetch_data.resolve();
561 });
562 });
563 } else {
564 deferred_fetch_data.resolve();
565 }
566
567 // Display the widget
568 return $.when(deferred_fetch_data).then(function(){
569 // Render template
570 var presets_array = [];
571 for (var id in self.presets)
572 if (self.presets.hasOwnProperty(id))
573 presets_array.push(self.presets[id]);
574 self.$el.prepend(QWeb.render("bank_statement_reconciliation_line", {line: self.st_line, mode: self.context.mode, presets: presets_array}));
575
576 // Stuff that require the template to be rendered
577 self.$(".match").slideUp(0);
578 self.$(".create").slideUp(0);
579 if (self.st_line.no_match) self.$el.addClass("no_match");
580 if (self.context.mode !== "match") self.updateMatches();
581 self.bindPopoverTo(self.$(".line_info_button"));
582 self.createFormWidgets();
583
584 // Special case hack : no identified partner
585 if (self.st_line.has_no_partner) {
586 self.$el.css("opacity", "0");
587 self.updateBalance();
588 self.$(".change_partner_container").show(0);
589 self.change_partner_field.$el.find("input").attr("placeholder", _t("Select Partner"));
590 self.$(".match").slideUp(0);
591 self.$el.addClass("no_partner");
592 self.set("mode", self.context.mode);
593 self.animation_speed = self.getParent().animation_speed;
594 self.aestetic_animation_speed = self.getParent().aestetic_animation_speed;
595 self.$el.animate({opacity: 1}, self.aestetic_animation_speed);
596 self.is_consistent = true;
597 return;
598 }
599
600 // TODO : the .on handler's returned deferred is lost
601 return $.when(self.set("mode", self.context.mode)).then(function(){
602 self.is_consistent = true;
603
604 // Make sure the display is OK
605 self.balanceChanged();
606 self.createdLinesChanged();
607 self.updateAccountingViewMatchedLines();
608
609 // Make an entrance
610 self.animation_speed = self.getParent().animation_speed;
611 self.aestetic_animation_speed = self.getParent().aestetic_animation_speed;
612 if (self.context.animate_entrance) return self.$el.animate({opacity: 1}, self.aestetic_animation_speed);
613 });
614 });
615 });
616 },
617
618 restart: function(mode) {
619 var self = this;
620 mode = (mode === undefined ? 'inactive' : mode);
621 self.$el.css("height", self.$el.outerHeight());
622 // Destroy everything
623 _.each(self.getChildren(), function(o){ o.destroy() });
624 self.is_consistent = false;
625 return $.when(self.$el.animate({opacity: 0}, self.animation_speed)).then(function() {
626 self.getParent().unexcludeMoveLines(self, self.partner_id, _.map(self.get("mv_lines_selected"), function(o){ return o.id }));
627 $.each(self.$(".bootstrap_popover"), function(){ $(this).popover('destroy') });
628 self.$el.empty();
629 self.$el.removeClass("no_partner");
630 self.context.mode = mode;
631 self.context.initial_data_provided = false;
632 self.is_valid = true;
633 self.is_consistent = true;
634 self.filter = "";
635 self.set("balance", undefined, {silent: true});
636 self.set("mode", undefined, {silent: true});
637 self.set("pager_index", 0, {silent: true});
638 self.set("mv_lines", [], {silent: true});
639 self.set("mv_lines_selected", [], {silent: true});
640 self.mv_lines_deselected = [];
641 self.set("lines_created", [], {silent: true});
642 self.set("line_created_being_edited", [{'id': 0}], {silent: true});
643 // Rebirth
644 return $.when(self.start()).then(function() {
645 self.$el.css("height", "auto");
646 self.is_consistent = true;
647 self.$el.animate({opacity: 1}, self.animation_speed);
648 });
649 });
650 },
651
652 /* create form widgets, append them to the dom and bind their events handlers */
653 createFormWidgets: function() {
654 var self = this;
655 var create_form_fields = self.getParent().create_form_fields;
656 var create_form_fields_arr = [];
657 for (var key in create_form_fields)
658 if (create_form_fields.hasOwnProperty(key))
659 create_form_fields_arr.push(create_form_fields[key]);
660 create_form_fields_arr.sort(function(a, b){ return b.index - a.index });
661
662 // field_manager
663 var dataset = new instance.web.DataSet(this, "account.account", self.context);
664 dataset.ids = [];
665 dataset.arch = {
666 attrs: { string: "Stéphanie de Monaco", version: "7.0", class: "oe_form_container" },
667 children: [],
668 tag: "form"
669 };
670
671 var field_manager = new instance.web.FormView (
672 this, dataset, false, {
673 initial_mode: 'edit',
674 disable_autofocus: false,
675 $buttons: $(),
676 $pager: $()
677 });
678
679 field_manager.load_form(dataset);
680
681 // fields default properties
682 var Default_field = function() {
683 this.context = {};
684 this.domain = [];
685 this.help = "";
686 this.readonly = false;
687 this.required = true;
688 this.selectable = true;
689 this.states = {};
690 this.views = {};
691 };
692 var Default_node = function(field_name) {
693 this.tag = "field";
694 this.children = [];
695 this.required = true;
696 this.attrs = {
697 invisible: "False",
698 modifiers: '{"required":true}',
699 name: field_name,
700 nolabel: "True",
701 };
702 };
703
704 // Append fields to the field_manager
705 field_manager.fields_view.fields = {};
706 for (var i=0; i<create_form_fields_arr.length; i++) {
707 field_manager.fields_view.fields[create_form_fields_arr[i].id] = _.extend(new Default_field(), create_form_fields_arr[i].field_properties);
708 }
709 field_manager.fields_view.fields["change_partner"] = _.extend(new Default_field(), {
710 relation: "res.partner",
711 string: _t("Partner"),
712 type: "many2one",
713 domain: [['parent_id','=',false], '|', ['customer','=',true], ['supplier','=',true]],
714 });
715
716 // Returns a function that serves as a xhr response handler
717 var hideGroupResponseClosureFactory = function(field_widget, $container, obj_key){
718 return function(has_group){
719 if (has_group) $container.show();
720 else {
721 field_widget.destroy();
722 $container.remove();
723 delete self[obj_key];
724 }
725 };
726 };
727
728 // generate the create "form"
729 self.create_form = [];
730 for (var i=0; i<create_form_fields_arr.length; i++) {
731 var field_data = create_form_fields_arr[i];
732
733 // create widgets
734 var node = new Default_node(field_data.id);
735 if (! field_data.required) node.attrs.modifiers = "";
736 var field = new field_data.constructor(field_manager, node);
737 self[field_data.id+"_field"] = field;
738 self.create_form.push(field);
739
740 // on update : change the last created line
741 field.corresponding_property = field_data.corresponding_property;
742 field.on("change:value", self, self.formCreateInputChanged);
743
744 // append to DOM
745 var $field_container = $(QWeb.render("form_create_field", {id: field_data.id, label: field_data.label}));
746 field.appendTo($field_container.find("td"));
747 self.$(".create_form").prepend($field_container);
748
749 // now that widget's dom has been created (appendTo does that), bind events and adds tabindex
750 if (field_data.field_properties.type != "many2one") {
751 // Triggers change:value TODO : moche bind ?
752 field.$el.find("input").keyup(function(e, field){ field.commit_value(); }.bind(null, null, field));
753 }
754 field.$el.find("input").attr("tabindex", field_data.tabindex);
755
756 // Hide the field if group not OK
757 if (field_data.group !== undefined) {
758 var target = $field_container;
759 target.hide();
760 self.model_res_users
761 .call("has_group", [field_data.group])
762 .then(hideGroupResponseClosureFactory(field, target, (field_data.id+"_field")));
763 }
764 }
765
766 // generate the change partner "form"
767 var change_partner_node = new Default_node("change_partner"); change_partner_node.attrs.modifiers = "";
768 self.change_partner_field = new instance.web.form.FieldMany2One(field_manager, change_partner_node);
769 self.change_partner_field.appendTo(self.$(".change_partner_container"));
770 self.change_partner_field.on("change:value", self.change_partner_field, function() {
771 self.changePartner(this.get_value());
772 });
773
774 field_manager.do_show();
775 },
776
777 /** Utils */
778
779 /* TODO : if t-call for attr, all in qweb */
780 decorateStatementLine: function(line){
781 line.q_popover = QWeb.render("bank_statement_reconciliation_line_details", {line: line});
782 },
783
784 // adds fields, prefixed with q_, to the move line for qweb rendering
785 decorateMoveLine: function(line){
786 line.partial_reconcile = false;
787 line.propose_partial_reconcile = false;
788 line.q_due_date = (line.date_maturity === false ? line.date : line.date_maturity);
789 line.q_amount = (line.debit !== 0 ? "- "+line.q_debit : "") + (line.credit !== 0 ? line.q_credit : "");
790 line.q_popover = QWeb.render("bank_statement_reconciliation_move_line_details", {line: line});
791 line.q_label = line.name;
792
793 // WARNING : pretty much of a ugly hack
794 // The value of account_move.ref is either the move's communication or it's name without the slashes
795 if (line.ref && line.ref !== line.name.replace(/\//g,''))
796 line.q_label += " : " + line.ref;
797 },
798
799 bindPopoverTo: function(el) {
800 var self = this;
801 $(el).addClass("bootstrap_popover");
802 el.popover({
803 'placement': 'left',
804 'container': self.el,
805 'html': true,
806 'trigger': 'hover',
807 'animation': false,
808 'toggle': 'popover'
809 });
810 },
811
812 islineCreatedBeingEditedValid: function() {
813 var line = this.get("line_created_being_edited")[0];
814 return line.amount // must be defined and not 0
815 && line.account_id // must be defined (and will never be 0)
816 && line.label; // must be defined and not empty
817 },
818
819 /* returns the created lines, plus the ones being edited if valid */
820 getCreatedLines: function() {
821 var self = this;
822 var created_lines = self.get("lines_created").slice();
823 if (self.islineCreatedBeingEditedValid())
824 return created_lines.concat(self.get("line_created_being_edited"));
825 else
826 return created_lines;
827 },
828
829 /** Matching */
830
831 moveLineClickHandler: function(e) {
832 var self = this;
833 if (e.currentTarget.dataset.selected === "true") self.deselectMoveLine(e.currentTarget);
834 else self.selectMoveLine(e.currentTarget);
835 },
836
837 // Takes a move line from the match view and adds it to the mv_lines_selected array
838 selectMoveLine: function(mv_line) {
839 var self = this;
840 var line_id = mv_line.dataset.lineid;
841
842 // find the line in mv_lines or mv_lines_deselected
843 var line = _.find(self.get("mv_lines"), function(o){ return o.id == line_id });
844 if (! line) {
845 line = _.find(self.mv_lines_deselected, function(o){ return o.id == line_id });
846 self.mv_lines_deselected = _.filter(self.mv_lines_deselected, function(o) { return o.id != line_id });
847 }
848 // If no line found, the view is probably not up to date to the model (asynchronous fun)
849 if (! line) return;
850
851 // Warn the user if he's selecting lines from both a payable and a receivable account
852 var last_selected_line = _.last(self.get("mv_lines_selected"));
853 if (last_selected_line && last_selected_line.account_type != line.account_type) {
854 // TODO : web client API
855 alert(_.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));
856 return;
857 }
858
859 self.set("mv_lines_selected", self.get("mv_lines_selected").concat(line));
860 },
861
862 // Removes a move line from the mv_lines_selected array
863 deselectMoveLine: function(mv_line) {
864 var self = this;
865 var line_id = mv_line.dataset.lineid;
866 var line = _.find(self.get("mv_lines_selected"), function(o) { return o.id == line_id });
867 // If no line found, the view is probably not up to date to the model (asynchronous fun)
868 if (! line) return;
869
870 // add the line to mv_lines_deselected and remove it from mv_lines_selected
871 self.mv_lines_deselected.unshift(line);
872 var mv_lines_selected = _.filter(self.get("mv_lines_selected"), function(o) { return o.id != line_id });
873
874 // remove partial reconciliation stuff if necessary
875 if (line.partial_reconcile === true) self.unpartialReconcileLine(line);
876 if (line.propose_partial_reconcile === true) line.propose_partial_reconcile = false;
877
878 self.$el.removeClass("no_match");
879 self.set("mode", "match");
880 self.set("mv_lines_selected", mv_lines_selected);
881 },
882
883
884 /** Matches pagination */
885
886 pagerControlLeftHandler: function() {
887 var self = this;
888 if (self.$(".pager_control_left").hasClass("disabled")) { return; /* shouldn't happen, anyway*/ }
889 if (self.total_move_lines_num < 0) { return; }
890 self.set("pager_index", self.get("pager_index")-1 );
891 },
892
893 pagerControlRightHandler: function() {
894 var self = this;
895 var new_index = self.get("pager_index")+1;
896 if (self.$(".pager_control_right").hasClass("disabled")) { return; /* shouldn't happen, anyway*/ }
897 if ((new_index * self.max_move_lines_displayed) >= self.total_move_lines_num) { return; }
898 self.set("pager_index", new_index );
899 },
900
901 filterHandler: function() {
902 var self = this;
903 self.set("pager_index", 0);
904 self.filter = self.$(".filter").val();
905 window.clearTimeout(self.apply_filter_timeout);
906 self.apply_filter_timeout = window.setTimeout(self.proxy('updateMatches'), 200);
907 },
908
909
910 /** Creating */
911
912 initializeCreateForm: function() {
913 var self = this;
914
915 _.each(self.create_form, function(field) {
916 field.set("value", false);
917 });
918 self.amount_field.set("value", -1*self.get("balance"));
919 self.account_id_field.focus();
920 },
921
922 addLineBeingEdited: function() {
923 var self = this;
924 if (! self.islineCreatedBeingEditedValid()) return;
925
926 self.set("lines_created", self.get("lines_created").concat(self.get("line_created_being_edited")));
927 // Add empty created line
928 var new_id = self.get("line_created_being_edited")[0].id + 1;
929 self.set("line_created_being_edited", [{'id': new_id}]);
930
931 self.initializeCreateForm();
932 },
933
934 removeLine: function($line) {
935 var self = this;
936 var line_id = $line.data("lineid");
937
938 // if deleting the created line that is being edited, validate it before
939 if (line_id === self.get("line_created_being_edited")[0].id) {
940 self.addLineBeingEdited();
941 }
942 self.set("lines_created", _.filter(self.get("lines_created"), function(o) { return o.id != line_id }));
943 self.amount_field.set("value", -1*self.get("balance"));
944 },
945
946 presetClickHandler: function(e) {
947 var self = this;
948 self.initializeCreateForm();
949 var preset = self.presets[e.currentTarget.dataset.presetid];
950 for (var key in preset) {
951 if (! preset.hasOwnProperty(key) || key === "amount") continue;
952 if (self.hasOwnProperty(key+"_field"))
953 self[key+"_field"].set_value(preset[key]);
954 }
955 var sign = self.amount_field.get_value() < 0 ? -1 : 1;
956 if (preset.amount && self.amount_field) {
957 if (preset.amount_type === "fixed")
958 self.amount_field.set_value(sign * preset.amount);
959 else if (preset.amount_type === "percentage_of_total")
960 self.amount_field.set_value(sign * self.st_line.amount * preset.amount / 100);
961 else if (preset.amount_type === "percentage_of_balance") {
962 self.amount_field.set_value(0);
963 self.updateBalance();
964 self.amount_field.set_value(sign * Math.abs(self.get("balance")) * preset.amount / 100);
965 }
966 }
967 },
968
969
970 /** Display */
971
972 initialLineClickHandler: function() {
973 var self = this;
974 if (self.get("mode") === "match") {
975 self.set("mode", "inactive");
976 } else {
977 self.set("mode", "match");
978 }
979 },
980
981 lineOpenBalanceClickHandler: function() {
982 var self = this;
983 if (self.get("mode") === "create") {
984 self.set("mode", "match");
985 } else {
986 self.set("mode", "create");
987 }
988 },
989
990 partnerNameClickHandler: function() {
991 var self = this;
992 self.$(".partner_name").hide();
993 self.change_partner_field.$el.find("input").attr("placeholder", self.st_line.partner_name);
994 self.$(".change_partner_container").show();
995 },
996
997
998 /** Views updating */
999
1000 updateAccountingViewMatchedLines: function() {
1001 var self = this;
1002 $.each(self.$(".tbody_matched_lines .bootstrap_popover"), function(){ $(this).popover('destroy') });
1003 self.$(".tbody_matched_lines").empty();
1004
1005 _(self.get("mv_lines_selected")).each(function(line){
1006 var $line = $(QWeb.render("bank_statement_reconciliation_move_line", {line: line, selected: true}));
1007 self.bindPopoverTo($line.find(".line_info_button"));
1008 if (line.propose_partial_reconcile) self.bindPopoverTo($line.find(".do_partial_reconcile_button"));
1009 if (line.partial_reconcile) self.bindPopoverTo($line.find(".undo_partial_reconcile_button"));
1010 self.$(".tbody_matched_lines").append($line);
1011 });
1012 },
1013
1014 updateAccountingViewCreatedLines: function() {
1015 var self = this;
1016 $.each(self.$(".tbody_created_lines .bootstrap_popover"), function(){ $(this).popover('destroy') });
1017 self.$(".tbody_created_lines").empty();
1018
1019 _(self.getCreatedLines()).each(function(line){
1020 var $line = $(QWeb.render("bank_statement_reconciliation_created_line", {line: line}));
1021 $line.find(".line_remove_button").click(function(){ self.removeLine($(this).closest(".created_line")) });
1022 self.$(".tbody_created_lines").append($line);
1023 if (line.no_remove_action) {
1024 // Then the previous line's remove button deletes this line too
1025 $line.hover(function(){ $(this).prev().addClass("active") },function(){ $(this).prev().removeClass("active") });
1026 }
1027 });
1028 },
1029
1030 updateMatchView: function() {
1031 var self = this;
1032 var table = self.$(".match table");
1033 var nothing_displayed = true;
1034
1035 // Display move lines
1036 $.each(self.$(".match table .bootstrap_popover"), function(){ $(this).popover('destroy') });
1037 table.empty();
1038 var slice_start = self.get("pager_index") * self.max_move_lines_displayed;
1039 var slice_end = (self.get("pager_index")+1) * self.max_move_lines_displayed;
1040 _( _.filter(self.mv_lines_deselected, function(o){
1041 return o.name.indexOf(self.filter) !== -1 || o.ref.indexOf(self.filter) !== -1 })
1042 .slice(slice_start, slice_end)).each(function(line){
1043 var $line = $(QWeb.render("bank_statement_reconciliation_move_line", {line: line, selected: false}));
1044 self.bindPopoverTo($line.find(".line_info_button"));
1045 table.append($line);
1046 nothing_displayed = false;
1047 });
1048 _(self.get("mv_lines")).each(function(line){
1049 var $line = $(QWeb.render("bank_statement_reconciliation_move_line", {line: line, selected: false}));
1050 self.bindPopoverTo($line.find(".line_info_button"));
1051 table.append($line);
1052 nothing_displayed = false;
1053 });
1054 if (nothing_displayed)
1055 table.append(QWeb.render("filter_no_match", {filter_str: self.filter}));
1056 },
1057
1058 updatePagerControls: function() {
1059 var self = this;
1060
1061 if (self.get("pager_index") === 0)
1062 self.$(".pager_control_left").addClass("disabled");
1063 else
1064 self.$(".pager_control_left").removeClass("disabled");
1065 if (self.total_move_lines_num <= ((self.get("pager_index")+1) * self.max_move_lines_displayed))
1066 self.$(".pager_control_right").addClass("disabled");
1067 else
1068 self.$(".pager_control_right").removeClass("disabled");
1069 },
1070
1071
1072 /** Properties changed */
1073
1074 // Updates the validation button and the "open balance" line
1075 balanceChanged: function() {
1076 var self = this;
1077 var balance = self.get("balance");
1078
1079 // Special case hack : no identified partner
1080 if (self.st_line.has_no_partner) {
1081 if (Math.abs(balance).toFixed(3) === "0.000") {
1082 self.$(".button_ok").addClass("oe_highlight");
1083 self.$(".button_ok").removeAttr("disabled");
1084 self.$(".button_ok").text("OK");
1085 self.is_valid = true;
1086 } else {
1087 self.$(".button_ok").removeClass("oe_highlight");
1088 self.$(".button_ok").attr("disabled", "disabled");
1089 self.$(".button_ok").text("OK");
1090 self.is_valid = false;
1091 }
1092 return;
1093 }
1094
1095 self.$(".tbody_open_balance").empty();
1096 if (Math.abs(balance).toFixed(3) === "0.000") {
1097 self.$(".button_ok").addClass("oe_highlight");
1098 self.$(".button_ok").text("OK");
1099 } else {
1100 self.$(".button_ok").removeClass("oe_highlight");
1101 self.$(".button_ok").text("Keep open");
1102 var debit = (balance > 0 ? self.formatCurrency(balance) : "");
1103 var credit = (balance < 0 ? self.formatCurrency(-1*balance) : "");
1104 var $line = $(QWeb.render("bank_statement_reconciliation_line_open_balance", {debit: debit, credit: credit, account_code: self.map_account_id_code[self.st_line.open_balance_account_id]}));
1105 self.$(".tbody_open_balance").append($line);
1106 }
1107 },
1108
1109 modeChanged: function() {
1110 var self = this;
1111
1112 self.$(".action_pane.active").removeClass("active");
1113
1114 // Special case hack : if no_partner, either inactive or create
1115 if (self.st_line.has_no_partner) {
1116 if (self.get("mode") === "inactive") {
1117 self.$(".match").slideUp(self.animation_speed);
1118 self.$(".create").slideUp(self.animation_speed);
1119 self.$(".toggle_match").removeClass("visible_toggle");
1120 self.el.dataset.mode = "inactive";
1121 } else {
1122 self.initializeCreateForm();
1123 self.$(".match").slideUp(self.animation_speed);
1124 self.$(".create").slideDown(self.animation_speed);
1125 self.$(".toggle_match").addClass("visible_toggle");
1126 self.el.dataset.mode = "create";
1127 }
1128 return;
1129 }
1130
1131 if (self.get("mode") === "inactive") {
1132 self.$(".match").slideUp(self.animation_speed);
1133 self.$(".create").slideUp(self.animation_speed);
1134 self.el.dataset.mode = "inactive";
1135
1136 } else if (self.get("mode") === "match") {
1137 return $.when(self.updateMatches()).then(function() {
1138 if (self.$el.hasClass("no_match")) {
1139 self.set("mode", "inactive");
1140 return;
1141 }
1142 self.$(".match").slideDown(self.animation_speed);
1143 self.$(".create").slideUp(self.animation_speed);
1144 self.el.dataset.mode = "match";
1145 });
1146
1147 } else if (self.get("mode") === "create") {
1148 self.initializeCreateForm();
1149 self.$(".match").slideUp(self.animation_speed);
1150 self.$(".create").slideDown(self.animation_speed);
1151 self.el.dataset.mode = "create";
1152 }
1153 },
1154
1155 pagerChanged: function() {
1156 var self = this;
1157 self.updateMatches();
1158 },
1159
1160 mvLinesChanged: function() {
1161 var self = this;
1162 // If pager_index is out of range, set it to display the last page
1163 if (self.get("pager_index") !== 0 && self.total_move_lines_num <= (self.get("pager_index") * self.max_move_lines_displayed)) {
1164 self.set("pager_index", Math.ceil(self.total_move_lines_num/self.max_move_lines_displayed)-1);
1165 }
1166
1167 // If there is no match to display, disable match view and pass in mode inactive
1168 if (self.total_move_lines_num + self.mv_lines_deselected.length === 0 && self.filter === "") {
1169 self.$el.addClass("no_match");
1170 if (self.get("mode") === "match") {
1171 self.set("mode", "inactive");
1172 }
1173 } else {
1174 self.$el.removeClass("no_match");
1175 }
1176
1177 self.updateMatchView();
1178 self.updatePagerControls();
1179 },
1180
1181 mvLinesSelectedChanged: function(elt, val) {
1182 var self = this;
1183
1184 var added_lines_ids = _.map(_.difference(val.newValue, val.oldValue), function(o){ return o.id });
1185 var removed_lines_ids = _.map(_.difference(val.oldValue, val.newValue), function(o){ return o.id });
1186
1187 self.getParent().excludeMoveLines(self, self.partner_id, added_lines_ids);
1188 self.getParent().unexcludeMoveLines(self, self.partner_id, removed_lines_ids);
1189
1190 $.when(self.updateMatches()).then(function(){
1191 self.updateAccountingViewMatchedLines();
1192 self.updateBalance();
1193 });
1194 },
1195
1196 // Generic function for updating the line_created_being_edited
1197 formCreateInputChanged: function(elt, val) {
1198 var self = this;
1199 var line_created_being_edited = self.get("line_created_being_edited");
1200 line_created_being_edited[0][elt.corresponding_property] = val.newValue;
1201
1202 // Specific cases
1203 if (elt === self.account_id_field)
1204 line_created_being_edited[0].account_num = self.map_account_id_code[elt.get("value")];
1205
1206 // Update tax line
1207 var deferred_tax = new $.Deferred();
1208 if (elt === self.tax_id_field || elt === self.amount_field) {
1209 var amount = self.amount_field.get("value");
1210 var tax = self.map_tax_id_amount[self.tax_id_field.get("value")];
1211 if (amount && tax) {
1212 deferred_tax = $.when(self.model_tax
1213 .call("compute_for_bank_reconciliation", [self.tax_id_field.get("value"), amount]))
1214 .then(function(data){
1215 var tax = data.taxes[0];
1216 var tax_account_id = (amount > 0 ? tax.account_collected_id : tax.account_paid_id)
1217 line_created_being_edited[0].amount = (data.total.toFixed(3) === amount.toFixed(3) ? amount : data.total);
1218 line_created_being_edited[1] = {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};
1219 }
1220 );
1221 } else {
1222 line_created_being_edited[0].amount = amount;
1223 delete line_created_being_edited[1];
1224 deferred_tax.resolve();
1225 }
1226 } else { deferred_tax.resolve(); }
1227
1228 $.when(deferred_tax).then(function(){
1229 // Format amounts
1230 if (line_created_being_edited[0].amount)
1231 line_created_being_edited[0].amount_str = self.formatCurrency(Math.abs(line_created_being_edited[0].amount));
1232 if (line_created_being_edited[1] && line_created_being_edited[1].amount)
1233 line_created_being_edited[1].amount_str = self.formatCurrency(Math.abs(line_created_being_edited[1].amount));
1234
1235 self.set("line_created_being_edited", line_created_being_edited);
1236 self.createdLinesChanged(); // TODO For some reason, previous line doesn't trigger change handler
1237 });
1238 },
1239
1240 createdLinesChanged: function() {
1241 var self = this;
1242 self.updateAccountingViewCreatedLines();
1243 self.updateBalance();
1244
1245 if (self.islineCreatedBeingEditedValid()) self.$(".add_line").show();
1246 else self.$(".add_line").hide();
1247 },
1248
1249
1250 /** Model */
1251
1252 doPartialReconcileButtonClickHandler: function(e) {
1253 var self = this;
1254
1255 var line_id = $(e.currentTarget).closest("tr").data("lineid");
1256 var line = _.find(self.get("mv_lines_selected"), function(o) { return o.id == line_id });
1257 self.partialReconcileLine(line);
1258
1259 $(e.currentTarget).popover('destroy');
1260 self.updateAccountingViewMatchedLines();
1261 self.updateBalance();
1262 e.stopPropagation();
1263 },
1264
1265 partialReconcileLine: function(line) {
1266 var self = this;
1267 var balance = self.get("balance");
1268 line.initial_amount = line.debit !== 0 ? line.debit : -1 * line.credit;
1269 if (balance < 0) {
1270 line.debit -= balance;
1271 line.debit_str = self.formatCurrency(line.debit);
1272 } else {
1273 line.credit -= balance;
1274 line.credit_str = self.formatCurrency(line.credit);
1275 }
1276 line.propose_partial_reconcile = false;
1277 line.partial_reconcile = true;
1278 },
1279
1280 undoPartialReconcileButtonClickHandler: function(e) {
1281 var self = this;
1282
1283 var line_id = $(e.currentTarget).closest("tr").data("lineid");
1284 var line = _.find(self.get("mv_lines_selected"), function(o) { return o.id == line_id });
1285 self.unpartialReconcileLine(line);
1286
1287 $(e.currentTarget).popover('destroy');
1288 self.updateAccountingViewMatchedLines();
1289 self.updateBalance();
1290 e.stopPropagation();
1291 },
1292
1293 unpartialReconcileLine: function(line) {
1294 if (line.initial_amount > 0) {
1295 line.debit = line.initial_amount;
1296 line.debit_str = this.formatCurrency(line.debit);
1297 } else {
1298 line.credit = -1 * line.initial_amount;
1299 line.credit_str = this.formatCurrency(line.credit);
1300 }
1301 line.propose_partial_reconcile = true;
1302 line.partial_reconcile = false;
1303 },
1304
1305 updateBalance: function() {
1306 var self = this;
1307 var mv_lines_selected = self.get("mv_lines_selected");
1308 var balance = 0;
1309 balance -= self.st_line.amount;
1310 _.each(mv_lines_selected, function(o) {
1311 balance = balance - o.debit + o.credit;
1312 });
1313 _.each(self.getCreatedLines(), function(o) {
1314 balance += o.amount;
1315 });
1316 self.set("balance", balance);
1317
1318 // Propose partial reconciliation if necessary
1319 var lines_selected_num = mv_lines_selected.length;
1320 var lines_created_num = self.getCreatedLines().length;
1321 if (lines_selected_num === 1 && lines_created_num === 0 && self.st_line.amount * balance > 0) {
1322 mv_lines_selected[0].propose_partial_reconcile = true;
1323 self.updateAccountingViewMatchedLines();
1324 }
1325 if (lines_selected_num !== 1 || lines_created_num !== 0) {
1326 // remove partial reconciliation stuff if necessary
1327 _.each(mv_lines_selected, function(line) {
1328 if (line.partial_reconcile === true) self.unpartialReconcileLine(line);
1329 if (line.propose_partial_reconcile === true) line.propose_partial_reconcile = false;
1330 });
1331 self.updateAccountingViewMatchedLines();
1332 }
1333 },
1334
1335 loadReconciliationProposition: function() {
1336 var self = this;
1337 return self.model_bank_statement_line
1338 .call("get_reconciliation_proposition", [self.st_line.id, self.getParent().excluded_move_lines_ids[self.partner_id]])
1339 .then(function (lines) {
1340 _(lines).each(self.decorateMoveLine.bind(self));
1341 self.set("mv_lines_selected", self.get("mv_lines_selected").concat(lines));
1342 });
1343 },
1344
1345 // Loads move lines according to the widget's state
1346 updateMatches: function() {
1347 var self = this;
1348 var deselected_lines_num = self.mv_lines_deselected.length;
1349 var move_lines = {};
1350 var move_lines_num = 0;
1351 var offset = self.get("pager_index") * self.max_move_lines_displayed - deselected_lines_num;
1352 if (offset < 0) offset = 0;
1353 var limit = (self.get("pager_index")+1) * self.max_move_lines_displayed - deselected_lines_num;
1354 if (limit > self.max_move_lines_displayed) limit = self.max_move_lines_displayed;
1355 var excluded_ids = _.collect(self.get("mv_lines_selected").concat(self.mv_lines_deselected), function(o){ return o.id });
1356 excluded_ids = excluded_ids.concat(self.getParent().excluded_move_lines_ids[self.partner_id]);
1357
1358 var deferred_move_lines;
1359 if (limit > 0) {
1360 // Load move lines
1361 deferred_move_lines = self.model_bank_statement_line
1362 .call("get_move_lines_counterparts", [self.st_line.id, excluded_ids, self.filter, offset, limit])
1363 .then(function (lines) {
1364 _(lines).each(self.decorateMoveLine.bind(self));
1365 move_lines = lines;
1366 });
1367 }
1368
1369 // Fetch the number of move lines corresponding to this statement line and this filter
1370 var deferred_total_move_lines_num = self.model_bank_statement_line
1371 .call("get_move_lines_counterparts", [self.st_line.id, excluded_ids, self.filter, offset, limit, true])
1372 .then(function(num){
1373 move_lines_num = num;
1374 });
1375
1376 return $.when(deferred_move_lines, deferred_total_move_lines_num).then(function(){
1377 self.total_move_lines_num = move_lines_num + deselected_lines_num;
1378 self.set("mv_lines", move_lines);
1379 });
1380 },
1381
1382 // Changes the partner_id of the statement_line in the DB and reloads the widget
1383 changePartner: function(partner_id) {
1384 var self = this;
1385 self.is_consistent = false;
1386 return self.model_bank_statement_line
1387 // Update model
1388 .call("write", [[self.st_line_id], {'partner_id': partner_id}])
1389 .then(function () {
1390 return $.when(self.restart(self.get("mode"))).then(function(){
1391 self.is_consistent = true;
1392 });
1393 });
1394 },
1395
1396 // Returns an object that can be passed to process_reconciliation()
1397 prepareSelectedMoveLineForPersisting: function(line) {
1398 return {
1399 name: line.name,
1400 debit: line.debit,
1401 credit: line.credit,
1402 counterpart_move_line_id: line.id,
1403 };
1404 },
1405
1406 // idem
1407 prepareCreatedMoveLineForPersisting: function(line) {
1408 var dict = {};
1409
1410 if (dict['account_id'] === undefined)
1411 dict['account_id'] = line.account_id;
1412 dict['name'] = line.label;
1413 if (line.amount > 0) dict['credit'] = line.amount;
1414 if (line.amount < 0) dict['debit'] = -1*line.amount;
1415 if (line.tax_id) dict['tax_code_id'] = line.tax_id;
1416 if (line.analytic_account_id) dict['analytic_account_id'] = line.analytic_account_id;
1417
1418 return dict;
1419 },
1420
1421 // idem
1422 prepareOpenBalanceForPersisting: function() {
1423 var balance = this.get("balance");
1424 var dict = {};
1425
1426 dict['account_id'] = this.st_line.open_balance_account_id;
1427 dict['name'] = _t("Open balance");
1428 if (balance > 0) dict['debit'] = balance;
1429 if (balance < 0) dict['credit'] = -1*balance;
1430
1431 return dict;
1432 },
1433
1434 // Persist data, notify parent view and terminate widget
1435 persistAndDestroy: function() {
1436 var self = this;
1437 if (! self.is_consistent) return;
1438
1439 self.getParent().unexcludeMoveLines(self, self.partner_id, _.map(self.get("mv_lines_selected"), function(o){ return o.id }));
1440
1441 // Prepare data
1442 var mv_line_dicts = [];
1443 _.each(self.get("mv_lines_selected"), function(o) { mv_line_dicts.push(self.prepareSelectedMoveLineForPersisting(o)) });
1444 _.each(self.getCreatedLines(), function(o) { mv_line_dicts.push(self.prepareCreatedMoveLineForPersisting(o)) });
1445 if (Math.abs(self.get("balance")).toFixed(3) !== "0.000") mv_line_dicts.push(self.prepareOpenBalanceForPersisting());
1446
1447 // Sliding animation
1448 var height = self.$el.outerHeight();
1449 var container = $("<div />");
1450 container.css("height", height)
1451 .css("marginTop", self.$el.css("marginTop"))
1452 .css("marginBottom", self.$el.css("marginBottom"));
1453 self.$el.wrap(container);
1454 var deferred_animation = self.$el.parent().slideUp(self.animation_speed*height/150);
1455
1456 // RPC
1457 return self.model_bank_statement_line
1458 .call("process_reconciliation", [self.st_line_id, mv_line_dicts])
1459 .then(function () {
1460 $.each(self.$(".bootstrap_popover"), function(){ $(this).popover('destroy') });
1461 return $.when(deferred_animation).then(function(){
1462 self.$el.parent().remove();
1463 var parent = self.getParent();
1464 return $.when(self.destroy()).then(function() {
1465 parent.childValidated(self);
1466 });
1467 });
1468 }, function(){
1469 self.$el.parent().slideDown(self.animation_speed*height/150, function(){
1470 self.$el.unwrap();
1471 });
1472 });
1473
1474 },
1475 });
1476
9 instance.web.views.add('tree_account_reconciliation', 'instance.web.account.ReconciliationListView');1477 instance.web.views.add('tree_account_reconciliation', 'instance.web.account.ReconciliationListView');
10 instance.web.account.ReconciliationListView = instance.web.ListView.extend({1478 instance.web.account.ReconciliationListView = instance.web.ListView.extend({
11 init: function() {1479 init: function() {
121480
=== added file 'account/static/src/xml/account_bank_statement_reconciliation.xml'
--- account/static/src/xml/account_bank_statement_reconciliation.xml 1970-01-01 00:00:00 +0000
+++ account/static/src/xml/account_bank_statement_reconciliation.xml 2014-05-30 16:18:57 +0000
@@ -0,0 +1,194 @@
1<?xml version="1.0" encoding="UTF-8"?>
2
3<templates xml:space="preserve">
4
5 <t t-name="bank_statement_nothing_to_reconcile">
6 <div class="oe_form_sheetbg"><div class="oe_form_sheet oe_form_sheet_width">
7 <div class="oe_view_nocontent"><p>
8 <b>Good Job!</b> Bank statements are fully reconciled.</p>
9 <p>This page displays all the bank transactions that are to be reconciled and provides with a neat interface to do so.</p>
10 </div>
11 </div></div>
12 </t>
13
14 <t t-name="bank_statement_reconciliation">
15 <div class="oe_form_sheetbg"><div class="oe_form_sheet oe_form_sheet_width">
16 <h1><t t-esc="title"/></h1>
17 <div class="progress progress-striped">
18 <div class="progress-text"><span class="valuenow">0</span> / <span class="valuemax"><t t-esc="total_lines"/></span></div>
19 <div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" t-att-aria-valuemax="total_lines" style="width: 0%;">
20 </div>
21 </div>
22 <div class="oe_clear"></div>
23 <div class="reconciliation_lines_container"></div>
24 <p class='protip'>Tip : Hit ctrl-enter to validate the whole sheet.</p>
25 </div></div>
26 </t>
27
28 <t t-name="bank_statement_reconciliation_done_message">
29 <div class='done_message'>
30 <h2><t t-raw="title" /></h2>
31 <p>It took you <strong><t t-esc="time_taken" /></strong> to reconcile <strong><t t-esc="transactions_done" /> transactions.<br/></strong> That's on average <t t-esc="sec_per_item" /> seconds per transaction.</p>
32 <t t-if="done_with_ctrl_enter !== 0">
33 <p>You validated <t t-esc="done_with_ctrl_enter" /> reconciliations with the ctrl-enter shortcut.</p>
34 </t>
35 <p class='achievements'>
36 <t t-foreach="achievements" t-as="achievement">
37 <i class='fa fa-certificate achievement' t-att-data-title='achievement.title' t-att-data-content='achievement.desc'><i t-att-class="'fa '+achievement.icon"></i></i>
38 </t>
39 </p>
40 <p class="action_buttons">
41 <t t-if="has_statement_id">
42 <button class="button_back_to_statement">Back to statement</button>
43 <button class="button_close_statement">Close the statement</button>
44 </t>
45 </p>
46 </div>
47 </t>
48
49 <t t-name="bank_statement_reconciliation_line">
50 <table t-att-data-mode="mode">
51 <tr>
52 <td>
53 <table class="accounting_view">
54 <caption>
55 <button class="button_ok"></button>
56 <span class="partner_name"><t t-esc="line.partner_name"/></span>
57 <div class="change_partner_container oe_form"></div>
58 </caption>
59 <tbody class="tbody_initial_line">
60 <tr class="initial_line">
61 <td><span class="toggle_match glyphicon glyphicon-cog"></span></td>
62 <td><t t-esc="line.account_code"/></td>
63 <td><t t-esc="line.date"/></td>
64 <td><t t-esc="line.name"/>
65 <t t-if="line.amount_currency_str"> (<t t-esc="line.amount_currency_str"/>)</t></td>
66 <td><t t-if="line.amount &gt; 0">
67 <t t-esc="line.amount_str"/></t></td>
68 <td><t t-if="line.amount &lt; 0">
69 <t t-esc="line.amount_str"/></t></td>
70 <td><span class="line_info_button glyphicon glyphicon-info-sign" t-att-data-content="line.q_popover"></span></td>
71 </tr>
72 </tbody>
73 <tbody class="tbody_matched_lines"></tbody>
74 <tbody class="tbody_created_lines"></tbody>
75 <tbody class="tbody_open_balance"></tbody>
76 </table>
77 </td>
78 </tr>
79 <tr>
80 <td>
81 <div class="action_pane match">
82 <div class="match_controls">
83 <input type="text" class="filter" placeholder="Filter" value="" />
84 <span class="pager_control_right pull-right glyphicon glyphicon-chevron-right"></span>
85 <span class="pager_control_left pull-right glyphicon glyphicon-chevron-left"></span>
86 </div>
87 <table></table>
88 </div>
89
90 <div class="action_pane create">
91 <!-- NB : I use a .quick_add:empty selector. whitespace characters being a node, there shall be none -->
92 <div class="quick_add btn-group btn-group-sm"><t t-foreach="presets" t-as="preset"><button type='button' class='btn btn-default preset' t-att-data-presetid="preset.id"><t t-esc="preset.name"/></button></t></div>
93 <div class="oe_form create_form">
94 <!-- here come some form_create_field -->
95 <table class="create_field add_line_container"><tr><td><a href="javascript:void(0)" class="add_line">New</a></td></tr></table>
96 </div>
97 </div>
98 </td>
99 </tr>
100 </table>
101 </t>
102
103 <t t-name="filter_no_match">
104 <tr><td style='text-align: center;'>No result matching '<t t-esc="filter_str" />'</td></tr>
105 </t>
106
107 <t t-name="form_create_field">
108 <table t-att-class='"create_field create_"+id'><tr>
109 <th><t t-esc="label"/></th>
110 <td class="create_account_container" t-att-class='"create_"+id+"_container"'></td>
111 </tr></table>
112 </t>
113
114 <t t-name="bank_statement_reconciliation_line_details">
115 <table class='details'>
116 <tr><td>Date</td><td><t t-esc="line.date"/></td></tr>
117 <tr><td>Partner</td><td><t t-esc="line.partner_name"/></td></tr>
118 <tr t-if="line.ref"><td>Transaction</td><td><t t-esc="line.ref"/></td></tr>
119 <tr><td>Description</td><td><t t-esc="line.name"/></td></tr>
120 <tr><td>Amount</td><td><t t-esc="line.amount_str"/><t t-if="line.amount_currency_str"> (<t t-esc="line.amount_currency_str"/>)</t></td></tr>
121 <tr><td>Account</td><td><t t-esc="line.account_code"/> <t t-esc="line.account_name"/></td></tr>
122 </table>
123 </t>
124
125
126 <t t-name="bank_statement_reconciliation_move_line">
127 <tr class="mv_line" t-att-data-lineid="line.id" t-att-data-selected="selected">
128 <td><span class="glyphicon glyphicon-add-remove"></span></td>
129 <td><t t-esc="line.account_code"/></td>
130 <td><t t-esc="line.q_due_date"/></td>
131 <td><t t-esc="line.q_label"/></td>
132
133 <td><t t-if="line.debit !== 0">
134 <t t-if="line.propose_partial_reconcile" t-call="icon_do_partial_reconciliation"></t>
135 <t t-if="line.partial_reconcile" t-call="icon_undo_partial_reconciliation"></t>
136 <t t-esc="line.debit_str"/>
137 </t></td>
138 <td><t t-if="line.credit !== 0">
139 <t t-if="line.propose_partial_reconcile"><t t-call="icon_do_partial_reconciliation" /></t>
140 <t t-if="line.partial_reconcile"><t t-call="icon_undo_partial_reconciliation" /></t>
141 <t t-esc="line.credit_str"/>
142 </t></td>
143 <td><span class="line_info_button glyphicon glyphicon-info-sign" t-att-data-content="line.q_popover"></span></td>
144 </tr>
145 </t>
146
147 <t t-name="icon_do_partial_reconciliation">
148 <i class="do_partial_reconcile_button fa fa-exclamation-triangle" data-content="This move's amount is higher than the transaction's amount. Click to do a partial reconciliation"></i>
149 </t>
150
151 <t t-name="icon_undo_partial_reconciliation">
152 <i class="undo_partial_reconcile_button fa fa-exclamation-triangle" data-content="Undo the partial reconciliation."></i>
153 </t>
154
155 <t t-name="bank_statement_reconciliation_move_line_details">
156 <table class='details'>
157 <tr><td>ID</td><td><t t-esc="line.id"/></td></tr>
158 <tr><td>Account</td><td><t t-esc="line.account_code"/> <t t-esc="line.account_name"/></td></tr>
159 <tr><td>Journal</td><td><t t-esc="line.journal_name"/></td></tr>
160 <tr><td>Period</td><td><t t-esc="line.period_name"/></td></tr>
161 <tr><td>Date</td><td><t t-esc="line.date"/></td></tr>
162 <tr><td>Due Date</td><td><t t-esc="line.q_due_date"/></td></tr>
163 <tr><td>Amount</td>
164 <td><t t-if="line.debit !== 0" t-esc="line.debit_str"/><t t-if="line.credit !== 0" t-esc="line.credit_str"/>
165 <t t-if="line.amount_currency_str"> (<t t-esc="line.amount_currency_str"/>)</t>
166 </td></tr>
167 </table>
168 </t>
169
170
171 <t t-name="bank_statement_reconciliation_created_line">
172 <tr class="created_line" t-att-data-lineid="line.id">
173 <td><t t-if="! line.no_remove_action"><span class="line_remove_button glyphicon glyphicon-remove"></span></t></td>
174 <td><t t-esc="line.account_num"/></td>
175 <td></td>
176 <td><t t-esc="line.label"/></td>
177 <td><t t-if="line.amount &lt; 0"><t t-esc="line.amount_str"/></t></td>
178 <td><t t-if="line.amount &gt; 0"><t t-esc="line.amount_str"/></t></td>
179 <td></td>
180 </tr>
181 </t>
182
183 <t t-name="bank_statement_reconciliation_line_open_balance">
184 <tr class="line_open_balance">
185 <td><span class="toggle_create glyphicon glyphicon-play"></span></td>
186 <td><t t-esc="account_code"/></td>
187 <td></td>
188 <td>Open balance</td>
189 <td><t t-esc="debit"/></td>
190 <td><t t-esc="credit"/></td>
191 <td></td>
192 </tr>
193 </t>
194</templates>
0195
=== modified file 'account/views/account.xml'
--- account/views/account.xml 2014-04-24 17:21:29 +0000
+++ account/views/account.xml 2014-05-30 16:18:57 +0000
@@ -8,7 +8,8 @@
8 <link rel="stylesheet" href="/account/static/src/css/account_move_reconciliation.css"/>8 <link rel="stylesheet" href="/account/static/src/css/account_move_reconciliation.css"/>
9 <link rel="stylesheet" href="/account/static/src/css/account_move_line_quickadd.css"/>9 <link rel="stylesheet" href="/account/static/src/css/account_move_line_quickadd.css"/>
10 <link rel="stylesheet" href="/account/static/src/css/account_bank_and_cash.css"/>10 <link rel="stylesheet" href="/account/static/src/css/account_bank_and_cash.css"/>
11 <script type="text/javascript" src="/account/static/src/js/account_move_reconciliation.js"></script>11 <link rel="stylesheet" href="/account/static/src/css/account_bank_statement_reconciliation.css"/>
12 <script type="text/javascript" src="/account/static/src/js/account_widgets.js"></script>
12 <script type="text/javascript" src="/account/static/src/js/account_move_line_quickadd.js"></script>13 <script type="text/javascript" src="/account/static/src/js/account_move_line_quickadd.js"></script>
13 </xpath>14 </xpath>
14 </template>15 </template>
1516
=== modified file 'account/wizard/__init__.py'
--- account/wizard/__init__.py 2012-11-29 22:26:45 +0000
+++ account/wizard/__init__.py 2014-05-30 16:18:57 +0000
@@ -63,8 +63,6 @@
6363
64import account_change_currency64import account_change_currency
6565
66import pos_box;66import pos_box
6767import account_statement_from_invoice
68# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:68# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
69
70
7169
=== renamed file 'account_voucher/wizard/account_statement_from_invoice.py' => 'account/wizard/account_statement_from_invoice.py'
--- account_voucher/wizard/account_statement_from_invoice.py 2014-02-12 17:51:41 +0000
+++ account/wizard/account_statement_from_invoice.py 2014-05-30 16:18:57 +0000
@@ -22,7 +22,6 @@
22import time22import time
2323
24from openerp.osv import fields, osv24from openerp.osv import fields, osv
25from openerp.tools.translate import _
2625
27class account_statement_from_invoice_lines(osv.osv_memory):26class account_statement_from_invoice_lines(osv.osv_memory):
28 """27 """
@@ -35,12 +34,13 @@
35 }34 }
3635
37 def populate_statement(self, cr, uid, ids, context=None):36 def populate_statement(self, cr, uid, ids, context=None):
37 #TODO: can be moved in account module
38 if context is None:38 if context is None:
39 context = {}39 context = {}
40 statement_id = context.get('statement_id', False)40 statement_id = context.get('statement_id', False)
41 if not statement_id:41 if not statement_id:
42 return {'type': 'ir.actions.act_window_close'}42 return {'type': 'ir.actions.act_window_close'}
43 data = self.read(cr, uid, ids, context=context)[0]43 data = self.read(cr, uid, ids, context=context)[0]
44 line_ids = data['line_ids']44 line_ids = data['line_ids']
45 if not line_ids:45 if not line_ids:
46 return {'type': 'ir.actions.act_window_close'}46 return {'type': 'ir.actions.act_window_close'}
@@ -49,14 +49,11 @@
49 statement_obj = self.pool.get('account.bank.statement')49 statement_obj = self.pool.get('account.bank.statement')
50 statement_line_obj = self.pool.get('account.bank.statement.line')50 statement_line_obj = self.pool.get('account.bank.statement.line')
51 currency_obj = self.pool.get('res.currency')51 currency_obj = self.pool.get('res.currency')
52 voucher_obj = self.pool.get('account.voucher')
53 voucher_line_obj = self.pool.get('account.voucher.line')
54 line_date = time.strftime('%Y-%m-%d')52 line_date = time.strftime('%Y-%m-%d')
55 statement = statement_obj.browse(cr, uid, statement_id, context=context)53 statement = statement_obj.browse(cr, uid, statement_id, context=context)
5654
57 # for each selected move lines55 # for each selected move lines
58 for line in line_obj.browse(cr, uid, line_ids, context=context):56 for line in line_obj.browse(cr, uid, line_ids, context=context):
59 voucher_res = {}
60 ctx = context.copy()57 ctx = context.copy()
61 # take the date for computation of currency => use payment date58 # take the date for computation of currency => use payment date
62 ctx['date'] = line_date59 ctx['date'] = line_date
@@ -70,55 +67,19 @@
70 if line.amount_currency:67 if line.amount_currency:
71 amount = currency_obj.compute(cr, uid, line.currency_id.id,68 amount = currency_obj.compute(cr, uid, line.currency_id.id,
72 statement.currency.id, line.amount_currency, context=ctx)69 statement.currency.id, line.amount_currency, context=ctx)
73 elif (line.invoice and line.invoice.currency_id.id <> statement.currency.id):70 elif (line.invoice and line.invoice.currency_id.id != statement.currency.id):
74 amount = currency_obj.compute(cr, uid, line.invoice.currency_id.id,71 amount = currency_obj.compute(cr, uid, line.invoice.currency_id.id,
75 statement.currency.id, amount, context=ctx)72 statement.currency.id, amount, context=ctx)
7673
77 context.update({'move_line_ids': [line.id],74 context.update({'move_line_ids': [line.id],
78 'invoice_id': line.invoice.id})75 'invoice_id': line.invoice.id})
79 type = 'general'76
80 ttype = amount < 0 and 'payment' or 'receipt'
81 sign = 1
82 if line.journal_id.type in ('sale', 'sale_refund'):
83 type = 'customer'
84 ttype = 'receipt'
85 elif line.journal_id.type in ('purchase', 'purhcase_refund'):
86 type = 'supplier'
87 ttype = 'payment'
88 sign = -1
89 result = voucher_obj.onchange_partner_id(cr, uid, [], partner_id=line.partner_id.id, journal_id=statement.journal_id.id, amount=sign*amount, currency_id= statement.currency.id, ttype=ttype, date=line_date, context=context)
90 voucher_res = { 'type': ttype,
91 'name': line.name,
92 'partner_id': line.partner_id.id,
93 'journal_id': statement.journal_id.id,
94 'account_id': result['value'].get('account_id', statement.journal_id.default_credit_account_id.id),
95 'company_id': statement.company_id.id,
96 'currency_id': statement.currency.id,
97 'date': statement.date,
98 'amount': sign*amount,
99 'payment_rate': result['value']['payment_rate'],
100 'payment_rate_currency_id': result['value']['payment_rate_currency_id'],
101 'period_id':statement.period_id.id}
102 voucher_id = voucher_obj.create(cr, uid, voucher_res, context=context)
103
104 voucher_line_dict = {}
105 for line_dict in result['value']['line_cr_ids'] + result['value']['line_dr_ids']:
106 move_line = line_obj.browse(cr, uid, line_dict['move_line_id'], context)
107 if line.move_id.id == move_line.move_id.id:
108 voucher_line_dict = line_dict
109
110 if voucher_line_dict:
111 voucher_line_dict.update({'voucher_id': voucher_id})
112 voucher_line_obj.create(cr, uid, voucher_line_dict, context=context)
113 statement_line_obj.create(cr, uid, {77 statement_line_obj.create(cr, uid, {
114 'name': line.name or '?',78 'name': line.name or '?',
115 'amount': amount,79 'amount': amount,
116 'type': type,
117 'partner_id': line.partner_id.id,80 'partner_id': line.partner_id.id,
118 'account_id': line.account_id.id,
119 'statement_id': statement_id,81 'statement_id': statement_id,
120 'ref': line.ref,82 'ref': line.ref,
121 'voucher_id': voucher_id,
122 'date': statement.date,83 'date': statement.date,
123 }, context=context)84 }, context=context)
124 return {'type': 'ir.actions.act_window_close'}85 return {'type': 'ir.actions.act_window_close'}
12586
=== renamed file 'account_voucher/wizard/account_statement_from_invoice_view.xml' => 'account/wizard/account_statement_from_invoice_view.xml'
=== modified file 'account/wizard/pos_box.py'
--- account/wizard/pos_box.py 2013-12-27 15:35:17 +0000
+++ account/wizard/pos_box.py 2014-05-30 16:18:57 +0000
@@ -56,7 +56,6 @@
56 return {56 return {
57 'statement_id' : record.id,57 'statement_id' : record.id,
58 'journal_id' : record.journal_id.id,58 'journal_id' : record.journal_id.id,
59 'account_id' : record.journal_id.internal_account_id.id,
60 'amount' : box.amount or 0.0,59 'amount' : box.amount or 0.0,
61 'ref' : '%s' % (box.ref or ''),60 'ref' : '%s' % (box.ref or ''),
62 'name' : box.name,61 'name' : box.name,
@@ -73,7 +72,6 @@
73 return {72 return {
74 'statement_id' : record.id,73 'statement_id' : record.id,
75 'journal_id' : record.journal_id.id,74 'journal_id' : record.journal_id.id,
76 'account_id' : record.journal_id.internal_account_id.id,
77 'amount' : -amount if amount > 0.0 else amount,75 'amount' : -amount if amount > 0.0 else amount,
78 'name' : box.name,76 'name' : box.name,
79 }77 }
8078
=== modified file 'account_analytic_plans/__openerp__.py'
--- account_analytic_plans/__openerp__.py 2014-04-02 16:40:53 +0000
+++ account_analytic_plans/__openerp__.py 2014-05-30 16:18:57 +0000
@@ -74,6 +74,7 @@
74 'wizard/analytic_plan_create_model_view.xml',74 'wizard/analytic_plan_create_model_view.xml',
75 'wizard/account_crossovered_analytic_view.xml',75 'wizard/account_crossovered_analytic_view.xml',
76 'views/report_crossoveredanalyticplans.xml',76 'views/report_crossoveredanalyticplans.xml',
77 'views/account_analytic_plans.xml',
77 ],78 ],
78 'demo': [],79 'demo': [],
79 'test': ['test/acount_analytic_plans_report.yml'],80 'test': ['test/acount_analytic_plans_report.yml'],
8081
=== modified file 'account_analytic_plans/account_analytic_plans_view.xml'
--- account_analytic_plans/account_analytic_plans_view.xml 2014-02-10 05:26:55 +0000
+++ account_analytic_plans/account_analytic_plans_view.xml 2014-05-30 16:18:57 +0000
@@ -233,57 +233,25 @@
233233
234 <!-- add property field on default analytic account-->234 <!-- add property field on default analytic account-->
235235
236 <record model="ir.ui.view" id="view_default_inherit_form">236 <record model="ir.ui.view" id="view_default_inherit_form">
237 <field name="name">account.analytic.default.form.plans</field>237 <field name="name">account.analytic.default.form.plans</field>
238 <field name="model">account.analytic.default</field>238 <field name="model">account.analytic.default</field>
239 <field name="inherit_id" ref="account_analytic_default.view_account_analytic_default_form"/>239 <field name="inherit_id" ref="account_analytic_default.view_account_analytic_default_form"/>
240 <field name="arch" type="xml">240 <field name="arch" type="xml">
241 <field name="analytic_id" required="1" position="replace">241 <field name="analytic_id" required="1" position="replace">
242 <field name="analytics_id" required="1"/>242 <field name="analytics_id" required="1"/>
243 </field>243 </field>
244 </field>244 </field>
245 </record>245 </record>
246 <record model="ir.ui.view" id="view_default_inherit_tree">246 <record model="ir.ui.view" id="view_default_inherit_tree">
247 <field name="name">account.analytic.default.tree.plans</field>247 <field name="name">account.analytic.default.tree.plans</field>
248 <field name="model">account.analytic.default</field>248 <field name="model">account.analytic.default</field>
249 <field name="inherit_id" ref="account_analytic_default.view_account_analytic_default_tree"/>249 <field name="inherit_id" ref="account_analytic_default.view_account_analytic_default_tree"/>
250 <field name="arch" type="xml">250 <field name="arch" type="xml">
251 <xpath expr="//field[@name='analytic_id']" position="attributes">251 <xpath expr="//field[@name='analytic_id']" position="replace">
252 <attribute name="invisible">1</attribute>252 <field name="analytics_id" required="1"/>
253 </xpath>253 </xpath>
254 <xpath expr="//field[@name='analytic_id']" position="after">254 </field>
255 <field name="analytics_id" required="1"/>255 </record>
256 </xpath>
257 </field>
258 </record>
259
260 <record id="view_bank_statement_inherit_form" model="ir.ui.view">
261 <field name="name">account.bank.statement.form.inherit</field>
262 <field name="model">account.bank.statement</field>
263 <field name="inherit_id" ref="account.view_bank_statement_form"/>
264 <field name="arch" type="xml">
265 <xpath expr="/form/sheet/notebook/page/field[@name='line_ids']/tree/field[@name='analytic_account_id']" position="replace">
266 <field name="analytics_id" groups="analytic.group_analytic_accounting"/>
267 </xpath>
268 <xpath expr="/form/sheet/notebook/page/field[@name='line_ids']/form/group/field[@name='analytic_account_id']" position="replace">
269 <field name="analytics_id" groups="analytic.group_analytic_accounting"/>
270 </xpath>
271 </field>
272 </record>
273
274 <record id="view_bank_statement_inherit_form2" model="ir.ui.view">
275 <field name="name">account.bank.statement.form.inherit</field>
276 <field name="model">account.bank.statement</field>
277 <field name="inherit_id" ref="account.view_bank_statement_form2"/>
278 <field name="arch" type="xml">
279 <xpath expr="/form/sheet/notebook/page/field[@name='line_ids']/tree/field[@name='analytic_account_id']" position="replace">
280 <field name="analytics_id" groups="analytic.group_analytic_accounting"/>
281 </xpath>
282 <xpath expr="/form/sheet/notebook/page/field[@name='line_ids']/form/group/field[@name='analytic_account_id']" position="replace">
283 <field name="analytics_id" groups="analytic.group_analytic_accounting"/>
284 </xpath>
285 </field>
286 </record>
287
288</data>256</data>
289</openerp>257</openerp>
290258
=== added directory 'account_analytic_plans/static'
=== added directory 'account_analytic_plans/static/src'
=== added directory 'account_analytic_plans/static/src/js'
=== added file 'account_analytic_plans/static/src/js/account_bank_reconciliation.js'
--- account_analytic_plans/static/src/js/account_bank_reconciliation.js 1970-01-01 00:00:00 +0000
+++ account_analytic_plans/static/src/js/account_bank_reconciliation.js 2014-05-30 16:18:57 +0000
@@ -0,0 +1,35 @@
1openerp.account_analytic_plans = function(instance) {
2
3var _t = instance.web._t,
4 _lt = instance.web._lt;
5var QWeb = instance.web.qweb;
6
7instance.web.account.bankStatementReconciliation.include({
8
9 init: function(parent, context) {
10 this._super(parent, context);
11 delete this.create_form_fields.analytic_account_id;
12 this.create_form_fields["analytic_plan"] = {
13 id: "analytic_plan",
14 index: 4,
15 corresponding_property: "analytics_id",
16 label: _t("Analytic Distribution"),
17 required: false,
18 tabindex: 14,
19 group: "analytic.group_analytic_accounting",
20 constructor: instance.web.form.FieldMany2One,
21 field_properties: {
22 relation: "account.analytic.plan.instance",
23 string: _t("Analytic Distribution"),
24 type: "many2one",
25 }
26 };
27 },
28
29 start: function() {
30 return this._super().then(function() {
31 });
32 },
33
34});
35};
036
=== added file 'account_analytic_plans/views/account_analytic_plans.xml'
--- account_analytic_plans/views/account_analytic_plans.xml 1970-01-01 00:00:00 +0000
+++ account_analytic_plans/views/account_analytic_plans.xml 2014-05-30 16:18:57 +0000
@@ -0,0 +1,12 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- vim:fdn=3:
3-->
4<openerp>
5 <data>
6 <template id="assets_backend" name="account analytic plans assets" inherit_id="web.assets_backend">
7 <xpath expr="." position="inside">
8 <script type="text/javascript" src="/account_analytic_plans/static/src/js/account_bank_reconciliation.js"></script>
9 </xpath>
10 </template>
11 </data>
12</openerp>
013
=== modified file 'account_bank_statement_extensions/account_bank_statement_view.xml'
--- account_bank_statement_extensions/account_bank_statement_view.xml 2012-11-29 22:26:45 +0000
+++ account_bank_statement_extensions/account_bank_statement_view.xml 2014-05-30 16:18:57 +0000
@@ -74,10 +74,7 @@
74 <field name="name"/>74 <field name="name"/>
75 <field name="statement_id"/>75 <field name="statement_id"/>
76 <field name="ref" readonly="1"/>76 <field name="ref" readonly="1"/>
77 <field name="partner_id" on_change="onchange_partner_id(partner_id)"/>77 <field name="partner_id"/>
78 <field name="type" on_change="onchange_type(partner_id, type)"/>
79 <field name="account_id"/>
80 <field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('type', '&lt;&gt;', 'view')]"/>
81 <field name="amount" readonly="1" sum="Total Amount"/>78 <field name="amount" readonly="1" sum="Total Amount"/>
82 <field name="globalisation_id" string="Glob. Id"/>79 <field name="globalisation_id" string="Glob. Id"/>
83 <field name="globalisation_amount" string="Glob. Am."/>80 <field name="globalisation_amount" string="Glob. Am."/>
@@ -98,10 +95,7 @@
98 <field name="val_date"/>95 <field name="val_date"/>
99 <field name="name"/>96 <field name="name"/>
100 <field name="ref" readonly="0"/>97 <field name="ref" readonly="0"/>
101 <field name="partner_id" on_change="onchange_partner_id(partner_id)"/>98 <field name="partner_id"/>
102 <field name="type" on_change="onchange_type(partner_id, type)"/>
103 <field domain="[('type', '&lt;&gt;', 'view')]" name="account_id"/>
104 <field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('type', '&lt;&gt;', 'view')]"/>
105 <field name="amount"/>99 <field name="amount"/>
106 <field name="globalisation_id"/>100 <field name="globalisation_id"/>
107 <field name="sequence" readonly="0"/>101 <field name="sequence" readonly="0"/>
@@ -129,7 +123,6 @@
129 <field name="statement_id"/>123 <field name="statement_id"/>
130 <field name="globalisation_id" string="Glob. Id"/>124 <field name="globalisation_id" string="Glob. Id"/>
131 <group string="Extended Filters..." expand="0">125 <group string="Extended Filters..." expand="0">
132 <field name="account_id"/>
133 <field name="partner_id"/>126 <field name="partner_id"/>
134 <field name="amount"/>127 <field name="amount"/>
135 <field name="globalisation_amount" string="Glob. Amount"/>128 <field name="globalisation_amount" string="Glob. Amount"/>
@@ -138,7 +131,6 @@
138 <group string="Group By..." expand="1">131 <group string="Group By..." expand="1">
139 <filter string="Journal" context="{'group_by':'journal_id'}" icon="terp-folder-green"/>132 <filter string="Journal" context="{'group_by':'journal_id'}" icon="terp-folder-green"/>
140 <filter string="Statement" context="{'group_by':'statement_id'}" icon="terp-folder-orange"/>133 <filter string="Statement" context="{'group_by':'statement_id'}" icon="terp-folder-orange"/>
141 <filter string="Fin.Account" context="{'group_by':'account_id'}" icon="terp-folder-yellow"/>
142 </group>134 </group>
143 </search>135 </search>
144 </field>136 </field>
145137
=== modified file 'account_payment/wizard/account_payment_populate_statement.py'
--- account_payment/wizard/account_payment_populate_statement.py 2013-10-27 12:31:04 +0000
+++ account_payment/wizard/account_payment_populate_statement.py 2014-05-30 16:18:57 +0000
@@ -107,12 +107,9 @@
107 st_line_id = statement_line_obj.create(cr, uid, {107 st_line_id = statement_line_obj.create(cr, uid, {
108 'name': line.order_id.reference or '?',108 'name': line.order_id.reference or '?',
109 'amount': - amount,109 'amount': - amount,
110 'type': 'supplier',
111 'partner_id': line.partner_id.id,110 'partner_id': line.partner_id.id,
112 'account_id': line.move_line_id.account_id.id,
113 'statement_id': statement.id,111 'statement_id': statement.id,
114 'ref': line.communication,112 'ref': line.communication,
115 'voucher_id': voucher_id,
116 }, context=context)113 }, context=context)
117114
118 line_obj.write(cr, uid, [line.id], {'bank_statement_line_id': st_line_id})115 line_obj.write(cr, uid, [line.id], {'bank_statement_line_id': st_line_id})
119116
=== modified file 'account_voucher/__init__.py'
--- account_voucher/__init__.py 2012-11-29 22:26:45 +0000
+++ account_voucher/__init__.py 2014-05-30 16:18:57 +0000
@@ -22,6 +22,5 @@
22import account_voucher22import account_voucher
23import invoice23import invoice
24import report24import report
25import wizard
2625
27# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:26# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
2827
=== modified file 'account_voucher/__openerp__.py'
--- account_voucher/__openerp__.py 2014-04-02 16:40:53 +0000
+++ account_voucher/__openerp__.py 2014-05-30 16:18:57 +0000
@@ -49,7 +49,6 @@
49 'security/ir.model.access.csv',49 'security/ir.model.access.csv',
50 'account_voucher_sequence.xml',50 'account_voucher_sequence.xml',
51 'account_voucher_workflow.xml',51 'account_voucher_workflow.xml',
52 'wizard/account_statement_from_invoice_view.xml',
53 'account_voucher_view.xml',52 'account_voucher_view.xml',
54 'voucher_payment_receipt_view.xml',53 'voucher_payment_receipt_view.xml',
55 'voucher_sales_purchase_view.xml',54 'voucher_sales_purchase_view.xml',
5655
=== modified file 'account_voucher/account_voucher.py'
--- account_voucher/account_voucher.py 2014-05-02 13:03:52 +0000
+++ account_voucher/account_voucher.py 2014-05-30 16:18:57 +0000
@@ -327,7 +327,6 @@
327 }327 }
328328
329 _columns = {329 _columns = {
330 'active': fields.boolean('Active', help="By default, reconciliation vouchers made on draft bank statements are set as inactive, which allow to hide the customer/supplier payment while the bank statement isn't confirmed."),
331 'type':fields.selection([330 'type':fields.selection([
332 ('sale','Sale'),331 ('sale','Sale'),
333 ('purchase','Purchase'),332 ('purchase','Purchase'),
@@ -389,7 +388,6 @@
389 'currency_help_label': fields.function(_fnct_currency_help_label, type='text', string="Helping Sentence", help="This sentence helps you to know how to specify the payment rate by giving you the direct effect it has"), 388 'currency_help_label': fields.function(_fnct_currency_help_label, type='text', string="Helping Sentence", help="This sentence helps you to know how to specify the payment rate by giving you the direct effect it has"),
390 }389 }
391 _defaults = {390 _defaults = {
392 'active': True,
393 'period_id': _get_period,391 'period_id': _get_period,
394 'partner_id': _get_partner,392 'partner_id': _get_partner,
395 'journal_id':_get_journal,393 'journal_id':_get_journal,
@@ -1583,114 +1581,6 @@
1583 })1581 })
1584 return values1582 return values
15851583
1586class account_bank_statement(osv.osv):
1587 _inherit = 'account.bank.statement'
1588
1589 def button_confirm_bank(self, cr, uid, ids, context=None):
1590 voucher_obj = self.pool.get('account.voucher')
1591 voucher_ids = []
1592 for statement in self.browse(cr, uid, ids, context=context):
1593 voucher_ids += [line.voucher_id.id for line in statement.line_ids if line.voucher_id]
1594 if voucher_ids:
1595 voucher_obj.write(cr, uid, voucher_ids, {'active': True}, context=context)
1596 return super(account_bank_statement, self).button_confirm_bank(cr, uid, ids, context=context)
1597
1598 def button_cancel(self, cr, uid, ids, context=None):
1599 voucher_obj = self.pool.get('account.voucher')
1600 for st in self.browse(cr, uid, ids, context=context):
1601 voucher_ids = []
1602 for line in st.line_ids:
1603 if line.voucher_id:
1604 voucher_ids.append(line.voucher_id.id)
1605 voucher_obj.cancel_voucher(cr, uid, voucher_ids, context)
1606 return super(account_bank_statement, self).button_cancel(cr, uid, ids, context=context)
1607
1608 def create_move_from_st_line(self, cr, uid, st_line_id, company_currency_id, next_number, context=None):
1609 voucher_obj = self.pool.get('account.voucher')
1610 move_line_obj = self.pool.get('account.move.line')
1611 bank_st_line_obj = self.pool.get('account.bank.statement.line')
1612 st_line = bank_st_line_obj.browse(cr, uid, st_line_id, context=context)
1613 if st_line.voucher_id:
1614 voucher_obj.write(cr, uid, [st_line.voucher_id.id],
1615 {'number': next_number,
1616 'date': st_line.date,
1617 'period_id': st_line.statement_id.period_id.id},
1618 context=context)
1619 if st_line.voucher_id.state == 'cancel':
1620 voucher_obj.action_cancel_draft(cr, uid, [st_line.voucher_id.id], context=context)
1621 voucher_obj.signal_proforma_voucher(cr, uid, [st_line.voucher_id.id])
1622
1623 v = voucher_obj.browse(cr, uid, st_line.voucher_id.id, context=context)
1624 bank_st_line_obj.write(cr, uid, [st_line_id], {
1625 'move_ids': [(4, v.move_id.id, False)]
1626 })
1627
1628 return move_line_obj.write(cr, uid, [x.id for x in v.move_ids], {'statement_id': st_line.statement_id.id}, context=context)
1629 return super(account_bank_statement, self).create_move_from_st_line(cr, uid, st_line.id, company_currency_id, next_number, context=context)
1630
1631 def write(self, cr, uid, ids, vals, context=None):
1632 # Restrict to modify the journal if we already have some voucher of reconciliation created/generated.
1633 # Because the voucher keeps in memory the journal it was created with.
1634 for bk_st in self.browse(cr, uid, ids, context=context):
1635 if vals.get('journal_id') and bk_st.line_ids:
1636 if any([x.voucher_id and True or False for x in bk_st.line_ids]):
1637 raise osv.except_osv(_('Unable to Change Journal!'), _('You can not change the journal as you already reconciled some statement lines!'))
1638 return super(account_bank_statement, self).write(cr, uid, ids, vals, context=context)
1639
1640
1641class account_bank_statement_line(osv.osv):
1642 _inherit = 'account.bank.statement.line'
1643
1644 def onchange_partner_id(self, cr, uid, ids, partner_id, context=None):
1645 res = super(account_bank_statement_line, self).onchange_partner_id(cr, uid, ids, partner_id, context=context)
1646 if 'value' not in res:
1647 res['value'] = {}
1648 res['value'].update({'voucher_id' : False})
1649 return res
1650
1651 def onchange_amount(self, cr, uid, ids, amount, context=None):
1652 return {'value' : {'voucher_id' : False}}
1653
1654 def _amount_reconciled(self, cursor, user, ids, name, args, context=None):
1655 if not ids:
1656 return {}
1657 res = {}
1658 for line in self.browse(cursor, user, ids, context=context):
1659 if line.voucher_id:
1660 res[line.id] = line.voucher_id.amount#
1661 else:
1662 res[line.id] = 0.0
1663 return res
1664
1665 def _check_amount(self, cr, uid, ids, context=None):
1666 for obj in self.browse(cr, uid, ids, context=context):
1667 if obj.voucher_id:
1668 diff = abs(obj.amount) - abs(obj.voucher_id.amount)
1669 if not self.pool.get('res.currency').is_zero(cr, uid, obj.statement_id.currency, diff):
1670 return False
1671 return True
1672
1673 _constraints = [
1674 (_check_amount, 'The amount of the voucher must be the same amount as the one on the statement line.', ['amount']),
1675 ]
1676
1677 _columns = {
1678 'amount_reconciled': fields.function(_amount_reconciled,
1679 string='Amount reconciled', type='float'),
1680 'voucher_id': fields.many2one('account.voucher', 'Reconciliation'),
1681 }
1682
1683 def unlink(self, cr, uid, ids, context=None):
1684 voucher_obj = self.pool.get('account.voucher')
1685 statement_line = self.browse(cr, uid, ids, context=context)
1686 unlink_ids = []
1687 for st_line in statement_line:
1688 if st_line.voucher_id:
1689 unlink_ids.append(st_line.voucher_id.id)
1690 voucher_obj.unlink(cr, uid, unlink_ids, context=context)
1691 return super(account_bank_statement_line, self).unlink(cr, uid, ids, context=context)
1692
1693
1694def resolve_o2m_operations(cr, uid, target_osv, operations, fields, context):1584def resolve_o2m_operations(cr, uid, target_osv, operations, fields, context):
1695 results = []1585 results = []
1696 for operation in operations:1586 for operation in operations:
16971587
=== modified file 'account_voucher/account_voucher_view.xml'
--- account_voucher/account_voucher_view.xml 2014-04-10 14:51:31 +0000
+++ account_voucher/account_voucher_view.xml 2014-05-30 16:18:57 +0000
@@ -193,59 +193,7 @@
193 <field name="context">{'state':'posted'}</field>193 <field name="context">{'state':'posted'}</field>
194 <field name="search_view_id" ref="view_voucher_filter"/>194 <field name="search_view_id" ref="view_voucher_filter"/>
195 </record>195 </record>
196196
197 <record id="view_bank_statement_form_invoice" model="ir.ui.view">
198 <field name="name">account.bank.statement.invoice.form.inherit</field>
199 <field name="model">account.bank.statement</field>
200 <field name="inherit_id" ref="account.view_bank_statement_form"/>
201 <field name="arch" type="xml">
202 <xpath expr="//div[@name='import_buttons']" position="inside">
203 <button class="oe_inline oe_stat_button" name="%(action_view_account_statement_from_invoice_lines)d"
204 string="Import Invoice" type="action"
205 attrs="{'invisible':[('state','=','confirm')]}" widget="statinfo" icon="fa-pencil-square-o"/>
206 </xpath>
207 </field>
208 </record>
209
210 <record id="view_bank_statement_form_voucher" model="ir.ui.view">
211 <field name="name">account.bank.statement.voucher.tree.inherit</field>
212 <field name="model">account.bank.statement</field>
213 <field name="inherit_id" ref="account.view_bank_statement_form"/>
214 <field name="arch" type="xml">
215 <xpath expr="//page[@name='statement_line_ids']/field[@name='line_ids']/tree/field[@name='amount']" position="after">
216 <field name="voucher_id" string="" widget="many2onebutton" options="{'label':{'create':'Reconcile','edit':'Edit Reconciliation'}}" context="{'line_type': type, 'default_type': amount &lt; 0 and 'payment' or 'receipt', 'type': amount &lt; 0 and 'payment' or 'receipt', 'default_partner_id': partner_id, 'default_journal_id': parent.journal_id, 'default_amount': abs(amount), 'default_reference': ref, 'default_date': date, 'default_name': name, 'default_active': False, 'account_id': account_id}"/>
217 </xpath>
218 <xpath expr="//page[@name='statement_line_ids']/field[@name='line_ids']/form/group/field[@name='sequence']" position="before">
219 <field name="voucher_id" widget="many2onebutton" options="{'label':{'create':'Reconcile','edit':'Edit Reconciliation'}}" context="{'line_type': type, 'default_type': amount &lt; 0 and 'payment' or 'receipt', 'type': amount &lt; 0 and 'payment' or 'receipt', 'default_partner_id': partner_id, 'default_journal_id': parent.journal_id, 'default_amount': abs(amount), 'default_reference': ref, 'default_date': date, 'default_name': name, 'default_active': False, 'account_id': account_id}"/>
220 </xpath>
221 <field name="amount" position="attributes">
222 <attribute name="on_change">onchange_amount(amount)</attribute>
223 </field>
224 </field>
225 </record>
226
227 <record id="view_cash_statement_tree_voucher" model="ir.ui.view">
228 <field name="name">account.cash.statement.voucher.tree.inherit</field>
229 <field name="model">account.bank.statement</field>
230 <field name="inherit_id" ref="account.view_bank_statement_form2"/>
231 <field name="arch" type="xml">
232 <xpath expr="//page/field[@name='line_ids']/tree/field[@name='amount']" position="after">
233 <field name="voucher_id" context="{'line_type': type, 'default_type': amount &lt; 0 and 'payment' or 'receipt', 'type': amount &lt; 0 and 'payment' or 'receipt', 'default_partner_id': partner_id, 'default_journal_id': parent.journal_id, 'default_amount': abs(amount), 'default_reference': ref, 'default_date': date, 'default_name': name, 'account_id': account_id}"/>
234 </xpath>
235 </field>
236 </record>
237
238 <record id="view_cash_statement_form_voucher" model="ir.ui.view">
239 <field name="name">account.cash.statement.voucher.form.inherit</field>
240 <field name="model">account.bank.statement</field>
241 <field name="inherit_id" ref="account.view_bank_statement_form2"/>
242 <field name="arch" type="xml">
243 <xpath expr="//page/field[@name='line_ids']/form/group/field[@name='amount']" position="after">
244 <field name="voucher_id" context="{'line_type': type, 'default_type': amount &lt; 0 and 'payment' or 'receipt', 'type': amount &lt; 0 and 'payment' or 'receipt', 'default_partner_id': partner_id, 'default_journal_id': parent.journal_id, 'default_amount': abs(amount), 'default_reference': ref, 'default_date': date, 'default_name': name, 'account_id': account_id}"/>
245 </xpath>
246 </field>
247 </record>
248
249 <!-- res.config form view -->197 <!-- res.config form view -->
250 <record model="ir.ui.view" id="view_account_settings_currency_xchange_form">198 <record model="ir.ui.view" id="view_account_settings_currency_xchange_form">
251 <field name="name">account.config.settings.inherit</field>199 <field name="name">account.config.settings.inherit</field>
252200
=== removed directory 'account_voucher/wizard'
=== removed file 'account_voucher/wizard/__init__.py'
--- account_voucher/wizard/__init__.py 2012-11-29 22:26:45 +0000
+++ account_voucher/wizard/__init__.py 1970-01-01 00:00:00 +0000
@@ -1,24 +0,0 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# OpenERP, Open Source Management Solution
5# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21
22import account_statement_from_invoice
23
24# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
250
=== modified file 'l10n_be_coda/__openerp__.py'
--- l10n_be_coda/__openerp__.py 2012-12-06 11:18:16 +0000
+++ l10n_be_coda/__openerp__.py 2014-05-30 16:18:57 +0000
@@ -2,9 +2,9 @@
2##############################################################################2##############################################################################
3#3#
4# OpenERP, Open Source Management Solution4# OpenERP, Open Source Management Solution
5# 5#
6# Copyright (c) 2011 Noviat nv/sa (www.noviat.be). All rights reserved.6# Copyright (c) 2011 Noviat nv/sa (www.noviat.be). All rights reserved.
7# 7#
8# This program is free software: you can redistribute it and/or modify8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the10# published by the Free Software Foundation, either version 3 of the
@@ -34,64 +34,64 @@
34 * CODA v2.2 support.34 * CODA v2.2 support.
35 * Foreign Currency support.35 * Foreign Currency support.
36 * Support for all data record types (0, 1, 2, 3, 4, 8, 9).36 * Support for all data record types (0, 1, 2, 3, 4, 8, 9).
37 * Parsing & logging of all Transaction Codes and Structured Format 37 * Parsing & logging of all Transaction Codes and Structured Format
38 Communications.38 Communications.
39 * Automatic Financial Journal assignment via CODA configuration parameters.39 * Automatic Financial Journal assignment via CODA configuration parameters.
40 * Support for multiple Journals per Bank Account Number.40 * Support for multiple Journals per Bank Account Number.
41 * Support for multiple statements from different bank accounts in a single 41 * Support for multiple statements from different bank accounts in a single
42 CODA file.42 CODA file.
43 * Support for 'parsing only' CODA Bank Accounts (defined as type='info' in 43 * Support for 'parsing only' CODA Bank Accounts (defined as type='info' in
44 the CODA Bank Account configuration records).44 the CODA Bank Account configuration records).
45 * Multi-language CODA parsing, parsing configuration data provided for EN, 45 * Multi-language CODA parsing, parsing configuration data provided for EN,
46 NL, FR.46 NL, FR.
4747
48The machine readable CODA Files are parsed and stored in human readable format in 48The machine readable CODA Files are parsed and stored in human readable format in
49CODA Bank Statements. Also Bank Statements are generated containing a subset of 49CODA Bank Statements. Also Bank Statements are generated containing a subset of
50the CODA information (only those transaction lines that are required for the 50the CODA information (only those transaction lines that are required for the
51creation of the Financial Accounting records). The CODA Bank Statement is a 51creation of the Financial Accounting records). The CODA Bank Statement is a
52'read-only' object, hence remaining a reliable representation of the original52'read-only' object, hence remaining a reliable representation of the original
53CODA file whereas the Bank Statement will get modified as required by accounting 53CODA file whereas the Bank Statement will get modified as required by accounting
54business processes.54business processes.
5555
56CODA Bank Accounts configured as type 'Info' will only generate CODA Bank Statements.56CODA Bank Accounts configured as type 'Info' will only generate CODA Bank Statements.
5757
58A removal of one object in the CODA processing results in the removal of the 58A removal of one object in the CODA processing results in the removal of the
59associated objects. The removal of a CODA File containing multiple Bank 59associated objects. The removal of a CODA File containing multiple Bank
60Statements will also remove those associated statements.60Statements will also remove those associated statements.
6161
62The following reconciliation logic has been implemented in the CODA processing:62The following reconciliation logic has been implemented in the CODA processing:
63-------------------------------------------------------------------------------63-------------------------------------------------------------------------------
64 1) The Company's Bank Account Number of the CODA statement is compared against 64 1) The Company's Bank Account Number of the CODA statement is compared against
65 the Bank Account Number field of the Company's CODA Bank Account 65 the Bank Account Number field of the Company's CODA Bank Account
66 configuration records (whereby bank accounts defined in type='info' 66 configuration records (whereby bank accounts defined in type='info'
67 configuration records are ignored). If this is the case an 'internal transfer'67 configuration records are ignored). If this is the case an 'internal transfer'
68 transaction is generated using the 'Internal Transfer Account' field of the 68 transaction is generated using the 'Internal Transfer Account' field of the
69 CODA File Import wizard.69 CODA File Import wizard.
70 2) As a second step the 'Structured Communication' field of the CODA transaction70 2) As a second step the 'Structured Communication' field of the CODA transaction
71 line is matched against the reference field of in- and outgoing invoices 71 line is matched against the reference field of in- and outgoing invoices
72 (supported : Belgian Structured Communication Type).72 (supported : Belgian Structured Communication Type).
73 3) When the previous step doesn't find a match, the transaction counterparty is 73 3) When the previous step doesn't find a match, the transaction counterparty is
74 located via the Bank Account Number configured on the OpenERP Customer and 74 located via the Bank Account Number configured on the OpenERP Customer and
75 Supplier records.75 Supplier records.
76 4) In case the previous steps are not successful, the transaction is generated 76 4) In case the previous steps are not successful, the transaction is generated
77 by using the 'Default Account for Unrecognized Movement' field of the CODA 77 by using the 'Default Account for Unrecognized Movement' field of the CODA
78 File Import wizard in order to allow further manual processing.78 File Import wizard in order to allow further manual processing.
7979
80In stead of a manual adjustment of the generated Bank Statements, you can also 80In stead of a manual adjustment of the generated Bank Statements, you can also
81re-import the CODA after updating the OpenERP database with the information that 81re-import the CODA after updating the OpenERP database with the information that
82was missing to allow automatic reconciliation.82was missing to allow automatic reconciliation.
8383
84Remark on CODA V1 support:84Remark on CODA V1 support:
85~~~~~~~~~~~~~~~~~~~~~~~~~~85~~~~~~~~~~~~~~~~~~~~~~~~~~
86In some cases a transaction code, transaction category or structured 86In some cases a transaction code, transaction category or structured
87communication code has been given a new or clearer description in CODA V2.The87communication code has been given a new or clearer description in CODA V2.The
88description provided by the CODA configuration tables is based upon the CODA 88description provided by the CODA configuration tables is based upon the CODA
89V2.2 specifications.89V2.2 specifications.
90If required, you can manually adjust the descriptions via the CODA configuration menu.90If required, you can manually adjust the descriptions via the CODA configuration menu.
91''',91''',
92 'images' : ['images/coda_logs.jpeg','images/import_coda_logs.jpeg'],92 'images': ['images/coda_logs.jpeg', 'images/import_coda_logs.jpeg'],
93 'depends': ['account_voucher','base_iban', 'l10n_be_invoice_bba',],93 'depends': ['account_voucher', 'base_iban', 'l10n_be_invoice_bba'],
94 'demo': [],94 'demo': ['l10n_be_coda_demo.xml'],
95 'data': [95 'data': [
96 'l10n_be_coda_wizard.xml',96 'l10n_be_coda_wizard.xml',
97 'l10n_be_coda_view.xml',97 'l10n_be_coda_view.xml',
9898
=== added file 'l10n_be_coda/l10n_be_coda_demo.xml'
--- l10n_be_coda/l10n_be_coda_demo.xml 1970-01-01 00:00:00 +0000
+++ l10n_be_coda/l10n_be_coda_demo.xml 2014-05-30 16:18:57 +0000
@@ -0,0 +1,36 @@
1<?xml version="1.0" ?>
2<openerp>
3 <data>
4 <record id="demo_bank_account" model="res.partner.bank">
5 <field name="state">bank</field>
6 <field name="acc_number">BE33737018595246</field>
7 <field name="bank_bic">KREDBEBB</field>
8 <field name="journal_id" ref="account.bank_journal"/>
9 <field name="partner_id" ref="base.main_partner"/>
10 </record>
11 <!--
12 Fiscal year
13 -->
14
15 <record id="data_fiscalyear_2011" model="account.fiscalyear">
16 <field eval="'Fiscal Year X 2011'" name="name"/>
17 <field eval="'FY2011'" name="code"/>
18 <field eval="'2011-01-01'" name="date_start"/>
19 <field eval="'2011-12-31'" name="date_stop"/>
20 <field name="company_id" ref="base.main_company"/>
21 </record>
22
23 <!--
24 Fiscal Periods
25 -->
26
27 <record id="period_1_2011" model="account.period">
28 <field eval="'01/2011'" name="code"/>
29 <field eval="'X 01/2011'" name="name"/>
30 <field name="fiscalyear_id" ref="data_fiscalyear_2011"/>
31 <field eval="'2011-01-01'" name="date_start"/>
32 <field eval="'2011-01-31'" name="date_stop"/>
33 <field name="company_id" ref="base.main_company"/>
34 </record>
35 </data>
36</openerp>
037
=== modified file 'l10n_be_coda/l10n_be_coda_view.xml'
--- l10n_be_coda/l10n_be_coda_view.xml 2013-10-27 12:31:04 +0000
+++ l10n_be_coda/l10n_be_coda_view.xml 2014-05-30 16:18:57 +0000
@@ -25,8 +25,6 @@
25 <field name="name"/>25 <field name="name"/>
26 <field name="ref" readonly="0"/>26 <field name="ref" readonly="0"/>
27 <field name="partner_id"/>27 <field name="partner_id"/>
28 <field name="type" />
29 <field domain="[('type', '&lt;&gt;', 'view')]" name="account_id"/>
30 <field name="amount"/>28 <field name="amount"/>
31 <field name="sequence" readonly="0"/>29 <field name="sequence" readonly="0"/>
32 </group>30 </group>
@@ -46,10 +44,7 @@
46 <field name="date"/>44 <field name="date"/>
47 <field name="name"/>45 <field name="name"/>
48 <field name="ref"/>46 <field name="ref"/>
49 <field name="partner_id" on_change="onchange_partner_id(partner_id)"/>47 <field name="partner_id"/>
50 <field name="type" on_change="onchange_type(partner_id, type)"/>
51 <field name="account_id" options='{"no_open":True}' domain="[('type', '&lt;&gt;', 'view')]"/>
52 <field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('type', '&lt;&gt;', 'view')]"/>
53 <field name="amount"/>48 <field name="amount"/>
54 <field name="note"/>49 <field name="note"/>
55 </tree>50 </tree>
@@ -66,17 +61,14 @@
66 <filter name="credit" string="Credit" domain="[('amount','&lt;',0)]" icon="terp-folder-orange" help="Credit Transactions."/>61 <filter name="credit" string="Credit" domain="[('amount','&lt;',0)]" icon="terp-folder-orange" help="Credit Transactions."/>
67 <field name="statement_id"/>62 <field name="statement_id"/>
68 <group expand="0" string="Extended Filters...">63 <group expand="0" string="Extended Filters...">
69 <field name="account_id"/>
70 <field name="partner_id"/>64 <field name="partner_id"/>
71 <field name="amount"/>65 <field name="amount"/>
72 <field name="type"/>
73 <field name="note"/>66 <field name="note"/>
74 </group>67 </group>
75 <newline/>68 <newline/>
76 <group string="Group By..." expand="0">69 <group string="Group By..." expand="0">
77 <filter string="Partner" context="{'group_by':'partner_id'}" icon="terp-folder-green"/>70 <filter string="Partner" context="{'group_by':'partner_id'}" icon="terp-folder-green"/>
78 <filter string="Statement" context="{'group_by':'statement_id'}" icon="terp-folder-orange"/>71 <filter string="Statement" context="{'group_by':'statement_id'}" icon="terp-folder-orange"/>
79 <filter string="Fin.Account" context="{'group_by':'account_id'}" icon="terp-folder-yellow"/>
80 </group>72 </group>
81 </search>73 </search>
82 </field>74 </field>
8375
=== modified file 'l10n_be_coda/l10n_be_coda_wizard.xml'
--- l10n_be_coda/l10n_be_coda_wizard.xml 2012-12-20 14:52:27 +0000
+++ l10n_be_coda/l10n_be_coda_wizard.xml 2014-05-30 16:18:57 +0000
@@ -10,7 +10,6 @@
10 <form string="Import CODA File" version="7.0">10 <form string="Import CODA File" version="7.0">
11 <group col="2">11 <group col="2">
12 <field name="coda_data" filename="coda_fname"/>12 <field name="coda_data" filename="coda_fname"/>
13 <field name="temporary_account_id" />
14 </group>13 </group>
15 <footer>14 <footer>
16 <button name="coda_parsing" string="_Import" type="object" class="oe_highlight"/>15 <button name="coda_parsing" string="_Import" type="object" class="oe_highlight"/>
1716
=== modified file 'l10n_be_coda/wizard/account_coda_import.py'
--- l10n_be_coda/wizard/account_coda_import.py 2013-10-27 12:31:04 +0000
+++ l10n_be_coda/wizard/account_coda_import.py 2014-05-30 16:18:57 +0000
@@ -37,20 +37,10 @@
37 'coda_data': fields.binary('CODA File', required=True),37 'coda_data': fields.binary('CODA File', required=True),
38 'coda_fname': fields.char('CODA Filename', size=128, required=True),38 'coda_fname': fields.char('CODA Filename', size=128, required=True),
39 'note': fields.text('Log'),39 'note': fields.text('Log'),
40 'temporary_account_id': fields.many2one('account.account', 'Temporary Account', domain="[('type','!=','view')]", help="It acts as a temporary account for general amount", required=True),
41 }40 }
4241
43 def _get_default_tmp_account(self, cr, uid, context):
44 tmp_accounts = self.pool.get('account.account').search(cr, uid, [('code', '=', '490000')])
45 if tmp_accounts and len(tmp_accounts) > 0:
46 tmp_account_id = tmp_accounts[0]
47 else:
48 tmp_account_id = False
49 return tmp_account_id
50
51 _defaults = {42 _defaults = {
52 'coda_fname': lambda *a: '',43 'coda_fname': lambda *a: '',
53 'temporary_account_id': _get_default_tmp_account,
54 }44 }
5545
56 def coda_parsing(self, cr, uid, ids, context=None, batch=False, codafile=None, codafilename=None):46 def coda_parsing(self, cr, uid, ids, context=None, batch=False, codafile=None, codafilename=None):
@@ -64,7 +54,6 @@
64 try:54 try:
65 codafile = data.coda_data55 codafile = data.coda_data
66 codafilename = data.coda_fname56 codafilename = data.coda_fname
67 temporaryaccount = data.temporary_account_id.id
68 except:57 except:
69 raise osv.except_osv(_('Error'), _('Wizard in incorrect state. Please hit the Cancel button'))58 raise osv.except_osv(_('Error'), _('Wizard in incorrect state. Please hit the Cancel button'))
70 return {}59 return {}
@@ -149,7 +138,6 @@
149 statementLine['amount'] = float(rmspaces(line[32:47])) / 1000138 statementLine['amount'] = float(rmspaces(line[32:47])) / 1000
150 if statementLine['debit'] == '1':139 if statementLine['debit'] == '1':
151 statementLine['amount'] = - statementLine['amount']140 statementLine['amount'] = - statementLine['amount']
152 statementLine['transaction_type'] = line[53]
153 statementLine['transactionDate'] = time.strftime(tools.DEFAULT_SERVER_DATE_FORMAT, time.strptime(rmspaces(line[47:53]), '%d%m%y'))141 statementLine['transactionDate'] = time.strftime(tools.DEFAULT_SERVER_DATE_FORMAT, time.strptime(rmspaces(line[47:53]), '%d%m%y'))
154 statementLine['transaction_family'] = rmspaces(line[54:56])142 statementLine['transaction_family'] = rmspaces(line[54:56])
155 statementLine['transaction_code'] = rmspaces(line[56:58])143 statementLine['transaction_code'] = rmspaces(line[56:58])
@@ -211,7 +199,6 @@
211 infoLine['sequence'] = len(statement['lines']) + 1199 infoLine['sequence'] = len(statement['lines']) + 1
212 infoLine['ref'] = rmspaces(line[2:10])200 infoLine['ref'] = rmspaces(line[2:10])
213 infoLine['transactionRef'] = rmspaces(line[10:31])201 infoLine['transactionRef'] = rmspaces(line[10:31])
214 infoLine['transaction_type'] = line[31]
215 infoLine['transaction_family'] = rmspaces(line[32:34])202 infoLine['transaction_family'] = rmspaces(line[32:34])
216 infoLine['transaction_code'] = rmspaces(line[34:36])203 infoLine['transaction_code'] = rmspaces(line[34:36])
217 infoLine['transaction_category'] = rmspaces(line[36:39])204 infoLine['transaction_category'] = rmspaces(line[36:39])
@@ -304,91 +291,78 @@
304 if 'counterpartyAddress' in line and line['counterpartyAddress'] != '':291 if 'counterpartyAddress' in line and line['counterpartyAddress'] != '':
305 note.append(_('Counter Party Address') + ': ' + line['counterpartyAddress'])292 note.append(_('Counter Party Address') + ': ' + line['counterpartyAddress'])
306 line['name'] = "\n".join(filter(None, [line['counterpartyName'], line['communication']]))293 line['name'] = "\n".join(filter(None, [line['counterpartyName'], line['communication']]))
307 line['transaction_type'] = 'general'
308 partner = None294 partner = None
309 partner_id = None295 partner_id = None
310 invoice = False296 invoice = False
311 if line['communication_struct'] and 'communication_type' in line and line['communication_type'] == '101':297 if line['communication_struct'] and 'communication_type' in line and line['communication_type'] == '101':
312 ids = self.pool.get('account.invoice').search(cr, uid, [('reference', '=', line['communication']), ('reference_type', '=', 'bba')])298 ids = self.pool.get('account.invoice').search(cr, uid, [('reference', '=', line['communication']), ('reference_type', '=', 'bba')])
313 if ids:299
314 invoice = self.pool.get('account.invoice').browse(cr, uid, ids[0])300# Gère les communications structurées
315 partner = invoice.partner_id301# TODO : à faire primer sur resolution_proposition : si la communication indique une facture, on la sélectionne
316 partner_id = partner.id302
317 if invoice.type in ['in_invoice', 'in_refund'] and line['debit'] == '1':303# if ids:
318 line['transaction_type'] = 'supplier'304# invoice = self.pool.get('account.invoice').browse(cr, uid, ids[0])
319 elif invoice.type in ['out_invoice', 'out_refund'] and line['debit'] == '0':305# partner = invoice.partner_id
320 line['transaction_type'] = 'customer'306# partner_id = partner.id
321 line['account'] = invoice.account_id.id307# if invoice.type in ['in_invoice', 'in_refund'] and line['debit'] == '1':
322 line['reconcile'] = False308# line['transaction_type'] = 'supplier'
323 if invoice.type in ['in_invoice', 'out_invoice']:309# elif invoice.type in ['out_invoice', 'out_refund'] and line['debit'] == '0':
324 iml_ids = self.pool.get('account.move.line').search(cr, uid, [('move_id', '=', invoice.move_id.id), ('reconcile_id', '=', False), ('account_id.reconcile', '=', True)])310# line['transaction_type'] = 'customer'
325 if iml_ids:311# line['account'] = invoice.account_id.id
326 line['reconcile'] = iml_ids[0]312# line['reconcile'] = False
327 if line['reconcile']:313# if invoice.type in ['in_invoice', 'out_invoice']:
328 voucher_vals = {314# iml_ids = self.pool.get('account.move.line').search(cr, uid, [('move_id', '=', invoice.move_id.id), ('reconcile_id', '=', False), ('account_id.reconcile', '=', True)])
329 'type': line['transaction_type'] == 'supplier' and 'payment' or 'receipt',315# if iml_ids:
330 'name': line['name'],316# line['reconcile'] = iml_ids[0]
331 'partner_id': partner_id,317# if line['reconcile']:
332 'journal_id': statement['journal_id'].id,318# voucher_vals = {
333 'account_id': statement['journal_id'].default_credit_account_id.id,319# 'type': line['transaction_type'] == 'supplier' and 'payment' or 'receipt',
334 'company_id': statement['journal_id'].company_id.id,320# 'name': line['name'],
335 'currency_id': statement['journal_id'].company_id.currency_id.id,321# 'partner_id': partner_id,
336 'date': line['entryDate'],322# 'journal_id': statement['journal_id'].id,
337 'amount': abs(line['amount']),323# 'account_id': statement['journal_id'].default_credit_account_id.id,
338 'period_id': statement['period_id'],324# 'company_id': statement['journal_id'].company_id.id,
339 'invoice_id': invoice.id,325# 'currency_id': statement['journal_id'].company_id.currency_id.id,
340 }326# 'date': line['entryDate'],
341 context['invoice_id'] = invoice.id327# 'amount': abs(line['amount']),
342 voucher_vals.update(self.pool.get('account.voucher').onchange_partner_id(cr, uid, [],328# 'period_id': statement['period_id'],
343 partner_id=partner_id,329# 'invoice_id': invoice.id,
344 journal_id=statement['journal_id'].id,330# }
345 amount=abs(line['amount']),331# context['invoice_id'] = invoice.id
346 currency_id=statement['journal_id'].company_id.currency_id.id,332# voucher_vals.update(self.pool.get('account.voucher').onchange_partner_id(cr, uid, [],
347 ttype=line['transaction_type'] == 'supplier' and 'payment' or 'receipt',333# partner_id=partner_id,
348 date=line['transactionDate'],334# journal_id=statement['journal_id'].id,
349 context=context335# amount=abs(line['amount']),
350 )['value'])336# currency_id=statement['journal_id'].company_id.currency_id.id,
351 line_drs = []337# ttype=line['transaction_type'] == 'supplier' and 'payment' or 'receipt',
352 for line_dr in voucher_vals['line_dr_ids']:338# date=line['transactionDate'],
353 line_drs.append((0, 0, line_dr))339# context=context
354 voucher_vals['line_dr_ids'] = line_drs340# )['value'])
355 line_crs = []341# line_drs = []
356 for line_cr in voucher_vals['line_cr_ids']:342# for line_dr in voucher_vals['line_dr_ids']:
357 line_crs.append((0, 0, line_cr))343# line_drs.append((0, 0, line_dr))
358 voucher_vals['line_cr_ids'] = line_crs344# voucher_vals['line_dr_ids'] = line_drs
359 line['voucher_id'] = self.pool.get('account.voucher').create(cr, uid, voucher_vals, context=context)345# line_crs = []
346# for line_cr in voucher_vals['line_cr_ids']:
347# line_crs.append((0, 0, line_cr))
348# voucher_vals['line_cr_ids'] = line_crs
349# line['voucher_id'] = self.pool.get('account.voucher').create(cr, uid, voucher_vals, context=context)
360 if 'counterpartyNumber' in line and line['counterpartyNumber']:350 if 'counterpartyNumber' in line and line['counterpartyNumber']:
361 ids = self.pool.get('res.partner.bank').search(cr, uid, [('acc_number', '=', str(line['counterpartyNumber']))])351 ids = self.pool.get('res.partner.bank').search(cr, uid, [('acc_number', '=', str(line['counterpartyNumber']))])
362 if ids and len(ids) > 0:352 if ids and len(ids) > 0:
363 partner = self.pool.get('res.partner.bank').browse(cr, uid, ids[0], context=context).partner_id353 partner = self.pool.get('res.partner.bank').browse(cr, uid, ids[0], context=context).partner_id
364 partner_id = partner.id354 partner_id = partner.id
365 if not invoice:
366 if line['debit'] == '0':
367 line['account'] = partner.property_account_receivable.id
368 if partner.customer:
369 line['transaction_type'] = 'customer'
370 elif line['debit'] == '1':
371 line['account'] = partner.property_account_payable.id
372 if partner.supplier:
373 line['transaction_type'] = 'supplier'
374 if not partner and not invoice:
375 line['account'] = temporaryaccount
376 if 'communication' in line and line['communication'] != '':355 if 'communication' in line and line['communication'] != '':
377 note.append(_('Communication') + ': ' + line['communication'])356 note.append(_('Communication') + ': ' + line['communication'])
378 if 'voucher_id' not in line:
379 line['voucher_id'] = None
380 data = {357 data = {
381 'name': line['name'],358 'name': line['name'],
382 'note': "\n".join(note),359 'note': "\n".join(note),
383 'date': line['entryDate'],360 'date': line['entryDate'],
384 'amount': line['amount'],361 'amount': line['amount'],
385 'type': line['transaction_type'],
386 'partner_id': partner_id,362 'partner_id': partner_id,
387 'account_id': line['account'],
388 'statement_id': statement['id'],363 'statement_id': statement['id'],
389 'ref': line['ref'],364 'ref': line['ref'],
390 'sequence': line['sequence'],365 'sequence': line['sequence'],
391 'voucher_id': line['voucher_id'],
392 'coda_account_number': line['counterpartyNumber'],366 'coda_account_number': line['counterpartyNumber'],
393 }367 }
394 self.pool.get('account.bank.statement.line').create(cr, uid, data, context=context)368 self.pool.get('account.bank.statement.line').create(cr, uid, data, context=context)
395369
=== modified file 'point_of_sale/point_of_sale.py'
--- point_of_sale/point_of_sale.py 2014-05-08 14:39:40 +0000
+++ point_of_sale/point_of_sale.py 2014-05-30 16:18:57 +0000
@@ -457,19 +457,13 @@
457 if st.difference and st.journal_id.cash_control == True:457 if st.difference and st.journal_id.cash_control == True:
458 if st.difference > 0.0:458 if st.difference > 0.0:
459 name= _('Point of Sale Profit')459 name= _('Point of Sale Profit')
460 account_id = st.journal_id.profit_account_id.id
461 else:460 else:
462 account_id = st.journal_id.loss_account_id.id
463 name= _('Point of Sale Loss')461 name= _('Point of Sale Loss')
464 if not account_id:
465 raise osv.except_osv( _('Error!'),
466 _("Please set your profit and loss accounts on your payment method '%s'. This will allow OpenERP to post the difference of %.2f in your ending balance. To close this session, you can update the 'Closing Cash Control' to avoid any difference.") % (st.journal_id.name,st.difference))
467 bsl.create(cr, uid, {462 bsl.create(cr, uid, {
468 'statement_id': st.id,463 'statement_id': st.id,
469 'amount': st.difference,464 'amount': st.difference,
470 'ref': record.name,465 'ref': record.name,
471 'name': name,466 'name': name,
472 'account_id': account_id
473 }, context=context)467 }, context=context)
474468
475 if st.journal_id.type == 'bank':469 if st.journal_id.type == 'bank':
@@ -822,20 +816,9 @@
822 'amount': data['amount'],816 'amount': data['amount'],
823 'date': data.get('payment_date', time.strftime('%Y-%m-%d')),817 'date': data.get('payment_date', time.strftime('%Y-%m-%d')),
824 'name': order.name + ': ' + (data.get('payment_name', '') or ''),818 'name': order.name + ': ' + (data.get('payment_name', '') or ''),
819 'partner_id': order.partner_id and order.partner_id.id or None,
825 }820 }
826821
827 account_def = property_obj.get(cr, uid, 'property_account_receivable', 'res.partner', context=context)
828 args['account_id'] = (order.partner_id and order.partner_id.property_account_receivable \
829 and order.partner_id.property_account_receivable.id) or (account_def and account_def.id) or False
830 args['partner_id'] = order.partner_id and order.partner_id.id or None
831
832 if not args['account_id']:
833 if not args['partner_id']:
834 msg = _('There is no receivable account defined to make payment.')
835 else:
836 msg = _('There is no receivable account defined to make payment for the partner: "%s" (id:%d).') % (order.partner_id.name, order.partner_id.id,)
837 raise osv.except_osv(_('Configuration Error!'), msg)
838
839 context.pop('pos_session_id', False)822 context.pop('pos_session_id', False)
840823
841 journal_id = data.get('journal', False)824 journal_id = data.get('journal', False)
@@ -857,7 +840,6 @@
857 'statement_id' : statement_id,840 'statement_id' : statement_id,
858 'pos_statement_id' : order_id,841 'pos_statement_id' : order_id,
859 'journal_id' : journal_id,842 'journal_id' : journal_id,
860 'type' : 'customer',
861 'ref' : order.session_id.name,843 'ref' : order.session_id.name,
862 })844 })
863845
864846
=== modified file 'point_of_sale/point_of_sale_view.xml'
--- point_of_sale/point_of_sale_view.xml 2014-05-07 18:29:17 +0000
+++ point_of_sale/point_of_sale_view.xml 2014-05-30 16:18:57 +0000
@@ -68,13 +68,6 @@
68 <field name="statement_id"/>68 <field name="statement_id"/>
69 <field name="amount"/>69 <field name="amount"/>
70 </tree>70 </tree>
71 <form string="Statement lines" version="7.0">
72 <group col="4">
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: