diff --git a/addons/delivery/__openerp__.py b/addons/delivery/__openerp__.py index 089dc3e14d7..6201668bd90 100644 --- a/addons/delivery/__openerp__.py +++ b/addons/delivery/__openerp__.py @@ -32,7 +32,7 @@ You can define your own carrier and delivery grids for prices. When creating invoices from picking, OpenERP is able to add and compute the shipping line. """, 'author': 'OpenERP SA', - 'depends': ['sale', 'purchase', 'stock_account'], + 'depends': ['sale_stock', 'purchase'], 'data': [ 'security/ir.model.access.csv', 'delivery_report.xml', diff --git a/addons/delivery/report/shipping.py b/addons/delivery/report/shipping.py index 53bdad807c0..6f313c14b11 100644 --- a/addons/delivery/report/shipping.py +++ b/addons/delivery/report/shipping.py @@ -28,8 +28,19 @@ class shipping(report_sxw.rml_parse): super(shipping, self).__init__(cr, uid, name, context=context) self.localcontext.update({ 'time': time, + 'get_partner_invoice_info': self.get_partner_invoice_info, }) + def get_partner_invoice_info(self, origin): + """This method is used to get information of invoiced partner. + :param: origin: origin of picking + :return: tuple contaning partner name and address of invoiced partner + """ + sale_obj = self.pool.get('sale.order') + sale_id = sale_obj.search(self.cr, self.uid, [('name', '=', origin)])[0] + partner_invoice_id = sale_obj.browse(self.cr, self.uid, sale_id).partner_invoice_id + return partner_invoice_id.name, self.pool.get('res.partner')._display_address(self.cr, self.uid, partner_invoice_id) + report_sxw.report_sxw('report.sale.shipping','stock.picking','addons/delivery/report/shipping.rml',parser=shipping) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/delivery/report/shipping.rml b/addons/delivery/report/shipping.rml index 5a3750e64a8..d9d90c1b3bd 100644 --- a/addons/delivery/report/shipping.rml +++ b/addons/delivery/report/shipping.rml @@ -107,14 +107,11 @@ - + Description - - Lot - Quantity @@ -130,12 +127,12 @@ Invoiced to - [[ o.sale_id and o.sale_id.partner_invoice_id and o.sale_id.partner_invoice_id.name or '']] - [[ o.sale_id and o.sale_id.partner_invoice_id and display_address(o.sale_id.partner_invoice_id) ]] + [[ o.origin and get_partner_invoice_info(o.origin)[0] or '' ]] + [[ o.origin and get_partner_invoice_info(o.origin)[1] or '' ]] - [[ o.partner_id and o.partner_id and o.partner_id.name or '' ]] - [[ o.partner_id and o.partner_id and display_address(o.partner_id) ]] + [[ o.partner_id and o.partner_id.name or '' ]] + [[ o.partner_id and display_address(o.partner_id) ]] @@ -165,7 +162,7 @@ - [[ o.sale_id and o.sale_id.name ]] + [[ o.origin or '' ]] [[ formatLang(o.date,date_time=True) ]] @@ -184,14 +181,11 @@ - + Description - - Lot - Quantity @@ -199,14 +193,11 @@
[[repeatIn(o.move_lines,'line')]] - + [[line.product_id.code ]] [[ line.product_id and line.product_id.name or '']] - - [[ (line.prodlot_id and (line.prodlot_id.name + (line.prodlot_id.ref and ('/' + line.prodlot_id.ref) or ''))) or ' ' ]] - [[ formatLang(line.product_qty) ]] [[ line.product_uom and line.product_uom.name ]] diff --git a/addons/delivery/stock.py b/addons/delivery/stock.py index 3c1440cf951..3512f08825e 100644 --- a/addons/delivery/stock.py +++ b/addons/delivery/stock.py @@ -30,7 +30,6 @@ class stock_picking(osv.osv): def _cal_weight(self, cr, uid, ids, name, args, context=None): res = {} - uom_obj = self.pool.get('product.uom') for picking in self.browse(cr, uid, ids, context=context): total_weight = total_weight_net = 0.00 @@ -119,26 +118,22 @@ class stock_picking(osv.osv): 'invoice_line_tax_id': [(6, 0, taxes_ids)], } - def action_invoice_create(self, cr, uid, ids, journal_id=False, - group=False, type='out_invoice', context=None): - invoice_obj = self.pool.get('account.invoice') - picking_obj = self.pool.get('stock.picking') + def _create_invoice_from_picking(self, cr, uid, picking, vals, context=None): + ''' This function simply creates the invoice from the given values. It is overriden in delivery module to add the delivery costs. picking is a browse_record + ''' invoice_line_obj = self.pool.get('account.invoice.line') - result = super(stock_picking, self).action_invoice_create(cr, uid, - ids, journal_id=journal_id, group=group, type=type, - context=context) - for picking in picking_obj.browse(cr, uid, result, context=context): - invoice = invoice_obj.browse(cr, uid, picking.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) - invoice_obj.button_compute(cr, uid, [invoice.id], context=context) - return result - def _get_default_uom(self,cr,uid,c): + 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_line = self._prepare_shipping_invoice_line(cr, uid, picking, invoice, context=context) + if invoice_line: + invoice_line_obj.create(cr, uid, invoice_line) + return invoice_id + + def _get_default_uom(self, cr, uid, c): uom_categ, uom_categ_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'product', 'product_uom_categ_kgm') - return self.pool.get('product.uom').search(cr, uid, [('category_id', '=', uom_categ_id),('factor','=',1)])[0] + return self.pool.get('product.uom').search(cr, uid, [('category_id', '=', uom_categ_id), ('factor', '=', 1)])[0] _defaults = { - 'weight_uom_id': lambda self,cr,uid,c: self._get_default_uom(cr,uid,c) + 'weight_uom_id': lambda self, cr, uid, c: self._get_default_uom(cr, uid, c) } diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py index 13350b37148..b47410f2122 100644 --- a/addons/sale_stock/sale_stock.py +++ b/addons/sale_stock/sale_stock.py @@ -430,3 +430,33 @@ class sale_order_line(osv.osv): res.update({'warning': warning}) return res +class stock_move(osv.osv): + _inherit = 'stock.move' + + def _create_invoice_line_from_vals(self, cr, uid, move, invoice_line_vals, context=None): + invoice_line_id = self.pool.get('account.invoice.line').create(cr, uid, invoice_line_vals, context=context) + if move.procurement_id and move.procurement_id.sale_line_id: + sale_line = move.procurement_id.sale_line_id + self.pool.get('sale.order.line').write(cr, uid, [sale_line.id], { + 'invoice_lines': [(4, invoice_line_id)] + }, context=context) + self.pool.get('sale.order').write(cr, uid, [sale_line.order_id.id], { + 'invoice_ids': [(4, invoice_line_vals['invoice_id'])], + }) + return invoice_line_id + + def _get_master_data(self, cr, uid, move, company, context=None): + if move.procurement_id and move.procurement_id.sale_line_id: + sale_order = move.procurement_id.sale_line_id.order_id + return sale_order.partner_invoice_id, sale_order.user_id.id, sale_order.pricelist_id.currency_id.id + return super(stock_move, self)._get_master_data(cr, uid, move, company, context=context) + + def _get_invoice_line_vals(self, cr, uid, move, partner, inv_type, context=None): + res = super(stock_move, self)._get_invoice_line_vals(cr, uid, move, partner, inv_type, context=context) + if move.procurement_id and move.procurement_id.sale_line_id: + sale_line = move.procurement_id.sale_line_id + res['invoice_line_tax_id'] = [(6, 0, [x.id for x in sale_line.tax_id])] + res['account_analytic_id'] = sale_line.order_id.project_id and sale_line.order_id.project_id.id or False + res['price_unit'] = sale_line.price_unit + res['discount'] = sale_line.discount + return res diff --git a/addons/stock_account/stock.py b/addons/stock_account/stock.py index 249ab3ddfd1..af63a8b7506 100644 --- a/addons/stock_account/stock.py +++ b/addons/stock_account/stock.py @@ -20,21 +20,20 @@ ############################################################################## from openerp.osv import fields, osv -from openerp.tools.translate import _ #---------------------------------------------------------- # Procurement Rule #---------------------------------------------------------- class procurement_rule(osv.osv): _inherit = 'procurement.rule' - _columns= { + _columns = { 'invoice_state': fields.selection([ ("invoiced", "Invoiced"), ("2binvoiced", "To Be Invoiced"), ("none", "Not Applicable")], "Invoice Status", required=False), } - + #---------------------------------------------------------- # Procurement Order #---------------------------------------------------------- @@ -43,18 +42,17 @@ class procurement_rule(osv.osv): class procurement_order(osv.osv): _inherit = "procurement.order" _columns = { - 'invoice_state': fields.selection( - [("invoiced", "Invoiced"), + 'invoice_state': fields.selection([("invoiced", "Invoiced"), ("2binvoiced", "To Be Invoiced"), ("none", "Not Applicable") - ], "Invoice Control", required=True), + ], "Invoice Control", required=True), } def _run_move_create(self, cr, uid, procurement, context=None): res = super(procurement_order, self)._run_move_create(cr, uid, procurement, context=context) res.update({'invoice_state': (procurement.rule_id.invoice_state in ('none', False) and procurement.invoice_state or procurement.rule_id.invoice_state) or 'none'}) return res - + _defaults = { 'invoice_state': 'none' } @@ -70,15 +68,51 @@ class stock_move(osv.osv): 'invoice_state': fields.selection([("invoiced", "Invoiced"), ("2binvoiced", "To Be Invoiced"), ("none", "Not Applicable")], "Invoice Control", - select=True, required=True, track_visibility='onchange', + select=True, required=True, track_visibility='onchange', states={'draft': [('readonly', False)]}), } - _defaults= { + _defaults = { 'invoice_state': lambda *args, **argv: 'none' + } + + def _get_master_data(self, cr, uid, move, company, context=None): + ''' returns a tupple (browse_record(res.partner), ID(res.users), ID(res.currency)''' + return move.picking_id.partner_id, uid, company.currency_id.id + + def _create_invoice_line_from_vals(self, cr, uid, move, invoice_line_vals, context=None): + return self.pool.get('account.invoice.line').create(cr, uid, invoice_line_vals, context=context) + + def _get_invoice_line_vals(self, cr, uid, move, partner, inv_type, context=None): + fp_obj = self.pool.get('account.fiscal.position') + # Get account_id + if inv_type in ('out_invoice', 'out_refund'): + account_id = move.product_id.property_account_income.id + if not account_id: + account_id = move.product_id.categ_id.property_account_income_categ.id + else: + account_id = move.product_id.property_account_expense.id + if not account_id: + account_id = move.product_id.categ_id.property_account_expense_categ.id + fiscal_position = partner.property_account_position + account_id = fp_obj.map_account(cr, uid, fiscal_position, account_id) + + # set UoS if it's a sale and the picking doesn't have one + uos_id = move.product_uom.id + quantity = move.product_uom_qty + if move.product_uos: + uos_id = move.product_uos.id + quantity = move.product_uos_qty + return { + 'name': move.name, + 'account_id': account_id, + 'product_id': move.product_id.id, + 'uos_id': uos_id, + 'quantity': quantity, + 'price_unit': move.product_id.list_price, # TODO: use price_get + 'discount': 0.0, + 'account_analytic_id': False, } - - #---------------------------------------------------------- # Picking #---------------------------------------------------------- @@ -90,9 +124,9 @@ class stock_picking(osv.osv): for pick in self.browse(cr, uid, ids, context=context): result[pick.id] = 'none' for move in pick.move_lines: - if move.invoice_state=='invoiced': + if move.invoice_state == 'invoiced': result[pick.id] = 'invoiced' - elif move.invoice_state=='2binvoiced': + elif move.invoice_state == '2binvoiced': result[pick.id] = '2binvoiced' break return result @@ -100,7 +134,7 @@ class stock_picking(osv.osv): def __get_picking_move(self, cr, uid, ids, context={}): res = [] for move in self.pool.get('stock.move').browse(cr, uid, ids, context=context): - if move.picking_id: + if move.picking_id: res.append(move.picking_id.id) return res @@ -109,11 +143,11 @@ class stock_picking(osv.osv): ("invoiced", "Invoiced"), ("2binvoiced", "To Be Invoiced"), ("none", "Not Applicable") - ], string="Invoice Control", required=True, + ], string="Invoice Control", required=True, store={ - 'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['state'], 10), - 'stock.move': (__get_picking_move, ['picking_id'], 10), + 'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['state'], 10), + 'stock.move': (__get_picking_move, ['picking_id', 'invoice_state'], 10), }, ), } @@ -121,6 +155,12 @@ class stock_picking(osv.osv): 'invoice_state': lambda *args, **argv: 'none' } + def _create_invoice_from_picking(self, cr, uid, picking, vals, context=None): + ''' This function simply creates the invoice from the given values. It is overriden in delivery module to add the delivery costs. + ''' + invoice_obj = self.pool.get('account.invoice') + return invoice_obj.create(cr, uid, vals, context=context) + def action_invoice_create(self, cr, uid, ids, journal_id=False, group=False, type='out_invoice', context=None): """ Creates invoice based on the invoice state selected for picking. @param journal_id: Id of journal @@ -134,7 +174,7 @@ class stock_picking(osv.osv): key = group and picking.id or True for move in picking.move_lines: if move.procurement_id and (move.procurement_id.invoice_state == '2binvoiced') or move.invoice_state == '2binvoiced': - if (move.state <> 'cancel') and not move.scrapped: + if (move.state != 'cancel') and not move.scrapped: todo.setdefault(key, []) todo[key].append(move) invoices = [] @@ -144,27 +184,12 @@ class stock_picking(osv.osv): def __invoice_create_line(self, cr, uid, moves, journal_id=False, inv_type='out_invoice', context=None): invoice_obj = self.pool.get('account.invoice') + move_obj = self.pool.get('stock.move') invoices = {} for move in moves: company = move.company_id - account_analytic_id = False - if move.procurement_id: - sale_line = move.procurement_id.sale_line_id - sale = sale_line.order_id - user_id = sale.user_id and sale.user_id.id or False - partner = sale.partner_invoice_id - currency_id = sale.pricelist_id.currency_id.id - origin = sale.name - account_analytic_id = sale.project_id and sale.project_id.id or False - unit_price = sale_line.price_unit - discount = sale_line.discount - else: - partner = move.picking_id.partner_id - currency_id = company.currency_id.id - user_id = uid - origin = move.picking_id.name - unit_price = move.product_id.list_price #TODO: use price_get - discount = 0 + origin = move.picking_id.name + partner, user_id, currency_id = move_obj._get_master_data(cr, uid, move, company, context=context) key = (partner.id, currency_id, company.id, user_id) if key not in invoices: @@ -176,7 +201,7 @@ class stock_picking(osv.osv): account_id = partner.property_account_payable.id payment_term = partner.property_supplier_payment_term.id or False - invoice_id = invoice_obj.create(cr, uid, { + invoice_vals = { 'origin': origin, 'date_invoice': context.get('date_inv', False), 'user_id': user_id, @@ -188,52 +213,18 @@ class stock_picking(osv.osv): 'company_id': company.id, 'currency_id': currency_id, 'journal_id': journal_id, - }, context=context) + } + invoice_id = self._create_invoice_from_picking(cr, uid, move.picking_id, invoice_vals, context=context) invoices[key] = invoice_id - # Get account_id - if inv_type in ('out_invoice', 'out_refund'): - account_id = move.product_id.property_account_income.id - if not account_id: - account_id = move.product_id.categ_id.property_account_income_categ.id - else: - account_id = move.product_id.property_account_expense.id - if not account_id: - account_id = move.product_id.categ_id.property_account_expense_categ.id - fp_obj = self.pool.get('account.fiscal.position') - fiscal_position = partner.property_account_position - account_id = fp_obj.map_account(cr, uid, fiscal_position, account_id) + invoice_line_vals = move_obj._get_invoice_line_vals(cr, uid, move, partner, inv_type, context=context) + invoice_line_vals['invoice_id'] = invoices[key] + invoice_line_vals['origin'] = origin - # set UoS if it's a sale and the picking doesn't have one - if move.product_uos: - uos_id = move.product_uos.id - quantity = move.product_uos_qty - else: - uos_id = move.product_uom.id - quantity = move.product_uom_qty - - invoice_line_id = self.pool.get('account.invoice.line').create(cr, uid, { - 'name': move.name, - 'origin': move.picking_id and move.picking_id.origin or False, - 'invoice_id': invoices[key], - 'account_id': account_id, - 'product_id': move.product_id.id, - 'uos_id': uos_id, - 'quantity': quantity, - 'price_unit': unit_price, - 'discount': discount, - #'invoice_line_tax_id': [(6, 0, [x.id for x in sale_line.tax_id])], TODO add me back - 'account_analytic_id': account_analytic_id, - }, context=context) + move_obj._create_invoice_line_from_vals(cr, uid, move, invoice_line_vals, context=context) + move_obj.write(cr, uid, move.id, {'invoice_state': 'invoiced'}, context=context) if move.procurement_id: - self.pool.get('sale.order.line').write(cr, uid, [sale_line.id], { - 'invoice_lines': [(4, invoice_line_id)] - }, context=context) - self.pool.get('sale.order').write(cr, uid, [sale.id], { - 'invoice_ids': [(4, invoices[key])], - }) - self.pool.get('procurement.order').write(cr, uid, [move.procurement_id.id], { 'invoice_state': 'invoiced', }, context=context)