Initialize v18 branch
Rename *_usability modules to *_usability_akretion
This commit is contained in:
1
sale_stock_usability_akretion/__init__.py
Normal file
1
sale_stock_usability_akretion/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import models
|
||||
33
sale_stock_usability_akretion/__manifest__.py
Normal file
33
sale_stock_usability_akretion/__manifest__.py
Normal file
@@ -0,0 +1,33 @@
|
||||
# Copyright 2015-2022 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': 'Sale Stock Usability',
|
||||
'version': '16.0.1.0.0',
|
||||
'category': 'Sales Management',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Small usability improvements to the sale_stock module',
|
||||
'description': """
|
||||
Sale Stock Usability
|
||||
====================
|
||||
|
||||
The usability enhancements include:
|
||||
|
||||
* TODO update the list
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'https://github.com/akretion/odoo-usability',
|
||||
'depends': ['sale_stock'],
|
||||
'data': [
|
||||
'views/sale_order.xml',
|
||||
'views/sale_report.xml',
|
||||
'views/procurement_group.xml',
|
||||
'views/stock_move.xml',
|
||||
'views/stock_picking.xml',
|
||||
],
|
||||
'installable': False,
|
||||
}
|
||||
63
sale_stock_usability_akretion/i18n/fr.po
Normal file
63
sale_stock_usability_akretion/i18n/fr.po
Normal file
@@ -0,0 +1,63 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * sale_stock_usability
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 16.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-07-04 16:09+0000\n"
|
||||
"PO-Revision-Date: 2024-07-04 16:09+0000\n"
|
||||
"Last-Translator: Alexis de Lattre <alexis.delattre@akretion.com>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: sale_stock_usability
|
||||
#: model:ir.model.fields,help:sale_stock_usability.field_sale_order__picking_policy
|
||||
msgid ""
|
||||
"If you deliver all products at once, the delivery order will be scheduled "
|
||||
"based on the greatest product lead time. Otherwise, it will be based on the "
|
||||
"shortest."
|
||||
msgstr ""
|
||||
"Si vous livrez tous les produits en même temps, le bon de livraison sera "
|
||||
"planifié sur base du produit avec le délai le plus long. Autrement, il le sera"
|
||||
" sur le plus court."
|
||||
|
||||
#. module: sale_stock_usability
|
||||
#: model:ir.model.fields,field_description:sale_stock_usability.field_sale_order__incoterm
|
||||
msgid "Incoterm"
|
||||
msgstr "Incoterm"
|
||||
|
||||
#. module: sale_stock_usability
|
||||
#: model:ir.model.fields,field_description:sale_stock_usability.field_sale_order__incoterm_location
|
||||
msgid "Incoterm Location"
|
||||
msgstr "Lieu associé à l'incoterm"
|
||||
|
||||
#. module: sale_stock_usability
|
||||
#: model:ir.model.fields,help:sale_stock_usability.field_sale_order__incoterm
|
||||
msgid ""
|
||||
"International Commercial Terms are a series of predefined commercial terms "
|
||||
"used in international transactions."
|
||||
msgstr ""
|
||||
"Les termes commerciaux internationaux sont une série de termes commerciaux "
|
||||
"prédéfinis utilisés dans les transactions internationales."
|
||||
|
||||
#. module: sale_stock_usability
|
||||
#: model:ir.model,name:sale_stock_usability.model_sale_order
|
||||
msgid "Sales Order"
|
||||
msgstr "Bon de commande"
|
||||
|
||||
#. module: sale_stock_usability
|
||||
#: model:ir.model.fields,field_description:sale_stock_usability.field_sale_order__picking_policy
|
||||
msgid "Shipping Policy"
|
||||
msgstr "Politique d'expédition"
|
||||
|
||||
#. module: sale_stock_usability
|
||||
#: model:ir.model.fields,field_description:sale_stock_usability.field_sale_order__warehouse_id
|
||||
#: model_terms:ir.ui.view,arch_db:sale_stock_usability.view_order_product_search
|
||||
msgid "Warehouse"
|
||||
msgstr "Entrepôt"
|
||||
3
sale_stock_usability_akretion/models/__init__.py
Normal file
3
sale_stock_usability_akretion/models/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from . import sale_order
|
||||
from . import account_move
|
||||
from . import stock_picking
|
||||
33
sale_stock_usability_akretion/models/account_move.py
Normal file
33
sale_stock_usability_akretion/models/account_move.py
Normal file
@@ -0,0 +1,33 @@
|
||||
# Copyright 2024 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 AccountMove(models.Model):
|
||||
_inherit = 'account.move'
|
||||
|
||||
def _report_get_sale_pickings(self, sale_order=None):
|
||||
self.ensure_one()
|
||||
# the sale_order arg is usefull when using
|
||||
# py3o_lines_layout_groupby_order() to display the delivery orders
|
||||
# linked to a specific sale_order
|
||||
assert self.move_type in ('out_invoice', 'out_refund')
|
||||
sale_orders = sale_order or self.sale_ids
|
||||
picking_domain = [
|
||||
('id', 'in', sale_orders.picking_ids.ids),
|
||||
('state', '=', 'done'),
|
||||
('date_done', '<', self.create_date),
|
||||
('company_id', '=', self.company_id.id),
|
||||
]
|
||||
previous_inv = self.env['account.move'].search([
|
||||
('move_type', 'in', ('out_invoice', 'out_refund')),
|
||||
('create_date', '<', self.create_date),
|
||||
('id', 'in', sale_orders.invoice_ids.ids),
|
||||
('company_id', '=', self.company_id.id),
|
||||
], limit=1, order='id desc')
|
||||
if previous_inv:
|
||||
picking_domain.append(('date_done', '>', previous_inv.create_date))
|
||||
pickings = self.env['stock.picking'].search(picking_domain)
|
||||
return pickings
|
||||
37
sale_stock_usability_akretion/models/sale_order.py
Normal file
37
sale_stock_usability_akretion/models/sale_order.py
Normal file
@@ -0,0 +1,37 @@
|
||||
# Copyright 2015-2020 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 api, fields, models
|
||||
from odoo.tools import float_compare, float_round
|
||||
|
||||
|
||||
class SaleOrder(models.Model):
|
||||
_inherit = 'sale.order'
|
||||
|
||||
warehouse_id = fields.Many2one(tracking=True)
|
||||
incoterm = fields.Many2one(tracking=True)
|
||||
incoterm_location = fields.Char(tracking=True)
|
||||
picking_policy = fields.Selection(tracking=True)
|
||||
|
||||
def report_qty_to_deliver(self):
|
||||
# Can be useful for delivery report
|
||||
self.ensure_one()
|
||||
res = []
|
||||
prec = self.env['decimal.precision'].precision_get(
|
||||
'Product Unit of Measure')
|
||||
for line in self.order_line:
|
||||
if (
|
||||
line.product_id.type in ('product', 'consu') and
|
||||
float_compare(
|
||||
line.product_uom_qty, line.qty_delivered,
|
||||
precision_digits=prec) > 0):
|
||||
qty_to_deliver = float_round(
|
||||
line.product_uom_qty - line.qty_delivered, precision_digits=prec)
|
||||
res.append({
|
||||
'product': line.product_id,
|
||||
'name': line.name,
|
||||
'uom': line.product_uom,
|
||||
'qty_to_deliver': qty_to_deliver,
|
||||
})
|
||||
return res
|
||||
84
sale_stock_usability_akretion/models/stock_picking.py
Normal file
84
sale_stock_usability_akretion/models/stock_picking.py
Normal file
@@ -0,0 +1,84 @@
|
||||
# Copyright 2024 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 fields, models, _
|
||||
from odoo.exceptions import UserError
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class StockPicking(models.Model):
|
||||
_inherit = 'stock.picking'
|
||||
|
||||
def _report_delivery_prices(self):
|
||||
self.ensure_one()
|
||||
assert self.state == 'done'
|
||||
if not self.partner_id:
|
||||
raise UserError(_("Partner is not set on picking %s.") % self.display_name)
|
||||
weight_uom_categ_id = self.env.ref('uom.product_uom_categ_kgm').id
|
||||
kg_uom = self.env.ref('uom.product_uom_kgm')
|
||||
partner_pricelist = self.partner_id.property_product_pricelist
|
||||
currency = self.sale_id.currency_id or partner_pricelist.currency_id
|
||||
total_amount = 0.0
|
||||
total_weight_kg = 0.0
|
||||
lines = []
|
||||
for line in self.move_line_ids:
|
||||
move = line.move_id
|
||||
uom = line.product_uom_id
|
||||
if uom.category_id.id == weight_uom_categ_id:
|
||||
weight_kg_subtotal = uom._compute_quantity(line.qty_done, kg_uom)
|
||||
else:
|
||||
qty_product_uom = uom._compute_quantity(line.qty_done, line.product_id.uom_id)
|
||||
weight_kg_subtotal = qty_product_uom * line.product_id.weight
|
||||
if (
|
||||
move.sale_line_id and
|
||||
move.sale_line_id.product_id == line.product_id and
|
||||
move.sale_line_id.product_uom_qty > 0 and
|
||||
move.sale_line_id.product_uom == uom):
|
||||
price_unit = currency.round(
|
||||
line.move_id.sale_line_id.price_subtotal / move.sale_line_id.product_uom_qty)
|
||||
logger.info(
|
||||
'For move line %s, got price %s from sale order line',
|
||||
line.display_name, price_unit)
|
||||
else:
|
||||
# TODO remove tax if tax included
|
||||
price_unit = partner_pricelist._get_product_price(
|
||||
line.product_id, line.qty_done, uom=uom,
|
||||
date=fields.Date.to_date(self.date_done))
|
||||
price_unit = currency.round(price_unit)
|
||||
# Only for very special case where picking is linked to sale order but this line
|
||||
# is from linked to sale order line, and the partner pricelist is NOT in the same
|
||||
# currency as the sale order pricelist. Should very rarely happen.
|
||||
if currency != partner_pricelist.currency_id:
|
||||
raise UserError(_(
|
||||
"The pricelist of the related sale order is in currency "
|
||||
"%(sale_pricelist_currency)s whereas the pricelist "
|
||||
"%(partner_pricelist_name)s of partner %(partner)s "
|
||||
"is in currency %(partner_pricelist_currency)s.",
|
||||
sale_pricelist_currency=self.sale_id.currency_id.name,
|
||||
partner_pricelist_name=partner_pricelist.name,
|
||||
partner=self.partner_id.display_name,
|
||||
partner_pricelist_currency=partner_pricelist.currency_id.name))
|
||||
logger.info(
|
||||
'For move line %s, got price %s from partner pricelist %s',
|
||||
line.display_name, price_unit, partner_pricelist.display_name)
|
||||
price_subtotal = currency.round(price_unit * line.qty_done)
|
||||
total_amount += price_subtotal
|
||||
lines.append({
|
||||
'line': line,
|
||||
'qty': line.qty_done,
|
||||
'uom': uom,
|
||||
'product': line.product_id,
|
||||
'weight_kg_subtotal': weight_kg_subtotal,
|
||||
'price_unit': price_unit,
|
||||
'price_subtotal': price_subtotal,
|
||||
'lot': line.lot_id and line.lot_id.display_name or (line.lot_name or ''),
|
||||
})
|
||||
res = {
|
||||
'lines': lines,
|
||||
'currency': currency,
|
||||
'total_amount': currency.round(total_amount),
|
||||
'total_weight_kg': total_weight_kg,
|
||||
}
|
||||
return res
|
||||
BIN
sale_stock_usability_akretion/static/description/icon.png
Normal file
BIN
sale_stock_usability_akretion/static/description/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.5 KiB |
21
sale_stock_usability_akretion/views/procurement_group.xml
Normal file
21
sale_stock_usability_akretion/views/procurement_group.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2015-2022 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="procurement_group_form_view" model="ir.ui.view">
|
||||
<field name="name">sale_stock_usability.procurement.group.form</field>
|
||||
<field name="model">procurement.group</field>
|
||||
<field name="inherit_id" ref="stock.procurement_group_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="move_type" position="after">
|
||||
<field name="sale_id"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
23
sale_stock_usability_akretion/views/sale_order.xml
Normal file
23
sale_stock_usability_akretion/views/sale_order.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2015-2022 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_stock_usability.order.form</field>
|
||||
<field name="model">sale.order</field>
|
||||
<field name="inherit_id" ref="sale_stock.view_order_form_inherit_sale_stock"/>
|
||||
<field name="arch" type="xml">
|
||||
<!-- move warehouse_id to the top, not hidden in the 2nd tab -->
|
||||
<xpath expr="//group[@name='sale_shipping']/field[@name='warehouse_id' and @force_save='1']" position="replace"/>
|
||||
<group name="order_details" position="inside">
|
||||
<field name="warehouse_id" options="{'no_create': True}" groups="stock.group_stock_multi_warehouses" force_save="1"/>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
20
sale_stock_usability_akretion/views/sale_report.xml
Normal file
20
sale_stock_usability_akretion/views/sale_report.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 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_product_search" model="ir.ui.view">
|
||||
<field name="model">sale.report</field>
|
||||
<field name="inherit_id" ref="sale.view_order_product_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<filter name="status" position="after">
|
||||
<filter string="Warehouse" name="warehouse_id_groupby" context="{'group_by':'warehouse_id'}"/>
|
||||
</filter>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
21
sale_stock_usability_akretion/views/stock_move.xml
Normal file
21
sale_stock_usability_akretion/views/stock_move.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2015-2022 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_move_form" model="ir.ui.view">
|
||||
<field name="name">sale_stock_usability.stock_move.form</field>
|
||||
<field name="model">stock.move</field>
|
||||
<field name="inherit_id" ref="stock.view_move_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="origin" position="after">
|
||||
<field name="sale_line_id" readonly="1"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
21
sale_stock_usability_akretion/views/stock_picking.xml
Normal file
21
sale_stock_usability_akretion/views/stock_picking.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2015-2022 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_picking_form" model="ir.ui.view">
|
||||
<field name="name">sale_stock_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="before">
|
||||
<field name="sale_id" readonly="1" attrs="{'invisible': [('sale_id', '=', False)]}"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user