diff --git a/addons/account_anglo_saxon/__openerp__.py b/addons/account_anglo_saxon/__openerp__.py index 7ac4bdbd71e..4fc15bba4f5 100644 --- a/addons/account_anglo_saxon/__openerp__.py +++ b/addons/account_anglo_saxon/__openerp__.py @@ -44,7 +44,7 @@ account.""", 'category': 'Accounting & Finance', 'demo': [], 'data': ['product_view.xml'], - 'test': ['test/anglo_saxon.yml'], + 'test': ['test/anglo_saxon.yml', 'test/anglo_saxon_avg_fifo.yml'], 'auto_install': False, 'installable': True, } diff --git a/addons/account_anglo_saxon/invoice.py b/addons/account_anglo_saxon/invoice.py index f27d9b3ae72..8b31a48b92b 100644 --- a/addons/account_anglo_saxon/invoice.py +++ b/addons/account_anglo_saxon/invoice.py @@ -117,21 +117,27 @@ class account_invoice_line(osv.osv): for line in res: if a == line['account_id'] and i_line.product_id.id == line['product_id']: uom = i_line.product_id.uos_id or i_line.product_id.uom_id - standard_price = self.pool.get('product.uom')._compute_price(cr, uid, uom.id, i_line.product_id.standard_price, i_line.uos_id.id) - if standard_price != i_line.price_unit and line['price_unit'] == i_line.price_unit and acc: - price_diff = i_line.price_unit - standard_price - line.update({'price':standard_price * line['quantity']}) + valuation_price_unit = self.pool.get('product.uom')._compute_price(cr, uid, uom.id, i_line.product_id.standard_price, i_line.uos_id.id) + if i_line.product_id.cost_method != 'standard' and i_line.purchase_line_id: + #for average/fifo/lifo costing method, fetch real cost price from incomming moves + stock_move_obj = self.pool.get('stock.move') + valuation_stock_move = stock_move_obj.search(cr, uid, [('purchase_line_id', '=', i_line.purchase_line_id.id)], limit=1, context=context) + if valuation_stock_move: + valuation_price_unit = stock_move_obj.browse(cr, uid, valuation_stock_move[0], context=context).price_unit + if valuation_price_unit != i_line.price_unit and line['price_unit'] == i_line.price_unit and acc: + price_diff = i_line.price_unit - valuation_price_unit + line.update({'price': valuation_price_unit * line['quantity']}) diff_res.append({ - 'type':'src', + 'type': 'src', 'name': i_line.name[:64], - 'price_unit':price_diff, - 'quantity':line['quantity'], + 'price_unit': price_diff, + 'quantity': line['quantity'], 'price': price_diff * line['quantity'], - 'account_id':acc, - 'product_id':line['product_id'], - 'uos_id':line['uos_id'], - 'account_analytic_id':line['account_analytic_id'], - 'taxes':line.get('taxes',[]), + 'account_id': acc, + 'product_id': line['product_id'], + 'uos_id': line['uos_id'], + 'account_analytic_id': line['account_analytic_id'], + 'taxes': line.get('taxes', []), }) res += diff_res return res diff --git a/addons/account_anglo_saxon/test/anglo_saxon.yml b/addons/account_anglo_saxon/test/anglo_saxon.yml index 9e46aa52b12..6e9ebc0068e 100644 --- a/addons/account_anglo_saxon/test/anglo_saxon.yml +++ b/addons/account_anglo_saxon/test/anglo_saxon.yml @@ -109,7 +109,7 @@ - !record {model: purchase.order, id: purchase_order_001}: partner_id: base.res_partner_3 - location_id: stock.stock_location_3 + location_id: stock.stock_location_stock pricelist_id: 1 order_line: - product_id: product.product_product_3 @@ -128,12 +128,12 @@ partial_id = self.create(cr, uid, {},context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]}) self.do_partial(cr, uid, [partial_id]) - - I check the Stock Interim account (Received) is credit successfully. + I check the Stock Interim account (Received) is credited successfully. - !assert {model: account.account, id : account_anglo_stock_input, string : Stock Interim account (Received) is not credited successfully.}: - credit == 9 - - I check the Stock valuation account is debit sucessfully. + I check the Stock valuation account is debited sucessfully. - !assert {model: account.account, id : account_anglo_stock_valuation, string : Stock valuation account is not debited successfully.}: - debit == 9 @@ -192,7 +192,7 @@ invoice_state: 2binvoiced move_lines: - company_id: base.main_company - location_id: stock.stock_location_3 + location_id: stock.stock_location_stock product_id: product.product_product_3 product_qty: 1.0 product_uom: product.product_uom_unit diff --git a/addons/account_anglo_saxon/test/anglo_saxon_avg_fifo.yml b/addons/account_anglo_saxon/test/anglo_saxon_avg_fifo.yml new file mode 100644 index 00000000000..f7d52f4f5a8 --- /dev/null +++ b/addons/account_anglo_saxon/test/anglo_saxon_avg_fifo.yml @@ -0,0 +1,304 @@ +- + In order to test anglo_saxon Configure Different Accounts. +- + !record {model: account.account, id: account_anglo_stock_valuation_fifo}: + code: X3000f + name: Stock Valuation Account- (test) + parent_id: account.cas + type: other + user_type: account.data_account_type_asset +- + Configure Stock Interim account (Received). +- + !record {model: account.account, id: account_anglo_stock_input_fifo}: + code: X2800f + name: Stock Interim account (Received) + parent_id: account.cos + type: other + user_type: account.data_account_type_expense +- + Configure Stock Interim account (Delivered). +- + !record {model: account.account, id: account_anglo_stock_output_fifo}: + code: X2801f + name: Stock Interim account (Delivered) + parent_id: account.rev + type: other + user_type: account.data_account_type_income +- + Configure Price difference creditor Account. +- + !record {model: account.account, id: account_anglo_price_difference_fifo}: + code: X7095f + name: Price difference creditor Account + parent_id: account.cos + type: other + user_type: account.data_account_type_expense +- + Configure Cash Bank Account. +- + !record {model: account.account, id: account_anglo_cash_fifo}: + code: X5000f + name: Cash/Bank Account + parent_id: account.cash + type: other + user_type: account.data_account_type_asset +- + Configure Creditor Account Payable. +- + !record {model: account.account, id: account_anglo_payable_fifo}: + code: X440001f + name: Creditor Account Payable + parent_id: account.a_pay + type: other + user_type: account.data_account_type_payable +- + Configure Debtor Account Receivable. +- + !record {model: account.account, id: account_anglo_receivable_fifo}: + code: X400001f + name: Debtor Account Receivable + parent_id: account.a_recv + type: other + user_type: account.data_account_type_receivable +- + Configure Cost of Good sale Account. +- + !record {model: account.account, id: account_anglo_cogs_fifo}: + code: X7000f + name: Cost of goods sale account + parent_id: account.o_expense + type: other + user_type: account.data_account_type_expense +- + Configure Income Account. +- + !record {model: account.account, id: account_anglo_income_fifo}: + code: X8000f + name: Income Account + parent_id: account.o_income + type: other + user_type: account.data_account_type_income +- + I configure the account receivable of supplier +- + !record {model: res.partner, id: base.res_partner_3}: + property_account_payable: account_anglo_payable_fifo + property_account_receivable: account_anglo_receivable_fifo +- + I configure the account receivable of Customer. +- + !record {model: res.partner, id: base.res_partner_13}: + property_account_payable: account_anglo_payable_fifo + property_account_receivable: account_anglo_receivable_fifo +- + I configure the product category with stock valuation account. +- + !record {model: product.category, id: product.product_category_4}: + property_stock_valuation_account_id: account_anglo_stock_valuation_fifo +- + I create a product with required accounts, and cost method average (but same applies for fifo) +- + !record {model: product.product, id: product_fifo_anglo_saxon}: + name: 'FIFO product for anglo saxon tests' + list_price: 20.00 + standard_price: 0 + categ_id: product.product_category_4 + valuation: 'real_time' + property_account_income: account_anglo_income_fifo + property_account_expense: account_anglo_cogs_fifo + property_account_creditor_price_difference: account_anglo_price_difference_fifo + property_stock_account_input: account_anglo_stock_input_fifo + property_stock_account_output: account_anglo_stock_output_fifo + cost_method: 'average' +- + I create a draft Purchase Order. +- + !record {model: purchase.order, id: purchase_order_001_fifo}: + partner_id: base.res_partner_3 + location_id: stock.stock_location_stock + pricelist_id: 1 + order_line: + - product_id: product_fifo_anglo_saxon + product_qty: 1 + price_unit: 9 + date_planned: '2013-08-31' + taxes_id: [] +- + I confirm the purchase order. +- + !workflow {model: purchase.order, ref: purchase_order_001_fifo, action: purchase_confirm} +- + Reception is ready for process so now done the reception. +- + !python {model: stock.partial.picking}: | + pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_001_fifo")).picking_ids + partial_id = self.create(cr, uid, {},context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]}) + self.do_partial(cr, uid, [partial_id]) +- + I check the Stock Interim account (Received) is credit successfully. +- + !assert {model: account.account, id : account_anglo_stock_input_fifo, string : Stock Interim account (Received) is not credited successfully.}: + - credit == 9 +- + I check the Stock valuation account is debit sucessfully. +- + !assert {model: account.account, id : account_anglo_stock_valuation_fifo, string : Stock valuation account is not debited successfully.}: + - debit == 9 +- + I Validate Invoice of Purchase Order after having changed the price to 10. +- + !python {model: purchase.order}: | + invoice_ids = [x.id for x in self.browse(cr, uid, ref("purchase_order_001_fifo")).invoice_ids] + line_ids = self.pool.get('account.invoice.line').search(cr, uid, [('invoice_id', 'in', invoice_ids)]) + self.pool.get('account.invoice.line').write(cr, uid, line_ids, {'price_unit': 10}) + self.pool.get('account.invoice').signal_invoice_open(cr, uid, invoice_ids) +- + I check the Stock Interim account (Received) is debited sucessfully when Invoice validated. +- + !assert {model: account.account, id : account_anglo_stock_input_fifo, string : Stock Interim account (Received) is not debited successfully.}: + - debit == 9 +- + I check the Price difference creditor Account is debited sucessfully when Invoice validated. +- + !assert {model: account.account, id : account_anglo_price_difference_fifo, string : Price difference creditor Account is not debited successfully.}: + - debit == 1 +- + I check Payable(creditor) Account is Credited sucessfully when Invoice validated. +- + !assert {model: account.account, id : account_anglo_payable_fifo, string : Payable(creditor) Account is not Credited successfully.}: + - credit == 10 +- + I pay the invoice. +- + !python {model: purchase.order}: | + invoice_ids = self.browse(cr, uid, ref("purchase_order_001_fifo")).invoice_ids + order = self.browse(cr, uid, ref("purchase_order_001_fifo")) + journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'cash'), ('company_id', '=', order.company_id.id)], limit=1) + for invoice in invoice_ids: + invoice.pay_and_reconcile(invoice.amount_total, ref('account_anglo_cash_fifo'), ref('account.period_8'), journal_ids[0], ref('account_anglo_cash_fifo'), ref('account.period_8'), journal_ids[0], name='test') +- + I check Payable(Creditors) Account is Debited sucessfully after invoice paid. +- + !assert {model: account.account, id : account_anglo_payable_fifo, string : Payable(Creditors) Account is not Debited successfully.}: + - debit == 10 +- + I check Bank/Cash account is credited sucessfully after invoice paid. +- + !assert {model: account.account, id : account_anglo_cash_fifo, string: Bank/Cash account is not credited successfully.}: + - credit == 10 +- + I create an Outgoing Picking order +- + !record {model: stock.picking, id: stock_picking_out001_fifo}: + partner_id: base.res_partner_13 + invoice_state: 2binvoiced + move_lines: + - company_id: base.main_company + location_id: stock.stock_location_stock + product_id: product_fifo_anglo_saxon + product_qty: 1.0 + location_dest_id: stock.stock_location_customers + move_type: direct + type: out +- + I need to check the availability of the product, So I make my picking order for processing later. +- + !python {model: stock.picking}: | + self.draft_force_assign(cr, uid, [ref("stock_picking_out001_fifo")], {"lang": "en_US", "search_default_available": + 1, "tz": False, "active_model": "ir.ui.menu", "contact_display": "partner", + "active_ids": [ref("stock.menu_action_picking_tree")], "active_id": ref("stock.menu_action_picking_tree"), + }) +- + I check the product availability, Product is available in the stock and ready to be sent. +- + !python {model: stock.picking}: | + self.action_assign(cr, uid, [ref("stock_picking_out001_fifo")], {"lang": "en_US", "search_default_available": + 1, "tz": False, "active_model": "ir.ui.menu", "contact_display": "partner", + "active_ids": [ref("stock.menu_action_picking_tree")], "active_id": ref("stock.menu_action_picking_tree"), + }) +- + I process the delivery. +- + !python {model: stock.partial.picking}: | + partial_id = self.create(cr, uid, {}, context={'active_model':'stock.picking','active_ids':[ref('stock_picking_out001_fifo')]}) + self.do_partial(cr, uid, [partial_id]) +- + I check Stock Interim account (Delivery) is debited successfully. +- + !assert {model: account.account, id : account_anglo_stock_output_fifo, string : Stock Interim account (Delivery) is not debited successfully.}: + - debit == 9 +- + I check the Stock valuation account is credited sucessfully. +- + !assert {model: account.account, id : account_anglo_stock_valuation_fifo, string : Stock valuation account is not credited successfully.}: + - credit == 9 +- + As the Invoice state of the picking order is To be invoiced. I create invoice for my outgoing picking order. +- + !python {model: stock.invoice.onshipping}: | + wiz_id = self.create(cr, uid, {'invoice_date': '2013-03-04', 'journal_id': ref('account.sales_journal')}, + {'active_ids': [ref("stock_picking_out001_fifo")], "active_model": "stock.picking"}) + self.create_invoice(cr, uid, [wiz_id], {"lang": "en_US", + "search_default_available": 1, "tz": False, "active_model": "stock.picking", + "contact_display": "partner", "active_ids": [ref("stock_picking_out001_fifo")], "active_id": ref("stock_picking_out001_fifo")}) +- + I check that the customer invoice is created successfully. +- + !python {model: account.invoice}: | + partner_id = self.pool.get('stock.picking').browse(cr, uid, ref('stock_picking_out001_fifo')).partner_id.id + inv_ids = self.search(cr, uid, [('type','=','out_invoice'),('partner_id','=',partner_id)]) + assert inv_ids, 'No Invoice is generated!' +- + I open the Invoice. +- + !python {model: stock.picking}: | + move_name = self.pool.get('stock.picking').browse(cr, uid, ref('stock_picking_out001_fifo')).name + account_invoice = self.pool.get('account.invoice').search(cr, uid, [('origin', '=', move_name)]) + account_invoice_line = self.pool.get('account.invoice.line').search(cr, uid, [('invoice_id', 'in', account_invoice)]) + self.pool.get('account.invoice.line').write(cr, uid, account_invoice_line, {'invoice_line_tax_id': [(6, 0, [])]}) + self.pool.get('account.invoice').button_reset_taxes(cr, uid, account_invoice) + self.pool.get('account.invoice').signal_invoice_open(cr, uid, account_invoice) +- + I check Income Account is Credited sucessfully when Invoice validated. +- + !assert {model: account.account, id : account_anglo_income_fifo, string : Income Account is not Credited successfully.}: + - credit == 20 +- + I check Cost of goods sold account for debit. +- + !assert {model: account.account, id : account_anglo_cogs_fifo, string : Cost of goods sale is not Debited successfully.}: + - debit == 9 +- + I check Stock Interim account (Delivery) +- + !assert {model: account.account, id : account_anglo_stock_output_fifo, string : Stock Interim account (Delivery) is not credited successfully.}: + - credit == 9 +- + I check Receivable(Debtor) Account for debit. +- + !assert {model: account.account, id : account_anglo_receivable_fifo, string : Receivable(Debtors) Account is not Debited successfully.}: + - debit == 20 +- + I pay the invoice. +- + !python {model: account.invoice}: | + move_name = self.pool.get('stock.picking').browse(cr, uid, ref('stock_picking_out001_fifo')).name + account_invoice= self.pool.get('account.invoice').search(cr, uid, [('origin', '=', move_name)]) + journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'cash')], limit=1) + pay = self.pay_and_reconcile(cr, uid, account_invoice, + 20.0, ref('account_anglo_cash_fifo'), ref('account.period_8'), + journal_ids[0], ref('account_anglo_cash_fifo'), + ref('account.period_8'), journal_ids[0], + name='Payment for test customer invoice') + assert (pay == True), "Incorrect Payment." +- + I check Receivable(Debtor) Account for credit. +- + !assert {model: account.account, id : account_anglo_receivable_fifo, string : Receivable(Debtors) Account is not Credited successfully.}: + - credit == 20 +- + I check Bank/Cash account is debited sucessfully after invoice paid. +- + !assert {model: account.account, id : account_anglo_cash_fifo, string: Bank/Cash account is not successfully credited.}: + - debit == 20 diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 0ad39fca4f8..aad9d3b1459 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -485,6 +485,7 @@ class purchase_order(osv.osv): 'uos_id': order_line.product_uom.id or False, 'invoice_line_tax_id': [(6, 0, [x.id for x in order_line.taxes_id])], 'account_analytic_id': order_line.account_analytic_id.id or False, + 'purchase_line_id': order_line.id, } def action_cancel_draft(self, cr, uid, ids, context=None): @@ -633,6 +634,7 @@ class purchase_order(osv.osv): } def _prepare_order_line_move(self, cr, uid, order, order_line, picking_id, context=None): + ''' prepare the stock move data from the PO line ''' return { 'name': order_line.name or '', 'product_id': order_line.product_id.id, @@ -869,7 +871,7 @@ class purchase_order_line(osv.osv): '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", store=True), - 'date_order': fields.related('order_id','date_order',string='Order Date',readonly=True,type="date") + 'date_order': fields.related('order_id','date_order',string='Order Date',readonly=True,type="date"), } _defaults = { @@ -1246,5 +1248,13 @@ class account_invoice(osv.Model): purchase_order_obj.message_post(cr, uid, po_ids, body=_("Invoice paid"), context=context) return res +class account_invoice_line(osv.Model): + """ Override account_invoice_line to add the link to the purchase order line it is related to""" + _inherit = 'account.invoice.line' + _columns = { + 'purchase_line_id': fields.many2one('purchase.order.line', + 'Purchase Order Line', ondelete='set null', select=True, + readonly=True), + } # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: