diff --git a/addons/procurement/procurement.py b/addons/procurement/procurement.py index 478e330e673..11d36ae7777 100644 --- a/addons/procurement/procurement.py +++ b/addons/procurement/procurement.py @@ -61,7 +61,7 @@ class procurement_group(osv.osv): ('direct', 'Partial'), ('one', 'All at once')], 'Delivery Method', required=True), 'partner_id': fields.many2one('res.partner', string = 'Partner'), #Sale should pass it here - 'procurement_ids': fields.many2one('procurement.order', 'group_id', 'Procurements'), + 'procurement_ids': fields.one2many('procurement.order', 'group_id', 'Procurements'), } _defaults = { 'name': lambda self, cr, uid, c: self.pool.get('ir.sequence').get(cr, uid, 'procurement.group') or '', diff --git a/addons/sale/sale.py b/addons/sale/sale.py index b9bc83f3c6f..1a693637b7f 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -286,7 +286,7 @@ class sale_order(osv.osv): partner_lang = self.pool.get('res.partner').browse(cr, uid, partner_id, context=context).lang context_lang.update({'lang': partner_lang}) return self.pool.get('res.users').browse(cr, uid, uid, context=context_lang).company_id.sale_note - + def onchange_partner_id(self, cr, uid, ids, part, context=None): if not part: return {'value': {'partner_invoice_id': False, 'partner_shipping_id': False, 'payment_term': False, 'fiscal_position': False}} @@ -635,6 +635,8 @@ class sale_order(osv.osv): 'company_id': order.company_id.id, 'note': line.name, 'group_id': group_id, + 'invoice_state': (order.order_policy=='picking') and '2binvoiced' or 'none', + 'sale_line_id': line.id } def _get_date_planned(self, cr, uid, order, line, start_date, context=None): @@ -656,7 +658,7 @@ class sale_order(osv.osv): procurement_obj = self.pool.get('procurement.order') for order in self.browse(cr, uid, ids, context=context): proc_ids = [] - group_id = self.pool.get("procurement.group").create(cr, uid, {'name': order.name, 'sale_id': order.id}, context=context) + group_id = self.pool.get("procurement.group").create(cr, uid, {'name': order.name}, context=context) order.write({'procurement_group_id': group_id}, context=context) for line in order.order_line: if (line.state == 'done') or not line.product_id: @@ -664,7 +666,7 @@ class sale_order(osv.osv): proc_id = procurement_obj.create(cr, uid, self._prepare_order_line_procurement(cr, uid, order, line, group_id=group_id, context=context)) proc_ids.append(proc_id) - line.write({'procurement_id': proc_id}) + #Confirm procurement order such that rules will be applied on it procurement_obj.run(cr, uid, proc_ids, context=context) # FP NOTE: do we need this? isn't it the workflow that should set this @@ -683,9 +685,6 @@ class sale_order(osv.osv): - - - # TODO add a field price_unit_uos # - update it on change product and unit price # - use it in report if there is a uos @@ -738,7 +737,8 @@ class sale_order_line(osv.osv): 'invoiced': fields.function(_fnct_line_invoiced, string='Invoiced', type='boolean', store={ 'account.invoice': (_order_lines_from_invoice, ['state'], 10), - 'sale.order.line': (lambda self,cr,uid,ids,ctx=None: ids, ['invoice_lines'], 10)}), + 'sale.order.line': (lambda self,cr,uid,ids,ctx=None: ids, ['invoice_lines'], 10) + }), 'price_unit': fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Product Price'), readonly=True, states={'draft': [('readonly', False)]}), 'type': fields.selection([('make_to_stock', 'from stock'), ('make_to_order', 'on order')], 'Procurement Method', required=True, readonly=True, states={'draft': [('readonly', False)]}, help="From stock: When needed, the product is taken from the stock or we wait for replenishment.\nOn order: When needed, the product is purchased or produced."), @@ -761,8 +761,7 @@ class sale_order_line(osv.osv): 'salesman_id':fields.related('order_id', 'user_id', type='many2one', relation='res.users', store=True, string='Salesperson'), 'company_id': fields.related('order_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True), 'delay': fields.float('Delivery Lead Time', required=True, help="Number of days between the order confirmation and the shipping of the products to the customer", readonly=True, states={'draft': [('readonly', False)]}), - 'procurement_id': fields.many2one('procurement.order', 'Procurement'), - #'property_ids': fields.many2many('mrp.property', 'sale_order_line_property_rel', 'order_id', 'property_id', 'Properties', readonly=True, states={'draft': [('readonly', False)]}), + 'procurement_ids': fields.many2one('procurement.order', 'sale_line_ids', 'Procurements'), } _order = 'order_id desc, sequence, id' _defaults = { @@ -841,11 +840,6 @@ class sale_order_line(osv.osv): return res - - - - - def invoice_line_create(self, cr, uid, ids, context=None): if context is None: context = {} @@ -1075,12 +1069,20 @@ class account_invoice(osv.Model): wf_service.trg_validate(uid, 'account.invoice', id, 'invoice_cancel', cr) return super(account_invoice, self).unlink(cr, uid, ids, context=context) -class procurement_group(osv.osv): - _inherit = 'procurement.group' - +class procurement_order(osv.osv): + _inherit = 'procurement.order' _columns = { - 'sale_id': fields.many2one('sale.order', string = 'Sales Order') - } + 'sale_line_id': fields.many2one('sale.order.line', string = 'Sale Order Line') + 'invoice_state': fields.selection( + [ + ("invoiced", "Invoiced"), + ("2binvoiced", "To Be Invoiced"), + ("none", "Not Applicable") + ], "Invoice Control", required=True), + } + _defaults = { + 'invoice_state': 'none', + } + -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale_stock/__init__.py b/addons/sale_stock/__init__.py index b5899113530..f521debcea5 100644 --- a/addons/sale_stock/__init__.py +++ b/addons/sale_stock/__init__.py @@ -25,4 +25,3 @@ import report import company import res_config -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/addons/sale_stock/__openerp__.py b/addons/sale_stock/__openerp__.py index 39dbe0ac68e..fe0b28fe43a 100644 --- a/addons/sale_stock/__openerp__.py +++ b/addons/sale_stock/__openerp__.py @@ -45,7 +45,7 @@ You can choose flexible invoicing methods: 'author': 'OpenERP SA', 'website': 'http://www.openerp.com', 'images': ['images/deliveries_to_invoice.jpeg'], - 'depends': ['sale', 'stock_account', 'procurement'], + 'depends': ['sale', 'stock_account'], 'init_xml': [], 'update_xml': ['security/sale_stock_security.xml', 'security/ir.model.access.csv', @@ -65,4 +65,3 @@ You can choose flexible invoicing methods: 'installable': True, 'auto_install': True, } -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale_stock/company.py b/addons/sale_stock/company.py index 5be1dbd524d..129c412187a 100644 --- a/addons/sale_stock/company.py +++ b/addons/sale_stock/company.py @@ -34,5 +34,3 @@ class company(osv.osv): _defaults = { 'security_lead': 0.0, } - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale_stock/report/__init__.py b/addons/sale_stock/report/__init__.py index 418927acc78..db31a38b3f3 100644 --- a/addons/sale_stock/report/__init__.py +++ b/addons/sale_stock/report/__init__.py @@ -18,4 +18,5 @@ # along with this program. If not, see . # ############################################################################## -import sale_report \ No newline at end of file + +import sale_report diff --git a/addons/sale_stock/report/sale_report.py b/addons/sale_stock/report/sale_report.py index 0feb3ee2392..3b4047cb436 100644 --- a/addons/sale_stock/report/sale_report.py +++ b/addons/sale_stock/report/sale_report.py @@ -39,7 +39,6 @@ class sale_report(osv.osv): ('cancel', 'Cancelled') ], 'Order Status', readonly=True), } - def init(self, cr): tools.drop_view_if_exists(cr, 'sale_report') cr.execute(""" @@ -93,4 +92,3 @@ class sale_report(osv.osv): ) """) -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py index ddf4e29e076..031bfbba97d 100644 --- a/addons/sale_stock/sale_stock.py +++ b/addons/sale_stock/sale_stock.py @@ -70,10 +70,11 @@ class sale_order(osv.osv): if not sale.procurement_group_id: res[sale.id] = [] continue + picking_ids = {} for procurement in sale.procurement_group_id.procurement_ids: if procurement.move_id and procurement.move_id.picking_id: - picking_ids.append(procurement.move_id.picking_id.id) - res[sale.id] = list(set(picking_ids)) + picking_ids[procurement.move_id.picking_id.id] = True + res[sale.id] = picking_ids.keys() return res def _prepare_order_line_procurement(self, cr, uid, order, line, group_id = False, context=None): @@ -261,13 +262,6 @@ class sale_order(osv.osv): res.append(line.procurement_id.id) return res -class stock_move(osv.osv): - _inherit = 'stock.move' - _columns = { - 'sale_line_id': fields.many2one('sale.order.line', 'Sale Line'), - } - - class sale_order_line(osv.osv): _inherit = 'sale.order.line' @@ -281,7 +275,6 @@ class sale_order_line(osv.osv): return res _columns = { - 'move_ids': fields.one2many('stock.move', 'sale_line_id', 'Inventory Moves', readonly=True), 'product_packaging': fields.many2one('product.packaging', 'Packaging'), 'number_packages': fields.function(_number_packages, type='integer', string='Number Packages'), } diff --git a/addons/sale_stock/sale_stock_demo.xml b/addons/sale_stock/sale_stock_demo.xml index 2e7b641659d..9359e0a7875 100644 --- a/addons/sale_stock/sale_stock_demo.xml +++ b/addons/sale_stock/sale_stock_demo.xml @@ -38,22 +38,6 @@ - - make_to_order - - - - make_to_order - - - - make_to_order - - - - make_to_order - - diff --git a/addons/sale_stock/stock.py b/addons/sale_stock/stock.py index ef5fcd36d0c..4d52e610092 100644 --- a/addons/sale_stock/stock.py +++ b/addons/sale_stock/stock.py @@ -24,98 +24,127 @@ from openerp.tools.translate import _ class stock_picking(osv.osv): _inherit = 'stock.picking' + def __get_invoice_state(self, cursor, user, ids, name, arg, context=None): + result = {} + for pick in self.browse(cr, uid, ids, context=context): + result[pick.id] = 'none' + for move in pick.move_lines: + if move.procurement_id: + if move.procurement_id.invoice_state=='invoiced': + result[pick.id] = 'invoiced' + elif move.procurement_id.invoice_state=='2binvoiced': + result[pick.id] = '2binvoiced' + break + return result + _columns = { - 'sale_id': fields.many2one('sale.order', 'Sales Order', ondelete='set null', select=True), - } - _defaults = { - 'sale_id': False + # TODO: add a store=... + 'invoice_state': fields.function(_get_invoice_state, type='selection', selection=[ + ("invoiced", "Invoiced"), + ("2binvoiced", "To Be Invoiced"), + ("none", "Not Applicable") + ], "Invoice Control", required=True), + } - def get_currency_id(self, cursor, user, picking): - if picking.sale_id: - return picking.sale_id.pricelist_id.currency_id.id - else: - return super(stock_picking, self).get_currency_id(cursor, user, picking) - - def _get_partner_to_invoice(self, cr, uid, picking, context=None): - """ Inherit the original function of the 'stock' module - We select the partner of the sales order as the partner of the customer invoice + 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 + @param group: Whether to create a group invoice or not + @param type: Type invoice to be created + @return: Ids of created invoices for the pickings """ - if picking.sale_id: - return picking.sale_id.partner_invoice_id - return super(stock_picking, self)._get_partner_to_invoice(cr, uid, picking, context=context) + context = context or {} + todo = {} + for picking in self.browse(cr, uid, ids, context=context): + key = group and picking.id or True + for move in picking.move_lines: + if (not move.procurement_id) or (move.procurement_id.invoice_state <> '2binvoiced'): + if (move.state <> 'cancel') and not move.scrapped: + todo[key].append(move) + for moves in todo.values(): + self.__invoice_create_line(cr, uid, moves, journal_id, type, context=context) + return True - def _get_comment_invoice(self, cursor, user, picking): - if picking.note or (picking.sale_id and picking.sale_id.note): - return picking.note or picking.sale_id.note - return super(stock_picking, self)._get_comment_invoice(cursor, user, picking) + def __invoice_create_line(self, cr, uid, moves, journal_id=False, inv_type='out_invoice', context=None): + invoices = {} + for move in moves: + sale_line = move.procurement_id.sale_line_id + sale = sale_line.order_id + partner = sale.partner_invoice_id - def _prepare_invoice(self, cr, uid, picking, partner, inv_type, journal_id, context=None): - """ Inherit the original function of the 'stock' module in order to override some - values if the picking has been generated by a sales order - """ - invoice_vals = super(stock_picking, self)._prepare_invoice(cr, uid, picking, partner, inv_type, journal_id, context=context) - if picking.sale_id: - invoice_vals['fiscal_position'] = picking.sale_id.fiscal_position.id - invoice_vals['payment_term'] = picking.sale_id.payment_term.id - invoice_vals['user_id'] = picking.sale_id.user_id.id - invoice_vals['name'] = picking.sale_id.client_order_ref or '' - return invoice_vals + currency_id = sale.pricelist_id.currency_id.id + key = (partner.id, currency_id, sale.company_id.id, sale.user_id and sale.user_id.id or False) - def _prepare_invoice_line(self, cr, uid, group, picking, move_line, invoice_id, invoice_vals, context=None): - invoice_vals = super(stock_picking, self)._prepare_invoice_line(cr, uid, group, picking, move_line, invoice_id, invoice_vals, context=context) - if picking.sale_id: - if move_line.sale_line_id: - invoice_vals['account_analytic_id'] = self._get_account_analytic_invoice(cr, uid, picking, move_line) - return invoice_vals + if key not in invoices: + # Get account and payment terms + if inv_type in ('out_invoice', 'out_refund'): + account_id = partner.property_account_receivable.id + payment_term = partner.property_payment_term.id or False + else: + account_id = partner.property_account_payable.id + payment_term = partner.property_supplier_payment_term.id or False - def _get_price_unit_invoice(self, cursor, user, move_line, type): - if move_line.sale_line_id and move_line.sale_line_id.product_id.id == move_line.product_id.id: - uom_id = move_line.product_id.uom_id.id - uos_id = move_line.product_id.uos_id and move_line.product_id.uos_id.id or False - price = move_line.sale_line_id.price_unit - coeff = move_line.product_id.uos_coeff - if uom_id != uos_id and coeff != 0: - price_unit = price / coeff - return price_unit - return move_line.sale_line_id.price_unit - return super(stock_picking, self)._get_price_unit_invoice(cursor, user, move_line, type) + invoice_id = self.pool.get('account.invoice').create(cr, uid, { + 'origin': sale.name, + 'date_invoice': context.get('date_inv', False), + 'user_id': sale.user_id and sale.user_id.id or False + 'partner_id': partner.id, + 'account_id': account_id, + 'payment_term': payment_term, + 'type': inv_type, + 'fiscal_position': partner.property_account_position.id, + 'company_id': sale.company_id.id, + 'currency_id': sale.pricelist_id.currency_id.id, + 'journal_id': journal_id, + }, context=context) + invoices[key] = invoice_id - def _get_discount_invoice(self, cursor, user, move_line): - if move_line.sale_line_id: - return move_line.sale_line_id.discount - return super(stock_picking, self)._get_discount_invoice(cursor, user, move_line) + # 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) - def _get_taxes_invoice(self, cursor, user, move_line, type): - if move_line.sale_line_id and move_line.sale_line_id.product_id.id == move_line.product_id.id: - return [x.id for x in move_line.sale_line_id.tax_id] - return super(stock_picking, self)._get_taxes_invoice(cursor, user, move_line, type) + # 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 - def _get_account_analytic_invoice(self, cursor, user, picking, move_line): - if picking.sale_id: - return picking.sale_id.project_id.id - return super(stock_picking, self)._get_account_analytic_invoice(cursor, user, picking, move_line) + 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': line.product_id.id, + 'uos_id': uos_id, + 'quantity': quantity, + 'price_unit': sale_line.price_unit, + 'discount': sale_line.discount, + 'invoice_line_tax_id': [(6, 0, [x.id for x in sale_line.tax_id])], + 'account_analytic_id': sale.project_id and sale.project_id.id or False, + }, context=context) - def _invoice_line_hook(self, cursor, user, move_line, invoice_line_id): - if move_line.sale_line_id: - move_line.sale_line_id.write({'invoice_lines': [(4, invoice_line_id)]}) - return super(stock_picking, self)._invoice_line_hook(cursor, user, move_line, invoice_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.id], { + 'invoice_ids': [(4, invoices[key])], + }) - def _invoice_hook(self, cursor, user, picking, invoice_id): - sale_obj = self.pool.get('sale.order') - if picking.sale_id: - sale_obj.write(cursor, user, [picking.sale_id.id], { - 'invoice_ids': [(4, invoice_id)], - }) - return super(stock_picking, self)._invoice_hook(cursor, user, picking, invoice_id) - - def action_done(self, cr, uid, ids, context=None): - """ Changes picking state to done. This method is called at the end of - the workflow by the activity "done". - """ - for record in self.browse(cr, uid, ids, context): - if record.type == "out" and record.sale_id: - self.pool.get('sale.order').message_post(cr, uid, [record.sale_id.id], body=_("Products delivered"), context=context) - return super(stock_picking, self).action_done(cr, uid, ids, context=context) + self.pool.get('procurement.order').write(cr, uid, [move.procurement_id.id], { + 'invoice_state': 'invoiced', + }, context=context) -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + invoice_obj.button_compute(cr, uid, invoices.values(), context=context, set_total=(inv_type in ('in_invoice', 'in_refund'))) + return invoices.keys() diff --git a/addons/sale_stock/stock_view.xml b/addons/sale_stock/stock_view.xml index 64ea51d7e12..9a31b8e02a7 100644 --- a/addons/sale_stock/stock_view.xml +++ b/addons/sale_stock/stock_view.xml @@ -2,41 +2,6 @@ - - stock.move.form - stock.move - - - - - - - - - - diff --git a/addons/stock/__init__.py b/addons/stock/__init__.py index 4495c45ca11..a3e04934caf 100644 --- a/addons/stock/__init__.py +++ b/addons/stock/__init__.py @@ -23,10 +23,7 @@ from stock import * import partner import product import procurement -#import stock_fifo_lifo import report import wizard import res_config - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock/procurement.py b/addons/stock/procurement.py index a3a9178971f..290f96a8201 100644 --- a/addons/stock/procurement.py +++ b/addons/stock/procurement.py @@ -148,5 +148,3 @@ class procurement_order(osv.osv): pass return {} - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock/stock.py b/addons/stock/stock.py index a6cd65d8666..74f10d3db0d 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1431,104 +1431,6 @@ class stock_move(osv.osv): self.action_done(cr, uid, res, context=context) return res -# def price_calculation(self, cr, uid, ids, quants, context=None): -# ''' -# This method puts the right price on the stock move, -# adapts the price on the product when necessary -# and creates the necessary stock move matchings -# :param quants: are quants to be reconciled and needs to be done when IN move reconciles out move -# -# It returns a list of tuples with (move_id, match_id) -# which is used for generating the accounting entries when FIFO/LIFO -# ''' -# product_obj = self.pool.get('product.product') -# currency_obj = self.pool.get('res.currency') -# matching_obj = self.pool.get('stock.move.matching') -# uom_obj = self.pool.get('product.uom') -# quant_obj = self.pool.get('stock.quant') -# -# product_avail = {} -# res = {} -# for move in self.browse(cr, uid, ids, context=context): -# # Initialize variables -# res[move.id] = [] -# move_qty = move.product_qty -# move_uom = move.product_uom.id -# company_id = move.company_id.id -# ctx = context.copy() -# user = self.pool.get('res.users').browse(cr, uid, uid, context=context) -# ctx['force_company'] = move.company_id.id -# product = product_obj.browse(cr, uid, move.product_id.id, context=ctx) -# cost_method = product.cost_method -# product_uom_qty = uom_obj._compute_qty(cr, uid, move_uom, move_qty, product.uom_id.id, round=False) -# if not product.id in product_avail: -# product_avail[product.id] = product.qty_available -# -# # Check if out -> do stock move matchings and if fifo/lifo -> update price -# # only update the cost price on the product form on stock moves of type == 'out' because if a valuation has to be made without PO, -# # for inventories for example we want to use the last value used for an outgoing move -# if move.location_id.usage == 'internal' and move.location_dest_id.usage != 'internal': -# fifo = (cost_method != 'lifo') -# #Ok -> do calculation based on quants -# price_amount = 0.0 -# amount = 0.0 -# #if move.id in quants??? -# #search quants_move which are the quants associated with this move, which are not propagated quants -# quants_move = quant_obj.search(cr, uid, [('history_ids', 'in', move.id), ('propagated_from_id', '=', False)], context=context) -# for quant in quant_obj.browse(cr, uid, quants_move, context=context): -# price_amount += quant.qty * quant.price_unit -# amount += quant.qty -# -## tuples = product_obj.get_stock_matchings_fifolifo(cr, uid, [product.id], move_qty, fifo, -## move_uom, move.company_id.currency_id.id, context=ctx) #TODO Would be better to use price_currency_id for migration? -## price_amount = 0.0 -## amount = 0.0 -## #Write stock matchings -## for match in tuples: -## matchvals = {'move_in_id': match[0], 'qty': match[1], -## 'move_out_id': move.id} -## match_id = matching_obj.create(cr, uid, matchvals, context=context) -## res[move.id].append(match_id) -## price_amount += match[1] * match[2] -## amount += match[1] -# #Write price on out move -# if product_avail[product.id] >= product_uom_qty and product.cost_method in ['real']: -# if amount > 0: -# self.write(cr, uid, move.id, {'price_unit': price_amount / move_qty}, context=context) #Should be converted -# product_obj.write(cr, uid, product.id, {'standard_price': price_amount / amount}, context=ctx) -# else: -# pass -## raise osv.except_osv(_('Error'), _("Something went wrong finding quants ") + str(self.search(cr, uid, [('company_id','=', company_id), ('qty_remaining', '>', 0), ('state', '=', 'done'), -## ('location_id.usage', '!=', 'internal'), ('location_dest_id.usage', '=', 'internal'), ('product_id', '=', product.id)], -## order = 'date, id', context=context)) + str(move_qty) + str(move_uom) + str(move.company_id.currency_id.id)) -# else: -# new_price = uom_obj._compute_price(cr, uid, product.uom_id.id, product.standard_price, move_uom) -# self.write(cr, uid, move.id, {'price_unit': new_price}, context=ctx) -# #Adjust product_avail when not average and move returned from -# if product.cost_method != 'average': -# product_avail[product.id] -= product_uom_qty -# -# #Check if in => if price 0.0, take standard price / Update price when average price and price on move != standard price -# if move.location_id.usage != 'internal' and move.location_dest_id.usage == 'internal': -# if move.price_unit == 0.0: -# new_price = uom_obj._compute_price(cr, uid, product.uom_id.id, product.standard_price, move_uom) -# self.write(cr, uid, move.id, {'price_unit': new_price}, context=ctx) -# elif product.cost_method == 'average': -# move_product_price = uom_obj._compute_price(cr, uid, move_uom, move.price_unit, product.uom_id.id) -# if product_avail[product.id] > 0.0: -# amount_unit = product.standard_price -# new_std_price = ((amount_unit * product_avail[product.id])\ -# + (move_product_price * product_uom_qty))/(product_avail[product.id] + product_uom_qty) -# else: -# new_std_price = move_product_price -# product_obj.write(cr, uid, [product.id], {'standard_price': new_std_price}, context=ctx) -# # Should create the stock move matchings for previous outs for the negative stock that can be matched with is in -# if product_avail[product.id] < 0.0: #TODO LATER -# resneg = self._generate_negative_stock_matchings(cr, uid, [move.id], product, quants[move.id], context=ctx) -# res[move.id] += resneg -# product_avail[product.id] += product_uom_qty -# return res - def split(self, cr, uid, move, qty, context=None): """ Partially (or not) moves a stock.move. @param partial_datas: Dictionary containing details of partial picking @@ -2235,5 +2137,3 @@ class stock_picking_type(osv.osv): } - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4 diff --git a/addons/stock_account/__init__.py b/addons/stock_account/__init__.py index 4e87ff34a07..3bab8f50207 100644 --- a/addons/stock_account/__init__.py +++ b/addons/stock_account/__init__.py @@ -23,4 +23,3 @@ import product import stock_account import wizard -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock_account/__openerp__.py b/addons/stock_account/__openerp__.py index 371d1b86acd..2434e88acfb 100644 --- a/addons/stock_account/__openerp__.py +++ b/addons/stock_account/__openerp__.py @@ -64,4 +64,3 @@ Dashboard / Reports for Warehouse Management will include: 'auto_install': True, } -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock_account/product.py b/addons/stock_account/product.py index ed19dca2b43..046970ec0b0 100644 --- a/addons/stock_account/product.py +++ b/addons/stock_account/product.py @@ -236,5 +236,3 @@ class product_category(osv.osv): help="When real-time inventory valuation is enabled on a product, this account will hold the current value of the products.",), } - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock_account/stock_account.py b/addons/stock_account/stock_account.py index 71d26c088b4..2dc3d804ccd 100644 --- a/addons/stock_account/stock_account.py +++ b/addons/stock_account/stock_account.py @@ -198,352 +198,3 @@ class stock_quant(osv.osv): 'line_id': move_lines, 'ref': move.picking_id and move.picking_id.name}, context=context) - -#---------------------------------------------------------- -# Stock Picking -#---------------------------------------------------------- - -class stock_picking(osv.osv): - _inherit = "stock.picking" - - _columns = { - 'invoice_state': fields.selection([ - ("invoiced", "Invoiced"), - ("2binvoiced", "To Be Invoiced"), - ("none", "Not Applicable")], "Invoice Control", - select=True, required=True, readonly=True, track_visibility='onchange', states={'draft': [('readonly', False)]}), - } - _defaults = { - 'invoice_state': 'none', - } - - #TODO update standard price on product after do_partial() - - #TODO: we don't need to change invoice_state on cancelation, do we? - #def action_cancel(self, cr, uid, ids, context=None): - # """ Changes picking state to cancel. - # @return: True - # """ - # for pick in self.browse(cr, uid, ids, context=context): - # ids2 = [move.id for move in pick.move_lines] - # self.pool.get('stock.move').action_cancel(cr, uid, ids2, context) - # self.write(cr, uid, ids, {'state': 'cancel', 'invoice_state': 'none'}) - # return True - - def copy(self, cr, uid, id, default=None, context=None): - if default is None: - default = {} - picking_obj = self.browse(cr, uid, id, context=context) - if 'invoice_state' not in default and picking_obj.invoice_state == 'invoiced': - default['invoice_state'] = '2binvoiced' - return super(stock_picking, self).copy(cr, uid, id, default, context) - - - def get_currency_id(self, cr, uid, picking): - return False - - def _get_partner_to_invoice(self, cr, uid, picking, context=None): - """ Gets the partner that will be invoiced - Note that this function is inherited in the sale and purchase modules - @param picking: object of the picking for which we are selecting the partner to invoice - @return: object of the partner to invoice - """ - return picking.partner_id and picking.partner_id.id - - def _get_comment_invoice(self, cr, uid, picking): - """ - @return: comment string for invoice - """ - return picking.note or '' - - def _get_price_unit_invoice(self, cr, uid, move_line, type, context=None): - """ Gets price unit for invoice - @param move_line: Stock move lines - @param type: Type of invoice - @return: The price unit for the move line - """ - if context is None: - context = {} - - if type in ('in_invoice', 'in_refund'): - # Take the user company and pricetype - context['currency_id'] = move_line.company_id.currency_id.id - amount_unit = move_line.product_id.price_get('standard_price', context=context)[move_line.product_id.id] - return amount_unit - else: - return move_line.product_id.list_price - - def _get_discount_invoice(self, cr, uid, move_line): - '''Return the discount for the move line''' - return 0.0 - - def _get_taxes_invoice(self, cr, uid, move_line, type): - """ Gets taxes on invoice - @param move_line: Stock move lines - @param type: Type of invoice - @return: Taxes Ids for the move line - """ - if type in ('in_invoice', 'in_refund'): - taxes = move_line.product_id.supplier_taxes_id - else: - taxes = move_line.product_id.taxes_id - - if move_line.picking_id and move_line.picking_id.partner_id and move_line.picking_id.partner_id.id: - return self.pool.get('account.fiscal.position').map_tax( - cr, - uid, - move_line.picking_id.partner_id.property_account_position, - taxes - ) - else: - return map(lambda x: x.id, taxes) - - def _get_account_analytic_invoice(self, cr, uid, picking, move_line): - return False - - def _invoice_line_hook(self, cr, uid, move_line, invoice_line_id): - '''Call after the creation of the invoice line''' - return - - def _invoice_hook(self, cr, uid, picking, invoice_id): - '''Call after the creation of the invoice''' - return - - def _get_invoice_type(self, pick): - src_usage = dest_usage = None - inv_type = None - if pick.invoice_state == '2binvoiced': - if pick.move_lines: - src_usage = pick.move_lines[0].location_id.usage - dest_usage = pick.move_lines[0].location_dest_id.usage - if pick.type == 'out' and dest_usage == 'supplier': - inv_type = 'in_refund' - elif pick.type == 'out' and dest_usage == 'customer': - inv_type = 'out_invoice' - elif pick.type == 'in' and src_usage == 'supplier': - inv_type = 'in_invoice' - elif pick.type == 'in' and src_usage == 'customer': - inv_type = 'out_refund' - else: - inv_type = 'out_invoice' - return inv_type - - def _prepare_invoice_group(self, cr, uid, picking, partner, invoice, context=None): - """ Builds the dict for grouped invoices - @param picking: picking object - @param partner: object of the partner to invoice (not used here, but may be usefull if this function is inherited) - @param invoice: object of the invoice that we are updating - @return: dict that will be used to update the invoice - """ - comment = self._get_comment_invoice(cr, uid, picking) - return { - 'name': (invoice.name or '') + ', ' + (picking.name or ''), - 'origin': (invoice.origin or '') + ', ' + (picking.name or '') + (picking.origin and (':' + picking.origin) or ''), - 'comment': (comment and (invoice.comment and invoice.comment + "\n" + comment or comment)) or (invoice.comment and invoice.comment or ''), - 'date_invoice': context.get('date_inv', False), - 'user_id': uid, - } - - def _prepare_invoice(self, cr, uid, picking, partner, inv_type, journal_id, context=None): - """ Builds the dict containing the values for the invoice - @param picking: picking object - @param partner: object of the partner to invoice - @param inv_type: type of the invoice ('out_invoice', 'in_invoice', ...) - @param journal_id: ID of the accounting journal - @return: dict that will be used to create the invoice object - """ - if isinstance(partner, int): - partner = self.pool.get('res.partner').browse(cr, uid, partner, context=context) - if inv_type in ('out_invoice', 'out_refund'): - account_id = partner.property_account_receivable.id - payment_term = partner.property_payment_term.id or False - else: - account_id = partner.property_account_payable.id - payment_term = partner.property_supplier_payment_term.id or False - comment = self._get_comment_invoice(cr, uid, picking) - invoice_vals = { - 'name': picking.name, - 'origin': (picking.name or '') + (picking.origin and (':' + picking.origin) or ''), - 'type': inv_type, - 'account_id': account_id, - 'partner_id': partner.id, - 'comment': comment, - 'payment_term': payment_term, - 'fiscal_position': partner.property_account_position.id, - 'date_invoice': context.get('date_inv', False), - 'company_id': picking.company_id.id, - 'user_id': uid, - } - cur_id = self.get_currency_id(cr, uid, picking) - if cur_id: - invoice_vals['currency_id'] = cur_id - if journal_id: - invoice_vals['journal_id'] = journal_id - return invoice_vals - - def _prepare_invoice_line(self, cr, uid, group, picking, move_line, invoice_id, - invoice_vals, context=None): - """ Builds the dict containing the values for the invoice line - @param group: True or False - @param picking: picking object - @param: move_line: move_line object - @param: invoice_id: ID of the related invoice - @param: invoice_vals: dict used to created the invoice - @return: dict that will be used to create the invoice line - """ - if group: - name = (picking.name or '') + '-' + move_line.name - else: - name = move_line.name - origin = move_line.picking_id.name or '' - if move_line.picking_id.origin: - origin += ':' + move_line.picking_id.origin - - if invoice_vals['type'] in ('out_invoice', 'out_refund'): - account_id = move_line.product_id.property_account_income.id - if not account_id: - account_id = move_line.product_id.categ_id.\ - property_account_income_categ.id - else: - account_id = move_line.product_id.property_account_expense.id - if not account_id: - account_id = move_line.product_id.categ_id.\ - property_account_expense_categ.id - if invoice_vals['fiscal_position']: - fp_obj = self.pool.get('account.fiscal.position') - fiscal_position = fp_obj.browse(cr, uid, invoice_vals['fiscal_position'], context=context) - 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_line.product_uos and move_line.product_uos.id or False - if not uos_id and invoice_vals['type'] in ('out_invoice', 'out_refund'): - uos_id = move_line.product_uom.id - - return { - 'name': name, - 'origin': origin, - 'invoice_id': invoice_id, - 'uos_id': uos_id, - 'product_id': move_line.product_id.id, - 'account_id': account_id, - 'price_unit': self._get_price_unit_invoice(cr, uid, move_line, invoice_vals['type']), - 'discount': self._get_discount_invoice(cr, uid, move_line), - 'quantity': move_line.product_uos_qty or move_line.product_qty, - 'invoice_line_tax_id': [(6, 0, self._get_taxes_invoice(cr, uid, move_line, invoice_vals['type']))], - 'account_analytic_id': self._get_account_analytic_invoice(cr, uid, picking, move_line), - } - - 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 - @param group: Whether to create a group invoice or not - @param type: Type invoice to be created - @return: Ids of created invoices for the pickings - """ - if context is None: - context = {} - - invoice_obj = self.pool.get('account.invoice') - invoice_line_obj = self.pool.get('account.invoice.line') - partner_obj = self.pool.get('res.partner') - invoices_group = {} - res = {} - inv_type = type - for picking in self.browse(cr, uid, ids, context=context): - if picking.invoice_state != '2binvoiced': - continue - partner = self._get_partner_to_invoice(cr, uid, picking, context=context) - if isinstance(partner, int): - partner = partner_obj.browse(cr, uid, [partner], context=context)[0] - if not partner: - raise osv.except_osv(_('Error, no partner!'), - _('Please put a partner on the picking list if you want to generate invoice.')) - - if not inv_type: - inv_type = self._get_invoice_type(picking) - - if group and partner.id in invoices_group: - invoice_id = invoices_group[partner.id] - invoice = invoice_obj.browse(cr, uid, invoice_id) - invoice_vals_group = self._prepare_invoice_group(cr, uid, picking, partner, invoice, context=context) - invoice_obj.write(cr, uid, [invoice_id], invoice_vals_group, context=context) - else: - invoice_vals = self._prepare_invoice(cr, uid, picking, partner, inv_type, journal_id, context=context) - invoice_id = invoice_obj.create(cr, uid, invoice_vals, context=context) - invoices_group[partner.id] = invoice_id - res[picking.id] = invoice_id - for move_line in picking.move_lines: - if move_line.state == 'cancel': - continue - if move_line.scrapped: - # do no invoice scrapped products - continue - vals = self._prepare_invoice_line(cr, uid, group, picking, move_line, - invoice_id, invoice_vals, context=context) - if vals: - invoice_line_id = invoice_line_obj.create(cr, uid, vals, context=context) - self._invoice_line_hook(cr, uid, move_line, invoice_line_id) - - invoice_obj.button_compute(cr, uid, [invoice_id], context=context, - set_total=(inv_type in ('in_invoice', 'in_refund'))) - self.write(cr, uid, [picking.id], { - 'invoice_state': 'invoiced', - }, context=context) - self._invoice_hook(cr, uid, picking, invoice_id) - self.write(cr, uid, res.keys(), { - 'invoice_state': 'invoiced', - }, context=context) - return res - - - - - # FP Note: review all methods above this line for stock.picking - -# ---------------------------------------------------- -# Move -# ---------------------------------------------------- - -class stock_move(osv.osv): - - _inherit = "stock.move" - - #TODO cancel a move must delete the accounting entry if not posted yet (otherwise raise an error) - def action_cancel(self, cr, uid, ids, context=None): - super(stock_move, self).action_cancel(cr, uid, ids, context=context) - -#class stock_inventory(osv.osv): -# _name = "stock.inventory" -# -# def action_cancel_draft(self, cr, uid, ids, context=None): -# """ Cancels the stock move and change inventory state to draft. -# @return: True -# """ -# for inv in self.browse(cr, uid, ids, context=context): -# self.pool.get('stock.move').action_cancel(cr, uid, [x.id for x in inv.move_ids], context=context) -# self.write(cr, uid, [inv.id], {'state':'draft'}, context=context) -# return True -# -# def action_cancel_inventory(self, cr, uid, ids, context=None): -# """ Cancels both stock move and inventory -# @return: True -# """ -# move_obj = self.pool.get('stock.move') -# account_move_obj = self.pool.get('account.move') -# for inv in self.browse(cr, uid, ids, context=context): -# move_obj.action_cancel(cr, uid, [x.id for x in inv.move_ids], context=context) -# for move in inv.move_ids: -# account_move_ids = account_move_obj.search(cr, uid, [('name', '=', move.name)]) -# if account_move_ids: -# account_move_data_l = account_move_obj.read(cr, uid, account_move_ids, ['state'], context=context) -# for account_move in account_move_data_l: -# if account_move['state'] == 'posted': -# raise osv.except_osv(_('User Error!'), -# _('In order to cancel this inventory, you must first unpost related journal entries.')) -# account_move_obj.unlink(cr, uid, [account_move['id']], context=context) -# self.write(cr, uid, [inv.id], {'state': 'cancel'}, context=context) -# return True - - - - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock_account/stock_account_view.xml b/addons/stock_account/stock_account_view.xml index 1f570a8527c..0410396191d 100644 --- a/addons/stock_account/stock_account_view.xml +++ b/addons/stock_account/stock_account_view.xml @@ -2,7 +2,6 @@ - stock.location.form.inherit stock.location @@ -17,7 +16,7 @@ - - - stock.picking.in.search.inherit + stock.picking.search.inherit stock.picking @@ -63,16 +38,6 @@ - - stock.picking.out.search.inherit - stock.picking - - - - - - - diff --git a/addons/stock_account/wizard/stock_invoice_onshipping.py b/addons/stock_account/wizard/stock_invoice_onshipping.py index c95508cd71b..30f6664f4aa 100644 --- a/addons/stock_account/wizard/stock_invoice_onshipping.py +++ b/addons/stock_account/wizard/stock_invoice_onshipping.py @@ -146,5 +146,3 @@ class stock_invoice_onshipping(osv.osv_memory): context=context) return res - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: