#
##############################################################################
-from mx import DateTime
import time
from datetime import datetime
from dateutil.relativedelta import relativedelta
from osv import osv, fields
import netsvc
-import ir
import pooler
-from tools import config
from tools.translate import _
import decimal_precision as dp
from osv.orm import browse_record, browse_null
# Model definition
#
class purchase_order(osv.osv):
+
def _calc_amount(self, cr, uid, ids, prop, unknow_none, unknow_dict):
res = {}
for order in self.browse(cr, uid, ids):
def _amount_all(self, cr, uid, ids, field_name, arg, context=None):
res = {}
cur_obj=self.pool.get('res.currency')
- for order in self.browse(cr, uid, ids):
+ for order in self.browse(cr, uid, ids, context=context):
res[order.id] = {
'amount_untaxed': 0.0,
'amount_tax': 0.0,
if not value: return False
if type(ids)!=type([]):
ids=[ids]
- for po in self.browse(cr, uid, ids, context):
- cr.execute("""update purchase_order_line set
- date_planned=%s
- where
- order_id=%s and
- (date_planned=%s or date_planned<%s)""", (value,po.id,po.minimum_planned_date,value))
+ for po in self.browse(cr, uid, ids, context=context):
+ if po.order_line:
+ cr.execute("""update purchase_order_line set
+ date_planned=%s
+ where
+ order_id=%s and
+ (date_planned=%s or date_planned<%s)""", (value,po.id,po.minimum_planned_date,value))
+ cr.execute("""update purchase_order set
+ minimum_planned_date=%s where id=%s""", (value, po.id))
return True
def _minimum_planned_date(self, cr, uid, ids, field_name, arg, context=None):
res={}
purchase_obj=self.browse(cr, uid, ids, context=context)
for purchase in purchase_obj:
- res[purchase.id] = time.strftime('%Y-%m-%d %H:%M:%S')
+ res[purchase.id] = False
if purchase.order_line:
min_date=purchase.order_line[0].date_planned
for line in purchase.order_line:
res[purchase.id]=min_date
return res
+
def _invoiced_rate(self, cursor, user, ids, name, arg, context=None):
res = {}
for purchase in self.browse(cursor, user, ids, context=context):
tot = 0.0
- if purchase.invoice_id and purchase.invoice_id.state not in ('draft','cancel'):
- tot += purchase.invoice_id.amount_untaxed
+ for invoice in purchase.invoice_ids:
+ if invoice.state not in ('draft','cancel'):
+ tot += invoice.amount_untaxed
+
if purchase.amount_untaxed:
- res[purchase.id] = tot * 100.0 / purchase.amount_untaxed
+ res[purchase.id] = min(100.0, tot * 100.0 / (purchase.amount_untaxed))
else:
res[purchase.id] = 0.0
return res
def _invoiced(self, cursor, user, ids, name, arg, context=None):
res = {}
for purchase in self.browse(cursor, user, ids, context=context):
- if purchase.invoice_id.reconciled:
- res[purchase.id] = purchase.invoice_id.reconciled
- else:
- res[purchase.id] = False
+ invoiced = False
+ if purchase.invoiced_rate == 100.00:
+ invoiced = True
+ res[purchase.id] = invoiced
return res
STATE_SELECTION = [
('draft', 'Request for Quotation'),
('wait', 'Waiting'),
- ('confirmed', 'Waiting Supplier Ack'),
+ ('confirmed', 'Waiting Approval'),
('approved', 'Approved'),
('except_picking', 'Shipping Exception'),
('except_invoice', 'Invoice Exception'),
help="Reference of the document that generated this purchase order request."
),
'partner_ref': fields.char('Supplier Reference', states={'confirmed':[('readonly',True)], 'approved':[('readonly',True)],'done':[('readonly',True)]}, size=64),
- 'date_order':fields.date('Date Ordered', required=True, states={'confirmed':[('readonly',True)], 'approved':[('readonly',True)]}, help="Date on which this document has been created."),
- 'date_approve':fields.date('Date Approved', readonly=1, help="Date on which purchase order has been approved"),
+ 'date_order':fields.date('Date Ordered', required=True, states={'confirmed':[('readonly',True)], 'approved':[('readonly',True)]}, select=True, help="Date on which this document has been created."),
+ 'date_approve':fields.date('Date Approved', readonly=1, select=True, help="Date on which purchase order has been approved"),
'partner_id':fields.many2one('res.partner', 'Supplier', required=True, states={'confirmed':[('readonly',True)], 'approved':[('readonly',True)],'done':[('readonly',True)]}, change_default=True),
'partner_address_id':fields.many2one('res.partner.address', 'Address', required=True,
states={'confirmed':[('readonly',True)], 'approved':[('readonly',True)],'done':[('readonly',True)]},domain="[('partner_id', '=', partner_id)]"),
'order_line': fields.one2many('purchase.order.line', 'order_id', 'Order Lines', states={'approved':[('readonly',True)],'done':[('readonly',True)]}),
'validator' : fields.many2one('res.users', 'Validated by', readonly=True),
'notes': fields.text('Notes'),
- 'invoice_id': fields.many2one('account.invoice', 'Invoice', readonly=True, help="An invoice generated for a purchase order"),
+ 'invoice_ids': fields.many2many('account.invoice', 'purchase_invoice_rel', 'purchase_id', 'invoice_id', 'Invoices', help="Invoices generated for a purchase order"),
'picking_ids': fields.one2many('stock.picking', 'purchase_id', 'Picking List', readonly=True, help="This is the list of picking list that have been generated for this purchase"),
'shipped':fields.boolean('Received', readonly=True, select=True, help="It indicates that a picking has been done"),
'shipped_rate': fields.function(_shipped_rate, method=True, string='Received', type='float'),
help="From Order: a draft invoice will be pre-generated based on the purchase order. The accountant " \
"will just have to validate this invoice for control.\n" \
"From Picking: a draft invoice will be pre-generated based on validated receptions.\n" \
- "Manual: no invoice will be pre-generated. The accountant will have to encode manually."
+ "Manual: allows you to generate suppliers invoices by chosing in the uninvoiced lines of all manual purchase orders."
+ ),
+ 'minimum_planned_date':fields.function(_minimum_planned_date, fnct_inv=_set_minimum_planned_date, method=True, string='Expected Date', type='date', select=True, help="This is computed as the minimum scheduled date of all purchase order lines' products.",
+ store = {
+ 'purchase.order.line': (_get_order, ['date_planned'], 10),
+ }
),
- 'minimum_planned_date':fields.function(_minimum_planned_date, fnct_inv=_set_minimum_planned_date, method=True,store=True, string='Expected Date', type='date', help="This is computed as the minimum scheduled date of all purchase order lines' products."),
'amount_untaxed': fields.function(_amount_all, method=True, digits_compute= dp.get_precision('Purchase Price'), string='Untaxed Amount',
store={
'purchase.order.line': (_get_order, None, 10),
'company_id': fields.many2one('res.company','Company',required=True,select=1),
}
_defaults = {
- 'date_order': time.strftime('%Y-%m-%d'),
+ 'date_order': lambda *a: time.strftime('%Y-%m-%d'),
'state': 'draft',
'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'purchase.order'),
'shipped': 0,
'pricelist_id': lambda self, cr, uid, context: context.get('partner_id', False) and self.pool.get('res.partner').browse(cr, uid, context['partner_id']).property_product_pricelist_purchase.id,
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'purchase.order', context=c),
}
+ _sql_constraints = [
+ ('name_uniq', 'unique(name)', 'Order Reference must be unique !'),
+ ]
_name = "purchase.order"
_description = "Purchase Order"
_order = "name desc"
def unlink(self, cr, uid, ids, context=None):
- purchase_orders = self.read(cr, uid, ids, ['state'])
+ purchase_orders = self.read(cr, uid, ids, ['state'], context=context)
unlink_ids = []
for s in purchase_orders:
if s['state'] in ['draft','cancel']:
return super(purchase_order, self).unlink(cr, uid, unlink_ids, context=context)
- def button_dummy(self, cr, uid, ids, context={}):
+ def button_dummy(self, cr, uid, ids, context=None):
return True
def onchange_dest_address_id(self, cr, uid, ids, adr_id):
if not adr_id:
return {}
- part_id = self.pool.get('res.partner.address').read(cr, uid, [adr_id], ['partner_id'])[0]['partner_id'][0]
- loc_id = self.pool.get('res.partner').browse(cr, uid, part_id).property_stock_customer.id
- return {'value':{'location_id': loc_id, 'warehouse_id': False}}
+ values = {'warehouse_id': False}
+ part_id = self.pool.get('res.partner.address').browse(cr, uid, adr_id).partner_id
+ if part_id:
+ loc_id = part_id.property_stock_customer.id
+ values.update({'location_id': loc_id})
+ return {'value':values}
def onchange_warehouse_id(self, cr, uid, ids, warehouse_id):
if not warehouse_id:
fiscal_position = part.property_account_position and part.property_account_position.id or False
return {'value':{'partner_address_id': addr['default'], 'pricelist_id': pricelist, 'fiscal_position': fiscal_position}}
- def wkf_approve_order(self, cr, uid, ids, context={}):
+ def wkf_approve_order(self, cr, uid, ids, context=None):
self.write(cr, uid, ids, {'state': 'approved', 'date_approve': time.strftime('%Y-%m-%d')})
- for (id,name) in self.name_get(cr, uid, ids):
- message = _('Purchase order ') + " '" + name + "' "+_("is approved by the supplier")
- self.log(cr, uid, id, message)
return True
#TODO: implement messages system
- def wkf_confirm_order(self, cr, uid, ids, context={}):
- product = []
+ def wkf_confirm_order(self, cr, uid, ids, context=None):
todo = []
- for po in self.browse(cr, uid, ids):
+ for po in self.browse(cr, uid, ids, context=context):
if not po.order_line:
raise osv.except_osv(_('Error !'),_('You can not confirm purchase order without Purchase Order Lines.'))
for line in po.order_line:
if line.state=='draft':
todo.append(line.id)
- current_name = self.name_get(cr, uid, ids)[0][1]
+ message = _("Purchase order '%s' is confirmed.") % (po.name,)
+ self.log(cr, uid, po.id, message)
+# current_name = self.name_get(cr, uid, ids)[0][1]
self.pool.get('purchase.order.line').action_confirm(cr, uid, todo, context)
for id in ids:
self.write(cr, uid, [id], {'state' : 'confirmed', 'validator' : uid})
- for line in po.order_line:
- product.append(line.product_id.default_code or '')
- params = ', '.join(map(lambda x : str(x), product))
- message = _('Purchase order ') + " '" + po.name + "' "+_('placed on')+ " '" + po.date_order + "' "+_('for')+" '" + params + "' "+ _("is confirmed")
- self.log(cr, uid, id, message)
return True
def wkf_warn_buyer(self, cr, uid, ids):
managers.append(manager.id)
for manager_id in managers:
request.create(cr, uid,{
- 'name' : "Purchase amount over the limit",
+ 'name' : _("Purchase amount over the limit"),
'act_from' : uid,
'act_to' : manager_id,
- 'body': 'Somebody has just confirmed a purchase with an amount over the defined limit',
+ 'body': _('Somebody has just confirmed a purchase with an amount over the defined limit'),
'ref_partner_id': po.partner_id.id,
'ref_doc1': 'purchase.order,%d' % (po.id,),
})
wf_service.trg_delete(uid, 'purchase.order', p_id, cr)
wf_service.trg_create(uid, 'purchase.order', p_id, cr)
for (id,name) in self.name_get(cr, uid, ids):
- message = _('Purchase order') + " '" + name + "' "+ _("is in the draft state")
- self.log(cr, uid, id, message)
+ message = _("Purchase order '%s' has been set in draft state.") % name
+ self.log(cr, uid, id, message)
return True
def action_invoice_create(self, cr, uid, ids, *args):
res = False
-
+ property_obj = self.pool.get('ir.property')
+ fp_obj = self.pool.get('account.fiscal.position')
journal_obj = self.pool.get('account.journal')
for o in self.browse(cr, uid, ids):
il = []
for ol in o.order_line:
todo.append(ol.id)
if ol.product_id:
- a = ol.product_id.product_tmpl_id.property_account_expense.id
- if not a:
- a = ol.product_id.categ_id.property_account_expense_categ.id
- if not a:
+ acc_id = ol.product_id.product_tmpl_id.property_account_expense.id
+ if not acc_id:
+ acc_id = ol.product_id.categ_id.property_account_expense_categ.id
+ if not acc_id:
raise osv.except_osv(_('Error !'), _('There is no expense account defined for this product: "%s" (id:%d)') % (ol.product_id.name, ol.product_id.id,))
else:
- a = self.pool.get('ir.property').get(cr, uid, 'property_account_expense_categ', 'product.category').id
+ prop = property_obj.get(cr, uid, 'property_account_expense_categ', 'product.category')
+ acc_id = prop and prop.id or False
fpos = o.fiscal_position or False
- a = self.pool.get('account.fiscal.position').map_account(cr, uid, fpos, a)
- il.append(self.inv_line_create(cr, uid, a, ol))
+ acc_id = fp_obj.map_account(cr, uid, fpos, acc_id)
+ if not acc_id:
+ raise osv.except_osv(_('Error !'),
+ _('There is no expense account defined in default Properties for Product Category or Fiscal Position is not defined !'))
+ il.append(self.inv_line_create(cr, uid, acc_id, ol))
- a = o.partner_id.property_account_payable.id
+ acc_id = o.partner_id.property_account_payable.id
journal_ids = journal_obj.search(cr, uid, [('type', '=','purchase'),('company_id', '=', o.company_id.id)], limit=1)
if not journal_ids:
raise osv.except_osv(_('Error !'),
_('There is no purchase journal defined for this company: "%s" (id:%d)') % (o.company_id.name, o.company_id.id))
inv = {
'name': o.partner_ref or o.name,
- 'reference': "P%dPO%d" % (o.partner_id.id, o.id),
- 'account_id': a,
+ 'reference': o.partner_ref or o.name,
+ 'account_id': acc_id,
'type': 'in_invoice',
'partner_id': o.partner_id.id,
'currency_id': o.pricelist_id.currency_id.id,
'journal_id': len(journal_ids) and journal_ids[0] or False,
'origin': o.name,
'invoice_line': il,
- 'fiscal_position': o.partner_id.property_account_position.id,
+ 'fiscal_position': o.fiscal_position.id or o.partner_id.property_account_position.id,
'payment_term': o.partner_id.property_payment_term and o.partner_id.property_payment_term.id or False,
'company_id': o.company_id.id,
}
- inv_id = self.pool.get('account.invoice').create(cr, uid, inv, {'type':'in_invoice'})
+ inv_id = self.pool.get('account.invoice').create(cr, uid, inv, {'type':'in_invoice', 'journal_type': 'purchase'})
self.pool.get('account.invoice').button_compute(cr, uid, [inv_id], {'type':'in_invoice'}, set_total=True)
self.pool.get('purchase.order.line').write(cr, uid, todo, {'invoiced':True})
- self.write(cr, uid, [o.id], {'invoice_id': inv_id})
+ self.write(cr, uid, [o.id], {'invoice_ids': [(4, inv_id)]})
res = inv_id
return res
return True
return False
- def action_cancel(self, cr, uid, ids, context={}):
- ok = True
- purchase_order_line_obj = self.pool.get('purchase.order.line')
- for purchase in self.browse(cr, uid, ids):
+ def action_cancel(self, cr, uid, ids, context=None):
+ for purchase in self.browse(cr, uid, ids, context=context):
for pick in purchase.picking_ids:
if pick.state not in ('draft','cancel'):
raise osv.except_osv(
for pick in purchase.picking_ids:
wf_service = netsvc.LocalService("workflow")
wf_service.trg_validate(uid, 'stock.picking', pick.id, 'button_cancel', cr)
- inv = purchase.invoice_id
- if inv and inv.state not in ('cancel','draft'):
- raise osv.except_osv(
- _('Could not cancel this purchase order !'),
- _('You must first cancel all invoices attached to this purchase order.'))
- if inv:
- wf_service = netsvc.LocalService("workflow")
- wf_service.trg_validate(uid, 'account.invoice', inv.id, 'invoice_cancel', cr)
+ for inv in purchase.invoice_ids:
+ if inv and inv.state not in ('cancel','draft'):
+ raise osv.except_osv(
+ _('Could not cancel this purchase order !'),
+ _('You must first cancel all invoices attached to this purchase order.'))
+ if inv:
+ wf_service = netsvc.LocalService("workflow")
+ wf_service.trg_validate(uid, 'account.invoice', inv.id, 'invoice_cancel', cr)
self.write(cr,uid,ids,{'state':'cancel'})
- message = _('Purchase order ') + " '" + purchase.name + "' "+ _("is cancelled")
- self.log(cr, uid, id, message)
+ for (id,name) in self.name_get(cr, uid, ids):
+ message = _("Purchase order '%s' is cancelled.") % name
+ self.log(cr, uid, id, message)
return True
def action_picking_create(self,cr, uid, ids, *args):
picking_id = False
for order in self.browse(cr, uid, ids):
+ reception_address_id = False
+ if order.dest_address_id:
+ reception_address_id = order.dest_address_id.id
+ elif order.warehouse_id and order.warehouse_id.partner_address_id:
+ reception_address_id = order.warehouse_id.partner_address_id.id
+ else:
+ if order.company_id.partner_id.address:
+ addresses_default = [address.id for address in order.company_id.partner_id.address if address.type == 'default']
+ addresses_delivery = [address.id for address in order.company_id.partner_id.address if address.type == 'delivery']
+ reception_address_id = (addresses_delivery and addresses_delivery[0]) or (addresses_default and addresses_default[0]) or False
loc_id = order.partner_id.property_stock_supplier.id
istate = 'none'
if order.invoice_method=='picking':
'name': pick_name,
'origin': order.name+((order.origin and (':'+order.origin)) or ''),
'type': 'in',
- 'address_id': order.dest_address_id.id or order.partner_address_id.id,
+ 'address_id': reception_address_id,
'invoice_state': istate,
'purchase_id': order.id,
'company_id': order.company_id.id,
if order_line.product_id.product_tmpl_id.type in ('product', 'consu'):
dest = order.location_id.id
move = self.pool.get('stock.move').create(cr, uid, {
- 'name': 'PO:'+order_line.name,
+ 'name': order.name + ': ' +(order_line.name or ''),
'product_id': order_line.product_id.id,
'product_qty': order_line.product_qty,
'product_uos_qty': order_line.product_qty,
'state': 'draft',
'purchase_line_id': order_line.id,
'company_id': order.company_id.id,
+ 'price_unit': order_line.price_unit
})
if order_line.move_dest_id:
self.pool.get('stock.move').write(cr, uid, [order_line.move_dest_id.id], {'location_id':order.location_id.id})
wf_service.trg_validate(uid, 'stock.picking', picking_id, 'button_confirm', cr)
return picking_id
- def copy(self, cr, uid, id, default=None,context={}):
+ def copy(self, cr, uid, id, default=None, context=None):
if not default:
default = {}
default.update({
'state':'draft',
'shipped':False,
'invoiced':False,
- 'invoice_id':False,
- 'picking_ids':[],
+ 'invoice_ids': [],
+ 'picking_ids': [],
'name': self.pool.get('ir.sequence').get(cr, uid, 'purchase.order'),
})
return super(purchase_order, self).copy(cr, uid, id, default, context)
- def do_merge(self, cr, uid, ids, context):
+ def do_merge(self, cr, uid, ids, context=None):
"""
To merge similar type of purchase orders.
Orders will only be merged if:
new_orders = {}
- for porder in [order for order in self.browse(cr, uid, ids) if order.state == 'draft']:
+ for porder in [order for order in self.browse(cr, uid, ids, context=context) if order.state == 'draft']:
order_key = make_key(porder, ('partner_id', 'location_id', 'pricelist_id'))
new_order = new_orders.setdefault(order_key, ({}, []))
new_order[1].append(porder.id)
allorders = []
+ orders_info = {}
for order_key, (order_data, old_ids) in new_orders.iteritems():
# skip merges with only one order
if len(old_ids) < 2:
# create the new order
neworder_id = self.create(cr, uid, order_data)
+ orders_info.update({neworder_id: old_ids})
allorders.append(neworder_id)
# make triggers pointing to the old orders point to the new order
for old_id in old_ids:
wf_service.trg_redirect(uid, 'purchase.order', old_id, neworder_id, cr)
wf_service.trg_validate(uid, 'purchase.order', old_id, 'purchase_cancel', cr)
- return allorders
+ return orders_info
purchase_order()
class purchase_order_line(osv.osv):
- def _amount_line(self, cr, uid, ids, prop, arg,context):
+ def _amount_line(self, cr, uid, ids, prop, arg, context=None):
res = {}
cur_obj=self.pool.get('res.currency')
tax_obj = self.pool.get('account.tax')
_columns = {
'name': fields.char('Description', size=256, required=True),
'product_qty': fields.float('Quantity', required=True, digits=(16,2)),
- 'date_planned': fields.date('Scheduled date', required=True),
+ 'date_planned': fields.date('Scheduled Date', required=True, select=True),
'taxes_id': fields.many2many('account.tax', 'purchase_order_taxe', 'ord_id', 'tax_id', 'Taxes'),
'product_uom': fields.many2one('product.uom', 'Product UOM', required=True),
'product_id': fields.many2one('product.product', 'Product', domain=[('purchase_ok','=',True)], change_default=True),
'notes': fields.text('Notes'),
'order_id': fields.many2one('purchase.order', 'Order Reference', select=True, required=True, ondelete='cascade'),
'account_analytic_id':fields.many2one('account.analytic.account', 'Analytic Account',),
- 'company_id': fields.related('order_id','company_id',type='many2one',relation='res.company',string='Company'),
+ 'company_id': fields.related('order_id','company_id',type='many2one',relation='res.company',string='Company', store=True, readonly=True),
'state': fields.selection([('draft', 'Draft'), ('confirmed', 'Confirmed'), ('done', 'Done'), ('cancel', 'Cancelled')], 'State', required=True, readonly=True,
help=' * The \'Draft\' state is set automatically when purchase order in draft state. \
\n* The \'Confirmed\' state is set automatically as confirm when purchase order in confirm state. \
\n* The \'Cancelled\' state is set automatically when user cancel purchase order.'),
'invoice_lines': fields.many2many('account.invoice.line', 'purchase_order_line_invoice_rel', 'order_line_id', 'invoice_id', 'Invoice Lines', readonly=True),
'invoiced': fields.boolean('Invoiced', readonly=True),
- 'partner_id': fields.related('order_id','partner_id',string='Partner',readonly=True,type="many2one", relation="res.partner"),
+ 'partner_id': fields.related('order_id','partner_id',string='Partner',readonly=True,type="many2one", relation="res.partner", store=True),
'date_order': fields.related('order_id','date_order',string='Order Date',readonly=True,type="date")
}
_name = 'purchase.order.line'
_description = 'Purchase Order Line'
- def copy_data(self, cr, uid, id, default=None,context={}):
+ def copy_data(self, cr, uid, id, default=None, context=None):
if not default:
default = {}
- default.update({'state':'draft', 'move_ids':[],'invoiced':0,'invoice_lines':[]})
+ default.update({'state':'draft', 'move_ids':[], 'move_dest_id':False, 'invoiced':0,'invoice_lines':[]})
return super(purchase_order_line, self).copy_data(cr, uid, id, default, context)
def product_id_change(self, cr, uid, ids, pricelist, product, qty, uom,
if not product:
return {'value': {'price_unit': price_unit or 0.0, 'name': name or '',
'notes': notes or'', 'product_uom' : uom or False}, 'domain':{'product_uom':[]}}
+ res = {}
prod= self.pool.get('product.product').browse(cr, uid, product)
+
+ product_uom_pool = self.pool.get('product.uom')
lang=False
if partner_id:
lang=self.pool.get('res.partner').read(cr, uid, partner_id, ['lang'])['lang']
- context={'lang':lang}
- context['partner_id'] = partner_id
-
+ context = self.pool.get('res.users').context_get(cr, uid)
+ context_partner = {'lang':lang, 'partner_id': partner_id}
prod = self.pool.get('product.product').browse(cr, uid, product, context=context)
prod_uom_po = prod.uom_po_id.id
if not uom:
date_order = time.strftime('%Y-%m-%d')
qty = qty or 1.0
seller_delay = 0
+
+ prod_name = self.pool.get('product.product').name_get(cr, uid, [prod.id], context=context_partner)[0][1]
+ res = {}
for s in prod.seller_ids:
if s.name.id == partner_id:
seller_delay = s.delay
- temp_qty = s.qty # supplier _qty assigned to temp
+ if s.product_uom:
+ temp_qty = product_uom_pool._compute_qty(cr, uid, s.product_uom.id, s.min_qty, to_uom_id=prod.uom_id.id)
+ uom = s.product_uom.id #prod_uom_po
+ temp_qty = s.min_qty # supplier _qty assigned to temp
if qty < temp_qty: # If the supplier quantity is greater than entered from user, set minimal.
qty = temp_qty
- if price_unit:
- price = price_unit
- else:
- price = self.pool.get('product.pricelist').price_get(cr,uid,[pricelist],
- product, qty or 1.0, partner_id, {
+ res.update({'warning': {'title': _('Warning'), 'message': _('The selected supplier has a minimal quantity set to %s, you cannot purchase less.') % qty}})
+ qty_in_product_uom = product_uom_pool._compute_qty(cr, uid, uom, qty, to_uom_id=prod.uom_id.id)
+ price = self.pool.get('product.pricelist').price_get(cr,uid,[pricelist],
+ product, qty_in_product_uom or 1.0, partner_id, {
'uom': uom,
'date': date_order,
})[pricelist]
+ if price is False:
+ warning = {
+ 'title': 'No valid pricelist line found !',
+ 'message':
+ "Couldn't find a pricelist line matching this product and quantity.\n"
+ "You have to change either the product, the quantity or the pricelist."
+ }
+ res.update({'warning': warning})
dt = (datetime.now() + relativedelta(days=int(seller_delay) or 0.0)).strftime('%Y-%m-%d %H:%M:%S')
- prod_name = self.pool.get('product.product').name_get(cr, uid, [prod.id])[0][1]
- res = {'value': {'price_unit': price, 'name': name or prod_name,
+ res.update({'value': {'price_unit': price, 'name': prod_name,
'taxes_id':map(lambda x: x.id, prod.supplier_taxes_id),
'date_planned': date_planned or dt,'notes': notes or prod.description_purchase,
'product_qty': qty,
- 'product_uom': uom}}
+ 'product_uom': uom}})
domain = {}
- partner = self.pool.get('res.partner').browse(cr, uid, partner_id)
taxes = self.pool.get('account.tax').browse(cr, uid,map(lambda x: x.id, prod.supplier_taxes_id))
fpos = fiscal_position and self.pool.get('account.fiscal.position').browse(cr, uid, fiscal_position) or False
res['value']['taxes_id'] = self.pool.get('account.fiscal.position').map_tax(cr, uid, fpos, taxes)
return res
def product_uom_change(self, cr, uid, ids, pricelist, product, qty, uom,
- partner_id, date_order=False,fiscal_position=False):
+ partner_id, date_order=False, fiscal_position=False, date_planned=False,
+ name=False, price_unit=False, notes=False):
res = self.product_id_change(cr, uid, ids, pricelist, product, qty, uom,
- partner_id, date_order=date_order,fiscal_position=fiscal_position)
+ partner_id, date_order=date_order, fiscal_position=fiscal_position, date_planned=date_planned,
+ name=name, price_unit=price_unit, notes=notes)
if 'product_uom' in res['value']:
+ if uom and (uom != res['value']['product_uom']) and res['value']['product_uom']:
+ seller_uom_name = self.pool.get('product.uom').read(cr, uid, [res['value']['product_uom']], ['name'])[0]['name']
+ res.update({'warning': {'title': _('Warning'), 'message': _('The selected supplier only sells this product by %s') % seller_uom_name }})
del res['value']['product_uom']
if not uom:
res['value']['price_unit'] = 0.0
return res
- def action_confirm(self, cr, uid, ids, context={}):
- self.write(cr, uid, ids, {'state': 'confirmed'}, context)
- for (id,name) in self.name_get(cr, uid, ids):
- message = _('Purchase order line') + " '" + name + "' "+ _("is confirmed")
- self.log(cr, uid, id, message)
+ def action_confirm(self, cr, uid, ids, context=None):
+ self.write(cr, uid, ids, {'state': 'confirmed'}, context=context)
return True
purchase_order_line()
'purchase_id': fields.many2one('purchase.order', 'Purchase Order'),
}
- def action_po_assign(self, cr, uid, ids, context={}):
+ def action_po_assign(self, cr, uid, ids, context=None):
""" This is action which call from workflow to assign purchase order to procurements
@return: True
"""
res = res.values()
return len(res) and res[0] or 0 #TO CHECK: why workflow is generated error if return not integer value
- def make_po(self, cr, uid, ids, context={}):
+ def make_po(self, cr, uid, ids, context=None):
""" Make purchase order from procurement
@return: New created Purchase Orders procurement wise
"""
res = {}
- company = self.pool.get('res.users').browse(cr, uid, uid, context).company_id
+ if context is None:
+ context = {}
+ company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id
partner_obj = self.pool.get('res.partner')
uom_obj = self.pool.get('product.uom')
pricelist_obj = self.pool.get('product.pricelist')
prod_obj = self.pool.get('product.product')
acc_pos_obj = self.pool.get('account.fiscal.position')
po_obj = self.pool.get('purchase.order')
- for procurement in self.browse(cr, uid, ids):
+ po_line_obj = self.pool.get('purchase.order.line')
+ 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.
seller_qty = procurement.product_id.seller_qty
partner_id = partner.id
address_id = partner_obj.address_get(cr, uid, [partner_id], ['delivery'])['delivery']
pricelist_id = partner.property_product_pricelist_purchase.id
+ fiscal_position = partner.property_account_position and partner.property_account_position.id or False
uom_id = procurement.product_id.uom_po_id.id
if seller_qty:
qty = max(qty,seller_qty)
- price = pricelist_obj.price_get(cr, uid, [pricelist_id], procurement.product_id.id, qty, False, {'uom': uom_id})[pricelist_id]
+ price = pricelist_obj.price_get(cr, uid, [pricelist_id], procurement.product_id.id, qty, partner_id, {'uom': uom_id})[pricelist_id]
+
+ newdate = datetime.strptime(procurement.date_planned, '%Y-%m-%d %H:%M:%S')
+ newdate = (newdate - relativedelta(days=company.po_lead)) - relativedelta(days=seller_delay)
- newdate = DateTime.strptime(procurement.date_planned, '%Y-%m-%d %H:%M:%S')
- newdate = newdate - DateTime.RelativeDateTime(days=company.po_lead)
- newdate = newdate - seller_delay
+ res_onchange = po_line_obj.product_id_change(cr, uid, ids, pricelist_id, procurement.product_id.id, qty, uom_id,
+ partner_id, time.strftime('%Y-%m-%d'), fiscal_position=fiscal_position, date_planned=datetime.now() + relativedelta(days=seller_delay or 0.0),
+ name=procurement.name, price_unit=procurement.product_id.list_price, notes=procurement.product_id.description_purchase)
#Passing partner_id to context for purchase order line integrity of Line name
context.update({'lang': partner.lang, 'partner_id': partner_id})
line = {
'name': product.partner_ref,
- 'product_qty': qty,
+ 'product_qty': res_onchange['value']['product_qty'],
'product_id': procurement.product_id.id,
- 'product_uom': uom_id,
- 'price_unit': price,
+ 'product_uom': res_onchange['value']['product_uom'],
+ 'price_unit': res_onchange['value']['price_unit'],
'date_planned': newdate.strftime('%Y-%m-%d %H:%M:%S'),
'move_dest_id': res_id,
'notes': product.description_purchase,
procurement_order()
+class stock_invoice_onshipping(osv.osv_memory):
+ _inherit = "stock.invoice.onshipping"
+
+ def create_invoice(self, cr, uid, ids, context=None):
+ if context is None:
+ context = {}
+ res = super(stock_invoice_onshipping,self).create_invoice(cr, uid, ids, context=context)
+ purchase_obj = self.pool.get('purchase.order')
+ picking_obj = self.pool.get('stock.picking')
+ for pick_id in res:
+ pick = picking_obj.browse(cr, uid, pick_id, context=context)
+ if pick.purchase_id:
+ purchase_obj.write(cr, uid, [pick.purchase_id.id], {
+ 'invoice_ids': [(4, res[pick_id])]}, context=context)
+ return res
+
+stock_invoice_onshipping()
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: