Add module purchase_stock_usability

Port purchase_usability to v12
This commit is contained in:
Alexis de Lattre
2019-02-01 19:45:59 +01:00
parent ee3b872e66
commit 92a175ea97
12 changed files with 160 additions and 165 deletions

56
.gitignore vendored Normal file
View File

@@ -0,0 +1,56 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
# C extensions
*.so
# Distribution / packaging
.Python
env/
bin/
build/
develop-eggs/
dist/
eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.cache
nosetests.xml
coverage.xml
# Translations
*.mo
# Pycharm
.idea
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
# Rope
.ropeproject
# Sphinx documentation
docs/_build/
# Backup files
*~
*.swp

View File

@@ -17,32 +17,3 @@ class BaseLanguageInstall(models.TransientModel):
_inherit = 'base.language.install' _inherit = 'base.language.install'
overwrite = fields.Boolean(default=True) overwrite = fields.Boolean(default=True)
class BaseUsabilityInstalled(models.AbstractModel):
_name = "base.usability.installed"
_description = "technical flag to see if base_usability module is installed"
formatLang_original = misc.formatLang
def formatLang(self, value, digits=None, grouping=True, monetary=False,
dp=False, currency_obj=False, int_no_digits=True):
with api.Environment.manage():
env = api.Environment(self.cr, self.uid, {})
if (
'base.usability.installed' in env and
int_no_digits and
not monetary and
isinstance(value, float) and
dp):
prec = env['decimal.precision'].precision_get(dp)
if not float_compare(value, int(value), precision_digits=prec):
digits = 0
dp = False
res = formatLang_original(
self, value, digits=digits, grouping=grouping, monetary=monetary,
dp=dp, currency_obj=currency_obj)
return res
misc.formatLang = formatLang

View File

@@ -0,0 +1 @@
from . import purchase

View File

@@ -0,0 +1,29 @@
# Copyright (C) 2014-2019 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
'name': 'Purchase Stock Usability',
'version': '12.0.1.0.0',
'category': 'Purchases',
'license': 'AGPL-3',
'summary': 'Usability improvements on purchase_stock module',
'description': """
Purchase Stock Usability
========================
Several usability improvements on the official purchase_stock module:
Please contact Alexis de Lattre from Akretion <alexis.delattre@akretion.com> for any help or question about this module.
""",
'author': 'Akretion',
'website': 'http://www.akretion.com',
'depends': [
'purchase_stock',
'purchase_usability',
],
'data': [
'stock_view.xml',
],
'installable': True,
}

View File

