Merge lp:~julie-w/unifield-server/US-4058 into lp:unifield-server/uf7

Proposed by jftempo
Status: Needs review
Proposed branch: lp:~julie-w/unifield-server/US-4058
Merge into: lp:unifield-server/uf7
Diff against target: 2496 lines (+524/-392)
21 files modified
bin/addons/account/account_cash_statement.py (+19/-16)
bin/addons/account_corrections/account_move_line.py (+10/-2)
bin/addons/base/module/module.py (+0/-7)
bin/addons/delivery_mechanism/wizard/enter_reason.py (+3/-1)
bin/addons/msf_accrual/wizard/wizard_accrual_reversal.py (+1/-1)
bin/addons/msf_accrual/wizard/wizard_accrual_validation.py (+2/-2)
bin/addons/msf_homere_interface/wizard/hr_payroll_import.py (+3/-0)
bin/addons/msf_instance/add_instance.py (+40/-3)
bin/addons/msf_outgoing/msf_outgoing.py (+97/-97)
bin/addons/msf_outgoing/report/labels.rml (+1/-1)
bin/addons/msf_profile/i18n/fr_MF.po (+19/-0)
bin/addons/msf_supply_doc_export/wizard/po_follow_up.py (+49/-49)
bin/addons/purchase/purchase_workflow.py (+39/-27)
bin/addons/register_accounting/report/fully_report_xls.mako (+10/-2)
bin/addons/register_accounting/wizard/import_invoice_on_registers.py (+2/-1)
bin/addons/register_accounting/wizard/wizard_register_import.py (+93/-70)
bin/addons/sale/sale_workflow.py (+42/-27)
bin/addons/sync_so/purchase.py (+1/-1)
bin/addons/tender_flow/tender_flow.py (+89/-84)
bin/release.py (+1/-1)
bin/sql_db.py (+3/-0)
To merge this branch: bzr merge lp:~julie-w/unifield-server/US-4058
Reviewer Review Type Date Requested Status
UniField Dev Team Pending
Review via email: mp+337538@code.launchpad.net
To post a comment you must log in.

Unmerged revisions

4719. By Julie Nuguet on 2018-02-08

US-4058 [FIX] Accruals: duplications were created when posting accrual & reversal lines

4718. By jftempo on 2018-02-02

US-3893 [FIX] C&R IN at header level should set state of stock moves to 'Canceled-r' and FO should remain Confirmed

lp:~mallorymarcot/unifield-server/us-3893

4717. By jftempo on 2018-02-02

US-3944 [FIX] PO/FO: prevent from validating an order with taxes if linked to an intermission partner

lp:~julie-w/unifield-server/US-3944

4716. By jftempo on 2018-02-02

US-3885 [FIX] PO created from Tender are not auto linked to initial IR/FO and AD is not populated from FO

lp:~mallorymarcot/unifield-server/us-3885

4715. By jftempo on 2018-02-02

US-3853 [IMP] Register Lines import: checks on "third party required"

lp:~julie-w/unifield-server/US-3853

4714. By jftempo on 2018-02-02

US-3612 [FIX] Register Full Report: remove duplicates for the use case 'advance return lines linked to Free1/2'

lp:~julie-w/unifield-server/US-3612

4713. By jftempo on 2018-02-02

US-2924 [FIX] Pick pdf labels: print weight

lp:~mallorymarcot/unifield-server/us-2924

4712. By jftempo on 2018-02-02

US-3259 [FIX] PO Follow Up per Supplier: escape html entities

lp:~mallorymarcot/unifield-server/us-3259

4711. By jftempo on 2018-02-02

US-3798 [FIX] Funding Pool: when a FP is created use the current instance_id by default

lp:~julie-w/unifield-server/US-3798

4710. By jftempo on 2018-02-02

US-3493 [IMP] Payroll import: strip spaces in all entries

