import ir
from mx import DateTime
import pooler
+from tools import config
#
# Model definition
return res
def _amount_untaxed(self, cr, uid, ids, field_name, arg, context):
- id_set = ",".join(map(str, ids))
- cr.execute("SELECT s.id,COALESCE(SUM(l.price_unit*l.product_qty),0)::decimal(16,2) AS amount FROM purchase_order s LEFT OUTER JOIN purchase_order_line l ON (s.id=l.order_id) WHERE s.id IN ("+id_set+") GROUP BY s.id ")
- res = dict(cr.fetchall())
+ res = {}
+ cur_obj=self.pool.get('res.currency')
+ for purchase in self.browse(cr, uid, ids):
+ res[purchase.id] = 0.0
+ for line in purchase.order_line:
+ res[purchase.id] += line.price_subtotal
+ cur = purchase.pricelist_id.currency_id
+ res[purchase.id] = cur_obj.round(cr, uid, cur, res[purchase.id])
+
return res
def _amount_tax(self, cr, uid, ids, field_name, arg, context):
res = {}
+ cur_obj=self.pool.get('res.currency')
for order in self.browse(cr, uid, ids):
val = 0.0
+ cur=order.pricelist_id.currency_id
for line in order.order_line:
- for tax in line.taxes_id:
- for c in self.pool.get('account.tax').compute(cr, uid, [tax.id], line.price_unit, line.product_qty, order.partner_address_id.id):
- val+=c['amount']
- res[order.id]=round(val,2)
+ for c in self.pool.get('account.tax').compute(cr, uid, line.taxes_id, line.price_unit, line.product_qty, order.partner_address_id.id, line.product_id, order.partner_id):
+ val+= cur_obj.round(cr, uid, cur, c['amount'])
+ res[order.id]=cur_obj.round(cr, uid, cur, val)
return res
def _amount_total(self, cr, uid, ids, field_name, arg, context):
res = {}
untax = self._amount_untaxed(cr, uid, ids, field_name, arg, context)
tax = self._amount_tax(cr, uid, ids, field_name, arg, context)
+ cur_obj=self.pool.get('res.currency')
for id in ids:
- res[id] = untax.get(id, 0.0) + tax.get(id, 0.0)
+ order=self.browse(cr, uid, [id])[0]
+ cur=order.pricelist_id.currency_id
+ res[id] = cur_obj.round(cr, uid, cur, untax.get(id, 0.0) + tax.get(id, 0.0))
return res
_columns = {
'partner_ref': fields.char('Partner Reference', size=64),
'date_order':fields.date('Date Ordered', required=True, states={'confirmed':[('readonly',True)], 'approved':[('readonly',True)]}),
'date_approve':fields.date('Date Approved'),
- 'partner_id':fields.many2one('res.partner', 'Partner', required=True, states={'confirmed':[('readonly',True)], 'approved':[('readonly',True)]}, change_default=True, relate=True),
+ 'partner_id':fields.many2one('res.partner', 'Partner', required=True, states={'confirmed':[('readonly',True)], 'approved':[('readonly',True)]}, change_default=True),
'partner_address_id':fields.many2one('res.partner.address', 'Address', required=True, states={'posted':[('readonly',True)]}),
'dest_address_id':fields.many2one('res.partner.address', 'Destination Address', states={'posted':[('readonly',True)]}),
- 'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', states={'posted':[('readonly',True)]}, relate=True),
+ 'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', states={'posted':[('readonly',True)]}),
'location_id': fields.many2one('stock.location', 'Delivery destination', required=True),
- 'project_id':fields.many2one('account.analytic.account', 'Analytic Account', states={'posted':[('readonly',True)]}),
'pricelist_id':fields.many2one('product.pricelist', 'Pricelist', required=True, states={'confirmed':[('readonly',True)], 'approved':[('readonly',True)]}),
- 'state': fields.selection([('draft', 'Request for Quotation'), ('wait', 'Waiting'), ('confirmed', 'Confirmed'), ('approved', 'Approved'),('except_ship', 'Shipping Exception'), ('except_invoice', 'Invoice Exception'), ('done', 'Done'), ('cancel', 'Cancelled')], 'Order State', readonly=True, help="The state of the purchase order or the quotation request. A quotation is a purchase order in a 'Draft' state. Then the order has to be confirmed by the user, the state switch to 'Confirmed'. Then the supplier must confirm the order to change the state to 'Approved'. When the purchase order is paid and received, the state becomes 'Done'. If a cancel action occurs in the invoice or in the reception of goods, the state becomes in exception.", select=True),
+ 'state': fields.selection([('draft', 'Request for Quotation'), ('wait', 'Waiting'), ('confirmed', 'Confirmed'), ('approved', 'Approved'),('except_picking', 'Shipping Exception'), ('except_invoice', 'Invoice Exception'), ('done', 'Done'), ('cancel', 'Cancelled')], 'Order State', readonly=True, help="The state of the purchase order or the quotation request. A quotation is a purchase order in a 'Draft' state. Then the order has to be confirmed by the user, the state switch to 'Confirmed'. Then the supplier must confirm the order to change the state to 'Approved'. When the purchase order is paid and received, the state becomes 'Done'. If a cancel action occurs in the invoice or in the reception of goods, the state becomes in exception.", select=True),
'order_line': fields.one2many('purchase.order.line', 'order_id', 'Order State', states={'confirmed':[('readonly',True)], 'approved':[('readonly',True)]}),
'validator' : fields.many2one('res.users', 'Validated by', readonly=True),
'notes': fields.text('Notes'),
'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'purchase.order'),
'shipped': lambda *a: 0,
'invoice_method': lambda *a: 'order',
- 'invoiced': lambda *a: 0
+ 'invoiced': lambda *a: 0,
+ 'partner_address_id': lambda self, cr, uid, context: context.get('partner_id', False) and self.pool.get('res.partner').address_get(cr, uid, [context['partner_id']], ['default'])['default'],
+ '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,
}
_name = "purchase.order"
_description = "Purchase order"
+ _order = "name desc"
def button_dummy(self, cr, uid, ids, context={}):
return True
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[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}}
def onchange_warehouse_id(self, cr, uid, ids, warehouse_id):
if not part:
return {'value':{'partner_address_id': False}}
addr = self.pool.get('res.partner').address_get(cr, uid, [part], ['default'])
- pricelist = self.pool.get('res.partner').browse(cr, uid, part).property_product_pricelist_purchase[0]
+ pricelist = self.pool.get('res.partner').browse(cr, uid, part).property_product_pricelist_purchase.id
return {'value':{'partner_address_id': addr['default'], 'pricelist_id': pricelist}}
def wkf_approve_order(self, cr, uid, ids):
for ol in o.order_line:
if ol.product_id:
- a = ol.product_id.product_tmpl_id.property_account_expense
+ 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:
- a = ol.product_id.categ_id.property_account_expense_categ[0]
- else:
- a = a[0]
+ raise osv.except_osv('Error !', 'There is no income account defined for this product: "%s" (id:%d)' % (line.product_id.name, line.product_id.id,))
else:
a = self.pool.get('ir.property').get(cr, uid, 'property_account_expense_categ', 'product.category')
il.append((0, False, {
'quantity': ol.product_qty,
'product_id': ol.product_id.id or False,
'uos_id': ol.product_uom.id or False,
- 'invoice_line_tax_id': [(6, 0, [x.id for x in ol.taxes_id])]
+ 'invoice_line_tax_id': [(6, 0, [x.id for x in ol.taxes_id])],
+ 'account_analytic_id': ol.account_analytic_id.id,
}))
- a = o.partner_id.property_account_payable[0]
+ a = o.partner_id.property_account_payable.id
inv = {
'name': o.name,
'reference': "P%dPO%d" % (o.partner_id.id, o.id),
'type': 'in_invoice',
'partner_id': o.partner_id.id,
'currency_id': o.pricelist_id.currency_id.id,
- 'project_id': o.project_id.id,
'address_invoice_id': o.partner_address_id.id,
'address_contact_id': o.partner_address_id.id,
'origin': o.name,
'invoice_line': il,
}
- inv_id = self.pool.get('account.invoice').create(cr, uid, inv)
+ inv_id = self.pool.get('account.invoice').create(cr, uid, inv, {'type':'in_invoice'})
+ self.pool.get('account.invoice').button_compute(cr, uid, [inv_id], {'type':'in_invoice'}, set_total=True)
self.write(cr, uid, [o.id], {'invoice_id': inv_id})
res = inv_id
def action_picking_create(self,cr, uid, ids, *args):
picking_id = False
for order in self.browse(cr, uid, ids):
- loc_id = order.partner_id.property_stock_supplier[0]
+ loc_id = order.partner_id.property_stock_supplier.id
istate = 'none'
if order.invoice_method=='picking':
istate = '2binvoiced'
'shipped':False,
'invoiced':False,
'invoice_id':False,
- 'picking_ids':False,
+ 'picking_ids':[],
'name': self.pool.get('ir.sequence').get(cr, uid, 'purchase.order'),
})
return super(purchase_order, self).copy(cr, uid, id, default, context)
class purchase_order_line(osv.osv):
def _amount_line(self, cr, uid, ids, prop, unknow_none,unknow_dict):
res = {}
+ cur_obj=self.pool.get('res.currency')
for line in self.browse(cr, uid, ids):
- res[line.id] = line.price_unit * line.product_qty
+ cur = line.order_id.pricelist_id.currency_id
+ res[line.id] = cur_obj.round(cr, uid, cur, line.price_unit * line.product_qty)
return res
_columns = {
'name': fields.char('Description', size=64, required=True),
'product_qty': fields.float('Quantity', required=True, digits=(16,2)),
- 'date_planned': fields.date('Date Promised', required=True),
+ 'date_planned': fields.date('Scheduled date', required=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, relate=True),
+ 'product_id': fields.many2one('product.product', 'Product', domain=[('purchase_ok','=',True)], change_default=True),
'move_id': fields.many2one('stock.move', 'Reservation', ondelete='set null'),
'move_dest_id': fields.many2one('stock.move', 'Reservation Destination', ondelete='set null'),
- 'price_unit': fields.float('Unit Price', required=True),
+ 'price_unit': fields.float('Unit Price', required=True, digits=(16, int(config['price_accuracy']))),
'price_subtotal': fields.function(_amount_line, method=True, string='Subtotal'),
'notes': fields.text('Notes'),
- 'order_id': fields.many2one('purchase.order', 'Order Ref', select=True)
+ 'order_id': fields.many2one('purchase.order', 'Order Ref', select=True, required=True, ondelete='cascade'),
+ 'account_analytic_id':fields.many2one('account.analytic.account', 'Analytic Account',),
}
_defaults = {
'product_qty': lambda *a: 1.0
raise osv.except_osv('No Pricelist !', 'You have to select a pricelist in the sale form !\n Please set one before choosing a product.')
if not product:
return {'value': {'price_unit': 0.0, 'name':'','notes':''}, 'domain':{'product_uom':[]}}
+ lang=False
+ if partner_id:
+ lang=self.pool.get('res.partner').read(cr, uid, [partner_id])[0]['lang']
+ context={'lang':lang}
+
+ prod = self.pool.get('product.product').read(cr, uid, [product], ['supplier_taxes_id','name','seller_delay','uom_po_id','description_purchase'])[0]
+ prod_uom_po = prod['uom_po_id'][0]
+ if not uom:
+ uom = prod_uom_po
price = self.pool.get('product.pricelist').price_get(cr,uid,[pricelist], product, qty or 1.0, partner_id, {'uom': uom})[pricelist]
- prod = self.pool.get('product.product').read(cr, uid, [product], ['taxes_id','name','seller_delay','uom_po_id','description_purchase'])[0]
dt = (DateTime.now() + DateTime.RelativeDateTime(days=prod['seller_delay'] or 0.0)).strftime('%Y-%m-%d')
- prod_name = self.pool.get('product.product').name_get(cr, uid, [product])[0][1]
- res = {'value': {'price_unit': price, 'name':prod_name, 'taxes_id':prod['taxes_id'], 'date_planned': dt,'notes':prod['description_purchase']}}
+ prod_name = self.pool.get('product.product').name_get(cr, uid, [product], context=context)[0][1]
+
+ res = {'value': {'price_unit': price, 'name':prod_name, 'taxes_id':prod['supplier_taxes_id'], 'date_planned': dt,'notes':prod['description_purchase'], 'product_uom': uom}}
domain = {}
- if not uom:
- res['value']['product_uom'] = prod['uom_po_id'][0]
- if res['value']['product_uom']:
- res2 = self.pool.get('product.uom').read(cr, uid, [res['value']['product_uom']], ['category_id'])
- if res2 and res2[0]['category_id']:
- domain = {'product_uom':[('category_id','=',res2[0]['category_id'][0])]}
+
+ res2 = self.pool.get('product.uom').read(cr, uid, [uom], ['category_id'])
+ res3 = self.pool.get('product.uom').read(cr, uid, [prod_uom_po], ['category_id'])
+ domain = {'product_uom':[('category_id','=',res2[0]['category_id'][0])]}
+ if res2[0]['category_id'] != res3[0]['category_id']:
+ raise osv.except_osv('Wrong Product UOM !', 'You have to select a product UOM in the same category than the purchase UOM of the product')
+
res['domain'] = domain
return res
+
+ def product_uom_change(self, cr, uid, ids, pricelist, product, qty, uom, partner_id):
+ res = self.product_id_change(cr, uid, ids, pricelist, product, qty, uom, partner_id)
+ if 'product_uom' in res['value']:
+ del res['value']['product_uom']
+ if not uom:
+ res['value']['price_unit'] = 0.0
+ return res
purchase_order_line()