@@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
# Copyright 2015-2019 Akretion France (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields, api
class PurchaseOrder(models.Model):
_inherit = 'purchase.order'
picking_type_id = fields.Many2one(track_visibility='onchange')
incoterm_id = fields.Many2one(track_visibility='onchange')
# inherit compute method of the field delivery_partner_id
# defined in purchase_usability
@api.depends('dest_address_id', 'picking_type_id')
def _compute_delivery_partner_id(self):
for o in self:
delivery_partner_id = False
if o.dest_address_id:
delivery_partner_id = o.dest_address_id
elif (
o.picking_type_id.warehouse_id and
o.picking_type_id.warehouse_id.partner_id):
delivery_partner_id = o.picking_type_id.warehouse_id.partner_id
o.delivery_partner_id = delivery_partner_id

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2019 Akretion (http://www.akretion.com/)
@author: Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<odoo>
<record id="view_picking_form" model="ir.ui.view">
<field name="name">purchase_usability.stock.picking.form</field>
<field name="model">stock.picking</field>
<field name="inherit_id" ref="stock.view_picking_form"/>
<field name="arch" type="xml">
<field name="origin" position="after">
<field name="purchase_id" attrs="{'invisible': [('picking_type_code', '!=', 'incoming')]}"/>
</field>
</field>
</record>
</odoo>

View File

@@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
from . import purchase from . import purchase
from . import product from . import product
from . import partner from . import partner

View File

@@ -1,19 +1,18 @@
# -*- coding: utf-8 -*- # Copyright (C) 2014-2019 Akretion (http://www.akretion.com)
# Copyright (C) 2014-2017 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com> # @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{ {
'name': 'Purchase Usability', 'name': 'Purchase Usability',
'version': '10.0.0.1.0', 'version': '12.0.1.0.0',
'category': 'Purchase Management', 'category': 'Purchases',
'license': 'AGPL-3', 'license': 'AGPL-3',
'summary': 'Show invoices and receptions on PO', 'summary': 'Usability improvements on purchase module',
'description': """ 'description': """
Purchase Usability Extension Purchase Usability
============================ ==================
Display Invoices and Incoming Shipments on Purchase Order form view (in dedicated tabs). Several usability improvements on the official purchase module:
Please contact Alexis de Lattre from Akretion <alexis.delattre@akretion.com> for any help or question about this module. Please contact Alexis de Lattre from Akretion <alexis.delattre@akretion.com> for any help or question about this module.
""", """,
@@ -22,7 +21,6 @@ Please contact Alexis de Lattre from Akretion <alexis.delattre@akretion.com> for
'depends': ['purchase'], 'depends': ['purchase'],
'data': [ 'data': [
'purchase_view.xml', 'purchase_view.xml',
'stock_view.xml',
], ],
'active': False, 'installable': True,
} }

View File

@@ -1,30 +1,11 @@
# -*- coding: utf-8 -*- # Copyright 2017-2019 Akretion France
# © 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>) # @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields, api from odoo import models, fields
class ResPartner(models.Model): class ResPartner(models.Model):
_inherit = 'res.partner' _inherit = 'res.partner'
purchase_warn = fields.Selection(track_visibility='onchange') purchase_warn = fields.Selection(track_visibility='onchange')
# Fix an access right issue when accessing partner form without being
# a member of the purchase/User group
@api.multi
def _purchase_invoice_count(self):
poo = self.env['purchase.order']
aio = self.env['account.invoice']
for partner in self:
try:
partner.purchase_order_count = poo.search_count(
[('partner_id', 'child_of', partner.id)])
except Exception:
pass
try:
partner.supplier_invoice_count = aio.search_count([
('partner_id', 'child_of', partner.id),
('type', '=', 'in_invoice')])
except Exception:
pass

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # Copyright 2016-2019 Akretion France
# © 2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>) # @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields from odoo import models, fields

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# © 2015-2016 Akretion (http://www.akretion.com) # Copyright 2015-2019 Akretion France (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com> # @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
@@ -10,45 +10,22 @@ from odoo.tools.misc import formatLang
class PurchaseOrder(models.Model): class PurchaseOrder(models.Model):
_inherit = 'purchase.order' _inherit = 'purchase.order'
picking_type_id = fields.Many2one(track_visibility='onchange')
dest_address_id = fields.Many2one(track_visibility='onchange') dest_address_id = fields.Many2one(track_visibility='onchange')
currency_id = fields.Many2one(track_visibility='onchange') currency_id = fields.Many2one(track_visibility='onchange')
payment_term_id = fields.Many2one(track_visibility='onchange') payment_term_id = fields.Many2one(track_visibility='onchange')
fiscal_position_id = fields.Many2one(track_visibility='onchange') fiscal_position_id = fields.Many2one(track_visibility='onchange')
incoterm_id = fields.Many2one(track_visibility='onchange')
partner_ref = fields.Char(track_visibility='onchange') partner_ref = fields.Char(track_visibility='onchange')
# field 'partner_id': native value for track_visibility='always' # field 'partner_id': native value for track_visibility='always'
partner_id = fields.Many2one(track_visibility='onchange') partner_id = fields.Many2one(track_visibility='onchange')
# for report # the field 'delivery_partner_id' is used in report
# the compute method of that field is inherited in purchase_stock_usability
delivery_partner_id = fields.Many2one( delivery_partner_id = fields.Many2one(
'res.partner', compute='_compute_delivery_partner_id', readonly=True) 'res.partner', compute='_compute_delivery_partner_id', readonly=True)
@api.multi @api.depends('dest_address_id')
@api.depends('dest_address_id', 'picking_type_id')
def _compute_delivery_partner_id(self): def _compute_delivery_partner_id(self):
for o in self: for order in self:
delivery_partner_id = False order.delivery_partner_id = order.dest_address_id
if o.dest_address_id:
delivery_partner_id = o.dest_address_id
elif (
o.picking_type_id.warehouse_id and
o.picking_type_id.warehouse_id.partner_id):
delivery_partner_id = o.picking_type_id.warehouse_id.partner_id
o.delivery_partner_id = delivery_partner_id
@api.multi
def button_confirm(self):
'''Reload view upon order confirmation to display the 3 qty cols'''
res = super(PurchaseOrder, self).button_confirm()
if len(self) == 1:
res = self.env['ir.actions.act_window'].for_xml_id(
'purchase', 'purchase_form_action')
res.update({
'view_mode': 'form,tree,kanban,pivot,graph,calendar',
'res_id': self.id,
'views': False,
})
return res
def print_order(self): def print_order(self):
action = self.env['report'].get_action( action = self.env['report'].get_action(
@@ -63,17 +40,8 @@ class PurchaseOrder(models.Model):
for po in self: for po in self:
name = po.name name = po.name
if po.partner_ref: if po.partner_ref:
name += ' ('+po.partner_ref+')' name += ' (' + po.partner_ref + ')'
if po.amount_untaxed: if self.env.context.get('show_total_amount') and po.amount_total:
name += ': ' + formatLang(self.env, po.amount_untaxed, currency_obj=po.currency_id) name += ': ' + formatLang(self.env, po.amount_untaxed, currency_obj=po.currency_id)
result.append((po.id, name)) result.append((po.id, name))
return result return result
class StockPicking(models.Model):
_inherit = 'stock.picking'
# Field added to have a clickable link from picking to PO
purchase_id = fields.Many2one(
related='move_lines.purchase_line_id.order_id', readonly=True,
string='Purchase Order')

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- <!--
© 2014-2016 Akretion (http://www.akretion.com/) Copyright 2014-2019 Akretion (http://www.akretion.com/)
@author: Alexis de Lattre <alexis.delattre@akretion.com> @author: Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
--> -->
@@ -14,7 +14,7 @@
<field name="inherit_id" ref="purchase.purchase_order_form"/> <field name="inherit_id" ref="purchase.purchase_order_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<button name="action_rfq_send" states="purchase" position="after"> <button name="action_rfq_send" states="purchase" position="after">
<button name="print_order" states="purchase" string="Print Order" type="object" groups="base.group_user"/> <button name="print_order" states="purchase" string="Print Order" type="object"/>
</button> </button>
<field name="fiscal_position_id" position="attributes"> <field name="fiscal_position_id" position="attributes">
<attribute name="widget">selection</attribute> <attribute name="widget">selection</attribute>
@@ -38,9 +38,6 @@
<field name="model">purchase.order</field> <field name="model">purchase.order</field>
<field name="inherit_id" ref="purchase.purchase_order_tree"/> <field name="inherit_id" ref="purchase.purchase_order_tree"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="state" position="after">
<field name="is_shipped" invisible="not context.get('show_purchase', False)"/>
</field>
<!-- the 'origin' field can be very long ; it can list a lot of MO or OP! <!-- the 'origin' field can be very long ; it can list a lot of MO or OP!
I think limiting the size of the field would not be the best option, I think limiting the size of the field would not be the best option,
because the info it carries can be interesting. So we just remove it from because the info it carries can be interesting. So we just remove it from
@@ -56,11 +53,6 @@
<field name="model">purchase.order</field> <field name="model">purchase.order</field>
<field name="inherit_id" ref="purchase.view_purchase_order_filter"/> <field name="inherit_id" ref="purchase.view_purchase_order_filter"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<filter name="not_invoiced" position="before">
<filter name="shipped" string="Fully Received" domain="[('is_shipped', '=', True)]"/>
<filter name="not_shipped" string="Not Fully Received" domain="[('is_shipped', '=', False)]"/>
<separator/>
</filter>
<field name="name" position="attributes"> <field name="name" position="attributes">
<attribute name="string">Reference or Origin</attribute> <attribute name="string">Reference or Origin</attribute>
<attribute name="filter_domain">['|', ('name', 'ilike', self), ('origin', 'ilike', self)]</attribute> <attribute name="filter_domain">['|', ('name', 'ilike', self), ('origin', 'ilike', self)]</attribute>
@@ -105,20 +97,9 @@
<!-- Do not show cancelled quotations by default in "Requests for Quotation" --> <!-- Do not show cancelled quotations by default in "Requests for Quotation" -->
<record id="purchase.purchase_rfq" model="ir.actions.act_window"> <record id="purchase.purchase_rfq" model="ir.actions.act_window">
<field name="context">{'search_default_draft': 1, 'search_default_todo': 1}</field> <field name="context">{'search_default_draft': 1}</field>
</record> </record>
<record id="purchase_order_line_form2" model="ir.ui.view">
<field name="name">usability.purchase.order.line.form</field>
<field name="model">purchase.order.line</field>
<field name="inherit_id" ref="purchase.purchase_order_line_form2"/>
<field name="arch" type="xml">
<field name="order_id" position="attributes">
<attribute name="context">{'show_purchase': True}</attribute>
</field>
</field>
</record>
<record id="purchase_order_line_tree" model="ir.ui.view"> <record id="purchase_order_line_tree" model="ir.ui.view">
<field name="name">usability.purchase.order.line.tree</field> <field name="name">usability.purchase.order.line.tree</field>
<field name="model">purchase.order.line</field> <field name="model">purchase.order.line</field>
@@ -180,42 +161,5 @@
<!-- The menu entry should be added in customer-specific module --> <!-- The menu entry should be added in customer-specific module -->
<!-- in v10, the cart button is present on the product.template form view
but not on the product.product form view
In v8, it was present on both, so I put the cart button on the product.product form view too -->
<record id="action_purchase_line_product_product_tree" model="ir.actions.act_window">
<field name="name">Purchase Order Lines</field>
<field name="res_model">purchase.order.line</field>
<field name="view_id" ref="purchase_order_line_tree"/>
<field name="domain">[('product_id','in',active_ids), ('state', 'in', ['purchase', 'done'])]</field>
<field name="context">{}</field>
</record>
<record id="view_product_normal_purchase_buttons_from" model="ir.ui.view">
<field name="name">product.product.purchase.button.inherit</field>
<field name="model">product.product</field>
<field name="inherit_id" ref="product.product_normal_form_view"/>
<field name="groups_id" eval="[(4, ref('purchase.group_purchase_user'))]"/>
<field name="arch" type="xml">
<div name="button_box" position="inside">
<button class="oe_inline oe_stat_button"
name="%(action_purchase_line_product_product_tree)d"
type="action" icon="fa-shopping-cart">
<field string="Purchases" name="purchase_count" widget="statinfo"/>
</button>
</div>
</field>
</record>
<record id="view_product_supplier_inherit" model="ir.ui.view">
<field name="name">purchase_usability.product.template.form</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="purchase.view_product_supplier_inherit"/>
<field name="arch" type="xml">
<field name="purchase_method" position="attributes">
<attribute name="groups"></attribute>
</field>
</field>
</record>
</odoo> </odoo>