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) 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 id in res.keys():
- order=self.browse(cr, uid, [id])[0]
- cur=order.pricelist_id.currency_id
- res[id]=cur_obj.round(cr, uid, cur, res[id])
+ 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):
val = 0.0
cur=order.pricelist_id.currency_id
for line in order.order_line:
- 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):
+ 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
'name': fields.char('Order Description', size=64, required=True, select=True),
'origin': fields.char('Origin', size=64),
'ref': fields.char('Order Reference', size=64),
- 'partner_ref': fields.char('Partner Reference', size=64),
+ 'partner_ref': fields.char('Partner Ref.', 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'),
'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),
'invoiced':fields.boolean('Invoiced & Paid', readonly=True, select=True),
- 'invoice_method': fields.selection([('manual','Manual'),('order','From order'),('picking','From picking')], 'Invoicing method', required=True),
+ 'invoice_method': fields.selection([('manual','Manual'),('order','From order'),('picking','From picking')], 'Invoicing Control', required=True),
'amount_untaxed': fields.function(_amount_untaxed, method=True, string='Untaxed Amount'),
'amount_tax': fields.function(_amount_tax, method=True, string='Taxes'),
'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):
'ref_partner_id': po.partner_id.id,
'ref_doc1': 'purchase.order,%d' % (po.id,),
})
+ def inv_line_create(self,a,ol):
+ return (0, False, {
+ 'name': ol.name,
+ 'account_id': a,
+ 'price_unit': ol.price_unit or 0.0,
+ '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])],
+ 'account_analytic_id': ol.account_analytic_id.id,
+ })
def action_invoice_create(self, cr, uid, ids, *args):
res = False
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[0]
- else:
- a = a[0]
+ a = ol.product_id.categ_id.property_account_expense_categ.id
+ if not a:
+ 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')
- il.append((0, False, {
- 'name': ol.name,
- 'account_id': a,
- 'price_unit': ol.price_unit or 0.0,
- '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])]
- }))
+ il.append(self.inv_line_create(a,ol))
+# il.append((0, False, {
+# 'name': ol.name,
+# 'account_id': a,
+# 'price_unit': ol.price_unit or 0.0,
+# '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])],
+# '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,
+ 'name': o.partner_ref or o.name,
'reference': "P%dPO%d" % (o.partner_id.id, o.id),
'account_id': a,
'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'
_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, 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, required=True, ondelete='cascade')
+ '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
default.update({'state':'draft', 'move_id':False})
return super(purchase_order_line, self).copy(cr, uid, id, default, context)
- def product_id_change(self, cr, uid, ids, pricelist, product, qty, uom, partner_id):
+ def product_id_change(self, cr, uid, ids, pricelist, product, qty, uom,
+ partner_id, date_order=False):
if not pricelist:
- raise osv.except_osv('No Pricelist !', 'You have to select a pricelist in the sale form !\n Please set one before choosing a product.')
+ raise osv.except_osv('No Pricelist !', 'You have to select a pricelist in the purchase 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}
- 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]
+
+ 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
+ if not date_order:
+ date_order = time.strftime('%Y-%m-%d')
+ price = self.pool.get('product.pricelist').price_get(cr,uid,[pricelist],
+ product, qty or 1.0, partner_id, {
+ 'uom': uom,
+ 'date': date_order,
+ })[pricelist]
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], context=context)[0][1]
- res = {'value': {'price_unit': price, 'name':prod_name, 'taxes_id':prod['taxes_id'], 'date_planned': dt,'notes':prod['description_purchase']}}
+
+ 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, date_order=False):
+ res = self.product_id_change(cr, uid, ids, pricelist, product, qty, uom,
+ partner_id, date_order=date_order)
+ 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()