lp:~julie-w/unifield-server/US-3493

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bin/addons/account/account_cash_statement.py'
--- bin/addons/account/account_cash_statement.py 2016-08-18 08:32:03 +0000
+++ bin/addons/account/account_cash_statement.py 2018-02-12 10:19:50 +0000
@@ -61,7 +61,7 @@
61 'subtotal': fields.function(_sub_total, method=True, string='Sub Total', type='float', digits_compute=dp.get_precision('Account')),61 'subtotal': fields.function(_sub_total, method=True, string='Sub Total', type='float', digits_compute=dp.get_precision('Account')),
62 'starting_id': fields.many2one('account.bank.statement', ondelete='cascade'),62 'starting_id': fields.many2one('account.bank.statement', ondelete='cascade'),
63 'ending_id': fields.many2one('account.bank.statement', ondelete='cascade'),63 'ending_id': fields.many2one('account.bank.statement', ondelete='cascade'),
64 }64 }
6565
66account_cashbox_line()66account_cashbox_line()
6767
@@ -115,7 +115,7 @@
115 for statement in self.browse(cr, uid, ids, context=context):115 for statement in self.browse(cr, uid, ids, context=context):
116 encoding_total=0.0116 encoding_total=0.0
117 for line in statement.line_ids:117 for line in statement.line_ids:
118 encoding_total += line.amount118 encoding_total += line.amount
119 res2[statement.id] = encoding_total119 res2[statement.id] = encoding_total
120 return res2120 return res2
121121
@@ -125,7 +125,7 @@
125 res = {}125 res = {}
126126
127 company_currency_id = res_users_obj.browse(cursor, user, user,127 company_currency_id = res_users_obj.browse(cursor, user, user,
128 context=context).company_id.currency_id.id128 context=context).company_id.currency_id.id
129129
130 statements = self.browse(cursor, user, ids, context=context)130 statements = self.browse(cursor, user, ids, context=context)
131 for statement in statements:131 for statement in statements:
@@ -136,14 +136,14 @@
136 if line.account_id.id == \136 if line.account_id.id == \
137 statement.journal_id.default_debit_account_id.id:137 statement.journal_id.default_debit_account_id.id:
138 res[statement.id] += res_currency_obj.compute(cursor,138 res[statement.id] += res_currency_obj.compute(cursor,
139 user, company_currency_id, currency_id,139 user, company_currency_id, currency_id,
140 line.debit, context=context)140 line.debit, context=context)
141 else:141 else:
142 if line.account_id.id == \142 if line.account_id.id == \
143 statement.journal_id.default_credit_account_id.id:143 statement.journal_id.default_credit_account_id.id:
144 res[statement.id] -= res_currency_obj.compute(cursor,144 res[statement.id] -= res_currency_obj.compute(cursor,
145 user, company_currency_id, currency_id,145 user, company_currency_id, currency_id,
146 line.credit, context=context)146 line.credit, context=context)
147147
148 if statement.state in ('draft', 'open'):148 if statement.state in ('draft', 'open'):
149 for line in statement.line_ids:149 for line in statement.line_ids:
@@ -221,8 +221,8 @@
221 'balance_end_real': fields.float('Closing Balance', digits_compute=dp.get_precision('Account'), states={'confirm': [('readonly', True)]}, help="closing balance entered by the cashbox verifier"),221 'balance_end_real': fields.float('Closing Balance', digits_compute=dp.get_precision('Account'), states={'confirm': [('readonly', True)]}, help="closing balance entered by the cashbox verifier"),
222 'state': fields.selection(222 'state': fields.selection(
223 [('draft', 'Draft'),223 [('draft', 'Draft'),
224 ('confirm', 'Closed'),224 ('confirm', 'Closed'),
225 ('open','Open')], 'State', required=True, states={'confirm': [('readonly', True)]}, readonly="1"),225 ('open','Open')], 'State', required=True, states={'confirm': [('readonly', True)]}, readonly="1"),
226 'total_entry_encoding': fields.function(_get_sum_entry_encoding, method=True, store=True, string="Cash Transaction", help="Total cash transactions"),226 'total_entry_encoding': fields.function(_get_sum_entry_encoding, method=True, store=True, string="Cash Transaction", help="Total cash transactions"),
227 'closing_date': fields.datetime("Closed On"),227 'closing_date': fields.datetime("Closed On"),
228 'balance_end': fields.function(_end_balance, method=True, store=True, string='Balance', help="Closing balance based on Starting Balance and Cash Transactions"),228 'balance_end': fields.function(_end_balance, method=True, store=True, string='Balance', help="Closing balance based on Starting Balance and Cash Transactions"),
@@ -238,12 +238,12 @@
238 'user_id': lambda self, cr, uid, context=None: uid,238 'user_id': lambda self, cr, uid, context=None: uid,
239 'starting_details_ids': _get_cash_open_box_lines,239 'starting_details_ids': _get_cash_open_box_lines,
240 'ending_details_ids': _get_default_cash_close_box_lines240 'ending_details_ids': _get_default_cash_close_box_lines
241 }241 }
242242
243 def create(self, cr, uid, vals, context=None):243 def create(self, cr, uid, vals, context=None):
244 sql = [244 sql = [
245 ('journal_id', '=', vals.get('journal_id', False)),245 ('journal_id', '=', vals.get('journal_id', False)),
246 ('state', '=', 'open')246 ('state', '=', 'open')
247 ]247 ]
248 open_jrnl = self.search(cr, uid, sql)248 open_jrnl = self.search(cr, uid, sql)
249 if open_jrnl:249 if open_jrnl:
@@ -255,10 +255,10 @@
255 for start in vals.get('starting_details_ids'):255 for start in vals.get('starting_details_ids'):
256 dict_val = start[2]256 dict_val = start[2]
257 for end in open_close['end']:257 for end in open_close['end']:
258 if end[2]['pieces'] == dict_val['pieces']:258 if end[2]['pieces'] == dict_val['pieces']:
259 end[2]['number'] += dict_val['number']259 end[2]['number'] += dict_val['number']
260 vals.update({260 vals.update({
261# 'ending_details_ids': open_close['start'],261 # 'ending_details_ids': open_close['start'],
262 'starting_details_ids': open_close['end']262 'starting_details_ids': open_close['end']
263 })263 })
264 else:264 else:
@@ -308,8 +308,11 @@
308 return super(account_cash_statement, self).onchange_journal_id(cr, uid, statement_id, journal_id, context=context)308 return super(account_cash_statement, self).onchange_journal_id(cr, uid, statement_id, journal_id, context=context)
309309
310 def _equal_balance(self, cr, uid, cash_id, context=None):310 def _equal_balance(self, cr, uid, cash_id, context=None):
311 if context is None:
312 context = {}
311 statement = self.browse(cr, uid, cash_id, context=context)313 statement = self.browse(cr, uid, cash_id, context=context)
312 self.write(cr, uid, [cash_id], {'balance_end_real': statement.balance_end})314 context.update({'from_cash_statement_equal_balance': True})
315 self.write(cr, uid, [cash_id], {'balance_end_real': statement.balance_end}, context=context)
313 statement.balance_end_real = statement.balance_end316 statement.balance_end_real = statement.balance_end
314 if abs(statement.balance_end - statement.balance_end_cash) > 10**-4:317 if abs(statement.balance_end - statement.balance_end_cash) > 10**-4:
315 return False318 return False
316319
=== modified file 'bin/addons/account_corrections/account_move_line.py'
--- bin/addons/account_corrections/account_move_line.py 2017-10-27 12:10:07 +0000
+++ bin/addons/account_corrections/account_move_line.py 2018-02-12 10:19:50 +0000
@@ -527,6 +527,9 @@
527 j_extra_ids = j_obj.search(cr, uid, [('type', '=', 'extra'),527 j_extra_ids = j_obj.search(cr, uid, [('type', '=', 'extra'),
528 ('is_current_instance', '=', True)])528 ('is_current_instance', '=', True)])
529 j_extra_id = j_extra_ids and j_extra_ids[0] or False529 j_extra_id = j_extra_ids and j_extra_ids[0] or False
530 j_ana_extra_ids = ana_j_obj.search(cr, uid, [('type', '=', 'extra'), ('is_current_instance', '=', True)], context=context)
531 j_ana_extra_id = j_ana_extra_ids and j_ana_extra_ids[0] or False
532
530 # Search attached period533 # Search attached period
531 period_ids = self.pool.get('account.period').search(cr, uid, [('date_start', '<=', date), ('date_stop', '>=', date)], context=context,534 period_ids = self.pool.get('account.period').search(cr, uid, [('date_start', '<=', date), ('date_stop', '>=', date)], context=context,
532 limit=1, order='date_start, name')535 limit=1, order='date_start, name')
@@ -555,8 +558,13 @@
555 journal_id = j_corr_id558 journal_id = j_corr_id
556 if is_inkind:559 if is_inkind:
557 journal_id = j_extra_id560 journal_id = j_extra_id
558 if not journal_id and is_inkind:561 j_ana_corr_id = j_ana_extra_id
559 raise osv.except_osv(_('Error'), _('No OD-Extra Accounting Journal found!'))562
563 if is_inkind:
564 if not journal_id:
565 raise osv.except_osv(_('Error'), _('No OD-Extra Accounting Journal found!'))
566 elif not j_ana_extra_id:
567 raise osv.except_osv(_('Error'), _('No OD-Extra Accounting Analytic Journal found!'))
560 elif not journal_id:568 elif not journal_id:
561 raise osv.except_osv(_('Error'), _('No correction journal found!'))569 raise osv.except_osv(_('Error'), _('No correction journal found!'))
562570
563571
=== modified file 'bin/addons/base/module/module.py'
--- bin/addons/base/module/module.py 2017-10-04 05:23:42 +0000
+++ bin/addons/base/module/module.py 2018-02-12 10:19:50 +0000
@@ -538,13 +538,6 @@
538 if not mod.description:538 if not mod.description:
539 logger.warn('module %s: description is empty !', mod.name)539 logger.warn('module %s: description is empty !', mod.name)
540540
541 if not mod.certificate or not mod.certificate.isdigit():
542 logger.info('module %s: no quality certificate', mod.name)
543 else:
544 val = long(mod.certificate[2:]) % 97 == 29
545 if not val:
546 logger.critical('module %s: invalid quality certificate: %s', mod.name, mod.certificate)
547 raise osv.except_osv(_('Error'), _('Module %s: Invalid Quality Certificate') % (mod.name,))
548541
549 def list_web(self, cr, uid, context=None):542 def list_web(self, cr, uid, context=None):
550 """ list_web(cr, uid, context) -> [(module_name, module_version)]543 """ list_web(cr, uid, context) -> [(module_name, module_version)]
551544
=== modified file 'bin/addons/delivery_mechanism/wizard/enter_reason.py'
--- bin/addons/delivery_mechanism/wizard/enter_reason.py 2017-11-03 10:59:21 +0000
+++ bin/addons/delivery_mechanism/wizard/enter_reason.py 2018-02-12 10:19:50 +0000
@@ -66,6 +66,8 @@
66 # set the reason66 # set the reason
67 obj.write({'change_reason': change_reason}, context=context)67 obj.write({'change_reason': change_reason}, context=context)
6868
69 if context.get('do_resource', False):
70 self.pool.get('stock.move').write(cr, uid, [move.id for move in obj.move_lines], {'has_to_be_resourced': True}, context=context)
69 self.pool.get('stock.move').action_cancel(cr, uid, [move.id for move in obj.move_lines], context=context)71 self.pool.get('stock.move').action_cancel(cr, uid, [move.id for move in obj.move_lines], context=context)
7072
71 # cancel the IN73 # cancel the IN
@@ -74,7 +76,7 @@
74 # correct the corresponding po manually if exists - should be in shipping exception76 # correct the corresponding po manually if exists - should be in shipping exception
75 if obj.purchase_id:77 if obj.purchase_id:
76 wf_service.trg_validate(uid, 'purchase.order', obj.purchase_id.id, 'picking_ok', cr)78 wf_service.trg_validate(uid, 'purchase.order', obj.purchase_id.id, 'picking_ok', cr)
77 purchase_obj.log(cr, uid, obj.purchase_id.id, _('The Purchase Order %s is %s%% received')%(obj.purchase_id.name, round(obj.purchase_id.shipped_rate,2)))79 purchase_obj.log(cr, uid, obj.purchase_id.id, _('The Purchase Order %s is %s%% received') % (obj.purchase_id.name, round(obj.purchase_id.shipped_rate, 2)))
7880
79 self.infolog(cr, uid, "The Incoming shipment id:%s (%s) has been canceled%s." % (81 self.infolog(cr, uid, "The Incoming shipment id:%s (%s) has been canceled%s." % (
80 obj.id, obj.name, cancel_type != 'update_out' and ' and resourced' or '',82 obj.id, obj.name, cancel_type != 'update_out' and ' and resourced' or '',
8183
=== modified file 'bin/addons/msf_accrual/wizard/wizard_accrual_reversal.py'
--- bin/addons/msf_accrual/wizard/wizard_accrual_reversal.py 2016-02-19 13:23:15 +0000
+++ bin/addons/msf_accrual/wizard/wizard_accrual_reversal.py 2018-02-12 10:19:50 +0000
@@ -70,7 +70,7 @@
70 raise osv.except_osv(_('Warning !'), _("The reversal period '%s' is not open!" % reversal_period.name))70 raise osv.except_osv(_('Warning !'), _("The reversal period '%s' is not open!" % reversal_period.name))
7171
72 # post the accrual reversal72 # post the accrual reversal
73 accrual_line_obj.accrual_reversal_post(cr, uid, context['active_ids'], document_date,73 accrual_line_obj.accrual_reversal_post(cr, uid, [accrual_line.id], document_date,
74 posting_date, context=context)74 posting_date, context=context)
7575
76 # close the wizard76 # close the wizard
7777
=== modified file 'bin/addons/msf_accrual/wizard/wizard_accrual_validation.py'
--- bin/addons/msf_accrual/wizard/wizard_accrual_validation.py 2016-05-24 08:44:23 +0000
+++ bin/addons/msf_accrual/wizard/wizard_accrual_validation.py 2018-02-12 10:19:50 +0000
@@ -62,11 +62,11 @@
62 raise osv.except_osv(_('Warning !'), _("The reversal period '%s' is not open!" % reversal_period.name))62 raise osv.except_osv(_('Warning !'), _("The reversal period '%s' is not open!" % reversal_period.name))
6363
64 # post the accrual64 # post the accrual
65 accrual_line_obj.accrual_post(cr, uid, context['active_ids'], context=context)65 accrual_line_obj.accrual_post(cr, uid, [accrual_line.id], context=context)
66 # post its reversal only if it is a reversing accrual66 # post its reversal only if it is a reversing accrual
67 if accrual_line.accrual_type == 'reversing_accrual':67 if accrual_line.accrual_type == 'reversing_accrual':
68 reversal_date = (datetime.datetime.strptime(accrual_line.date, '%Y-%m-%d') + relativedelta(days=1)).strftime('%Y-%m-%d')68 reversal_date = (datetime.datetime.strptime(accrual_line.date, '%Y-%m-%d') + relativedelta(days=1)).strftime('%Y-%m-%d')
69 accrual_line_obj.accrual_reversal_post(cr, uid, context['active_ids'], reversal_date,69 accrual_line_obj.accrual_reversal_post(cr, uid, [accrual_line.id], reversal_date,
70 reversal_date, context=context)70 reversal_date, context=context)
71 71
72 # close the wizard72 # close the wizard
7373
=== modified file 'bin/addons/msf_homere_interface/wizard/hr_payroll_import.py'
--- bin/addons/msf_homere_interface/wizard/hr_payroll_import.py 2017-10-06 14:55:12 +0000
+++ bin/addons/msf_homere_interface/wizard/hr_payroll_import.py 2018-02-12 10:19:50 +0000
@@ -136,6 +136,9 @@
136 error_message = ""136 error_message = ""
137 partner_obj = self.pool.get('res.partner')137 partner_obj = self.pool.get('res.partner')
138138
139 # strip spaces in all columns
140 for i in range(len(data)):
141 data[i] = data[i].strip()
139 if len(data) == 13:142 if len(data) == 13:
140 accounting_code, description, second_description, third, expense, receipt, project, financing_line, \143 accounting_code, description, second_description, third, expense, receipt, project, financing_line, \
141 financing_contract, date, currency, project, analytic_line = zip(data)144 financing_contract, date, currency, project, analytic_line = zip(data)
142145
=== modified file 'bin/addons/msf_instance/add_instance.py'
--- bin/addons/msf_instance/add_instance.py 2016-10-28 09:07:17 +0000
+++ bin/addons/msf_instance/add_instance.py 2018-02-12 10:19:50 +0000
@@ -425,10 +425,27 @@
425 def write(self, cr, uid, ids, vals, context=None):425 def write(self, cr, uid, ids, vals, context=None):
426 if not ids:426 if not ids:
427 return True427 return True
428 if context is None:
429 context = {}
428 if 'journal_id' in vals:430 if 'journal_id' in vals:
429 journal = self.pool.get('account.journal').read(cr, uid, vals['journal_id'], ['instance_id'], context=context)431 journal = self.pool.get('account.journal').read(cr, uid, vals['journal_id'], ['instance_id'], context=context)
430 vals['instance_id'] = journal.get('instance_id')[0]432 vals['instance_id'] = journal.get('instance_id')[0]
431 return super(account_bank_statement, self).write(cr, uid, ids, vals, context=context)433 res = True
434 for reg in self.browse(cr, uid, ids, fields_to_fetch=['closing_balance_frozen'], context=context):
435 # if the End-of-the-Month Balance has already been confirmed for a register, ignore changes on fields that
436 # should be read-only in that case (cover the use case of concurrent changes by 2 users)
437 newvals = vals.copy()
438 if reg.closing_balance_frozen:
439 # remove the values for each register with a confirmed balance
440 # Note: at Cashbox closing the balance_end_real is set to the reg.balance_end value: keep this change
441 if 'balance_end_real' in newvals and not context.get('from_cash_statement_equal_balance', False):
442 del newvals['balance_end_real']
443 if 'balance_start' in newvals:
444 del newvals['balance_start']
445 if 'ending_details_ids' in newvals:
446 del newvals['ending_details_ids']
447 res = res and super(account_bank_statement, self).write(cr, uid, [reg.id], newvals, context=context)
448 return res
432449
433account_bank_statement()450account_bank_statement()
434451
@@ -499,8 +516,25 @@
499 vals['instance_id'] = register.get('instance_id')[0]516 vals['instance_id'] = register.get('instance_id')[0]
500 return super(account_cashbox_line, self).write(cr, uid, ids, vals, context=context)517 return super(account_cashbox_line, self).write(cr, uid, ids, vals, context=context)
501518
519 def unlink(self, cr, uid, ids, context=None):
520 """
521 CashBox Line Deletion method
522 The deletion isn't triggered for Closing Balance Lines linked to a reg. with a Confirmed month-end cash count
523 (covers the use case of concurrent changes by 2 users)
524 """
525 if context is None:
526 context = {}
527 if isinstance(ids, (int, long)):
528 ids = [ids]
529 res = True
530 for line in self.browse(cr, uid, ids, fields_to_fetch=['ending_id'], context=context):
531 if not line.ending_id or not line.ending_id.closing_balance_frozen:
532 res = res and super(account_cashbox_line, self).unlink(cr, uid, [line.id], context=context)
533 return res
534
502account_cashbox_line()535account_cashbox_line()
503536
537
504class account_analytic_account(osv.osv):538class account_analytic_account(osv.osv):
505 _name = 'account.analytic.account'539 _name = 'account.analytic.account'
506 _inherit = 'account.analytic.account'540 _inherit = 'account.analytic.account'
@@ -534,10 +568,11 @@
534 'current_instance_type': lambda self, cr, uid, c: self.pool.get('res.users').browse(cr, uid, uid, c).company_id.instance_id.level,568 'current_instance_type': lambda self, cr, uid, c: self.pool.get('res.users').browse(cr, uid, uid, c).company_id.instance_id.level,
535 }569 }
536570
537 def check_fp(self, cr, uid, vals, context=None):571 def check_fp(self, cr, uid, vals, to_update=False, context=None):
538 """572 """
539 Check that FP have an instance_id573 Check that FP have an instance_id
540 Check that the given instance is not section level!574 Check that the given instance is not section level!
575 If to_update is True and no instance_id is in vals: update vals with the id of the current instance
541 """576 """
542 if context is None:577 if context is None:
543 context = {}578 context = {}
@@ -554,6 +589,8 @@
554 if not current_instance or current_instance.level == 'section':589 if not current_instance or current_instance.level == 'section':
555 raise osv.except_osv(_('Error'), _('Proprietary Instance is mandatory for FP accounts!'))590 raise osv.except_osv(_('Error'), _('Proprietary Instance is mandatory for FP accounts!'))
556 instance_id = current_instance.id591 instance_id = current_instance.id
592 if to_update:
593 vals.update({'instance_id': instance_id})
557 instance_level = self.pool.get('msf.instance').browse(cr, uid, instance_id).level594 instance_level = self.pool.get('msf.instance').browse(cr, uid, instance_id).level
558 if instance_level == 'section':595 if instance_level == 'section':
559 raise osv.except_osv(_('Warning'), _('Proprietary Instance for FP accounts should be only COORDO and/or MISSION'))596 raise osv.except_osv(_('Warning'), _('Proprietary Instance for FP accounts should be only COORDO and/or MISSION'))
@@ -567,7 +604,7 @@
567 context = {}604 context = {}
568 # Check that instance_id is filled in for FP605 # Check that instance_id is filled in for FP
569 if context.get('from_web', False) is True:606 if context.get('from_web', False) is True:
570 self.check_fp(cr, uid, vals, context=context)607 self.check_fp(cr, uid, vals, to_update=True, context=context)
571 return super(account_analytic_account, self).create(cr, uid, vals, context=context)608 return super(account_analytic_account, self).create(cr, uid, vals, context=context)
572609
573 def write(self, cr, uid, ids, vals, context=None):610 def write(self, cr, uid, ids, vals, context=None):
574611
=== modified file 'bin/addons/msf_outgoing/msf_outgoing.py'
--- bin/addons/msf_outgoing/msf_outgoing.py 2017-12-14 17:30:55 +0000
+++ bin/addons/msf_outgoing/msf_outgoing.py 2018-02-12 10:19:50 +0000
@@ -613,7 +613,7 @@
613 shipment_name = '%s-%s' % (shipment.name, shipment_number)613 shipment_name = '%s-%s' % (shipment.name, shipment_number)
614 source_shipment_address_id = shipment.address_id.id if shipment.address_id else False614 source_shipment_address_id = shipment.address_id.id if shipment.address_id else False
615615
616 if context.get('rw_shipment_name', False) and context.get('sync_message_execution', False): # RW Sync - update the shipment name same as on RW instance616 if context.get('rw_shipment_name', False) and context.get('sync_message_execution', False): # RW Sync - update the shipment name same as on RW instance
617 shipment_name = context.get('rw_shipment_name')617 shipment_name = context.get('rw_shipment_name')
618 del context['rw_shipment_name']618 del context['rw_shipment_name']
619619
@@ -659,7 +659,7 @@
659 del context['description_ppl']659 del context['description_ppl']
660660
661 for family in wizard.family_ids:661 for family in wizard.family_ids:
662 if not family.selected_number: # UTP-1015 fix from Quentin662 if not family.selected_number: # UTP-1015 fix from Quentin
663 continue663 continue
664664
665 picking = family.draft_packing_id665 picking = family.draft_packing_id
@@ -674,7 +674,7 @@
674 'backorder_id': picking.id,674 'backorder_id': picking.id,
675 'shipment_id': False,675 'shipment_id': False,
676 'move_lines': [],676 'move_lines': [],
677 'description_ppl': description_ppl or picking.description_ppl, # US-803: added the description677 'description_ppl': description_ppl or picking.description_ppl, # US-803: added the description
678 }678 }
679 # Update context for copy679 # Update context for copy
680 context.update({680 context.update({
@@ -709,8 +709,8 @@
709709
710 # Log creation message710 # Log creation message
711 message = _('The new Shipment id:%s (%s) has been created.')711 message = _('The new Shipment id:%s (%s) has been created.')
712 self.log(cr, uid, shipment.id, message%(shipment.id, shipment_name,))712 self.log(cr, uid, shipment.id, message % (shipment.id, shipment_name,))
713 self.infolog(cr, uid, message%(shipment.id, shipment.name))713 self.infolog(cr, uid, message % (shipment.id, shipment.name))
714 # The shipment is automatically shipped, no more pack states in between.714 # The shipment is automatically shipped, no more pack states in between.
715 self.ship(cr, uid, [shipment_id], context=context)715 self.ship(cr, uid, [shipment_id], context=context)
716716
@@ -729,7 +729,7 @@
729 })729 })
730730
731 return {731 return {
732 'name':_("Shipment"),732 'name': _("Shipment"),
733 'type': 'ir.actions.act_window',733 'type': 'ir.actions.act_window',
734 'res_model': 'shipment',734 'res_model': 'shipment',
735 'view_mode': 'form,tree',735 'view_mode': 'form,tree',
@@ -881,7 +881,7 @@
881 'from_pack': family.to_pack - family.selected_number + 1,881 'from_pack': family.to_pack - family.selected_number + 1,
882 'to_pack': family.to_pack,882 'to_pack': family.to_pack,
883 'state': 'done',883 'state': 'done',
884 'not_shipped': True, #BKLG-13: set the pack returned to stock also as not_shipped, for showing to view ship draft884 'not_shipped': True, # BKLG-13: set the pack returned to stock also as not_shipped, for showing to view ship draft
885 }885 }
886 context['non_stock_noupdate'] = True886 context['non_stock_noupdate'] = True
887887
@@ -902,12 +902,12 @@
902 ('wizard_id', '=', picking_processor_wiz.id),902 ('wizard_id', '=', picking_processor_wiz.id),
903 ('move_id', '=', draft_move.id),903 ('move_id', '=', draft_move.id),
904 ], context=context)904 ], context=context)
905 if not save_as_draft_move: # then create the SaD line:905 if not save_as_draft_move: # then create the SaD line:
906 move_data = self.pool.get('create.picking.move.processor')._get_line_data(cr, uid, wizard=picking_processor_wiz, move=draft_move, context=context)906 move_data = self.pool.get('create.picking.move.processor')._get_line_data(cr, uid, wizard=picking_processor_wiz, move=draft_move, context=context)
907 move_data.update({'quantity': return_qty})907 move_data.update({'quantity': return_qty})
908 save_as_draft_move = self.pool.get('create.picking.move.processor').create(cr, uid, move_data, context=context)908 save_as_draft_move = self.pool.get('create.picking.move.processor').create(cr, uid, move_data, context=context)
909 save_as_draft_move = [save_as_draft_move]909 save_as_draft_move = [save_as_draft_move]
910 else: # update Sad line910 else: # update Sad line
911 for sad_move in self.pool.get('create.picking.move.processor').browse(cr, uid, save_as_draft_move, context=context):911 for sad_move in self.pool.get('create.picking.move.processor').browse(cr, uid, save_as_draft_move, context=context):
912 self.pool.get('create.picking.move.processor').write(cr, uid, sad_move.id, {912 self.pool.get('create.picking.move.processor').write(cr, uid, sad_move.id, {
913 'ordered_quantity': sad_move.ordered_quantity + return_qty,913 'ordered_quantity': sad_move.ordered_quantity + return_qty,
@@ -935,13 +935,13 @@
935 # If everything is allright (all draft packing are finished) the shipment is done also935 # If everything is allright (all draft packing are finished) the shipment is done also
936 self.complete_finished(cr, uid, shipment_ids, context=context)936 self.complete_finished(cr, uid, shipment_ids, context=context)
937937
938 #UF-2531: Create manually the message for the return pack of the ship938 # UF-2531: Create manually the message for the return pack of the ship
939 if shipment and shipment.id:939 if shipment and shipment.id:
940 self._manual_create_rw_shipment_message(cr, uid, shipment.id, return_info, 'usb_shipment_return_packs_shipment_draft', context=context)940 self._manual_create_rw_shipment_message(cr, uid, shipment.id, return_info, 'usb_shipment_return_packs_shipment_draft', context=context)
941941
942 view_id = data_obj.get_object_reference(cr, uid, 'msf_outgoing', 'view_picking_ticket_form')942 view_id = data_obj.get_object_reference(cr, uid, 'msf_outgoing', 'view_picking_ticket_form')
943 return {943 return {
944 'name':_("Picking Ticket"),944 'name': _("Picking Ticket"),
945 'view_mode': 'form,tree',945 'view_mode': 'form,tree',
946 'view_id': [view_id and view_id[1] or False],946 'view_id': [view_id and view_id[1] or False],
947 'view_type': 'form',947 'view_type': 'form',
@@ -1207,13 +1207,13 @@
1207 # if everything is allright (all draft packing are finished) the shipment is done also1207 # if everything is allright (all draft packing are finished) the shipment is done also
1208 self.complete_finished(cr, uid, shipment_ids, context=context)1208 self.complete_finished(cr, uid, shipment_ids, context=context)
12091209
1210 #UF-2531: Create manually the message for the return pack of the ship1210 # UF-2531: Create manually the message for the return pack of the ship
1211 if shipment and shipment.id:1211 if shipment and shipment.id:
1212 self._manual_create_rw_shipment_message(cr, uid, shipment.id, return_info, 'usb_shipment_return_packs', context=context)1212 self._manual_create_rw_shipment_message(cr, uid, shipment.id, return_info, 'usb_shipment_return_packs', context=context)
12131213
1214 view_id = data_obj.get_object_reference(cr, uid, 'msf_outgoing', 'view_shipment_form')1214 view_id = data_obj.get_object_reference(cr, uid, 'msf_outgoing', 'view_shipment_form')
1215 return {1215 return {
1216 'name':_("Shipment"),1216 'name': _("Shipment"),
1217 'view_mode': 'form,tree',1217 'view_mode': 'form,tree',
1218 'view_id': [view_id and view_id[1] or False],1218 'view_id': [view_id and view_id[1] or False],
1219 'view_type': 'form',1219 'view_type': 'form',
@@ -1279,7 +1279,7 @@
1279 # the state does not need to be updated - function1279 # the state does not need to be updated - function
1280 # update actual ship date (shipment_actual_date) to today + time1280 # update actual ship date (shipment_actual_date) to today + time
1281 today = time.strftime(db_datetime_format)1281 today = time.strftime(db_datetime_format)
1282 vals = {'shipment_actual_date': today,}1282 vals = {'shipment_actual_date': today, }
1283 if context.get('source_shipment_address_id', False):1283 if context.get('source_shipment_address_id', False):
1284 vals['address_id'] = context['source_shipment_address_id']1284 vals['address_id'] = context['source_shipment_address_id']
12851285
@@ -1308,7 +1308,7 @@
1308 pick_obj.write(cr, uid, [new_packing_id], ({'claim': True}), context=context)1308 pick_obj.write(cr, uid, [new_packing_id], ({'claim': True}), context=context)
1309 new_packing = pick_obj.browse(cr, uid, new_packing_id, context=context)1309 new_packing = pick_obj.browse(cr, uid, new_packing_id, context=context)
13101310
1311 if new_packing.move_lines and pick_obj._get_usb_entity_type(cr, uid) == pick_obj.REMOTE_WAREHOUSE and not context.get('sync_message_execution', False): # RW Sync - set the replicated to True for not syncing it again1311 if new_packing.move_lines and pick_obj._get_usb_entity_type(cr, uid) == pick_obj.REMOTE_WAREHOUSE and not context.get('sync_message_execution', False): # RW Sync - set the replicated to True for not syncing it again
1312 pick_obj.write(cr, uid, [new_packing_id], {'for_shipment_replicate': True}, context=context)1312 pick_obj.write(cr, uid, [new_packing_id], {'for_shipment_replicate': True}, context=context)
13131313
1314 # update the shipment_date of the corresponding sale order if the date is not set yet - with current date1314 # update the shipment_date of the corresponding sale order if the date is not set yet - with current date
@@ -1490,7 +1490,7 @@
1490 'payment_term': payment_term_id,1490 'payment_term': payment_term_id,
1491 'fiscal_position': partner.property_account_position.id,1491 'fiscal_position': partner.property_account_position.id,
1492 'date_invoice': context.get('date_inv', False) or today,1492 'date_invoice': context.get('date_inv', False) or today,
1493 'user_id':uid,1493 'user_id': uid,
1494 }1494 }
14951495
1496 cur_id = shipment.pack_family_memory_ids[0].currency_id.id1496 cur_id = shipment.pack_family_memory_ids[0].currency_id.id
@@ -1826,8 +1826,8 @@
1826 _name = 'stock.picking'1826 _name = 'stock.picking'
18271827
1828 # For use only in Remote Warehouse1828 # For use only in Remote Warehouse
1829 CENTRAL_PLATFORM="central_platform"1829 CENTRAL_PLATFORM = "central_platform"
1830 REMOTE_WAREHOUSE="remote_warehouse"1830 REMOTE_WAREHOUSE = "remote_warehouse"
18311831
1832 def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):1832 def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
1833 '''1833 '''
@@ -1855,8 +1855,8 @@
1855 pass1855 pass
18561856
1857 res = super(stock_picking, self).fields_view_get(cr, uid, view_id, view_type, context=context, toolbar=toolbar, submenu=submenu)1857 res = super(stock_picking, self).fields_view_get(cr, uid, view_id, view_type, context=context, toolbar=toolbar, submenu=submenu)
1858 #US-688 Do not show the button new, duplicate in the tree and form view of picking1858 # US-688 Do not show the button new, duplicate in the tree and form view of picking
1859 if view_type in ['tree','form'] and res['name'] in ['picking.ticket.form', 'picking.ticket.tree']:1859 if view_type in ['tree', 'form'] and res['name'] in ['picking.ticket.form', 'picking.ticket.tree']:
1860 root = etree.fromstring(res['arch'])1860 root = etree.fromstring(res['arch'])
1861 root.set('hide_new_button', 'True')1861 root.set('hide_new_button', 'True')
1862 root.set('hide_delete_button', 'True')1862 root.set('hide_delete_button', 'True')
@@ -1906,7 +1906,7 @@
1906 context.update({'picking_type': 'incoming_shipment'})1906 context.update({'picking_type': 'incoming_shipment'})
1907 else:1907 else:
1908 context.update({'picking_type': 'internal_move'})1908 context.update({'picking_type': 'internal_move'})
1909 context.update({'_terp_view_name': 'Internal Moves'}) # REF-92: Update also the Form view name, otherwise Products to Process1909 context.update({'_terp_view_name': 'Internal Moves'}) # REF-92: Update also the Form view name, otherwise Products to Process
19101910
1911 return super(stock_picking, self)._hook_picking_get_view(cr, uid, ids, context=context, *args, **kwargs)1911 return super(stock_picking, self)._hook_picking_get_view(cr, uid, ids, context=context, *args, **kwargs)
19121912
@@ -2702,7 +2702,7 @@
2702 res = cr.dictfetchone()2702 res = cr.dictfetchone()
2703 if res and res['id']:2703 if res and res['id']:
2704 seq = 'ir_sequence_%03d' % res['id']2704 seq = 'ir_sequence_%03d' % res['id']
2705 cr.execute("ALTER SEQUENCE " + seq +" RESTART WITH " + str(value_to_force))2705 cr.execute("ALTER SEQUENCE " + seq + " RESTART WITH " + str(value_to_force))
2706 return2706 return
27072707
2708 def create(self, cr, uid, vals, context=None):2708 def create(self, cr, uid, vals, context=None):
@@ -2734,12 +2734,12 @@
2734 # The following lines are to re-enter explicitly the values, even if they are already set to False2734 # The following lines are to re-enter explicitly the values, even if they are already set to False
2735 vals['backorder_id'] = vals.get('backorder_id', False)2735 vals['backorder_id'] = vals.get('backorder_id', False)
2736 vals['shipment_id'] = vals.get('shipment_id', False)2736 vals['shipment_id'] = vals.get('shipment_id', False)
2737 else: # if it is a CONSO-OUT --_> set the state for replicating back to CP2737 else: # if it is a CONSO-OUT --_> set the state for replicating back to CP
2738 if 'name' in vals and 'OUT-CONSO' in vals['name']:2738 if 'name' in vals and 'OUT-CONSO' in vals['name']:
2739 vals.update(already_replicated=False,)2739 vals.update(already_replicated=False,)
2740 #UF-2531: When the INT from scratch created in RW, just set it for sync to CP2740 # UF-2531: When the INT from scratch created in RW, just set it for sync to CP
2741 if usb_entity == self.REMOTE_WAREHOUSE and (('type' in vals and vals['type']=='internal') or 2741 if usb_entity == self.REMOTE_WAREHOUSE and (('type' in vals and vals['type'] == 'internal') or
2742 ('origin' not in vals or vals['origin']==False)): #US-702 Sync also the OUT from scratch in RW2742 ('origin' not in vals or vals['origin'] == False)): # US-702 Sync also the OUT from scratch in RW
2743 vals.update(already_replicated=False,)2743 vals.update(already_replicated=False,)
27442744
2745 # the action adds subtype in the context depending from which screen it is created2745 # the action adds subtype in the context depending from which screen it is created
@@ -2771,10 +2771,10 @@
27712771
2772 if not vals['backorder_id']:2772 if not vals['backorder_id']:
2773 # creation of *draft* picking ticket2773 # creation of *draft* picking ticket
2774 vals.update(sequence_id=self.create_sequence(cr, uid, {'name':vals['name'],2774 vals.update(sequence_id=self.create_sequence(cr, uid, {'name': vals['name'],
2775 'code':vals['name'],2775 'code': vals['name'],
2776 'prefix':'',2776 'prefix': '',
2777 'padding':2}, context=context))2777 'padding': 2}, context=context))
27782778
2779 if 'subtype' in vals and vals['subtype'] == 'packing':2779 if 'subtype' in vals and vals['subtype'] == 'packing':
2780 # creation of a new packing2780 # creation of a new packing
@@ -2783,10 +2783,10 @@
27832783
2784 if not vals['backorder_id']:2784 if not vals['backorder_id']:
2785 # creation of *draft* picking ticket2785 # creation of *draft* picking ticket
2786 vals.update(sequence_id=self.create_sequence(cr, uid, {'name':vals['name'],2786 vals.update(sequence_id=self.create_sequence(cr, uid, {'name': vals['name'],
2787 'code':vals['name'],2787 'code': vals['name'],
2788 'prefix':'',2788 'prefix': '',
2789 'padding':2,2789 'padding': 2,
2790 }, context=context))2790 }, context=context))
27912791
2792 # create packing object2792 # create packing object
@@ -2797,7 +2797,7 @@
2797 if new_packing and ((new_packing.type == 'out' and new_packing.subtype == 'picking' and new_packing.name.find('-') == -1) or2797 if new_packing and ((new_packing.type == 'out' and new_packing.subtype == 'picking' and new_packing.name.find('-') == -1) or
2798 (new_packing.type == 'in' and new_packing.subtype == 'standard') or2798 (new_packing.type == 'in' and new_packing.subtype == 'standard') or
2799 (new_packing.type == 'internal' and new_packing.subtype == 'standard' and new_packing.sale_id)):2799 (new_packing.type == 'internal' and new_packing.subtype == 'standard' and new_packing.sale_id)):
2800 for_update = {'already_replicated':False}2800 for_update = {'already_replicated': False}
28012801
2802 '''2802 '''
2803 Only get the current sequence for the IN object at the moment, as we still have problem with the naming of documents functionally2803 Only get the current sequence for the IN object at the moment, as we still have problem with the naming of documents functionally
@@ -2911,7 +2911,7 @@
2911 shipment_ids = [n['id']]2911 shipment_ids = [n['id']]
2912 found = True2912 found = True
2913 break2913 break
2914 if not found: # If the name is new, then create a new Shipment2914 if not found: # If the name is new, then create a new Shipment
2915 shipment_ids = []2915 shipment_ids = []
29162916
2917 # only one 'draft' shipment should be available2917 # only one 'draft' shipment should be available
@@ -2946,10 +2946,10 @@
2946 'shipment_actual_date': rts,2946 'shipment_actual_date': rts,
2947 'sale_id': vals.get('sale_id', False),2947 'sale_id': vals.get('sale_id', False),
2948 'transport_type': sale_id and sale_order_obj.read(cr, uid, sale_id, ['transport_type'], context=context)['transport_type'] or False,2948 'transport_type': sale_id and sale_order_obj.read(cr, uid, sale_id, ['transport_type'], context=context)['transport_type'] or False,
2949 'sequence_id': self.create_sequence(cr, uid, {'name':name,2949 'sequence_id': self.create_sequence(cr, uid, {'name': name,
2950 'code':name,2950 'code': name,
2951 'prefix':'',2951 'prefix': '',
2952 'padding':2}, context=context)}2952 'padding': 2}, context=context)}
29532953
2954 shipment_id = shipment_obj.create(cr, uid, values, context=context)2954 shipment_id = shipment_obj.create(cr, uid, values, context=context)
2955 shipment_obj.log(cr, uid, shipment_id, _('The new Draft Shipment %s has been created.') % (name,))2955 shipment_obj.log(cr, uid, shipment_id, _('The new Draft Shipment %s has been created.') % (name,))
@@ -3225,7 +3225,7 @@
3225 search_view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock', 'view_picking_out_search')3225 search_view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock', 'view_picking_out_search')
3226 search_view_id = search_view_id and search_view_id[1] or False3226 search_view_id = search_view_id and search_view_id[1] or False
3227 context.update({'picking_type': 'delivery_order', 'view_id': view_id, 'search_view_id': search_view_id})3227 context.update({'picking_type': 'delivery_order', 'view_id': view_id, 'search_view_id': search_view_id})
3228 return {'name':_("Delivery Orders"),3228 return {'name': _("Delivery Orders"),
3229 'view_mode': 'form,tree',3229 'view_mode': 'form,tree',
3230 'view_id': [view_id, tree_view_id],3230 'view_id': [view_id, tree_view_id],
3231 'search_view_id': search_view_id,3231 'search_view_id': search_view_id,
@@ -3287,10 +3287,10 @@
3287 'subtype': 'picking',3287 'subtype': 'picking',
3288 'converted_to_standard': False,3288 'converted_to_standard': False,
3289 'state': 'draft',3289 'state': 'draft',
3290 'sequence_id': self.create_sequence(cr, uid, {'name':new_name,3290 'sequence_id': self.create_sequence(cr, uid, {'name': new_name,
3291 'code':new_name,3291 'code': new_name,
3292 'prefix':'',3292 'prefix': '',
3293 'padding':2}, context=context)3293 'padding': 2}, context=context)
3294 }3294 }
32953295
3296 self.write(cr, uid, [out.id], default_vals, context=context)3296 self.write(cr, uid, [out.id], default_vals, context=context)
@@ -3465,13 +3465,13 @@
3465 if need_new_picking and not rw_full_process:3465 if need_new_picking and not rw_full_process:
3466 cp_vals = {3466 cp_vals = {
3467 'name': sequence_obj.get(cr, uid, 'stock.picking.%s' % (picking.type)),3467 'name': sequence_obj.get(cr, uid, 'stock.picking.%s' % (picking.type)),
3468 'move_lines' : [],3468 'move_lines': [],
3469 'state':'draft',3469 'state': 'draft',
3470 }3470 }
3471 context['allow_copy'] = True3471 context['allow_copy'] = True
34723472
3473 new_picking_id = picking_obj.copy(cr, uid, picking.id, cp_vals, context=context)3473 new_picking_id = picking_obj.copy(cr, uid, picking.id, cp_vals, context=context)
3474 # US-327: if it's an internal picking and in partial process, then set the already_replicated to True, so no replicate needed 3474 # US-327: if it's an internal picking and in partial process, then set the already_replicated to True, so no replicate needed
3475 if picking.type == 'internal' and (usb_entity == self.REMOTE_WAREHOUSE or context.get('sync_message_execution', False)):3475 if picking.type == 'internal' and (usb_entity == self.REMOTE_WAREHOUSE or context.get('sync_message_execution', False)):
3476 to_be_replicated = False3476 to_be_replicated = False
3477 self.write(cr, uid, [new_picking_id], {'already_replicated': True}, context=context)3477 self.write(cr, uid, [new_picking_id], {'already_replicated': True}, context=context)
@@ -3646,14 +3646,14 @@
3646 # Create the new picking object3646 # Create the new picking object
3647 # A sequence for each draft picking ticket is used for the picking ticket3647 # A sequence for each draft picking ticket is used for the picking ticket
36483648
3649 #UF-2531: Use the name of the PICK sent from the RW sync if it's the case3649 # UF-2531: Use the name of the PICK sent from the RW sync if it's the case
3650 pick_name = False3650 pick_name = False
3651 already_replicated = False3651 already_replicated = False
3652 if 'associate_pick_name' in context:3652 if 'associate_pick_name' in context:
3653 pick_name = context.get('associate_pick_name', False)3653 pick_name = context.get('associate_pick_name', False)
3654 del context['associate_pick_name']3654 del context['associate_pick_name']
3655 already_replicated = True3655 already_replicated = True
3656 #US-803: Set the pick name that given from sync3656 # US-803: Set the pick name that given from sync
3657 elif 'rw_backorder_name' in context:3657 elif 'rw_backorder_name' in context:
3658 pick_name = context.get('rw_backorder_name', False)3658 pick_name = context.get('rw_backorder_name', False)
3659 del context['rw_backorder_name']3659 del context['rw_backorder_name']
@@ -3767,7 +3767,7 @@
3767 if usb_entity == self.REMOTE_WAREHOUSE and not context.get('sync_message_execution', False):3767 if usb_entity == self.REMOTE_WAREHOUSE and not context.get('sync_message_execution', False):
3768 self._manual_create_rw_messages(cr, uid, context=context)3768 self._manual_create_rw_messages(cr, uid, context=context)
37693769
3770 return {'name':_("Picking Ticket"),3770 return {'name': _("Picking Ticket"),
3771 'view_mode': 'form,tree',3771 'view_mode': 'form,tree',
3772 'view_id': [view_id],3772 'view_id': [view_id],
3773 'view_type': 'form',3773 'view_type': 'form',
@@ -3864,7 +3864,7 @@
3864 })3864 })
38653865
3866 # Create the new ppl object3866 # Create the new ppl object
3867 #US-702: If the PPL is from RW, then add the suffix RW, if it is created via RW Sync in CP, then use the one from the context (name sent by RW instance)3867 # US-702: If the PPL is from RW, then add the suffix RW, if it is created via RW Sync in CP, then use the one from the context (name sent by RW instance)
3868 ppl_number = 'PPL/%s' % picking.name.split("/")[1]3868 ppl_number = 'PPL/%s' % picking.name.split("/")[1]
3869 if context.get('rw_backorder_name', False):3869 if context.get('rw_backorder_name', False):
3870 ppl_number = context.get('rw_backorder_name')3870 ppl_number = context.get('rw_backorder_name')
@@ -3979,7 +3979,7 @@
3979 diff_qty = move_vals['initial_qty'] - move_vals['processed_qty']3979 diff_qty = move_vals['initial_qty'] - move_vals['processed_qty']
3980 if diff_qty != 0.00:3980 if diff_qty != 0.00:
3981 # Original move from the draft picking ticket which will be updated3981 # Original move from the draft picking ticket which will be updated
3982 if move_vals['move'].backmove_id: #2531: Added a check to make sure the following code can be run correctly3982 if move_vals['move'].backmove_id: # 2531: Added a check to make sure the following code can be run correctly
3983 original_move_id = move_vals['move'].backmove_id.id3983 original_move_id = move_vals['move'].backmove_id.id
3984 original_vals = move_obj.browse(cr, uid, original_move_id, context=context)3984 original_vals = move_obj.browse(cr, uid, original_move_id, context=context)
3985 if original_vals.product_uom.id != move_vals['move'].product_uom.id:3985 if original_vals.product_uom.id != move_vals['move'].product_uom.id:
@@ -4020,7 +4020,7 @@
4020 if usb_entity == self.REMOTE_WAREHOUSE and not context.get('sync_message_execution', False):4020 if usb_entity == self.REMOTE_WAREHOUSE and not context.get('sync_message_execution', False):
4021 self._manual_create_rw_messages(cr, uid, context=context)4021 self._manual_create_rw_messages(cr, uid, context=context)
40224022
4023 return {'name':_("Pre-Packing List"),4023 return {'name': _("Pre-Packing List"),
4024 'view_mode': 'form,tree',4024 'view_mode': 'form,tree',
4025 'view_id': [view_id],4025 'view_id': [view_id],
4026 'view_type': 'form',4026 'view_type': 'form',
@@ -4225,7 +4225,7 @@
4225 'shipment_id': False,4225 'shipment_id': False,
4226 'origin': picking.origin,4226 'origin': picking.origin,
4227 'move_lines': [],4227 'move_lines': [],
4228 'date': today, # Set date as today for the new PACK object4228 'date': today, # Set date as today for the new PACK object
4229 }4229 }
42304230
4231 # Change the context for copy4231 # Change the context for copy
@@ -4239,7 +4239,7 @@
4239 new_packing_id = self.copy(cr, uid, picking.id, pack_values, context=context)4239 new_packing_id = self.copy(cr, uid, picking.id, pack_values, context=context)
4240 if picking.claim:4240 if picking.claim:
4241 self.write(cr, uid, new_packing_id, ({'claim': True}), context=context)4241 self.write(cr, uid, new_packing_id, ({'claim': True}), context=context)
4242 if usb_entity == self.REMOTE_WAREHOUSE and not context.get('sync_message_execution', False): # RW Sync - set the replicated to True for not syncing it again4242 if usb_entity == self.REMOTE_WAREHOUSE and not context.get('sync_message_execution', False): # RW Sync - set the replicated to True for not syncing it again
4243 self.write(cr, uid, new_packing_id, {'already_replicated': False}, context=context)4243 self.write(cr, uid, new_packing_id, {'already_replicated': False}, context=context)
42444244
4245 # Reset context values4245 # Reset context values
@@ -4336,7 +4336,7 @@
4336 shipment_id = obj.shipment_id.id4336 shipment_id = obj.shipment_id.id
4337 shipment_name = obj.shipment_id.name4337 shipment_name = obj.shipment_id.name
43384338
4339 if context.get('rw_shipment_name', False) and context.get('sync_message_execution', False): # RW Sync - update the shipment name same as on RW instance4339 if context.get('rw_shipment_name', False) and context.get('sync_message_execution', False): # RW Sync - update the shipment name same as on RW instance
4340 new_name = context.get('rw_shipment_name')4340 new_name = context.get('rw_shipment_name')
4341 if new_name != obj.shipment_id.name:4341 if new_name != obj.shipment_id.name:
4342 del context['rw_shipment_name']4342 del context['rw_shipment_name']
@@ -4356,7 +4356,7 @@
43564356
4357 view_id = data_obj.get_object_reference(cr, uid, 'msf_outgoing', 'view_shipment_form')4357 view_id = data_obj.get_object_reference(cr, uid, 'msf_outgoing', 'view_shipment_form')
4358 view_id = view_id and view_id[1] or False4358 view_id = view_id and view_id[1] or False
4359 return {'name':_("Shipment"),4359 return {'name': _("Shipment"),
4360 'view_mode': 'form,tree',4360 'view_mode': 'form,tree',
4361 'view_id': [view_id],4361 'view_id': [view_id],
4362 'view_type': 'form',4362 'view_type': 'form',
@@ -4490,12 +4490,12 @@
4490 ('wizard_id', '=', picking_processor_wiz.id),4490 ('wizard_id', '=', picking_processor_wiz.id),
4491 ('move_id', '=', draft_move_id),4491 ('move_id', '=', draft_move_id),
4492 ], context=context)4492 ], context=context)
4493 if not save_as_draft_move: # then create the SaD line:4493 if not save_as_draft_move: # then create the SaD line:
4494 move_data = self.pool.get('create.picking.move.processor')._get_line_data(cr, uid, wizard=picking_processor_wiz, move=line.move_id.backmove_id, context=context)4494 move_data = self.pool.get('create.picking.move.processor')._get_line_data(cr, uid, wizard=picking_processor_wiz, move=line.move_id.backmove_id, context=context)
4495 move_data.update({'quantity': return_qty})4495 move_data.update({'quantity': return_qty})
4496 save_as_draft_move = self.pool.get('create.picking.move.processor').create(cr, uid, move_data, context=context)4496 save_as_draft_move = self.pool.get('create.picking.move.processor').create(cr, uid, move_data, context=context)
4497 save_as_draft_move = [save_as_draft_move]4497 save_as_draft_move = [save_as_draft_move]
4498 else: # update Sad line4498 else: # update Sad line
4499 for sad_move in self.pool.get('create.picking.move.processor').browse(cr, uid, save_as_draft_move, context=context):4499 for sad_move in self.pool.get('create.picking.move.processor').browse(cr, uid, save_as_draft_move, context=context):
4500 self.pool.get('create.picking.move.processor').write(cr, uid, sad_move.id, {4500 self.pool.get('create.picking.move.processor').write(cr, uid, sad_move.id, {
4501 'ordered_quantity': sad_move.ordered_quantity + return_qty,4501 'ordered_quantity': sad_move.ordered_quantity + return_qty,
@@ -4537,17 +4537,17 @@
4537 view_id = view_id and view_id[1] or False4537 view_id = view_id and view_id[1] or False
4538 context['picking_type'] = 'picking_ticket'4538 context['picking_type'] = 'picking_ticket'
45394539
4540 #UF-2531: Create manually the message for the return pack of the ship4540 # UF-2531: Create manually the message for the return pack of the ship
4541 self._manual_create_rw_picking_message(cr, uid, picking.id, return_info, 'usb_picking_return_products', context=context)4541 self._manual_create_rw_picking_message(cr, uid, picking.id, return_info, 'usb_picking_return_products', context=context)
45424542
4543 context.update({'picking_type': 'picking_ticket'})4543 context.update({'picking_type': 'picking_ticket'})
4544 return {4544 return {
4545 'name':_("Picking Ticket"),4545 'name': _("Picking Ticket"),
4546 'view_mode': 'form,tree',4546 'view_mode': 'form,tree',
4547 'view_id': [view_id],4547 'view_id': [view_id],
4548 'view_type': 'form',4548 'view_type': 'form',
4549 'res_model': 'stock.picking',4549 'res_model': 'stock.picking',
4550 'res_id': draft_picking_id ,4550 'res_id': draft_picking_id,
4551 'type': 'ir.actions.act_window',4551 'type': 'ir.actions.act_window',
4552 'target': 'crush',4552 'target': 'crush',
4553 'context': context,4553 'context': context,
@@ -4641,12 +4641,12 @@
4641 ('wizard_id', '=', picking_processor_wiz.id),4641 ('wizard_id', '=', picking_processor_wiz.id),
4642 ('move_id', '=', draft_move.id),4642 ('move_id', '=', draft_move.id),
4643 ], context=context)4643 ], context=context)
4644 if not save_as_draft_move: # then create the SaD line:4644 if not save_as_draft_move: # then create the SaD line:
4645 move_data = self.pool.get('create.picking.move.processor')._get_line_data(cr, uid, wizard=picking_processor_wiz, move=move, context=context)4645 move_data = self.pool.get('create.picking.move.processor')._get_line_data(cr, uid, wizard=picking_processor_wiz, move=move, context=context)
4646 move_data.update({'quantity': move.product_qty})4646 move_data.update({'quantity': move.product_qty})
4647 save_as_draft_move = self.pool.get('create.picking.move.processor').create(cr, uid, move_data, context=context)4647 save_as_draft_move = self.pool.get('create.picking.move.processor').create(cr, uid, move_data, context=context)
4648 save_as_draft_move = [save_as_draft_move]4648 save_as_draft_move = [save_as_draft_move]
4649 else: # update Sad line4649 else: # update Sad line
4650 for sad_move in self.pool.get('create.picking.move.processor').browse(cr, uid, save_as_draft_move, context=context):4650 for sad_move in self.pool.get('create.picking.move.processor').browse(cr, uid, save_as_draft_move, context=context):
4651 self.pool.get('create.picking.move.processor').write(cr, uid, sad_move.id, {4651 self.pool.get('create.picking.move.processor').write(cr, uid, sad_move.id, {
4652 'ordered_quantity': sad_move.ordered_quantity + move.product_qty,4652 'ordered_quantity': sad_move.ordered_quantity + move.product_qty,
@@ -4982,10 +4982,10 @@
4982 _columns = {'from_pack': fields.integer(string='From p.'),4982 _columns = {'from_pack': fields.integer(string='From p.'),
4983 'to_pack': fields.integer(string='To p.'),4983 'to_pack': fields.integer(string='To p.'),
4984 'pack_type': fields.many2one('pack.type', string='Pack Type'),4984 'pack_type': fields.many2one('pack.type', string='Pack Type'),
4985 'length' : fields.float(digits=(16, 2), string='Length [cm]'),4985 'length': fields.float(digits=(16, 2), string='Length [cm]'),
4986 'width' : fields.float(digits=(16, 2), string='Width [cm]'),4986 'width': fields.float(digits=(16, 2), string='Width [cm]'),
4987 'height' : fields.float(digits=(16, 2), string='Height [cm]'),4987 'height': fields.float(digits=(16, 2), string='Height [cm]'),
4988 'weight' : fields.float(digits=(16, 2), string='Weight p.p [kg]'),4988 'weight': fields.float(digits=(16, 2), string='Weight p.p [kg]'),
4989 # 'pack_family_id': fields.many2one('pack.family', string='Pack Family'),4989 # 'pack_family_id': fields.many2one('pack.family', string='Pack Family'),
4990 'initial_location': fields.many2one('stock.location', string='Initial Picking Location'),4990 'initial_location': fields.many2one('stock.location', string='Initial Picking Location'),
4991 # relation to the corresponding move from draft **picking** ticket object4991 # relation to the corresponding move from draft **picking** ticket object
@@ -5015,7 +5015,7 @@
5015 'stock.move': (lambda obj, cr, uid, ids, c={}: ids, ['picking_id'], 10),5015 'stock.move': (lambda obj, cr, uid, ids, c={}: ids, ['picking_id'], 10),
5016 'stock.picking': (_get_picking, ['shipment_id'], 10),5016 'stock.picking': (_get_picking, ['shipment_id'], 10),
5017 }5017 }
5018 ), 5018 ),
5019 # Fields used for domain5019 # Fields used for domain
5020 'location_virtual_id': fields.many2one('stock.location', string='Virtual location'),5020 'location_virtual_id': fields.many2one('stock.location', string='Virtual location'),
5021 'location_output_id': fields.many2one('stock.location', string='Output location'),5021 'location_output_id': fields.many2one('stock.location', string='Output location'),
@@ -5090,26 +5090,6 @@
5090 signal = 'cancel_r' if resource else 'cancel'5090 signal = 'cancel_r' if resource else 'cancel'
5091 wf_service.trg_validate(uid, 'purchase.order.line', move.purchase_line_id.id, signal, cr)5091 wf_service.trg_validate(uid, 'purchase.order.line', move.purchase_line_id.id, signal, cr)
50925092
5093 not_done_moves = self.pool.get('stock.move').search(cr, uid, [
5094 ('purchase_line_id', '=', move.purchase_line_id.id),
5095 ('state', 'not in', ['cancel', 'cancel_r', 'done']),
5096 ('picking_id.type', '=', 'in'),
5097 ], context=context)
5098 if (not not_done_moves) or all([x in ids for x in not_done_moves]):
5099 # all in lines processed or will be processed for this po line
5100 wf_service.trg_validate(uid, 'purchase.order.line', move.purchase_line_id.id, 'done', cr)
5101
5102 if move.purchase_line_id.is_line_split and move.purchase_line_id.original_line_id:
5103 # check if the original PO line can be set to done
5104 not_done_moves = self.pool.get('stock.move').search(cr, uid, [
5105 ('purchase_line_id', '=', move.purchase_line_id.original_line_id.id),
5106 ('state', 'not in', ['cancel', 'cancel_r', 'done']),
5107 ('picking_id.type', '=', 'in'),
5108 ], context=context)
5109 if (not not_done_moves) or all([x in ids for x in not_done_moves]):
5110 # all in lines processed or will be processed for this po line
5111 wf_service.trg_validate(uid, 'purchase.order.line', move.purchase_line_id.original_line_id.id, 'done', cr)
5112
5113 sol_ids = pol_obj.get_sol_ids_from_pol_ids(cr, uid, [move.purchase_line_id.id], context=context)5093 sol_ids = pol_obj.get_sol_ids_from_pol_ids(cr, uid, [move.purchase_line_id.id], context=context)
5114 for sol in sol_obj.browse(cr, uid, sol_ids, context=context):5094 for sol in sol_obj.browse(cr, uid, sol_ids, context=context):
5115 # If the line will be sourced in another way, do not cancel the OUT move5095 # If the line will be sourced in another way, do not cancel the OUT move
@@ -5118,15 +5098,15 @@
5118 continue5098 continue
51195099
5120 diff_qty = uom_obj._compute_qty(cr, uid, move.product_uom.id, move.product_qty, sol.product_uom.id)5100 diff_qty = uom_obj._compute_qty(cr, uid, move.product_uom.id, move.product_qty, sol.product_uom.id)
5121 if move.picking_id.partner_id2.partner_type not in ['internal','section','intermission']:5101 if move.picking_id.partner_id2.partner_type not in ['internal', 'section', 'intermission']:
5122 sol_obj.update_or_cancel_line(cr, uid, sol.id, diff_qty, resource=resource,context=context)5102 sol_obj.update_or_cancel_line(cr, uid, sol.id, diff_qty, resource=resource, context=context)
5123 # Cancel the remaining OUT line5103 # Cancel the remaining OUT line
5124 if diff_qty < sol.product_uom_qty:5104 if diff_qty < sol.product_uom_qty:
5125 data_back = self.create_data_back(move)5105 data_back = self.create_data_back(move)
5126 out_move = self.get_mirror_move(cr, uid, [move.id], data_back, context=context)[move.id]5106 out_move = self.get_mirror_move(cr, uid, [move.id], data_back, context=context)[move.id]
5127 out_move_id = False5107 out_move_id = False
5128 if out_move['moves']:5108 if out_move['moves']:
5129 out_move_id = sorted(out_move['moves'], key=lambda x: abs(x.product_qty-diff_qty))[0].id5109 out_move_id = sorted(out_move['moves'], key=lambda x: abs(x.product_qty - diff_qty))[0].id
5130 elif out_move['move_id']:5110 elif out_move['move_id']:
5131 out_move_id = out_move['move_id']5111 out_move_id = out_move['move_id']
51325112
@@ -5134,6 +5114,26 @@
5134 context.setdefault('not_resource_move', []).append(out_move_id)5114 context.setdefault('not_resource_move', []).append(out_move_id)
5135 self.action_cancel(cr, uid, [out_move_id], context=context)5115 self.action_cancel(cr, uid, [out_move_id], context=context)
51365116
5117 not_done_moves = self.pool.get('stock.move').search(cr, uid, [
5118 ('purchase_line_id', '=', move.purchase_line_id.id),
5119 ('state', 'not in', ['cancel', 'cancel_r', 'done']),
5120 ('picking_id.type', '=', 'in'),
5121 ], context=context)
5122 if (not not_done_moves) or all([x in ids for x in not_done_moves]):
5123 # all in lines processed or will be processed for this po line
5124 wf_service.trg_validate(uid, 'purchase.order.line', move.purchase_line_id.id, 'done', cr)
5125
5126 if move.purchase_line_id.is_line_split and move.purchase_line_id.original_line_id:
5127 # check if the original PO line can be set to done
5128 not_done_moves = self.pool.get('stock.move').search(cr, uid, [
5129 ('purchase_line_id', '=', move.purchase_line_id.original_line_id.id),
5130 ('state', 'not in', ['cancel', 'cancel_r', 'done']),
5131 ('picking_id.type', '=', 'in'),
5132 ], context=context)
5133 if (not not_done_moves) or all([x in ids for x in not_done_moves]):
5134 # all in lines processed or will be processed for this po line
5135 wf_service.trg_validate(uid, 'purchase.order.line', move.purchase_line_id.original_line_id.id, 'done', cr)
5136
5137 self.pool.get('purchase.order.line').update_fo_lines(cr, uid, [move.purchase_line_id.id], context=context)5137 self.pool.get('purchase.order.line').update_fo_lines(cr, uid, [move.purchase_line_id.id], context=context)
51385138
5139 elif move.sale_line_id and (pick_type == 'internal' or (pick_type == 'out' and subtype_ok)):5139 elif move.sale_line_id and (pick_type == 'internal' or (pick_type == 'out' and subtype_ok)):
@@ -5306,10 +5306,10 @@
5306 'from_pack': fields.integer(string='From p.'),5306 'from_pack': fields.integer(string='From p.'),
5307 'to_pack': fields.integer(string='To p.'),5307 'to_pack': fields.integer(string='To p.'),
5308 'pack_type': fields.many2one('pack.type', string='Pack Type'),5308 'pack_type': fields.many2one('pack.type', string='Pack Type'),
5309 'length' : fields.float(digits=(16, 2), string='Length [cm]'),5309 'length': fields.float(digits=(16, 2), string='Length [cm]'),
5310 'width' : fields.float(digits=(16, 2), string='Width [cm]'),5310 'width': fields.float(digits=(16, 2), string='Width [cm]'),
5311 'height' : fields.float(digits=(16, 2), string='Height [cm]'),5311 'height': fields.float(digits=(16, 2), string='Height [cm]'),
5312 'weight' : fields.float(digits=(16, 2), string='Weight p.p [kg]'),5312 'weight': fields.float(digits=(16, 2), string='Weight p.p [kg]'),
5313 # functions5313 # functions
5314 'move_lines': fields.function(_vals_get, method=True, type='one2many', relation='stock.move', string='Stock Moves', multi='get_vals',),5314 'move_lines': fields.function(_vals_get, method=True, type='one2many', relation='stock.move', string='Stock Moves', multi='get_vals',),
5315 'fake_state': fields.function(_vals_get, method=True, type='char', String='Fake state', multi='get_vals'),5315 'fake_state': fields.function(_vals_get, method=True, type='char', String='Fake state', multi='get_vals'),
53165316
=== modified file 'bin/addons/msf_outgoing/report/labels.rml'
--- bin/addons/msf_outgoing/report/labels.rml 2017-04-24 13:16:28 +0000
+++ bin/addons/msf_outgoing/report/labels.rml 2018-02-12 10:19:50 +0000
@@ -137,7 +137,7 @@
137 <para style="P4">[[ stock_picking.ppl_customize_label.weight and translate('Weight:') or ' ' ]]</para>137 <para style="P4">[[ stock_picking.ppl_customize_label.weight and translate('Weight:') or ' ' ]]</para>
138 </td>138 </td>
139 <td>139 <td>
140 <para style="P3">[[ stock_picking.ppl_customize_label.weight and str(pack_family.weight or '0.0') + ' kg' or ' ' ]]</para>140 <para style="P3">[[ stock_picking.ppl_customize_label.weight and str(stock_picking.total_weight or '0.0') + ' kg' or ' ' ]]</para>
141 </td>141 </td>
142 </tr>142 </tr>
143 <tr>143 <tr>
144144
=== modified file 'bin/addons/msf_profile/i18n/fr_MF.po'
--- bin/addons/msf_profile/i18n/fr_MF.po 2017-12-12 10:23:48 +0000
+++ bin/addons/msf_profile/i18n/fr_MF.po 2018-02-12 10:19:50 +0000
@@ -101136,3 +101136,22 @@
101136#, python-format101136#, python-format
101137msgid "You must select at least one currency of transfers."101137msgid "You must select at least one currency of transfers."
101138msgstr "Vous devez sélectionner au moins une devise de virement."101138msgstr "Vous devez sélectionner au moins une devise de virement."
101139
101140#. module: account_corrections
101141#: code:addons/account_corrections/account_move_line.py:567
101142#, python-format
101143msgid "No OD-Extra Accounting Analytic Journal found!"
101144msgstr "Aucun Journal Analytique de type OD-Extra Accounting n'a été trouvé !"
101145
101146#. module: register_accounting
101147#: code:addons/register_accounting/wizard/wizard_register_import.py:490
101148#, python-format
101149msgid "Line %s. Third Party %s not found or not compatible with the Type for specific treatment of the account '%s - %s'."
101150msgstr "Ligne %s. Tiers %s non trouvé ou non compatible avec le Type pour traitement spécifique du compte '%s - %s'."
101151
101152#. modules: purchase, sale
101153#: code:addons/purchase/purchase_workflow.py:413
101154#: code:addons/sale/sale_workflow.py:491
101155#, python-format
101156msgid "You can't use taxes with an intermission partner."
101157msgstr "Vous ne pouvez pas utiliser de taxes avec un partenaire intermission."
101139101158
=== modified file 'bin/addons/msf_supply_doc_export/wizard/po_follow_up.py'
--- bin/addons/msf_supply_doc_export/wizard/po_follow_up.py 2016-01-29 15:34:00 +0000
+++ bin/addons/msf_supply_doc_export/wizard/po_follow_up.py 2018-02-12 10:19:50 +0000
@@ -22,7 +22,7 @@
22from osv import osv22from osv import osv
23from osv import fields23from osv import fields
24from tools.translate import _24from tools.translate import _
25from lxml import etree25from urllib import quote_plus
2626
27import time27import time
28from datetime import datetime28from datetime import datetime
@@ -42,116 +42,116 @@
42 _description = 'PO Follow up report wizard'42 _description = 'PO Follow up report wizard'
4343
44 _columns = {44 _columns = {
45 'po_id':fields.many2one('purchase.order',string="Order Reference", help="Unique number of the Purchase Order. Optional", required=False),45 'po_id': fields.many2one('purchase.order', string="Order Reference", help="Unique number of the Purchase Order. Optional", required=False),
46 'state': fields.selection(PURCHASE_ORDER_STATE_SELECTION, 'State', help="The state of the purchase order. Optional", select=True, required=False),46 'state': fields.selection(PURCHASE_ORDER_STATE_SELECTION, 'State', help="The state of the purchase order. Optional", select=True, required=False),
47 'po_date_from':fields.date("PO date from", required="False"),47 'po_date_from': fields.date("PO date from", required="False"),
48 'po_date_thru':fields.date("PO date to", required="False"),48 'po_date_thru': fields.date("PO date to", required="False"),
49 'partner_id':fields.many2one('res.partner', 'Supplier', required=False),49 'partner_id': fields.many2one('res.partner', 'Supplier', required=False),
50 'project_ref':fields.char('Supplier reference', size=64, required=False),50 'project_ref': fields.char('Supplier reference', size=64, required=False),
51 'export_format': fields.selection([('xls', 'Excel'), ('pdf', 'PDF')], string="Export format", required=True), 51 'export_format': fields.selection([('xls', 'Excel'), ('pdf', 'PDF')], string="Export format", required=True),
52 'background_time': fields.integer('Number of second before background processing'),52 'background_time': fields.integer('Number of second before background processing'),
53 }53 }
54 54
55 _defaults = {55 _defaults = {
56 'export_format': lambda *a: 'xls',56 'export_format': lambda *a: 'xls',
57 'background_time': lambda *a: 20,57 'background_time': lambda *a: 20,
58 }58 }
59 59
60 def button_validate(self, cr, uid, ids, context=None):60 def button_validate(self, cr, uid, ids, context=None):
61 wiz = self.browse(cr,uid,ids)[0]61 wiz = self.browse(cr, uid, ids)[0]
6262
63 domain = [('rfq_ok', '=', False)]63 domain = [('rfq_ok', '=', False)]
64 states = {}64 states = {}
65 for state_val, state_string in PURCHASE_ORDER_STATE_SELECTION:65 for state_val, state_string in PURCHASE_ORDER_STATE_SELECTION:
66 states[state_val] = state_string66 states[state_val] = state_string
67 report_parms = {67 report_parms = {
68 'title': 'PO Follow Up per Supplier',68 'title': 'PO Follow Up per Supplier',
69 'run_date': time.strftime("%d/%m/%Y"),69 'run_date': time.strftime("%d/%m/%Y"),
70 'date_from': '',70 'date_from': '',
71 'date_thru': '',71 'date_thru': '',
72 'state': '',72 'state': '',
73 'supplier':''73 'supplier': ''
74 }74 }
75 75
76 # PO number76 # PO number
77 if wiz.po_id:77 if wiz.po_id:
78 domain.append(('id','=', wiz.po_id.id))78 domain.append(('id', '=', wiz.po_id.id))
79 79
80 # Status80 # Status
81 if wiz.state:81 if wiz.state:
82 domain.append(('state','=', wiz.state))82 domain.append(('state', '=', wiz.state))
83 report_parms['state'] = states[wiz.state]83 report_parms['state'] = states[wiz.state]
84 84
85 # Dates85 # Dates
86 if wiz.po_date_from:86 if wiz.po_date_from:
87 domain.append(('date_order','>=',wiz.po_date_from))87 domain.append(('date_order', '>=', wiz.po_date_from))
88 tmp = datetime.strptime(wiz.po_date_from,"%Y-%m-%d")88 tmp = datetime.strptime(wiz.po_date_from, "%Y-%m-%d")
89 report_parms['date_from'] = tmp.strftime("%d/%m/%Y")89 report_parms['date_from'] = tmp.strftime("%d/%m/%Y")
9090
91 if wiz.po_date_thru:91 if wiz.po_date_thru:
92 domain.append(('date_order','<=',wiz.po_date_thru))92 domain.append(('date_order', '<=', wiz.po_date_thru))
93 tmp = datetime.strptime(wiz.po_date_thru,"%Y-%m-%d")93 tmp = datetime.strptime(wiz.po_date_thru, "%Y-%m-%d")
94 report_parms['date_thru'] = tmp.strftime("%d/%m/%Y")94 report_parms['date_thru'] = tmp.strftime("%d/%m/%Y")
9595
96 # Supplier96 # Supplier
97 if wiz.partner_id:97 if wiz.partner_id:
98 domain.append(('partner_id','=', wiz.partner_id.id))98 domain.append(('partner_id', '=', wiz.partner_id.id))
99 report_parms['supplier'] = wiz.partner_id.name 99 report_parms['supplier'] = quote_plus(wiz.partner_id.name)
100 100
101 # Supplier Reference101 # Supplier Reference
102 if wiz.project_ref:102 if wiz.project_ref:
103 domain.append(('project_ref','like',wiz.project_ref))103 domain.append(('project_ref', 'like', wiz.project_ref))
104 104
105 # get the PO ids based on the selected criteria105 # get the PO ids based on the selected criteria
106 po_obj = self.pool.get('purchase.order')106 po_obj = self.pool.get('purchase.order')
107 po_ids = po_obj.search(cr, uid, domain)107 po_ids = po_obj.search(cr, uid, domain)
108 108
109 if not po_ids:109 if not po_ids:
110 raise osv.except_osv(_('Error'), _('No Purchase Orders match the specified criteria.'))110 raise osv.except_osv(_('Error'), _('No Purchase Orders match the specified criteria.'))
111 return True111 return True
112 112
113 report_header = []113 report_header = []
114 report_header.append(report_parms['title'])114 report_header.append(report_parms['title'])
115 115
116 report_header_line2 = ''116 report_header_line2 = ''
117 if wiz.partner_id:117 if wiz.partner_id:
118 report_header_line2 += wiz.partner_id.name118 report_header_line2 += wiz.partner_id.name
119 report_header_line2 += ' Report run date: ' + time.strftime("%d/%m/%Y") #TODO to be removed119 report_header_line2 += ' Report run date: ' + time.strftime("%d/%m/%Y") # TODO to be removed
120 if wiz.po_date_from:120 if wiz.po_date_from:
121 report_header_line2 += wiz.po_date_from121 report_header_line2 += wiz.po_date_from
122 #UF-2496: Minor fix to append the "date from" correctly into header122 # UF-2496: Minor fix to append the "date from" correctly into header
123 if wiz.po_date_thru:123 if wiz.po_date_thru:
124 if wiz.po_date_from:124 if wiz.po_date_from:
125 report_header_line2 += ' - '125 report_header_line2 += ' - '
126 report_header_line2 += wiz.po_date_thru126 report_header_line2 += wiz.po_date_thru
127 report_header.append(report_header_line2)127 report_header.append(quote_plus(report_header_line2))
128 128
129 datas = {'ids': po_ids, 'report_header': report_header, 'report_parms': report_parms} 129 datas = {'ids': po_ids, 'report_header': report_header, 'report_parms': report_parms}
130 if wiz.export_format == 'xls':130 if wiz.export_format == 'xls':
131 report_name = 'po.follow.up_xls'131 report_name = 'po.follow.up_xls'
132 else:132 else:
133 report_name = 'po.follow.up_rml'133 report_name = 'po.follow.up_rml'
134 134
135 if wiz.po_date_from:135 if wiz.po_date_from:
136 domain.append(('date_order','>=',wiz.po_date_from))136 domain.append(('date_order', '>=', wiz.po_date_from))
137 137
138 background_id = self.pool.get('memory.background.report').create(cr, uid, {'file_name': report_name, 'report_name': report_name}, context=context)138 background_id = self.pool.get('memory.background.report').create(cr, uid, {'file_name': report_name, 'report_name': report_name}, context=context)
139 context['background_id'] = background_id139 context['background_id'] = background_id
140 context['background_time'] = wiz.background_time140 context['background_time'] = wiz.background_time
141 141
142 return { 142 return {
143 'type': 'ir.actions.report.xml', 143 'type': 'ir.actions.report.xml',
144 'report_name': report_name, 144 'report_name': report_name,
145 'datas': datas, 145 'datas': datas,
146 'nodestroy': True, 146 'nodestroy': True,
147 'context': context, 147 'context': context,
148 }148 }
149 149
150po_follow_up()150po_follow_up()
151151
152152
153# already defined in account_mcdb/wizard/output_currency_for_export.py153# already defined in account_mcdb/wizard/output_currency_for_export.py
154#class background_report(osv.osv_memory):154# class background_report(osv.osv_memory):
155# _name = 'memory.background.report'155# _name = 'memory.background.report'
156# _description = 'Report result'156# _description = 'Report result'
157#157#
@@ -164,4 +164,4 @@
164# }164# }
165# def update_percent(self, cr, uid, ids, percent, context=None):165# def update_percent(self, cr, uid, ids, percent, context=None):
166# self.write(cr, uid, ids, {'percent': percent})166# self.write(cr, uid, ids, {'percent': percent})
167#background_report()167# background_report()
168168
=== modified file 'bin/addons/purchase/purchase_workflow.py'
--- bin/addons/purchase/purchase_workflow.py 2017-12-14 17:30:55 +0000
+++ bin/addons/purchase/purchase_workflow.py 2018-02-12 10:19:50 +0000
@@ -49,7 +49,7 @@
49 '''49 '''
50 if context is None:50 if context is None:
51 context = {}51 context = {}
52 if isinstance(ids, (int,long)):52 if isinstance(ids, (int, long)):
53 ids = [ids]53 ids = [ids]
5454
55 for pol in self.browse(cr, uid, ids, context=context):55 for pol in self.browse(cr, uid, ids, context=context):
@@ -73,7 +73,7 @@
73 domain = [('purchase_line_id', '=', pol.id), ('type', '=', 'in'), ('state', '=', 'assigned')]73 domain = [('purchase_line_id', '=', pol.id), ('type', '=', 'in'), ('state', '=', 'assigned')]
74 linked_in_move = self.pool.get('stock.move').search(cr, uid, domain, context=context)74 linked_in_move = self.pool.get('stock.move').search(cr, uid, domain, context=context)
75 if linked_in_move:75 if linked_in_move:
76 self.pool.get('stock.move').action_cancel(cr, uid, linked_in_move, context=context) 76 self.pool.get('stock.move').action_cancel(cr, uid, linked_in_move, context=context)
7777
78 return True78 return True
7979
@@ -84,7 +84,7 @@
84 '''84 '''
85 if context is None:85 if context is None:
86 context = {}86 context = {}
87 if isinstance(ids, (int,long)):87 if isinstance(ids, (int, long)):
88 ids = [ids]88 ids = [ids]
8989
90 for pol in self.browse(cr, uid, ids, fields_to_fetch=['price_unit'], context=context):90 for pol in self.browse(cr, uid, ids, fields_to_fetch=['price_unit'], context=context):
@@ -99,7 +99,7 @@
99 '''99 '''
100 if context is None:100 if context is None:
101 context = {}101 context = {}
102 if isinstance(ids, (int,long)):102 if isinstance(ids, (int, long)):
103 ids = [ids]103 ids = [ids]
104104
105 for pol in self.browse(cr, uid, ids, context=context):105 for pol in self.browse(cr, uid, ids, context=context):
@@ -117,7 +117,7 @@
117 ], context=context)117 ], context=context)
118 so_id = so_id and so_id[0] or False118 so_id = so_id and so_id[0] or False
119 if not so_id:119 if not so_id:
120 continue # no sale order linked to our PO line120 continue # no sale order linked to our PO line
121 sale_order = self.pool.get('sale.order').browse(cr, uid, so_id, context=context)121 sale_order = self.pool.get('sale.order').browse(cr, uid, so_id, context=context)
122 if sale_order.state == 'cancel' and sale_order.procurement_request:122 if sale_order.state == 'cancel' and sale_order.procurement_request:
123 to_trigger = True123 to_trigger = True
@@ -126,7 +126,7 @@
126 sale_order = pol.linked_sol_id.order_id126 sale_order = pol.linked_sol_id.order_id
127 else:127 else:
128 # case of PO line from scratch, nothing to update128 # case of PO line from scratch, nothing to update
129 continue 129 continue
130130
131 # convert from currency of pol to currency of sol131 # convert from currency of pol to currency of sol
132 price_unit_converted = self.pool.get('res.currency').compute(cr, uid, pol.currency_id.id, sale_order.currency_id.id, pol.price_unit or 0.0,132 price_unit_converted = self.pool.get('res.currency').compute(cr, uid, pol.currency_id.id, sale_order.currency_id.id, pol.price_unit or 0.0,
@@ -204,14 +204,14 @@
204 # the right OUT move (moves are already splits at this level):204 # the right OUT move (moves are already splits at this level):
205 if sol_values['is_line_split']:205 if sol_values['is_line_split']:
206 linked_out_moves = self.pool.get('stock.move').search(cr, uid, [206 linked_out_moves = self.pool.get('stock.move').search(cr, uid, [
207 ('sale_line_id', '=', sol_values['original_line_id']), 207 ('sale_line_id', '=', sol_values['original_line_id']),
208 ('type', '=', 'out')], 208 ('type', '=', 'out')],
209 context=context)209 context=context)
210 if len(linked_out_moves) > 1:210 if len(linked_out_moves) > 1:
211 for out_move in self.pool.get('stock.move').browse(cr, uid, linked_out_moves, context=context):211 for out_move in self.pool.get('stock.move').browse(cr, uid, linked_out_moves, context=context):
212 if out_move.state in ('assigned', 'confirmed') and out_move.product_qty == sol_values['product_uom_qty']:212 if out_move.state in ('assigned', 'confirmed') and out_move.product_qty == sol_values['product_uom_qty']:
213 self.pool.get('stock.move').write(cr, uid, [out_move.id], {'sale_line_id': new_sol}, context=context)213 self.pool.get('stock.move').write(cr, uid, [out_move.id], {'sale_line_id': new_sol}, context=context)
214 else: # update FO line214 else: # update FO line
215 self.pool.get('sale.order.line').write(cr, uid, [pol.linked_sol_id.id], sol_values, context=context)215 self.pool.get('sale.order.line').write(cr, uid, [pol.linked_sol_id.id], sol_values, context=context)
216216
217217
@@ -226,7 +226,7 @@
226 '''226 '''
227 if context is None:227 if context is None:
228 context = {}228 context = {}
229 if isinstance(ids, (int,long)):229 if isinstance(ids, (int, long)):
230 ids = [ids]230 ids = [ids]
231 if not fo_id:231 if not fo_id:
232 raise Exception, "No parent Sale Order given for the new Sale Order line"232 raise Exception, "No parent Sale Order given for the new Sale Order line"
@@ -305,10 +305,10 @@
305 '''305 '''
306 if context is None:306 if context is None:
307 context = {}307 context = {}
308 if isinstance(ids, (int,long)):308 if isinstance(ids, (int, long)):
309 ids = [ids]309 ids = [ids]
310 if not ids:310 if not ids:
311 raise Exception , "No PO line given"311 raise Exception, "No PO line given"
312312
313 # load common data into context:313 # load common data into context:
314 self.pool.get('data.tools').load_common_data(cr, uid, ids, context=context)314 self.pool.get('data.tools').load_common_data(cr, uid, ids, context=context)
@@ -332,7 +332,7 @@
332 pick_id = self.pool.get('stock.picking').create(cr, uid, pick_values, context=context)332 pick_id = self.pool.get('stock.picking').create(cr, uid, pick_values, context=context)
333333
334 # log picking creation334 # log picking creation
335 self.pool.get('stock.picking').log(cr, uid, pick_id, _('The new internal Picking %s has been created.')%name)335 self.pool.get('stock.picking').log(cr, uid, pick_id, _('The new internal Picking %s has been created.') % name)
336336
337 return pick_id337 return pick_id
338338
@@ -343,7 +343,7 @@
343 '''343 '''
344 if context is None:344 if context is None:
345 context = {}345 context = {}
346 if isinstance(ids, (int,long)):346 if isinstance(ids, (int, long)):
347 ids = [ids]347 ids = [ids]
348 wf_service = netsvc.LocalService("workflow")348 wf_service = netsvc.LocalService("workflow")
349349
@@ -383,7 +383,7 @@
383 '''383 '''
384 if context is None:384 if context is None:
385 context = {}385 context = {}
386 if isinstance(ids, (int,long)):386 if isinstance(ids, (int, long)):
387 ids = [ids]387 ids = [ids]
388 self.write(cr, uid, ids, {'state': 'validated_n'}, context=context)388 self.write(cr, uid, ids, {'state': 'validated_n'}, context=context)
389389
@@ -400,6 +400,17 @@
400400
401 return True401 return True
402402
403 def check_po_tax(self, cr, uid, ids, context=None):
404 """
405 Prevents from validating a PO with taxes when using an Intermission partner
406 """
407 if context is None:
408 context = {}
409 if isinstance(ids, (int, long)):
410 ids = [ids]
411 for po_line in self.browse(cr, uid, ids, fields_to_fetch=['order_id', 'taxes_id'], context=context):
412 if po_line.taxes_id and po_line.order_id.partner_type == 'intermission':
413 raise osv.except_osv(_('Error'), _("You can't use taxes with an intermission partner."))
403414
404 def action_validate(self, cr, uid, ids, context=None):415 def action_validate(self, cr, uid, ids, context=None):
405 '''416 '''
@@ -407,7 +418,7 @@
407 '''418 '''
408 if context is None:419 if context is None:
409 context = {}420 context = {}
410 if isinstance(ids, (int,long)):421 if isinstance(ids, (int, long)):
411 ids = [ids]422 ids = [ids]
412 wf_service = netsvc.LocalService("workflow")423 wf_service = netsvc.LocalService("workflow")
413424
@@ -415,6 +426,7 @@
415 self.check_analytic_distribution(cr, uid, ids, context=context)426 self.check_analytic_distribution(cr, uid, ids, context=context)
416 self.check_if_stock_take_date_with_esc_partner(cr, uid, ids, context=context)427 self.check_if_stock_take_date_with_esc_partner(cr, uid, ids, context=context)
417 self.check_unit_price(cr, uid, ids, context=context)428 self.check_unit_price(cr, uid, ids, context=context)
429 self.check_po_tax(cr, uid, ids, context=context)
418430
419 # update FO lines:431 # update FO lines:
420 self.update_fo_lines(cr, uid, ids, context=context)432 self.update_fo_lines(cr, uid, ids, context=context)
@@ -451,7 +463,7 @@
451 '''463 '''
452 if context is None:464 if context is None:
453 context = {}465 context = {}
454 if isinstance(ids, (int,long)):466 if isinstance(ids, (int, long)):
455 ids = [ids]467 ids = [ids]
456 wf_service = netsvc.LocalService("workflow")468 wf_service = netsvc.LocalService("workflow")
457469
@@ -472,13 +484,13 @@
472 '''484 '''
473 if context is None:485 if context is None:
474 context = {}486 context = {}
475 if isinstance(ids, (int,long)):487 if isinstance(ids, (int, long)):
476 ids = [ids]488 ids = [ids]
477 wf_service = netsvc.LocalService("workflow")489 wf_service = netsvc.LocalService("workflow")
478490
479 self.write(cr, uid, ids, {'state': 'sourced_v'}, context=context)491 self.write(cr, uid, ids, {'state': 'sourced_v'}, context=context)
480492
481 #update linked sol (same instance) to sourced-v (if has)493 # update linked sol (same instance) to sourced-v (if has)
482 for po in self.browse(cr, uid, ids, context=context):494 for po in self.browse(cr, uid, ids, context=context):
483 if po.linked_sol_id:495 if po.linked_sol_id:
484 wf_service.trg_validate(uid, 'sale.order.line', po.linked_sol_id.id, 'sourced_v', cr)496 wf_service.trg_validate(uid, 'sale.order.line', po.linked_sol_id.id, 'sourced_v', cr)
@@ -492,7 +504,7 @@
492 '''504 '''
493 if context is None:505 if context is None:
494 context = {}506 context = {}
495 if isinstance(ids, (int,long)):507 if isinstance(ids, (int, long)):
496 ids = [ids]508 ids = [ids]
497509
498 self.write(cr, uid, ids, {'state': 'sourced_n'}, context=context)510 self.write(cr, uid, ids, {'state': 'sourced_n'}, context=context)
@@ -547,9 +559,9 @@
547 self.pool.get('stock.move').in_action_confirm(cr, uid, incoming_move_id, context)559 self.pool.get('stock.move').in_action_confirm(cr, uid, incoming_move_id, context)
548560
549 # create internal moves (INT):561 # create internal moves (INT):
550 if pol.order_id.location_id.input_ok and pol.product_id.type not in ('service_recep', 'consu'): 562 if pol.order_id.location_id.input_ok and pol.product_id.type not in ('service_recep', 'consu'):
551 internal_pick = self.pool.get('stock.picking').search(cr, uid, [563 internal_pick = self.pool.get('stock.picking').search(cr, uid, [
552 ('type', '=', 'internal'), 564 ('type', '=', 'internal'),
553 ('purchase_id', '=', pol.order_id.id),565 ('purchase_id', '=', pol.order_id.id),
554 ('state', 'not in', ['done', 'cancel']),566 ('state', 'not in', ['done', 'cancel']),
555 ], context=context)567 ], context=context)
@@ -604,7 +616,7 @@
604 '''616 '''
605 if context is None:617 if context is None:
606 context = {}618 context = {}
607 if isinstance(ids, (int,long)):619 if isinstance(ids, (int, long)):
608 ids = [ids]620 ids = [ids]
609 wf_service = netsvc.LocalService("workflow")621 wf_service = netsvc.LocalService("workflow")
610622
@@ -613,8 +625,8 @@
613625
614 for pol in self.browse(cr, uid, ids, context=context):626 for pol in self.browse(cr, uid, ids, context=context):
615 # no PICK/OUT needed in this cases; close SO line:627 # no PICK/OUT needed in this cases; close SO line:
616 internal_ir = pol.linked_sol_id and pol.linked_sol_id.order_id.procurement_request and pol.linked_sol_id.order_id.location_requestor_id.usage == 'internal' or False # PO line from Internal IR628 internal_ir = pol.linked_sol_id and pol.linked_sol_id.order_id.procurement_request and pol.linked_sol_id.order_id.location_requestor_id.usage == 'internal' or False # PO line from Internal IR
617 dpo = pol.order_id.order_type == 'direct' or False # direct PO629 dpo = pol.order_id.order_type == 'direct' or False # direct PO
618 ir_non_stockable = pol.linked_sol_id and pol.linked_sol_id.order_id.procurement_request and pol.linked_sol_id.product_id.type in ('consu', 'service', 'service_recep') or False630 ir_non_stockable = pol.linked_sol_id and pol.linked_sol_id.order_id.procurement_request and pol.linked_sol_id.product_id.type in ('consu', 'service', 'service_recep') or False
619631
620 if internal_ir or dpo or ir_non_stockable:632 if internal_ir or dpo or ir_non_stockable:
@@ -700,7 +712,7 @@
700 """712 """
701 if context is None:713 if context is None:
702 context = {}714 context = {}
703 if isinstance(ids, (int,long)):715 if isinstance(ids, (int, long)):
704 ids = [ids]716 ids = [ids]
705717
706 for po in self.browse(cr, uid, ids, context=context):718 for po in self.browse(cr, uid, ids, context=context):
@@ -715,7 +727,7 @@
715 '''727 '''
716 if context is None:728 if context is None:
717 context = {}729 context = {}
718 if isinstance(ids, (int,long)):730 if isinstance(ids, (int, long)):
719 ids = [ids]731 ids = [ids]
720 wf_service = netsvc.LocalService("workflow")732 wf_service = netsvc.LocalService("workflow")
721733
722734
=== modified file 'bin/addons/register_accounting/report/fully_report_xls.mako'
--- bin/addons/register_accounting/report/fully_report_xls.mako 2017-09-26 11:57:14 +0000
+++ bin/addons/register_accounting/report/fully_report_xls.mako 2018-02-12 10:19:50 +0000
@@ -904,8 +904,16 @@
904<!-- Display analytic lines linked to this register line -->904<!-- Display analytic lines linked to this register line -->
905<%905<%
906a_lines = False906a_lines = False
907adv_return_aal = line.cash_return_move_line_id and line.cash_return_move_line_id.analytic_lines or []
908adv_return_fp_lines = []
909adv_return_free_lines = []
910for adv_return_l in adv_return_aal:
911 if adv_return_l.free_account:
912 adv_return_free_lines.append(adv_return_l)
913 else:
914 adv_return_fp_lines.append(adv_return_l)
907if line.fp_analytic_lines and not line.invoice_id and not line.imported_invoice_line_ids:915if line.fp_analytic_lines and not line.invoice_id and not line.imported_invoice_line_ids:
908 a_lines = line.cash_return_move_line_id and line.cash_return_move_line_id.analytic_lines or line.fp_analytic_lines916 a_lines = adv_return_fp_lines or line.fp_analytic_lines
909%>917%>
910% if a_lines:918% if a_lines:
911% for ana_line in sorted(a_lines, key=lambda x: x.id):919% for ana_line in sorted(a_lines, key=lambda x: x.id):
@@ -964,7 +972,7 @@
964<%972<%
965a_lines = False973a_lines = False
966if line.free_analytic_lines and not line.invoice_id and not line.imported_invoice_line_ids:974if line.free_analytic_lines and not line.invoice_id and not line.imported_invoice_line_ids:
967 a_lines = line.free_analytic_lines975 a_lines = adv_return_free_lines or line.free_analytic_lines
968%>976%>
969% if a_lines:977% if a_lines:
970% for ana_line in sorted(a_lines, key=lambda x: x.id):978% for ana_line in sorted(a_lines, key=lambda x: x.id):
971979
=== modified file 'bin/addons/register_accounting/wizard/import_invoice_on_registers.py'
--- bin/addons/register_accounting/wizard/import_invoice_on_registers.py 2017-06-06 09:58:17 +0000
+++ bin/addons/register_accounting/wizard/import_invoice_on_registers.py 2018-02-12 10:19:50 +0000
@@ -244,7 +244,8 @@
244244
245 # Create register line245 # Create register line
246 partial = False246 partial = False
247 if line.amount and line.amount_to_pay and line.amount < abs(line.amount_to_pay):247 equal_amounts = abs(abs(line.amount) - abs(line.amount_to_pay)) <= 10**-3
248 if not equal_amounts and line.amount < abs(line.amount_to_pay):
248 partial = ' - ' + _('partial pymt')249 partial = ' - ' + _('partial pymt')
249 ref = line.ref250 ref = line.ref
250 if not ref or ref == 'false':251 if not ref or ref == 'false':
251252
=== modified file 'bin/addons/register_accounting/wizard/wizard_register_import.py'
--- bin/addons/register_accounting/wizard/wizard_register_import.py 2017-04-19 13:19:37 +0000
+++ bin/addons/register_accounting/wizard/wizard_register_import.py 2018-02-12 10:19:50 +0000
@@ -61,9 +61,9 @@
61 if not context:61 if not context:
62 context = {}62 context = {}
63 view = super(wizard_register_import, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu)63 view = super(wizard_register_import, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu)
64 if view_type=='form':64 if view_type == 'form':
65 form = etree.fromstring(view['arch'])65 form = etree.fromstring(view['arch'])
66 for el in [('document_date', 'Document Date'), ('posting_date', 'Posting Date'), ('cheque_number', 'Cheque Number'), ('description', 'Description'), ('reference', 'Reference'), ('account', 'Account'), ('third_party', 'Third Party'), ('amount_in', 'Amount In'), ('amount_out', 'Amount Out'), ('destination', 'Destination'), ('cost_center', 'Cost Centre'), ('funding_pool', 'Funding Pool'), ('proprietary_instance', "Proprietary instance's code"), ('journal', "Journal's code"), ('currency', "Currency's code"),('free1', "Free 1"),('free2', "Free 2")]:66 for el in [('document_date', 'Document Date'), ('posting_date', 'Posting Date'), ('cheque_number', 'Cheque Number'), ('description', 'Description'), ('reference', 'Reference'), ('account', 'Account'), ('third_party', 'Third Party'), ('amount_in', 'Amount In'), ('amount_out', 'Amount Out'), ('destination', 'Destination'), ('cost_center', 'Cost Centre'), ('funding_pool', 'Funding Pool'), ('proprietary_instance', "Proprietary instance's code"), ('journal', "Journal's code"), ('currency', "Currency's code"), ('free1', "Free 1"), ('free2', "Free 2")]:
67 fields = form.xpath('/form//th[@class="' + el[0] + '"]')67 fields = form.xpath('/form//th[@class="' + el[0] + '"]')
68 for field in fields:68 for field in fields:
69 field.text = _(el[1])69 field.text = _(el[1])
@@ -149,20 +149,20 @@
149 currency_id = l.get('currency_id', False) and l.get('currency_id')[0] or False149 currency_id = l.get('currency_id', False) and l.get('currency_id')[0] or False
150 account = account_obj.read(cr, uid, account_id, ['is_analytic_addicted'])150 account = account_obj.read(cr, uid, account_id, ['is_analytic_addicted'])
151 cheque_number = l.get('cheque_number')151 cheque_number = l.get('cheque_number')
152 free_1_id = l.get('free_1_id',False) and l.get('free_1_id')[0] or False152 free_1_id = l.get('free_1_id', False) and l.get('free_1_id')[0] or False
153 free_2_id = l.get('free_2_id',False) and l.get('free_2_id')[0] or False153 free_2_id = l.get('free_2_id', False) and l.get('free_2_id')[0] or False
154154
155 vals = {155 vals = {
156 'name': l.get('description', ''),156 'name': l.get('description', ''),
157 'ref': l.get('ref', ''),157 'ref': l.get('ref', ''),
158 'document_date': l.get('document_date', False),158 'document_date': l.get('document_date', False),
159 'date': date,159 'date': date,
160 'account_id': account_id,160 'account_id': account_id,
161 'amount': l.get('debit', 0.0) - l.get('credit', 0.0),161 'amount': l.get('debit', 0.0) - l.get('credit', 0.0),
162 'partner_id': partner_id,162 'partner_id': partner_id,
163 'employee_id': employee_id,163 'employee_id': employee_id,
164 'transfer_journal_id': transfer_journal_id,164 'transfer_journal_id': transfer_journal_id,
165 'statement_id': register_id,165 'statement_id': register_id,
166 }166 }
167 if cheque_number:167 if cheque_number:
168 vals['cheque_number'] = str(cheque_number)168 vals['cheque_number'] = str(cheque_number)
@@ -182,21 +182,21 @@
182 'source_date': date,182 'source_date': date,
183 'destination_id': destination_id,183 'destination_id': destination_id,
184 }184 }
185 common_vals.update({'analytic_id': cost_center_id,})185 common_vals.update({'analytic_id': cost_center_id, })
186 self.pool.get('cost.center.distribution.line').create(cr, uid, common_vals)186 self.pool.get('cost.center.distribution.line').create(cr, uid, common_vals)
187 common_vals.update({'analytic_id': funding_pool_id or msf_fp_id, 'cost_center_id': cost_center_id,})187 common_vals.update({'analytic_id': funding_pool_id or msf_fp_id, 'cost_center_id': cost_center_id, })
188 self.pool.get('funding.pool.distribution.line').create(cr, uid, common_vals)188 self.pool.get('funding.pool.distribution.line').create(cr, uid, common_vals)
189189
190 if free_1_id:190 if free_1_id:
191 common_vals.update({'analytic_id': free_1_id,})191 common_vals.update({'analytic_id': free_1_id, })
192 self.pool.get('free.1.distribution.line').create(cr,uid,common_vals)192 self.pool.get('free.1.distribution.line').create(cr, uid, common_vals)
193193
194 if free_2_id:194 if free_2_id:
195 common_vals.update({'analytic_id': free_2_id,})195 common_vals.update({'analytic_id': free_2_id, })
196 self.pool.get('free.2.distribution.line').create(cr,uid,common_vals)196 self.pool.get('free.2.distribution.line').create(cr, uid, common_vals)
197197
198 # Check analytic distribution. Use SKIP_WRITE_CHECK to not do anything else that writing analytic distribution field198 # Check analytic distribution. Use SKIP_WRITE_CHECK to not do anything else that writing analytic distribution field
199 absl_obj.write(cr, uid, [absl_id], {'analytic_distribution_id': distrib_id,}, context={'skip_write_check': True})199 absl_obj.write(cr, uid, [absl_id], {'analytic_distribution_id': distrib_id, }, context={'skip_write_check': True})
200 # Add this line to be check at the end of the process200 # Add this line to be check at the end of the process
201 to_check.append(absl_id)201 to_check.append(absl_id)
202 # Update wizard with current progression202 # Update wizard with current progression
@@ -212,7 +212,7 @@
212 to_delete.append(absl_data.get('id'))212 to_delete.append(absl_data.get('id'))
213 to_delete_distrib.append(absl_data.get('analytic_distribution_id', [False])[0])213 to_delete_distrib.append(absl_data.get('analytic_distribution_id', [False])[0])
214 # Delete analytic distribution field on register lines214 # Delete analytic distribution field on register lines
215 absl_obj.write(cr, uid, to_delete, {'analytic_distribution_id': False}, context={'skip_write_check': True}) # do not do anything else than changing analytic_distribution_id field content (thanks to SKIP_WRITE_CHECK)215 absl_obj.write(cr, uid, to_delete, {'analytic_distribution_id': False}, context={'skip_write_check': True}) # do not do anything else than changing analytic_distribution_id field content (thanks to SKIP_WRITE_CHECK)
216 # Delete analytic distribution216 # Delete analytic distribution
217 self.pool.get('analytic.distribution').unlink(cr, uid, to_delete_distrib, context)217 self.pool.get('analytic.distribution').unlink(cr, uid, to_delete_distrib, context)
218 return True218 return True
@@ -234,6 +234,9 @@
234 processed = 0234 processed = 0
235 errors = []235 errors = []
236 cheque_numbers = []236 cheque_numbers = []
237 employee_obj = self.pool.get('hr.employee')
238 journal_obj = self.pool.get('account.journal')
239 partner_obj = self.pool.get('res.partner')
237 try:240 try:
238 msf_fp_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution', 'analytic_account_msf_private_funds')[1]241 msf_fp_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution', 'analytic_account_msf_private_funds')[1]
239 except ValueError:242 except ValueError:
@@ -270,22 +273,22 @@
270 # cols variable describe each column and its expected number273 # cols variable describe each column and its expected number
271 cols = {274 cols = {
272 'document_date': 0,275 'document_date': 0,
273 'posting_date': 1,276 'posting_date': 1,
274 'cheque_number': 2,277 'cheque_number': 2,
275 'description': 3,278 'description': 3,
276 'reference': 4,279 'reference': 4,
277 'account': 5,280 'account': 5,
278 'third_party': 6,281 'third_party': 6,
279 'amount_in': 7,282 'amount_in': 7,
280 'amount_out': 8,283 'amount_out': 8,
281 'destination': 9,284 'destination': 9,
282 'cost_center': 10,285 'cost_center': 10,
283 'funding_pool': 11,286 'funding_pool': 11,
284 'free1': 12,287 'free1': 12,
285 'free2': 13,288 'free2': 13,
286 }289 }
287 # Number of line to bypass in line's count290 # Number of line to bypass in line's count
288 base_num = 5 # because of Python that begins to 0.291 base_num = 5 # because of Python that begins to 0.
289 # Attempt to read 3 first lines292 # Attempt to read 3 first lines
290 first_line = self.pool.get('import.cell.data').get_line_values(cr, uid, ids, rows.next())293 first_line = self.pool.get('import.cell.data').get_line_values(cr, uid, ids, rows.next())
291 try:294 try:
@@ -296,7 +299,7 @@
296 try:299 try:
297 journal_code = second_line[1]300 journal_code = second_line[1]
298 except IndexError, e:301 except IndexError, e:
299 raise osv.except_osv(_('Warning'), _('No journal code found.'))302 raise osv.except_osv(_('Warning'), _('No journal code found.'))
300 third_line = self.pool.get('import.cell.data').get_line_values(cr, uid, ids, rows.next())303 third_line = self.pool.get('import.cell.data').get_line_values(cr, uid, ids, rows.next())
301 try:304 try:
302 currency_code = third_line[1]305 currency_code = third_line[1]
@@ -309,7 +312,7 @@
309 if isinstance(instance_ids, (int, long)):312 if isinstance(instance_ids, (int, long)):
310 instance_ids = [instance_ids]313 instance_ids = [instance_ids]
311 # Check second info: journal's code314 # Check second info: journal's code
312 journal_ids = self.pool.get('account.journal').search(cr, uid, [('code', '=', journal_code)])315 journal_ids = journal_obj.search(cr, uid, [('code', '=', journal_code)])
313 if not journal_ids or len(journal_ids) > 1:316 if not journal_ids or len(journal_ids) > 1:
314 raise osv.except_osv(_('Warning'), _('Journal %s not found.') % (journal_code or '',))317 raise osv.except_osv(_('Warning'), _('Journal %s not found.') % (journal_code or '',))
315 if isinstance(journal_ids, (int, long)):318 if isinstance(journal_ids, (int, long)):
@@ -346,7 +349,7 @@
346 # Check file's content349 # Check file's content
347 for num, r in enumerate(rows):350 for num, r in enumerate(rows):
348 # Update wizard351 # Update wizard
349 progression = ((float(num+1) * remaining) / float(nb_rows)) + 6352 progression = ((float(num + 1) * remaining) / float(nb_rows)) + 6
350 self.write(cr, uid, [wiz.id], {'message': _('Checking file…'), 'progression': progression}, context)353 self.write(cr, uid, [wiz.id], {'message': _('Checking file…'), 'progression': progression}, context)
351 # Prepare some values354 # Prepare some values
352 r_debit = 0355 r_debit = 0
@@ -446,42 +449,62 @@
446 if register_type == 'cheque':449 if register_type == 'cheque':
447 if r_cheque_number:450 if r_cheque_number:
448 if r_cheque_number in cheque_numbers:451 if r_cheque_number in cheque_numbers:
449 errors.append(_('Line %s. Cheque number %s is duplicated from another line') % (current_line_num,r_cheque_number,))452 errors.append(_('Line %s. Cheque number %s is duplicated from another line') % (current_line_num, r_cheque_number,))
450 absl = self.pool.get('account.bank.statement.line')453 absl = self.pool.get('account.bank.statement.line')
451 cheque_number_id = absl.search(cr, uid, [('cheque_number','=',r_cheque_number)],context=context)454 cheque_number_id = absl.search(cr, uid, [('cheque_number', '=', r_cheque_number)], context=context)
452 if cheque_number_id:455 if cheque_number_id:
453 errors.append(_('Line %s. Cheque number %s has already been entered into the system.') % (current_line_num,r_cheque_number,))456 errors.append(_('Line %s. Cheque number %s has already been entered into the system.') % (current_line_num, r_cheque_number,))
454 cheque_numbers.append(r_cheque_number)457 cheque_numbers.append(r_cheque_number)
455 else:458 else:
456 errors.append(_('Line %s. Cheque number is missing') % (current_line_num,))459 errors.append(_('Line %s. Cheque number is missing') % (current_line_num,))
457 # Check that Third party exists (if not empty)460
461 # Check Account/Third Party compatibility regarding the Account "Type for specific treatment"
458 partner_type = 'partner'462 partner_type = 'partner'
459 if line[cols['third_party']]:463 tp_ids = []
460 if type_for_register == 'advance':464 has_specific_type = type_for_register in ['advance', 'transfer', 'transfer_same', 'down_payment', 'payroll'] or False
461 tp_ids = self.pool.get('hr.employee').search(cr, uid, [('name', '=', line[cols['third_party']])])465 if has_specific_type:
462 partner_type = 'employee'466 if line[cols['third_party']]:
463 elif type_for_register in ['transfer', 'transfer_same']:467 # Type Operational Advance ==> EMPLOYEE required
464 tp_ids = self.pool.get('account.journal').search(cr, uid, [('code', '=', line[cols['third_party']])])468 if type_for_register == 'advance':
465 if tp_ids:469 tp_ids = employee_obj.search(cr, uid, [('name', '=', line[cols['third_party']])], context=context)
470 partner_type = 'employee'
471 # Type Internal transfer ==> JOURNAL required
472 elif type_for_register in ['transfer', 'transfer_same']:
473 tp_ids = journal_obj.search(cr, uid, [('code', '=', line[cols['third_party']])], context=context)
466 partner_type = 'journal'474 partner_type = 'journal'
467 tp_journal = self.pool.get('account.journal').browse(cr, uid, tp_ids, context=context)[0]475 if tp_ids:
468 if type_for_register == 'transfer':476 tp_journal = journal_obj.browse(cr, uid, tp_ids, fields_to_fetch=['currency'], context=context)[0]
469 if tp_journal.currency.id == register_currency:477 if type_for_register == 'transfer':
470 errors.append(_('Line %s. A Transfer Journal must have a different currency than the register.') % (current_line_num,))478 if tp_journal.currency.id == register_currency:
471 if type_for_register == 'transfer_same':479 errors.append(_('Line %s. A Transfer Journal must have a different currency than the register.') % (current_line_num,))
472 if tp_journal.currency.id != register_currency:480 continue
473 errors.append(_('Line %s. A Transfer Same Journal must have the same currency as the register.') % (current_line_num,))481 if type_for_register == 'transfer_same':
474 else:482 if tp_journal.currency.id != register_currency:
475 tp_ids = self.pool.get('res.partner').search(cr, uid, [('name', '=', line[cols['third_party']])])483 errors.append(_('Line %s. A Transfer Same Journal must have the same currency as the register.') % (current_line_num,))
476 partner_type = 'partner'484 continue
477 if not tp_ids:485 # Type DP or payroll ==> PARTNER required
478 # Search now if employee exists486 elif type_for_register in ['down_payment', 'payroll']:
479 tp_ids = self.pool.get('hr.employee').search(cr, uid, [('name', '=', line[cols['third_party']])])487 tp_ids = partner_obj.search(cr, uid, [('name', '=', line[cols['third_party']])], context=context)
488 partner_type = 'partner'
489 # Any type for Spec. Treatment listed above ==> EMPTY partner NOT allowed
490 if not tp_ids:
491 errors.append(
492 _("Line %s. Third Party %s not found or not compatible with the Type for specific"
493 " treatment of the account '%s - %s'.") % (current_line_num, line[cols['third_party']] or '',
494 account['code'], account['name'],))
495 continue
496 elif line[cols['third_party']]:
497 # if the account has no specific type, search for a partner, then an employee
498 # (the journal type is ignored in that case. If used it should trigger an error message)
499 tp_ids = partner_obj.search(cr, uid, [('name', '=', line[cols['third_party']])], context=context)
500 partner_type = 'partner'
501 if not tp_ids:
502 tp_ids = employee_obj.search(cr, uid, [('name', '=', line[cols['third_party']])], context=context)
480 partner_type = 'employee'503 partner_type = 'employee'
481 # If really not, raise an error for this line504 if not tp_ids:
482 if not tp_ids:505 errors.append(_('Line %s. Third party not found: %s') % (current_line_num, line[cols['third_party']],))
483 errors.append(_('Line %s. Third party not found: %s') % (current_line_num, line[cols['third_party']],))506 continue
484 continue507 if tp_ids:
485 r_partner = tp_ids[0]508 r_partner = tp_ids[0]
486509
487 # US-672 TP compat with account510 # US-672 TP compat with account
@@ -569,7 +592,7 @@
569 # - Booking Currency592 # - Booking Currency
570 vals = {593 vals = {
571 'description': r_description or '',594 'description': r_description or '',
572 'ref': line[4] or '',595 'ref': line[4] or '',
573 'account_id': r_account or False,596 'account_id': r_account or False,
574 'debit': r_debit or 0.0,597 'debit': r_debit or 0.0,
575 'credit': r_credit or 0.0,598 'credit': r_credit or 0.0,
@@ -586,14 +609,14 @@
586 'free_2_id': r_free2 or False,609 'free_2_id': r_free2 or False,
587 }610 }
588 if type_for_register == 'advance':611 if type_for_register == 'advance':
589 vals.update({'employee_id': r_partner,})612 vals.update({'employee_id': r_partner, })
590 elif type_for_register in ['transfer', 'transfer_same']:613 elif type_for_register in ['transfer', 'transfer_same']:
591 vals.update({'transfer_journal_id': r_partner})614 vals.update({'transfer_journal_id': r_partner})
592 else:615 else:
593 if partner_type == 'partner':616 if partner_type == 'partner':
594 vals.update({'partner_id': r_partner,})617 vals.update({'partner_id': r_partner, })
595 elif partner_type == 'employee':618 elif partner_type == 'employee':
596 vals.update({'employee_id': r_partner,})619 vals.update({'employee_id': r_partner, })
597 line_res = self.pool.get('wizard.register.import.lines').create(cr, uid, vals, context)620 line_res = self.pool.get('wizard.register.import.lines').create(cr, uid, vals, context)
598 if not line_res:621 if not line_res:
599 errors.append(_('Line %s. A problem occurred for line registration. Please contact an Administrator.') % (current_line_num,))622 errors.append(_('Line %s. A problem occurred for line registration. Please contact an Administrator.') % (current_line_num,))
@@ -612,7 +635,7 @@
612 # Delete old errors635 # Delete old errors
613 error_ids = self.pool.get('wizard.register.import.errors').search(cr, uid, [], context)636 error_ids = self.pool.get('wizard.register.import.errors').search(cr, uid, [], context)
614 if error_ids:637 if error_ids:
615 self.pool.get('wizard.register.import.errors').unlink(cr, uid, error_ids ,context)638 self.pool.get('wizard.register.import.errors').unlink(cr, uid, error_ids, context)
616 # create errors lines639 # create errors lines
617 for e in errors:640 for e in errors:
618 self.pool.get('wizard.register.import.errors').create(cr, uid, {'wizard_id': wiz.id, 'name': e}, context)641 self.pool.get('wizard.register.import.errors').create(cr, uid, {'wizard_id': wiz.id, 'name': e}, context)
619642
=== modified file 'bin/addons/sale/sale_workflow.py'
--- bin/addons/sale/sale_workflow.py 2018-01-08 13:50:26 +0000
+++ bin/addons/sale/sale_workflow.py 2018-02-12 10:19:50 +0000
@@ -52,7 +52,7 @@
52 o_ana_dist_id = so.analytic_distribution_id and so.analytic_distribution_id.id52 o_ana_dist_id = so.analytic_distribution_id and so.analytic_distribution_id.id
53 distrib_id = l_ana_dist_id or o_ana_dist_id or False53 distrib_id = l_ana_dist_id or o_ana_dist_id or False
5454
55 #US-830 : Remove the definition of a default AD for the inter-mission FO is no AD is defined55 # US-830 : Remove the definition of a default AD for the inter-mission FO is no AD is defined
56 if not distrib_id and not so.order_type in ('loan', 'donation_st', 'donation_exp'):56 if not distrib_id and not so.order_type in ('loan', 'donation_st', 'donation_exp'):
57 raise osv.except_osv(57 raise osv.except_osv(
58 _('Warning'),58 _('Warning'),
@@ -102,7 +102,7 @@
102 '''102 '''
103 if context is None:103 if context is None:
104 context = {}104 context = {}
105 if isinstance(ids, (int,long)):105 if isinstance(ids, (int, long)):
106 ids = [ids]106 ids = [ids]
107107
108 # for each line get a new copy:108 # for each line get a new copy:
@@ -122,7 +122,7 @@
122 '''122 '''
123 if context is None:123 if context is None:
124 context = {}124 context = {}
125 if isinstance(ids, (int,long)):125 if isinstance(ids, (int, long)):
126 ids = [ids]126 ids = [ids]
127127
128 for sol in self.browse(cr, uid, ids, context=context):128 for sol in self.browse(cr, uid, ids, context=context):
@@ -139,14 +139,14 @@
139 '''139 '''
140 if context is None:140 if context is None:
141 context = {}141 context = {}
142 if isinstance(ids, (int,long)):142 if isinstance(ids, (int, long)):
143 ids = [ids]143 ids = [ids]
144 wf_service = netsvc.LocalService("workflow")144 wf_service = netsvc.LocalService("workflow")
145145
146 new_sol_id = False146 new_sol_id = False
147 for sol in self.browse(cr, uid, ids, context=context):147 for sol in self.browse(cr, uid, ids, context=context):
148 new_sol_id = self.copy(cr, uid, sol.id, {148 new_sol_id = self.copy(cr, uid, sol.id, {
149 'resourced_original_line': sol.id, 149 'resourced_original_line': sol.id,
150 'resourced_original_remote_line': sol.sync_linked_pol,150 'resourced_original_remote_line': sol.sync_linked_pol,
151 'resourced_at_state': sol.state,151 'resourced_at_state': sol.state,
152 'is_line_split': False,152 'is_line_split': False,
@@ -164,7 +164,7 @@
164 '''164 '''
165 if context is None:165 if context is None:
166 context = {}166 context = {}
167 if isinstance(ids, (int,long)):167 if isinstance(ids, (int, long)):
168 ids = [ids]168 ids = [ids]
169169
170 sol = self.browse(cr, uid, ids[0], context=context)170 sol = self.browse(cr, uid, ids[0], context=context)
@@ -189,7 +189,7 @@
189 '''189 '''
190 if context is None:190 if context is None:
191 context = {}191 context = {}
192 if isinstance(ids, (int,long)):192 if isinstance(ids, (int, long)):
193 ids = [ids]193 ids = [ids]
194194
195 self.write(cr, uid, ids, {'state': 'done'}, context=context)195 self.write(cr, uid, ids, {'state': 'done'}, context=context)
@@ -197,7 +197,7 @@
197 # generate sync message manually :197 # generate sync message manually :
198 return_info = {}198 return_info = {}
199 for sol_id in ids:199 for sol_id in ids:
200 self.pool.get('sync.client.message_rule')._manual_create_sync_message(cr, uid, 'sale.order.line', sol_id, return_info, 200 self.pool.get('sync.client.message_rule')._manual_create_sync_message(cr, uid, 'sale.order.line', sol_id, return_info,
201 'purchase.order.line.sol_update_original_pol', self._logger, check_identifier=False, context=context)201 'purchase.order.line.sol_update_original_pol', self._logger, check_identifier=False, context=context)
202202
203 return True203 return True
@@ -217,7 +217,7 @@
217 # generate sync message manually :217 # generate sync message manually :
218 return_info = {}218 return_info = {}
219 for sol_id in ids:219 for sol_id in ids:
220 self.pool.get('sync.client.message_rule')._manual_create_sync_message(cr, uid, 'sale.order.line', sol_id, return_info, 220 self.pool.get('sync.client.message_rule')._manual_create_sync_message(cr, uid, 'sale.order.line', sol_id, return_info,
221 'purchase.order.line.sol_update_original_pol', self._logger, check_identifier=False, context=context)221 'purchase.order.line.sol_update_original_pol', self._logger, check_identifier=False, context=context)
222222
223 return True223 return True
@@ -237,7 +237,7 @@
237 # generate sync message237 # generate sync message
238 return_info = {}238 return_info = {}
239 for sol_id in ids:239 for sol_id in ids:
240 self.pool.get('sync.client.message_rule')._manual_create_sync_message(cr, uid, 'sale.order.line', sol_id, return_info, 240 self.pool.get('sync.client.message_rule')._manual_create_sync_message(cr, uid, 'sale.order.line', sol_id, return_info,
241 'purchase.order.line.sol_update_original_pol', self._logger, check_identifier=False, context=context)241 'purchase.order.line.sol_update_original_pol', self._logger, check_identifier=False, context=context)
242242
243 return True243 return True
@@ -271,7 +271,7 @@
271 # generate sync message manually :271 # generate sync message manually :
272 return_info = {}272 return_info = {}
273 for sol_id in ids:273 for sol_id in ids:
274 self.pool.get('sync.client.message_rule')._manual_create_sync_message(cr, uid, 'sale.order.line', sol_id, return_info, 274 self.pool.get('sync.client.message_rule')._manual_create_sync_message(cr, uid, 'sale.order.line', sol_id, return_info,
275 'purchase.order.line.sol_update_original_pol', self._logger, check_identifier=False, context=context)275 'purchase.order.line.sol_update_original_pol', self._logger, check_identifier=False, context=context)
276276
277 return True277 return True
@@ -283,7 +283,7 @@
283 '''283 '''
284 if context is None:284 if context is None:
285 context = {}285 context = {}
286 if isinstance(ids, (int,long)):286 if isinstance(ids, (int, long)):
287 ids = [ids]287 ids = [ids]
288288
289 sol = self.browse(cr, uid, ids[0], context=context)289 sol = self.browse(cr, uid, ids[0], context=context)
@@ -314,7 +314,7 @@
314 '''314 '''
315 if context is None:315 if context is None:
316 context = {}316 context = {}
317 if isinstance(ids, (int,long)):317 if isinstance(ids, (int, long)):
318 ids = [ids]318 ids = [ids]
319319
320 pick_to_use = False320 pick_to_use = False
@@ -363,18 +363,20 @@
363 '''363 '''
364 if context is None:364 if context is None:
365 context = {}365 context = {}
366 if isinstance(ids, (int,long)):366 if isinstance(ids, (int, long)):
367 ids = [ids]367 ids = [ids]
368368
369 for sol in self.browse(cr, uid, ids, context=context):369 for sol in self.browse(cr, uid, ids, context=context):
370 out_moves_to_cancel = self.pool.get('stock.move').search(cr, uid, [370 out_moves_to_cancel = self.pool.get('stock.move').search(cr, uid, [
371 ('sale_line_id', '=', sol.id), 371 ('sale_line_id', '=', sol.id),
372 ('type', '=', 'out'),372 ('type', '=', 'out'),
373 ('state', 'in', ['assigned', 'confirmed']),373 ('state', 'in', ['assigned', 'confirmed']),
374 ], context=context)374 ], context=context)
375375
376 if out_moves_to_cancel:376 if out_moves_to_cancel:
377 context.update({'not_resource_move': out_moves_to_cancel})
377 self.pool.get('stock.move').action_cancel(cr, uid, out_moves_to_cancel, context=context)378 self.pool.get('stock.move').action_cancel(cr, uid, out_moves_to_cancel, context=context)
379 context.pop('not_resource_move')
378380
379 return True381 return True
380382
@@ -398,7 +400,7 @@
398 ('order_id.order_type', '=', 'direct'),400 ('order_id.order_type', '=', 'direct'),
399 ], context=context)401 ], context=context)
400402
401 if sol.order_id.procurement_request and sol.product_id.type in ('consu', 'service', 'service_recep'): # IR non stockable403 if sol.order_id.procurement_request and sol.product_id.type in ('consu', 'service', 'service_recep'): # IR non stockable
402 continue404 continue
403405
404 if linked_dpo_line:406 if linked_dpo_line:
@@ -439,7 +441,7 @@
439 # Change Currency ??441 # Change Currency ??
440 if sol.order_partner_id.partner_type in ('section', 'intermission'):442 if sol.order_partner_id.partner_type in ('section', 'intermission'):
441 picking = picking_obj.browse(cr, uid, pick_to_use, context=context)443 picking = picking_obj.browse(cr, uid, pick_to_use, context=context)
442 move = self.pool.get('stock.move').browse(cr ,uid, move_id, context=context)444 move = self.pool.get('stock.move').browse(cr, uid, move_id, context=context)
443 invoice_id, inv_type = picking_obj.action_invoice_create_header(cr, uid, picking, journal_id=False, invoices_group=False, type=False, use_draft=True, context=context)445 invoice_id, inv_type = picking_obj.action_invoice_create_header(cr, uid, picking, journal_id=False, invoices_group=False, type=False, use_draft=True, context=context)
444 if invoice_id:446 if invoice_id:
445 picking_obj.action_invoice_create_line(cr, uid, picking, move, invoice_id, group=False, inv_type=inv_type, partner=sol.order_id.partner_id, context=context)447 picking_obj.action_invoice_create_line(cr, uid, picking, move, invoice_id, group=False, inv_type=inv_type, partner=sol.order_id.partner_id, context=context)
@@ -460,24 +462,35 @@
460 self.pool.get('stock.move').action_confirm(cr, uid, [move_id], context=context)462 self.pool.get('stock.move').action_confirm(cr, uid, [move_id], context=context)
461463
462 # confirm the OUT if in draft state:464 # confirm the OUT if in draft state:
463 pick_state = self.pool.get('stock.picking').read(cr, uid, pick_to_use, ['state'] ,context=context)['state']465 pick_state = self.pool.get('stock.picking').read(cr, uid, pick_to_use, ['state'], context=context)['state']
464 if picking_data['type'] == 'out' and picking_data['subtype'] == 'standard' and pick_state == 'draft':466 if picking_data['type'] == 'out' and picking_data['subtype'] == 'standard' and pick_state == 'draft':
465 self.pool.get('stock.picking').draft_force_assign(cr, uid, [pick_to_use], context=context)467 self.pool.get('stock.picking').draft_force_assign(cr, uid, [pick_to_use], context=context)
466 # run check availability on PICK/OUT:468 # run check availability on PICK/OUT:
467 if picking_data['type'] == 'out' and picking_data['subtype'] in ['picking', 'standard']:469 if picking_data['type'] == 'out' and picking_data['subtype'] in ['picking', 'standard']:
468 self.pool.get('stock.picking').action_assign(cr, uid, [pick_to_use], context=context)470 self.pool.get('stock.picking').action_assign(cr, uid, [pick_to_use], context=context)
469 if picking_data['type'] == 'internal' and sol.type == 'make_to_stock' and sol.order_id.procurement_request:471 if picking_data['type'] == 'internal' and sol.type == 'make_to_stock' and sol.order_id.procurement_request:
470 wf_service.trg_validate(uid, 'stock.picking', pick_to_use, 'button_confirm', cr) 472 wf_service.trg_validate(uid, 'stock.picking', pick_to_use, 'button_confirm', cr)
471473
472 self.write(cr, uid, ids, {'state': 'confirmed'}, context=context)474 self.write(cr, uid, ids, {'state': 'confirmed'}, context=context)
473475
474 # generate sync message:476 # generate sync message:
475 return_info = {}477 return_info = {}
476 for sol_id in ids:478 for sol_id in ids:
477 self.pool.get('sync.client.message_rule')._manual_create_sync_message(cr, uid, 'sale.order.line', sol_id, return_info, 479 self.pool.get('sync.client.message_rule')._manual_create_sync_message(cr, uid, 'sale.order.line', sol_id, return_info,
478 'purchase.order.line.sol_update_original_pol', self._logger, check_identifier=False, context=context)480 'purchase.order.line.sol_update_original_pol', self._logger, check_identifier=False, context=context)
479 return True481 return True
480482
483 def check_fo_tax(self, cr, uid, ids, context=None):
484 """
485 Prevents from validating a FO with taxes when using an Intermission partner
486 """
487 if context is None:
488 context = {}
489 if isinstance(ids, (int, long)):
490 ids = [ids]
491 for fo_line in self.browse(cr, uid, ids, fields_to_fetch=['order_id', 'tax_id'], context=context):
492 if fo_line.tax_id and fo_line.order_id.partner_type == 'intermission':
493 raise osv.except_osv(_('Error'), _("You can't use taxes with an intermission partner."))
481494
482 def action_validate(self, cr, uid, ids, context=None):495 def action_validate(self, cr, uid, ids, context=None):
483 '''496 '''
@@ -486,13 +499,15 @@
486 if context is None:499 if context is None:
487 context = {}500 context = {}
488 if isinstance(ids, (int, long)):501 if isinstance(ids, (int, long)):
489 ids = [ids] 502 ids = [ids]
503
504 self.check_fo_tax(cr, uid, ids, context=context)
490505
491 for sol in self.browse(cr, uid, ids, context=context):506 for sol in self.browse(cr, uid, ids, context=context):
492 to_write = {}507 to_write = {}
493 if not sol.stock_take_date and sol.order_id.stock_take_date:508 if not sol.stock_take_date and sol.order_id.stock_take_date:
494 to_write['stock_take_date'] = sol.order_id.stock_take_date509 to_write['stock_take_date'] = sol.order_id.stock_take_date
495 if not sol.order_id.procurement_request: # in case of FO510 if not sol.order_id.procurement_request: # in case of FO
496 # check unit price:511 # check unit price:
497 if not sol.price_unit or sol.price_unit <= 0:512 if not sol.price_unit or sol.price_unit <= 0:
498 raise osv.except_osv(513 raise osv.except_osv(
@@ -522,13 +537,13 @@
522 # generate sync message:537 # generate sync message:
523 return_info = {}538 return_info = {}
524 for sol in self.browse(cr, uid, ids, context=context):539 for sol in self.browse(cr, uid, ids, context=context):
525 self.pool.get('sync.client.message_rule')._manual_create_sync_message(cr, uid, 'sale.order.line', sol.id, return_info, 540 self.pool.get('sync.client.message_rule')._manual_create_sync_message(cr, uid, 'sale.order.line', sol.id, return_info,
526 'purchase.order.line.sol_update_original_pol', self._logger, check_identifier=False, context=context)541 'purchase.order.line.sol_update_original_pol', self._logger, check_identifier=False, context=context)
527542
528 return True543 return True
529544
530545
531 def action_draft(self, cr ,uid, ids, context=None):546 def action_draft(self, cr, uid, ids, context=None):
532 '''547 '''
533 Workflow method called when trying to reset draft the sale.order.line548 Workflow method called when trying to reset draft the sale.order.line
534 '''549 '''
@@ -560,7 +575,7 @@
560 # generate sync message:575 # generate sync message:
561 return_info = {}576 return_info = {}
562 for sol_id in ids:577 for sol_id in ids:
563 self.pool.get('sync.client.message_rule')._manual_create_sync_message(cr, uid, 'sale.order.line', sol_id, return_info, 578 self.pool.get('sync.client.message_rule')._manual_create_sync_message(cr, uid, 'sale.order.line', sol_id, return_info,
564 'purchase.order.line.sol_update_original_pol', self._logger, check_identifier=False, context=context)579 'purchase.order.line.sol_update_original_pol', self._logger, check_identifier=False, context=context)
565580
566 return True581 return True
@@ -585,11 +600,11 @@
585 # generate sync message for original FO line:600 # generate sync message for original FO line:
586 return_info = {}601 return_info = {}
587 for sol_id in ids:602 for sol_id in ids:
588 self.pool.get('sync.client.message_rule')._manual_create_sync_message(cr, uid, 'sale.order.line', sol_id, return_info, 603 self.pool.get('sync.client.message_rule')._manual_create_sync_message(cr, uid, 'sale.order.line', sol_id, return_info,
589 'purchase.order.line.sol_update_original_pol', self._logger, check_identifier=False, context=context)604 'purchase.order.line.sol_update_original_pol', self._logger, check_identifier=False, context=context)
590605
591 # generate sync message for resourced line:606 # generate sync message for resourced line:
592 self.pool.get('sync.client.message_rule')._manual_create_sync_message(cr, uid, 'sale.order.line', resourced_sol, return_info, 607 self.pool.get('sync.client.message_rule')._manual_create_sync_message(cr, uid, 'sale.order.line', resourced_sol, return_info,
593 'purchase.order.line.sol_update_original_pol', self._logger, check_identifier=False, context=context)608 'purchase.order.line.sol_update_original_pol', self._logger, check_identifier=False, context=context)
594609
595 return True610 return True
596611
=== modified file 'bin/addons/sync_so/purchase.py'
--- bin/addons/sync_so/purchase.py 2017-12-13 14:46:52 +0000
+++ bin/addons/sync_so/purchase.py 2018-02-12 10:19:50 +0000
@@ -146,6 +146,7 @@
146 pol_updated = False146 pol_updated = False
147 if not pol_id: # then create new PO line147 if not pol_id: # then create new PO line
148 kind = 'new line'148 kind = 'new line'
149 pol_values['line_number'] = sol_dict['line_number']
149 if sol_dict['is_line_split']:150 if sol_dict['is_line_split']:
150 sync_linked_sol = int(sol_dict['original_line_id'].get('id').split('/')[-1]) if sol_dict['original_line_id'] else False151 sync_linked_sol = int(sol_dict['original_line_id'].get('id').split('/')[-1]) if sol_dict['original_line_id'] else False
151 if not sync_linked_sol:152 if not sync_linked_sol:
@@ -161,7 +162,6 @@
161 pol_values['origin'] = orig_pol_info.origin162 pol_values['origin'] = orig_pol_info.origin
162 if sol_dict['in_name_goods_return'] and not sol_dict['is_line_split']:163 if sol_dict['in_name_goods_return'] and not sol_dict['is_line_split']:
163 # in case of FO from missing/replacement claim164 # in case of FO from missing/replacement claim
164 pol_values['line_number'] = sol_dict['line_number']
165 pol_values['origin'] = self.pool.get('purchase.order').browse(cr, uid, po_ids[0], context=context).origin165 pol_values['origin'] = self.pool.get('purchase.order').browse(cr, uid, po_ids[0], context=context).origin
166 pol_values['from_synchro_return_goods'] = True166 pol_values['from_synchro_return_goods'] = True
167 # case of PO line doesn't exists, so created in FO (COO) and pushed back in PO (PROJ)167 # case of PO line doesn't exists, so created in FO (COO) and pushed back in PO (PROJ)
168168
=== modified file 'bin/addons/tender_flow/tender_flow.py'
--- bin/addons/tender_flow/tender_flow.py 2017-11-13 08:37:20 +0000
+++ bin/addons/tender_flow/tender_flow.py 2018-02-12 10:19:50 +0000
@@ -40,7 +40,7 @@
40 def copy(self, cr, uid, id, default=None, context=None, done_list=[], local=False):40 def copy(self, cr, uid, id, default=None, context=None, done_list=[], local=False):
41 if not default:41 if not default:
42 default = {}42 default = {}
43 default['internal_state'] = 'draft' # UF-733: Reset the internal_state43 default['internal_state'] = 'draft' # UF-733: Reset the internal_state
44 if not 'sale_order_id' in default:44 if not 'sale_order_id' in default:
45 default['sale_order_id'] = False45 default['sale_order_id'] = False
46 return super(osv.osv, self).copy(cr, uid, id, default, context=context)46 return super(osv.osv, self).copy(cr, uid, id, default, context=context)
@@ -91,8 +91,8 @@
91 res = {}91 res = {}
92 for tender in self.browse(cr, uid, ids, context=context):92 for tender in self.browse(cr, uid, ids, context=context):
93 retour = False93 retour = False
94 ids_proc = self.pool.get('procurement.order').search(cr,uid,[('tender_id','=',tender.id)])94 ids_proc = self.pool.get('procurement.order').search(cr, uid, [('tender_id', '=', tender.id)])
95 ids_sol = self.pool.get('sale.order.line').search(cr,uid,[('procurement_id','in',ids_proc),('order_id.procurement_request','=',False)])95 ids_sol = self.pool.get('sale.order.line').search(cr, uid, [('procurement_id', 'in', ids_proc), ('order_id.procurement_request', '=', False)])
96 if ids_sol:96 if ids_sol:
97 retour = True97 retour = True
98 res[tender.id] = retour98 res[tender.id] = retour
@@ -100,22 +100,22 @@
100100
101 _columns = {'name': fields.char('Tender Reference', size=64, required=True, select=True, readonly=True),101 _columns = {'name': fields.char('Tender Reference', size=64, required=True, select=True, readonly=True),
102 'sale_order_id': fields.many2one('sale.order', string="Sale Order", readonly=True),102 'sale_order_id': fields.many2one('sale.order', string="Sale Order", readonly=True),
103 'state': fields.selection([('draft', 'Draft'),('comparison', 'Comparison'), ('done', 'Closed'), ('cancel', 'Cancelled'),], string="State", readonly=True),103 'state': fields.selection([('draft', 'Draft'), ('comparison', 'Comparison'), ('done', 'Closed'), ('cancel', 'Cancelled'), ], string="State", readonly=True),
104 'supplier_ids': fields.many2many('res.partner', 'tender_supplier_rel', 'tender_id', 'supplier_id', string="Suppliers", domain="[('id', '!=', company_id)]",104 'supplier_ids': fields.many2many('res.partner', 'tender_supplier_rel', 'tender_id', 'supplier_id', string="Suppliers", domain="[('id', '!=', company_id)]",
105 states={'draft':[('readonly',False)]}, readonly=True,105 states={'draft': [('readonly', False)]}, readonly=True,
106 context={'search_default_supplier': 1,}),106 context={'search_default_supplier': 1, }),
107 'location_id': fields.many2one('stock.location', 'Location', required=True, states={'draft':[('readonly',False)]}, readonly=True, domain=[('usage', '=', 'internal')]),107 'location_id': fields.many2one('stock.location', 'Location', required=True, states={'draft': [('readonly', False)]}, readonly=True, domain=[('usage', '=', 'internal')]),
108 'company_id': fields.many2one('res.company','Company',required=True, states={'draft':[('readonly',False)]}, readonly=True),108 'company_id': fields.many2one('res.company', 'Company', required=True, states={'draft': [('readonly', False)]}, readonly=True),
109 'rfq_ids': fields.one2many('purchase.order', 'tender_id', string="RfQs", readonly=True),109 'rfq_ids': fields.one2many('purchase.order', 'tender_id', string="RfQs", readonly=True),
110 'priority': fields.selection(ORDER_PRIORITY, string='Tender Priority', states={'draft':[('readonly',False)],}, readonly=True,),110 'priority': fields.selection(ORDER_PRIORITY, string='Tender Priority', states={'draft': [('readonly', False)], }, readonly=True,),
111 'categ': fields.selection(ORDER_CATEGORY, string='Tender Category', required=True, states={'draft':[('readonly',False)],}, readonly=True),111 'categ': fields.selection(ORDER_CATEGORY, string='Tender Category', required=True, states={'draft': [('readonly', False)], }, readonly=True),
112 'creator': fields.many2one('res.users', string="Creator", readonly=True, required=True,),112 'creator': fields.many2one('res.users', string="Creator", readonly=True, required=True,),
113 'warehouse_id': fields.many2one('stock.warehouse', string="Warehouse", required=True, states={'draft':[('readonly',False)],}, readonly=True),113 'warehouse_id': fields.many2one('stock.warehouse', string="Warehouse", required=True, states={'draft': [('readonly', False)], }, readonly=True),
114 'creation_date': fields.date(string="Creation Date", readonly=True, states={'draft':[('readonly',False)]}),114 'creation_date': fields.date(string="Creation Date", readonly=True, states={'draft': [('readonly', False)]}),
115 'details': fields.char(size=30, string="Details", states={'draft':[('readonly',False)],}, readonly=True),115 'details': fields.char(size=30, string="Details", states={'draft': [('readonly', False)], }, readonly=True),
116 'requested_date': fields.date(string="Requested Date", required=True, states={'draft':[('readonly',False)],}, readonly=True),116 'requested_date': fields.date(string="Requested Date", required=True, states={'draft': [('readonly', False)], }, readonly=True),
117 'notes': fields.text('Notes'),117 'notes': fields.text('Notes'),
118 'internal_state': fields.selection([('draft', 'Draft'),('updated', 'Rfq Updated'), ], string="Internal State", readonly=True),118 'internal_state': fields.selection([('draft', 'Draft'), ('updated', 'Rfq Updated'), ], string="Internal State", readonly=True),
119 'rfq_name_list': fields.function(_vals_get, method=True, string='RfQs Ref', type='char', readonly=True, store=False, multi='get_vals',),119 'rfq_name_list': fields.function(_vals_get, method=True, string='RfQs Ref', type='char', readonly=True, store=False, multi='get_vals',),
120 'product_id': fields.related('tender_line_ids', 'product_id', type='many2one', relation='product.product', string='Product'),120 'product_id': fields.related('tender_line_ids', 'product_id', type='many2one', relation='product.product', string='Product'),
121 'delivery_address': fields.many2one('res.partner.address', string='Delivery address', required=True),121 'delivery_address': fields.many2one('res.partner.address', string='Delivery address', required=True),
@@ -174,7 +174,7 @@
174 if not tender.tender_from_fo:174 if not tender.tender_from_fo:
175 return retour175 return retour
176 for sup in tender.supplier_ids:176 for sup in tender.supplier_ids:
177 if sup.partner_type == 'internal' :177 if sup.partner_type == 'internal':
178 retour = False178 retour = False
179 return retour179 return retour
180180
@@ -280,7 +280,7 @@
280 '''280 '''
281 on_change function for the warehouse281 on_change function for the warehouse
282 '''282 '''
283 result = {'value':{},}283 result = {'value': {}, }
284 if warehouse_id:284 if warehouse_id:
285 input_loc_id = self.pool.get('stock.warehouse').browse(cr, uid, warehouse_id, context=context).lot_input_id.id285 input_loc_id = self.pool.get('stock.warehouse').browse(cr, uid, warehouse_id, context=context).lot_input_id.id
286 result['value'].update(location_id=input_loc_id)286 result['value'].update(location_id=input_loc_id)
@@ -303,7 +303,7 @@
303 # check some supplier have been selected303 # check some supplier have been selected
304 if not tender.supplier_ids:304 if not tender.supplier_ids:
305 raise osv.except_osv(_('Warning !'), _('You must select at least one supplier!'))305 raise osv.except_osv(_('Warning !'), _('You must select at least one supplier!'))
306 #utp-315: check that the suppliers are not inactive (I use a SQL request because the inactive partner are ignored with the browse)306 # utp-315: check that the suppliers are not inactive (I use a SQL request because the inactive partner are ignored with the browse)
307 sql = """307 sql = """
308 select tsr.supplier_id, rp.name, rp.active308 select tsr.supplier_id, rp.name, rp.active
309 from tender_supplier_rel tsr309 from tender_supplier_rel tsr
@@ -325,7 +325,7 @@
325 # create a purchase order for each supplier325 # create a purchase order for each supplier
326 address_id = partner_obj.address_get(cr, uid, [supplier.id], ['default'])['default']326 address_id = partner_obj.address_get(cr, uid, [supplier.id], ['default'])['default']
327 if not address_id:327 if not address_id:
328 raise osv.except_osv(_('Warning !'), _('The supplier "%s" has no address defined!')%(supplier.name,))328 raise osv.except_osv(_('Warning !'), _('The supplier "%s" has no address defined!') % (supplier.name,))
329 pricelist_id = supplier.property_product_pricelist_purchase.id329 pricelist_id = supplier.property_product_pricelist_purchase.id
330 values = {'origin': tender.sale_order_id and tender.sale_order_id.name + ';' + tender.name or tender.name,330 values = {'origin': tender.sale_order_id and tender.sale_order_id.name + ';' + tender.name or tender.name,
331 'rfq_ok': True,331 'rfq_ok': True,
@@ -353,14 +353,14 @@
353 if line.qty <= 0.00:353 if line.qty <= 0.00:
354 raise osv.except_osv(_('Error !'), _('You cannot generate RfQs for an line with a null quantity.'))354 raise osv.except_osv(_('Error !'), _('You cannot generate RfQs for an line with a null quantity.'))
355355
356 if line.product_id.id == obj_data.get_object_reference(cr, uid,'msf_doc_import', 'product_tbd')[1]:356 if line.product_id.id == obj_data.get_object_reference(cr, uid, 'msf_doc_import', 'product_tbd')[1]:
357 raise osv.except_osv(_('Warning !'), _('You can\'t have "To Be Defined" for the product. Please select an existing product.'))357 raise osv.except_osv(_('Warning !'), _('You can\'t have "To Be Defined" for the product. Please select an existing product.'))
358 newdate = datetime.strptime(line.date_planned, '%Y-%m-%d')358 newdate = datetime.strptime(line.date_planned, '%Y-%m-%d')
359 values = {'name': line.product_id.partner_ref,359 values = {'name': line.product_id.partner_ref,
360 'product_qty': line.qty,360 'product_qty': line.qty,
361 'product_id': line.product_id.id,361 'product_id': line.product_id.id,
362 'product_uom': line.product_uom.id,362 'product_uom': line.product_uom.id,
363 'price_unit': 0.0, # was price variable - uf-607363 'price_unit': 0.0, # was price variable - uf-607
364 'date_planned': newdate.strftime('%Y-%m-%d'),364 'date_planned': newdate.strftime('%Y-%m-%d'),
365 'notes': line.product_id.description_purchase,365 'notes': line.product_id.description_purchase,
366 'order_id': po_id,366 'order_id': po_id,
@@ -369,7 +369,7 @@
369 }369 }
370 # create purchase order line370 # create purchase order line
371 pol_obj.create(cr, uid, values, context=context)371 pol_obj.create(cr, uid, values, context=context)
372 message = "Request for Quotation '%s' has been created."%po_obj.browse(cr, uid, po_id, context=context).name372 message = "Request for Quotation '%s' has been created." % po_obj.browse(cr, uid, po_id, context=context).name
373 # create the log message373 # create the log message
374 self.pool.get('res.log').create(cr, uid,374 self.pool.get('res.log').create(cr, uid,
375 {'name': message,375 {'name': message,
@@ -385,7 +385,7 @@
385 tender.name,385 tender.name,
386 ))386 ))
387387
388 self.write(cr, uid, ids, {'state':'comparison'}, context=context)388 self.write(cr, uid, ids, {'state': 'comparison'}, context=context)
389 return True389 return True
390390
391391
@@ -395,7 +395,7 @@
395 '''395 '''
396 if context is None:396 if context is None:
397 context = {}397 context = {}
398 if isinstance(ids, (int,long)):398 if isinstance(ids, (int, long)):
399 ids = [ids]399 ids = [ids]
400400
401 self.create_po(cr, uid, ids, context=context)401 self.create_po(cr, uid, ids, context=context)
@@ -420,12 +420,12 @@
420 # close linked RfQ:420 # close linked RfQ:
421 rfq_list = []421 rfq_list = []
422 for rfq in tender.rfq_ids:422 for rfq in tender.rfq_ids:
423 if rfq.rfq_state not in ('updated', 'cancel'): 423 if rfq.rfq_state not in ('updated', 'cancel'):
424 rfq_list.append(rfq.id)424 rfq_list.append(rfq.id)
425 else:425 else:
426 self.pool.get('purchase.order').write(cr, uid, [rfq.id], {'rfq_state': 'done'}, context=context)426 self.pool.get('purchase.order').write(cr, uid, [rfq.id], {'rfq_state': 'done'}, context=context)
427427
428 self.write(cr, uid, [tender.id], {'state':'done'}, context=context)428 self.write(cr, uid, [tender.id], {'state': 'done'}, context=context)
429 self.infolog(cr, uid, "The tender id:%s (%s) has been closed" % (429 self.infolog(cr, uid, "The tender id:%s (%s) has been closed" % (
430 tender.id,430 tender.id,
431 tender.name,431 tender.name,
@@ -444,12 +444,12 @@
444 raise osv.except_osv(_('Error !'), _("Some RfQ are already Closed. Integrity failure."))444 raise osv.except_osv(_('Error !'), _("Some RfQ are already Closed. Integrity failure."))
445 # all rfqs must have been treated445 # all rfqs must have been treated
446 rfq_ids = po_obj.search(cr, uid, [('tender_id', '=', tender.id),446 rfq_ids = po_obj.search(cr, uid, [('tender_id', '=', tender.id),
447 ('rfq_state', 'in', ('draft', 'sent',)),], context=context)447 ('rfq_state', 'in', ('draft', 'sent',)), ], context=context)
448 if rfq_ids:448 if rfq_ids:
449 raise osv.except_osv(_('Warning !'), _("Generated RfQs must be Updated or Cancelled."))449 raise osv.except_osv(_('Warning !'), _("Generated RfQs must be Updated or Cancelled."))
450 # at least one rfq must be updated and not canceled450 # at least one rfq must be updated and not canceled
451 rfq_ids = po_obj.search(cr, uid, [('tender_id', '=', tender.id),451 rfq_ids = po_obj.search(cr, uid, [('tender_id', '=', tender.id),
452 ('rfq_state', 'in', ('updated',)),], context=context)452 ('rfq_state', 'in', ('updated',)), ], context=context)
453 if not rfq_ids:453 if not rfq_ids:
454 raise osv.except_osv(_('Warning !'), _("At least one RfQ must be in state Updated."))454 raise osv.except_osv(_('Warning !'), _("At least one RfQ must be in state Updated."))
455455
@@ -469,7 +469,7 @@
469 suppliers = {}469 suppliers = {}
470 for line in tender.tender_line_ids:470 for line in tender.tender_line_ids:
471 if line.product_id and line.supplier_id and line.line_state != 'cancel':471 if line.product_id and line.supplier_id and line.line_state != 'cancel':
472 suppliers.update({line.product_id.id:line.supplier_id.id,})472 suppliers.update({line.product_id.id: line.supplier_id.id, })
473 # rfq corresponding to this tender with done state (has been updated and not canceled)473 # rfq corresponding to this tender with done state (has been updated and not canceled)
474 # the list of rfq which will be compared474 # the list of rfq which will be compared
475 c = dict(context, active_ids=rfq_ids, tender_id=tender.id, end_wizard=False, suppliers=suppliers,)475 c = dict(context, active_ids=rfq_ids, tender_id=tender.id, end_wizard=False, suppliers=suppliers,)
@@ -503,7 +503,7 @@
503 # find the corresponding suppinfo with sequence -99503 # find the corresponding suppinfo with sequence -99
504 info_99_list = info_obj.search(cr, uid, [('product_id', '=', product.product_tmpl_id.id),504 info_99_list = info_obj.search(cr, uid, [('product_id', '=', product.product_tmpl_id.id),
505 ('name', '=', line.purchase_order_line_id.order_id.partner_id.id),505 ('name', '=', line.purchase_order_line_id.order_id.partner_id.id),
506 ('sequence', '=', -99),], context=context)506 ('sequence', '=', -99), ], context=context)
507507
508 if info_99_list:508 if info_99_list:
509 # we drop it509 # we drop it
@@ -513,12 +513,12 @@
513 values = {'name': line.supplier_id.id,513 values = {'name': line.supplier_id.id,
514 'product_name': False,514 'product_name': False,
515 'product_code': False,515 'product_code': False,
516 'sequence' : -99,516 'sequence': -99,
517 #'product_uom': line.product_uom.id,517 #'product_uom': line.product_uom.id,
518 #'min_qty': 0.0,518 #'min_qty': 0.0,
519 #'qty': function519 #'qty': function
520 'product_id' : product.product_tmpl_id.id,520 'product_id': product.product_tmpl_id.id,
521 'delay' : int(line.supplier_id.default_delay),521 'delay': int(line.supplier_id.default_delay),
522 #'pricelist_ids': created just after522 #'pricelist_ids': created just after
523 #'company_id': default value523 #'company_id': default value
524 }524 }
@@ -574,10 +574,13 @@
574 self.pool.get('purchase.order').log(cr, uid, po_to_use, 'The Purchase Order %s for supplier %s has been created.' % (po.name, po.partner_id.name))574 self.pool.get('purchase.order').log(cr, uid, po_to_use, 'The Purchase Order %s for supplier %s has been created.' % (po.name, po.partner_id.name))
575 self.pool.get('purchase.order').infolog(cr, uid, 'The Purchase order %s for supplier %s has been created.' % (po.name, po.partner_id.name))575 self.pool.get('purchase.order').infolog(cr, uid, 'The Purchase order %s for supplier %s has been created.' % (po.name, po.partner_id.name))
576576
577 anal_dist_to_copy = tender_line.sale_order_line_id and tender_line.sale_order_line_id.analytic_distribution_id.id or False
578
577 # attach new PO line:579 # attach new PO line:
578 pol_values = {580 pol_values = {
579 'order_id': po_to_use,581 'order_id': po_to_use,
580 'linked_sol_id': tender_line.sale_order_line_id.id or False,582 'linked_sol_id': tender_line.sale_order_line_id.id or False,
583 'origin': tender_line.sale_order_line_id and tender_line.sale_order_line_id.order_id.name or False,
581 'name': tender_line.product_id.partner_ref,584 'name': tender_line.product_id.partner_ref,
582 'product_qty': tender_line.qty,585 'product_qty': tender_line.qty,
583 'product_id': tender_line.product_id.id,586 'product_id': tender_line.product_id.id,
@@ -589,6 +592,8 @@
589 'notes': tender_line.product_id.description_purchase,592 'notes': tender_line.product_id.description_purchase,
590 'comment': tender_line.comment,593 'comment': tender_line.comment,
591 }594 }
595 if anal_dist_to_copy:
596 pol_values['analytic_distribution_id'] = self.pool.get('analytic.distribution').copy(cr, uid, anal_dist_to_copy, {}, context=context)
592 self.pool.get('purchase.order.line').create(cr, uid, pol_values, context=context)597 self.pool.get('purchase.order.line').create(cr, uid, pol_values, context=context)
593598
594 # when the po is generated, the tender is done - no more modification or comparison599 # when the po is generated, the tender is done - no more modification or comparison
@@ -769,9 +774,9 @@
769 '''774 '''
770 _name = 'tender.line'775 _name = 'tender.line'
771 _rec_name = 'product_id'776 _rec_name = 'product_id'
772 _description= 'Tender Line'777 _description = 'Tender Line'
773778
774 _SELECTION_TENDER_STATE = [('draft', 'Draft'),('comparison', 'Comparison'), ('done', 'Closed'),]779 _SELECTION_TENDER_STATE = [('draft', 'Draft'), ('comparison', 'Comparison'), ('done', 'Closed'), ]
775780
776 def on_product_change(self, cr, uid, id, product_id, uom_id, product_qty, categ, context=None):781 def on_product_change(self, cr, uid, id, product_id, uom_id, product_qty, categ, context=None):
777 '''782 '''
@@ -793,7 +798,7 @@
793 result['value']['text_error'] = False798 result['value']['text_error'] = False
794 result['value']['to_correct_ok'] = False799 result['value']['to_correct_ok'] = False
795800
796 res_qty = self.onchange_uom_qty(cr, uid, id, uom_id or result.get('value', {}).get('product_uom',False), product_qty)801 res_qty = self.onchange_uom_qty(cr, uid, id, uom_id or result.get('value', {}).get('product_uom', False), product_qty)
797 result['value']['qty'] = res_qty.get('value', {}).get('qty', product_qty)802 result['value']['qty'] = res_qty.get('value', {}).get('qty', product_qty)
798803
799 if uom_id:804 if uom_id:
@@ -841,9 +846,9 @@
841 else:846 else:
842 result[line.id]['currency_id'] = result[line.id]['func_currency_id']847 result[line.id]['currency_id'] = result[line.id]['func_currency_id']
843848
844 result[line.id]['func_total_price'] = self.pool.get('res.currency').compute(cr, uid, result[line.id]['currency_id'], 849 result[line.id]['func_total_price'] = self.pool.get('res.currency').compute(cr, uid, result[line.id]['currency_id'],
845 result[line.id]['func_currency_id'], 850 result[line.id]['func_currency_id'],
846 result[line.id]['total_price'], 851 result[line.id]['total_price'],
847 round=True, context=context)852 round=True, context=context)
848853
849 return result854 return result
@@ -865,7 +870,7 @@
865 'date_planned': fields.related('tender_id', 'requested_date', type='date', string='Requested Date', store=False,),870 'date_planned': fields.related('tender_id', 'requested_date', type='date', string='Requested Date', store=False,),
866 # functions871 # functions
867 'supplier_id': fields.related('purchase_order_line_id', 'order_id', 'partner_id', type='many2one', relation='res.partner', string="Supplier", readonly=True),872 'supplier_id': fields.related('purchase_order_line_id', 'order_id', 'partner_id', type='many2one', relation='res.partner', string="Supplier", readonly=True),
868 'price_unit': fields.related('purchase_order_line_id', 'price_unit', type="float", string="Price unit", digits_compute=dp.get_precision('Purchase Price Computation'), readonly=True), # same precision as related field!873 'price_unit': fields.related('purchase_order_line_id', 'price_unit', type="float", string="Price unit", digits_compute=dp.get_precision('Purchase Price Computation'), readonly=True), # same precision as related field!
869 'delivery_confirmed_date': fields.related('purchase_order_line_id', 'confirmed_delivery_date', type="date", string="Delivery Confirmed Date", readonly=True),874 'delivery_confirmed_date': fields.related('purchase_order_line_id', 'confirmed_delivery_date', type="date", string="Delivery Confirmed Date", readonly=True),
870 'total_price': fields.function(_get_total_price, method=True, type='float', string="Total Price", digits_compute=dp.get_precision('Purchase Price'), multi='total'),875 'total_price': fields.function(_get_total_price, method=True, type='float', string="Total Price", digits_compute=dp.get_precision('Purchase Price'), multi='total'),
871 'currency_id': fields.function(_get_total_price, method=True, type='many2one', relation='res.currency', string='Cur.', multi='total'),876 'currency_id': fields.function(_get_total_price, method=True, type='many2one', relation='res.currency', string='Cur.', multi='total'),
@@ -874,7 +879,7 @@
874 'purchase_order_id': fields.related('purchase_order_line_id', 'order_id', type='many2one', relation='purchase.order', string="Related RfQ", readonly=True,),879 'purchase_order_id': fields.related('purchase_order_line_id', 'order_id', type='many2one', relation='purchase.order', string="Related RfQ", readonly=True,),
875 'purchase_order_line_number': fields.related('purchase_order_line_id', 'line_number', type="char", string="Related Line Number", readonly=True,),880 'purchase_order_line_number': fields.related('purchase_order_line_id', 'line_number', type="char", string="Related Line Number", readonly=True,),
876 'state': fields.related('tender_id', 'state', type="selection", selection=_SELECTION_TENDER_STATE, string="State",),881 'state': fields.related('tender_id', 'state', type="selection", selection=_SELECTION_TENDER_STATE, string="State",),
877 'line_state': fields.selection([('draft','Draft'), ('cancel', 'Canceled'), ('done', 'Done')], string='State', readonly=True),882 'line_state': fields.selection([('draft', 'Draft'), ('cancel', 'Canceled'), ('done', 'Done')], string='State', readonly=True),
878 'comment': fields.char(size=128, string='Comment'),883 'comment': fields.char(size=128, string='Comment'),
879 'has_to_be_resourced': fields.boolean(string='Has to be resourced'),884 'has_to_be_resourced': fields.boolean(string='Has to be resourced'),
880 'created_by_rfq': fields.boolean(string='Created by RfQ'),885 'created_by_rfq': fields.boolean(string='Created by RfQ'),
@@ -940,7 +945,7 @@
940945
941 return super(tender_line, self).copy(cr, uid, id, default, context=context)946 return super(tender_line, self).copy(cr, uid, id, default, context=context)
942947
943 def cancel_sourcing(self,cr, uid, ids, context=None):948 def cancel_sourcing(self, cr, uid, ids, context=None):
944 '''949 '''
945 Cancel the line and re-source the FO line950 Cancel the line and re-source the FO line
946 '''951 '''
@@ -997,11 +1002,11 @@
997 del context['update_or_cancel_line_not_delete']1002 del context['update_or_cancel_line_not_delete']
9981003
999 # Update the FO state1004 # Update the FO state
1000 #for so in so_to_update:1005 # for so in so_to_update:
1001 # wf_service.trg_write(uid, 'sale.order', so, cr)1006 # wf_service.trg_write(uid, 'sale.order', so, cr)
10021007
1003 # UF-733: if all tender lines have been compared (have PO Line id), then set the tender to be ready1008 # UF-733: if all tender lines have been compared (have PO Line id), then set the tender to be ready
1004 # for proceeding to other actions (create PO, Done etc) 1009 # for proceeding to other actions (create PO, Done etc)
1005 for tender in tender_obj.browse(cr, uid, list(tender_to_update), context=context):1010 for tender in tender_obj.browse(cr, uid, list(tender_to_update), context=context):
1006 if tender.internal_state == 'draft':1011 if tender.internal_state == 'draft':
1007 flag = True1012 flag = True
@@ -1149,7 +1154,7 @@
1149 '''1154 '''
1150 if context is None:1155 if context is None:
1151 context = {}1156 context = {}
1152 if isinstance(ids, (int,long)):1157 if isinstance(ids, (int, long)):
1153 ids = [ids]1158 ids = [ids]
11541159
1155 for tender_line in self.browse(cr, uid, ids, context=context):1160 for tender_line in self.browse(cr, uid, ids, context=context):
@@ -1164,7 +1169,7 @@
1164 'origin': (tender.sale_order_id and tender.sale_order_id.name or "") + '; ' + tender.name,1169 'origin': (tender.sale_order_id and tender.sale_order_id.name or "") + '; ' + tender.name,
1165 'partner_id': tender_line.supplier_id.id,1170 'partner_id': tender_line.supplier_id.id,
1166 'partner_address_id': self.pool.get('res.partner').address_get(cr, uid, [tender_line.supplier_id.id], ['default'])['default'],1171 'partner_address_id': self.pool.get('res.partner').address_get(cr, uid, [tender_line.supplier_id.id], ['default'])['default'],
1167 'customer_id': tender_line.sale_order_line_id and tender_line.sale_order_line_id.order_id.partner_id.id or False, 1172 'customer_id': tender_line.sale_order_line_id and tender_line.sale_order_line_id.order_id.partner_id.id or False,
1168 'location_id': tender.location_id.id,1173 'location_id': tender.location_id.id,
1169 'company_id': tender.company_id.id,1174 'company_id': tender.company_id.id,
1170 'cross_docking_ok': True if tender_line.sale_order_line_id else False,1175 'cross_docking_ok': True if tender_line.sale_order_line_id else False,
@@ -1189,7 +1194,7 @@
1189 tender class1194 tender class
1190 '''1195 '''
1191 _inherit = 'tender'1196 _inherit = 'tender'
1192 _columns = {'tender_line_ids': fields.one2many('tender.line', 'tender_id', string="Tender lines", states={'draft':[('readonly',False)]}, readonly=True),1197 _columns = {'tender_line_ids': fields.one2many('tender.line', 'tender_id', string="Tender lines", states={'draft': [('readonly', False)]}, readonly=True),
1193 }1198 }
11941199
1195 def copy(self, cr, uid, id, default=None, context=None):1200 def copy(self, cr, uid, id, default=None, context=None):
@@ -1252,16 +1257,16 @@
1252 'rfq_id': fields.many2one('purchase.order', string='RfQ', readonly=True),1257 'rfq_id': fields.many2one('purchase.order', string='RfQ', readonly=True),
1253 'rfq_line_id': fields.many2one('purchase.order.line', string='RfQ line', readonly=True),1258 'rfq_line_id': fields.many2one('purchase.order.line', string='RfQ line', readonly=True),
1254 'is_rfq_done': fields.boolean(string="RfQ Closed"),1259 'is_rfq_done': fields.boolean(string="RfQ Closed"),
1255 'state': fields.selection([('draft','Draft'),1260 'state': fields.selection([('draft', 'Draft'),
1256 ('confirmed','Confirmed'),1261 ('confirmed', 'Confirmed'),
1257 ('exception','Exception'),1262 ('exception', 'Exception'),
1258 ('running','Converted'),1263 ('running', 'Converted'),
1259 ('cancel','Cancelled'),1264 ('cancel', 'Cancelled'),
1260 ('ready','Ready'),1265 ('ready', 'Ready'),
1261 ('done','Closed'),1266 ('done', 'Closed'),
1262 ('tender', 'Tender'),1267 ('tender', 'Tender'),
1263 ('rfq', 'Request for Quotation'),1268 ('rfq', 'Request for Quotation'),
1264 ('waiting','Waiting'),], 'State', required=True,1269 ('waiting', 'Waiting'), ], 'State', required=True,
1265 help='When a procurement is created the state is set to \'Draft\'.\n If the procurement is confirmed, the state is set to \'Confirmed\'.\1270 help='When a procurement is created the state is set to \'Draft\'.\n If the procurement is confirmed, the state is set to \'Confirmed\'.\
1266 \nAfter confirming the state is set to \'Running\'.\n If any exception arises in the order then the state is set to \'Exception\'.\n Once the exception is removed the state becomes \'Ready\'.\n It is in \'Waiting\'. state when the procurement is waiting for another one to finish.'),1271 \nAfter confirming the state is set to \'Running\'.\n If any exception arises in the order then the state is set to \'Exception\'.\n Once the exception is removed the state becomes \'Ready\'.\n It is in \'Waiting\'. state when the procurement is waiting for another one to finish.'),
1267 'price_unit': fields.float('Unit Price from Tender', digits_compute=dp.get_precision('Purchase Price Computation')),1272 'price_unit': fields.float('Unit Price from Tender', digits_compute=dp.get_precision('Purchase Price Computation')),
@@ -1279,7 +1284,7 @@
1279 if proc.supplier and not proc.supplier.address:1284 if proc.supplier and not proc.supplier.address:
1280 self.write(cr, uid, [proc.id], {1285 self.write(cr, uid, [proc.id], {
1281 'state': 'exception',1286 'state': 'exception',
1282 'message': _('The supplier "%s" has no address defined!')%(proc.supplier.name,),1287 'message': _('The supplier "%s" has no address defined!') % (proc.supplier.name,),
1283 }, context=context)1288 }, context=context)
12841289
1285 return True1290 return True
@@ -1308,8 +1313,8 @@
1308 break1313 break
1309 # find the rfq1314 # find the rfq
1310 rfq_id = False1315 rfq_id = False
1311 # UTP-934: If source rfq to different supplier, different rfq must be created, and cannot be using the same rfq 1316 # UTP-934: If source rfq to different supplier, different rfq must be created, and cannot be using the same rfq
1312 rfq_ids = rfq_obj.search(cr, uid, [('sale_order_id', '=', sale_order.id),('partner_id', '=', proc.supplier.id), ('state', '=', 'draft'), ('rfq_ok', '=', True),], context=context)1317 rfq_ids = rfq_obj.search(cr, uid, [('sale_order_id', '=', sale_order.id), ('partner_id', '=', proc.supplier.id), ('state', '=', 'draft'), ('rfq_ok', '=', True), ], context=context)
1313 if rfq_ids:1318 if rfq_ids:
1314 rfq_id = rfq_ids[0]1319 rfq_id = rfq_ids[0]
1315 # create if not found1320 # create if not found
@@ -1320,7 +1325,7 @@
1320 address_id = partner_obj.address_get(cr, uid, [supplier.id], ['default'])['default']1325 address_id = partner_obj.address_get(cr, uid, [supplier.id], ['default'])['default']
1321 if not address_id:1326 if not address_id:
1322 self.write(cr, uid, [proc.id], {1327 self.write(cr, uid, [proc.id], {
1323 'message': _('The supplier "%s" has no address defined!')%(supplier.name,),1328 'message': _('The supplier "%s" has no address defined!') % (supplier.name,),
1324 }, context=context)1329 }, context=context)
1325 continue1330 continue
13261331
@@ -1338,7 +1343,7 @@
1338 'rfq_ok': True,1343 'rfq_ok': True,
1339 'from_procurement': True,1344 'from_procurement': True,
1340 'order_type': sale_order.order_type,1345 'order_type': sale_order.order_type,
1341 'origin': sale_order.name,}, context=context)1346 'origin': sale_order.name, }, context=context)
13421347
1343 prsd_obj.chk_create(cr, uid, {1348 prsd_obj.chk_create(cr, uid, {
1344 'order_id': sale_order.id,1349 'order_id': sale_order.id,
@@ -1366,7 +1371,7 @@
1366 self.write(cr, uid, ids, {'rfq_id': rfq_id, 'rfq_line_id': rfq_line_id}, context=context)1371 self.write(cr, uid, ids, {'rfq_id': rfq_id, 'rfq_line_id': rfq_line_id}, context=context)
13671372
1368 # log message concerning RfQ creation1373 # log message concerning RfQ creation
1369 rfq_obj.log(cr, uid, rfq_id, "The Request for Quotation '%s' has been created and must be completed before purchase order creation."%rfq_obj.browse(cr, uid, rfq_id, context=context).name, context={'rfq_ok': 1})1374 rfq_obj.log(cr, uid, rfq_id, "The Request for Quotation '%s' has been created and must be completed before purchase order creation." % rfq_obj.browse(cr, uid, rfq_id, context=context).name, context={'rfq_ok': 1})
1370 rfq_line = rfq_line_obj.browse(cr, uid, rfq_line_id, context=context)1375 rfq_line = rfq_line_obj.browse(cr, uid, rfq_line_id, context=context)
1371 self.infolog(cr, uid, "The FO/IR line id:%s (line number: %s) has been sourced on order to RfQ line id:%s (line number: %s) of the RfQ id:%s (%s)" % (1376 self.infolog(cr, uid, "The FO/IR line id:%s (line number: %s) has been sourced on order to RfQ line id:%s (line number: %s) of the RfQ id:%s (%s)" % (
1372 sale_order_line.id,1377 sale_order_line.id,
@@ -1399,7 +1404,7 @@
1399 sale_order_line = sol1404 sale_order_line = sol
1400 # find the tender1405 # find the tender
1401 tender_id = False1406 tender_id = False
1402 tender_ids = tender_obj.search(cr, uid, [('sale_order_id', '=', sale_order.id),('state', '=', 'draft'),], context=context)1407 tender_ids = tender_obj.search(cr, uid, [('sale_order_id', '=', sale_order.id), ('state', '=', 'draft'), ], context=context)
1403 if tender_ids:1408 if tender_ids:
1404 tender_id = tender_ids[0]1409 tender_id = tender_ids[0]
1405 # create if not found1410 # create if not found
@@ -1433,7 +1438,7 @@
14331438
1434 # log message concerning tender creation1439 # log message concerning tender creation
1435 tender_line = tender_line_obj.browse(cr, uid, tender_line_id, context=context)1440 tender_line = tender_line_obj.browse(cr, uid, tender_line_id, context=context)
1436 tender_obj.log(cr, uid, tender_id, "The tender '%s' has been created and must be completed before purchase order creation."%tender_line.tender_id.name)1441 tender_obj.log(cr, uid, tender_id, "The tender '%s' has been created and must be completed before purchase order creation." % tender_line.tender_id.name)
1437 self.infolog(cr, uid, "The FO/IR line id:%s (%s) has been sourced on order to tender line id:%s of the tender id:%s (%s)" % (1442 self.infolog(cr, uid, "The FO/IR line id:%s (%s) has been sourced on order to tender line id:%s of the tender id:%s (%s)" % (
1438 sale_order_line.id,1443 sale_order_line.id,
1439 sale_order_line.line_number,1444 sale_order_line.line_number,
@@ -1450,14 +1455,14 @@
1450 '''1455 '''
1451 set is_tender_done value1456 set is_tender_done value
1452 '''1457 '''
1453 self.write(cr, uid, ids, {'is_tender_done': True, 'state': 'exception',}, context=context)1458 self.write(cr, uid, ids, {'is_tender_done': True, 'state': 'exception', }, context=context)
1454 return True1459 return True
14551460
1456 def wkf_action_rfq_done(self, cr, uid, ids, context=None):1461 def wkf_action_rfq_done(self, cr, uid, ids, context=None):
1457 '''1462 '''
1458 set is_rfq_done value1463 set is_rfq_done value
1459 '''1464 '''
1460 self.write(cr, uid, ids, {'is_rfq_done': True, 'state': 'exception',}, context=context)1465 self.write(cr, uid, ids, {'is_rfq_done': True, 'state': 'exception', }, context=context)
1461 return True1466 return True
14621467
1463 def _get_pricelist_from_currency(self, cr, uid, currency_id, context=None):1468 def _get_pricelist_from_currency(self, cr, uid, currency_id, context=None):
@@ -1488,7 +1493,7 @@
1488 # do not display a log if we come from po update backward update of so1493 # do not display a log if we come from po update backward update of so
1489 data = self.read(cr, uid, ids, ['so_back_update_dest_po_id_procurement_order'], context=context)1494 data = self.read(cr, uid, ids, ['so_back_update_dest_po_id_procurement_order'], context=context)
1490 if not data[0]['so_back_update_dest_po_id_procurement_order']:1495 if not data[0]['so_back_update_dest_po_id_procurement_order']:
1491 po_obj.log(cr, uid, result, "The Purchase Order '%s' has been created following 'on order' sourcing."%po_obj.browse(cr, uid, result, context=context).name)1496 po_obj.log(cr, uid, result, "The Purchase Order '%s' has been created following 'on order' sourcing." % po_obj.browse(cr, uid, result, context=context).name)
1492 return result1497 return result
14931498
1494 def po_values_hook(self, cr, uid, ids, context=None, *args, **kwargs):1499 def po_values_hook(self, cr, uid, ids, context=None, *args, **kwargs):
@@ -1570,7 +1575,7 @@
1570 _constraints = [1575 _constraints = [
1571 (_check_valid_till,1576 (_check_valid_till,
1572 'You must specify a Valid Till date.',1577 'You must specify a Valid Till date.',
1573 ['valid_till']),]1578 ['valid_till']), ]
15741579
1575 def default_get(self, cr, uid, fields, context=None):1580 def default_get(self, cr, uid, fields, context=None):
1576 '''1581 '''
@@ -1612,7 +1617,7 @@
1612 '''1617 '''
1613 if context is None:1618 if context is None:
1614 context = {}1619 context = {}
1615 if isinstance(ids, (int,long)):1620 if isinstance(ids, (int, long)):
1616 ids = [ids]1621 ids = [ids]
1617 wf_service = netsvc.LocalService("workflow")1622 wf_service = netsvc.LocalService("workflow")
16181623
@@ -1640,10 +1645,10 @@
1640 purchase_orders = self.read(cr, uid, ids, ['state'], context=context)1645 purchase_orders = self.read(cr, uid, ids, ['state'], context=context)
1641 unlink_ids = []1646 unlink_ids = []
1642 for s in purchase_orders:1647 for s in purchase_orders:
1643 if s['state'] in ['draft','cancel']:1648 if s['state'] in ['draft', 'cancel']:
1644 unlink_ids.append(s['id'])1649 unlink_ids.append(s['id'])
1645 else:1650 else:
1646 raise osv.except_osv(_('Invalid action !'), _('Cannot delete Purchase Order(s) which are in %s State!') % _(dict(PURCHASE_ORDER_STATE_SELECTION).get(s['state'])))1651 raise osv.except_osv(_('Invalid action !'), _('Cannot delete Purchase Order(s) which are in %s State!') % _(dict(PURCHASE_ORDER_STATE_SELECTION).get(s['state'])))
16471652
1648 return super(purchase_order, self).unlink(cr, uid, ids, context=context)1653 return super(purchase_order, self).unlink(cr, uid, ids, context=context)
16491654
@@ -1675,18 +1680,18 @@
1675 This hook belongs to the rfq_sent method from tender_flow>tender_flow.py1680 This hook belongs to the rfq_sent method from tender_flow>tender_flow.py
1676 - check lines after import1681 - check lines after import
1677 '''1682 '''
1678 pol_obj = self.pool.get('purchase.order.line') 1683 pol_obj = self.pool.get('purchase.order.line')
16791684
1680 res = True 1685 res = True
1681 empty_lines = pol_obj.search(cr, uid, [ 1686 empty_lines = pol_obj.search(cr, uid, [
1682 ('order_id', 'in', ids), 1687 ('order_id', 'in', ids),
1683 ('product_qty', '<=', 0.00), 1688 ('product_qty', '<=', 0.00),
1684 ], context=context) 1689 ], context=context)
1685 if empty_lines: 1690 if empty_lines:
1686 raise osv.except_osv( 1691 raise osv.except_osv(
1687 _('Error'), 1692 _('Error'),
1688 _('All lines of the RfQ should have a quantity before sending the RfQ to the supplier'),1693 _('All lines of the RfQ should have a quantity before sending the RfQ to the supplier'),
1689 ) 1694 )
1690 return res1695 return res
16911696
1692 def action_sent(self, cr, uid, ids, context=None):1697 def action_sent(self, cr, uid, ids, context=None):
@@ -1695,7 +1700,7 @@
1695 '''1700 '''
1696 if context is None:1701 if context is None:
1697 context = {}1702 context = {}
1698 if isinstance(ids, (int,long)):1703 if isinstance(ids, (int, long)):
1699 ids = [ids]1704 ids = [ids]
17001705
1701 self.write(cr, uid, ids, {1706 self.write(cr, uid, ids, {
@@ -2123,7 +2128,7 @@
21232128
2124 po_accepted_values = {'client_action_multi': ['Order Follow Up',2129 po_accepted_values = {'client_action_multi': ['Order Follow Up',
2125 'action_view_purchase_order_group'],2130 'action_view_purchase_order_group'],
2126 'client_print_multi': ['Purchase Order (Merged)', 2131 'client_print_multi': ['Purchase Order (Merged)',
2127 'Purchase Order',2132 'Purchase Order',
2128 'Allocation report',2133 'Allocation report',
2129 'Order impact vs. Budget'],2134 'Order impact vs. Budget'],
@@ -2146,14 +2151,14 @@
2146 or v[1] == 'Purchase Order' \2151 or v[1] == 'Purchase Order' \
2147 or v[1] == 'Purchase Order (Merged)' \2152 or v[1] == 'Purchase Order (Merged)' \
2148 or v[1] == 'Allocation report' \2153 or v[1] == 'Allocation report' \
2149 or v[1] == 'Order impact vs. Budget' :2154 or v[1] == 'Order impact vs. Budget':
2150 new_values.append(v)2155 new_values.append(v)
2151 elif context.get('request_for_quotation', False) and 'purchase.order' in [x[0] for x in models]:2156 elif context.get('request_for_quotation', False) and 'purchase.order' in [x[0] for x in models]:
2152 new_values = []2157 new_values = []
2153 for v in values:2158 for v in values:
2154 if key == 'action' and v[1] in rfq_accepted_values[key2] \2159 if key == 'action' and v[1] in rfq_accepted_values[key2] \
2155 or v[1] == 'Request for Quotation' \2160 or v[1] == 'Request for Quotation' \
2156 or v[1] == 'Request For Quotation Excel Export' :2161 or v[1] == 'Request For Quotation Excel Export':
2157 new_values.append(v)2162 new_values.append(v)
21582163
2159 return new_values2164 return new_values
21602165
=== modified file 'bin/release.py'
--- bin/release.py 2018-01-30 16:12:16 +0000
+++ bin/release.py 2018-02-12 10:19:50 +0000
@@ -20,7 +20,7 @@
20##############################################################################20##############################################################################
2121
22name = 'openerp-server'22name = 'openerp-server'
23version = 'UF7.1'23version = 'UF8.0dev'
24major_version = '7.0'24major_version = '7.0'
25description = 'OpenERP Server'25description = 'OpenERP Server'
26long_desc = '''OpenERP is a complete ERP and CRM. The main features are accounting (analytic26long_desc = '''OpenERP is a complete ERP and CRM. The main features are accounting (analytic
2727
=== modified file 'bin/sql_db.py'
--- bin/sql_db.py 2017-10-19 14:14:14 +0000
+++ bin/sql_db.py 2018-02-12 10:19:50 +0000
@@ -390,6 +390,9 @@
390 try:390 try:
391 result = psycopg2.connect(dsn=dsn, connection_factory=PsycoConnection)391 result = psycopg2.connect(dsn=dsn, connection_factory=PsycoConnection)
392 except psycopg2.Error:392 except psycopg2.Error:
393 log = logging.getLogger()
394 if len(log.handlers) > 1:
395 log.removeHandler(log.handlers[1])
393 self.__logger.exception('Connection to the database failed')396 self.__logger.exception('Connection to the database failed')
394 raise397 raise
395 self._connections.append((result, True, time.time()))398 self._connections.append((result, True, time.time()))

Subscribers

People subscribed via source and target branches