← Back to team overview

openerp-community-reviewer team mailing list archive

[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