Initialize v18 branch
Rename *_usability modules to *_usability_akretion
This commit is contained in:
2
stock_usability_akretion/__init__.py
Normal file
2
stock_usability_akretion/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from . import models
|
||||
from .post_install import create_config_parameter_immediate_tranfer
|
||||
45
stock_usability_akretion/__manifest__.py
Normal file
45
stock_usability_akretion/__manifest__.py
Normal file
@@ -0,0 +1,45 @@
|
||||
# Copyright 2014-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': 'Stock Usability',
|
||||
'version': '16.0.1.0.0',
|
||||
'category': 'Inventory, Logistic, Storage',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Several usability enhancements in Warehouse management',
|
||||
'description': """
|
||||
Stock Usability
|
||||
===============
|
||||
|
||||
The usability enhancements include:
|
||||
* display the source location on the tree view of the move lines of the pickings (by default, only the destination location is displayed).
|
||||
* always display the field *Backorder* on the form view of picking (by default, this field is only displayed when it has a value, so the user doesn't know when the field has no value because he doesn't see the field !)
|
||||
* add a group by Partner in the picking search view (particularly usefull for receptions)
|
||||
* add graph view for pickings
|
||||
* remove ability to translate stock.location, stock.location.route and stock.picking.type
|
||||
|
||||
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_quant.xml',
|
||||
'views/stock_location.xml',
|
||||
'views/stock_move.xml',
|
||||
'views/stock_move_line.xml',
|
||||
'views/stock_picking.xml',
|
||||
'views/stock_picking_type.xml',
|
||||
'views/stock_warehouse.xml',
|
||||
'views/stock_warehouse_orderpoint.xml',
|
||||
'views/product.xml',
|
||||
'views/procurement_group.xml',
|
||||
'views/stock_lot.xml',
|
||||
'views/procurement_scheduler_log.xml',
|
||||
'security/ir.model.access.csv',
|
||||
],
|
||||
'post_init_hook': 'create_config_parameter_immediate_tranfer',
|
||||
'installable': False,
|
||||
}
|
||||
393
stock_usability_akretion/i18n/fr.po
Normal file
393
stock_usability_akretion/i18n/fr.po
Normal file
@@ -0,0 +1,393 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * stock_usability
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 16.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-07-04 16:23+0000\n"
|
||||
"PO-Revision-Date: 2024-07-04 16:24+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: stock_usability
|
||||
#: model:ir.model.fields,help:stock_usability.field_product_product__detailed_type
|
||||
#: model:ir.model.fields,help:stock_usability.field_product_template__detailed_type
|
||||
msgid ""
|
||||
"A storable product is a product for which you manage stock. The Inventory "
|
||||
"app has to be installed.\n"
|
||||
"A consumable product is a product for which stock is not managed.\n"
|
||||
"A service is a non-material product you provide."
|
||||
msgstr ""
|
||||
"Un produit stockable est un produit dont on gère le stock. L'application "
|
||||
"\"Inventaire\" doit être installée. \n"
|
||||
"Un produit consommable est un produit pour lequel le stock n'est pas géré.\n"
|
||||
"Un service est un produit immatériel que vous fournissez."
|
||||
|
||||
#. module: stock_usability
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.view_move_form
|
||||
msgid "Advanced"
|
||||
msgstr "Avancé"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.view_picking_form
|
||||
msgid "Are you sure you want to cancel this picking?"
|
||||
msgstr "Êtes-vous sûr de vouloir annuler ce bon de préparation ?"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.stock_quant_tree_simple
|
||||
msgid "Available"
|
||||
msgstr "Disponible"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_procurement_scheduler_log__company_id
|
||||
msgid "Company"
|
||||
msgstr "Société"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model,name:stock_usability.model_res_partner
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_stock_picking__partner_id
|
||||
msgid "Contact"
|
||||
msgstr "Contact"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_procurement_scheduler_log__create_uid
|
||||
msgid "Created by"
|
||||
msgstr "Créé par"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_procurement_scheduler_log__create_date
|
||||
msgid "Created on"
|
||||
msgstr "Créé le"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_product_product__sale_delay
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_product_template__sale_delay
|
||||
msgid "Customer Lead Time"
|
||||
msgstr "Délai de livraison au client"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.view_picking_internal_search
|
||||
msgid "Date Done"
|
||||
msgstr "Date du transfert"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,help:stock_usability.field_product_product__sale_delay
|
||||
#: model:ir.model.fields,help:stock_usability.field_product_template__sale_delay
|
||||
msgid ""
|
||||
"Delivery lead time, in days. It's the number of days, promised to the "
|
||||
"customer, between the confirmation of the sales order and the delivery."
|
||||
msgstr ""
|
||||
"Délai de livraison, en jours. C'est le nombre de jours, promis au client, "
|
||||
"entre la confirmation de la commande client et la livraison."
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_procurement_scheduler_log__display_name
|
||||
msgid "Display Name"
|
||||
msgstr "Nom affiché"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,help:stock_usability.field_product_product__tracking
|
||||
#: model:ir.model.fields,help:stock_usability.field_product_template__tracking
|
||||
msgid "Ensure the traceability of a storable product in your warehouse."
|
||||
msgstr "Assurer la traçabilité d'un produit stockable dans votre entrepôt."
|
||||
|
||||
#. module: stock_usability
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.view_location_search
|
||||
msgid "Group By"
|
||||
msgstr "Grouper par"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_procurement_scheduler_log__id
|
||||
msgid "ID"
|
||||
msgstr "ID"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,help:stock_usability.field_stock_move__product_barcode
|
||||
#: model:ir.model.fields,help:stock_usability.field_stock_move_line__product_barcode
|
||||
#: model:ir.model.fields,help:stock_usability.field_stock_quant__product_barcode
|
||||
msgid "International Article Number used for product identification."
|
||||
msgstr ""
|
||||
"Numéro d'article international utilisé pour l'identification du produit."
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_stock_picking_type__is_dropship
|
||||
msgid "Is Dropship"
|
||||
msgstr "Est un dropship"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_stock_picking__is_locked
|
||||
msgid "Is Locked"
|
||||
msgstr "Est verrouillé"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,help:stock_usability.field_stock_picking__move_type
|
||||
msgid "It specifies goods to be deliver partially or all at once"
|
||||
msgstr ""
|
||||
"Indique si les marchandises doivent être livrées partiellement ou en une "
|
||||
"seule fois."
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_procurement_scheduler_log____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr "Dernière modification le"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_procurement_scheduler_log__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr "Dernière mise à jour par"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_procurement_scheduler_log__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr "Dernière mise à jour le"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.view_location_search
|
||||
msgid "Location Type"
|
||||
msgstr "Type d'emplacement"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.ui.menu,name:stock_usability.stock_location_menu
|
||||
msgid "Locations"
|
||||
msgstr "Emplacements"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model,name:stock_usability.model_procurement_scheduler_log
|
||||
msgid "Logs of the Procurement Scheduler"
|
||||
msgstr "Journaux du planificateur des approvisionnements"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model,name:stock_usability.model_stock_warehouse_orderpoint
|
||||
msgid "Minimum Inventory Rule"
|
||||
msgstr "Règle d'inventaire minimum"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_stock_picking__picking_type_id
|
||||
msgid "Operation Type"
|
||||
msgstr "Type d'opération"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.view_picking_internal_search
|
||||
msgid "Partner"
|
||||
msgstr "Partenaire"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.view_move_form
|
||||
msgid "Picking"
|
||||
msgstr "Transfert"
|
||||
|
||||
#. module: stock_usability
|
||||
#. odoo-python
|
||||
#: code:addons/stock_usability/models/stock_picking.py:0
|
||||
#, python-format
|
||||
msgid "Picking <b>unreserved</b>."
|
||||
msgstr "Bon de préparation <b>déréservé</b>."
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model,name:stock_usability.model_stock_picking_type
|
||||
msgid "Picking Type"
|
||||
msgstr "Type de transfert"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_procurement_group__picking_ids
|
||||
msgid "Pickings"
|
||||
msgstr "Transferts"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model,name:stock_usability.model_procurement_group
|
||||
msgid "Procurement Group"
|
||||
msgstr "Groupe d'approvisionnement"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.procurement_scheduler_log_tree
|
||||
msgid "Procurement Scheduler Logs"
|
||||
msgstr "Journal du planificateur des approvisionnements"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model,name:stock_usability.model_product_template
|
||||
msgid "Product"
|
||||
msgstr "Produit"
|
||||
|
||||
#. module: stock_usability
|
||||
#. odoo-python
|
||||
#: code:addons/stock_usability/models/stock_move.py:0
|
||||
#: code:addons/stock_usability/models/stock_move_line.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Product <a href=# data-oe-model=product.product data-oe-id=%d>%s</a> qty %s "
|
||||
"%s <b>unreserved</b>"
|
||||
msgstr ""
|
||||
"Produit <a href=# data-oe-model=product.product data-oe-id=%d>%s</a> "
|
||||
"qté %s %s <b>déréservée</b>"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_stock_move__product_barcode
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_stock_move_line__product_barcode
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_stock_quant__product_barcode
|
||||
msgid "Product Barcode"
|
||||
msgstr "Code-barres du produit"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.actions.act_window,name:stock_usability.stock_move_line_from_lot_action
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.view_move_form
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.view_production_lot_form
|
||||
msgid "Product Moves"
|
||||
msgstr "Mouvements de produits"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model,name:stock_usability.model_stock_move_line
|
||||
msgid "Product Moves (Stock Move Line)"
|
||||
msgstr "Mouvements de produit (Ligne de mouvement de stock)"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_product_product__detailed_type
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_product_template__detailed_type
|
||||
msgid "Product Type"
|
||||
msgstr "Type de produit"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model,name:stock_usability.model_product_product
|
||||
msgid "Product Variant"
|
||||
msgstr "Variante de produit"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.actions.act_window,name:stock_usability.location_open_quants_regular_tree
|
||||
#: model:ir.model,name:stock_usability.model_stock_quant
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.view_location_form
|
||||
msgid "Quants"
|
||||
msgstr "Quants"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.view_location_search
|
||||
msgid "Removal Strategy"
|
||||
msgstr "Stratégie d'enlèvement"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.actions.act_window,name:stock_usability.location_open_orderpoint
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.view_location_form
|
||||
msgid "Reordering Rules"
|
||||
msgstr "Règles de réapprovisionnement"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.stock_quant_tree_simple
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.view_stock_quant_tree_inventory_editable
|
||||
msgid "Reservations"
|
||||
msgstr "Réservations"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.stock_quant_tree_simple
|
||||
msgid "Reserved"
|
||||
msgstr "Réservé"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.view_warehouse
|
||||
msgid "Routes"
|
||||
msgstr "Routes"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.procurement_scheduler_log_tree
|
||||
msgid "Scheduler End Time"
|
||||
msgstr "Heure de fin du planificateur"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.procurement_scheduler_log_tree
|
||||
msgid "Scheduler Executed by"
|
||||
msgstr "Planificateur exécuté par"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.actions.act_window,name:stock_usability.procurement_scheduler_log_action
|
||||
#: model:ir.ui.menu,name:stock_usability.procurement_scheduler_log_menu
|
||||
msgid "Scheduler Logs"
|
||||
msgstr "Journal du planificateur"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,help:stock_usability.field_res_partner__picking_warn
|
||||
#: model:ir.model.fields,help:stock_usability.field_res_users__picking_warn
|
||||
msgid ""
|
||||
"Selecting the \"Warning\" option will notify user with the message, "
|
||||
"Selecting \"Blocking Message\" will throw an exception with the message and "
|
||||
"block the flow. The Message has to be written in the next field."
|
||||
msgstr ""
|
||||
"Sélectionner l'option 'Avertissement' notifiera l'utilisateur avec le "
|
||||
"message. Sélectionner 'Message bloquant' lancera une exception avec le "
|
||||
"message et bloquera le flux. Le message doit être encodé dans le champ "
|
||||
"suivant."
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_stock_picking__move_type
|
||||
msgid "Shipping Policy"
|
||||
msgstr "Politique d'expédition"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_procurement_scheduler_log__start_datetime
|
||||
msgid "Start Date"
|
||||
msgstr "Date de début"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model,name:stock_usability.model_stock_move
|
||||
msgid "Stock Move"
|
||||
msgstr "Mouvement de stock"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.product_form_view_procurement_button
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.product_template_form_view_procurement_button
|
||||
msgid "Stock Moves"
|
||||
msgstr "Mouvements de stock"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_res_partner__picking_warn
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_res_users__picking_warn
|
||||
msgid "Stock Picking"
|
||||
msgstr "Transfert"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_product_product__tracking
|
||||
#: model:ir.model.fields,field_description:stock_usability.field_product_template__tracking
|
||||
msgid "Tracking"
|
||||
msgstr "Suivi"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model,name:stock_usability.model_stock_picking
|
||||
msgid "Transfer"
|
||||
msgstr "Transfert"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.stock_picking_pivot
|
||||
msgid "Transfers"
|
||||
msgstr "Transferts"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.stock_quant_tree_simple
|
||||
msgid "Unit"
|
||||
msgstr "Unité"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.view_move_line_tree
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.view_move_tree
|
||||
#: model_terms:ir.ui.view,arch_db:stock_usability.view_picking_form
|
||||
msgid "Unreserve"
|
||||
msgstr "Déréserver"
|
||||
|
||||
#. module: stock_usability
|
||||
#: model:ir.model.fields,help:stock_usability.field_stock_picking__is_locked
|
||||
msgid ""
|
||||
"When the picking is not done this allows changing the initial demand. When "
|
||||
"the picking is done this allows changing the done quantities."
|
||||
msgstr ""
|
||||
"Quand le bon de préparation n'est pas à l'état terminé, cela permet de modifier la "
|
||||
"demande initiale. Lorsque le transfert est terminé, cela permet de "
|
||||
"modifier les quantités traitées."
|
||||
|
||||
#. module: stock_usability
|
||||
#. odoo-python
|
||||
#: code:addons/stock_usability/models/stock_move_line.py:0
|
||||
#, python-format
|
||||
msgid "You cannot unreserve a move line in done state."
|
||||
msgstr "Il n'est pas possible de déréserver un mouvement de stock à l'état terminé."
|
||||
11
stock_usability_akretion/models/__init__.py
Normal file
11
stock_usability_akretion/models/__init__.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from . import stock_move
|
||||
from . import stock_move_line
|
||||
from . import stock_picking
|
||||
from . import stock_picking_type
|
||||
from . import stock_warehouse_orderpoint
|
||||
from . import stock_quant
|
||||
from . import stock_lot
|
||||
from . import procurement_group
|
||||
from . import procurement_scheduler_log
|
||||
from . import product
|
||||
from . import res_partner
|
||||
46
stock_usability_akretion/models/procurement_group.py
Normal file
46
stock_usability_akretion/models/procurement_group.py
Normal file
@@ -0,0 +1,46 @@
|
||||
# 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).
|
||||
|
||||
from odoo import api, fields, models
|
||||
from datetime import datetime
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ProcurementGroup(models.Model):
|
||||
_inherit = 'procurement.group'
|
||||
|
||||
picking_ids = fields.One2many(
|
||||
'stock.picking', 'group_id', string='Pickings', readonly=True)
|
||||
|
||||
@api.model
|
||||
def run_scheduler(self, use_new_cursor=False, company_id=False):
|
||||
'''Inherit to add info logs'''
|
||||
logger.info(
|
||||
'START procurement scheduler '
|
||||
'(company ID=%d, uid=%d, use_new_cursor=%s)',
|
||||
company_id, self._uid, use_new_cursor)
|
||||
start_datetime = datetime.now()
|
||||
res = super().run_scheduler(
|
||||
use_new_cursor=use_new_cursor, company_id=company_id)
|
||||
logger.info(
|
||||
'END procurement scheduler '
|
||||
'(company ID=%d, uid=%d, use_new_cursor=%s)',
|
||||
company_id, self._uid, use_new_cursor)
|
||||
try:
|
||||
# I put it in a try/except, to be sure that, even if the user
|
||||
# the execute the scheduler doesn't have create right on
|
||||
# procurement.scheduler.log
|
||||
self.env['procurement.scheduler.log'].create({
|
||||
'company_id': company_id,
|
||||
'start_datetime': start_datetime,
|
||||
})
|
||||
# If I don't do an explicit cr.commit(), it doesn't create
|
||||
# the procurement.scheduler.log... I don't know why
|
||||
self._cr.commit()
|
||||
except Exception as e:
|
||||
logger.warning(
|
||||
'Could not create procurement.scheduler.log (error: %s)', e)
|
||||
return res
|
||||
15
stock_usability_akretion/models/procurement_scheduler_log.py
Normal file
15
stock_usability_akretion/models/procurement_scheduler_log.py
Normal file
@@ -0,0 +1,15 @@
|
||||
# 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).
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class ProcurementSchedulerLog(models.Model):
|
||||
_name = 'procurement.scheduler.log'
|
||||
_description = 'Logs of the Procurement Scheduler'
|
||||
_order = 'create_date desc'
|
||||
|
||||
company_id = fields.Many2one(
|
||||
'res.company', string='Company', readonly=True)
|
||||
start_datetime = fields.Datetime(string='Start Date', readonly=True)
|
||||
31
stock_usability_akretion/models/product.py
Normal file
31
stock_usability_akretion/models/product.py
Normal file
@@ -0,0 +1,31 @@
|
||||
# Copyright 2016-2022 Akretion France
|
||||
# @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 ProductTemplate(models.Model):
|
||||
_inherit = 'product.template'
|
||||
|
||||
tracking = fields.Selection(tracking=True)
|
||||
sale_delay = fields.Float(tracking=True)
|
||||
# the 'stock' module adds 'product' in detailed_type...
|
||||
# but forgets to make it the default
|
||||
detailed_type = fields.Selection(default='product')
|
||||
|
||||
def action_view_stock_move(self):
|
||||
action = self.env["ir.actions.actions"]._for_xml_id("stock.stock_move_action")
|
||||
action['domain'] = [('product_id.product_tmpl_id', 'in', self.ids)]
|
||||
action['context'] = {'search_default_done': True}
|
||||
return action
|
||||
|
||||
|
||||
class ProductProduct(models.Model):
|
||||
_inherit = 'product.product'
|
||||
|
||||
def action_view_stock_move(self):
|
||||
action = self.env["ir.actions.actions"]._for_xml_id("stock.stock_move_action")
|
||||
action['domain'] = [('product_id', 'in', self.ids)]
|
||||
action['context'] = {'search_default_done': True}
|
||||
return action
|
||||
11
stock_usability_akretion/models/res_partner.py
Normal file
11
stock_usability_akretion/models/res_partner.py
Normal file
@@ -0,0 +1,11 @@
|
||||
# Copyright 2017-2022 Akretion France (https://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 ResPartner(models.Model):
|
||||
_inherit = 'res.partner'
|
||||
|
||||
picking_warn = fields.Selection(tracking=True)
|
||||
14
stock_usability_akretion/models/stock_lot.py
Normal file
14
stock_usability_akretion/models/stock_lot.py
Normal file
@@ -0,0 +1,14 @@
|
||||
# Copyright 2024 Akretion France (https://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 StockLot(models.Model):
|
||||
_inherit = 'stock.lot'
|
||||
|
||||
name = fields.Char(tracking=True)
|
||||
ref = fields.Char(tracking=True)
|
||||
product_id = fields.Many2one(tracking=True)
|
||||
company_id = fields.Many2one(tracking=True)
|
||||
30
stock_usability_akretion/models/stock_move.py
Normal file
30
stock_usability_akretion/models/stock_move.py
Normal file
@@ -0,0 +1,30 @@
|
||||
# Copyright 2014-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).
|
||||
|
||||
from odoo import fields, models, _
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class StockMove(models.Model):
|
||||
_inherit = 'stock.move'
|
||||
|
||||
# for optional display in tree view
|
||||
product_barcode = fields.Char(
|
||||
related='product_id.barcode', string="Product Barcode")
|
||||
|
||||
def button_do_unreserve(self):
|
||||
for move in self:
|
||||
move._do_unreserve()
|
||||
picking = move.picking_id
|
||||
if picking:
|
||||
product = move.product_id
|
||||
picking.message_post(body=_(
|
||||
"Product <a href=# data-oe-model=product.product "
|
||||
"data-oe-id=%d>%s</a> qty %s %s <b>unreserved</b>")
|
||||
% (product.id, product.display_name,
|
||||
move.product_qty, product.uom_id.name))
|
||||
# Copied from do_unreserved of stock.picking
|
||||
picking.package_level_ids.filtered(lambda p: not p.move_ids).unlink()
|
||||
37
stock_usability_akretion/models/stock_move_line.py
Normal file
37
stock_usability_akretion/models/stock_move_line.py
Normal file
@@ -0,0 +1,37 @@
|
||||
# Copyright 2014-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).
|
||||
|
||||
from odoo import fields, models, _
|
||||
from odoo.exceptions import UserError
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class StockMoveLine(models.Model):
|
||||
_inherit = 'stock.move.line'
|
||||
|
||||
# for optional display in tree view
|
||||
product_barcode = fields.Char(
|
||||
related='product_id.barcode', string="Product Barcode")
|
||||
|
||||
# TODO: I think it's not complete
|
||||
def button_do_unreserve(self):
|
||||
for moveline in self:
|
||||
if moveline.state == 'cancel':
|
||||
continue
|
||||
elif moveline.state == 'done':
|
||||
raise UserError(_(
|
||||
"You cannot unreserve a move line in done state."))
|
||||
picking = moveline.move_id.picking_id
|
||||
if picking:
|
||||
product = moveline.product_id
|
||||
picking.message_post(body=_(
|
||||
"Product <a href=# data-oe-model=product.product "
|
||||
"data-oe-id=%d>%s</a> qty %s %s <b>unreserved</b>")
|
||||
% (product.id, product.display_name,
|
||||
moveline.reserved_qty, product.uom_id.name))
|
||||
# Copied from do_unreserved of stock.picking
|
||||
picking.package_level_ids.filtered(lambda p: not p.move_ids).unlink()
|
||||
moveline.unlink()
|
||||
26
stock_usability_akretion/models/stock_picking.py
Normal file
26
stock_usability_akretion/models/stock_picking.py
Normal file
@@ -0,0 +1,26 @@
|
||||
# Copyright 2014-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).
|
||||
|
||||
from odoo import fields, models, _
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class StockPicking(models.Model):
|
||||
_inherit = 'stock.picking'
|
||||
# _order = 'id desc'
|
||||
# In the stock module: _order = "priority desc, scheduled_date asc, id desc"
|
||||
# The problem is date asc
|
||||
|
||||
partner_id = fields.Many2one(tracking=True)
|
||||
picking_type_id = fields.Many2one(tracking=True)
|
||||
move_type = fields.Selection(tracking=True)
|
||||
is_locked = fields.Boolean(tracking=True)
|
||||
|
||||
def do_unreserve(self):
|
||||
res = super().do_unreserve()
|
||||
for pick in self:
|
||||
pick.message_post(body=_("Picking <b>unreserved</b>."))
|
||||
return res
|
||||
26
stock_usability_akretion/models/stock_picking_type.py
Normal file
26
stock_usability_akretion/models/stock_picking_type.py
Normal file
@@ -0,0 +1,26 @@
|
||||
# Copyright 2023 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 api, fields, models
|
||||
|
||||
|
||||
class StockPickingType(models.Model):
|
||||
_inherit = 'stock.picking.type'
|
||||
|
||||
is_dropship = fields.Boolean(compute="_compute_is_dropship", store=True)
|
||||
|
||||
@api.depends("code", "warehouse_id", "default_location_src_id", "default_location_dest_id")
|
||||
def _compute_is_dropship(self):
|
||||
supplier_loc_id = self.env.ref("stock.stock_location_suppliers").id
|
||||
customer_loc_id = self.env.ref("stock.stock_location_customers").id
|
||||
for picktype in self:
|
||||
is_dropship = False
|
||||
if (
|
||||
picktype.code == 'incoming'
|
||||
and not picktype.warehouse_id
|
||||
and picktype.default_location_src_id.id == supplier_loc_id
|
||||
and picktype.default_location_dest_id.id == customer_loc_id
|
||||
):
|
||||
is_dropship = True
|
||||
picktype.is_dropship = is_dropship
|
||||
51
stock_usability_akretion/models/stock_quant.py
Normal file
51
stock_usability_akretion/models/stock_quant.py
Normal file
@@ -0,0 +1,51 @@
|
||||
# Copyright 2014-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).
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class StockQuant(models.Model):
|
||||
_inherit = 'stock.quant'
|
||||
|
||||
product_barcode = fields.Char(
|
||||
related='product_id.barcode', string="Product Barcode")
|
||||
|
||||
def action_stock_move_lines_reserved(self):
|
||||
self.ensure_one()
|
||||
action = self.env["ir.actions.actions"]._for_xml_id(
|
||||
"stock.stock_move_line_action")
|
||||
action['domain'] = [
|
||||
('state', 'not in', ('draft', 'done', 'cancel')),
|
||||
('reserved_uom_qty', '!=', 0),
|
||||
('product_id', '=', self.product_id.id),
|
||||
('location_id', '=', self.location_id.id),
|
||||
('lot_id', '=', self.lot_id.id or False),
|
||||
'|',
|
||||
('package_id', '=', self.package_id.id or False),
|
||||
('result_package_id', '=', self.package_id.id or False),
|
||||
]
|
||||
action['context'] = {'create': 0}
|
||||
return action
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields_list):
|
||||
res = super().default_get(fields_list)
|
||||
if (
|
||||
not res.get('location_id') and
|
||||
self._context.get('search_location') and
|
||||
isinstance(self._context['search_location'], list) and
|
||||
len(self._context['search_location']) == 1):
|
||||
res['location_id'] = self._context['search_location'][0]
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def action_view_inventory(self):
|
||||
action = super().action_view_inventory()
|
||||
# Remove filter 'My Counts' set by default for Stock Users
|
||||
if (
|
||||
action.get('context') and
|
||||
isinstance(action['context'], dict) and
|
||||
action['context'].get('search_default_my_count')):
|
||||
action['context'].pop('search_default_my_count')
|
||||
return action
|
||||
@@ -0,0 +1,30 @@
|
||||
# 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).
|
||||
|
||||
from odoo import fields, models
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class StockWarehouseOrderpoint(models.Model):
|
||||
_inherit = 'stock.warehouse.orderpoint'
|
||||
|
||||
# In the 'stock' module, the default value for 'trigger' is 'auto'
|
||||
# but all the Odoo deployments I've seen so far need 'manual' by default
|
||||
trigger = fields.Selection(default='manual')
|
||||
product_barcode = fields.Char(related='product_id.barcode', string="Product Barcode")
|
||||
|
||||
def _procure_orderpoint_confirm(
|
||||
self, use_new_cursor=False, company_id=None, raise_user_error=True):
|
||||
logger.info(
|
||||
'procurement scheduler: START to create moves from '
|
||||
'orderpoints')
|
||||
res = super()._procure_orderpoint_confirm(
|
||||
use_new_cursor=use_new_cursor, company_id=company_id,
|
||||
raise_user_error=raise_user_error)
|
||||
logger.info(
|
||||
'procurement scheduler: END creation of moves from '
|
||||
'orderpoints')
|
||||
return res
|
||||
25
stock_usability_akretion/post_install.py
Normal file
25
stock_usability_akretion/post_install.py
Normal file
@@ -0,0 +1,25 @@
|
||||
# Copyright 2021-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).
|
||||
|
||||
import logging
|
||||
from odoo import SUPERUSER_ID, api
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def create_config_parameter_immediate_tranfer(cr, registry):
|
||||
env = api.Environment(cr, SUPERUSER_ID, {})
|
||||
ico = env["ir.config_parameter"]
|
||||
conf_param = ico.search([('key', '=', 'stock.no_default_immediate_tranfer')])
|
||||
if not conf_param:
|
||||
ico.create({
|
||||
'key': 'stock.no_default_immediate_tranfer',
|
||||
'value': 'True',
|
||||
})
|
||||
logger.info(
|
||||
'ir.config_parameter stock.no_default_immediate_tranfer created')
|
||||
else:
|
||||
logger.info(
|
||||
'ir.config_parameter stock.no_default_immediate_tranfer '
|
||||
'already exists')
|
||||
5
stock_usability_akretion/security/ir.model.access.csv
Normal file
5
stock_usability_akretion/security/ir.model.access.csv
Normal file
@@ -0,0 +1,5 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_procurement_scheduler_log_full,Full access on procurement.scheduler.log to System group,model_procurement_scheduler_log,base.group_system,1,1,1,1
|
||||
access_procurement_scheduler_log_user,Read/Create procurement.scheduler.log to Stock user,model_procurement_scheduler_log,stock.group_stock_user,1,0,1,0
|
||||
access_procurement_scheduler_log_read,Read access on procurement.scheduler.log to Employee,model_procurement_scheduler_log,base.group_user,1,0,0,0
|
||||
access_stock_warehouse_orderpoint_employee,Read access on stock.warehouse.orderpoint to employee (needed to open product form view with employee-only group),stock.model_stock_warehouse_orderpoint,base.group_user,1,0,0,0
|
||||
|
BIN
stock_usability_akretion/static/description/icon.png
Normal file
BIN
stock_usability_akretion/static/description/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.5 KiB |
@@ -0,0 +1,238 @@
|
||||
diff --git a/addons/stock/models/product.py b/addons/stock/models/product.py
|
||||
index bbb6f301834..48d016010dc 100644
|
||||
--- a/addons/stock/models/product.py
|
||||
+++ b/addons/stock/models/product.py
|
||||
@@ -36,6 +36,18 @@ class Product(models.Model):
|
||||
"or any of its children.\n"
|
||||
"Otherwise, this includes goods stored in any Stock Location "
|
||||
"with 'internal' type.")
|
||||
+ reserved_qty = fields.Float(
|
||||
+ compute='_compute_quantities',
|
||||
+ digits=dp.get_precision('Product Unit of Measure'),
|
||||
+ search='_search_reserved_qty',
|
||||
+ string='Reserved Quantity')
|
||||
+ free_qty = fields.Float(
|
||||
+ compute='_compute_quantities',
|
||||
+ search='_search_free_qty',
|
||||
+ digits=dp.get_precision('Product Unit of Measure'),
|
||||
+ string='Free To Use Quantity',
|
||||
+ help="The free to use quantity corresponds to the quantity on hand "
|
||||
+ "- reserved quantity")
|
||||
virtual_available = fields.Float(
|
||||
'Forecast Quantity', compute='_compute_quantities', search='_search_virtual_available',
|
||||
digits=dp.get_precision('Product Unit of Measure'),
|
||||
@@ -84,6 +96,8 @@ class Product(models.Model):
|
||||
product.incoming_qty = res[product.id]['incoming_qty']
|
||||
product.outgoing_qty = res[product.id]['outgoing_qty']
|
||||
product.virtual_available = res[product.id]['virtual_available']
|
||||
+ product.reserved_qty = res[product.id]['reserved_qty']
|
||||
+ product.free_qty = res[product.id]['free_qty']
|
||||
|
||||
def _product_available(self, field_names=None, arg=False):
|
||||
""" Compatibility method """
|
||||
@@ -124,7 +138,7 @@ class Product(models.Model):
|
||||
domain_move_out_todo = [('state', 'in', ('waiting', 'confirmed', 'assigned', 'partially_available'))] + domain_move_out
|
||||
moves_in_res = dict((item['product_id'][0], item['product_qty']) for item in Move.read_group(domain_move_in_todo, ['product_id', 'product_qty'], ['product_id'], orderby='id'))
|
||||
moves_out_res = dict((item['product_id'][0], item['product_qty']) for item in Move.read_group(domain_move_out_todo, ['product_id', 'product_qty'], ['product_id'], orderby='id'))
|
||||
- quants_res = dict((item['product_id'][0], item['quantity']) for item in Quant.read_group(domain_quant, ['product_id', 'quantity'], ['product_id'], orderby='id'))
|
||||
+ quants_res = dict((item['product_id'][0], (item['quantity'], item['reserved_quantity'])) for item in Quant.read_group(domain_quant, ['product_id', 'quantity', 'reserved_quantity'], ['product_id'], orderby='id'))
|
||||
if dates_in_the_past:
|
||||
# Calculate the moves that were done before now to calculate back in time (as most questions will be recent ones)
|
||||
domain_move_in_done = [('state', '=', 'done'), ('date', '>', to_date)] + domain_move_in_done
|
||||
@@ -138,10 +152,13 @@ class Product(models.Model):
|
||||
rounding = product.uom_id.rounding
|
||||
res[product_id] = {}
|
||||
if dates_in_the_past:
|
||||
- qty_available = quants_res.get(product_id, 0.0) - moves_in_res_past.get(product_id, 0.0) + moves_out_res_past.get(product_id, 0.0)
|
||||
+ qty_available = quants_res.get(product_id, [0.0])[0] - moves_in_res_past.get(product_id, 0.0) + moves_out_res_past.get(product_id, 0.0)
|
||||
else:
|
||||
- qty_available = quants_res.get(product_id, 0.0)
|
||||
+ qty_available = quants_res.get(product_id, [0.0])[0]
|
||||
+ reserved_quantity = quants_res.get(product_id, [False, 0.0])[1]
|
||||
res[product_id]['qty_available'] = float_round(qty_available, precision_rounding=rounding)
|
||||
+ res[product_id]['reserved_qty'] = float_round(reserved_quantity, precision_rounding=rounding)
|
||||
+ res[product_id]['free_qty'] = float_round(qty_available - reserved_quantity, precision_rounding=rounding)
|
||||
res[product_id]['incoming_qty'] = float_round(moves_in_res.get(product_id, 0.0), precision_rounding=rounding)
|
||||
res[product_id]['outgoing_qty'] = float_round(moves_out_res.get(product_id, 0.0), precision_rounding=rounding)
|
||||
res[product_id]['virtual_available'] = float_round(
|
||||
@@ -261,10 +278,16 @@ class Product(models.Model):
|
||||
# TDE FIXME: should probably clean the search methods
|
||||
return self._search_product_quantity(operator, value, 'outgoing_qty')
|
||||
|
||||
+ def _search_reserved_qty(self, operator, value):
|
||||
+ return self._search_product_quantity(operator, value, 'reserved_qty')
|
||||
+
|
||||
+ def _search_free_qty(self, operator, value):
|
||||
+ return self._search_product_quantity(operator, value, 'free_qty')
|
||||
+
|
||||
def _search_product_quantity(self, operator, value, field):
|
||||
# TDE FIXME: should probably clean the search methods
|
||||
# to prevent sql injections
|
||||
- if field not in ('qty_available', 'virtual_available', 'incoming_qty', 'outgoing_qty'):
|
||||
+ if field not in ('qty_available', 'virtual_available', 'incoming_qty', 'outgoing_qty', 'reserved_qty', 'free_qty'):
|
||||
raise UserError(_('Invalid domain left operand %s') % field)
|
||||
if operator not in ('<', '>', '=', '!=', '<=', '>='):
|
||||
raise UserError(_('Invalid domain operator %s') % operator)
|
||||
@@ -387,6 +410,12 @@ class Product(models.Model):
|
||||
action['context'] = {'search_default_internal_loc': 1}
|
||||
return action
|
||||
|
||||
+ def action_open_move_lines(self):
|
||||
+ action = self.env.ref('stock.stock_move_line_action').read()[0]
|
||||
+ action['domain'] = [('product_id', '=', self.id), ('state', 'not in', ('done', 'cancel'))]
|
||||
+ action['context'] = {'default_product_id': self.id}
|
||||
+ return action
|
||||
+
|
||||
def action_open_product_lot(self):
|
||||
self.ensure_one()
|
||||
action = self.env.ref('stock.action_production_lot_form').read()[0]
|
||||
@@ -451,6 +480,18 @@ class ProductTemplate(models.Model):
|
||||
qty_available = fields.Float(
|
||||
'Quantity On Hand', compute='_compute_quantities', search='_search_qty_available',
|
||||
digits=dp.get_precision('Product Unit of Measure'))
|
||||
+ reserved_qty = fields.Float(
|
||||
+ compute='_compute_quantities',
|
||||
+ digits=dp.get_precision('Product Unit of Measure'),
|
||||
+ search='_search_reserved_qty',
|
||||
+ string='Reserved Quantity')
|
||||
+ free_qty = fields.Float(
|
||||
+ compute='_compute_quantities',
|
||||
+ search='_search_free_qty',
|
||||
+ digits=dp.get_precision('Product Unit of Measure'),
|
||||
+ string='Free To Use Quantity',
|
||||
+ help="The free to use quantity corresponds to the quantity on hand "
|
||||
+ "- reserved quantity")
|
||||
virtual_available = fields.Float(
|
||||
'Forecasted Quantity', compute='_compute_quantities', search='_search_virtual_available',
|
||||
digits=dp.get_precision('Product Unit of Measure'))
|
||||
@@ -490,6 +531,8 @@ class ProductTemplate(models.Model):
|
||||
res = self._compute_quantities_dict()
|
||||
for template in self:
|
||||
template.qty_available = res[template.id]['qty_available']
|
||||
+ template.reserved_qty = res[template.id]['reserved_qty']
|
||||
+ template.free_qty = res[template.id]['free_qty']
|
||||
template.virtual_available = res[template.id]['virtual_available']
|
||||
template.incoming_qty = res[template.id]['incoming_qty']
|
||||
template.outgoing_qty = res[template.id]['outgoing_qty']
|
||||
@@ -503,16 +546,22 @@ class ProductTemplate(models.Model):
|
||||
prod_available = {}
|
||||
for template in self:
|
||||
qty_available = 0
|
||||
+ reserved_qty = 0
|
||||
+ free_qty = 0
|
||||
virtual_available = 0
|
||||
incoming_qty = 0
|
||||
outgoing_qty = 0
|
||||
for p in template.product_variant_ids:
|
||||
qty_available += variants_available[p.id]["qty_available"]
|
||||
+ reserved_qty += variants_available[p.id]["reserved_qty"]
|
||||
+ free_qty += variants_available[p.id]["free_qty"]
|
||||
virtual_available += variants_available[p.id]["virtual_available"]
|
||||
incoming_qty += variants_available[p.id]["incoming_qty"]
|
||||
outgoing_qty += variants_available[p.id]["outgoing_qty"]
|
||||
prod_available[template.id] = {
|
||||
"qty_available": qty_available,
|
||||
+ "reserved_qty": reserved_qty,
|
||||
+ "free_qty": free_qty,
|
||||
"virtual_available": virtual_available,
|
||||
"incoming_qty": incoming_qty,
|
||||
"outgoing_qty": outgoing_qty,
|
||||
@@ -524,6 +573,16 @@ class ProductTemplate(models.Model):
|
||||
product_variant_ids = self.env['product.product'].search(domain)
|
||||
return [('product_variant_ids', 'in', product_variant_ids.ids)]
|
||||
|
||||
+ def _search_reserved_qty(self, operator, value):
|
||||
+ domain = [('reserved_qty', operator, value)]
|
||||
+ product_variant_ids = self.env['product.product'].search(domain)
|
||||
+ return [('product_variant_ids', 'in', product_variant_ids.ids)]
|
||||
+
|
||||
+ def _search_free_qty(self, operator, value):
|
||||
+ domain = [('free_qty', operator, value)]
|
||||
+ product_variant_ids = self.env['product.product'].search(domain)
|
||||
+ return [('product_variant_ids', 'in', product_variant_ids.ids)]
|
||||
+
|
||||
def _search_virtual_available(self, operator, value):
|
||||
domain = [('virtual_available', operator, value)]
|
||||
product_variant_ids = self.env['product.product'].search(domain)
|
||||
@@ -609,6 +668,13 @@ class ProductTemplate(models.Model):
|
||||
action['context'] = {'search_default_internal_loc': 1}
|
||||
return action
|
||||
|
||||
+ def action_open_move_lines(self):
|
||||
+ products = self.mapped('product_variant_ids')
|
||||
+ action = self.env.ref('stock.stock_move_line_action').read()[0]
|
||||
+ action['domain'] = [('product_id', 'in', products.ids), ('state', 'not in', ('done', 'cancel'))]
|
||||
+ action['context'] = {}
|
||||
+ return action
|
||||
+
|
||||
def action_view_orderpoints(self):
|
||||
products = self.mapped('product_variant_ids')
|
||||
action = self.env.ref('stock.product_open_orderpoint').read()[0]
|
||||
diff --git a/addons/stock/views/product_views.xml b/addons/stock/views/product_views.xml
|
||||
index 70321544e00..99bd47b4e56 100644
|
||||
--- a/addons/stock/views/product_views.xml
|
||||
+++ b/addons/stock/views/product_views.xml
|
||||
@@ -36,6 +36,8 @@
|
||||
</tree>
|
||||
<field name="price" position="after">
|
||||
<field name="qty_available" attrs="{'invisible':[('type', '!=', 'product')]}"/>
|
||||
+ <field name="reserved_qty" attrs="{'invisible': [('type', '!=', 'product')]}"/>
|
||||
+ <field name="free_qty" attrs="{'invisible': [('type', '!=', 'product')]}"/>
|
||||
<field name="virtual_available" attrs="{'invisible':[('type', '!=', 'product')]}"/>
|
||||
</field>
|
||||
</field>
|
||||
@@ -52,6 +54,8 @@
|
||||
</tree>
|
||||
<field name="uom_id" position="before">
|
||||
<field name="qty_available" attrs="{'invisible':[('type', '!=', 'product')]}"/>
|
||||
+ <field name="reserved_qty" attrs="{'invisible': [('type', '!=', 'product')]}"/>
|
||||
+ <field name="free_qty" attrs="{'invisible': [('type', '!=', 'product')]}"/>
|
||||
<field name="virtual_available" attrs="{'invisible':[('type', '!=', 'product')]}"/>
|
||||
</field>
|
||||
</field>
|
||||
@@ -140,6 +144,7 @@
|
||||
</field>
|
||||
<ul position="inside">
|
||||
<li t-if="record.type.raw_value == 'product'">On hand: <field name="qty_available"/> <field name="uom_id"/></li>
|
||||
+ <li t-if="record.type.raw_value == 'product'">Reserved: <field name="reserved_qty"/> <field name="uom_id"/></li>
|
||||
</ul>
|
||||
</field>
|
||||
</record>
|
||||
@@ -208,6 +213,18 @@
|
||||
<span class="o_stat_text">On Hand</span>
|
||||
</div>
|
||||
</button>
|
||||
+ <button class="oe_stat_button"
|
||||
+ name="action_open_move_lines"
|
||||
+ icon="fa-building-o"
|
||||
+ type="object" attrs="{'invisible': [('type', '!=', 'product')]}">
|
||||
+ <div class="o_field_widget o_stat_info">
|
||||
+ <span class="o_stat_value">
|
||||
+ <field name="reserved_qty" widget="statinfo" nolabel="1" class="mr4"/>
|
||||
+ <field name="uom_name"/>
|
||||
+ </span>
|
||||
+ <span class="o_stat_text">Reserved</span>
|
||||
+ </div>
|
||||
+ </button>
|
||||
<button type="action"
|
||||
name="%(stock.action_stock_level_forecast_report_product)d"
|
||||
attrs="{'invisible':[('type', '!=', 'product')]}"
|
||||
@@ -291,6 +308,18 @@
|
||||
<span class="o_stat_text">On Hand</span>
|
||||
</div>
|
||||
</button>
|
||||
+ <button type="object"
|
||||
+ name="action_open_move_lines"
|
||||
+ attrs="{'invisible': [('type', '!=', 'product')]}"
|
||||
+ class="oe_stat_button" icon="fa-building-o">
|
||||
+ <div class="o_field_widget o_stat_info">
|
||||
+ <span class="o_stat_value" widget="statinfo">
|
||||
+ <field name="reserved_qty" widget="statinfo" nolabel="1" class="mr4"/>
|
||||
+ <field name="uom_name"/>
|
||||
+ </span>
|
||||
+ <span class="o_stat_text">Reserved</span>
|
||||
+ </div>
|
||||
+ </button>
|
||||
<button type="action"
|
||||
name="%(stock.action_stock_level_forecast_report_template)d"
|
||||
attrs="{'invisible':[('type', '!=', 'product')]}"
|
||||
21
stock_usability_akretion/views/procurement_group.xml
Normal file
21
stock_usability_akretion/views/procurement_group.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
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).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="procurement_group_form_view" model="ir.ui.view">
|
||||
<field name="name">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="partner_id" readonly="1"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
33
stock_usability_akretion/views/procurement_scheduler_log.xml
Normal file
33
stock_usability_akretion/views/procurement_scheduler_log.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2015-2020 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="procurement_scheduler_log_tree" model="ir.ui.view">
|
||||
<field name="name">procurement_scheduler_log_tree</field>
|
||||
<field name="model">procurement.scheduler.log</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Procurement Scheduler Logs">
|
||||
<field name="start_datetime"/>
|
||||
<field name="create_date" string="Scheduler End Time"/>
|
||||
<field name="create_uid" string="Scheduler Executed by"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="procurement_scheduler_log_action" model="ir.actions.act_window">
|
||||
<field name="name">Scheduler Logs</field>
|
||||
<field name="res_model">procurement.scheduler.log</field>
|
||||
<field name="view_mode">tree</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="procurement_scheduler_log_menu"
|
||||
action="procurement_scheduler_log_action"
|
||||
parent="stock.menu_warehouse_report" sequence="300"/>
|
||||
|
||||
</odoo>
|
||||
68
stock_usability_akretion/views/product.xml
Normal file
68
stock_usability_akretion/views/product.xml
Normal file
@@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2021-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).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
|
||||
<record id="view_stock_product_template_tree" model="ir.ui.view">
|
||||
<field name="name">stock.usability.product.template.tree</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="stock.view_stock_product_template_tree" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="responsible_id" position="attributes">
|
||||
<attribute name="optional">hide</attribute>
|
||||
</field>
|
||||
<field name="virtual_available" position="before">
|
||||
<field name="incoming_qty" optional="hide" sum="1"/>
|
||||
<field name="outgoing_qty" optional="hide" sum="1"/>
|
||||
<!-- we would like to also have free_qty, as on product.product, but this field doesn't exist on product.template -->
|
||||
</field>
|
||||
<!-- we have sum=1 on product.product qty fields, but not on product.template...so I add it on product.template -->
|
||||
<field name="virtual_available" position="attributes">
|
||||
<attribute name="sum">1</attribute>
|
||||
</field>
|
||||
<field name="qty_available" position="attributes">
|
||||
<attribute name="sum">1</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="product_template_form_view_procurement_button" model="ir.ui.view">
|
||||
<field name="name">stock_usability.product.template.form</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="stock.product_template_form_view_procurement_button"/>
|
||||
<field name="arch" type="xml">
|
||||
<button name="action_view_stock_move_lines" position="before">
|
||||
<button string="Stock Moves"
|
||||
type="object"
|
||||
name= "action_view_stock_move"
|
||||
attrs="{'invisible': [('type', 'not in', ('product', 'consu'))]}"
|
||||
groups="stock.group_stock_user"
|
||||
class="oe_stat_button" icon="fa-exchange"
|
||||
/>
|
||||
</button>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="product_form_view_procurement_button" model="ir.ui.view">
|
||||
<field name="name">stock_usability.product.product.form</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="inherit_id" ref="stock.product_form_view_procurement_button"/>
|
||||
<field name="arch" type="xml">
|
||||
<button name="action_view_stock_move_lines" position="before">
|
||||
<button string="Stock Moves"
|
||||
type="object"
|
||||
name= "action_view_stock_move"
|
||||
attrs="{'invisible': [('type', 'not in', ('product', 'consu'))]}"
|
||||
groups="stock.group_stock_user"
|
||||
class="oe_stat_button" icon="fa-exchange"
|
||||
/>
|
||||
</button>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
83
stock_usability_akretion/views/stock_location.xml
Normal file
83
stock_usability_akretion/views/stock_location.xml
Normal file
@@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2014-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).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
|
||||
<record id="view_location_search" model="ir.ui.view">
|
||||
<field name="name">stock.usability.stock.location.search</field>
|
||||
<field name="model">stock.location</field>
|
||||
<field name="inherit_id" ref="stock.view_location_search" />
|
||||
<field name="arch" type="xml">
|
||||
<filter name="inactive" position="after">
|
||||
<group string="Group By" name="groupby">
|
||||
<filter name="usage_groupby" string="Location Type"
|
||||
context="{'group_by': 'usage'}"/>
|
||||
<filter name="removal_strategy_groupby" string="Removal Strategy"
|
||||
context="{'group_by': 'removal_strategy_id'}"/>
|
||||
</group>
|
||||
</filter>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="location_open_orderpoint" model="ir.actions.act_window">
|
||||
<field name="name">Reordering Rules</field>
|
||||
<field name="res_model">stock.warehouse.orderpoint</field>
|
||||
<field name="context">{'default_location_id': active_id, 'search_default_location_id': active_id}</field>
|
||||
</record>
|
||||
|
||||
<record id="location_open_quants_regular_tree" model="ir.actions.act_window">
|
||||
<field name="name">Quants</field>
|
||||
<field name="res_model">stock.quant</field>
|
||||
<field name="domain">[('location_id', 'child_of', active_ids)]</field>
|
||||
<field name="view_id" ref="stock_usability.stock_quant_tree_simple"/>
|
||||
</record>
|
||||
|
||||
<record id="view_location_form" model="ir.ui.view">
|
||||
<field name="name">stock.usability.stock.location.form</field>
|
||||
<field name="model">stock.location</field>
|
||||
<field name="inherit_id" ref="stock.view_location_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<div name="button_box" position="inside">
|
||||
<button type="action" name="%(location_open_quants_regular_tree)d"
|
||||
string="Quants"
|
||||
class="oe_stat_button" icon="fa-cubes"/>
|
||||
<button type="action" name="%(location_open_orderpoint)d"
|
||||
string="Reordering Rules"
|
||||
class="oe_stat_button" icon="fa-refresh"/>
|
||||
</div>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_location_tree2" model="ir.ui.view">
|
||||
<field name="model">stock.location</field>
|
||||
<field name="inherit_id" ref="stock.view_location_tree2"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="storage_category_id" position="after">
|
||||
<field name="removal_strategy_id" optional="hide"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- By default, the menu entry for stock location is only under
|
||||
Configuration > Warehouse management
|
||||
But, the view of stock location is very useful to be able to list
|
||||
the items present on a particular stock location => so every user
|
||||
should be able to access it. So I add a menu entry under Inventory Control.
|
||||
The problem is that, in addons/stock/views/stock_quant_views.xml,
|
||||
there is a menu entry XMLID stock.menu_valuation pointing to stock.quant
|
||||
with name="Locations"... so we end up having 2 different menu entries "Locations"
|
||||
pointing to different models.
|
||||
Until I find a proper solution to that, I decided to remove the menu entry
|
||||
|
||||
<menuitem id="stock_location_menu" action="stock.action_location_form"
|
||||
parent="stock.menu_warehouse_report"
|
||||
groups="stock.group_stock_multi_locations"
|
||||
sequence="160"/>
|
||||
-->
|
||||
|
||||
</odoo>
|
||||
35
stock_usability_akretion/views/stock_lot.xml
Normal file
35
stock_usability_akretion/views/stock_lot.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 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="stock.action_production_lot_form" model="ir.actions.act_window">
|
||||
<!-- remove from context 'search_default_group_by_product': 1-->
|
||||
<field name="context">{'display_complete': True, 'default_company_id': allowed_company_ids[0]}</field>
|
||||
</record>
|
||||
|
||||
<record id="stock_move_line_from_lot_action" model="ir.actions.act_window">
|
||||
<field name="name">Product Moves</field>
|
||||
<field name="res_model">stock.move.line</field>
|
||||
<field name="view_mode">tree,kanban,pivot,form</field>
|
||||
<field name="domain">[('lot_id', '=', active_id)]</field>
|
||||
<field name="context">{'search_default_done': 1, 'create': 0}</field>
|
||||
</record>
|
||||
|
||||
<record id="view_production_lot_form" model="ir.ui.view">
|
||||
<field name="model">stock.lot</field>
|
||||
<field name="inherit_id" ref="stock.view_production_lot_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<button name="action_lot_open_quants" position="after">
|
||||
<button name="%(stock_move_line_from_lot_action)d" string="Product Moves" type="action" icon="fa-exchange"/>
|
||||
</button>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
||||
66
stock_usability_akretion/views/stock_move.xml
Normal file
66
stock_usability_akretion/views/stock_move.xml
Normal file
@@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2014-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).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
|
||||
<!-- Display advanced fields in stock moves form view -->
|
||||
<record id="view_move_form" model="ir.ui.view">
|
||||
<field name="name">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="state" position="before">
|
||||
<button type="object" name="button_do_unreserve" string="Unreserve"
|
||||
groups="stock.group_stock_user"
|
||||
attrs="{'invisible': [('reserved_quant_ids', '=', [])]}"/>
|
||||
</field> -->
|
||||
<field name="origin" position="after">
|
||||
<field name="picking_id" readonly="1" string="Picking"/>
|
||||
</field>
|
||||
<group name="origin_grp" position="after">
|
||||
<group name="advanced" string="Advanced" groups="stock.group_stock_manager">
|
||||
<field name="warehouse_id" readonly="1"/>
|
||||
<field name="route_ids" widget="many2many_tags" readonly="1"/>
|
||||
<field name="rule_id" readonly="1"/>
|
||||
<field name="propagate_cancel" readonly="1"/>
|
||||
<field name="price_unit" readonly="1"/>
|
||||
<field name="partner_id" readonly="1"/>
|
||||
<field name="restrict_partner_id" readonly="1"/>
|
||||
</group>
|
||||
</group>
|
||||
<group name="linked_group" position="after">
|
||||
<group name="move_line_ids" string="Product Moves" colspan="2">
|
||||
<field name="move_line_ids" nolabel="1" readonly="1" colspan="2"/>
|
||||
</group>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_move_tree" model="ir.ui.view">
|
||||
<field name="name">stock_usability.move.tree.better.order</field>
|
||||
<field name="model">stock.move</field>
|
||||
<field name="inherit_id" ref="stock.view_move_tree" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="state" position="after">
|
||||
<button type="object" name="button_do_unreserve" string="Unreserve"
|
||||
groups="stock.group_stock_user"
|
||||
states="partially_available,assigned"
|
||||
icon="fa-ban"/>
|
||||
</field>
|
||||
<field name="product_id" position="after">
|
||||
<field name="product_barcode" optional="hide"/>
|
||||
</field>
|
||||
<field name="reference" position="after">
|
||||
<field name="origin" optional="hide"/>
|
||||
<field name="partner_id" optional="hide"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
50
stock_usability_akretion/views/stock_move_line.xml
Normal file
50
stock_usability_akretion/views/stock_move_line.xml
Normal file
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2014-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).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="view_move_line_tree" model="ir.ui.view">
|
||||
<field name="name">stock_usability.stock.move.line.tree</field>
|
||||
<field name="model">stock.move.line</field>
|
||||
<field name="inherit_id" ref="stock.view_move_line_tree" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="qty_done" position="before">
|
||||
<field name="reserved_uom_qty" sum="1"/>
|
||||
</field>
|
||||
<field name="qty_done" position="attributes">
|
||||
<attribute name="sum">1</attribute>
|
||||
</field>
|
||||
<field name="state" position="after">
|
||||
<button type="object" name="button_do_unreserve" string="Unreserve"
|
||||
groups="stock.group_stock_user"
|
||||
states="partially_available,assigned"
|
||||
icon="fa-ban"/>
|
||||
</field>
|
||||
<field name="product_id" position="after">
|
||||
<field name="product_barcode" optional="hide"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- View embedded in picking -->
|
||||
<record id="view_stock_move_line_detailed_operation_tree" model="ir.ui.view">
|
||||
<field name="model">stock.move.line</field>
|
||||
<field name="inherit_id" ref="stock.view_stock_move_line_detailed_operation_tree" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="product_id" position="after">
|
||||
<field name="product_barcode" optional="hide"/>
|
||||
</field>
|
||||
<field name="qty_done" position="attributes">
|
||||
<attribute name="sum">1</attribute>
|
||||
</field>
|
||||
<field name="reserved_uom_qty" position="attributes">
|
||||
<attribute name="sum">1</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
120
stock_usability_akretion/views/stock_picking.xml
Normal file
120
stock_usability_akretion/views/stock_picking.xml
Normal file
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2014-2020 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">stock_usability.view_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="backorder_id" position="attributes">
|
||||
<attribute name="attrs">{}</attribute>
|
||||
</field>
|
||||
<field name="partner_id" position="attributes">
|
||||
<attribute name="context">{'show_address': 1}</attribute>
|
||||
<attribute name="options">{'always_reload': True}</attribute>
|
||||
</field>
|
||||
<button name="action_cancel" type="object" position="attributes">
|
||||
<attribute name="confirm">Are you sure you want to cancel this picking?</attribute>
|
||||
</button>
|
||||
<!-- STOCK MOVE -->
|
||||
<!-- This sum is useful to check the 'number of items' to transfer... -->
|
||||
<xpath expr="//field[@name='move_ids_without_package']/tree/field[@name='product_uom_qty']" position="attributes">
|
||||
<attribute name="sum">1</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='move_ids_without_package']/tree/field[@name='quantity_done']" position="attributes">
|
||||
<attribute name="sum">1</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='move_ids_without_package']/tree/field[@name='location_id']" position="replace"/>
|
||||
<xpath expr="//field[@name='move_ids_without_package']/tree/field[@name='location_dest_id']" position="replace"/>
|
||||
<xpath expr="//field[@name='move_ids_without_package']/tree/field[@name='name']" position="replace"/>
|
||||
<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" 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"
|
||||
groups="stock.group_stock_user"
|
||||
states="partially_available,assigned"
|
||||
icon="fa-ban"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='move_ids_without_package']/form//field[@name='product_uom']" position="after">
|
||||
<field name="location_id" groups="stock.group_stock_multi_locations" domain="[('id', 'child_of', 'parent.location_id')]" options="{'no_create': True}"/>
|
||||
<field name="location_dest_id" groups="stock.group_stock_multi_locations" domain="[('id', 'child_of', 'parent.location_dest_id')]" options="{'no_create': True}"/>
|
||||
</xpath>
|
||||
<xpath expr="//sheet/group/group/field[@name='location_id' and @groups='stock.group_stock_multi_locations']" position="attributes">
|
||||
<attribute name="attrs">{}</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//sheet/group/group/field[@name='location_dest_id' and @groups='stock.group_stock_multi_locations']" position="attributes">
|
||||
<attribute name="attrs">{}</attribute>
|
||||
</xpath>
|
||||
<group name="other_infos" position="inside">
|
||||
<!-- the field picking_type_id is shown at the top of the form view when hide_picking_type = False, which depend on a context key. I want to always show it in the last tab -->
|
||||
<field name="picking_type_id" readonly="1"/>
|
||||
</group>
|
||||
</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>
|
||||
<field name="inherit_id" ref="stock.view_picking_internal_search" />
|
||||
<field name="arch" type="xml">
|
||||
<filter name="picking_type" position="after">
|
||||
<filter string="Partner" name="partner_groupby" context="{'group_by': 'partner_id'}"/>
|
||||
</filter>
|
||||
<filter name="origin" position="replace"/>
|
||||
<filter name="expected_date" position="after">
|
||||
<filter name="date_done_groupby" string="Date Done"
|
||||
context="{'group_by': 'date_done:day'}"/>
|
||||
</filter>
|
||||
<filter name="expected_date" position="attributes">
|
||||
<!-- group per day -->
|
||||
<attribute name="context">{'group_by': 'scheduled_date:day'}</attribute>
|
||||
</filter>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="stock_picking_pivot" model="ir.ui.view">
|
||||
<field name="name">stock_usability.picking_pivot</field>
|
||||
<field name="model">stock.picking</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Transfers">
|
||||
<field name="date_done" type="row" interval="month"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="stock.action_picking_tree_all" model="ir.actions.act_window">
|
||||
<field name="view_mode">tree,kanban,form,calendar,pivot</field> <!-- add pivot -->
|
||||
</record>
|
||||
|
||||
<record id="stock.stock_picking_action_picking_type" model="ir.actions.act_window">
|
||||
<field name="view_mode">tree,kanban,form,calendar,pivot</field> <!-- add pivot -->
|
||||
</record>
|
||||
|
||||
<record id="stock.action_picking_tree_ready" model="ir.actions.act_window">
|
||||
<field name="view_mode">tree,kanban,form,calendar,pivot</field> <!-- add pivot -->
|
||||
</record>
|
||||
|
||||
<record id="stock.action_picking_tree_waiting" model="ir.actions.act_window">
|
||||
<field name="view_mode">tree,kanban,form,calendar,pivot</field> <!-- add pivot -->
|
||||
</record>
|
||||
|
||||
<record id="stock.action_picking_tree_late" model="ir.actions.act_window">
|
||||
<field name="view_mode">tree,kanban,form,calendar,pivot</field> <!-- add pivot -->
|
||||
</record>
|
||||
|
||||
<record id="stock.action_picking_tree_backorder" model="ir.actions.act_window">
|
||||
<field name="view_mode">tree,kanban,form,calendar,pivot</field> <!-- add pivot -->
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
33
stock_usability_akretion/views/stock_picking_type.xml
Normal file
33
stock_usability_akretion/views/stock_picking_type.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2014-2023 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="model">stock.picking.type</field>
|
||||
<field name="inherit_id" ref="stock.view_picking_type_form" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="return_picking_type_id" position="before">
|
||||
<field name="is_dropship"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="view_picking_type_tree" model="ir.ui.view">
|
||||
<field name="name">usability.stock.picking.type.tree</field>
|
||||
<field name="model">stock.picking.type</field>
|
||||
<field name="inherit_id" ref="stock.view_picking_type_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="warehouse_id" position="after">
|
||||
<field name="default_location_src_id"/>
|
||||
<field name="default_location_dest_id"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
132
stock_usability_akretion/views/stock_quant.xml
Normal file
132
stock_usability_akretion/views/stock_quant.xml
Normal file
@@ -0,0 +1,132 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2014-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).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
|
||||
<record id="view_stock_quant_tree" model="ir.ui.view">
|
||||
<field name="name">stock.usability.quant.tree</field>
|
||||
<field name="model">stock.quant</field>
|
||||
<field name="inherit_id" ref="stock.view_stock_quant_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="product_id" position="after">
|
||||
<field name="product_barcode" optional="hide"/>
|
||||
</field>
|
||||
<!-- Move available_quantity AFTER quantity -->
|
||||
<field name="quantity" position="after">
|
||||
<field name="reserved_quantity" sum="1" optional="show"/>
|
||||
<field name="available_quantity" position="move"/>
|
||||
</field>
|
||||
<field name="quantity" position="attributes">
|
||||
<attribute name="sum">1</attribute>
|
||||
</field>
|
||||
<field name="available_quantity" position="attributes">
|
||||
<attribute name="sum">1</attribute>
|
||||
<attribute name="optional">show</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- view used from product form -->
|
||||
<record id="view_stock_quant_tree_inventory_editable" model="ir.ui.view">
|
||||
<field name="model">stock.quant</field>
|
||||
<field name="inherit_id" ref="stock.view_stock_quant_tree_inventory_editable"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="quantity" position="after">
|
||||
<field name="reserved_quantity" sum="1" optional="show"/>
|
||||
<button type="object" name="action_stock_move_lines_reserved" string="Reservations" attrs="{'invisible': [('reserved_quantity', '=', 0)]}"/>
|
||||
<field name="available_quantity" position="move"/>
|
||||
</field>
|
||||
<field name="quantity" position="attributes">
|
||||
<attribute name="sum">1</attribute>
|
||||
</field>
|
||||
<field name="available_quantity" position="attributes">
|
||||
<attribute name="sum">1</attribute>
|
||||
<attribute name="optional">show</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="quant_search_view" model="ir.ui.view">
|
||||
<field name="model">stock.quant</field>
|
||||
<field name="inherit_id" ref="stock.quant_search_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<!-- With the context set via the field location_id
|
||||
odoo will set default_location_id to [self]
|
||||
So, to make it work, we also inherit default_get
|
||||
to convert from list of 1 ID to an ID -->
|
||||
<field name="location_id" position="attributes">
|
||||
<attribute name="context">{'search_location': self}</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="stock_quant_tree_simple" model="ir.ui.view">
|
||||
<field name="model">stock.quant</field>
|
||||
<field name="priority">100</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree edit="0" create="0" delete="0">
|
||||
<field name="location_id"/>
|
||||
<field name="product_id" />
|
||||
<field name="lot_id" groups="stock.group_production_lot"/>
|
||||
<field name="owner_id" groups="stock.group_tracking_owner"/>
|
||||
<field name="quantity" sum="1"/>
|
||||
<field name="product_uom_id" string="Unit" groups="uom.group_uom"/>
|
||||
<field name="reserved_quantity" string="Reserved" sum="1" optional="show"/>
|
||||
<button type="object" name="action_stock_move_lines_reserved" string="Reservations" attrs="{'invisible': [('reserved_quantity', '=', 0)]}"/>
|
||||
<field name="available_quantity" string="Available" sum="1" optional="show"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!--
|
||||
<record id="view_stock_quant_tree_editable" model="ir.ui.view">
|
||||
<field name="model">stock.quant</field>
|
||||
<field name="inherit_id" ref="stock.view_stock_quant_tree_editable"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="reserved_quantity" position="after">
|
||||
<button type="object" name="action_stock_move_lines_reserved" string="Reservations" attrs="{'invisible': [('reserved_quantity', '=', 0)]}"/>
|
||||
<field name="available_quantity" sum="1" optional="show"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
-->
|
||||
|
||||
<!-- mig to v16 ?
|
||||
<record id="view_stock_quant_form" model="ir.ui.view">
|
||||
<field name="name">stock.usability.quant.form</field>
|
||||
<field name="model">stock.quant</field>
|
||||
<field name="inherit_id" ref="stock.view_stock_quant_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<div name="button_box" position="inside">
|
||||
<button class="oe_stat_button" icon="fa-arrows-v" type="object" name="action_stock_move_lines_reserved" string="Reservations"/>
|
||||
</div>
|
||||
<xpath expr="//field[@name='reserved_quantity']/.." position="after">
|
||||
<label for="available_quantity" />
|
||||
<div class="o_row">
|
||||
<field name="available_quantity"/>
|
||||
<field name="product_uom_id" groups="uom.group_uom"/>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
-->
|
||||
|
||||
<!-- more detailed stock.move tree view when using the button from product form -->
|
||||
<!-- TODO TEST
|
||||
<record id="stock.act_product_stock_move_open" model="ir.actions.act_window">
|
||||
<field name="view_id" ref="stock.view_move_tree"/>
|
||||
</record> -->
|
||||
|
||||
<!-- Rename menu entry Locations -> Quants -->
|
||||
<record id="stock.menu_valuation" model="ir.ui.menu">
|
||||
<field name="name">Quants</field>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
||||
29
stock_usability_akretion/views/stock_warehouse.xml
Normal file
29
stock_usability_akretion/views/stock_warehouse.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2014-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).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
|
||||
<record id="view_warehouse" model="ir.ui.view">
|
||||
<field name="name">stock.usability.warehouse.form</field>
|
||||
<field name="model">stock.warehouse</field>
|
||||
<field name="inherit_id" ref="stock.view_warehouse" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='out_type_id']/.." position="after">
|
||||
<group name="routes" string="Routes">
|
||||
<field name="route_ids" widget="many2many_tags"/>
|
||||
<field name="crossdock_route_id"/>
|
||||
<field name="reception_route_id"/>
|
||||
<field name="delivery_route_id"/>
|
||||
<field name="resupply_route_ids"/>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2014-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).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
|
||||
<record id="view_warehouse_orderpoint_form" model="ir.ui.view">
|
||||
<field name="model">stock.warehouse.orderpoint</field>
|
||||
<field name="inherit_id" ref="stock.view_warehouse_orderpoint_form" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="product_id" position="after">
|
||||
<field name="trigger"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_warehouse_orderpoint_tree_editable" model="ir.ui.view">
|
||||
<field name="model">stock.warehouse.orderpoint</field>
|
||||
<field name="inherit_id" ref="stock.view_warehouse_orderpoint_tree_editable" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="trigger" position="attributes">
|
||||
<attribute name="optional">show</attribute>
|
||||
</field>
|
||||
<field name="product_id" position="after">
|
||||
<field name="product_barcode" optional="hide"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user