openerp-community-reviewer team mailing list archive
-
openerp-community-reviewer team
-
Mailing list archive
-
Message #03696
[Merge] lp:~david-cormier-j/sale-wkfl/sale_landed_costs into lp:sale-wkfl
David Cormier (Savoir-faire Linux) has proposed merging lp:~david-cormier-j/sale-wkfl/sale_landed_costs into lp:sale-wkfl.
Requested reviews:
Sale Core Editors (sale-core-editors)
For more details, see:
https://code.launchpad.net/~david-cormier-j/sale-wkfl/sale_landed_costs/+merge/205650
Add a sale_landed_costs module
This module is an adaptation of the purchase_landed_costs (in c2c_rd_addons project) for sales
--
https://code.launchpad.net/~david-cormier-j/sale-wkfl/sale_landed_costs/+merge/205650
Your team Sale Core Editors is requested to review the proposed merge of lp:~david-cormier-j/sale-wkfl/sale_landed_costs into lp:sale-wkfl.
=== added directory 'sale_landed_costs'
=== added file 'sale_landed_costs/__init__.py'
--- sale_landed_costs/__init__.py 1970-01-01 00:00:00 +0000
+++ sale_landed_costs/__init__.py 2014-02-10 20:32:58 +0000
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
+# Copyright (C) 2010-2012 Camptocamp Austria (<http://www.camptocamp.at>)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import sale
+
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added file 'sale_landed_costs/__openerp__.py'
--- sale_landed_costs/__openerp__.py 1970-01-01 00:00:00 +0000
+++ sale_landed_costs/__openerp__.py 2014-02-10 20:32:58 +0000
@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
+# Copyright (C) 2010-2012 Camptocamp Austria (<http://www.camptocamp.at>)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+
+{
+ 'name': 'Sale Order Landed Costs',
+ 'version': '1.0',
+ 'author': 'Camptocamp Austria',
+ 'maintainer': 'Savoir-faire Linux',
+ 'website': 'http://www.savoirfairelinux.com',
+ 'category': 'Warehouse Management',
+ 'description': """\
+This module add the possibility to include landed costs in the average price computation of Sale Orders.
+
+ Contributors:
+ Sandy Carter <sandy.carter@xxxxxxxxxxxxxxxxxxxx>
+ David Cormier <david.cormier@xxxxxxxxxxxxxxxxxxxx>
+
+""",
+ 'depends': ['sale', 'purchase_landed_costs'],
+ 'external_dependencies': {},
+ 'data': ['sale_view.xml'],
+ 'demo': [],
+ 'test': [],
+ 'installable': True,
+ 'active': False,
+}
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added file 'sale_landed_costs/sale.py'
--- sale_landed_costs/sale.py 1970-01-01 00:00:00 +0000
+++ sale_landed_costs/sale.py 2014-02-10 20:32:58 +0000
@@ -0,0 +1,188 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
+# Copyright (C) 2010-2012 Camptocamp Austria (<http://www.camptocamp.at>)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import orm, fields
+from openerp import netsvc
+import openerp.addons.decimal_precision as dp
+
+
+class landed_cost_position(orm.Model):
+ """Adding link to sale order and sale order lines"""
+ _inherit = "landed.cost.position"
+ _columns = {
+ 'sale_order_line_id': fields.many2one('sale.order.line', 'Sale Order Line'),
+ 'sale_order_id': fields.many2one('sale.order', 'Sale Order'),
+ }
+
+
+class sale_order_line(orm.Model):
+ """Adding landing costs fields"""
+ _inherit = "sale.order.line"
+
+ def _landing_cost(self, cr, uid, ids, name, args, context):
+ """Calculate landing costs from value costs and amount costs"""
+ ret = {}
+ for line in self.browse(cr, uid, ids):
+ ret[line.id] = sum(costs.amount if costs.price_type == 'value' else costs.amount * line.product_uom_qty
+ for costs in line.landed_cost_line_ids)
+ return ret
+
+ def _landing_cost_order(self, cr, uid, ids, name, args, context):
+ """Calculate landed costs from Absolute values and Per Quantity values"""
+ ret = {}
+ for line in self.browse(cr, uid, ids):
+ landed_costs = 0.0
+ if line.order_id.landed_cost_line_ids:
+ try:
+ landed_costs = (
+ line.order_id.landed_cost_base_value/line.order_id.amount_total * line.price_subtotal +
+ line.order_id.landed_cost_base_quantity/line.order_id.quantity_total * line.product_uom_qty)
+ except ZeroDivisionError:
+ landed_costs = 0.0
+ ret[line.id] = landed_costs
+ return ret
+
+ def _landed_cost(self, cr, uid, ids, name, args, context):
+ """Calculate total landed cost (regular price + landing costs)"""
+ ret = {}
+ for line in self.browse(cr, uid, ids):
+ ret[line.id] = line.price_subtotal + line.landing_costs + line.landing_costs_order
+ return ret
+
+ _columns = {
+ 'landed_cost_line_ids': fields.one2many('landed.cost.position', 'sale_order_line_id', 'Landed Costs Positions'),
+ 'landing_costs': fields.function(_landing_cost,
+ digits_compute=dp.get_precision('Account'),
+ string='Landing Costs'),
+ 'landing_costs_order': fields.function(_landing_cost_order,
+ digits_compute=dp.get_precision('Account'),
+ string='Landing Costs from Order'),
+ 'landed_costs': fields.function(_landed_cost,
+ digits_compute=dp.get_precision('Account'),
+ string='Landed Costs'),
+ }
+
+
+class sale_order(orm.Model):
+ """Adding landing costs fields as well as total"""
+ _inherit = "sale.order"
+
+ def _landed_cost_base_value(self, cr, uid, ids, name, args, context):
+ """Calculate total of costs of price type 'value'"""
+ ret = {}
+ for line in self.browse(cr, uid, ids):
+ ret[line.id] = sum(costs.amount for costs in line.landed_cost_line_ids if costs.price_type == 'value')
+ return ret
+
+ def _landed_cost_base_quantity(self, cr, uid, ids, name, args, context):
+ """Calculate total of costs of price type 'per_unit'"""
+ ret = {}
+ for line in self.browse(cr, uid, ids):
+ ret[line.id] = sum(costs.amount for costs in line.landed_cost_line_ids if costs.price_type == 'per_unit')
+ return ret
+
+ def _quantity_total(self, cr, uid, ids, name, args, context):
+ """Calculate total product quantity from sale order lines """
+ ret = {}
+ for line in self.browse(cr, uid, ids):
+ ret[line.id] = sum(sol.product_uom_qty for sol in line.order_line if sol.product_uom_qty > 0.0)
+ return ret
+
+ def _landed_cost(self, cr, uid, ids, name, args, context):
+ ret = {}
+ for line in self.browse(cr, uid, ids):
+ ret[line.id] = (line.landing_cost_lines + line.landed_cost_base_value + line.landed_cost_base_quantity +
+ line.amount_untaxed)
+ return ret
+
+ def _landing_cost_lines(self, cr, uid, ids, name, args, context):
+ """Calculate total landed costs from sale order lines """
+ ret = {}
+ for line in self.browse(cr, uid, ids):
+ ret[line.id] = sum(sol.landing_costs for sol in line.order_line if sol.product_uom_qty > 0.0)
+ return ret
+
+ _columns = {
+ 'landed_cost_line_ids': fields.one2many('landed.cost.position', 'sale_order_id', 'Landed Costs'),
+ 'landed_cost_base_value': fields.function(_landed_cost_base_value,
+ digits_compute=dp.get_precision('Account'),
+ string='Landed Costs Base Value'),
+ 'landed_cost_base_quantity': fields.function(_landed_cost_base_quantity,
+ digits_compute=dp.get_precision('Account'),
+ string='Landed Costs Base Quantity'),
+ 'landing_cost_lines': fields.function(_landing_cost_lines,
+ digits_compute=dp.get_precision('Account'),
+ string='Landing Cost Lines'),
+ 'landed_cost': fields.function(_landed_cost,
+ digits_compute=dp.get_precision('Account'),
+ string='Landed Costs Total Untaxed'),
+ 'quantity_total': fields.function(_quantity_total,
+ digits_compute=dp.get_precision('Product UoM'),
+ string='Total Quantity'),
+ }
+
+ def _get_product_account_expense_id(self, product):
+ """
+ Returns the product's account expense id if present
+ or it's parent categories account expense id otherwise
+ """
+ if product.property_account_expense.id:
+ return product.property_account_expense.id
+ return product.categ_id.property_account_expense_categ.id
+
+ def _create_pickings(self, cr, uid, order, context=None):
+
+ invoice_obj = self.pool.get('account.invoice')
+ invoice_line_obj = self.pool.get('account.invoice.line')
+ journal_obj = self.pool.get('account.journal')
+ journal_ids = journal_obj.search(cr, uid, [('type', '=', 'purchase'),
+ ('company_id', '=', order.company_id.id)],
+ limit=1)
+ for order_cost in order.landed_cost_line_ids:
+ vals_inv = {
+ 'partner_id': order_cost.partner_id.id,
+ 'currency_id': order_cost.currency_id.id or order.company_id.currency_id.id,
+ 'account_id': order_cost.partner_id.property_account_payable.id,
+ 'type': 'in_invoice',
+ 'origin': order.name,
+ 'fiscal_position': (order.partner_id.property_account_position and
+ order.partner_id.property_account_position.id or
+ False),
+ 'company_id': order.company_id.id,
+ 'journal_id': len(journal_ids) and journal_ids[0] or False
+ }
+ inv_id = invoice_obj.create(cr, uid, vals_inv, context=None)
+ vals_line = {
+ 'product_id': order_cost.product_id.id,
+ 'name': order_cost.product_id.name,
+ 'account_id': self._get_product_account_expense_id(order_cost.product_id),
+ 'partner_id': order_cost.partner_id.id,
+ 'invoice_id': inv_id,
+ 'price_unit': order_cost.amount,
+ 'invoice_line_tax_id': [(6, 0, [x.id for x in order_cost.product_id.supplier_taxes_id])]
+ }
+ invoice_line_obj.create(cr, uid, vals_line, context=None)
+
+ def action_done(self, cr, uid, ids, context=None):
+ for order in self.browse(cr, uid, ids):
+ self._create_pickings(cr, uid, order, context=context)
+ return super(sale_order, self).action_done(cr, uid, ids, context=context)
=== added file 'sale_landed_costs/sale_view.xml'
--- sale_landed_costs/sale_view.xml 1970-01-01 00:00:00 +0000
+++ sale_landed_costs/sale_view.xml 2014-02-10 20:32:58 +0000
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<openerp>
+ <data>
+ <!-- Landed costs Sale Form-->
+ <record model="ir.ui.view" id="sale_order_landed_cost_view">
+ <field name="name">sale.order.landed.cost.form.view</field>
+ <field name="model">sale.order</field>
+ <field name="inherit_id" ref="sale.view_order_form"/>
+ <field name="arch" type="xml">
+ <data>
+ <field name="price_subtotal" position="after">
+ <field name="landing_costs" invisible="1"/>
+ <field name="landing_costs_order"/>
+ <field name="landed_costs"/>
+ </field>
+ <notebook position="inside">
+ <page string="Landing Costs" attrs="{'readonly':[('state','=','done')]}">
+ <group>
+ <field name="quantity_total"/>
+ <field name="landed_cost_base_quantity" />
+ <field name="landed_cost_base_value" />
+ </group>
+ <group colspan="2" col="2">
+ <field name="landing_cost_lines"/>
+ <field name="landed_cost"/>
+ </group>
+
+ <field
+ name="landed_cost_line_ids"
+ colspan="4"
+ nolabel="1"
+ widget="one2many_list"
+ attrs="{'readonly': [('state', 'in', ('approved', 'done'))]}" />
+ </page>
+ </notebook>
+ </data>
+ </field>
+ </record>
+ </data>
+</openerp>
Follow ups