Merge lp:~david-cormier-j/sale-wkfl/sale_landed_costs into lp:~sale-core-editors/sale-wkfl/7.0

Proposed by David Cormier
Status: Needs review
Proposed branch: lp:~david-cormier-j/sale-wkfl/sale_landed_costs
Merge into: lp:~sale-core-editors/sale-wkfl/7.0
Diff against target: 321 lines (+301/-0)
4 files modified
sale_landed_costs/__init__.py (+26/-0)
sale_landed_costs/__openerp__.py (+47/-0)
sale_landed_costs/sale.py (+188/-0)
sale_landed_costs/sale_view.xml (+40/-0)
To merge this branch: bzr merge lp:~david-cormier-j/sale-wkfl/sale_landed_costs
Reviewer Review Type Date Requested Status
Pedro Manuel Baeza Needs Resubmitting
Joël Grand-Guillaume @ camptocamp code review, no tests Needs Fixing
Review via email: mp+205650@code.launchpad.net

Description of the change

Add a sale_landed_costs module

This module is an adaptation of the purchase_landed_costs (in c2c_rd_addons project) for sales

To post a comment you must log in.
Revision history for this message
Joël Grand-Guillaume @ camptocamp (jgrandguillaume-c2c) wrote :

Hi David,

Thanks for porting this module. A few remarks:

 * Would you please consider using the BZR extractor (https://launchpad.net/bazaar-extractor) to put this module in that branch ? This will then keep the commite message insead of having just one commit that add the module. This seems fair on order to keep the author's work.

 * Then, it deserve a bit of PEP8 formatting

Regards,

Joël

review: Needs Fixing (code review, no tests)
Revision history for this message
Pedro Manuel Baeza (pedro.baeza) wrote :

This project is now hosted on https://github.com/OCA/sale-workflow. Please move your proposal there. This guide may help you https://github.com/OCA/maintainers-tools/wiki/How-to-move-a-Merge-Proposal-to-GitHub

review: Needs Resubmitting

Unmerged revisions

33. By David Cormier

[FIX] proper attribution

32. By David Cormier

[NEW] Add sale landed costs

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== 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 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# OpenERP, Open Source Management Solution
5# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
6# Copyright (C) 2010-2012 Camptocamp Austria (<http://www.camptocamp.at>)
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23import sale
24
25
26# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
027
=== 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 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# OpenERP, Open Source Management Solution
5# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
6# Copyright (C) 2010-2012 Camptocamp Austria (<http://www.camptocamp.at>)
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23
24{
25 'name': 'Sale Order Landed Costs',
26 'version': '1.0',
27 'author': 'Camptocamp Austria',
28 'maintainer': 'Savoir-faire Linux',
29 'website': 'http://www.savoirfairelinux.com',
30 'category': 'Warehouse Management',
31 'description': """\
32This module add the possibility to include landed costs in the average price computation of Sale Orders.
33
34 Contributors:
35 Sandy Carter <sandy.carter@savoirfairelinux.com>
36 David Cormier <david.cormier@savoirfairelinux.com>
37
38""",
39 'depends': ['sale', 'purchase_landed_costs'],
40 'external_dependencies': {},
41 'data': ['sale_view.xml'],
42 'demo': [],
43 'test': [],
44 'installable': True,
45 'active': False,
46}
47# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
048
=== 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 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# OpenERP, Open Source Management Solution
5# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
6# Copyright (C) 2010-2012 Camptocamp Austria (<http://www.camptocamp.at>)
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23from openerp.osv import orm, fields
24from openerp import netsvc
25import openerp.addons.decimal_precision as dp
26
27
28class landed_cost_position(orm.Model):
29 """Adding link to sale order and sale order lines"""
30 _inherit = "landed.cost.position"
31 _columns = {
32 'sale_order_line_id': fields.many2one('sale.order.line', 'Sale Order Line'),
33 'sale_order_id': fields.many2one('sale.order', 'Sale Order'),
34 }
35
36
37class sale_order_line(orm.Model):
38 """Adding landing costs fields"""
39 _inherit = "sale.order.line"
40
41 def _landing_cost(self, cr, uid, ids, name, args, context):
42 """Calculate landing costs from value costs and amount costs"""
43 ret = {}
44 for line in self.browse(cr, uid, ids):
45 ret[line.id] = sum(costs.amount if costs.price_type == 'value' else costs.amount * line.product_uom_qty
46 for costs in line.landed_cost_line_ids)
47 return ret
48
49 def _landing_cost_order(self, cr, uid, ids, name, args, context):
50 """Calculate landed costs from Absolute values and Per Quantity values"""
51 ret = {}
52 for line in self.browse(cr, uid, ids):
53 landed_costs = 0.0
54 if line.order_id.landed_cost_line_ids:
55 try:
56 landed_costs = (
57 line.order_id.landed_cost_base_value/line.order_id.amount_total * line.price_subtotal +
58 line.order_id.landed_cost_base_quantity/line.order_id.quantity_total * line.product_uom_qty)
59 except ZeroDivisionError:
60 landed_costs = 0.0
61 ret[line.id] = landed_costs
62 return ret
63
64 def _landed_cost(self, cr, uid, ids, name, args, context):
65 """Calculate total landed cost (regular price + landing costs)"""
66 ret = {}
67 for line in self.browse(cr, uid, ids):
68 ret[line.id] = line.price_subtotal + line.landing_costs + line.landing_costs_order
69 return ret
70
71 _columns = {
72 'landed_cost_line_ids': fields.one2many('landed.cost.position', 'sale_order_line_id', 'Landed Costs Positions'),
73 'landing_costs': fields.function(_landing_cost,
74 digits_compute=dp.get_precision('Account'),
75 string='Landing Costs'),
76 'landing_costs_order': fields.function(_landing_cost_order,
77 digits_compute=dp.get_precision('Account'),
78 string='Landing Costs from Order'),
79 'landed_costs': fields.function(_landed_cost,
80 digits_compute=dp.get_precision('Account'),
81 string='Landed Costs'),
82 }
83
84
85class sale_order(orm.Model):
86 """Adding landing costs fields as well as total"""
87 _inherit = "sale.order"
88
89 def _landed_cost_base_value(self, cr, uid, ids, name, args, context):
90 """Calculate total of costs of price type 'value'"""
91 ret = {}
92 for line in self.browse(cr, uid, ids):
93 ret[line.id] = sum(costs.amount for costs in line.landed_cost_line_ids if costs.price_type == 'value')
94 return ret
95
96 def _landed_cost_base_quantity(self, cr, uid, ids, name, args, context):
97 """Calculate total of costs of price type 'per_unit'"""
98 ret = {}
99 for line in self.browse(cr, uid, ids):
100 ret[line.id] = sum(costs.amount for costs in line.landed_cost_line_ids if costs.price_type == 'per_unit')
101 return ret
102
103 def _quantity_total(self, cr, uid, ids, name, args, context):
104 """Calculate total product quantity from sale order lines """
105 ret = {}
106 for line in self.browse(cr, uid, ids):
107 ret[line.id] = sum(sol.product_uom_qty for sol in line.order_line if sol.product_uom_qty > 0.0)
108 return ret
109
110 def _landed_cost(self, cr, uid, ids, name, args, context):
111 ret = {}
112 for line in self.browse(cr, uid, ids):
113 ret[line.id] = (line.landing_cost_lines + line.landed_cost_base_value + line.landed_cost_base_quantity +
114 line.amount_untaxed)
115 return ret
116
117 def _landing_cost_lines(self, cr, uid, ids, name, args, context):
118 """Calculate total landed costs from sale order lines """
119 ret = {}
120 for line in self.browse(cr, uid, ids):
121 ret[line.id] = sum(sol.landing_costs for sol in line.order_line if sol.product_uom_qty > 0.0)
122 return ret
123
124 _columns = {
125 'landed_cost_line_ids': fields.one2many('landed.cost.position', 'sale_order_id', 'Landed Costs'),
126 'landed_cost_base_value': fields.function(_landed_cost_base_value,
127 digits_compute=dp.get_precision('Account'),
128 string='Landed Costs Base Value'),
129 'landed_cost_base_quantity': fields.function(_landed_cost_base_quantity,
130 digits_compute=dp.get_precision('Account'),
131 string='Landed Costs Base Quantity'),
132 'landing_cost_lines': fields.function(_landing_cost_lines,
133 digits_compute=dp.get_precision('Account'),
134 string='Landing Cost Lines'),
135 'landed_cost': fields.function(_landed_cost,
136 digits_compute=dp.get_precision('Account'),
137 string='Landed Costs Total Untaxed'),
138 'quantity_total': fields.function(_quantity_total,
139 digits_compute=dp.get_precision('Product UoM'),
140 string='Total Quantity'),
141 }
142
143 def _get_product_account_expense_id(self, product):
144 """
145 Returns the product's account expense id if present
146 or it's parent categories account expense id otherwise
147 """
148 if product.property_account_expense.id:
149 return product.property_account_expense.id
150 return product.categ_id.property_account_expense_categ.id
151
152 def _create_pickings(self, cr, uid, order, context=None):
153
154 invoice_obj = self.pool.get('account.invoice')
155 invoice_line_obj = self.pool.get('account.invoice.line')
156 journal_obj = self.pool.get('account.journal')
157 journal_ids = journal_obj.search(cr, uid, [('type', '=', 'purchase'),
158 ('company_id', '=', order.company_id.id)],
159 limit=1)
160 for order_cost in order.landed_cost_line_ids:
161 vals_inv = {
162 'partner_id': order_cost.partner_id.id,
163 'currency_id': order_cost.currency_id.id or order.company_id.currency_id.id,
164 'account_id': order_cost.partner_id.property_account_payable.id,
165 'type': 'in_invoice',
166 'origin': order.name,
167 'fiscal_position': (order.partner_id.property_account_position and
168 order.partner_id.property_account_position.id or
169 False),
170 'company_id': order.company_id.id,
171 'journal_id': len(journal_ids) and journal_ids[0] or False
172 }
173 inv_id = invoice_obj.create(cr, uid, vals_inv, context=None)
174 vals_line = {
175 'product_id': order_cost.product_id.id,
176 'name': order_cost.product_id.name,
177 'account_id': self._get_product_account_expense_id(order_cost.product_id),
178 'partner_id': order_cost.partner_id.id,
179 'invoice_id': inv_id,
180 'price_unit': order_cost.amount,
181 'invoice_line_tax_id': [(6, 0, [x.id for x in order_cost.product_id.supplier_taxes_id])]
182 }
183 invoice_line_obj.create(cr, uid, vals_line, context=None)
184
185 def action_done(self, cr, uid, ids, context=None):
186 for order in self.browse(cr, uid, ids):
187 self._create_pickings(cr, uid, order, context=context)
188 return super(sale_order, self).action_done(cr, uid, ids, context=context)
0189
=== 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 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<openerp>
3 <data>
4 <!-- Landed costs Sale Form-->
5 <record model="ir.ui.view" id="sale_order_landed_cost_view">
6 <field name="name">sale.order.landed.cost.form.view</field>
7 <field name="model">sale.order</field>
8 <field name="inherit_id" ref="sale.view_order_form"/>
9 <field name="arch" type="xml">
10 <data>
11 <field name="price_subtotal" position="after">
12 <field name="landing_costs" invisible="1"/>
13 <field name="landing_costs_order"/>
14 <field name="landed_costs"/>
15 </field>
16 <notebook position="inside">
17 <page string="Landing Costs" attrs="{'readonly':[('state','=','done')]}">
18 <group>
19 <field name="quantity_total"/>
20 <field name="landed_cost_base_quantity" />
21 <field name="landed_cost_base_value" />
22 </group>
23 <group colspan="2" col="2">
24 <field name="landing_cost_lines"/>
25 <field name="landed_cost"/>
26 </group>
27
28 <field
29 name="landed_cost_line_ids"
30 colspan="4"
31 nolabel="1"
32 widget="one2many_list"
33 attrs="{'readonly': [('state', 'in', ('approved', 'done'))]}" />
34 </page>
35 </notebook>
36 </data>
37 </field>
38 </record>
39 </data>
40</openerp>

Subscribers

People subscribed via source and target branches