diff --git a/addons/account/account.py b/addons/account/account.py
index d74bfce2f08..d4c34f49922 100644
--- a/addons/account/account.py
+++ b/addons/account/account.py
@@ -1154,6 +1154,19 @@ class account_move(osv.osv):
_description = "Account Entry"
_order = 'id desc'
+ def account_assert_balanced(self, cr, uid, context=None):
+ cr.execute("""\
+ SELECT move_id
+ FROM account_move_line
+ WHERE state = 'valid'
+ GROUP BY move_id
+ HAVING abs(sum(debit) - sum(credit)) > 0.00001
+ """)
+ assert len(cr.fetchall()) == 0, \
+ "For all Journal Items, the state is valid implies that the sum " \
+ "of credits equals the sum of debits"
+ return True
+
def account_move_prepare(self, cr, uid, journal_id, date=False, ref='', company_id=False, context=None):
'''
Prepares and returns a dictionary of values, ready to be passed to create() based on the parameters received.
@@ -2023,7 +2036,7 @@ class account_tax(osv.osv):
data['tax_amount']=quantity
# data['amount'] = quantity
elif tax.type=='code':
- localdict = {'price_unit':cur_price_unit, 'product':product, 'partner':partner}
+ localdict = {'price_unit':cur_price_unit, 'product':product, 'partner':partner, 'quantity': quantity}
exec tax.python_compute in localdict
amount = localdict['result']
data['amount'] = amount
diff --git a/addons/account/account_assert_test.xml b/addons/account/account_assert_test.xml
index 88025514763..32e8afb1b50 100644
--- a/addons/account/account_assert_test.xml
+++ b/addons/account/account_assert_test.xml
@@ -1,8 +1,6 @@
-
-
-
+
diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py
index 22bce5306be..9724451df5f 100644
--- a/addons/account_voucher/account_voucher.py
+++ b/addons/account_voucher/account_voucher.py
@@ -125,6 +125,9 @@ class account_voucher(osv.osv):
journal_pool = self.pool.get('account.journal')
journal_id = context.get('journal_id', False)
if journal_id:
+ if isinstance(journal_id, (list, tuple)):
+ # sometimes journal_id is a pair (id, display_name)
+ journal_id = journal_id[0]
journal = journal_pool.browse(cr, uid, journal_id, context=context)
if journal.currency:
return journal.currency.id
diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py
index 2c06865df44..e259de4cb44 100644
--- a/addons/crm/crm_lead.py
+++ b/addons/crm/crm_lead.py
@@ -789,7 +789,7 @@ class crm_lead(format_address, osv.osv):
partner_id = self._create_lead_partner(cr, uid, lead, context)
self.pool['res.partner'].write(cr, uid, partner_id, {'team_id': lead.team_id and lead.team_id.id or False})
if partner_id:
- lead.write({'partner_id': partner_id}, context=context)
+ lead.write({'partner_id': partner_id})
partner_ids[lead.id] = partner_id
return partner_ids
diff --git a/addons/delivery/sale.py b/addons/delivery/sale.py
index 4ef3224fc3e..a7e8b5d3716 100644
--- a/addons/delivery/sale.py
+++ b/addons/delivery/sale.py
@@ -53,10 +53,6 @@ class sale_order(osv.Model):
result['value']['carrier_id'] = dtype
return result
- def _prepare_order_picking(self, cr, uid, order, context=None):
- result = super(sale_order, self)._prepare_order_picking(cr, uid, order, context=context)
- result.update(carrier_id=order.carrier_id.id)
- return result
def _delivery_unset(self, cr, uid, ids, context=None):
sale_obj = self.pool['sale.order.line']
@@ -92,4 +88,4 @@ class sale_order(osv.Model):
'price_unit': grid_obj.get_price(cr, uid, grid.id, order, time.strftime('%Y-%m-%d'), context),
'tax_id': [(6, 0, taxes_ids)],
'is_delivery': True
- })
+ })
\ No newline at end of file
diff --git a/addons/delivery/stock.py b/addons/delivery/stock.py
index 7bfd52df420..c8781244fe0 100644
--- a/addons/delivery/stock.py
+++ b/addons/delivery/stock.py
@@ -120,9 +120,10 @@ class stock_picking(osv.osv):
}
def _create_invoice_from_picking(self, cr, uid, picking, vals, context=None):
+ invoice_obj = self.pool.get('account.invoice')
invoice_line_obj = self.pool.get('account.invoice.line')
invoice_id = super(stock_picking, self)._create_invoice_from_picking(cr, uid, picking, vals, context=context)
- invoice = self.browse(cr, uid, invoice_id, context=context)
+ invoice = invoice_obj.browse(cr, uid, invoice_id, context=context)
invoice_line = self._prepare_shipping_invoice_line(cr, uid, picking, invoice, context=context)
if invoice_line:
invoice_line_obj.create(cr, uid, invoice_line)
@@ -170,6 +171,24 @@ class stock_move(osv.osv):
'weight_uom_id': fields.many2one('product.uom', 'Unit of Measure', required=True,readonly="1",help="Unit of Measure (Unit of Measure) is the unit of measurement for Weight",),
}
+ def action_confirm(self, cr, uid, ids, context=None):
+ """
+ Pass the carrier to the picking from the sales order
+ (Should also work in case of Phantom BoMs when on explosion the original move is deleted)
+ """
+ procs_to_check = []
+ for move in self.browse(cr, uid, ids, context=context):
+ if move.procurement_id and move.procurement_id.sale_line_id and move.procurement_id.sale_line_id.order_id.carrier_id:
+ procs_to_check += [move.procurement_id]
+ res = super(stock_move, self).action_confirm(cr, uid, ids, context=context)
+ pick_obj = self.pool.get("stock.picking")
+ for proc in procs_to_check:
+ pickings = list(set([x.picking_id.id for x in proc.move_ids if x.picking_id and not x.picking_id.carrier_id]))
+ if pickings:
+ pick_obj.write(cr, uid, pickings, {'carrier_id': proc.sale_line_id.order_id.carrier_id.id}, context=context)
+ return res
+
+
def _get_default_uom(self, cr, uid, context=None):
uom_categ_id = self.pool.get('ir.model.data').xmlid_to_res_id(cr, uid, 'product.product_uom_categ_kgm')
return self.pool.get('product.uom').search(cr, uid, [('category_id', '=', uom_categ_id),('factor','=',1)])[0]
diff --git a/addons/fleet/fleet.py b/addons/fleet/fleet.py
index 6f62d114c0d..1b2b96ffbfb 100644
--- a/addons/fleet/fleet.py
+++ b/addons/fleet/fleet.py
@@ -426,8 +426,10 @@ class fleet_vehicle_odometer(osv.Model):
res = {}
for record in self.browse(cr, uid, ids, context=context):
name = record.vehicle_id.name
- if record.date:
- name = name+ ' / '+ str(record.date)
+ if not name:
+ name = record.date
+ elif record.date:
+ name += ' / '+ record.date
res[record.id] = name
return res
diff --git a/addons/google_calendar/google_calendar.py b/addons/google_calendar/google_calendar.py
index 03a311dd2ff..3d1a87661d2 100644
--- a/addons/google_calendar/google_calendar.py
+++ b/addons/google_calendar/google_calendar.py
@@ -494,7 +494,7 @@ class google_calendar(osv.AbstractModel):
all_my_attendees = self.pool['calendar.attendee'].search(cr, uid, [('partner_id', '=', current_user.partner_id.id)], context=context)
self.pool['calendar.attendee'].write(cr, uid, all_my_attendees, {'oe_synchro_date': False, 'google_internal_event_id': False}, context=context)
- current_user.write(reset_data, context=context)
+ current_user.write(reset_data)
return True
def synchronize_events_cron(self, cr, uid, context=None):
@@ -552,7 +552,7 @@ class google_calendar(osv.AbstractModel):
lastSync = False
_logger.info("[%s] Calendar Synchro - MODE FULL SYNCHRO FORCED" % user_to_sync)
else:
- current_user.write({'google_calendar_cal_id': current_google}, context=context)
+ current_user.write({'google_calendar_cal_id': current_google})
lastSync = False
_logger.info("[%s] Calendar Synchro - MODE FULL SYNCHRO - NEW CAL ID" % user_to_sync)
@@ -562,7 +562,7 @@ class google_calendar(osv.AbstractModel):
res = self.update_events(cr, uid, lastSync, context)
- current_user.write({'google_calendar_last_sync_date': ask_time}, context=context)
+ current_user.write({'google_calendar_last_sync_date': ask_time})
return {
"status": res and "need_refresh" or "no_new_event_form_google",
"url": ''
diff --git a/addons/hr/static/src/xml/suggestions.xml b/addons/hr/static/src/xml/suggestions.xml
index 816011852ca..6b7fbd43bf7 100644
--- a/addons/hr/static/src/xml/suggestions.xml
+++ b/addons/hr/static/src/xml/suggestions.xml
@@ -24,7 +24,7 @@
diff --git a/addons/hr_recruitment/hr_recruitment.py b/addons/hr_recruitment/hr_recruitment.py
index 071441a2c81..833da7ca684 100644
--- a/addons/hr_recruitment/hr_recruitment.py
+++ b/addons/hr_recruitment/hr_recruitment.py
@@ -493,7 +493,7 @@ class hr_applicant(osv.Model):
address_id = self.pool.get('res.partner').address_get(cr, uid, [applicant.partner_id.id], ['contact'])['contact']
contact_name = self.pool.get('res.partner').name_get(cr, uid, [applicant.partner_id.id])[0][1]
if applicant.job_id and (applicant.partner_name or contact_name):
- applicant.job_id.write({'no_of_hired_employee': applicant.job_id.no_of_hired_employee + 1}, context=context)
+ applicant.job_id.write({'no_of_hired_employee': applicant.job_id.no_of_hired_employee + 1})
create_ctx = dict(context, mail_broadcast=True)
emp_id = hr_employee.create(cr, uid, {'name': applicant.partner_name or contact_name,
'job_id': applicant.job_id.id,
diff --git a/addons/hr_timesheet/security/ir.model.access.csv b/addons/hr_timesheet/security/ir.model.access.csv
index b48988700db..757cd84f4b5 100644
--- a/addons/hr_timesheet/security/ir.model.access.csv
+++ b/addons/hr_timesheet/security/ir.model.access.csv
@@ -10,3 +10,4 @@ access_product_uom_hr_timesheet,product.uom.hr.timesheet,product.model_product_u
access_account_fiscalyear_hr_user,account.account.fiscalyear.user,account.model_account_fiscalyear,base.group_hr_user,1,1,1,1
access_hr_analytic_timesheet_user,hr.analytic.timesheet.user,model_hr_analytic_timesheet,base.group_user,1,1,1,0
access_account_analytic_journal_user,account.account.analytic.journal.user,analytic.model_account_analytic_journal,base.group_user,1,0,0,0
+access_hr_timesheet_report,hr.timesheet.report,model_hr_timesheet_report,base.group_hr_manager,1,1,0,0
diff --git a/addons/hr_timesheet_sheet/security/ir.model.access.csv b/addons/hr_timesheet_sheet/security/ir.model.access.csv
index 8eef30b35c4..2ad3c7d5ca2 100644
--- a/addons/hr_timesheet_sheet/security/ir.model.access.csv
+++ b/addons/hr_timesheet_sheet/security/ir.model.access.csv
@@ -3,6 +3,5 @@ access_hr_timesheet_sheet_sheet_user,hr_timesheet_sheet.sheet.user,model_hr_time
access_hr_timesheet_sheet_sheet_system_employee,hr_timesheet_sheet.sheet.system.employee,model_hr_timesheet_sheet_sheet,base.group_user,1,1,1,0
access_hr_timesheet_sheet_sheet_day,hr_timesheet_sheet.sheet.day,model_hr_timesheet_sheet_sheet_day,base.group_hr_user,1,1,1,1
access_hr_timesheet_sheet_sheet_account,hr_timesheet_sheet.sheet.account,model_hr_timesheet_sheet_sheet_account,base.group_hr_user,1,1,1,1
-access_hr_timesheet_report,hr.timesheet.report,model_hr_timesheet_report,base.group_hr_manager,1,1,0,0
access_hr_analytic_timesheet_system_user,hr.analytic.timesheet.system.user,model_hr_analytic_timesheet,base.group_user,1,0,0,0
access_hr_timesheet_sheet_sheet_day,hr.timesheet.sheet.sheet.day.user,model_hr_timesheet_sheet_sheet_day,base.group_user,1,1,1,0
diff --git a/addons/mail/static/src/xml/suggestions.xml b/addons/mail/static/src/xml/suggestions.xml
index 8279726ca45..52bc0aea4eb 100644
--- a/addons/mail/static/src/xml/suggestions.xml
+++ b/addons/mail/static/src/xml/suggestions.xml
@@ -25,7 +25,7 @@
diff --git a/addons/mrp/mrp.py b/addons/mrp/mrp.py
index 8b3da7b49c1..914cfc376a6 100644
--- a/addons/mrp/mrp.py
+++ b/addons/mrp/mrp.py
@@ -334,6 +334,11 @@ class mrp_bom(osv.osv):
res['value'].update({'product_uom': product.uom_id.id})
return res
+ def unlink(self, cr, uid, ids, context=None):
+ if self.pool['mrp.production'].search(cr, uid, [('bom_id', 'in', ids), ('state', 'not in', ['done', 'cancel'])], context=context):
+ raise osv.except_osv(_('Warning!'), _('You can not delete a Bill of Material with running manufacturing orders.\nPlease close or cancel it first.'))
+ return super(mrp_bom, self).unlink(cr, uid, ids, context=context)
+
def onchange_product_tmpl_id(self, cr, uid, ids, product_tmpl_id, product_qty=0, context=None):
""" Changes UoM and name if product_id changes.
@param product_id: Changed product_id
@@ -1200,7 +1205,7 @@ class mrp_production(osv.osv):
self._make_service_procurement(cr, uid, line, context=context)
if stock_moves:
self.pool.get('stock.move').action_confirm(cr, uid, stock_moves, context=context)
- production.write({'state': 'confirmed'}, context=context)
+ production.write({'state': 'confirmed'})
return 0
def action_assign(self, cr, uid, ids, context=None):
diff --git a/addons/point_of_sale/security/point_of_sale_security.xml b/addons/point_of_sale/security/point_of_sale_security.xml
index 58096a0b21d..1a472061220 100644
--- a/addons/point_of_sale/security/point_of_sale_security.xml
+++ b/addons/point_of_sale/security/point_of_sale_security.xml
@@ -25,5 +25,11 @@
[('company_id','child_of',[user.company_id.id])]
+
+ Point Of Sale Order Analysis multi-company
+
+
+ ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]
+
diff --git a/addons/point_of_sale/static/src/css/pos.css b/addons/point_of_sale/static/src/css/pos.css
index 2f647bbcb15..4e630488c96 100644
--- a/addons/point_of_sale/static/src/css/pos.css
+++ b/addons/point_of_sale/static/src/css/pos.css
@@ -1169,6 +1169,9 @@ td {
}
@media print {
+ * {
+ color: black !important;
+ }
body {
margin: 0;
}
diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js
index c746d12c8fc..07be5f01bb2 100644
--- a/addons/point_of_sale/static/src/js/models.js
+++ b/addons/point_of_sale/static/src/js/models.js
@@ -811,10 +811,13 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
get_unit_price: function(){
return this.price;
},
- get_display_price: function(){
+ get_base_price: function(){
var rounding = this.pos.currency.rounding;
return round_pr(round_pr(this.get_unit_price() * this.get_quantity(),rounding) * (1- this.get_discount()/100.0),rounding);
},
+ get_display_price: function(){
+ return this.get_base_price();
+ },
get_price_without_tax: function(){
return this.get_all_prices().priceWithoutTax;
},
@@ -830,7 +833,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
get_all_prices: function(){
var self = this;
var currency_rounding = this.pos.currency.rounding;
- var base = round_pr(this.get_quantity() * this.get_unit_price() * (1.0 - (this.get_discount() / 100.0)), currency_rounding);
+ var base = this.get_base_price();
var totalTax = base;
var totalNoTax = base;
diff --git a/addons/portal/__openerp__.py b/addons/portal/__openerp__.py
index 361971b0d92..042f2f20381 100644
--- a/addons/portal/__openerp__.py
+++ b/addons/portal/__openerp__.py
@@ -33,7 +33,7 @@
Customize access to your OpenERP database to external users by creating portals.
================================================================================
A portal defines a specific user menu and access rights for its members. This
-menu can ben seen by portal members, public users and any other user that
+menu can be seen by portal members, public users and any other user that
have the access to technical features (e.g. the administrator).
Also, each portal member is linked to a specific partner.
diff --git a/addons/product/product.py b/addons/product/product.py
index 3bcdf41cc2b..128aae5b1f7 100644
--- a/addons/product/product.py
+++ b/addons/product/product.py
@@ -847,7 +847,7 @@ class product_product(osv.osv):
context['uom'], value, uom.id)
value = value - product.price_extra
- return product.write({'list_price': value}, context=context)
+ return product.write({'list_price': value})
def _get_partner_code_name(self, cr, uid, ids, product, partner_id, context=None):
for supinfo in product.seller_ids:
@@ -898,8 +898,8 @@ class product_product(osv.osv):
res = self.write(cr, uid, [id], {'image_variant': image}, context=context)
product = self.browse(cr, uid, id, context=context)
if not product.product_tmpl_id.image:
- product.write({'image_variant': None}, context=context)
- product.product_tmpl_id.write({'image': image}, context=context)
+ product.write({'image_variant': None})
+ product.product_tmpl_id.write({'image': image})
return res
def _get_price_extra(self, cr, uid, ids, name, args, context=None):
@@ -1062,7 +1062,7 @@ class product_product(osv.osv):
if not limit or len(ids) < limit:
# we may underrun the limit because of dupes in the results, that's fine
limit2 = (limit - len(ids)) if limit else False
- ids.update(self.search(cr, user, args + [('name', operator, name)], limit=limit2, context=context))
+ ids.update(self.search(cr, user, args + [('name', operator, name), ('id', 'not in', list(ids))], limit=limit2, context=context))
ids = list(ids)
elif not ids and operator in expression.NEGATIVE_TERM_OPERATORS:
ids = self.search(cr, user, args + ['&', ('default_code', operator, name), ('name', operator, name)], limit=limit, context=context)
diff --git a/addons/project_timesheet/project_timesheet.py b/addons/project_timesheet/project_timesheet.py
index 39f48c47ea9..36e57341b2d 100644
--- a/addons/project_timesheet/project_timesheet.py
+++ b/addons/project_timesheet/project_timesheet.py
@@ -103,50 +103,57 @@ class project_work(osv.osv):
res['product_uom_id'] = emp.product_id.uom_id.id
return res
- def create(self, cr, uid, vals, *args, **kwargs):
- timesheet_obj = self.pool.get('hr.analytic.timesheet')
- task_obj = self.pool.get('project.task')
- uom_obj = self.pool.get('product.uom')
+ def _create_analytic_entries(self, cr, uid, vals, context):
+ """Create the hr analytic timesheet from project task work"""
+ timesheet_obj = self.pool['hr.analytic.timesheet']
+ task_obj = self.pool['project.task']
vals_line = {}
+ timeline_id = False
+ acc_id = False
+
+ task_obj = task_obj.browse(cr, uid, vals['task_id'], context=context)
+ result = self.get_user_related_details(cr, uid, vals.get('user_id', uid))
+ vals_line['name'] = '%s: %s' % (tools.ustr(task_obj.name), tools.ustr(vals['name'] or '/'))
+ vals_line['user_id'] = vals['user_id']
+ vals_line['product_id'] = result['product_id']
+ if vals.get('date'):
+ vals_line['date' ] = vals['date'][:10]
+
+ # Calculate quantity based on employee's product's uom
+ vals_line['unit_amount'] = vals['hours']
+
+ default_uom = self.pool['res.users'].browse(cr, uid, uid, context=context).company_id.project_time_mode_id.id
+ if result['product_uom_id'] != default_uom:
+ vals_line['unit_amount'] = self.pool['product.uom']._compute_qty(cr, uid, default_uom, vals['hours'], result['product_uom_id'])
+ acc_id = task_obj.project_id and task_obj.project_id.analytic_account_id.id or acc_id
+ if acc_id:
+ vals_line['account_id'] = acc_id
+ res = timesheet_obj.on_change_account_id(cr, uid, False, acc_id)
+ if res.get('value'):
+ vals_line.update(res['value'])
+ vals_line['general_account_id'] = result['general_account_id']
+ vals_line['journal_id'] = result['journal_id']
+ vals_line['amount'] = 0.0
+ vals_line['product_uom_id'] = result['product_uom_id']
+ amount = vals_line['unit_amount']
+ prod_id = vals_line['product_id']
+ unit = False
+ timeline_id = timesheet_obj.create(cr, uid, vals=vals_line, context=context)
+
+ # Compute based on pricetype
+ amount_unit = timesheet_obj.on_change_unit_amount(cr, uid, timeline_id,
+ prod_id, amount, False, unit, vals_line['journal_id'], context=context)
+ if amount_unit and 'amount' in amount_unit.get('value',{}):
+ updv = { 'amount': amount_unit['value']['amount'] }
+ timesheet_obj.write(cr, uid, [timeline_id], updv, context=context)
+
+ return timeline_id
+
+ def create(self, cr, uid, vals, *args, **kwargs):
context = kwargs.get('context', {})
if not context.get('no_analytic_entry',False):
- task_obj = task_obj.browse(cr, uid, vals['task_id'])
- result = self.get_user_related_details(cr, uid, vals.get('user_id', uid))
- vals_line['name'] = '%s: %s' % (tools.ustr(task_obj.name), tools.ustr(vals['name'] or '/'))
- vals_line['user_id'] = vals['user_id']
- vals_line['product_id'] = result['product_id']
- vals_line['date'] = vals['date'][:10]
-
- # Calculate quantity based on employee's product's uom
- vals_line['unit_amount'] = vals['hours']
-
- default_uom = self.pool.get('res.users').browse(cr, uid, uid).company_id.project_time_mode_id.id
- if result['product_uom_id'] != default_uom:
- vals_line['unit_amount'] = uom_obj._compute_qty(cr, uid, default_uom, vals['hours'], result['product_uom_id'])
- acc_id = task_obj.project_id and task_obj.project_id.analytic_account_id.id or False
- if acc_id:
- vals_line['account_id'] = acc_id
- res = timesheet_obj.on_change_account_id(cr, uid, False, acc_id)
- if res.get('value'):
- vals_line.update(res['value'])
- vals_line['general_account_id'] = result['general_account_id']
- vals_line['journal_id'] = result['journal_id']
- vals_line['amount'] = 0.0
- vals_line['product_uom_id'] = result['product_uom_id']
- amount = vals_line['unit_amount']
- prod_id = vals_line['product_id']
- unit = False
- context = dict(context, recompute=True)
- timeline_id = timesheet_obj.create(cr, uid, vals_line, context=context)
-
- # Compute based on pricetype
- amount_unit = timesheet_obj.on_change_unit_amount(cr, uid, timeline_id,
- prod_id, amount, False, unit, vals_line['journal_id'], context=context)
- if amount_unit and 'amount' in amount_unit.get('value',{}):
- updv = { 'amount': amount_unit['value']['amount'] }
- timesheet_obj.write(cr, uid, [timeline_id], updv, context=context)
- vals['hr_analytic_timesheet_id'] = timeline_id
+ vals['hr_analytic_timesheet_id'] = self._create_analytic_entries(cr, uid, vals, context=context)
return super(project_work,self).create(cr, uid, vals, *args, **kwargs)
def write(self, cr, uid, ids, vals, context=None):
@@ -234,6 +241,10 @@ class task(osv.osv):
def write(self, cr, uid, ids, vals, context=None):
if context is None:
context = {}
+ task_work_obj = self.pool['project.task.work']
+ acc_id = False
+ missing_analytic_entries = {}
+
if vals.get('project_id',False) or vals.get('name',False):
vals_line = {}
hr_anlytic_timesheet = self.pool.get('hr.analytic.timesheet')
@@ -245,6 +256,16 @@ class task(osv.osv):
if len(task_obj.work_ids):
for task_work in task_obj.work_ids:
if not task_work.hr_analytic_timesheet_id:
+ if acc_id :
+ # missing timesheet activities to generate
+ missing_analytic_entries[task_work.id] = {
+ 'name' : task_work.name,
+ 'user_id' : task_work.user_id.id,
+ 'date' : task_work.date and task_work.date[:10] or False,
+ 'account_id': acc_id,
+ 'hours' : task_work.hours,
+ 'task_id' : task_obj.id
+ }
continue
line_id = task_work.hr_analytic_timesheet_id.id
if vals.get('project_id',False):
@@ -252,7 +273,14 @@ class task(osv.osv):
if vals.get('name',False):
vals_line['name'] = '%s: %s' % (tools.ustr(vals['name']), tools.ustr(task_work.name) or '/')
hr_anlytic_timesheet.write(cr, uid, [line_id], vals_line, {})
- return super(task,self).write(cr, uid, ids, vals, context)
+
+ res = super(task,self).write(cr, uid, ids, vals, context)
+
+ for task_work_id, analytic_entry in missing_analytic_entries.items():
+ timeline_id = task_work_obj._create_analytic_entries(cr, uid, analytic_entry, context=context)
+ task_work_obj.write(cr, uid, task_work_id, {'hr_analytic_timesheet_id' : timeline_id}, context=context)
+
+ return res
class res_partner(osv.osv):
diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py
index 338437a5ecf..5dd100c6905 100644
--- a/addons/purchase/purchase.py
+++ b/addons/purchase/purchase.py
@@ -150,7 +150,20 @@ class purchase_order(osv.osv):
def _get_picking_in(self, cr, uid, context=None):
obj_data = self.pool.get('ir.model.data')
- return obj_data.get_object_reference(cr, uid, 'stock','picking_type_in') and obj_data.get_object_reference(cr, uid, 'stock','picking_type_in')[1] or False
+ type_obj = self.pool.get('stock.picking.type')
+ user_obj = self.pool.get('res.users')
+ company_id = user_obj.browse(cr, uid, uid, context=context).company_id.id
+ pick_type = obj_data.get_object_reference(cr, uid, 'stock', 'picking_type_in') and obj_data.get_object_reference(cr, uid, 'stock', 'picking_type_in')[1] or False
+ if pick_type:
+ type = type_obj.browse(cr, uid, pick_type, context=context)
+ if type and type.warehouse_id and type.warehouse_id.company_id.id == company_id:
+ return pick_type
+ types = type_obj.search(cr, uid, [('code', '=', 'incoming'), ('warehouse_id.company_id', '=', company_id)], context=context)
+ if not types:
+ types = type_obj.search(cr, uid, [('code', '=', 'incoming'), ('warehouse_id', '=', False)], context=context)
+ if not types:
+ raise osv.except_osv(_('Error!'), _("Make sure you have at least an incoming picking type defined"))
+ return types[0]
def _get_picking_ids(self, cr, uid, ids, field_names, args, context=None):
res = {}
diff --git a/addons/sale/sale.py b/addons/sale/sale.py
index af257f8d22e..2cbc975ae4c 100644
--- a/addons/sale/sale.py
+++ b/addons/sale/sale.py
@@ -701,7 +701,7 @@ class sale_order(osv.osv):
vals = self._prepare_procurement_group(cr, uid, order, context=context)
if not order.procurement_group_id:
group_id = self.pool.get("procurement.group").create(cr, uid, vals, context=context)
- order.write({'procurement_group_id': group_id}, context=context)
+ order.write({'procurement_group_id': group_id})
for line in order.order_line:
#Try to fix exception procurement (possible when after a shipping exception the user choose to recreate)
@@ -711,10 +711,11 @@ class sale_order(osv.osv):
line.refresh()
#run again procurement that are in exception in order to trigger another move
proc_ids += [x.id for x in line.procurement_ids if x.state in ('exception', 'cancel')]
+ procurement_obj.reset_to_confirmed(cr, uid, proc_ids, context=context)
elif sale_line_obj.need_procurement(cr, uid, [line.id], context=context):
if (line.state == 'done') or not line.product_id:
continue
- vals = self._prepare_order_line_procurement(cr, uid, order, line, group_id=group_id, context=context)
+ vals = self._prepare_order_line_procurement(cr, uid, order, line, group_id=order.procurement_group_id.id, context=context)
proc_id = procurement_obj.create(cr, uid, vals, context=context)
proc_ids.append(proc_id)
#Confirm procurement order such that rules will be applied on it
diff --git a/addons/sale_journal/sale_journal.py b/addons/sale_journal/sale_journal.py
index 076692cbf4a..f6e4abb6b53 100644
--- a/addons/sale_journal/sale_journal.py
+++ b/addons/sale_journal/sale_journal.py
@@ -61,17 +61,33 @@ class picking(osv.osv):
}
+class stock_move(osv.osv):
+ _inherit = "stock.move"
+
+ def action_confirm(self, cr, uid, ids, context=None):
+ """
+ Pass the invoice type to the picking from the sales order
+ (Should also work in case of Phantom BoMs when on explosion the original move is deleted, similar to carrier_id on delivery)
+ """
+ procs_to_check = []
+ for move in self.browse(cr, uid, ids, context=context):
+ if move.procurement_id and move.procurement_id.sale_line_id and move.procurement_id.sale_line_id.order_id.invoice_type_id:
+ procs_to_check += [move.procurement_id]
+ res = super(stock_move, self).action_confirm(cr, uid, ids, context=context)
+ pick_obj = self.pool.get("stock.picking")
+ for proc in procs_to_check:
+ pickings = list(set([x.picking_id.id for x in proc.move_ids if x.picking_id and not x.picking_id.invoice_type_id]))
+ if pickings:
+ pick_obj.write(cr, uid, pickings, {'invoice_type_id': proc.sale_line_id.order_id.invoice_type_id.id}, context=context)
+ return res
+
+
class sale(osv.osv):
_inherit = "sale.order"
_columns = {
'invoice_type_id': fields.many2one('sale_journal.invoice.type', 'Invoice Type', help="Generate invoice based on the selected option.")
}
- def _prepare_order_picking(self, cr, uid, order, context=None):
- result = super(sale,self)._prepare_order_picking(cr, uid, order, context=context)
- result.update(invoice_type_id=order.invoice_type_id and order.invoice_type_id.id or False)
- return result
-
def onchange_partner_id(self, cr, uid, ids, part, context=None):
result = super(sale, self).onchange_partner_id(cr, uid, ids, part, context=context)
if part:
diff --git a/addons/sale_stock/sale_stock_view.xml b/addons/sale_stock/sale_stock_view.xml
index 0d5223a03c8..404316324f5 100644
--- a/addons/sale_stock/sale_stock_view.xml
+++ b/addons/sale_stock/sale_stock_view.xml
@@ -38,17 +38,11 @@
+ on_change="product_id_change_with_wh(parent.pricelist_id,product_id,product_uom_qty,product_uom,product_uos_qty,False,name,parent.partner_id, False, False, parent.date_order, product_packaging, parent.fiscal_position, True, parent.warehouse_id, context)"/>
-
-
-
-
-
+
diff --git a/addons/stock/procurement.py b/addons/stock/procurement.py
index 07024a2529e..c105ed6c017 100644
--- a/addons/stock/procurement.py
+++ b/addons/stock/procurement.py
@@ -273,7 +273,7 @@ class procurement_order(osv.osv):
@param context: A standard dictionary for contextual values
@return: Dictionary of values
'''
- super(procurement_order, self).run_scheduler(cr, uid, use_new_cursor=use_new_cursor, context=context)
+ super(procurement_order, self).run_scheduler(cr, uid, use_new_cursor=use_new_cursor, company_id=company_id, context=context)
if context is None:
context = {}
try:
@@ -283,7 +283,7 @@ class procurement_order(osv.osv):
move_obj = self.pool.get('stock.move')
#Minimum stock rules
- self._procure_orderpoint_confirm(cr, SUPERUSER_ID, use_new_cursor=False, company_id=company_id, context=context)
+ self._procure_orderpoint_confirm(cr, SUPERUSER_ID, use_new_cursor=use_new_cursor, company_id=company_id, context=context)
#Search all confirmed stock_moves and try to assign them
confirmed_ids = move_obj.search(cr, uid, [('state', '=', 'confirmed')], limit=None, order='priority desc, date_expected asc', context=context)
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index ecaed0133a0..75def9b40d1 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -2640,13 +2640,27 @@ class stock_inventory(osv.osv):
def prepare_inventory(self, cr, uid, ids, context=None):
inventory_line_obj = self.pool.get('stock.inventory.line')
for inventory in self.browse(cr, uid, ids, context=context):
- #clean the existing inventory lines before redoing an inventory proposal
+ # If there are inventory lines already (e.g. from import), respect those and set their theoretical qty
line_ids = [line.id for line in inventory.line_ids]
- inventory_line_obj.unlink(cr, uid, line_ids, context=context)
- #compute the inventory lines and create them
- vals = self._get_inventory_lines(cr, uid, inventory, context=context)
- for product_line in vals:
- inventory_line_obj.create(cr, uid, product_line, context=context)
+ if not line_ids:
+ #compute the inventory lines and create them
+ vals = self._get_inventory_lines(cr, uid, inventory, context=context)
+ for product_line in vals:
+ inventory_line_obj.create(cr, uid, product_line, context=context)
+ else:
+ # On import calculate theoretical quantity
+ quant_obj = self.pool.get("stock.quant")
+ for line in inventory.line_ids:
+ dom = [('company_id', '=', line.company_id.id), ('location_id', 'child_of', line.location_id.id), ('lot_id', '=', line.prod_lot_id.id),
+ ('product_id','=', line.product_id.id), ('owner_id', '=', line.partner_id.id)]
+ if line.package_id:
+ dom += [('package_id', '=', line.package_id.id)]
+ quants = quant_obj.search(cr, uid, dom, context=context)
+ tot_qty = 0
+ for quant in quant_obj.browse(cr, uid, quants, context=context):
+ tot_qty += quant.qty
+ inventory_line_obj.write(cr, uid, [line.id], {'theoretical_qty': tot_qty}, context=context)
+
return self.write(cr, uid, ids, {'state': 'confirm', 'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)})
def _get_inventory_lines(self, cr, uid, inventory, context=None):
@@ -2712,7 +2726,7 @@ class stock_inventory_line(osv.osv):
'company_id': fields.related('inventory_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, select=True, readonly=True),
'prod_lot_id': fields.many2one('stock.production.lot', 'Serial Number', domain="[('product_id','=',product_id)]"),
'state': fields.related('inventory_id', 'state', type='char', string='Status', readonly=True),
- 'theoretical_qty': fields.float('Theoretical Quantity', readonly=True),
+ 'theoretical_qty': fields.float('Theoretical Quantity', digits_compute=dp.get_precision('Product Unit of Measure'), readonly=True),
'partner_id': fields.many2one('res.partner', 'Owner'),
'product_name': fields.related('product_id', 'name', type='char', string='Product Name', store={
'product.product': (_get_product_name_change, ['name', 'default_code'], 20),
diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml
index d923f5f6002..a95300d8744 100644
--- a/addons/stock/stock_view.xml
+++ b/addons/stock/stock_view.xml
@@ -1097,7 +1097,7 @@
-
+
@@ -1658,7 +1658,7 @@
stock.quant
-