95
54
journal_obj = self.pool.get('account.journal')
96
55
res = journal_obj.search(cr, uid, args, limit=1)
97
56
return res and res[0] or False
99
def _get_fake(self, cr, uid, ids, field_name=None, arg=None, context=None):
101
Fake method for 'ready_for_import_in_debit_note' field
108
def _search_ready_for_import_in_debit_note(self, cr, uid, obj, name, args, context=None):
111
account_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.import_invoice_default_account and \
112
self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.import_invoice_default_account.id or False
114
raise osv.except_osv(_('Error'), _('No default account for import invoice on Debit Note!'))
116
('account_id','=',account_id),
117
('reconciled','=',False),
118
('state', '=', 'open'),
119
('type', '=', 'out_invoice'),
120
('journal_id.type', 'not in', ['migration']),
121
('partner_id.partner_type', '=', 'section'),
123
return dom1+[('is_debit_note', '=', False)]
125
def _get_fake_m2o_id(self, cr, uid, ids, field_name=None, arg=None, context=None):
127
Get many2one field content
130
name = field_name.replace("fake_", '')
131
for i in self.browse(cr, uid, ids):
132
if context and context.get('is_intermission', False):
134
if name == 'account_id':
135
user = self.pool.get('res.users').browse(cr, uid, [uid], context=context)
136
if user[0].company_id.intermission_default_counterpart:
137
res[i.id] = user[0].company_id.intermission_default_counterpart.id
138
elif name == 'journal_id':
139
int_journal_id = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'intermission')], context=context)
141
if isinstance(int_journal_id, (int, long)):
142
int_journal_id = [int_journal_id]
143
res[i.id] = int_journal_id[0]
144
elif name == 'currency_id':
145
user = self.pool.get('res.users').browse(cr, uid, [uid], context=context)
146
if user[0].company_id.currency_id:
147
res[i.id] = user[0].company_id.currency_id.id
149
res[i.id] = getattr(i, name, False) and getattr(getattr(i, name, False), 'id', False) or False
152
def _get_have_donation_certificate(self, cr, uid, ids, field_name=None, arg=None, context=None):
154
If this invoice have a stock picking in which there is a Certificate of Donation, return True. Otherwise return False.
157
for i in self.browse(cr, uid, ids):
160
a_ids = self.pool.get('ir.attachment').search(cr, uid, [('res_model', '=', 'stock.picking'), ('res_id', '=', i.picking_id.id), ('description', '=', 'Certificate of Donation')])
165
def _get_virtual_fields(self, cr, uid, ids, field_name=None, arg=None, context=None):
167
Get fields in order to transform them into 'virtual fields" (kind of field duplicity):
173
for inv in self.browse(cr, uid, ids, context=context):
174
res[inv.id] = {'virtual_currency_id': inv.currency_id.id or False, 'virtual_account_id': inv.account_id.id or False,
175
'virtual_partner_id': inv.partner_id.id or False}
178
def _get_vat_ok(self, cr, uid, ids, field_name, args, context=None):
180
Return True if the system configuration VAT management is set to True
182
vat_ok = self.pool.get('unifield.setup.configuration').get_config(cr, uid).vat_ok
189
def _get_can_merge_lines(self, cr, uid, ids, field_name, args,
194
if isinstance(ids, (int, long, )):
197
for inv_br in self.browse(cr, uid, ids, context=context):
198
# US-357: allow merge of line only for draft SI
199
res[inv_br.id] = inv_br.state and inv_br.state == 'draft' \
200
and inv_br.invoice_line \
201
and inv_br.type == 'in_invoice' \
202
and not inv_br.is_direct_invoice \
203
and not inv_br.is_inkind_donation \
204
and not inv_br.is_debit_note \
205
and not inv_br.is_intermission \
58
def onchange_company_id(self, cr, uid, ids, company_id, part_id, type, invoice_line, currency_id):
60
This is a method to redefine the journal_id domain with the current_instance taken into account
62
res = super(account_invoice, self).onchange_company_id(cr, uid, ids, company_id, part_id, type, invoice_line, currency_id)
63
if 'domain' in res and 'journal_id' in res['domain']:
64
journal_domain = res['domain']['journal_id']
65
journal_domain.append(('is_current_instance','=',True))
66
new_journal_ids = self.pool.get('account.journal').search(cr, uid, journal_domain)
67
res['domain']['journal_id'] = [('id','in',new_journal_ids)]
211
71
'from_yml_test': fields.boolean('Only used to pass addons unit test', readonly=True, help='Never set this field to true !'),
212
72
'sequence_id': fields.many2one('ir.sequence', string='Lines Sequence', ondelete='cascade',
213
73
help="This field contains the information related to the numbering of the lines of this order."),
214
'date_invoice': fields.date('Posting Date', states={'paid':[('readonly',True)], 'open':[('readonly',True)],
215
'close':[('readonly',True)]}, select=True),
216
'document_date': fields.date('Document Date', states={'paid':[('readonly',True)], 'open':[('readonly',True)],
217
'close':[('readonly',True)]}, select=True),
218
'is_debit_note': fields.boolean(string="Is a Debit Note?"),
219
'is_inkind_donation': fields.boolean(string="Is an In-kind Donation?"),
220
'is_intermission': fields.boolean(string="Is an Intermission Voucher?"),
221
'ready_for_import_in_debit_note': fields.function(_get_fake, fnct_search=_search_ready_for_import_in_debit_note, type="boolean",
222
method=True, string="Can be imported as invoice in a debit note?",),
223
'imported_invoices': fields.one2many('account.invoice.line', 'import_invoice_id', string="Imported invoices", readonly=True),
224
'partner_move_line': fields.one2many('account.move.line', 'invoice_partner_link', string="Partner move line", readonly=True),
225
'fake_account_id': fields.function(_get_fake_m2o_id, method=True, type='many2one', relation="account.account", string="Account", readonly="True"),
226
'fake_journal_id': fields.function(_get_fake_m2o_id, method=True, type='many2one', relation="account.journal", string="Journal", readonly="True"),
227
'fake_currency_id': fields.function(_get_fake_m2o_id, method=True, type='many2one', relation="res.currency", string="Currency", readonly="True"),
228
'have_donation_certificate': fields.function(_get_have_donation_certificate, method=True, type='boolean', string="Have a Certificate of donation?"),
229
'purchase_list': fields.boolean(string='Purchase List ?', help='Check this box if the invoice comes from a purchase list', readonly=True, states={'draft':[('readonly',False)]}),
230
'virtual_currency_id': fields.function(_get_virtual_fields, method=True, store=False, multi='virtual_fields', string="Currency",
231
type='many2one', relation="res.currency", readonly=True),
232
'virtual_account_id': fields.function(_get_virtual_fields, method=True, store=False, multi='virtual_fields', string="Account",
233
type='many2one', relation="account.account", readonly=True),
234
'virtual_partner_id': fields.function(_get_virtual_fields, method=True, store=False, multi='virtual_fields', string="Supplier",
235
type='many2one', relation="res.partner", readonly=True),
236
'register_line_ids': fields.one2many('account.bank.statement.line', 'invoice_id', string="Register Lines"),
237
'is_direct_invoice': fields.boolean("Is direct invoice?", readonly=True),
238
'address_invoice_id': fields.many2one('res.partner.address', 'Invoice Address', readonly=True, required=False,
239
states={'draft':[('readonly',False)]}),
240
'register_posting_date': fields.date(string="Register posting date for Direct Invoice", required=False),
241
'vat_ok': fields.function(_get_vat_ok, method=True, type='boolean', string='VAT OK', store=False, readonly=True),
242
'st_lines': fields.one2many('account.bank.statement.line', 'invoice_id', string="Register lines", readonly=True, help="Register lines that have a link to this invoice."),
243
'can_merge_lines': fields.function(_get_can_merge_lines, method=True, type='boolean', string='Can merge lines ?'),
244
'is_merged_by_account': fields.boolean("Is merged by account"),
74
'date_invoice': fields.date('Posting Date', states={'paid':[('readonly',True)], 'open':[('readonly',True)],
75
'close':[('readonly',True)]}, select=True),
76
'document_date': fields.date('Document Date', states={'paid':[('readonly',True)], 'open':[('readonly',True)],
77
'close':[('readonly',True)]}, select=True),
248
81
'journal_id': _get_journal,
249
82
'from_yml_test': lambda *a: False,
250
83
'date_invoice': lambda *a: strftime('%Y-%m-%d'),
251
'is_debit_note': lambda obj, cr, uid, c: c.get('is_debit_note', False),
252
'is_inkind_donation': lambda obj, cr, uid, c: c.get('is_inkind_donation', False),
253
'is_intermission': lambda obj, cr, uid, c: c.get('is_intermission', False),
254
'is_direct_invoice': lambda *a: False,
255
'vat_ok': lambda obj, cr, uid, context: obj.pool.get('unifield.setup.configuration').get_config(cr, uid).vat_ok,
256
'can_merge_lines': lambda *a: False,
257
'is_merged_by_account': lambda *a: False,
260
def onchange_company_id(self, cr, uid, ids, company_id, part_id, ctype, invoice_line, currency_id):
262
This is a method to redefine the journal_id domain with the current_instance taken into account
264
res = super(account_invoice, self).onchange_company_id(cr, uid, ids, company_id, part_id, ctype, invoice_line, currency_id)
265
if company_id and ctype:
266
res.setdefault('domain', {})
267
res.setdefault('value', {})
269
'out_invoice': 'sale',
270
'in_invoice': 'purchase',
271
'out_refund': 'sale_refund',
272
'in_refund': 'purchase_refund',
274
journal_ids = self.pool.get('account.journal').search(cr, uid, [
275
('company_id','=',company_id), ('type', '=', ass.get(ctype, 'purchase')), ('is_current_instance', '=', True)
278
raise osv.except_osv(_('Configuration Error !'), _('Can\'t find any account journal of %s type for this company.\n\nYou can create one in the menu: \nConfiguration\Financial Accounting\Accounts\Journals.') % (ass.get(type, 'purchase'), ))
279
res['value']['journal_id'] = journal_ids[0]
280
# TODO: it's very bad to set a domain by onchange method, no time to rewrite UniField !
281
res['domain']['journal_id'] = [('id', 'in', journal_ids)]
284
def onchange_partner_id(self, cr, uid, ids, ctype, partner_id,\
285
date_invoice=False, payment_term=False, partner_bank_id=False, company_id=False, is_inkind_donation=False, is_intermission=False, is_debit_note=False, is_direct_invoice=False):
287
Update fake_account_id field regarding account_id result.
288
Get default donation account for Donation invoices.
289
Get default intermission account for Intermission Voucher IN/OUT invoices.
290
Get default currency from partner if this one is linked to a pricelist.
291
Ticket utp917 - added code to avoid currency cd change if a direct invoice
293
res = super(account_invoice, self).onchange_partner_id(cr, uid, ids, ctype, partner_id, date_invoice, payment_term, partner_bank_id, company_id)
294
if is_inkind_donation and partner_id:
295
partner = self.pool.get('res.partner').browse(cr, uid, partner_id)
296
account_id = partner and partner.donation_payable_account and partner.donation_payable_account.id or False
297
res['value']['account_id'] = account_id
298
if is_intermission and partner_id:
299
intermission_default_account = self.pool.get('res.users').browse(cr, uid, uid).company_id.intermission_default_counterpart
300
account_id = intermission_default_account and intermission_default_account.id or False
302
raise osv.except_osv(_('Error'), _('Please configure a default intermission account in Company configuration.'))
303
res['value']['account_id'] = account_id
304
if res.get('value', False) and 'account_id' in res['value']:
305
res['value'].update({'fake_account_id': res['value'].get('account_id')})
306
if partner_id and ctype:
307
p = self.pool.get('res.partner').browse(cr, uid, partner_id)
308
ai_direct_invoice = False
310
ai = self.browse(cr, uid, ids)[0]
311
ai_direct_invoice = ai.is_direct_invoice
314
if ctype in ['in_invoice', 'out_refund'] and p.property_product_pricelist_purchase:
315
c_id = p.property_product_pricelist_purchase.currency_id.id
316
elif ctype in ['out_invoice', 'in_refund'] and p.property_product_pricelist:
317
c_id = p.property_product_pricelist.currency_id.id
318
# UFTP-121: regarding UTP-917, we have to change currency when changing partner, but not for direct invoices
319
if c_id and (not is_direct_invoice and not ai_direct_invoice):
320
if not res.get('value', False):
321
res['value'] = {'currency_id': c_id}
323
res['value'].update({'currency_id': c_id})
324
# UFTP-168: If debit note, set account to False value
326
res['value'].update({'account_id': False, 'fake_account_id': False})
329
def _check_document_date(self, cr, uid, ids):
331
Check that document's date is done BEFORE posting date
333
if isinstance(ids, (int, long)):
335
for i in self.browse(cr, uid, ids):
336
self.pool.get('finance.tools').check_document_date(cr, uid,
337
i.document_date, i.date_invoice)
340
def _check_invoice_merged_lines(self, cr, uid, ids, context=None):
343
merge of lines by account break lines descriptions (required field)
344
=> before next workflow stage from draft (validate, split)
345
check that user has entered description on each line
346
(force user to enter a custom description)
348
for self_br in self.browse(cr, uid, ids, context=context):
349
if self_br.is_merged_by_account:
350
if not all([ l.name for l in self_br.invoice_line ]):
351
raise osv.except_osv(
353
_('Please enter a description in each merged line' \
354
' before invoice validation')
357
def _refund_cleanup_lines(self, cr, uid, lines):
359
Remove useless fields
362
if line.get('move_lines',False):
363
del line['move_lines']
364
if line.get('import_invoice_id',False):
365
del line['import_invoice_id']
366
res = super(account_invoice, self)._refund_cleanup_lines(cr, uid, lines)
369
def check_po_link(self, cr, uid, ids, context=None):
371
Check that invoice (only supplier invoices) has no link with a PO. This is because of commitments presence.
375
if isinstance(ids, (int, long)):
377
purchase_obj = self.pool.get('purchase.order')
378
commitment_obj = self.pool.get('account.commitment')
379
for inv in self.read(cr, uid, ids, ['purchase_ids', 'type', 'is_inkind_donation', 'is_debit_note', 'state']):
380
if inv.get('type', '') == 'in_invoice' and not inv.get('is_inkind_donation', False) and not inv.get('is_debit_note', False):
381
if inv.get('purchase_ids', False):
382
# UTP-808: Allow draft invoice deletion. If commitment exists, set them as done.
383
if inv.get('state', '') != 'draft':
384
raise osv.except_osv(_('Warning'), _('You cannot cancel or delete a supplier invoice linked to a PO.'))
386
for purchase in purchase_obj.browse(cr, uid, inv.get('purchase_ids', []), context=context):
387
commitment_obj.action_commitment_done(cr, uid, [x.id for x in purchase.commitment_ids])
390
def _hook_period_id(self, cr, uid, inv, context=None):
392
Give matches period that are not draft and not HQ-closed from given date.
393
Do not use special periods as period 13, 14 and 15.
400
# NB: there is some period state. So we define that we choose only open period (so not draft and not done)
401
res = self.pool.get('account.period').search(cr, uid, [('date_start','<=',inv.date_invoice or strftime('%Y-%m-%d')),
402
('date_stop','>=',inv.date_invoice or strftime('%Y-%m-%d')), ('state', 'not in', ['created', 'done']),
403
('company_id', '=', inv.company_id.id), ('special', '=', False)], context=context, order="date_start ASC, name ASC")
406
def __hook_lines_before_pay_and_reconcile(self, cr, uid, lines):
408
Add document date to account_move_line before pay and reconcile
411
if line[2] and 'date' in line[2] and not line[2].get('document_date', False):
412
line[2].update({'document_date': line[2].get('date')})
415
def fields_view_get(self, cr, uid, view_id=None, view_type=False, context=None, toolbar=False, submenu=False):
417
Rename Supplier/Customer to "Donor" if view_type == tree
421
res = super(account_invoice, self).fields_view_get(cr, uid, view_id, view_type, context=context, toolbar=toolbar, submenu=submenu)
422
if view_type == 'tree' and (context.get('journal_type', False) == 'inkind' or context.get('journal_type', False) == 'intermission'):
423
doc = etree.XML(res['arch'])
424
nodes = doc.xpath("//field[@name='partner_id']")
426
if context.get('journal_type') == 'intermission':
429
node.set('string', name)
430
res['arch'] = etree.tostring(doc)
431
elif view_type in ('tree', 'search') and context.get('type') in ['out_invoice', 'out_refund']:
432
doc = etree.XML(res['arch'])
433
nodes = doc.xpath("//field[@name='supplier_reference']")
435
node.getparent().remove(node)
436
res['arch'] = etree.tostring(doc)
439
def default_get(self, cr, uid, fields, context=None):
441
Fill in fake account and fake currency for intermission invoice (in context).
443
defaults = super(account_invoice, self).default_get(cr, uid, fields, context=context)
444
if context and context.get('is_intermission', False):
445
intermission_type = context.get('intermission_type', False)
446
if intermission_type in ('in', 'out'):
447
# UF-2270: manual intermission (in or out)
450
user = self.pool.get('res.users').browse(cr, uid, [uid], context=context)
451
if user and user[0] and user[0].company_id:
452
# get company default currency
453
if user[0].company_id.currency_id:
454
defaults['fake_currency_id'] = user[0].company_id.currency_id.id
455
defaults['currency_id'] = defaults['fake_currency_id']
456
# get 'intermission counter part' account
457
if user[0].company_id.intermission_default_counterpart:
458
defaults['fake_account_id'] = user[0].company_id.intermission_default_counterpart.id
459
defaults['account_id'] = defaults['fake_account_id']
461
raise osv.except_osv("Error","Company Intermission Counterpart Account must be set")
462
# 'INT' intermission journal
463
int_journal_id = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'intermission')], context=context)
465
if isinstance(int_journal_id, (int, long)):
466
int_journal_id = [int_journal_id]
467
defaults['fake_journal_id'] = int_journal_id[0]
468
defaults['journal_id'] = defaults['fake_journal_id']
471
def copy(self, cr, uid, inv_id, default=None, context=None):
473
Delete period_id from invoice.
474
Check context for splitting invoice.
475
Reset register_line_ids.
484
'purchase_ids': False, # UFTP-24 do not copy linked POs
485
'purchase_list': False, # UFTP-24 do not copy linked: reset of potential purchase list flag (from a PO direct purchase)
486
'partner_move_line': False,
487
'imported_invoices': False
489
# Reset register_line_ids if not given in default
490
if 'register_line_ids' not in default:
491
default['register_line_ids'] = []
492
# US-267: Reset st_lines if not given in default, otherwise a new line in Reg will be added
493
if 'st_lines' not in default:
494
default['st_lines'] = []
496
new_id = super(account_invoice, self).copy(cr, uid, inv_id, default, context)
497
# Case where you split an invoice
498
if 'split_it' in context:
499
purchase_obj = self.pool.get('purchase.order')
500
sale_obj = self.pool.get('sale.order')
502
# attach new invoice to PO
503
purchase_ids = purchase_obj.search(cr, uid, [('invoice_ids', 'in', [inv_id])], context=context)
505
purchase_obj.write(cr, uid, purchase_ids, {'invoice_ids': [(4, new_id)]}, context=context)
507
# attach new invoice to SO
508
sale_ids = sale_obj.search(cr, uid, [('invoice_ids', 'in', [inv_id])], context=context)
510
sale_obj.write(cr, uid, sale_ids, {'invoice_ids': [(4, new_id)]}, context=context)
513
def create(self, cr, uid, vals, context=None):
515
Filled in 'from_yml_test' to True if we come from tests
519
if 'document_date' in vals and 'date_invoice' in vals:
520
self.pool.get('finance.tools').check_document_date(cr, uid,
521
vals['document_date'], vals['date_invoice'], context=context)
523
# Create a sequence for this new invoice
524
res_seq = self.create_sequence(cr, uid, vals, context)
525
vals.update({'sequence_id': res_seq,})
527
# UTP-317 # Check that no inactive partner have been used to create this invoice
528
if 'partner_id' in vals:
529
partner_id = vals.get('partner_id')
530
if isinstance(partner_id, (str)):
531
partner_id = int(partner_id)
532
partner = self.pool.get('res.partner').browse(cr, uid, [partner_id])
533
if partner and partner[0] and not partner[0].active:
534
raise osv.except_osv(_('Warning'), _("Partner '%s' is not active.") % (partner[0] and partner[0].name or '',))
536
return super(account_invoice, self).create(cr, uid, vals, context)
538
def write(self, cr, uid, ids, vals, context=None):
544
if isinstance(ids, (int, long)):
547
# US_286: Forbit possibility to add include price tax
548
# in bottom left corner
549
if 'tax_line' in vals:
550
tax_obj = self.pool.get('account.tax')
551
for tax_line in vals['tax_line']:
553
if 'account_tax_id' in tax_line[2]:
554
args = [('price_include', '=', '1'),
555
('id', '=', tax_line[2]['account_tax_id'])]
556
tax_ids = tax_obj.search(cr, uid, args, limit=1,
557
order='NO_ORDER', context=context)
559
raise osv.except_osv(_('Error'),
560
_('Tax included in price can not be tied to the whole invoice.'))
562
res = super(account_invoice, self).write(cr, uid, ids, vals, context=context)
563
self._check_document_date(cr, uid, ids)
566
def unlink(self, cr, uid, ids, context=None):
568
Delete register line if this invoice is a Direct Invoice.
569
Don't delete an invoice that is linked to a PO. This is only for supplier invoices.
573
if isinstance(ids, (int, long)):
575
# Check register lines
576
for inv in self.browse(cr, uid, ids):
577
if inv.is_direct_invoice and inv.register_line_ids:
578
if not context.get('from_register', False):
579
self.pool.get('account.bank.statement.line').unlink(cr, uid, [x.id for x in inv.register_line_ids], {'from_direct_invoice': True})
581
self.check_po_link(cr, uid, ids)
582
return super(account_invoice, self).unlink(cr, uid, ids, context)
584
86
def create_sequence(self, cr, uid, vals, context=None):
586
88
Create new entry sequence for every new invoice
606
108
return seq_pool.create(cr, uid, seq)
608
def log(self, cr, uid, inv_id, message, secondary=False, context=None):
610
Change first "Invoice" word from message into "Debit Note" if this invoice is a debit note.
611
Change it to "In-kind donation" if this invoice is an In-kind donation.
615
local_ctx = context.copy()
616
# Prepare some values
617
# Search donation view and return it
619
# try / except for runbot
620
debit_res = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account_override', 'view_debit_note_form')
621
inkind_res = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account_override', 'view_inkind_donation_form')
622
intermission_res = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account_override', 'view_intermission_form')
623
supplier_invoice_res = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account', 'invoice_supplier_form')
624
customer_invoice_res = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account', 'invoice_form')
625
supplier_direct_invoice_res = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'register_accounting', 'direct_supplier_invoice_form')
626
except ValueError, e:
627
return super(account_invoice, self).log(cr, uid, inv_id, message, secondary, context)
628
debit_view_id = debit_res and debit_res[1] or False
629
debit_note_ctx = {'view_id': debit_view_id, 'type':'out_invoice', 'journal_type': 'sale', 'is_debit_note': True}
630
# Search donation view and return it
631
inkind_view_id = inkind_res and inkind_res[1] or False
632
inkind_ctx = {'view_id': inkind_view_id, 'type':'in_invoice', 'journal_type': 'inkind', 'is_inkind_donation': True}
633
# Search intermission view
634
intermission_view_id = intermission_res and intermission_res[1] or False
635
intermission_ctx = {'view_id': intermission_view_id, 'journal_type': 'intermission', 'is_intermission': True}
636
customer_view_id = customer_invoice_res[1] or False
637
customer_ctx = {'view_id': customer_view_id, 'type': 'out_invoice', 'journal_type': 'sale'}
638
message_changed = False
639
pattern = re.compile('^(Invoice)')
640
for el in [('is_debit_note', 'Debit Note', debit_note_ctx), ('is_inkind_donation', 'In-kind Donation', inkind_ctx), ('is_intermission', 'Intermission Voucher', intermission_ctx)]:
641
if self.read(cr, uid, inv_id, [el[0]]).get(el[0], False) is True:
642
m = re.match(pattern, message)
644
message = re.sub(pattern, el[1], message, 1)
645
message_changed = True
646
local_ctx.update(el[2])
647
# UF-1112: Give all customer invoices a name as "Stock Transfer Voucher".
648
if not message_changed and self.read(cr, uid, inv_id, ['type']).get('type', False) == 'out_invoice':
649
message = re.sub(pattern, 'Stock Transfer Voucher', message, 1)
651
local_ctx.update(customer_ctx)
652
# UF-1307: for supplier invoice log (from the incoming shipment), the context was not
653
# filled with all the information; this leaded to having a "Sale" journal in the supplier
654
# invoice if it was saved after coming from this link. Here's the fix.
655
if local_ctx.get('type', False) == 'in_invoice':
656
if not local_ctx.get('journal_type', False):
657
supplier_view_id = supplier_invoice_res and supplier_invoice_res[1] or False
658
local_ctx.update({'journal_type': 'purchase',
659
'view_id': supplier_view_id})
660
elif local_ctx.get('direct_invoice_view', False): # UFTP-166: The wrong context saved in log
661
supplier_view_id = supplier_direct_invoice_res and supplier_direct_invoice_res[1] or False
662
local_ctx = {'journal_type': 'purchase',
663
'view_id': supplier_view_id}
664
return super(account_invoice, self).log(cr, uid, inv_id, message, secondary, local_ctx)
666
def invoice_open(self, cr, uid, ids, context=None):
668
No longer fills the date automatically, but requires it to be set
673
self._check_invoice_merged_lines(cr, uid, ids, context=context)
675
# Prepare workflow object
676
wf_service = netsvc.LocalService("workflow")
677
for inv in self.browse(cr, uid, ids):
679
curr_date = strftime('%Y-%m-%d')
680
if not inv.date_invoice and not inv.document_date:
681
values.update({'date': curr_date, 'document_date': curr_date, 'state': 'date'})
682
elif not inv.date_invoice:
683
values.update({'date': curr_date, 'document_date': inv.document_date, 'state': 'date'})
684
elif not inv.document_date:
685
values.update({'date': inv.date_invoice, 'document_date': curr_date, 'state': 'date'})
686
if inv.type in ('in_invoice', 'in_refund') and abs(inv.check_total - inv.amount_total) >= (inv.currency_id.rounding/2.0):
687
state = values and 'both' or 'amount'
688
values.update({'check_total': inv.check_total , 'amount_total': inv.amount_total, 'state': state})
690
values['invoice_id'] = inv.id
691
wiz_id = self.pool.get('wizard.invoice.date').create(cr, uid, values, context)
693
'name': "Missing Information",
694
'type': 'ir.actions.act_window',
695
'res_model': 'wizard.invoice.date',
702
wf_service.trg_validate(uid, 'account.invoice', inv.id, 'invoice_open', cr)
705
def action_reconcile_imported_invoice(self, cr, uid, ids, context=None):
707
Reconcile each imported invoice with its attached invoice line
110
def create(self, cr, uid, vals, context=None):
112
Filled in 'from_yml_test' to True if we come from tests
116
if context.get('update_mode') in ['init', 'update']:
117
logging.getLogger('init').info('INV: set from yml test to True')
118
vals['from_yml_test'] = True
119
# Create a sequence for this new invoice
120
res_seq = self.create_sequence(cr, uid, vals, context)
121
vals.update({'sequence_id': res_seq,})
122
return super(account_invoice, self).create(cr, uid, vals, context)
124
def _check_document_date(self, cr, uid, ids):
126
Check that document's date is done BEFORE posting date
710
128
if isinstance(ids, (int, long)):
712
# browse all given invoices
713
for inv in self.browse(cr, uid, ids):
714
for invl in inv.invoice_line:
715
if not invl.import_invoice_id:
717
imported_invoice = invl.import_invoice_id
718
# reconcile partner line from import invoice with this invoice line attached move line
719
import_invoice_partner_move_lines = self.pool.get('account.move.line').search(cr, uid, [('invoice_partner_link', '=', imported_invoice.id)])
720
invl_move_lines = [x.id or None for x in invl.move_lines]
721
rec = self.pool.get('account.move.line').reconcile_partial(cr, uid, [import_invoice_partner_move_lines[0], invl_move_lines[0]], 'auto', context=context)
726
def action_reconcile_direct_invoice(self, cr, uid, inv, context=None):
728
Reconcile move line if invoice is a Direct Invoice
729
NB: In order to define that an invoice is a Direct Invoice, we need to have register_line_ids not null
731
# Verify that this invoice is linked to a register line and have a move
734
if inv.move_id and inv.register_line_ids:
735
ml_obj = self.pool.get('account.move.line')
736
# First search move line that becomes from invoice
737
res_ml_ids = ml_obj.search(cr, uid, [
738
('move_id', '=', inv.move_id.id),
739
('account_id', '=', inv.account_id.id),
740
('invoice_line_id', '=', False), # US-254: do not seek invoice line's JIs (if same account as header)
742
if len(res_ml_ids) > 1:
743
raise osv.except_osv(_('Error'), _('More than one journal items found for this invoice.'))
744
invoice_move_line_id = res_ml_ids[0]
745
# Then search move line that corresponds to the register line
746
reg_line = inv.register_line_ids[0]
747
reg_ml_ids = ml_obj.search(cr, uid, [('move_id', '=', reg_line.move_ids[0].id), ('account_id', '=', reg_line.account_id.id)])
748
if len(reg_ml_ids) > 1:
749
raise osv.except_osv(_('Error'), _('More than one journal items found for this register line.'))
750
register_move_line_id = reg_ml_ids[0]
751
# Finally do reconciliation
752
ml_obj.reconcile_partial(cr, uid, [invoice_move_line_id, register_move_line_id])
755
def action_cancel(self, cr, uid, ids, *args):
757
Reverse move if this object is a In-kind Donation. Otherwise do normal job: cancellation.
758
Don't delete an invoice that is linked to a PO. This is only for supplier invoices.
761
130
for i in self.browse(cr, uid, ids):
762
if i.is_inkind_donation:
763
move_id = i.move_id.id
764
tmp_res = self.pool.get('account.move').reverse(cr, uid, [move_id], strftime('%Y-%m-%d'))
765
# If success change invoice to cancel and detach move_id
767
# Change invoice state
768
self.write(cr, uid, [i.id], {'state': 'cancel', 'move_id':False})
770
to_cancel.append(i.id)
772
self.check_po_link(cr, uid, ids)
773
return super(account_invoice, self).action_cancel(cr, uid, to_cancel, args)
131
if i.document_date and i.date_invoice and i.date_invoice < i.document_date:
132
raise osv.except_osv(_('Error'), _('Posting date should be later than Document Date.'))
775
135
def action_date_assign(self, cr, uid, ids, *args):
777
137
Check Document date.
138
Add it if we come from a YAML test.
779
# Prepare some values
780
period_obj = self.pool.get('account.period')
781
140
# Default behaviour to add date
782
141
res = super(account_invoice, self).action_date_assign(cr, uid, ids, args)
783
142
# Process invoices
807
if isinstance(ids, (int, long)):
809
161
if not self.action_date_assign(cr, uid, ids, context, args):
811
163
if not self.action_move_create(cr, uid, ids, context, args):
813
165
if not self.action_number(cr, uid, ids, context):
815
if not self.action_reconcile_imported_invoice(cr, uid, ids, context):
819
def line_get_convert(self, cr, uid, x, part, date, context=None):
821
Add these field into invoice line:
169
def _hook_period_id(self, cr, uid, inv, context=None):
171
Give matches period that are not draft and not HQ-closed from given date
826
res = super(account_invoice, self).line_get_convert(cr, uid, x, part, date, context)
827
res.update({'invoice_line_id': x.get('invoice_line_id', False)})
178
# NB: there is some period state. So we define that we choose only open period (so not draft and not done)
179
res = self.pool.get('account.period').search(cr, uid, [('date_start','<=',inv.date_invoice or strftime('%Y-%m-%d')),
180
('date_stop','>=',inv.date_invoice or strftime('%Y-%m-%d')), ('state', 'not in', ['created', 'done']),
181
('company_id', '=', inv.company_id.id)], context=context, order="date_start ASC, name ASC")
830
184
def finalize_invoice_move_lines(self, cr, uid, inv, line):
832
186
Hook that changes move line data before write them.
833
Add a link between partner move line and invoice.
834
187
Add invoice document date to data.
836
def is_partner_line(dico):
837
if isinstance(dico, dict):
839
# In case where no amount_currency filled in, then take debit - credit for amount comparison
840
amount = dico.get('amount_currency', False) or (dico.get('debit', 0.0) - dico.get('credit', 0.0))
841
if amount == inv.amount_total and dico.get('partner_id', False) == inv.partner_id.id:
189
res = super(account_invoice, self).finalize_invoice_move_lines(cr, uid, inv, line)
847
193
el[2].update({'document_date': inv.document_date})
848
if el[2] and is_partner_line(el[2]):
849
el[2].update({'invoice_partner_link': inv.id})
850
new_line.append((el[0], el[1], el[2]))
853
return super(account_invoice, self).finalize_invoice_move_lines(cr, uid, inv, new_line)
855
def button_debit_note_import_invoice(self, cr, uid, ids, context=None):
857
Launch wizard that permits to import invoice on a debit note
196
def copy(self, cr, uid, id, default={}, context=None):
198
Delete period_id from invoice
202
default.update({'period_id': False,})
203
return super(account_invoice, self).copy(cr, uid, id, default, context)
205
def __hook_lines_before_pay_and_reconcile(self, cr, uid, lines):
207
Add document date to account_move_line before pay and reconcile
210
if line[2] and 'date' in line[2] and not line[2].get('document_date', False):
211
line[2].update({'document_date': line[2].get('date')})
214
def write(self, cr, uid, ids, vals, context=None):
862
220
if isinstance(ids, (int, long)):
864
# Browse all given invoices
865
for inv in self.browse(cr, uid, ids):
866
if inv.type != 'out_invoice' or inv.is_debit_note == False:
867
raise osv.except_osv(_('Error'), _('You can only do import invoice on a Debit Note!'))
868
w_id = self.pool.get('debit.note.import.invoice').create(cr, uid, {'invoice_id': inv.id, 'currency_id': inv.currency_id.id,
869
'partner_id': inv.partner_id.id}, context=context)
875
'type': 'ir.actions.act_window',
876
'res_model': 'debit.note.import.invoice',
877
'name': 'Import invoice',
885
def button_split_invoice(self, cr, uid, ids, context=None):
887
Launch the split invoice wizard to split an invoice in two elements.
892
if isinstance(ids, (int, long)):
894
self._check_invoice_merged_lines(cr, uid, ids, context=context)
897
wiz_lines_obj = self.pool.get('wizard.split.invoice.lines')
898
inv_lines_obj = self.pool.get('account.invoice.line')
900
wizard_id = self.pool.get('wizard.split.invoice').create(cr, uid, {'invoice_id': ids[0]}, context=context)
901
# Add invoices_lines into the wizard
902
invoice_line_ids = self.pool.get('account.invoice.line').search(cr, uid, [('invoice_id', '=', ids[0])], context=context)
903
# Some other verifications
904
if not len(invoice_line_ids):
905
raise osv.except_osv(_('Error'), _('No invoice line in this invoice or not enough elements'))
906
for invl in inv_lines_obj.browse(cr, uid, invoice_line_ids, context=context):
907
wiz_lines_obj.create(cr, uid, {'invoice_line_id': invl.id, 'product_id': invl.product_id.id, 'quantity': invl.quantity,
908
'price_unit': invl.price_unit, 'description': invl.name, 'wizard_id': wizard_id}, context=context)
912
'name': "Split Invoice",
913
'type': 'ir.actions.act_window',
914
'res_model': 'wizard.split.invoice',
916
'view_mode': 'form,tree',
918
'res_id': [wizard_id],
923
'wizard_id': wizard_id,
928
def button_donation_certificate(self, cr, uid, ids, context=None):
930
Open a view containing a list of all donation certificates linked to the given invoice.
932
for inv in self.browse(cr, uid, ids):
933
pick_id = inv.picking_id and inv.picking_id.id or ''
934
domain = "[('res_model', '=', 'stock.picking'), ('res_id', '=', " + str(pick_id) + "), ('description', '=', 'Certificate of Donation')]"
935
view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account_override', 'view_attachment_tree_2')
936
view_id = view_id and view_id[1] or False
937
search_view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account_override', 'view_attachment_search_2')
938
search_view_id = search_view_id and search_view_id[1] or False
940
'name': "Certificate of Donation",
941
'type': 'ir.actions.act_window',
942
'res_model': 'ir.attachment',
944
'view_mode': 'tree,form',
945
'view_id': [view_id],
946
'search_view_id': search_view_id,
953
def button_dummy_compute_total(self, cr, uid, ids, context=None):
956
def button_merge_lines(self, cr, uid, ids, context=None):
957
# US-357 merge lines (by account) button for draft SIs
959
if not inv_br.can_merge_lines:
960
raise osv.except_osv(_('Error'),
961
_("Invoice not eligible for lines merging"))
963
account_iterations = {}
964
for l in inv_br.invoice_line:
965
account_iterations[l.account_id.id] = \
966
account_iterations.setdefault(l.account_id.id, 0) + 1
969
if account_iterations:
970
for a in account_iterations:
971
if account_iterations[a] > 1:
976
raise osv.except_osv(_('Error'),
977
_("Invoice has no line to merge by account"))
979
def compute_merge(inv_br):
982
- A: lines vals by line number
983
- B: and list of inv id to keep (1 line by account (not merged))
984
:rtype : [dict, list]
987
- no impact on 'import_invoice_id', 'is_corrected' as the
988
invoice is draft so not imported, and no accounting entries
989
- for order_line_id and sale_order_line_id these m2o are used
990
for AD at line level but when merging we keep only AD from header
994
'_index_': index, # internal merged line index
997
'company_id': inv_br.company_id.id,
999
'invoice_id': inv_br.id,
1000
'invoice_line_tax_id': None, # m2m (None to distinguished False)
1002
'partner_id': inv_br.partner_id.id,
1007
by_account_vals = {} # key: account_id
1008
for l in inv_br.invoice_line:
1009
# get current merge vals for account or create new
1010
if l.account_id.id in by_account_vals:
1011
vals = by_account_vals[l.account_id.id]
1013
# new account to merge
1014
vals = vals_template.copy()
1017
'account_id': l.account_id.id,
1022
vals['price_unit'] += l.price_subtotal # qty 1 and price
1023
if vals['invoice_line_tax_id'] is None:
1024
vals['invoice_line_tax_id'] = l.invoice_line_tax_id \
1025
and [ t.id for t in l.invoice_line_tax_id ] or False
1027
# get rid of the product tax line if <> between merged lines
1028
if vals['invoice_line_tax_id'] is None:
1029
# first tax line browsed for the account
1030
if l.invoice_line_tax_id:
1031
vals['invoice_line_tax_id'] = [
1032
t.id for t in l.invoice_line_tax_id ]
1034
vals['invoice_line_tax_id'] = False
1035
elif vals['invoice_line_tax_id'] and l.invoice_line_tax_id:
1036
# track <> tax lines, if the case abort tax(es) in merge
1037
tax_ids = [ t.id for t in l.invoice_line_tax_id ]
1038
if cmp(vals['invoice_line_tax_id'], tax_ids) != 0:
1039
vals['invoice_line_tax_id'] = False
1041
# no tax(es) for this line, abort tax(es) in merge
1042
vals['invoice_line_tax_id'] = False
1045
by_account_vals[l.account_id.id] = vals
1047
# internal merged lines ids
1048
if not '_ids_' in by_account_vals[l.account_id.id]:
1049
by_account_vals[l.account_id.id]['_ids_'] = []
1050
by_account_vals[l.account_id.id]['_ids_'].append(l.id)
1054
for a in by_account_vals:
1055
if len(by_account_vals[a]['_ids_']) > 1:
1056
# more than 1 inv line by account
1057
index = by_account_vals[a]['_index_']
1058
del by_account_vals[a]['_index_']
1059
del by_account_vals[a]['_ids_']
1060
res[0][index] = by_account_vals[a]
1062
res[1].append(by_account_vals[a]['_ids_'][0])
1065
def delete_lines(inv_br, skip_ids):
1068
line_to_del_ids = []
1070
for l in inv_br.invoice_line:
1071
if l.id in skip_ids:
1072
continue # line not to del (1 by account)
1074
if l.analytic_distribution_id \
1075
and not l.analytic_distribution_id.id in ad_to_del_ids:
1076
ad_to_del_ids.append(l.analytic_distribution_id.id)
1077
line_to_del_ids.append(l.id)
1081
ad_obj.unlink(cr, uid, ad_to_del_ids, context=context)
1085
ail_obj.unlink(cr, uid, line_to_del_ids, context=context)
1087
def do_merge(inv_br, lines_vals, not_merged_ids):
1089
:param lines_vals: lines vals in order
1090
:type lines_vals: dict
1092
# the invoice is reviewed with merge lines
1093
# => reset the line number sequence from 1
1094
if inv_br.sequence_id:
1095
inv_br.sequence_id.write({'number_next': 1}, context=context)
1097
# create merge lines
1098
for ln in sorted(lines_vals.keys()):
1099
vals = lines_vals[ln]
1101
# post encode tax m2m
1102
vals['invoice_line_tax_id'] = vals['invoice_line_tax_id'] \
1103
and [(6, 0, vals['invoice_line_tax_id'])] or False
1106
if not self.pool.get('account.invoice.line').create(cr, uid,
1107
vals, context=context):
1110
# recompute seq number for not merged lines
1111
ail_obj = self.pool.get('account.invoice.line')
1113
for lid in not_merged_ids:
1114
ln = inv_br.sequence_id.get_id(code_or_id='id')
1115
ail_obj.write(cr, uid, [lid], {
1119
def merge_invoice(inv_br):
1121
merge_res = compute_merge(inv_br)
1122
delete_lines(inv_br, merge_res[1])
1123
do_merge(inv_br, merge_res[0], merge_res[1])
1126
inv_br.write({'is_merged_by_account': True}, context=context)
1128
# recompute taxes (reset not manual ones)
1129
self.button_reset_taxes(cr, uid, [inv_br.id], context=context)
1131
def post_merge(inv_br):
1133
# update check total for accurate check amount at validation
1135
inv_br.amount_total or inv_br.check_amount or 0.,
1141
if isinstance(ids, (int, long, )):
1144
ail_obj = self.pool.get('account.invoice.line')
1145
ad_obj = self.pool.get('analytic.distribution')
1148
for inv_br in self.browse(cr, uid, ids, context=context):
1149
merge_invoice(inv_br)
1151
# post processing (reload invoices)
1152
for inv_br in self.browse(cr, uid, ids, context=context):
222
res = super(account_invoice, self).write(cr, uid, ids, vals, context=context)
223
self._check_document_date(cr, uid, ids)
1157
226
account_invoice()
1270
273
for il in self.browse(cr, uid, ids):
1271
274
if not il.line_number and il.invoice_id.sequence_id:
1272
275
sequence = il.invoice_id.sequence_id
1273
il_number = sequence.get_id(code_or_id='id', context=context)
276
il_number = sequence.get_id(test='id', context=context)
1274
277
vals.update({'line_number': il_number})
1275
res = super(account_invoice_line, self).write(cr, uid, ids, vals, context)
1276
for invl in self.browse(cr, uid, ids):
1277
if invl.invoice_id and invl.invoice_id.is_direct_invoice and invl.invoice_id.state == 'draft':
1279
for l in invl.invoice_id.invoice_line:
1280
amount += l.price_subtotal
1281
self.pool.get('account.invoice').write(cr, uid, [invl.invoice_id.id], {'check_total': amount}, context)
1282
self.pool.get('account.bank.statement.line').write(cr, uid, [x.id for x in invl.invoice_id.register_line_ids], {'amount': -1 * amount}, context)
1285
def copy(self, cr, uid, inv_id, default=None, context=None):
1287
Check context to see if we come from a split. If yes, we create the link between invoice and PO/FO.
1294
new_id = super(account_invoice_line, self).copy(cr, uid, inv_id, default, context)
1296
if 'split_it' in context:
1297
purchase_lines_obj = self.pool.get('purchase.order.line')
1298
sale_lines_obj = self.pool.get('sale.order.line')
1300
if purchase_lines_obj:
1301
purchase_line_ids = purchase_lines_obj.search(cr, uid,
1302
[('invoice_lines', 'in', [inv_id])], order='NO_ORDER')
1303
if purchase_line_ids:
1304
purchase_lines_obj.write(cr, uid, purchase_line_ids, {'invoice_lines': [(4, new_id)]})
1307
sale_lines_ids = sale_lines_obj.search(cr, uid,
1308
[('invoice_lines', 'in', [inv_id])], order='NO_ORDER')
1310
sale_lines_obj.write(cr, uid, sale_lines_ids, {'invoice_lines': [(4, new_id)]})
1314
def copy_data(self, cr, uid, inv_id, default=None, context=None):
1316
Copy an invoice line without its move lines
1320
default.update({'move_lines': False,})
1321
return super(account_invoice_line, self).copy_data(cr, uid, inv_id, default, context)
1323
def unlink(self, cr, uid, ids, context=None):
1325
If invoice is a Direct Invoice and is in draft state:
1326
- compute total amount (check_total field)
1327
- write total to the register line
1331
if isinstance(ids, (int, long)):
1333
# Fetch all invoice_id to check
1334
direct_invoice_ids = []
1335
abst_obj = self.pool.get('account.bank.statement.line')
1336
for invl in self.browse(cr, uid, ids):
1337
if invl.invoice_id and invl.invoice_id.is_direct_invoice and invl.invoice_id.state == 'draft':
1338
direct_invoice_ids.append(invl.invoice_id.id)
1339
# find account_bank_statement_lines and used this to delete the account_moves and associated records
1340
absl_ids = abst_obj.search(cr, uid,
1341
[('invoice_id','=',invl.invoice_id.id)],
1344
abst_obj.unlink_moves(cr, uid, absl_ids, context)
1346
res = super(account_invoice_line, self).unlink(cr, uid, ids, context)
1347
# See all direct invoice
1348
for inv in self.pool.get('account.invoice').browse(cr, uid, direct_invoice_ids):
1350
for l in inv.invoice_line:
1351
amount += l.price_subtotal
1352
self.pool.get('account.invoice').write(cr, uid, [inv.id], {'check_total': amount}, context)
1353
self.pool.get('account.bank.statement.line').write(cr, uid, [x.id for x in inv.register_line_ids], {'amount': -1 * amount}, context)
1356
def move_line_get_item(self, cr, uid, line, context=None):
1358
Add a link between move line and its invoice line
1363
# update default dict with invoice line ID
1364
res = super(account_invoice_line, self).move_line_get_item(cr, uid, line, context=context)
1365
res.update({'invoice_line_id': line.id})
1368
def button_open_analytic_lines(self, cr, uid, ids, context=None):
1370
Return analytic lines linked to this invoice line.
1371
First we takes all journal items that are linked to this invoice line.
1372
Then for all journal items, we take all analytic journal items.
1373
Finally we display the result for "button_open_analytic_corrections" of analytic lines
1378
# Prepare some values
1380
# Browse give invoice lines
1381
for il in self.browse(cr, uid, ids, context=context):
1383
for ml in il.move_lines:
1384
if ml.analytic_lines:
1385
al_ids += [x.id for x in ml.analytic_lines]
1386
return self.pool.get('account.analytic.line').button_open_analytic_corrections(cr, uid, al_ids, context=context)
278
return super(account_invoice_line, self).write(cr, uid, ids, vals, context)
1388
280
account_invoice_line()
1391
class res_partner(osv.osv):
1392
_description='Partner'
1393
_inherit = "res.partner"
1395
def _get_fake(self, cr, uid, ids, name, args, context=None):
1399
if isinstance(ids, (int, long)):
1405
def _get_search_by_invoice_type(self, cr, uid, obj, name, args,
1413
msg = _("Domain %s not suported") % (str(args), )
1414
raise osv.except_osv(_('Error'), msg)
1415
if args[0][1] != '=':
1416
msg = _("Operator '%s' not suported") % (args[0][1], )
1417
raise osv.except_osv(_('Error'), msg)
1421
invoice_type = context.get('type', False)
1423
if invoice_type in ('in_invoice', 'in_refund', ):
1424
# in invoices: only supplier partner
1425
res = [('supplier', '=', True)]
1426
elif invoice_type in ('out_invoice', 'out_refund', ):
1427
# out invoices: only customer partner
1428
res = [('customer', '=', True)]
1433
'by_invoice_type': fields.function(_get_fake, type='boolean',
1434
fnct_search=_get_search_by_invoice_type, method=True),
1437
def name_search(self, cr, uid, name='', args=None, operator='ilike',
1438
context=None, limit=100):
1439
# BKLG-50: IN/OUT invoice/refund partner autocompletion filter
1440
# regarding supplier/customer
1444
alternate_domain = False
1445
invoice_type = context.get('type', False)
1447
if invoice_type in ('in_invoice', 'in_refund', ):
1448
alternate_domain = [('supplier', '=', True)]
1449
elif invoice_type in ('out_invoice', 'out_refund', ):
1450
alternate_domain = [('customer', '=', True)]
1451
if alternate_domain:
1452
args += alternate_domain
1454
return super(res_partner, self).name_search(cr, uid, name=name,
1455
args=args, operator=operator, context=context, limit=limit)
1459
281
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: