Compare commits
19 Commits
14.0-produ
...
14.0-imp-m
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
279dc7c6c0 | ||
|
|
f6ddbb48ac | ||
|
|
d3bddf5fda | ||
|
|
6f3a468a7c | ||
|
|
0bfa960153 | ||
|
|
a520ccff51 | ||
|
|
fa7611eb08 | ||
|
|
b2eda2a23b | ||
|
|
74ff1b5cb5 | ||
|
|
a7b4ed65eb | ||
|
|
7dfb32c2d6 | ||
|
|
d081bb0fd2 | ||
|
|
f3fdbec140 | ||
|
|
ac54c5cc75 | ||
|
|
78c11411c3 | ||
|
|
28ce11b216 | ||
|
|
00e034dacf | ||
|
|
8510b9518a | ||
|
|
15ef5df155 |
@@ -18,6 +18,9 @@
|
||||
<field name="invoice_incoterm_id" position="attributes">
|
||||
<attribute name="widget">selection</attribute>
|
||||
</field>
|
||||
<button name="action_register_payment" position="attributes">
|
||||
<attribute name="class">btn-default</attribute>
|
||||
</button>
|
||||
<button name="action_register_payment" position="before">
|
||||
<button name="%(account.account_invoices)d" type="action" string="Print" attrs="{'invisible': [('move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
|
||||
</button>
|
||||
@@ -26,6 +29,9 @@
|
||||
</button>
|
||||
<!-- move sent field and make it visible -->
|
||||
<field name="is_move_sent" position="replace"/>
|
||||
<field name="invoice_origin" position="attributes">
|
||||
<attribute name="invisible">0</attribute>
|
||||
</field>
|
||||
<field name="invoice_origin" position="after">
|
||||
<field name="is_move_sent" attrs="{'invisible': [('move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
|
||||
</field>
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
<field name="property_account_position_id" position="attributes">
|
||||
<attribute name="widget">selection</attribute>
|
||||
</field>
|
||||
<xpath expr="//field[@name='bank_ids']/tree/field[@name='acc_number']" position="after">
|
||||
<field name="acc_type"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
1
delivery_usability/models/__init__.py
Normal file
1
delivery_usability/models/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import stock_picking
|
||||
1
hr_contract_usability/__init__.py
Normal file
1
hr_contract_usability/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import models
|
||||
20
hr_contract_usability/__manifest__.py
Normal file
20
hr_contract_usability/__manifest__.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# Copyright 2021 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': 'HR Contract Usability',
|
||||
'version': '14.0.1.0.0',
|
||||
'category': 'Human Resources/Contracts',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Usability improvements on HR Contract module',
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': [
|
||||
'hr_contract',
|
||||
],
|
||||
'data': [
|
||||
'views/hr_payroll_structure_type.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
1
hr_contract_usability/models/__init__.py
Normal file
1
hr_contract_usability/models/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import hr_payroll_structure_type
|
||||
10
hr_contract_usability/models/hr_payroll_structure_type.py
Normal file
10
hr_contract_usability/models/hr_payroll_structure_type.py
Normal file
@@ -0,0 +1,10 @@
|
||||
# Copyright 2021 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).
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
class HrPayrollStructureType(models.Model):
|
||||
_inherit = 'hr.payroll.structure.type'
|
||||
|
||||
active = fields.Boolean(default=True)
|
||||
63
hr_contract_usability/views/hr_payroll_structure_type.xml
Normal file
63
hr_contract_usability/views/hr_payroll_structure_type.xml
Normal file
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2021 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).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="hr_payroll_structure_type_form" model="ir.ui.view">
|
||||
<field name="model">hr.payroll.structure.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
|
||||
<group name="main">
|
||||
<field name="name"/>
|
||||
<field name="default_resource_calendar_id"/>
|
||||
<field name="active" invisible="1"/>
|
||||
<field name="country_id"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_payroll_structure_type_tree" model="ir.ui.view">
|
||||
<field name="model">hr.payroll.structure.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree>
|
||||
<field name="name"/>
|
||||
<field name="default_resource_calendar_id" optional="show"/>
|
||||
<field name="country_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_payroll_structure_type_search" model="ir.ui.view">
|
||||
<field name="model">hr.payroll.structure.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<search>
|
||||
<field name="name"/>
|
||||
<separator/>
|
||||
<filter string="Archived" name="inactive" domain="[('active', '=', False)]"/>
|
||||
<group name="groupby">
|
||||
<filter name="country_groupby" string="Country" context="{'group_by': 'country_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_payroll_structure_type_action" model="ir.actions.act_window">
|
||||
<field name="name">Salary Structure Types</field>
|
||||
<field name="res_model">hr.payroll.structure.type</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
id="hr_payroll_structure_type_menu"
|
||||
action="hr_payroll_structure_type_action"
|
||||
parent="hr_contract.menu_human_resources_configuration_contract"
|
||||
sequence="10"/>
|
||||
|
||||
|
||||
</odoo>
|
||||
2
sale_confirm_wizard/__init__.py
Normal file
2
sale_confirm_wizard/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from . import models
|
||||
from . import wizard
|
||||
38
sale_confirm_wizard/__manifest__.py
Normal file
38
sale_confirm_wizard/__manifest__.py
Normal file
@@ -0,0 +1,38 @@
|
||||
# Copyright 2017-2021 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).
|
||||
|
||||
{
|
||||
'name': 'Sale Confirm Wizard',
|
||||
'version': '14.0.1.0.0',
|
||||
'category': 'Sales',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Open a wizard when you confirm a sale order to update important info',
|
||||
'description': """
|
||||
Sale Confirm Wizard
|
||||
===================
|
||||
|
||||
When you confirm a quotation, Odoo will open a small wizard where you will be able to check and update important information:
|
||||
|
||||
* customer PO number,
|
||||
* delivery address,
|
||||
* invoicing address,
|
||||
* payment terms.
|
||||
|
||||
It will also display the sale warning if the customer's company has one. And it is a blocker warning, the user won't be able to confirm the quotation.
|
||||
|
||||
This module has been developped because the experience has shown, when a sales assistant confirms a quotation in Odoo, it overlooks the important information written in the customer PO that may be different from the information of the quotation in Odoo, which causes many errors in delivery and invoicing.
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion
|
||||
<alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['sale'],
|
||||
'data': [
|
||||
'wizard/sale_confirm_view.xml',
|
||||
'views/sale_order.xml',
|
||||
'security/ir.model.access.csv',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
1
sale_confirm_wizard/models/__init__.py
Normal file
1
sale_confirm_wizard/models/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import sale_order
|
||||
17
sale_confirm_wizard/models/sale_order.py
Normal file
17
sale_confirm_wizard/models/sale_order.py
Normal file
@@ -0,0 +1,17 @@
|
||||
# Copyright 2020-2021 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
|
||||
|
||||
|
||||
class SaleOrder(models.Model):
|
||||
_inherit = 'sale.order'
|
||||
|
||||
def sale_confirm_wizard_button(self):
|
||||
"""This method is designed to be inherited.
|
||||
For example, inherit it if you don't want to start the wizard in
|
||||
some scenarios"""
|
||||
action = self.sudo().env.ref(
|
||||
'sale_confirm_wizard.sale_confirm_action').read()[0]
|
||||
return action
|
||||
2
sale_confirm_wizard/security/ir.model.access.csv
Normal file
2
sale_confirm_wizard/security/ir.model.access.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_sale_confirm_wizard,Full access on sale.confirm wizard,model_sale_confirm,sales_team.group_sale_salesman,1,1,1,1
|
||||
|
24
sale_confirm_wizard/views/sale_order.xml
Normal file
24
sale_confirm_wizard/views/sale_order.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2017-2021 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).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="view_order_form" model="ir.ui.view">
|
||||
<field name="name">sale.confirm.wizard.sale_order_form</field>
|
||||
<field name="model">sale.order</field>
|
||||
<field name="inherit_id" ref="sale.view_order_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<button id="action_confirm" position="attributes">
|
||||
<attribute name="name">sale_confirm_wizard_button</attribute>
|
||||
</button>
|
||||
<button name="action_confirm" attrs="{'invisible': [('state', 'not in', ['draft'])]}" position="attributes">
|
||||
<attribute name="name">sale_confirm_wizard_button</attribute>
|
||||
</button>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
1
sale_confirm_wizard/wizard/__init__.py
Normal file
1
sale_confirm_wizard/wizard/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import sale_confirm
|
||||
78
sale_confirm_wizard/wizard/sale_confirm.py
Normal file
78
sale_confirm_wizard/wizard/sale_confirm.py
Normal file
@@ -0,0 +1,78 @@
|
||||
# Copyright 2017-2021 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, _
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.addons.base.models.res_partner import WARNING_MESSAGE
|
||||
|
||||
|
||||
class SaleConfirm(models.TransientModel):
|
||||
_name = 'sale.confirm'
|
||||
_description = 'Wizard to confirm a sale order'
|
||||
|
||||
sale_id = fields.Many2one(
|
||||
'sale.order', string='Sale Order', readonly=True)
|
||||
client_order_ref = fields.Char(string='Customer PO Number')
|
||||
payment_term_id = fields.Many2one(
|
||||
'account.payment.term', string='Payment Terms')
|
||||
partner_invoice_id = fields.Many2one(
|
||||
'res.partner', 'Invoice Address', required=True)
|
||||
show_partner_invoice_id = fields.Many2one(
|
||||
related='partner_invoice_id',
|
||||
string='Detailed Invoice Address')
|
||||
partner_shipping_id = fields.Many2one(
|
||||
'res.partner', 'Delivery Address', required=True)
|
||||
show_partner_shipping_id = fields.Many2one(
|
||||
related='partner_shipping_id',
|
||||
string='Detailed Delivery Address')
|
||||
sale_warn = fields.Selection(
|
||||
WARNING_MESSAGE, 'Sale Warning Type', readonly=True)
|
||||
sale_warn_msg = fields.Text(string='Sale Warning Message', readonly=True)
|
||||
|
||||
@api.model
|
||||
def _prepare_default_get(self, order):
|
||||
partner = order.partner_id.commercial_partner_id
|
||||
default = {
|
||||
'sale_id': order.id,
|
||||
'client_order_ref': order.client_order_ref,
|
||||
'payment_term_id': order.payment_term_id.id or False,
|
||||
'partner_invoice_id': order.partner_invoice_id.id,
|
||||
'partner_shipping_id': order.partner_shipping_id.id,
|
||||
'sale_warn_msg': partner.sale_warn_msg,
|
||||
'sale_warn': partner.sale_warn,
|
||||
}
|
||||
return default
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields):
|
||||
res = super().default_get(fields)
|
||||
assert self._context.get('active_model') == 'sale.order',\
|
||||
'active_model should be sale.order'
|
||||
order = self.env['sale.order'].browse(self._context.get('active_id'))
|
||||
default = self._prepare_default_get(order)
|
||||
res.update(default)
|
||||
return res
|
||||
|
||||
def _prepare_update_so(self):
|
||||
self.ensure_one()
|
||||
return {
|
||||
'client_order_ref': self.client_order_ref,
|
||||
'payment_term_id': self.payment_term_id.id or False,
|
||||
'partner_invoice_id': self.partner_invoice_id.id,
|
||||
'partner_shipping_id': self.partner_shipping_id.id,
|
||||
}
|
||||
|
||||
def confirm(self):
|
||||
self.ensure_one()
|
||||
partner = self.sale_id.partner_id.commercial_partner_id
|
||||
if partner.sale_warn == 'block':
|
||||
raise UserError(_(
|
||||
"You cannot confirm this quotation because "
|
||||
"customer '%s' has a blocker sale warning:\n\n%s")
|
||||
% (partner.display_name, partner.sale_warn_msg))
|
||||
vals = self._prepare_update_so()
|
||||
self.sale_id.write(vals)
|
||||
# confirm sale order
|
||||
self.sale_id.action_confirm()
|
||||
return True
|
||||
54
sale_confirm_wizard/wizard/sale_confirm_view.xml
Normal file
54
sale_confirm_wizard/wizard/sale_confirm_view.xml
Normal file
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2017-2021 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).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="sale_confirm_form" model="ir.ui.view">
|
||||
<field name="name">sale.confirm.form</field>
|
||||
<field name="model">sale.confirm</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Confirm Order">
|
||||
<div><p>At this stage, you have received the Purchase Order from the customer and you are about to convert the related quotation to an order.</p></div>
|
||||
<group name="warn" groups="sale.group_warning_sale" attrs="{'invisible': ['|', ('sale_warn', '=', False), ('sale_warn', '=', 'no-message')]}" string="Warning" col="4">
|
||||
<field name="sale_warn" nolabel="1"/>
|
||||
<field name="sale_warn_msg" nolabel="1" colspan="3"/>
|
||||
</group>
|
||||
<group name="main" attrs="{'invisible': [('sale_warn', '=', 'block')]}">
|
||||
<field name="sale_id" invisible="1"/>
|
||||
<field name="client_order_ref"/>
|
||||
<field name="partner_invoice_id" context="{'default_type': 'invoice'}"
|
||||
groups="sale.group_delivery_invoice_address"/>
|
||||
<!-- partner_invoice_id can't show the full address because
|
||||
we are in edit mode -->
|
||||
<field name="show_partner_invoice_id" options="{'always_reload': True}"
|
||||
context="{'show_address': 1}"
|
||||
groups="sale.group_delivery_invoice_address"/>
|
||||
<field name="partner_shipping_id"
|
||||
context="{'default_type': 'delivery'}"
|
||||
groups="sale.group_delivery_invoice_address"/>
|
||||
<field name="show_partner_shipping_id" options="{'always_reload': True}"
|
||||
context="{'show_address': 1}"
|
||||
groups="sale.group_delivery_invoice_address"/>
|
||||
<field name="payment_term_id"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button type="object" name="confirm"
|
||||
string="Confirm Sale" class="btn-primary" attrs="{'invisible': [('sale_warn', '=', 'block')]}"/>
|
||||
<button special="cancel" string="Annuler" class="btn-default"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_confirm_action" model="ir.actions.act_window">
|
||||
<field name="name">Confirm Order</field>
|
||||
<field name="res_model">sale.confirm</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
1
stock_picking_type_default_partner/__init__.py
Normal file
1
stock_picking_type_default_partner/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import models
|
||||
25
stock_picking_type_default_partner/__manifest__.py
Normal file
25
stock_picking_type_default_partner/__manifest__.py
Normal file
@@ -0,0 +1,25 @@
|
||||
# Copyright 2014-2021 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).
|
||||
|
||||
|
||||
{
|
||||
'name': 'Stock Picking Type Default Partner',
|
||||
'version': '14.0.1.0.0',
|
||||
'category': 'Inventory, Logistics, Warehousing',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Adds a default partner on types of operation',
|
||||
'description': """
|
||||
Stock Picking Type Default Partner
|
||||
==================================
|
||||
|
||||
This module adds a new field on the Types of Operation (stock.picking.type) : *Default Partner*. This is useful for multi-site companies that create inter-site Type of Operations: all the operations that use this Type of Operation should have the same destination partner.
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['stock'],
|
||||
'data': ['views/stock_picking_type.xml'],
|
||||
'installable': True,
|
||||
}
|
||||
1
stock_picking_type_default_partner/models/__init__.py
Normal file
1
stock_picking_type_default_partner/models/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import stock_picking
|
||||
31
stock_picking_type_default_partner/models/stock_picking.py
Normal file
31
stock_picking_type_default_partner/models/stock_picking.py
Normal file
@@ -0,0 +1,31 @@
|
||||
# Copyright 2014-2021 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 StockPickingType(models.Model):
|
||||
_inherit = 'stock.picking.type'
|
||||
|
||||
default_partner_id = fields.Many2one(
|
||||
'res.partner', string='Default Partner', ondelete='restrict',
|
||||
help="If set, it will be the default partner on this type of "
|
||||
"pickings.")
|
||||
|
||||
|
||||
class StockPicking(models.Model):
|
||||
_inherit = 'stock.picking'
|
||||
|
||||
@api.model
|
||||
def _default_partner_id(self):
|
||||
if self._context.get('default_picking_type_id'):
|
||||
picktype = self.env['stock.picking.type'].browse(
|
||||
self._context.get('default_picking_type_id'))
|
||||
if picktype.default_partner_id:
|
||||
return picktype.default_partner_id
|
||||
return False
|
||||
|
||||
partner_id = fields.Many2one(
|
||||
default=lambda self: self._default_partner_id())
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2015-2021 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_type_form" model="ir.ui.view">
|
||||
<field name="name">default.partner.stock.picking.type.form</field>
|
||||
<field name="model">stock.picking.type</field>
|
||||
<field name="inherit_id" ref="stock.view_picking_type_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="default_location_dest_id" position="after">
|
||||
<field name="default_partner_id"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
||||
@@ -2,10 +2,44 @@
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.tools import float_compare, float_is_zero
|
||||
|
||||
|
||||
class StockInventory(models.Model):
|
||||
_inherit = 'stock.inventory'
|
||||
|
||||
prefill_counted_quantity = fields.Selection(
|
||||
readonly=True, states={'draft': [('readonly', False)]})
|
||||
|
||||
|
||||
class StockInventoryLine(models.Model):
|
||||
_inherit = 'stock.inventory.line'
|
||||
|
||||
product_barcode = fields.Char(related='product_id.barcode', string="Product Barcode")
|
||||
difference_qty = fields.Float(search="_search_difference_qty_usability")
|
||||
|
||||
def _search_difference_qty_usability(self, operator, value):
|
||||
# Inspired by the method _search_difference_qty() from the
|
||||
# official stock module
|
||||
# So a part of this code is copyright Odoo SA under LGPL licence
|
||||
if not self.env.context.get('default_inventory_id'):
|
||||
raise NotImplementedError(_('Unsupported search on %s outside of an Inventory Adjustment', 'difference_qty'))
|
||||
lines = self.search([('inventory_id', '=', self.env.context.get('default_inventory_id'))])
|
||||
line_ids = []
|
||||
for line in lines:
|
||||
if operator == '=':
|
||||
if float_is_zero(line.difference_qty, line.product_id.uom_id.rounding):
|
||||
line_ids.append(line.id)
|
||||
elif operator == '!=':
|
||||
if not float_is_zero(line.difference_qty, line.product_id.uom_id.rounding):
|
||||
line_ids.append(line.id)
|
||||
elif operator == '>':
|
||||
if float_compare(line.difference_qty, 0, line.product_id.uom_id.rounding) > 0:
|
||||
line_ids.append(line.id)
|
||||
elif operator == '<':
|
||||
if float_compare(line.difference_qty, 0, line.product_id.uom_id.rounding) < 0:
|
||||
line_ids.append(line.id)
|
||||
else:
|
||||
raise NotImplementedError()
|
||||
return [('id', 'in', line_ids)]
|
||||
|
||||
@@ -7,6 +7,20 @@
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="view_inventory_form" model="ir.ui.view">
|
||||
<field name="name">usability.stock.inventory.form</field>
|
||||
<field name="model">stock.inventory</field>
|
||||
<field name="inherit_id" ref="stock.view_inventory_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<button name="action_open_inventory_lines" states="confirm" position="after">
|
||||
<button name="action_open_inventory_lines" states="done" string="Show Inventory Lines" type="object"/>
|
||||
</button>
|
||||
<field name="prefill_counted_quantity" position="attributes">
|
||||
<attribute name="attrs">{}</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="stock_inventory_line_tree" model="ir.ui.view">
|
||||
<field name="name">usability.stock.inventory.line.tree</field>
|
||||
<field name="model">stock.inventory.line</field>
|
||||
@@ -30,4 +44,25 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="stock_inventory_line_search" model="ir.ui.view">
|
||||
<field name="name">usability.stock.inventory.line.search</field>
|
||||
<field name="model">stock.inventory.line</field>
|
||||
<field name="inherit_id" ref="stock.stock_inventory_line_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="product_id" position="after">
|
||||
<field name="categ_id"/>
|
||||
</field>
|
||||
<filter name="difference" position="after">
|
||||
<filter string="Difference = 0"
|
||||
name="counted_equal" domain="[('difference_qty', '=', 0)]"/>
|
||||
<filter string="Counted lower than Theoretical"
|
||||
name="counted_lower" domain="[('difference_qty', '<', 0)]"/>
|
||||
<filter string="Counted higher than Theoretical"
|
||||
name="counted_higher" domain="[('difference_qty', '>', 0)]"/>
|
||||
<separator/>
|
||||
<filter string="Counted" name="counted" domain="[('product_qty', '>', 0)]"/>
|
||||
</filter>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
<xpath expr="//field[@name='move_ids_without_package']/tree/field[@name='product_id']" position="after">
|
||||
<field name="product_barcode" optional="hide"/>
|
||||
<field name="name" optional="hide"/>
|
||||
<field name="location_id" groups="stock.group_stock_multi_locations" optional="show"/>
|
||||
<field name="location_dest_id" groups="stock.group_stock_multi_locations" optional="show"/>
|
||||
<field name="location_id" groups="stock.group_stock_multi_locations" optional="show" domain="[('id', 'child_of', 'parent.location_id')]" options="{'no_create': True}"/>
|
||||
<field name="location_dest_id" groups="stock.group_stock_multi_locations" optional="show" domain="[('id', 'child_of', 'parent.location_dest_id')]" options="{'no_create': True}"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='move_ids_without_package']/tree/button[@name='action_assign_serial']" position="after">
|
||||
<button type="object" name="button_do_unreserve" string="Unreserve"
|
||||
@@ -56,7 +56,7 @@
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="view_picking_internal_search" model="ir.ui.view">
|
||||
<field name="name">stock_usability.view_picking_search</field>
|
||||
<field name="model">stock.picking</field>
|
||||
|
||||
Reference in New Issue
Block a user