import time
import pytz
-from openerp import SUPERUSER_ID
+from openerp import SUPERUSER_ID, workflow
from datetime import datetime
from dateutil.relativedelta import relativedelta
from operator import attrgetter
_name = "purchase.order"
_inherit = ['mail.thread', 'ir.needaction_mixin']
_description = "Purchase Order"
- _order = "name desc"
+ _order = 'date_order desc, id desc'
def create(self, cr, uid, vals, context=None):
if vals.get('name','/')=='/':
if not acc_id:
raise osv.except_osv(_('Error!'), _('Define expense account for this company: "%s" (id:%d).') % (po_line.product_id.name, po_line.product_id.id,))
else:
- acc_id = property_obj.get(cr, uid, 'property_account_expense_categ', 'product.category').id
+ acc_id = property_obj.get(cr, uid, 'property_account_expense_categ', 'product.category', context=context).id
fpos = po_line.order_id.fiscal_position or False
return fiscal_obj.map_account(cr, uid, fpos, acc_id)
:return: ID of created invoice.
:rtype: int
"""
- res = False
-
+ if context is None:
+ context = {}
journal_obj = self.pool.get('account.journal')
inv_obj = self.pool.get('account.invoice')
inv_line_obj = self.pool.get('account.invoice.line')
+ res = False
+ uid_company_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id
for order in self.browse(cr, uid, ids, context=context):
+ context.pop('force_company', None)
+ if order.company_id.id != uid_company_id:
+ #if the company of the document is different than the current user company, force the company in the context
+ #then re-do a browse to read the property fields for the good company.
+ context['force_company'] = order.company_id.id
+ order = self.browse(cr, uid, order.id, context=context)
pay_acc_id = order.partner_id.property_account_payable.id
- journal_ids = journal_obj.search(cr, uid, [('type', '=','purchase'),('company_id', '=', order.company_id.id)], limit=1)
+ journal_ids = journal_obj.search(cr, uid, [('type', '=', 'purchase'), ('company_id', '=', order.company_id.id)], limit=1)
if not journal_ids:
raise osv.except_osv(_('Error!'),
_('Define purchase journal for this company: "%s" (id:%d).') % (order.company_id.name, order.company_id.id))
inv_line_id = inv_line_obj.create(cr, uid, inv_line_data, context=context)
inv_lines.append(inv_line_id)
- po_line.write({'invoiced':True, 'invoice_lines': [(4, inv_line_id)]}, context=context)
+ po_line.write({'invoiced': True, 'invoice_lines': [(4, inv_line_id)]}, context=context)
# get invoice data and create invoice
inv_data = {
continue
if order_line.product_id.type in ('product', 'consu'):
move = stock_move.create(cr, uid, self._prepare_order_line_move(cr, uid, order, order_line, picking_id, context=context))
- if order_line.move_dest_id:
+ if order_line.move_dest_id and order_line.move_dest_id.state != 'done':
order_line.move_dest_id.write({'location_id': order.location_id.id})
todo_moves.append(move)
stock_move.action_confirm(cr, uid, todo_moves)
'invoiced':False,
'invoice_ids': [],
'picking_ids': [],
+ 'partner_ref': '',
'name': self.pool.get('ir.sequence').get(cr, uid, 'purchase.order'),
})
return super(purchase_order, self).copy(cr, uid, id, default, context)
res[line.id] = cur_obj.round(cr, uid, cur, taxes['total'])
return res
+ def _get_uom_id(self, cr, uid, context=None):
+ try:
+ proxy = self.pool.get('ir.model.data')
+ result = proxy.get_object_reference(cr, uid, 'product', 'product_uom_unit')
+ return result[1]
+ except Exception, ex:
+ return False
+
_columns = {
'name': fields.text('Description', required=True),
'product_qty': fields.float('Quantity', digits_compute=dp.get_precision('Product Unit of Measure'), required=True),
}
_defaults = {
+ 'product_uom' : _get_uom_id,
'product_qty': lambda *a: 1.0,
'state': lambda *args: 'draft',
'invoiced': lambda *a: 0,
default.update({'state':'draft', 'move_ids':[],'invoiced':0,'invoice_lines':[]})
return super(purchase_order_line, self).copy_data(cr, uid, id, default, context)
+ def unlink(self, cr, uid, ids, context=None):
+ procurement_ids_to_cancel = []
+ for line in self.browse(cr, uid, ids, context=context):
+ if line.move_dest_id:
+ procurement_ids_to_cancel.extend(procurement.id for procurement in line.move_dest_id.procurements)
+ if procurement_ids_to_cancel:
+ self.pool['procurement.order'].action_cancel(cr, uid, procurement_ids_to_cancel)
+ return super(purchase_order_line, self).unlink(cr, uid, ids, context=context)
+
def onchange_product_uom(self, cr, uid, ids, pricelist_id, product_id, qty, uom_id,
partner_id, date_order=False, fiscal_position_id=False, date_planned=False,
name=False, price_unit=False, context=None):
"""
onchange handler of product_uom.
"""
+ if context is None:
+ context = {}
if not uom_id:
return {'value': {'price_unit': price_unit or 0.0, 'name': name or '', 'product_uom' : uom_id or False}}
+ context = dict(context, purchase_uom_check=True)
return self.onchange_product_id(cr, uid, ids, pricelist_id, product_id, qty, uom_id,
partner_id, date_order=date_order, fiscal_position_id=fiscal_position_id, date_planned=date_planned,
name=name, price_unit=price_unit, context=context)
product_product = self.pool.get('product.product')
product_uom = self.pool.get('product.uom')
res_partner = self.pool.get('res.partner')
- product_supplierinfo = self.pool.get('product.supplierinfo')
product_pricelist = self.pool.get('product.pricelist')
account_fiscal_position = self.pool.get('account.fiscal.position')
account_tax = self.pool.get('account.tax')
uom_id = product_uom_po_id
if product.uom_id.category_id.id != product_uom.browse(cr, uid, uom_id, context=context).category_id.id:
- if self._check_product_uom_group(cr, uid, context=context):
+ if context.get('purchase_uom_check') and self._check_product_uom_group(cr, uid, context=context):
res['warning'] = {'title': _('Warning!'), 'message': _('Selected Unit of Measure does not belong to the same category as the product Unit of Measure.')}
uom_id = product_uom_po_id
partner_obj = self.pool.get('res.partner')
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
for procurement in self.browse(cr, uid, ids, context=context):
- if not procurement.product_id.seller_ids:
- message = _('No supplier defined for this product !')
- self.message_post(cr, uid, [procurement.id], body=message)
- cr.execute('update procurement_order set message=%s where id=%s', (message, procurement.id))
- return False
+ message = ''
partner = procurement.product_id.seller_id #Taken Main Supplier of Product of Procurement.
- if not partner:
+ if not procurement.product_id.seller_ids:
+ message = _('No supplier defined for this product !')
+ elif not partner:
message = _('No default supplier defined for this product')
- self.message_post(cr, uid, [procurement.id], body=message)
- cr.execute('update procurement_order set message=%s where id=%s', (message, procurement.id))
+ elif not partner_obj.address_get(cr, uid, [partner.id], ['delivery'])['delivery']:
+ message = _('No address defined for the supplier')
+
+ if message:
+ if procurement.message != message:
+ cr.execute('update procurement_order set message=%s where id=%s', (message, procurement.id))
return False
+
if user.company_id and user.company_id.partner_id:
if partner.id == user.company_id.partner_id.id:
raise osv.except_osv(_('Configuration Error!'), _('The product "%s" has been defined with your company as reseller which seems to be a configuration error!' % procurement.product_id.name))
- address_id = partner_obj.address_get(cr, uid, [partner.id], ['delivery'])['delivery']
- if not address_id:
- message = _('No address defined for the supplier')
- self.message_post(cr, uid, [procurement.id], body=message)
- cr.execute('update procurement_order set message=%s where id=%s', (message, procurement.id))
- return False
return True
seller_delay = int(procurement.product_id.seller_delay)
return schedule_date - relativedelta(days=seller_delay)
+ def _get_warehouse(self, procurement, user_company):
+ """
+ Return the warehouse containing the procurment stock location (or one of it ancestors)
+ If none match, returns then first warehouse of the company
+ """
+ # TODO refactor the domain once we implement the "parent_of" domain operator
+ # NOTE This method has been copied in the `purchase_requisition` module to ensure
+ # retro-compatibility. This code duplication will be deleted in next stable version.
+ # Do not forget to update both version in case of modification.
+ company_id = (procurement.company_id or user_company).id
+ domains = [
+ [
+ '&', ('company_id', '=', company_id),
+ '|', '&', ('lot_stock_id.parent_left', '<', procurement.location_id.parent_left),
+ ('lot_stock_id.parent_right', '>', procurement.location_id.parent_right),
+ ('lot_stock_id', '=', procurement.location_id.id)
+ ],
+ [('company_id', '=', company_id)]
+ ]
+
+ cr, uid = procurement._cr, procurement._uid
+ context = procurement._context
+ Warehouse = self.pool['stock.warehouse']
+ for domain in domains:
+ ids = Warehouse.search(cr, uid, domain, context=context)
+ if ids:
+ return ids[0]
+ return False
+
def make_po(self, cr, uid, ids, context=None):
""" Make purchase order from procurement
@return: New created Purchase Orders procurement wise
prod_obj = self.pool.get('product.product')
acc_pos_obj = self.pool.get('account.fiscal.position')
seq_obj = self.pool.get('ir.sequence')
- warehouse_obj = self.pool.get('stock.warehouse')
for procurement in self.browse(cr, uid, ids, context=context):
res_id = procurement.move_id.id
partner = procurement.product_id.seller_id # Taken Main Supplier of Product of Procurement.
partner_id = partner.id
address_id = partner_obj.address_get(cr, uid, [partner_id], ['delivery'])['delivery']
pricelist_id = partner.property_product_pricelist_purchase.id
- warehouse_id = warehouse_obj.search(cr, uid, [('company_id', '=', procurement.company_id.id or company.id)], context=context)
uom_id = procurement.product_id.uom_po_id.id
qty = uom_obj._compute_qty(cr, uid, procurement.product_uom.id, procurement.product_qty, uom_id)
'origin': procurement.origin,
'partner_id': partner_id,
'location_id': procurement.location_id.id,
- 'warehouse_id': warehouse_id and warehouse_id[0] or False,
+ 'warehouse_id': self._get_warehouse(procurement, company),
'pricelist_id': pricelist_id,
'date_order': purchase_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
'company_id': procurement.company_id.id,
def invoice_validate(self, cr, uid, ids, context=None):
res = super(account_invoice, self).invoice_validate(cr, uid, ids, context=context)
purchase_order_obj = self.pool.get('purchase.order')
- po_ids = purchase_order_obj.search(cr, uid, [('invoice_ids', 'in', ids)], context=context)
- if po_ids:
- purchase_order_obj.message_post(cr, uid, po_ids, body=_("Invoice received"), context=context)
+ # read access on purchase.order object is not required
+ if not purchase_order_obj.check_access_rights(cr, uid, 'read', raise_exception=False):
+ user_id = SUPERUSER_ID
+ else:
+ user_id = uid
+ po_ids = purchase_order_obj.search(cr, user_id, [('invoice_ids', 'in', ids)], context=context)
+ for po_id in po_ids:
+ purchase_order_obj.message_post(cr, user_id, po_id, body=_("Invoice received"), context=context)
+ workflow.trg_write(uid, 'purchase.order', po_id, cr)
return res
def confirm_paid(self, cr, uid, ids, context=None):
res = super(account_invoice, self).confirm_paid(cr, uid, ids, context=context)
purchase_order_obj = self.pool.get('purchase.order')
- po_ids = purchase_order_obj.search(cr, uid, [('invoice_ids', 'in', ids)], context=context)
- if po_ids:
- purchase_order_obj.message_post(cr, uid, po_ids, body=_("Invoice paid"), context=context)
+ # read access on purchase.order object is not required
+ if not purchase_order_obj.check_access_rights(cr, uid, 'read', raise_exception=False):
+ user_id = SUPERUSER_ID
+ else:
+ user_id = uid
+ po_ids = purchase_order_obj.search(cr, user_id, [('invoice_ids', 'in', ids)], context=context)
+ for po_id in po_ids:
+ purchase_order_obj.message_post(cr, user_id, po_id, body=_("Invoice paid"), context=context)
return res
class account_invoice_line(osv.Model):