mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
124
stock_request/README.rst
Normal file
124
stock_request/README.rst
Normal file
@@ -0,0 +1,124 @@
|
||||
=============
|
||||
Stock Request
|
||||
=============
|
||||
|
||||
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
|
||||
:target: https://odoo-community.org/page/development-status
|
||||
:alt: Beta
|
||||
.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png
|
||||
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
|
||||
:alt: License: LGPL-3
|
||||
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstock--logistics--warehouse-lightgray.png?logo=github
|
||||
:target: https://github.com/OCA/stock-logistics-warehouse/tree/12.0/stock_request
|
||||
:alt: OCA/stock-logistics-warehouse
|
||||
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
|
||||
:target: https://translation.odoo-community.org/projects/stock-logistics-warehouse-12-0/stock-logistics-warehouse-12-0-stock_request
|
||||
:alt: Translate me on Weblate
|
||||
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
|
||||
:target: https://runbot.odoo-community.org/runbot/153/12.0
|
||||
:alt: Try me on Runbot
|
||||
|
||||
|badge1| |badge2| |badge3| |badge4| |badge5|
|
||||
|
||||
This module was written to allow users to request products that are
|
||||
frequently stocked by the company, to be transferred to their chosen location.
|
||||
|
||||
**Table of contents**
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
To configure this module:
|
||||
|
||||
* Go to Stock Requests > Settings
|
||||
|
||||
Users should be assigned to the groups 'Stock Request / User' or 'Stock
|
||||
Request / Manager'.
|
||||
|
||||
## Group Stock Request / User
|
||||
|
||||
* Can see her/his own Stock Requests, and others that she/he's been granted
|
||||
permission to follow.
|
||||
|
||||
* Can create/update only her/his Stock Requests.
|
||||
|
||||
## Group Stock Request / Manager
|
||||
|
||||
* Can fully manage all Stock Requests
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
## Creation
|
||||
|
||||
* Go to 'Stock Requests / Stock Requests' and create a new Request.
|
||||
* Indicate a product, quantity and location.
|
||||
* Press 'Confirm'.
|
||||
|
||||
Upon confirmation the request will be evaluated using the procurement rules
|
||||
for the selected location.
|
||||
|
||||
In case that transfers are created, the user will be able to access to them
|
||||
from the button 'Transfers' available in the Stock Request.
|
||||
|
||||
## Cancel
|
||||
|
||||
When the user cancels a Stock Request, the related pending stock moves will be
|
||||
also cancelled.
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/stock-logistics-warehouse/issues>`_.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us smashing it by providing a detailed and welcomed
|
||||
`feedback <https://github.com/OCA/stock-logistics-warehouse/issues/new?body=module:%20stock_request%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
|
||||
|
||||
Do not contact contributors directly about support or help with technical issues.
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Authors
|
||||
~~~~~~~
|
||||
|
||||
* Eficent
|
||||
|
||||
Contributors
|
||||
~~~~~~~~~~~~
|
||||
|
||||
* Jordi Ballester (EFICENT) <jordi.ballester@eficent.com>.
|
||||
* Enric Tobella <etobella@creublanca.es>
|
||||
* Atte Isopuro <atte.isopuro@avoin.systems>
|
||||
* Lois Rilo <lois.rilo@eficent.com>
|
||||
* Raul Martin <raul.martin@braintec-group.com>
|
||||
* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
|
||||
* `Open Source Integrators <https://www.opensourceintegrators.com>`_
|
||||
|
||||
* Maxime Chambreuil <mchambreuil@opensourceintegrators.com>
|
||||
* Steve Campbell <scampbell@opensourceintegrators.com>
|
||||
|
||||
Maintainers
|
||||
~~~~~~~~~~~
|
||||
|
||||
This module is maintained by the OCA.
|
||||
|
||||
.. image:: https://odoo-community.org/logo.png
|
||||
:alt: Odoo Community Association
|
||||
:target: https://odoo-community.org
|
||||
|
||||
OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||
mission is to support the collaborative development of Odoo features and
|
||||
promote its widespread use.
|
||||
|
||||
This module is part of the `OCA/stock-logistics-warehouse <https://github.com/OCA/stock-logistics-warehouse/tree/12.0/stock_request>`_ project on GitHub.
|
||||
|
||||
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
|
||||
1
stock_request/__init__.py
Normal file
1
stock_request/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import models
|
||||
27
stock_request/__manifest__.py
Normal file
27
stock_request/__manifest__.py
Normal file
@@ -0,0 +1,27 @@
|
||||
# Copyright 2017-2020 ForgeFlow, S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
{
|
||||
"name": "Stock Request",
|
||||
"summary": "Internal request for stock",
|
||||
"version": "13.0.1.0.0",
|
||||
"license": "LGPL-3",
|
||||
"website": "https://github.com/stock-logistics-warehouse",
|
||||
"author": "ForgeFlow, Odoo Community Association (OCA)",
|
||||
"category": "Warehouse Management",
|
||||
"depends": ["stock"],
|
||||
"data": [
|
||||
"security/stock_request_security.xml",
|
||||
"security/ir.model.access.csv",
|
||||
"views/product.xml",
|
||||
"views/stock_request_views.xml",
|
||||
"views/stock_request_allocation_views.xml",
|
||||
"views/stock_move_views.xml",
|
||||
"views/stock_picking_views.xml",
|
||||
"views/stock_request_order_views.xml",
|
||||
"views/res_config_settings_views.xml",
|
||||
"views/stock_request_menu.xml",
|
||||
"data/stock_request_sequence_data.xml",
|
||||
],
|
||||
"installable": True,
|
||||
}
|
||||
20
stock_request/data/stock_request_sequence_data.xml
Normal file
20
stock_request/data/stock_request_sequence_data.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo noupdate="1">
|
||||
|
||||
<record id="seq_stock_request" model="ir.sequence">
|
||||
<field name="name">Stock Request</field>
|
||||
<field name="code">stock.request</field>
|
||||
<field name="prefix">SR/</field>
|
||||
<field name="padding">5</field>
|
||||
<field name="company_id" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record id="seq_stock_request_order" model="ir.sequence">
|
||||
<field name="name">Stock Request Order</field>
|
||||
<field name="code">stock.request.order</field>
|
||||
<field name="prefix">SRO/</field>
|
||||
<field name="padding">5</field>
|
||||
<field name="company_id" eval="False"/>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
1020
stock_request/i18n/ca.po
Normal file
1020
stock_request/i18n/ca.po
Normal file
File diff suppressed because it is too large
Load Diff
1062
stock_request/i18n/de.po
Normal file
1062
stock_request/i18n/de.po
Normal file
File diff suppressed because it is too large
Load Diff
1021
stock_request/i18n/el_GR.po
Normal file
1021
stock_request/i18n/el_GR.po
Normal file
File diff suppressed because it is too large
Load Diff
1073
stock_request/i18n/es.po
Normal file
1073
stock_request/i18n/es.po
Normal file
File diff suppressed because it is too large
Load Diff
1021
stock_request/i18n/es_ES.po
Normal file
1021
stock_request/i18n/es_ES.po
Normal file
File diff suppressed because it is too large
Load Diff
1020
stock_request/i18n/eu.po
Normal file
1020
stock_request/i18n/eu.po
Normal file
File diff suppressed because it is too large
Load Diff
1020
stock_request/i18n/fi.po
Normal file
1020
stock_request/i18n/fi.po
Normal file
File diff suppressed because it is too large
Load Diff
1020
stock_request/i18n/fr.po
Normal file
1020
stock_request/i18n/fr.po
Normal file
File diff suppressed because it is too large
Load Diff
1021
stock_request/i18n/fr_CH.po
Normal file
1021
stock_request/i18n/fr_CH.po
Normal file
File diff suppressed because it is too large
Load Diff
1021
stock_request/i18n/fr_FR.po
Normal file
1021
stock_request/i18n/fr_FR.po
Normal file
File diff suppressed because it is too large
Load Diff
1020
stock_request/i18n/gl.po
Normal file
1020
stock_request/i18n/gl.po
Normal file
File diff suppressed because it is too large
Load Diff
1021
stock_request/i18n/hr.po
Normal file
1021
stock_request/i18n/hr.po
Normal file
File diff suppressed because it is too large
Load Diff
1022
stock_request/i18n/hr_HR.po
Normal file
1022
stock_request/i18n/hr_HR.po
Normal file
File diff suppressed because it is too large
Load Diff
1020
stock_request/i18n/it.po
Normal file
1020
stock_request/i18n/it.po
Normal file
File diff suppressed because it is too large
Load Diff
1020
stock_request/i18n/nl.po
Normal file
1020
stock_request/i18n/nl.po
Normal file
File diff suppressed because it is too large
Load Diff
1021
stock_request/i18n/nl_NL.po
Normal file
1021
stock_request/i18n/nl_NL.po
Normal file
File diff suppressed because it is too large
Load Diff
1020
stock_request/i18n/pt.po
Normal file
1020
stock_request/i18n/pt.po
Normal file
File diff suppressed because it is too large
Load Diff
1021
stock_request/i18n/pt_BR.po
Normal file
1021
stock_request/i18n/pt_BR.po
Normal file
File diff suppressed because it is too large
Load Diff
1021
stock_request/i18n/ro.po
Normal file
1021
stock_request/i18n/ro.po
Normal file
File diff suppressed because it is too large
Load Diff
1022
stock_request/i18n/ru.po
Normal file
1022
stock_request/i18n/ru.po
Normal file
File diff suppressed because it is too large
Load Diff
1021
stock_request/i18n/sl.po
Normal file
1021
stock_request/i18n/sl.po
Normal file
File diff suppressed because it is too large
Load Diff
992
stock_request/i18n/stock_request.pot
Normal file
992
stock_request/i18n/stock_request.pot
Normal file
@@ -0,0 +1,992 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * stock_request
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 12.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"Last-Translator: <>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_move_line.py:20
|
||||
#, python-format
|
||||
msgid "<li><b>%s</b>: Transferred quantity %s %s</li>"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__message_needaction
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__message_needaction
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__message_needaction
|
||||
msgid "Action Needed"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.res_config_settings_view_form
|
||||
msgid "Activates Stock Request Orders"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__activity_ids
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__activity_ids
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__activity_ids
|
||||
msgid "Activities"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__activity_state
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__activity_state
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__activity_state
|
||||
msgid "Activity State"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.res_config_settings_view_form
|
||||
msgid "Add State to Stock Request and Stock Request Orders if activated."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_allocation__allocated_product_qty
|
||||
msgid "Allocated Quantity"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.res_config_settings_view_form
|
||||
msgid "Allow All Locations Types"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_res_company__stock_request_allow_virtual_loc
|
||||
#: model:ir.model.fields,field_description:stock_request.field_res_config_settings__stock_request_allow_virtual_loc
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__allow_virtual_location
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__allow_virtual_location
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__allow_virtual_location
|
||||
msgid "Allow Virtual locations on Stock Requests"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.res_config_settings_view_form
|
||||
msgid "Analytic"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.res_config_settings_view_form
|
||||
msgid "Analytic accounting in Stock Requests"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.stock_request_search
|
||||
msgid "Archived"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__message_attachment_count
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__message_attachment_count
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__message_attachment_count
|
||||
msgid "Attachment Count"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.res_config_settings_view_form
|
||||
msgid "By default only internal and transit locations are allowed in Stock Request and Orders."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.stock_request_order_form
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.view_stock_request_form
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.actions.act_window,help:stock_request.action_stock_request_form
|
||||
msgid "Click to add a Stock Request."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model,name:stock_request.model_res_company
|
||||
msgid "Companies"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__company_id
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__company_id
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_allocation__company_id
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__company_id
|
||||
msgid "Company"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_request.py:189
|
||||
#, python-format
|
||||
msgid "Company must be equal to the order"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model,name:stock_request.model_res_config_settings
|
||||
msgid "Config Settings"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.stock_request_order_form
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.view_stock_request_form
|
||||
msgid "Confirm"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__create_uid
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_allocation__create_uid
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__create_uid
|
||||
msgid "Created by"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__create_date
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_allocation__create_date
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__create_date
|
||||
msgid "Created on"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request__expected_date
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request_order__expected_date
|
||||
msgid "Date when you expect to receive the goods."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__picking_count
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__picking_count
|
||||
msgid "Delivery Orders"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__display_name
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__display_name
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_allocation__display_name
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__display_name
|
||||
msgid "Display Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.view_stock_request_form
|
||||
msgid "Done"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.res_config_settings_view_form
|
||||
msgid "Enable Analytic Accounting in Stock Requests"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.res_config_settings_view_form
|
||||
msgid "Enable Orders"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.res_config_settings_view_form
|
||||
msgid "Enable Stock Requests Kanban cards"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.res_config_settings_view_form
|
||||
msgid "Enable Stock Requests for Purchases"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.res_config_settings_view_form
|
||||
msgid "Enable Submitted State"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__expected_date
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__expected_date
|
||||
msgid "Expected Date"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_request.py:196
|
||||
#, python-format
|
||||
msgid "Expected date must be equal to the order"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__message_follower_ids
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__message_follower_ids
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__message_follower_ids
|
||||
msgid "Followers"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__message_channel_ids
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__message_channel_ids
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__message_channel_ids
|
||||
msgid "Followers (Channels)"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__message_partner_ids
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__message_partner_ids
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__message_partner_ids
|
||||
msgid "Followers (Partners)"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.stock_request_search
|
||||
msgid "Group By"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_res_config_settings__group_stock_request_order
|
||||
msgid "Group Stock Request Order"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__id
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__id
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_allocation__id
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__id
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request__message_unread
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request_abstract__message_unread
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request_order__message_unread
|
||||
msgid "If checked new messages require your attention."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request__message_needaction
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request_abstract__message_needaction
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request_order__message_needaction
|
||||
msgid "If checked, new messages require your attention."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request__message_has_error
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request_abstract__message_has_error
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request_order__message_has_error
|
||||
msgid "If checked, some messages have a delivery error."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model,name:stock_request.model_stock_location
|
||||
msgid "Inventory Locations"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model,name:stock_request.model_stock_location_route
|
||||
msgid "Inventory Routes"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__message_is_follower
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__message_is_follower
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__message_is_follower
|
||||
msgid "Is Follower"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.stock_request_order_form
|
||||
msgid "Items"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.res_config_settings_view_form
|
||||
msgid "Kanban"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request____last_update
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract____last_update
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_allocation____last_update
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__write_uid
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_allocation__write_uid
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__write_date
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_allocation__write_date
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__location_id
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__location_id
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__location_id
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.stock_request_search
|
||||
msgid "Location"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_request.py:172
|
||||
#, python-format
|
||||
msgid "Location must be equal to the order"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__message_main_attachment_id
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__message_main_attachment_id
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__message_main_attachment_id
|
||||
msgid "Main Attachment"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.ui.menu,name:stock_request.menu_stock_request_master_data
|
||||
msgid "Master Data"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__message_has_error
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__message_has_error
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__message_has_error
|
||||
msgid "Message Delivery error"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__message_ids
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__message_ids
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__message_ids
|
||||
msgid "Messages"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request__procurement_group_id
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request_abstract__procurement_group_id
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request_order__procurement_group_id
|
||||
msgid "Moves created through this stock request will be put in this procurement group. If none is given, the moves generated by procurement rules will be grouped into one big picking."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__name
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__name
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__name
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: sql_constraint:stock.request:0
|
||||
#: sql_constraint:stock.request.abstract:0
|
||||
msgid "Name must be unique"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__activity_date_deadline
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__activity_date_deadline
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__activity_date_deadline
|
||||
msgid "Next Activity Deadline"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__activity_summary
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__activity_summary
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__activity_summary
|
||||
msgid "Next Activity Summary"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__activity_type_id
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__activity_type_id
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__activity_type_id
|
||||
msgid "Next Activity Type"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__message_needaction_counter
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__message_needaction_counter
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__message_needaction_counter
|
||||
msgid "Number of Actions"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__message_has_error_counter
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__message_has_error_counter
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__message_has_error_counter
|
||||
msgid "Number of error"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request__message_needaction_counter
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request_abstract__message_needaction_counter
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request_order__message_needaction_counter
|
||||
msgid "Number of messages which requires an action"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request__message_has_error_counter
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request_abstract__message_has_error_counter
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request_order__message_has_error_counter
|
||||
msgid "Number of messages with delivery error"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request__message_unread_counter
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request_abstract__message_unread_counter
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request_order__message_unread_counter
|
||||
msgid "Number of unread messages"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_request_order.py:267
|
||||
#, python-format
|
||||
msgid "Only orders on draft state can be unlinked"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_request.py:334
|
||||
#, python-format
|
||||
msgid "Only requests on draft state can be unlinked"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_allocation__open_product_qty
|
||||
msgid "Open Quantity"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.ui.menu,name:stock_request.menu_stock_request_operations
|
||||
msgid "Operations"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__order_id
|
||||
msgid "Order"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.res_config_settings_view_form
|
||||
msgid "Orders & Configuration"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: selection:stock.request,activity_state:0
|
||||
#: selection:stock.request.abstract,activity_state:0
|
||||
#: selection:stock.request.order,activity_state:0
|
||||
msgid "Overdue"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__picking_ids
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__picking_ids
|
||||
msgid "Pickings"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: selection:stock.request,activity_state:0
|
||||
#: selection:stock.request.abstract,activity_state:0
|
||||
#: selection:stock.request.order,activity_state:0
|
||||
msgid "Planned"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model,name:stock_request.model_procurement_group
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__procurement_group_id
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__procurement_group_id
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__procurement_group_id
|
||||
msgid "Procurement Group"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_request.py:182
|
||||
#, python-format
|
||||
msgid "Procurement group must be equal to the order"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__product_id
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__product_id
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_allocation__product_id
|
||||
msgid "Product"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model,name:stock_request.model_stock_move_line
|
||||
msgid "Product Moves (Stock Move Line)"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__product_uom_id
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__product_uom_id
|
||||
msgid "Product Unit of Measure"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.res_config_settings_view_form
|
||||
msgid "Purchases"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__qty_done
|
||||
msgid "Qty Done"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__qty_in_progress
|
||||
msgid "Qty In Progress"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__product_uom_qty
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__product_uom_qty
|
||||
msgid "Quantity"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request__qty_done
|
||||
msgid "Quantity completed"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request__qty_in_progress
|
||||
msgid "Quantity in progress."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request__product_qty
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request_abstract__product_qty
|
||||
msgid "Quantity in the default UoM of the product"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request_allocation__requested_product_uom_qty
|
||||
msgid "Quantity of the stock request allocated to the stock move, in the UoM of the Stock Request"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request_allocation__allocated_product_qty
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request_allocation__requested_product_qty
|
||||
msgid "Quantity of the stock request allocated to the stock move, in the default UoM of the product"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request__product_uom_qty
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request_abstract__product_uom_qty
|
||||
msgid "Quantity, specified in the unit of measure indicated in the request."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__product_qty
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__product_qty
|
||||
msgid "Real Quantity"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_move_line.py:12
|
||||
#, python-format
|
||||
msgid "Receipt confirmation %s for your Request %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: selection:stock.request,picking_policy:0
|
||||
#: selection:stock.request.order,picking_policy:0
|
||||
msgid "Receive all products at once"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: selection:stock.request,picking_policy:0
|
||||
#: selection:stock.request.order,picking_policy:0
|
||||
msgid "Receive each product when available"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.actions.server,name:stock_request.action_template_generate_stock_request_orders
|
||||
#: model:ir.actions.server,name:stock_request.action_variant_generate_stock_request_orders
|
||||
msgid "Request Stock"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_allocation__requested_product_qty
|
||||
msgid "Requested Quantity"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_allocation__requested_product_uom_qty
|
||||
msgid "Requested Quantity (UoM)"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__requested_by
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__requested_by
|
||||
msgid "Requested by"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_request.py:158
|
||||
#, python-format
|
||||
msgid "Requested by must be equal to the order"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__activity_user_id
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__activity_user_id
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__activity_user_id
|
||||
msgid "Responsible User"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__route_id
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__route_id
|
||||
msgid "Route"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__route_ids
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__route_ids
|
||||
msgid "Routes"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.stock_request_order_form
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.view_stock_request_form
|
||||
msgid "Set to Draft"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.actions.act_window,name:stock_request.action_stock_request_config
|
||||
#: model:ir.ui.menu,name:stock_request.menu_stock_request_config
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__picking_policy
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__picking_policy
|
||||
msgid "Shipping Policy"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__state
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__state
|
||||
msgid "Status"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request__activity_state
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request_abstract__activity_state
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request_order__activity_state
|
||||
msgid "Status based on activities\n"
|
||||
"Overdue: Due date is already passed\n"
|
||||
"Today: Activity date is today\n"
|
||||
"Planned: Future activities."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model,name:stock_request.model_stock_move
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_allocation__stock_move_id
|
||||
msgid "Stock Move"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__move_ids
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__move_ids
|
||||
msgid "Stock Moves"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model,name:stock_request.model_stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_allocation__stock_request_id
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__stock_request_ids
|
||||
#: model:ir.module.category,name:stock_request.module_category_stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.stock_request_order_form
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.view_stock_request_form
|
||||
msgid "Stock Request"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_picking__stock_request_count
|
||||
msgid "Stock Request #"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model,name:stock_request.model_stock_request_allocation
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_move__allocation_ids
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__allocation_ids
|
||||
msgid "Stock Request Allocation"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.view_move_form
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.view_move_picking_form
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.view_stock_request_allocation_form
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.view_stock_request_allocation_tree
|
||||
msgid "Stock Request Allocations"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:res.groups,name:stock_request.group_stock_request_manager
|
||||
msgid "Stock Request Manager"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model,name:stock_request.model_stock_request_order
|
||||
#: model:res.groups,name:stock_request.group_stock_request_order
|
||||
msgid "Stock Request Order"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.actions.act_window,name:stock_request.stock_request_order_action
|
||||
#: model:ir.ui.menu,name:stock_request.stock_request_order_menu
|
||||
msgid "Stock Request Orders"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model,name:stock_request.model_stock_request_abstract
|
||||
msgid "Stock Request Template"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:res.groups,name:stock_request.group_stock_request_user
|
||||
msgid "Stock Request User"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: sql_constraint:stock.request:0
|
||||
#: sql_constraint:stock.request.order:0
|
||||
msgid "Stock Request name must be unique"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_request_abstract.py:165
|
||||
#, python-format
|
||||
msgid "Stock Request product quantity has to be strictly positive."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.actions.act_window,name:stock_request.action_stock_request_form
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_move__stock_request_ids
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_picking__stock_request_ids
|
||||
#: model:ir.ui.menu,name:stock_request.menu_stock_request
|
||||
#: model:ir.ui.menu,name:stock_request.menu_stock_request_root
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.stock_request_order_form
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.stock_request_search
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.view_picking_form
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.view_stock_request_form
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.view_stock_request_tree
|
||||
msgid "Stock Requests"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_res_config_settings__module_stock_request_analytic
|
||||
msgid "Stock Requests Analytic integration"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_res_config_settings__module_stock_request_kanban
|
||||
msgid "Stock Requests Kanban integration"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.stock_request_search
|
||||
msgid "Stock Requests Search"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_res_config_settings__module_stock_request_purchase
|
||||
msgid "Stock Requests for Purchases"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model,name:stock_request.model_stock_rule
|
||||
msgid "Stock Rule"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.stock_request_order_form
|
||||
msgid "Stock request"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__stock_request_count
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.stock_request_order_tree
|
||||
msgid "Stock requests"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_res_config_settings__module_stock_request_submit
|
||||
msgid "Submitted state in Stock Requests"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_move.py:38
|
||||
#: code:addons/stock_request/models/stock_request_order.py:284
|
||||
#, python-format
|
||||
msgid "The company of the stock request must match with that of the location."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_request_order.py:275
|
||||
#, python-format
|
||||
msgid "The company of the stock request must match with that of the warehouse."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_move_line.py:15
|
||||
#, python-format
|
||||
msgid "The following requested items from Stock Request %s have now been received in %s using Picking %s:"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_request.py:206
|
||||
#, python-format
|
||||
msgid "The picking policy must be equal to the order"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_request_order.py:293
|
||||
#, python-format
|
||||
msgid "This action only works in the context of products"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: selection:stock.request,activity_state:0
|
||||
#: selection:stock.request.abstract,activity_state:0
|
||||
#: selection:stock.request.order,activity_state:0
|
||||
msgid "Today"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model,name:stock_request.model_stock_picking
|
||||
msgid "Transfer"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.stock_request_order_form
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.view_stock_request_form
|
||||
msgid "Transfers"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_request_order.py:314
|
||||
#, python-format
|
||||
msgid "Unfortunately it seems you do not have the necessary rights for creating stock requests. Please contact your administrator."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__message_unread
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__message_unread
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__message_unread
|
||||
msgid "Unread Messages"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__message_unread_counter
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__message_unread_counter
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__message_unread_counter
|
||||
msgid "Unread Messages Counter"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_allocation__product_uom_id
|
||||
msgid "UoM"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.res_config_settings_view_form
|
||||
msgid "Use Kanban cards for consumable products"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.res_config_settings_view_form
|
||||
msgid "Use Purchases with Stock Requests"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model,name:stock_request.model_stock_warehouse
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__warehouse_id
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__warehouse_id
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__warehouse_id
|
||||
#: model_terms:ir.ui.view,arch_db:stock_request.stock_request_search
|
||||
msgid "Warehouse"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_request.py:165
|
||||
#, python-format
|
||||
msgid "Warehouse must be equal to the order"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request__website_message_ids
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_abstract__website_message_ids
|
||||
#: model:ir.model.fields,field_description:stock_request.field_stock_request_order__website_message_ids
|
||||
msgid "Website Messages"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request__website_message_ids
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request_abstract__website_message_ids
|
||||
#: model:ir.model.fields,help:stock_request.field_stock_request_order__website_message_ids
|
||||
msgid "Website communication history"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_location.py:24
|
||||
#, python-format
|
||||
msgid "You cannot change the company of the location, as it is already assigned to stock request orders that belong to another company."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_location.py:17
|
||||
#, python-format
|
||||
msgid "You cannot change the company of the location, as it is already assigned to stock requests that belong to another company."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_location_route.py:17
|
||||
#, python-format
|
||||
msgid "You cannot change the company of the route, as it is already assigned to stock requests that belong to another company."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_warehouse.py:26
|
||||
#, python-format
|
||||
msgid "You cannot change the company of the warehouse, as it is already assigned to stock request orders that belong to another company."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_warehouse.py:18
|
||||
#, python-format
|
||||
msgid "You cannot change the company of the warehouse, as it is already assigned to stock requests that belong to another company."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_request_abstract.py:138
|
||||
#, python-format
|
||||
msgid "You have entered a location that is assigned to another company."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_request_abstract.py:133
|
||||
#, python-format
|
||||
msgid "You have entered a product that is assigned to another company."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_request_abstract.py:147
|
||||
#, python-format
|
||||
msgid "You have entered a route that is assigned to another company."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_request_abstract.py:142
|
||||
#, python-format
|
||||
msgid "You have entered a warehouse that is assigned to another company."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_request
|
||||
#: code:addons/stock_request/models/stock_request_abstract.py:157
|
||||
#, python-format
|
||||
msgid "You have to select a product unit of measure in the same category than the default unit of measure of the product"
|
||||
msgstr ""
|
||||
|
||||
1020
stock_request/i18n/tr.po
Normal file
1020
stock_request/i18n/tr.po
Normal file
File diff suppressed because it is too large
Load Diff
1021
stock_request/i18n/tr_TR.po
Normal file
1021
stock_request/i18n/tr_TR.po
Normal file
File diff suppressed because it is too large
Load Diff
1021
stock_request/i18n/vi_VN.po
Normal file
1021
stock_request/i18n/vi_VN.po
Normal file
File diff suppressed because it is too large
Load Diff
1037
stock_request/i18n/zh_CN.po
Normal file
1037
stock_request/i18n/zh_CN.po
Normal file
File diff suppressed because it is too large
Load Diff
14
stock_request/models/__init__.py
Normal file
14
stock_request/models/__init__.py
Normal file
@@ -0,0 +1,14 @@
|
||||
from . import procurement_group
|
||||
from . import stock_request_abstract
|
||||
from . import stock_request
|
||||
from . import stock_request_allocation
|
||||
from . import stock_request_order
|
||||
from . import stock_move
|
||||
from . import stock_picking
|
||||
from . import stock_rule
|
||||
from . import stock_move_line
|
||||
from . import res_config_settings
|
||||
from . import stock_warehouse
|
||||
from . import stock_location
|
||||
from . import stock_location_route
|
||||
from . import res_company
|
||||
29
stock_request/models/procurement_group.py
Normal file
29
stock_request/models/procurement_group.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# Copyright (C) 2019 Open Source Integrators
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
|
||||
from odoo import api, models
|
||||
|
||||
|
||||
class ProcurementGroup(models.Model):
|
||||
_inherit = "procurement.group"
|
||||
|
||||
@api.model
|
||||
def run(self, procurements):
|
||||
indexes_to_pop = []
|
||||
new_procs = []
|
||||
for i, procurement in enumerate(procurements):
|
||||
if "stock_request_id" in procurement.values and procurement.values.get(
|
||||
"stock_request_id"
|
||||
):
|
||||
req = self.env["stock.request"].browse(
|
||||
procurement.values.get("stock_request_id")
|
||||
)
|
||||
if req.order_id:
|
||||
new_procs.append(procurement._replace(origin=req.order_id.name))
|
||||
indexes_to_pop.append(i)
|
||||
if new_procs:
|
||||
indexes_to_pop.reverse()
|
||||
for index in indexes_to_pop:
|
||||
procurements.pop(index)
|
||||
procurements.extend(new_procs)
|
||||
return super().run(procurements)
|
||||
14
stock_request/models/res_company.py
Normal file
14
stock_request/models/res_company.py
Normal file
@@ -0,0 +1,14 @@
|
||||
# Copyright 2018 Eficent Business and IT Consulting Services S.L.
|
||||
# (http://www.eficent.com)
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class ResCompany(models.Model):
|
||||
_inherit = "res.company"
|
||||
|
||||
stock_request_allow_virtual_loc = fields.Boolean(
|
||||
string="Allow Virtual locations on Stock Requests"
|
||||
)
|
||||
38
stock_request/models/res_config_settings.py
Normal file
38
stock_request/models/res_config_settings.py
Normal file
@@ -0,0 +1,38 @@
|
||||
# Copyright 2018 Creu Blanca
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class ResConfigSettings(models.TransientModel):
|
||||
_inherit = "res.config.settings"
|
||||
|
||||
group_stock_request_order = fields.Boolean(
|
||||
implied_group="stock_request.group_stock_request_order"
|
||||
)
|
||||
|
||||
module_stock_request_purchase = fields.Boolean(
|
||||
string="Stock Requests for Purchases"
|
||||
)
|
||||
|
||||
module_stock_request_kanban = fields.Boolean(
|
||||
string="Stock Requests Kanban integration"
|
||||
)
|
||||
|
||||
stock_request_allow_virtual_loc = fields.Boolean(
|
||||
related="company_id.stock_request_allow_virtual_loc", readonly=False
|
||||
)
|
||||
|
||||
module_stock_request_analytic = fields.Boolean(
|
||||
string="Stock Requests Analytic integration"
|
||||
)
|
||||
|
||||
module_stock_request_submit = fields.Boolean(
|
||||
string="Submitted state in Stock Requests"
|
||||
)
|
||||
|
||||
# Dependencies
|
||||
@api.onchange("stock_request_allow_virtual_loc")
|
||||
def _onchange_stock_request_allow_virtual_loc(self):
|
||||
if self.stock_request_allow_virtual_loc:
|
||||
self.group_stock_multi_locations = True
|
||||
45
stock_request/models/stock_location.py
Normal file
45
stock_request/models/stock_location.py
Normal file
@@ -0,0 +1,45 @@
|
||||
# Copyright 2018 Eficent Business and IT Consulting Services, S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
from odoo import _, api, models
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class StockLocation(models.Model):
|
||||
_inherit = "stock.location"
|
||||
|
||||
@api.constrains("company_id")
|
||||
def _check_company_stock_request(self):
|
||||
if any(
|
||||
rec.company_id
|
||||
and self.env["stock.request"].search(
|
||||
[("company_id", "!=", rec.company_id.id), ("location_id", "=", rec.id)],
|
||||
limit=1,
|
||||
)
|
||||
for rec in self
|
||||
):
|
||||
raise ValidationError(
|
||||
_(
|
||||
"You cannot change the company of the location, as it is "
|
||||
"already assigned to stock requests that belong to "
|
||||
"another company."
|
||||
)
|
||||
)
|
||||
if any(
|
||||
rec.company_id
|
||||
and self.env["stock.request.order"].search(
|
||||
[
|
||||
("company_id", "!=", rec.company_id.id),
|
||||
("warehouse_id", "=", rec.id),
|
||||
],
|
||||
limit=1,
|
||||
)
|
||||
for rec in self
|
||||
):
|
||||
raise ValidationError(
|
||||
_(
|
||||
"You cannot change the company of the location, as it is "
|
||||
"already assigned to stock request orders that belong to "
|
||||
"another company."
|
||||
)
|
||||
)
|
||||
27
stock_request/models/stock_location_route.py
Normal file
27
stock_request/models/stock_location_route.py
Normal file
@@ -0,0 +1,27 @@
|
||||
# Copyright 2018 Eficent Business and IT Consulting Services, S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
from odoo import _, api, models
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class StockLocationRoute(models.Model):
|
||||
_inherit = "stock.location.route"
|
||||
|
||||
@api.constrains("company_id")
|
||||
def _check_company_stock_request(self):
|
||||
if any(
|
||||
rec.company_id
|
||||
and self.env["stock.request"].search(
|
||||
[("company_id", "!=", rec.company_id.id), ("route_id", "=", rec.id)],
|
||||
limit=1,
|
||||
)
|
||||
for rec in self
|
||||
):
|
||||
raise ValidationError(
|
||||
_(
|
||||
"You cannot change the company of the route, as it is "
|
||||
"already assigned to stock requests that belong to "
|
||||
"another company."
|
||||
)
|
||||
)
|
||||
50
stock_request/models/stock_move.py
Normal file
50
stock_request/models/stock_move.py
Normal file
@@ -0,0 +1,50 @@
|
||||
# Copyright 2017-2020 ForgeFlow, S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class StockMove(models.Model):
|
||||
_inherit = "stock.move"
|
||||
|
||||
allocation_ids = fields.One2many(
|
||||
comodel_name="stock.request.allocation",
|
||||
inverse_name="stock_move_id",
|
||||
string="Stock Request Allocation",
|
||||
)
|
||||
|
||||
stock_request_ids = fields.One2many(
|
||||
comodel_name="stock.request",
|
||||
string="Stock Requests",
|
||||
compute="_compute_stock_request_ids",
|
||||
)
|
||||
|
||||
@api.depends("allocation_ids")
|
||||
def _compute_stock_request_ids(self):
|
||||
for rec in self:
|
||||
rec.stock_request_ids = rec.allocation_ids.mapped("stock_request_id")
|
||||
|
||||
def _merge_moves_fields(self):
|
||||
res = super(StockMove, self)._merge_moves_fields()
|
||||
res["allocation_ids"] = [(4, m.id) for m in self.mapped("allocation_ids")]
|
||||
return res
|
||||
|
||||
@api.constrains("company_id")
|
||||
def _check_company_stock_request(self):
|
||||
if any(
|
||||
self.env["stock.request.allocation"].search(
|
||||
[
|
||||
("company_id", "!=", rec.company_id.id),
|
||||
("stock_move_id", "=", rec.id),
|
||||
],
|
||||
limit=1,
|
||||
)
|
||||
for rec in self
|
||||
):
|
||||
raise ValidationError(
|
||||
_(
|
||||
"The company of the stock request must match with "
|
||||
"that of the location."
|
||||
)
|
||||
)
|
||||
65
stock_request/models/stock_move_line.py
Normal file
65
stock_request/models/stock_move_line.py
Normal file
@@ -0,0 +1,65 @@
|
||||
# Copyright 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0).
|
||||
|
||||
from odoo import _, api, models
|
||||
|
||||
|
||||
class StockMoveLine(models.Model):
|
||||
_inherit = "stock.move.line"
|
||||
|
||||
@api.model
|
||||
def _stock_request_confirm_done_message_content(self, message_data):
|
||||
title = _("Receipt confirmation %s for your Request %s") % (
|
||||
message_data["picking_name"],
|
||||
message_data["request_name"],
|
||||
)
|
||||
message = "<h3>%s</h3>" % title
|
||||
message += _(
|
||||
"The following requested items from Stock Request %s "
|
||||
"have now been received in %s using Picking %s:"
|
||||
) % (
|
||||
message_data["request_name"],
|
||||
message_data["location_name"],
|
||||
message_data["picking_name"],
|
||||
)
|
||||
message += "<ul>"
|
||||
message += _("<li><b>%s</b>: Transferred quantity %s %s</li>") % (
|
||||
message_data["product_name"],
|
||||
message_data["product_qty"],
|
||||
message_data["product_uom"],
|
||||
)
|
||||
message += "</ul>"
|
||||
return message
|
||||
|
||||
def _prepare_message_data(self, ml, request, allocated_qty):
|
||||
return {
|
||||
"request_name": request.name,
|
||||
"picking_name": ml.picking_id.name,
|
||||
"product_name": ml.product_id.name_get()[0][1],
|
||||
"product_qty": allocated_qty,
|
||||
"product_uom": ml.product_uom_id.name,
|
||||
"location_name": ml.location_dest_id.name_get()[0][1],
|
||||
}
|
||||
|
||||
def _action_done(self):
|
||||
res = super(StockMoveLine, self)._action_done()
|
||||
for ml in self.filtered(lambda m: m.exists() and m.move_id.allocation_ids):
|
||||
qty_done = ml.product_uom_id._compute_quantity(
|
||||
ml.qty_done, ml.product_id.uom_id
|
||||
)
|
||||
|
||||
# We do sudo because potentially the user that completes the move
|
||||
# may not have permissions for stock.request.
|
||||
to_allocate_qty = ml.qty_done
|
||||
for allocation in ml.move_id.allocation_ids:
|
||||
allocated_qty = 0.0
|
||||
if allocation.open_product_qty:
|
||||
allocated_qty = min(allocation.open_product_qty, qty_done)
|
||||
allocation.allocated_product_qty += allocated_qty
|
||||
to_allocate_qty -= allocated_qty
|
||||
request = allocation.stock_request_id
|
||||
message_data = self._prepare_message_data(ml, request, allocated_qty)
|
||||
message = self._stock_request_confirm_done_message_content(message_data)
|
||||
request.message_post(body=message, subtype="mail.mt_comment")
|
||||
request.check_done()
|
||||
return res
|
||||
39
stock_request/models/stock_picking.py
Normal file
39
stock_request/models/stock_picking.py
Normal file
@@ -0,0 +1,39 @@
|
||||
# Copyright 2017-2020 ForgeFlow, S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class StockPicking(models.Model):
|
||||
_inherit = "stock.picking"
|
||||
|
||||
stock_request_ids = fields.One2many(
|
||||
comodel_name="stock.request",
|
||||
string="Stock Requests",
|
||||
compute="_compute_stock_request_ids",
|
||||
)
|
||||
stock_request_count = fields.Integer(
|
||||
"Stock Request #", compute="_compute_stock_request_ids"
|
||||
)
|
||||
|
||||
@api.depends("move_lines")
|
||||
def _compute_stock_request_ids(self):
|
||||
for rec in self:
|
||||
rec.stock_request_ids = rec.move_lines.mapped("stock_request_ids")
|
||||
rec.stock_request_count = len(rec.stock_request_ids)
|
||||
|
||||
def action_view_stock_request(self):
|
||||
"""
|
||||
:return dict: dictionary value for created view
|
||||
"""
|
||||
action = self.env.ref("stock_request.action_stock_request_form").read()[0]
|
||||
|
||||
requests = self.mapped("stock_request_ids")
|
||||
if len(requests) > 1:
|
||||
action["domain"] = [("id", "in", requests.ids)]
|
||||
elif requests:
|
||||
action["views"] = [
|
||||
(self.env.ref("stock_request.view_stock_request_form").id, "form")
|
||||
]
|
||||
action["res_id"] = requests.id
|
||||
return action
|
||||
337
stock_request/models/stock_request.py
Normal file
337
stock_request/models/stock_request.py
Normal file
@@ -0,0 +1,337 @@
|
||||
# Copyright 2017-2020 ForgeFlow, S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import UserError, ValidationError
|
||||
from odoo.tools import float_compare
|
||||
|
||||
REQUEST_STATES = [
|
||||
("draft", "Draft"),
|
||||
("open", "In progress"),
|
||||
("done", "Done"),
|
||||
("cancel", "Cancelled"),
|
||||
]
|
||||
|
||||
|
||||
class StockRequest(models.Model):
|
||||
_name = "stock.request"
|
||||
_description = "Stock Request"
|
||||
_inherit = "stock.request.abstract"
|
||||
_order = "id desc"
|
||||
|
||||
def __get_request_states(self):
|
||||
return REQUEST_STATES
|
||||
|
||||
def _get_request_states(self):
|
||||
return self.__get_request_states()
|
||||
|
||||
def _get_default_requested_by(self):
|
||||
return self.env["res.users"].browse(self.env.uid)
|
||||
|
||||
@staticmethod
|
||||
def _get_expected_date():
|
||||
return fields.Datetime.now()
|
||||
|
||||
def _get_default_expected_date(self):
|
||||
if self.order_id:
|
||||
res = self.order_id.expected_date
|
||||
else:
|
||||
res = self._get_expected_date()
|
||||
return res
|
||||
|
||||
name = fields.Char(states={"draft": [("readonly", False)]})
|
||||
state = fields.Selection(
|
||||
selection=_get_request_states,
|
||||
string="Status",
|
||||
copy=False,
|
||||
default="draft",
|
||||
index=True,
|
||||
readonly=True,
|
||||
track_visibility="onchange",
|
||||
)
|
||||
requested_by = fields.Many2one(
|
||||
"res.users",
|
||||
"Requested by",
|
||||
required=True,
|
||||
track_visibility="onchange",
|
||||
default=lambda s: s._get_default_requested_by(),
|
||||
)
|
||||
expected_date = fields.Datetime(
|
||||
"Expected Date",
|
||||
default=lambda s: s._get_default_expected_date(),
|
||||
index=True,
|
||||
required=True,
|
||||
readonly=True,
|
||||
states={"draft": [("readonly", False)]},
|
||||
help="Date when you expect to receive the goods.",
|
||||
)
|
||||
picking_policy = fields.Selection(
|
||||
[
|
||||
("direct", "Receive each product when available"),
|
||||
("one", "Receive all products at once"),
|
||||
],
|
||||
string="Shipping Policy",
|
||||
required=True,
|
||||
readonly=True,
|
||||
states={"draft": [("readonly", False)]},
|
||||
default="direct",
|
||||
)
|
||||
move_ids = fields.One2many(
|
||||
comodel_name="stock.move",
|
||||
compute="_compute_move_ids",
|
||||
string="Stock Moves",
|
||||
readonly=True,
|
||||
)
|
||||
picking_ids = fields.One2many(
|
||||
"stock.picking",
|
||||
compute="_compute_picking_ids",
|
||||
string="Pickings",
|
||||
readonly=True,
|
||||
)
|
||||
qty_in_progress = fields.Float(
|
||||
"Qty In Progress",
|
||||
digits="Product Unit of Measure",
|
||||
readonly=True,
|
||||
compute="_compute_qty",
|
||||
store=True,
|
||||
help="Quantity in progress.",
|
||||
)
|
||||
qty_done = fields.Float(
|
||||
"Qty Done",
|
||||
digits="Product Unit of Measure",
|
||||
readonly=True,
|
||||
compute="_compute_qty",
|
||||
store=True,
|
||||
help="Quantity completed",
|
||||
)
|
||||
picking_count = fields.Integer(
|
||||
string="Delivery Orders", compute="_compute_picking_ids", readonly=True
|
||||
)
|
||||
allocation_ids = fields.One2many(
|
||||
comodel_name="stock.request.allocation",
|
||||
inverse_name="stock_request_id",
|
||||
string="Stock Request Allocation",
|
||||
)
|
||||
order_id = fields.Many2one("stock.request.order", readonly=True)
|
||||
warehouse_id = fields.Many2one(
|
||||
states={"draft": [("readonly", False)]}, readonly=True
|
||||
)
|
||||
location_id = fields.Many2one(
|
||||
states={"draft": [("readonly", False)]}, readonly=True
|
||||
)
|
||||
product_id = fields.Many2one(states={"draft": [("readonly", False)]}, readonly=True)
|
||||
product_uom_id = fields.Many2one(
|
||||
states={"draft": [("readonly", False)]}, readonly=True
|
||||
)
|
||||
product_uom_qty = fields.Float(
|
||||
states={"draft": [("readonly", False)]}, readonly=True
|
||||
)
|
||||
procurement_group_id = fields.Many2one(
|
||||
states={"draft": [("readonly", False)]}, readonly=True
|
||||
)
|
||||
company_id = fields.Many2one(states={"draft": [("readonly", False)]}, readonly=True)
|
||||
route_id = fields.Many2one(states={"draft": [("readonly", False)]}, readonly=True)
|
||||
|
||||
_sql_constraints = [
|
||||
("name_uniq", "unique(name, company_id)", "Stock Request name must be unique")
|
||||
]
|
||||
|
||||
@api.depends("allocation_ids")
|
||||
def _compute_move_ids(self):
|
||||
for request in self:
|
||||
request.move_ids = request.allocation_ids.mapped("stock_move_id")
|
||||
|
||||
@api.depends("allocation_ids")
|
||||
def _compute_picking_ids(self):
|
||||
for request in self:
|
||||
request.picking_count = 0
|
||||
request.picking_ids = self.env["stock.picking"]
|
||||
request.picking_ids = request.move_ids.filtered(
|
||||
lambda m: m.state != "cancel"
|
||||
).mapped("picking_id")
|
||||
request.picking_count = len(request.picking_ids)
|
||||
|
||||
@api.depends(
|
||||
"allocation_ids",
|
||||
"allocation_ids.stock_move_id.state",
|
||||
"allocation_ids.stock_move_id.move_line_ids",
|
||||
"allocation_ids.stock_move_id.move_line_ids.qty_done",
|
||||
)
|
||||
def _compute_qty(self):
|
||||
for request in self:
|
||||
done_qty = sum(request.allocation_ids.mapped("allocated_product_qty"))
|
||||
open_qty = sum(request.allocation_ids.mapped("open_product_qty"))
|
||||
request.qty_done = request.product_id.uom_id._compute_quantity(
|
||||
done_qty, request.product_uom_id
|
||||
)
|
||||
request.qty_in_progress = request.product_id.uom_id._compute_quantity(
|
||||
open_qty, request.product_uom_id
|
||||
)
|
||||
|
||||
@api.constrains("order_id", "requested_by")
|
||||
def check_order_requested_by(self):
|
||||
if self.order_id and self.order_id.requested_by != self.requested_by:
|
||||
raise ValidationError(_("Requested by must be equal to the order"))
|
||||
|
||||
@api.constrains("order_id", "warehouse_id")
|
||||
def check_order_warehouse_id(self):
|
||||
if self.order_id and self.order_id.warehouse_id != self.warehouse_id:
|
||||
raise ValidationError(_("Warehouse must be equal to the order"))
|
||||
|
||||
@api.constrains("order_id", "location_id")
|
||||
def check_order_location(self):
|
||||
if self.order_id and self.order_id.location_id != self.location_id:
|
||||
raise ValidationError(_("Location must be equal to the order"))
|
||||
|
||||
@api.constrains("order_id", "procurement_group_id")
|
||||
def check_order_procurement_group(self):
|
||||
if (
|
||||
self.order_id
|
||||
and self.order_id.procurement_group_id != self.procurement_group_id
|
||||
):
|
||||
raise ValidationError(_("Procurement group must be equal to the order"))
|
||||
|
||||
@api.constrains("order_id", "company_id")
|
||||
def check_order_company(self):
|
||||
if self.order_id and self.order_id.company_id != self.company_id:
|
||||
raise ValidationError(_("Company must be equal to the order"))
|
||||
|
||||
@api.constrains("order_id", "expected_date")
|
||||
def check_order_expected_date(self):
|
||||
if self.order_id and self.order_id.expected_date != self.expected_date:
|
||||
raise ValidationError(_("Expected date must be equal to the order"))
|
||||
|
||||
@api.constrains("order_id", "picking_policy")
|
||||
def check_order_picking_policy(self):
|
||||
if self.order_id and self.order_id.picking_policy != self.picking_policy:
|
||||
raise ValidationError(_("The picking policy must be equal to the order"))
|
||||
|
||||
def _action_confirm(self):
|
||||
self._action_launch_procurement_rule()
|
||||
self.state = "open"
|
||||
|
||||
def action_confirm(self):
|
||||
self._action_confirm()
|
||||
return True
|
||||
|
||||
def action_draft(self):
|
||||
self.write({"state": "draft"})
|
||||
return True
|
||||
|
||||
def action_cancel(self):
|
||||
self.mapped("move_ids")._action_cancel()
|
||||
self.state = "cancel"
|
||||
return True
|
||||
|
||||
def action_done(self):
|
||||
self.state = "done"
|
||||
if self.order_id:
|
||||
self.order_id.check_done()
|
||||
return True
|
||||
|
||||
def check_done(self):
|
||||
precision = self.env["decimal.precision"].precision_get(
|
||||
"Product Unit of Measure"
|
||||
)
|
||||
for request in self:
|
||||
allocated_qty = sum(request.allocation_ids.mapped("allocated_product_qty"))
|
||||
qty_done = request.product_id.uom_id._compute_quantity(
|
||||
allocated_qty, request.product_uom_id
|
||||
)
|
||||
if (
|
||||
float_compare(
|
||||
qty_done, request.product_uom_qty, precision_digits=precision
|
||||
)
|
||||
>= 0
|
||||
):
|
||||
request.action_done()
|
||||
return True
|
||||
|
||||
def _prepare_procurement_values(self, group_id=False):
|
||||
|
||||
""" Prepare specific key for moves or other components that
|
||||
will be created from a procurement rule
|
||||
coming from a stock request. This method could be override
|
||||
in order to add other custom key that could be used in
|
||||
move/po creation.
|
||||
"""
|
||||
return {
|
||||
"date_planned": self.expected_date,
|
||||
"warehouse_id": self.warehouse_id,
|
||||
"stock_request_allocation_ids": self.id,
|
||||
"group_id": group_id or self.procurement_group_id.id or False,
|
||||
"route_ids": self.route_id,
|
||||
"stock_request_id": self.id,
|
||||
}
|
||||
|
||||
def _skip_procurement(self):
|
||||
return self.state != "draft" or self.product_id.type not in ("consu", "product")
|
||||
|
||||
def _action_launch_procurement_rule(self):
|
||||
"""
|
||||
Launch procurement group run method with required/custom
|
||||
fields genrated by a
|
||||
stock request. procurement group will launch '_run_move',
|
||||
'_run_buy' or '_run_manufacture'
|
||||
depending on the stock request product rule.
|
||||
"""
|
||||
precision = self.env["decimal.precision"].precision_get(
|
||||
"Product Unit of Measure"
|
||||
)
|
||||
errors = []
|
||||
for request in self:
|
||||
if request._skip_procurement():
|
||||
continue
|
||||
qty = 0.0
|
||||
for move in request.move_ids.filtered(lambda r: r.state != "cancel"):
|
||||
qty += move.product_qty
|
||||
|
||||
if float_compare(qty, request.product_qty, precision_digits=precision) >= 0:
|
||||
continue
|
||||
|
||||
values = request._prepare_procurement_values(
|
||||
group_id=request.procurement_group_id
|
||||
)
|
||||
try:
|
||||
procurements = []
|
||||
procurements.append(
|
||||
self.env["procurement.group"].Procurement(
|
||||
request.product_id,
|
||||
request.product_uom_qty,
|
||||
request.product_uom_id,
|
||||
request.location_id,
|
||||
request.name,
|
||||
request.name,
|
||||
self.env.company,
|
||||
values,
|
||||
)
|
||||
)
|
||||
self.env["procurement.group"].run(procurements)
|
||||
except UserError as error:
|
||||
errors.append(error.name)
|
||||
if errors:
|
||||
raise UserError("\n".join(errors))
|
||||
return True
|
||||
|
||||
def action_view_transfer(self):
|
||||
action = self.env.ref("stock.action_picking_tree_all").read()[0]
|
||||
|
||||
pickings = self.mapped("picking_ids")
|
||||
if len(pickings) > 1:
|
||||
action["domain"] = [("id", "in", pickings.ids)]
|
||||
elif pickings:
|
||||
action["views"] = [(self.env.ref("stock.view_picking_form").id, "form")]
|
||||
action["res_id"] = pickings.id
|
||||
return action
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
upd_vals = vals.copy()
|
||||
if upd_vals.get("name", "/") == "/":
|
||||
upd_vals["name"] = self.env["ir.sequence"].next_by_code("stock.request")
|
||||
return super().create(upd_vals)
|
||||
|
||||
def unlink(self):
|
||||
if self.filtered(lambda r: r.state != "draft"):
|
||||
raise UserError(_("Only requests on draft state can be unlinked"))
|
||||
return super(StockRequest, self).unlink()
|
||||
257
stock_request/models/stock_request_abstract.py
Normal file
257
stock_request/models/stock_request_abstract.py
Normal file
@@ -0,0 +1,257 @@
|
||||
# Copyright 2017-2020 ForgeFlow, S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class StockRequest(models.AbstractModel):
|
||||
_name = "stock.request.abstract"
|
||||
_description = "Stock Request Template"
|
||||
_inherit = ["mail.thread", "mail.activity.mixin"]
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields):
|
||||
res = super(StockRequest, self).default_get(fields)
|
||||
warehouse = None
|
||||
if "warehouse_id" not in res and res.get("company_id"):
|
||||
warehouse = self.env["stock.warehouse"].search(
|
||||
[("company_id", "=", res["company_id"])], limit=1
|
||||
)
|
||||
if warehouse:
|
||||
res["warehouse_id"] = warehouse.id
|
||||
res["location_id"] = warehouse.lot_stock_id.id
|
||||
return res
|
||||
|
||||
@api.depends(
|
||||
"product_id",
|
||||
"product_uom_id",
|
||||
"product_uom_qty",
|
||||
"product_id.product_tmpl_id.uom_id",
|
||||
)
|
||||
def _compute_product_qty(self):
|
||||
for rec in self:
|
||||
rec.product_qty = rec.product_uom_id._compute_quantity(
|
||||
rec.product_uom_qty, rec.product_id.product_tmpl_id.uom_id
|
||||
)
|
||||
|
||||
name = fields.Char("Name", copy=False, required=True, readonly=True, default="/")
|
||||
warehouse_id = fields.Many2one(
|
||||
"stock.warehouse", "Warehouse", ondelete="cascade", required=True
|
||||
)
|
||||
location_id = fields.Many2one(
|
||||
"stock.location",
|
||||
"Location",
|
||||
domain=[("usage", "in", ["internal", "transit"])],
|
||||
ondelete="cascade",
|
||||
required=True,
|
||||
)
|
||||
product_id = fields.Many2one(
|
||||
"product.product",
|
||||
"Product",
|
||||
domain=[("type", "in", ["product", "consu"])],
|
||||
ondelete="cascade",
|
||||
required=True,
|
||||
)
|
||||
allow_virtual_location = fields.Boolean(
|
||||
related="company_id.stock_request_allow_virtual_loc", readonly=True
|
||||
)
|
||||
product_uom_id = fields.Many2one(
|
||||
"uom.uom",
|
||||
"Product Unit of Measure",
|
||||
required=True,
|
||||
default=lambda self: self._context.get("product_uom_id", False),
|
||||
)
|
||||
product_uom_qty = fields.Float(
|
||||
"Quantity",
|
||||
digits="Product Unit of Measure",
|
||||
required=True,
|
||||
help="Quantity, specified in the unit of measure indicated in the request.",
|
||||
)
|
||||
product_qty = fields.Float(
|
||||
"Real Quantity",
|
||||
compute="_compute_product_qty",
|
||||
store=True,
|
||||
copy=False,
|
||||
digits="Product Unit of Measure",
|
||||
help="Quantity in the default UoM of the product",
|
||||
)
|
||||
procurement_group_id = fields.Many2one(
|
||||
"procurement.group",
|
||||
"Procurement Group",
|
||||
help="Moves created through this stock request will be put in this "
|
||||
"procurement group. If none is given, the moves generated by "
|
||||
"procurement rules will be grouped into one big picking.",
|
||||
)
|
||||
company_id = fields.Many2one(
|
||||
"res.company", "Company", required=True, default=lambda self: self.env.company
|
||||
)
|
||||
route_id = fields.Many2one(
|
||||
"stock.location.route",
|
||||
string="Route",
|
||||
domain="[('id', 'in', route_ids)]",
|
||||
ondelete="restrict",
|
||||
)
|
||||
|
||||
route_ids = fields.Many2many(
|
||||
"stock.location.route",
|
||||
string="Routes",
|
||||
compute="_compute_route_ids",
|
||||
readonly=True,
|
||||
)
|
||||
|
||||
_sql_constraints = [
|
||||
("name_uniq", "unique(name, company_id)", "Name must be unique")
|
||||
]
|
||||
|
||||
@api.depends("product_id", "warehouse_id", "location_id")
|
||||
def _compute_route_ids(self):
|
||||
route_obj = self.env["stock.location.route"]
|
||||
for wh in self.mapped("warehouse_id"):
|
||||
wh_routes = route_obj.search([("warehouse_ids", "=", wh.id)])
|
||||
for record in self.filtered(lambda r: r.warehouse_id == wh):
|
||||
routes = route_obj
|
||||
if record.product_id:
|
||||
routes += record.product_id.mapped(
|
||||
"route_ids"
|
||||
) | record.product_id.mapped("categ_id").mapped("total_route_ids")
|
||||
if record.warehouse_id:
|
||||
routes |= wh_routes
|
||||
parents = record.get_parents().ids
|
||||
record.route_ids = routes.filtered(
|
||||
lambda r: any(p.location_id.id in parents for p in r.rule_ids)
|
||||
)
|
||||
|
||||
def get_parents(self):
|
||||
location = self.location_id
|
||||
result = location
|
||||
while location.location_id:
|
||||
location = location.location_id
|
||||
result |= location
|
||||
return result
|
||||
|
||||
@api.constrains(
|
||||
"company_id", "product_id", "warehouse_id", "location_id", "route_id"
|
||||
)
|
||||
def _check_company_constrains(self):
|
||||
""" Check if the related models have the same company """
|
||||
for rec in self:
|
||||
if (
|
||||
rec.product_id.company_id
|
||||
and rec.product_id.company_id != rec.company_id
|
||||
):
|
||||
raise ValidationError(
|
||||
_(
|
||||
"You have entered a product that is assigned "
|
||||
"to another company."
|
||||
)
|
||||
)
|
||||
if (
|
||||
rec.location_id.company_id
|
||||
and rec.location_id.company_id != rec.company_id
|
||||
):
|
||||
raise ValidationError(
|
||||
_(
|
||||
"You have entered a location that is "
|
||||
"assigned to another company."
|
||||
)
|
||||
)
|
||||
if rec.warehouse_id.company_id != rec.company_id:
|
||||
raise ValidationError(
|
||||
_(
|
||||
"You have entered a warehouse that is "
|
||||
"assigned to another company."
|
||||
)
|
||||
)
|
||||
if (
|
||||
rec.route_id
|
||||
and rec.route_id.company_id
|
||||
and rec.route_id.company_id != rec.company_id
|
||||
):
|
||||
raise ValidationError(
|
||||
_(
|
||||
"You have entered a route that is "
|
||||
"assigned to another company."
|
||||
)
|
||||
)
|
||||
|
||||
@api.constrains("product_id")
|
||||
def _check_product_uom(self):
|
||||
""" Check if the UoM has the same category as the
|
||||
product standard UoM """
|
||||
if any(
|
||||
request.product_id.uom_id.category_id != request.product_uom_id.category_id
|
||||
for request in self
|
||||
):
|
||||
raise ValidationError(
|
||||
_(
|
||||
"You have to select a product unit of measure in the "
|
||||
"same category than the default unit "
|
||||
"of measure of the product"
|
||||
)
|
||||
)
|
||||
|
||||
@api.constrains("product_qty")
|
||||
def _check_qty(self):
|
||||
for rec in self:
|
||||
if rec.product_qty <= 0:
|
||||
raise ValidationError(
|
||||
_("Stock Request product quantity has to be strictly positive.")
|
||||
)
|
||||
|
||||
@api.onchange("warehouse_id")
|
||||
def onchange_warehouse_id(self):
|
||||
""" Finds location id for changed warehouse. """
|
||||
res = {"domain": {}}
|
||||
if self._name == "stock.request" and self.order_id:
|
||||
# When the stock request is created from an order the wh and
|
||||
# location are taken from the order and we rely on it to change
|
||||
# all request associated. Thus, no need to apply
|
||||
# the onchange, as it could lead to inconsistencies.
|
||||
return res
|
||||
if self.warehouse_id:
|
||||
loc_wh = self.location_id.get_warehouse()
|
||||
if self.warehouse_id != loc_wh:
|
||||
self.location_id = self.warehouse_id.lot_stock_id.id
|
||||
if self.warehouse_id.company_id != self.company_id:
|
||||
self.company_id = self.warehouse_id.company_id
|
||||
return res
|
||||
|
||||
@api.onchange("location_id")
|
||||
def onchange_location_id(self):
|
||||
if self.location_id:
|
||||
loc_wh = self.location_id.get_warehouse()
|
||||
if loc_wh and self.warehouse_id != loc_wh:
|
||||
self.warehouse_id = loc_wh
|
||||
self.with_context(no_change_childs=True).onchange_warehouse_id()
|
||||
|
||||
@api.onchange("allow_virtual_location")
|
||||
def onchange_allow_virtual_location(self):
|
||||
if self.allow_virtual_location:
|
||||
return {"domain": {"location_id": []}}
|
||||
|
||||
@api.onchange("company_id")
|
||||
def onchange_company_id(self):
|
||||
""" Sets a default warehouse when the company is changed and limits
|
||||
the user selection of warehouses. """
|
||||
if self.company_id and (
|
||||
not self.warehouse_id or self.warehouse_id.company_id != self.company_id
|
||||
):
|
||||
self.warehouse_id = self.env["stock.warehouse"].search(
|
||||
[("company_id", "=", self.company_id.id)], limit=1
|
||||
)
|
||||
self.onchange_warehouse_id()
|
||||
|
||||
return {"domain": {"warehouse_id": [("company_id", "=", self.company_id.id)]}}
|
||||
|
||||
@api.onchange("product_id")
|
||||
def onchange_product_id(self):
|
||||
res = {"domain": {}}
|
||||
if self.product_id:
|
||||
self.product_uom_id = self.product_id.uom_id.id
|
||||
res["domain"]["product_uom_id"] = [
|
||||
("category_id", "=", self.product_id.uom_id.category_id.id)
|
||||
]
|
||||
return res
|
||||
res["domain"]["product_uom_id"] = []
|
||||
return res
|
||||
88
stock_request/models/stock_request_allocation.py
Normal file
88
stock_request/models/stock_request_allocation.py
Normal file
@@ -0,0 +1,88 @@
|
||||
# Copyright 2017-2020 ForgeFlow, S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class StockRequestAllocation(models.Model):
|
||||
_name = "stock.request.allocation"
|
||||
_description = "Stock Request Allocation"
|
||||
|
||||
stock_request_id = fields.Many2one(
|
||||
string="Stock Request",
|
||||
comodel_name="stock.request",
|
||||
required=True,
|
||||
ondelete="cascade",
|
||||
)
|
||||
company_id = fields.Many2one(
|
||||
string="Company",
|
||||
comodel_name="res.company",
|
||||
readonly=True,
|
||||
related="stock_request_id.company_id",
|
||||
store=True,
|
||||
)
|
||||
stock_move_id = fields.Many2one(
|
||||
string="Stock Move",
|
||||
comodel_name="stock.move",
|
||||
required=True,
|
||||
ondelete="cascade",
|
||||
)
|
||||
product_id = fields.Many2one(
|
||||
string="Product",
|
||||
comodel_name="product.product",
|
||||
related="stock_request_id.product_id",
|
||||
readonly=True,
|
||||
)
|
||||
product_uom_id = fields.Many2one(
|
||||
string="UoM",
|
||||
comodel_name="uom.uom",
|
||||
related="stock_request_id.product_uom_id",
|
||||
readonly=True,
|
||||
)
|
||||
requested_product_uom_qty = fields.Float(
|
||||
"Requested Quantity (UoM)",
|
||||
help="Quantity of the stock request allocated to the stock move, "
|
||||
"in the UoM of the Stock Request",
|
||||
)
|
||||
requested_product_qty = fields.Float(
|
||||
"Requested Quantity",
|
||||
help="Quantity of the stock request allocated to the stock move, "
|
||||
"in the default UoM of the product",
|
||||
compute="_compute_requested_product_qty",
|
||||
)
|
||||
allocated_product_qty = fields.Float(
|
||||
"Allocated Quantity",
|
||||
help="Quantity of the stock request allocated to the stock move, "
|
||||
"in the default UoM of the product",
|
||||
)
|
||||
open_product_qty = fields.Float(
|
||||
"Open Quantity", compute="_compute_open_product_qty"
|
||||
)
|
||||
|
||||
@api.depends(
|
||||
"stock_request_id.product_id",
|
||||
"stock_request_id.product_uom_id",
|
||||
"requested_product_uom_qty",
|
||||
)
|
||||
def _compute_requested_product_qty(self):
|
||||
for rec in self:
|
||||
rec.requested_product_qty = rec.product_uom_id._compute_quantity(
|
||||
rec.requested_product_uom_qty, rec.product_id.uom_id
|
||||
)
|
||||
|
||||
@api.depends(
|
||||
"requested_product_qty",
|
||||
"allocated_product_qty",
|
||||
"stock_move_id",
|
||||
"stock_move_id.state",
|
||||
)
|
||||
def _compute_open_product_qty(self):
|
||||
for rec in self:
|
||||
if rec.stock_move_id.state == "cancel":
|
||||
rec.open_product_qty = 0.0
|
||||
else:
|
||||
rec.open_product_qty = (
|
||||
rec.requested_product_qty - rec.allocated_product_qty
|
||||
)
|
||||
if rec.open_product_qty < 0.0:
|
||||
rec.open_product_qty = 0.0
|
||||
363
stock_request/models/stock_request_order.py
Normal file
363
stock_request/models/stock_request_order.py
Normal file
@@ -0,0 +1,363 @@
|
||||
# Copyright 2018 Creu Blanca
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import AccessError, UserError, ValidationError
|
||||
|
||||
|
||||
class StockRequestOrder(models.Model):
|
||||
_name = "stock.request.order"
|
||||
_description = "Stock Request Order"
|
||||
_inherit = ["mail.thread", "mail.activity.mixin"]
|
||||
_order = "id desc"
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields):
|
||||
res = super().default_get(fields)
|
||||
warehouse = None
|
||||
if "warehouse_id" not in res and res.get("company_id"):
|
||||
warehouse = self.env["stock.warehouse"].search(
|
||||
[("company_id", "=", res["company_id"])], limit=1
|
||||
)
|
||||
if warehouse:
|
||||
res["warehouse_id"] = warehouse.id
|
||||
res["location_id"] = warehouse.lot_stock_id.id
|
||||
return res
|
||||
|
||||
def __get_request_order_states(self):
|
||||
return self.env["stock.request"]._get_request_states()
|
||||
|
||||
def _get_request_order_states(self):
|
||||
return self.__get_request_order_states()
|
||||
|
||||
def _get_default_requested_by(self):
|
||||
return self.env["res.users"].browse(self.env.uid)
|
||||
|
||||
name = fields.Char(
|
||||
"Name",
|
||||
copy=False,
|
||||
required=True,
|
||||
readonly=True,
|
||||
states={"draft": [("readonly", False)]},
|
||||
default="/",
|
||||
)
|
||||
state = fields.Selection(
|
||||
selection=_get_request_order_states,
|
||||
string="Status",
|
||||
copy=False,
|
||||
default="draft",
|
||||
index=True,
|
||||
readonly=True,
|
||||
track_visibility="onchange",
|
||||
)
|
||||
requested_by = fields.Many2one(
|
||||
"res.users",
|
||||
"Requested by",
|
||||
required=True,
|
||||
track_visibility="onchange",
|
||||
default=lambda s: s._get_default_requested_by(),
|
||||
)
|
||||
warehouse_id = fields.Many2one(
|
||||
"stock.warehouse",
|
||||
"Warehouse",
|
||||
readonly=True,
|
||||
ondelete="cascade",
|
||||
required=True,
|
||||
states={"draft": [("readonly", False)]},
|
||||
)
|
||||
location_id = fields.Many2one(
|
||||
"stock.location",
|
||||
"Location",
|
||||
readonly=True,
|
||||
domain=[("usage", "in", ["internal", "transit"])],
|
||||
ondelete="cascade",
|
||||
required=True,
|
||||
states={"draft": [("readonly", False)]},
|
||||
)
|
||||
allow_virtual_location = fields.Boolean(
|
||||
related="company_id.stock_request_allow_virtual_loc", readonly=True
|
||||
)
|
||||
procurement_group_id = fields.Many2one(
|
||||
"procurement.group",
|
||||
"Procurement Group",
|
||||
readonly=True,
|
||||
states={"draft": [("readonly", False)]},
|
||||
help="Moves created through this stock request will be put in this "
|
||||
"procurement group. If none is given, the moves generated by "
|
||||
"procurement rules will be grouped into one big picking.",
|
||||
)
|
||||
company_id = fields.Many2one(
|
||||
"res.company",
|
||||
"Company",
|
||||
required=True,
|
||||
readonly=True,
|
||||
states={"draft": [("readonly", False)]},
|
||||
default=lambda self: self.env.company,
|
||||
)
|
||||
expected_date = fields.Datetime(
|
||||
"Expected Date",
|
||||
default=fields.Datetime.now,
|
||||
index=True,
|
||||
required=True,
|
||||
readonly=True,
|
||||
states={"draft": [("readonly", False)]},
|
||||
help="Date when you expect to receive the goods.",
|
||||
)
|
||||
picking_policy = fields.Selection(
|
||||
[
|
||||
("direct", "Receive each product when available"),
|
||||
("one", "Receive all products at once"),
|
||||
],
|
||||
string="Shipping Policy",
|
||||
required=True,
|
||||
readonly=True,
|
||||
states={"draft": [("readonly", False)]},
|
||||
default="direct",
|
||||
)
|
||||
move_ids = fields.One2many(
|
||||
comodel_name="stock.move",
|
||||
compute="_compute_move_ids",
|
||||
string="Stock Moves",
|
||||
readonly=True,
|
||||
)
|
||||
picking_ids = fields.One2many(
|
||||
"stock.picking",
|
||||
compute="_compute_picking_ids",
|
||||
string="Pickings",
|
||||
readonly=True,
|
||||
)
|
||||
picking_count = fields.Integer(
|
||||
string="Delivery Orders", compute="_compute_picking_ids", readonly=True
|
||||
)
|
||||
stock_request_ids = fields.One2many(
|
||||
"stock.request", inverse_name="order_id", copy=True
|
||||
)
|
||||
stock_request_count = fields.Integer(
|
||||
string="Stock requests", compute="_compute_stock_request_count", readonly=True
|
||||
)
|
||||
|
||||
_sql_constraints = [
|
||||
("name_uniq", "unique(name, company_id)", "Stock Request name must be unique")
|
||||
]
|
||||
|
||||
@api.depends("stock_request_ids.allocation_ids")
|
||||
def _compute_picking_ids(self):
|
||||
for record in self:
|
||||
record.picking_ids = record.stock_request_ids.mapped("picking_ids")
|
||||
record.picking_count = len(record.picking_ids)
|
||||
|
||||
@api.depends("stock_request_ids")
|
||||
def _compute_move_ids(self):
|
||||
for record in self:
|
||||
record.move_ids = record.stock_request_ids.mapped("move_ids")
|
||||
|
||||
@api.depends("stock_request_ids")
|
||||
def _compute_stock_request_count(self):
|
||||
for record in self:
|
||||
record.stock_request_count = len(record.stock_request_ids)
|
||||
|
||||
@api.onchange("requested_by")
|
||||
def onchange_requested_by(self):
|
||||
self.change_childs()
|
||||
|
||||
@api.onchange("expected_date")
|
||||
def onchange_expected_date(self):
|
||||
self.change_childs()
|
||||
|
||||
@api.onchange("picking_policy")
|
||||
def onchange_picking_policy(self):
|
||||
self.change_childs()
|
||||
|
||||
@api.onchange("location_id")
|
||||
def onchange_location_id(self):
|
||||
if self.location_id:
|
||||
loc_wh = self.location_id.get_warehouse()
|
||||
if loc_wh and self.warehouse_id != loc_wh:
|
||||
self.warehouse_id = loc_wh
|
||||
self.with_context(no_change_childs=True).onchange_warehouse_id()
|
||||
self.change_childs()
|
||||
|
||||
@api.onchange("allow_virtual_location")
|
||||
def onchange_allow_virtual_location(self):
|
||||
if self.allow_virtual_location:
|
||||
return {"domain": {"location_id": []}}
|
||||
|
||||
@api.onchange("warehouse_id")
|
||||
def onchange_warehouse_id(self):
|
||||
if self.warehouse_id:
|
||||
# search with sudo because the user may not have permissions
|
||||
loc_wh = self.location_id.get_warehouse()
|
||||
if self.warehouse_id != loc_wh:
|
||||
self.location_id = self.warehouse_id.lot_stock_id
|
||||
self.with_context(no_change_childs=True).onchange_location_id()
|
||||
if self.warehouse_id.company_id != self.company_id:
|
||||
self.company_id = self.warehouse_id.company_id
|
||||
self.with_context(no_change_childs=True).onchange_company_id()
|
||||
self.change_childs()
|
||||
|
||||
@api.onchange("procurement_group_id")
|
||||
def onchange_procurement_group_id(self):
|
||||
self.change_childs()
|
||||
|
||||
@api.onchange("company_id")
|
||||
def onchange_company_id(self):
|
||||
if self.company_id and (
|
||||
not self.warehouse_id or self.warehouse_id.company_id != self.company_id
|
||||
):
|
||||
self.warehouse_id = self.env["stock.warehouse"].search(
|
||||
[("company_id", "=", self.company_id.id)], limit=1
|
||||
)
|
||||
self.with_context(no_change_childs=True).onchange_warehouse_id()
|
||||
self.change_childs()
|
||||
return {"domain": {"warehouse_id": [("company_id", "=", self.company_id.id)]}}
|
||||
|
||||
def change_childs(self):
|
||||
if not self._context.get("no_change_childs", False):
|
||||
for line in self.stock_request_ids:
|
||||
line.warehouse_id = self.warehouse_id
|
||||
line.location_id = self.location_id
|
||||
line.company_id = self.company_id
|
||||
line.picking_policy = self.picking_policy
|
||||
line.expected_date = self.expected_date
|
||||
line.requested_by = self.requested_by
|
||||
line.procurement_group_id = self.procurement_group_id
|
||||
|
||||
def action_confirm(self):
|
||||
for line in self.stock_request_ids:
|
||||
line.action_confirm()
|
||||
self.state = "open"
|
||||
return True
|
||||
|
||||
def action_draft(self):
|
||||
for line in self.stock_request_ids:
|
||||
line.action_draft()
|
||||
self.state = "draft"
|
||||
return True
|
||||
|
||||
def action_cancel(self):
|
||||
for line in self.stock_request_ids:
|
||||
line.action_cancel()
|
||||
self.state = "cancel"
|
||||
return True
|
||||
|
||||
def action_done(self):
|
||||
self.state = "done"
|
||||
return True
|
||||
|
||||
def check_done(self):
|
||||
if not self.stock_request_ids.filtered(lambda r: r.state != "done"):
|
||||
self.action_done()
|
||||
return
|
||||
|
||||
def action_view_transfer(self):
|
||||
action = self.env.ref("stock.action_picking_tree_all").read()[0]
|
||||
|
||||
pickings = self.mapped("picking_ids")
|
||||
if len(pickings) > 1:
|
||||
action["domain"] = [("id", "in", pickings.ids)]
|
||||
elif pickings:
|
||||
action["views"] = [(self.env.ref("stock.view_picking_form").id, "form")]
|
||||
action["res_id"] = pickings.id
|
||||
return action
|
||||
|
||||
def action_view_stock_requests(self):
|
||||
action = self.env.ref("stock_request.action_stock_request_form").read()[0]
|
||||
if len(self.stock_request_ids) > 1:
|
||||
action["domain"] = [("order_id", "in", self.ids)]
|
||||
elif self.stock_request_ids:
|
||||
action["views"] = [
|
||||
(self.env.ref("stock_request.view_stock_request_form").id, "form")
|
||||
]
|
||||
action["res_id"] = self.stock_request_ids.id
|
||||
return action
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
upd_vals = vals.copy()
|
||||
if upd_vals.get("name", "/") == "/":
|
||||
upd_vals["name"] = self.env["ir.sequence"].next_by_code(
|
||||
"stock.request.order"
|
||||
)
|
||||
return super().create(upd_vals)
|
||||
|
||||
def unlink(self):
|
||||
if self.filtered(lambda r: r.state != "draft"):
|
||||
raise UserError(_("Only orders on draft state can be unlinked"))
|
||||
return super().unlink()
|
||||
|
||||
@api.constrains("warehouse_id", "company_id")
|
||||
def _check_warehouse_company(self):
|
||||
if any(
|
||||
request.warehouse_id.company_id != request.company_id for request in self
|
||||
):
|
||||
raise ValidationError(
|
||||
_(
|
||||
"The company of the stock request must match with "
|
||||
"that of the warehouse."
|
||||
)
|
||||
)
|
||||
|
||||
@api.constrains("location_id", "company_id")
|
||||
def _check_location_company(self):
|
||||
if any(
|
||||
request.location_id.company_id
|
||||
and request.location_id.company_id != request.company_id
|
||||
for request in self
|
||||
):
|
||||
raise ValidationError(
|
||||
_(
|
||||
"The company of the stock request must match with "
|
||||
"that of the location."
|
||||
)
|
||||
)
|
||||
|
||||
@api.model
|
||||
def _create_from_product_multiselect(self, products):
|
||||
if not products:
|
||||
return False
|
||||
if products._name not in ("product.product", "product.template"):
|
||||
raise ValidationError(
|
||||
_("This action only works in the context of products")
|
||||
)
|
||||
if products._name == "product.template":
|
||||
# search instead of mapped so we don't include archived variants
|
||||
products = self.env["product.product"].search(
|
||||
[("product_tmpl_id", "in", products.ids)]
|
||||
)
|
||||
expected = self.default_get(["expected_date"])["expected_date"]
|
||||
try:
|
||||
order = self.env["stock.request.order"].create(
|
||||
dict(
|
||||
expected_date=expected,
|
||||
stock_request_ids=[
|
||||
(
|
||||
0,
|
||||
0,
|
||||
dict(
|
||||
product_id=product.id,
|
||||
product_uom_id=product.uom_id.id,
|
||||
product_uom_qty=1.0,
|
||||
expected_date=expected,
|
||||
),
|
||||
)
|
||||
for product in products
|
||||
],
|
||||
)
|
||||
)
|
||||
except AccessError:
|
||||
# TODO: if there is a nice way to hide the action from the
|
||||
# Action-menu if the user doesn't have the necessary rights,
|
||||
# that would be a better way of doing this
|
||||
raise UserError(
|
||||
_(
|
||||
"Unfortunately it seems you do not have the necessary rights "
|
||||
"for creating stock requests. Please contact your "
|
||||
"administrator."
|
||||
)
|
||||
)
|
||||
action = self.env.ref("stock_request.stock_request_order_action").read()[0]
|
||||
action["views"] = [
|
||||
(self.env.ref("stock_request.stock_request_order_form").id, "form")
|
||||
]
|
||||
action["res_id"] = order.id
|
||||
return action
|
||||
42
stock_request/models/stock_rule.py
Normal file
42
stock_request/models/stock_rule.py
Normal file
@@ -0,0 +1,42 @@
|
||||
# Copyright 2017-2020 ForgeFlow, S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
from odoo import models
|
||||
|
||||
|
||||
class StockRule(models.Model):
|
||||
_inherit = "stock.rule"
|
||||
|
||||
def _get_stock_move_values(
|
||||
self,
|
||||
product_id,
|
||||
product_qty,
|
||||
product_uom,
|
||||
location_id,
|
||||
name,
|
||||
origin,
|
||||
company_id,
|
||||
values,
|
||||
):
|
||||
result = super(StockRule, self)._get_stock_move_values(
|
||||
product_id,
|
||||
product_qty,
|
||||
product_uom,
|
||||
location_id,
|
||||
name,
|
||||
origin,
|
||||
company_id,
|
||||
values,
|
||||
)
|
||||
if values.get("stock_request_id", False):
|
||||
result["allocation_ids"] = [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"stock_request_id": values.get("stock_request_id"),
|
||||
"requested_product_uom_qty": product_qty,
|
||||
},
|
||||
)
|
||||
]
|
||||
return result
|
||||
46
stock_request/models/stock_warehouse.py
Normal file
46
stock_request/models/stock_warehouse.py
Normal file
@@ -0,0 +1,46 @@
|
||||
# Copyright 2018 Eficent Business and IT Consulting Services, S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
from odoo import _, api, models
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class StockWarehouse(models.Model):
|
||||
_inherit = "stock.warehouse"
|
||||
|
||||
@api.constrains("company_id")
|
||||
def _check_company_stock_request(self):
|
||||
if any(
|
||||
self.env["stock.request"].search(
|
||||
[
|
||||
("company_id", "!=", rec.company_id.id),
|
||||
("warehouse_id", "=", rec.id),
|
||||
],
|
||||
limit=1,
|
||||
)
|
||||
for rec in self
|
||||
):
|
||||
raise ValidationError(
|
||||
_(
|
||||
"You cannot change the company of the warehouse, as it is "
|
||||
"already assigned to stock requests that belong to "
|
||||
"another company."
|
||||
)
|
||||
)
|
||||
if any(
|
||||
self.env["stock.request.order"].search(
|
||||
[
|
||||
("company_id", "!=", rec.company_id.id),
|
||||
("warehouse_id", "=", rec.id),
|
||||
],
|
||||
limit=1,
|
||||
)
|
||||
for rec in self
|
||||
):
|
||||
raise ValidationError(
|
||||
_(
|
||||
"You cannot change the company of the warehouse, as it is "
|
||||
"already assigned to stock request orders that belong to "
|
||||
"another company."
|
||||
)
|
||||
)
|
||||
17
stock_request/readme/CONFIGURE.rst
Normal file
17
stock_request/readme/CONFIGURE.rst
Normal file
@@ -0,0 +1,17 @@
|
||||
To configure this module:
|
||||
|
||||
* Go to Stock Requests > Settings
|
||||
|
||||
Users should be assigned to the groups 'Stock Request / User' or 'Stock
|
||||
Request / Manager'.
|
||||
|
||||
## Group Stock Request / User
|
||||
|
||||
* Can see her/his own Stock Requests, and others that she/he's been granted
|
||||
permission to follow.
|
||||
|
||||
* Can create/update only her/his Stock Requests.
|
||||
|
||||
## Group Stock Request / Manager
|
||||
|
||||
* Can fully manage all Stock Requests
|
||||
12
stock_request/readme/CONTRIBUTORS.rst
Normal file
12
stock_request/readme/CONTRIBUTORS.rst
Normal file
@@ -0,0 +1,12 @@
|
||||
* Jordi Ballester (EFICENT) <jordi.ballester@forgeflow.com>.
|
||||
* Enric Tobella <etobella@creublanca.es>
|
||||
* Atte Isopuro <atte.isopuro@avoin.systems>
|
||||
* Lois Rilo <lois.rilo@forgeflow.com>
|
||||
* Raul Martin <raul.martin@braintec-group.com>
|
||||
* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
|
||||
* `Open Source Integrators <https://www.opensourceintegrators.com>`_
|
||||
|
||||
* Maxime Chambreuil <mchambreuil@opensourceintegrators.com>
|
||||
* Steve Campbell <scampbell@opensourceintegrators.com>
|
||||
|
||||
* Héctor Villarreal <hector.villarreal@forgeflow.com>
|
||||
2
stock_request/readme/DESCRIPTION.rst
Normal file
2
stock_request/readme/DESCRIPTION.rst
Normal file
@@ -0,0 +1,2 @@
|
||||
This module was written to allow users to request products that are
|
||||
frequently stocked by the company, to be transferred to their chosen location.
|
||||
16
stock_request/readme/USAGE.rst
Normal file
16
stock_request/readme/USAGE.rst
Normal file
@@ -0,0 +1,16 @@
|
||||
## Creation
|
||||
|
||||
* Go to 'Stock Requests / Stock Requests' and create a new Request.
|
||||
* Indicate a product, quantity and location.
|
||||
* Press 'Confirm'.
|
||||
|
||||
Upon confirmation the request will be evaluated using the procurement rules
|
||||
for the selected location.
|
||||
|
||||
In case that transfers are created, the user will be able to access to them
|
||||
from the button 'Transfers' available in the Stock Request.
|
||||
|
||||
## Cancel
|
||||
|
||||
When the user cancels a Stock Request, the related pending stock moves will be
|
||||
also cancelled.
|
||||
17
stock_request/security/ir.model.access.csv
Normal file
17
stock_request/security/ir.model.access.csv
Normal file
@@ -0,0 +1,17 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_stock_request_user,stock request user,model_stock_request,group_stock_request_user,1,1,1,
|
||||
access_stock_request_manager,stock request manager,model_stock_request,group_stock_request_manager,1,1,1,1
|
||||
access_stock_request_stock_user,stock.request stock user,model_stock_request,stock.group_stock_user,1,0,0,0
|
||||
access_stock_request_allocation_user,stock request allocation user,model_stock_request_allocation,group_stock_request_user,1,1,1,1
|
||||
access_stock_request_allocation_manager,stock request allocation manager,model_stock_request_allocation,group_stock_request_manager,1,1,1,1
|
||||
access_stock_request_allocation_stock_user,stock.request.allocation stock user,model_stock_request_allocation,base.group_user,1,0,0,0
|
||||
access_stock_location_user,stock.location.user,stock.model_stock_location,group_stock_request_user,1,0,0,0
|
||||
access_stock_location_request_manager,stock.location request manager,stock.model_stock_location,group_stock_request_manager,1,0,0,0
|
||||
access_stock_rule_request_manager,stock_rule_request_manager,stock.model_stock_rule,group_stock_request_manager,1,0,0,0
|
||||
access_stock_rule_user,stock_rule_user,stock.model_stock_rule,group_stock_request_user,1,0,0,0
|
||||
access_stock_request_order_user,stock request user,model_stock_request_order,group_stock_request_user,1,1,1,0
|
||||
access_stock_request_order_manager,stock request manager,model_stock_request_order,group_stock_request_manager,1,1,1,1
|
||||
access_stock_request_user_warehouse,stock request user Warehouse,stock.model_stock_warehouse,group_stock_request_user,1,0,0,0
|
||||
access_stock_request_manager_warehouse,stock request manager Warehouse,stock.model_stock_warehouse,group_stock_request_manager,1,0,0,0
|
||||
access_stock_request_user_stock_move,stock request user stock move,stock.model_stock_move,group_stock_request_user,1,0,0,0
|
||||
access_stock_request_manager_stock_move,stock request manager stock move,stock.model_stock_move,group_stock_request_manager,1,0,0,0
|
||||
|
117
stock_request/security/stock_request_security.xml
Normal file
117
stock_request/security/stock_request_security.xml
Normal file
@@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record model="ir.module.category" id="module_category_stock_request">
|
||||
<field name="name">Stock Request</field>
|
||||
<field name="parent_id" ref="base.module_category_warehouse_management"/>
|
||||
<field name="sequence">10</field>
|
||||
</record>
|
||||
|
||||
<record id="group_stock_request_user" model="res.groups">
|
||||
<field name="name">Stock Request User</field>
|
||||
<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
|
||||
<field name="category_id" ref="module_category_stock_request"/>
|
||||
</record>
|
||||
|
||||
<record id="group_stock_request_manager" model="res.groups">
|
||||
<field name="name">Stock Request Manager</field>
|
||||
<field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
|
||||
<field name="implied_ids"
|
||||
eval="[(4, ref('stock_request.group_stock_request_user')),(4, ref('stock.group_stock_user'))]"/>
|
||||
<field name="category_id" ref="module_category_stock_request"/>
|
||||
</record>
|
||||
|
||||
<record id="group_stock_request_order" model="res.groups">
|
||||
<field name="name">Stock Request Order</field>
|
||||
<field name="category_id" ref="base.module_category_hidden"/>
|
||||
</record>
|
||||
|
||||
<record id="stock.group_stock_user" model="res.groups">
|
||||
<field name="implied_ids"
|
||||
eval="[(4, ref('group_stock_request_user'))]"/>
|
||||
</record>
|
||||
|
||||
<data noupdate="1">
|
||||
<record model="ir.rule" id="stock_picking_rule">
|
||||
<field name="name">stock_request multi-company</field>
|
||||
<field name="model_id" search="[('model','=','stock.request')]"
|
||||
model="ir.model"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record id="stock_request_followers_rule" model="ir.rule">
|
||||
<field name="name">Follow Stock Request</field>
|
||||
<field name="model_id" ref="model_stock_request"/>
|
||||
<field name="groups" eval="[(6,0, [ref('group_stock_request_user')])]"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_unlink" eval="False"/>
|
||||
<field name="domain_force">['|',('requested_by','=',user.id),
|
||||
('message_partner_ids', 'in', [user.partner_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record id="stock_request_rule" model="ir.rule">
|
||||
<field name="name">Stock Request User</field>
|
||||
<field name="model_id" ref="model_stock_request"/>
|
||||
<field name="groups" eval="[(6,0, [ref('group_stock_request_user')])]"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_unlink" eval="True"/>
|
||||
<field name="domain_force">[('requested_by','=',user.id)]</field>
|
||||
</record>
|
||||
|
||||
<record id="stock_request_manager_rule" model="ir.rule">
|
||||
<field name="name">Stock Request Manager</field>
|
||||
<field name="model_id" ref="model_stock_request"/>
|
||||
<field name="groups" eval="[(6,0, [ref('group_stock_request_manager')])]"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_unlink" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule" id="stock_request_order_picking_rule">
|
||||
<field name="name">stock_request_order multi-company</field>
|
||||
<field name="model_id" ref="model_stock_request_order"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record id="stock_request_order_followers_rule" model="ir.rule">
|
||||
<field name="name">Follow Stock Request Order</field>
|
||||
<field name="model_id" ref="model_stock_request_order"/>
|
||||
<field name="groups" eval="[(6,0, [ref('stock_request.group_stock_request_user')])]"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_unlink" eval="False"/>
|
||||
<field name="domain_force">['|',('requested_by','=',user.id),
|
||||
('message_partner_ids', 'in', [user.partner_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record id="stock_request_order_rule" model="ir.rule">
|
||||
<field name="name">Stock Request Order User</field>
|
||||
<field name="model_id" ref="model_stock_request_order"/>
|
||||
<field name="groups" eval="[(6,0, [ref('stock_request.group_stock_request_user')])]"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_unlink" eval="True"/>
|
||||
<field name="domain_force">[('requested_by','=',user.id)]</field>
|
||||
</record>
|
||||
|
||||
<record id="stock_request_order_manager_rule" model="ir.rule">
|
||||
<field name="name">Stock Request Manager</field>
|
||||
<field name="model_id" ref="model_stock_request_order"/>
|
||||
<field name="groups" eval="[(6,0, [ref('stock_request.group_stock_request_manager')])]"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_unlink" eval="True"/>
|
||||
</record>
|
||||
</data>
|
||||
|
||||
</odoo>
|
||||
BIN
stock_request/static/description/icon.png
Normal file
BIN
stock_request/static/description/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
172
stock_request/static/description/icon.svg
Normal file
172
stock_request/static/description/icon.svg
Normal file
@@ -0,0 +1,172 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="100mm"
|
||||
height="100mm"
|
||||
viewBox="0 0 100 100"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
sodipodi:docname="icon.svg"
|
||||
inkscape:version="0.92.4 (f8dce91, 2019-08-02)">
|
||||
<defs
|
||||
id="defs2">
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath4562">
|
||||
<rect
|
||||
ry="4.1577382"
|
||||
y="13.040181"
|
||||
x="-124.92113"
|
||||
height="98.866074"
|
||||
width="99.811012"
|
||||
id="rect4564"
|
||||
style="fill:#aa0000;stroke-width:0.26458332"
|
||||
clip-path="none" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath4578">
|
||||
<rect
|
||||
ry="4.1577382"
|
||||
y="1.5119057"
|
||||
x="-120.00744"
|
||||
height="97.930626"
|
||||
width="99.811012"
|
||||
id="rect4580"
|
||||
style="fill:#aa0000;stroke-width:0.26458332" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.4"
|
||||
inkscape:cx="35.432324"
|
||||
inkscape:cy="70.109427"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer2"
|
||||
showgrid="false"
|
||||
inkscape:snap-page="true"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1052"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="28"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-global="false">
|
||||
<sodipodi:guide
|
||||
position="27.285156,77.130766"
|
||||
orientation="-0.70710678,0.70710678"
|
||||
id="guide4619"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="65.956845,10.583333"
|
||||
orientation="-0.70710678,0.70710678"
|
||||
id="guide4621"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="67.704985,78.09933"
|
||||
orientation="-0.70710678,0.70710678"
|
||||
id="guide4623"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="62.407434,24.722431"
|
||||
orientation="-0.70710678,0.70710678"
|
||||
id="guide4625"
|
||||
inkscape:locked="false" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-197)"
|
||||
style="display:inline" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="Layer 2"
|
||||
style="display:inline">
|
||||
<rect
|
||||
y="0"
|
||||
x="0"
|
||||
height="25.164532"
|
||||
width="100"
|
||||
id="rect4535"
|
||||
style="fill:#de8787;stroke-width:0.13272627"
|
||||
ry="4.9136906"
|
||||
inkscape:export-xdpi="91.327972"
|
||||
inkscape:export-ydpi="91.327972" />
|
||||
<rect
|
||||
ry="4.9136906"
|
||||
style="fill:#501616;stroke-width:0.13272627"
|
||||
id="rect4566"
|
||||
width="100"
|
||||
height="25.164532"
|
||||
x="0.18899068"
|
||||
y="74.958138"
|
||||
inkscape:export-xdpi="91.327972"
|
||||
inkscape:export-ydpi="91.327972" />
|
||||
<rect
|
||||
style="fill:#aa0000;stroke-width:0.26458332"
|
||||
id="rect914"
|
||||
width="99.811012"
|
||||
height="97.930626"
|
||||
x="0.18898809"
|
||||
y="1.1339295"
|
||||
ry="4.1577382"
|
||||
inkscape:export-xdpi="91.327972"
|
||||
inkscape:export-ydpi="91.327972" />
|
||||
<path
|
||||
id="path61"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 97.234379,149.70387 0.28348,94.58853 c 0,0 0.75595,3.1183 3.496281,3.87426 h 28.91518 c 0,0 3.30729,-0.94494 3.87426,-3.59077 v -7.74852 c 0,0 -0.94494,-3.1183 -3.68527,-3.59077 -2.74033,-0.47247 -18.23735,0 -18.23735,0 v -82.96577 c 0,0 -0.47247,-3.68526 -3.40179,-3.77976 h -7.46503 c 0,0 -2.834821,-0.0945 -3.779761,3.2128 z m -40.72672,-3.30742 -32.22284,0.0946 c 0,0 -11.24479,1.32285 -11.24479,11.15022 l 0.0946,25.22999 -10.866522,0.18914 c 0,0 -9.35491,-0.8503 -11.24479,10.77247 l 0.47232,47.05759 c 0,0 1.79532,21.82849 21.733562,21.63951 19.93824,-0.18899 21.73356,-21.54494 21.73356,-21.54494 l 14.45751,-0.0946 c 0,0 1.22835,21.734 21.73356,21.63951 0,0 21.1671,-0.28386 21.73407,-21.63951 0,0 -0.28348,-10.01622 -7.27604,-16.34732 v -24.28483 c 0,0 0.28326,-3.21309 -0.94516,-5.66993 -1.22842,-2.45685 -17.85938,-41.76593 -17.85938,-41.76593 0,0 -1.88966,-5.19754 -10.29963,-6.42596 z m -28.86542,14.55415 26.45989,0.13384 17.10489,39.28856 -0.13332,3.87521 h -21.91598 l -21.38164,-21.38112 z m -14.52107,69.22316 a 10.657372,10.657372 0 0 1 10.65722,10.65723 10.657372,10.657372 0 0 1 -10.65722,10.65723 10.657372,10.657372 0 0 1 -10.657752,-10.65723 10.657372,10.657372 0 0 1 10.657752,-10.65723 z m 58.20833,0 a 10.657372,10.657372 0 0 1 10.65723,10.65723 10.657372,10.657372 0 0 1 -10.65723,10.65723 10.657372,10.657372 0 0 1 -10.65775,-10.65723 10.657372,10.657372 0 0 1 10.65775,-10.65723 z"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m -92.911273,23.247206 -27.285157,27.28811 v 49.842664 h 37.697532 17.674503 l 29.218074,-29.216604 -13.586893,-4.10161 -3.29823,-44.78112 -13.501505,13.50151 -6.362234,-9.16857 -20.55609,-3.36438"
|
||||
style="display:inline;opacity:0.476;fill:#550000;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
id="path4576"
|
||||
clip-path="url(#clipPath4578)"
|
||||
transform="translate(120.21264,-0.31639914)"
|
||||
inkscape:export-xdpi="91.327972"
|
||||
inkscape:export-ydpi="91.327972" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 65.712353,24.643945 0.14027,46.803935 c 0,0 0.374059,1.542981 1.730014,1.917051 h 14.307701 c 0,0 1.636494,-0.467579 1.917043,-1.776775 v -3.834094 c 0,0 -0.467568,-1.542985 -1.823534,-1.77677 -1.355955,-0.233787 -9.024128,0 -9.024128,0 V 24.924486 c 0,0 -0.23379,-1.823526 -1.683265,-1.870286 h -3.693817 c 0,0 -1.402715,-0.04676 -1.870284,1.589745 z M 45.560112,23.00738 29.615728,23.05418 c 0,0 -5.564103,0.654568 -5.564103,5.517309 l 0.04681,12.484207 -5.376931,0.09359 c 0,0 -4.628961,-0.420742 -5.564104,5.330392 l 0.233712,23.284857 c 0,0 0.888353,10.801089 10.754117,10.707579 9.865764,-0.09354 10.754117,-10.660784 10.754117,-10.660784 l 7.153819,-0.04682 c 0,0 0.607805,10.754338 10.75411,10.707578 0,0 10.473823,-0.140456 10.754372,-10.707578 0,0 -0.140269,-4.956187 -3.600297,-8.088919 V 49.659084 c 0,0 0.14016,-1.589888 -0.467689,-2.805573 -0.607837,-1.215689 -8.83711,-20.666457 -8.83711,-20.666457 0,0 -0.935026,-2.571826 -5.096422,-3.179669 z m -14.283078,7.201629 13.092779,0.06622 8.463775,19.440614 -0.06602,1.917516 H 41.923187 L 31.343205,41.053641 Z m -7.18526,34.252739 a 5.2734399,5.2734399 0 0 1 5.273364,5.27337 5.2734399,5.2734399 0 0 1 -5.273364,5.273369 5.2734399,5.2734399 0 0 1 -5.273628,-5.273369 5.2734399,5.2734399 0 0 1 5.273628,-5.27337 z m 28.802424,0 a 5.2734399,5.2734399 0 0 1 5.273363,5.27337 5.2734399,5.2734399 0 0 1 -5.273363,5.273369 5.2734399,5.2734399 0 0 1 -5.273626,-5.273369 5.2734399,5.2734399 0 0 1 5.273626,-5.27337 z"
|
||||
style="fill:#501616;stroke:none;stroke-width:0.1309201px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
id="path4582"
|
||||
inkscape:export-xdpi="91.327972"
|
||||
inkscape:export-ydpi="91.327972" />
|
||||
<path
|
||||
id="path61-3"
|
||||
style="fill:#ffffff;stroke:#ffffff;stroke-width:0.1309201px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 67.229989,22.903912 0.14027,46.803935 c 0,0 0.374059,1.542981 1.730014,1.917051 h 14.307701 c 0,0 1.636494,-0.467579 1.917043,-1.776775 v -3.834094 c 0,0 -0.467568,-1.542985 -1.823534,-1.77677 -1.355955,-0.233787 -9.024128,0 -9.024128,0 V 23.184453 c 0,0 -0.23379,-1.823526 -1.683265,-1.870286 h -3.693817 c 0,0 -1.402715,-0.04676 -1.870284,1.589745 z m -20.152241,-1.636565 -15.944384,0.0468 c 0,0 -5.564103,0.654568 -5.564103,5.517309 l 0.04681,12.484207 -5.376931,0.09359 c 0,0 -4.628961,-0.420742 -5.564104,5.330392 l 0.233712,23.284857 c 0,0 0.888353,10.801089 10.754117,10.707579 9.865764,-0.09354 10.754117,-10.660784 10.754117,-10.660784 l 7.153819,-0.04682 c 0,0 0.607805,10.754338 10.75411,10.707578 0,0 10.473823,-0.140456 10.754372,-10.707578 0,0 -0.140269,-4.956187 -3.600297,-8.088919 V 47.919051 c 0,0 0.14016,-1.589888 -0.467689,-2.805573 -0.607837,-1.215689 -8.83711,-20.666457 -8.83711,-20.666457 0,0 -0.935026,-2.571826 -5.096422,-3.179669 z m -14.283078,7.201629 13.092779,0.06622 8.463775,19.440614 -0.06602,1.917516 H 43.440823 L 32.860841,39.313608 Z m -7.18526,34.252739 a 5.2734399,5.2734399 0 0 1 5.273364,5.27337 5.2734399,5.2734399 0 0 1 -5.273364,5.273369 5.2734399,5.2734399 0 0 1 -5.273628,-5.273369 5.2734399,5.2734399 0 0 1 5.273628,-5.27337 z m 28.802424,0 a 5.2734399,5.2734399 0 0 1 5.273363,5.27337 5.2734399,5.2734399 0 0 1 -5.273363,5.273369 5.2734399,5.2734399 0 0 1 -5.273626,-5.273369 5.2734399,5.2734399 0 0 1 5.273626,-5.27337 z"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:export-xdpi="91.327972"
|
||||
inkscape:export-ydpi="91.327972" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.5 KiB |
467
stock_request/static/description/index.html
Normal file
467
stock_request/static/description/index.html
Normal file
@@ -0,0 +1,467 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.15.1: http://docutils.sourceforge.net/" />
|
||||
<title>Stock Request</title>
|
||||
<style type="text/css">
|
||||
|
||||
/*
|
||||
:Author: David Goodger (goodger@python.org)
|
||||
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
|
||||
:Copyright: This stylesheet has been placed in the public domain.
|
||||
|
||||
Default cascading style sheet for the HTML output of Docutils.
|
||||
|
||||
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
|
||||
customize this style sheet.
|
||||
*/
|
||||
|
||||
/* used to remove borders from tables and images */
|
||||
.borderless, table.borderless td, table.borderless th {
|
||||
border: 0 }
|
||||
|
||||
table.borderless td, table.borderless th {
|
||||
/* Override padding for "table.docutils td" with "! important".
|
||||
The right padding separates the table cells. */
|
||||
padding: 0 0.5em 0 0 ! important }
|
||||
|
||||
.first {
|
||||
/* Override more specific margin styles with "! important". */
|
||||
margin-top: 0 ! important }
|
||||
|
||||
.last, .with-subtitle {
|
||||
margin-bottom: 0 ! important }
|
||||
|
||||
.hidden {
|
||||
display: none }
|
||||
|
||||
.subscript {
|
||||
vertical-align: sub;
|
||||
font-size: smaller }
|
||||
|
||||
.superscript {
|
||||
vertical-align: super;
|
||||
font-size: smaller }
|
||||
|
||||
a.toc-backref {
|
||||
text-decoration: none ;
|
||||
color: black }
|
||||
|
||||
blockquote.epigraph {
|
||||
margin: 2em 5em ; }
|
||||
|
||||
dl.docutils dd {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Uncomment (and remove this text!) to get bold-faced definition list terms
|
||||
dl.docutils dt {
|
||||
font-weight: bold }
|
||||
*/
|
||||
|
||||
div.abstract {
|
||||
margin: 2em 5em }
|
||||
|
||||
div.abstract p.topic-title {
|
||||
font-weight: bold ;
|
||||
text-align: center }
|
||||
|
||||
div.admonition, div.attention, div.caution, div.danger, div.error,
|
||||
div.hint, div.important, div.note, div.tip, div.warning {
|
||||
margin: 2em ;
|
||||
border: medium outset ;
|
||||
padding: 1em }
|
||||
|
||||
div.admonition p.admonition-title, div.hint p.admonition-title,
|
||||
div.important p.admonition-title, div.note p.admonition-title,
|
||||
div.tip p.admonition-title {
|
||||
font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
div.attention p.admonition-title, div.caution p.admonition-title,
|
||||
div.danger p.admonition-title, div.error p.admonition-title,
|
||||
div.warning p.admonition-title, .code .error {
|
||||
color: red ;
|
||||
font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
/* Uncomment (and remove this text!) to get reduced vertical space in
|
||||
compound paragraphs.
|
||||
div.compound .compound-first, div.compound .compound-middle {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
div.compound .compound-last, div.compound .compound-middle {
|
||||
margin-top: 0.5em }
|
||||
*/
|
||||
|
||||
div.dedication {
|
||||
margin: 2em 5em ;
|
||||
text-align: center ;
|
||||
font-style: italic }
|
||||
|
||||
div.dedication p.topic-title {
|
||||
font-weight: bold ;
|
||||
font-style: normal }
|
||||
|
||||
div.figure {
|
||||
margin-left: 2em ;
|
||||
margin-right: 2em }
|
||||
|
||||
div.footer, div.header {
|
||||
clear: both;
|
||||
font-size: smaller }
|
||||
|
||||
div.line-block {
|
||||
display: block ;
|
||||
margin-top: 1em ;
|
||||
margin-bottom: 1em }
|
||||
|
||||
div.line-block div.line-block {
|
||||
margin-top: 0 ;
|
||||
margin-bottom: 0 ;
|
||||
margin-left: 1.5em }
|
||||
|
||||
div.sidebar {
|
||||
margin: 0 0 0.5em 1em ;
|
||||
border: medium outset ;
|
||||
padding: 1em ;
|
||||
background-color: #ffffee ;
|
||||
width: 40% ;
|
||||
float: right ;
|
||||
clear: right }
|
||||
|
||||
div.sidebar p.rubric {
|
||||
font-family: sans-serif ;
|
||||
font-size: medium }
|
||||
|
||||
div.system-messages {
|
||||
margin: 5em }
|
||||
|
||||
div.system-messages h1 {
|
||||
color: red }
|
||||
|
||||
div.system-message {
|
||||
border: medium outset ;
|
||||
padding: 1em }
|
||||
|
||||
div.system-message p.system-message-title {
|
||||
color: red ;
|
||||
font-weight: bold }
|
||||
|
||||
div.topic {
|
||||
margin: 2em }
|
||||
|
||||
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
|
||||
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
|
||||
margin-top: 0.4em }
|
||||
|
||||
h1.title {
|
||||
text-align: center }
|
||||
|
||||
h2.subtitle {
|
||||
text-align: center }
|
||||
|
||||
hr.docutils {
|
||||
width: 75% }
|
||||
|
||||
img.align-left, .figure.align-left, object.align-left, table.align-left {
|
||||
clear: left ;
|
||||
float: left ;
|
||||
margin-right: 1em }
|
||||
|
||||
img.align-right, .figure.align-right, object.align-right, table.align-right {
|
||||
clear: right ;
|
||||
float: right ;
|
||||
margin-left: 1em }
|
||||
|
||||
img.align-center, .figure.align-center, object.align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table.align-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left }
|
||||
|
||||
.align-center {
|
||||
clear: both ;
|
||||
text-align: center }
|
||||
|
||||
.align-right {
|
||||
text-align: right }
|
||||
|
||||
/* reset inner alignment in figures */
|
||||
div.align-right {
|
||||
text-align: inherit }
|
||||
|
||||
/* div.align-center * { */
|
||||
/* text-align: left } */
|
||||
|
||||
.align-top {
|
||||
vertical-align: top }
|
||||
|
||||
.align-middle {
|
||||
vertical-align: middle }
|
||||
|
||||
.align-bottom {
|
||||
vertical-align: bottom }
|
||||
|
||||
ol.simple, ul.simple {
|
||||
margin-bottom: 1em }
|
||||
|
||||
ol.arabic {
|
||||
list-style: decimal }
|
||||
|
||||
ol.loweralpha {
|
||||
list-style: lower-alpha }
|
||||
|
||||
ol.upperalpha {
|
||||
list-style: upper-alpha }
|
||||
|
||||
ol.lowerroman {
|
||||
list-style: lower-roman }
|
||||
|
||||
ol.upperroman {
|
||||
list-style: upper-roman }
|
||||
|
||||
p.attribution {
|
||||
text-align: right ;
|
||||
margin-left: 50% }
|
||||
|
||||
p.caption {
|
||||
font-style: italic }
|
||||
|
||||
p.credits {
|
||||
font-style: italic ;
|
||||
font-size: smaller }
|
||||
|
||||
p.label {
|
||||
white-space: nowrap }
|
||||
|
||||
p.rubric {
|
||||
font-weight: bold ;
|
||||
font-size: larger ;
|
||||
color: maroon ;
|
||||
text-align: center }
|
||||
|
||||
p.sidebar-title {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold ;
|
||||
font-size: larger }
|
||||
|
||||
p.sidebar-subtitle {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold }
|
||||
|
||||
p.topic-title {
|
||||
font-weight: bold }
|
||||
|
||||
pre.address {
|
||||
margin-bottom: 0 ;
|
||||
margin-top: 0 ;
|
||||
font: inherit }
|
||||
|
||||
pre.literal-block, pre.doctest-block, pre.math, pre.code {
|
||||
margin-left: 2em ;
|
||||
margin-right: 2em }
|
||||
|
||||
pre.code .ln { color: grey; } /* line numbers */
|
||||
pre.code, code { background-color: #eeeeee }
|
||||
pre.code .comment, code .comment { color: #5C6576 }
|
||||
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
|
||||
pre.code .literal.string, code .literal.string { color: #0C5404 }
|
||||
pre.code .name.builtin, code .name.builtin { color: #352B84 }
|
||||
pre.code .deleted, code .deleted { background-color: #DEB0A1}
|
||||
pre.code .inserted, code .inserted { background-color: #A3D289}
|
||||
|
||||
span.classifier {
|
||||
font-family: sans-serif ;
|
||||
font-style: oblique }
|
||||
|
||||
span.classifier-delimiter {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold }
|
||||
|
||||
span.interpreted {
|
||||
font-family: sans-serif }
|
||||
|
||||
span.option {
|
||||
white-space: nowrap }
|
||||
|
||||
span.pre {
|
||||
white-space: pre }
|
||||
|
||||
span.problematic {
|
||||
color: red }
|
||||
|
||||
span.section-subtitle {
|
||||
/* font-size relative to parent (h1..h6 element) */
|
||||
font-size: 80% }
|
||||
|
||||
table.citation {
|
||||
border-left: solid 1px gray;
|
||||
margin-left: 1px }
|
||||
|
||||
table.docinfo {
|
||||
margin: 2em 4em }
|
||||
|
||||
table.docutils {
|
||||
margin-top: 0.5em ;
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
table.footnote {
|
||||
border-left: solid 1px black;
|
||||
margin-left: 1px }
|
||||
|
||||
table.docutils td, table.docutils th,
|
||||
table.docinfo td, table.docinfo th {
|
||||
padding-left: 0.5em ;
|
||||
padding-right: 0.5em ;
|
||||
vertical-align: top }
|
||||
|
||||
table.docutils th.field-name, table.docinfo th.docinfo-name {
|
||||
font-weight: bold ;
|
||||
text-align: left ;
|
||||
white-space: nowrap ;
|
||||
padding-left: 0 }
|
||||
|
||||
/* "booktabs" style (no vertical lines) */
|
||||
table.docutils.booktabs {
|
||||
border: 0px;
|
||||
border-top: 2px solid;
|
||||
border-bottom: 2px solid;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table.docutils.booktabs * {
|
||||
border: 0px;
|
||||
}
|
||||
table.docutils.booktabs th {
|
||||
border-bottom: thin solid;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
|
||||
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
|
||||
font-size: 100% }
|
||||
|
||||
ul.auto-toc {
|
||||
list-style-type: none }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="stock-request">
|
||||
<h1 class="title">Stock Request</h1>
|
||||
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/lgpl-3.0-standalone.html"><img alt="License: LGPL-3" src="https://img.shields.io/badge/licence-LGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/stock-logistics-warehouse/tree/12.0/stock_request"><img alt="OCA/stock-logistics-warehouse" src="https://img.shields.io/badge/github-OCA%2Fstock--logistics--warehouse-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/stock-logistics-warehouse-12-0/stock-logistics-warehouse-12-0-stock_request"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/153/12.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
|
||||
<p>This module was written to allow users to request products that are
|
||||
frequently stocked by the company, to be transferred to their chosen location.</p>
|
||||
<p><strong>Table of contents</strong></p>
|
||||
<div class="contents local topic" id="contents">
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#configuration" id="id1">Configuration</a></li>
|
||||
<li><a class="reference internal" href="#usage" id="id2">Usage</a></li>
|
||||
<li><a class="reference internal" href="#bug-tracker" id="id3">Bug Tracker</a></li>
|
||||
<li><a class="reference internal" href="#credits" id="id4">Credits</a><ul>
|
||||
<li><a class="reference internal" href="#authors" id="id5">Authors</a></li>
|
||||
<li><a class="reference internal" href="#contributors" id="id6">Contributors</a></li>
|
||||
<li><a class="reference internal" href="#maintainers" id="id7">Maintainers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="configuration">
|
||||
<h1><a class="toc-backref" href="#id1">Configuration</a></h1>
|
||||
<p>To configure this module:</p>
|
||||
<ul class="simple">
|
||||
<li>Go to Stock Requests > Settings</li>
|
||||
</ul>
|
||||
<p>Users should be assigned to the groups ‘Stock Request / User’ or ‘Stock
|
||||
Request / Manager’.</p>
|
||||
<p>## Group Stock Request / User</p>
|
||||
<ul class="simple">
|
||||
<li>Can see her/his own Stock Requests, and others that she/he’s been granted
|
||||
permission to follow.</li>
|
||||
<li>Can create/update only her/his Stock Requests.</li>
|
||||
</ul>
|
||||
<p>## Group Stock Request / Manager</p>
|
||||
<ul class="simple">
|
||||
<li>Can fully manage all Stock Requests</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="usage">
|
||||
<h1><a class="toc-backref" href="#id2">Usage</a></h1>
|
||||
<p>## Creation</p>
|
||||
<ul class="simple">
|
||||
<li>Go to ‘Stock Requests / Stock Requests’ and create a new Request.</li>
|
||||
<li>Indicate a product, quantity and location.</li>
|
||||
<li>Press ‘Confirm’.</li>
|
||||
</ul>
|
||||
<p>Upon confirmation the request will be evaluated using the procurement rules
|
||||
for the selected location.</p>
|
||||
<p>In case that transfers are created, the user will be able to access to them
|
||||
from the button ‘Transfers’ available in the Stock Request.</p>
|
||||
<p>## Cancel</p>
|
||||
<p>When the user cancels a Stock Request, the related pending stock moves will be
|
||||
also cancelled.</p>
|
||||
</div>
|
||||
<div class="section" id="bug-tracker">
|
||||
<h1><a class="toc-backref" href="#id3">Bug Tracker</a></h1>
|
||||
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/stock-logistics-warehouse/issues">GitHub Issues</a>.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us smashing it by providing a detailed and welcomed
|
||||
<a class="reference external" href="https://github.com/OCA/stock-logistics-warehouse/issues/new?body=module:%20stock_request%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
|
||||
<p>Do not contact contributors directly about support or help with technical issues.</p>
|
||||
</div>
|
||||
<div class="section" id="credits">
|
||||
<h1><a class="toc-backref" href="#id4">Credits</a></h1>
|
||||
<div class="section" id="authors">
|
||||
<h2><a class="toc-backref" href="#id5">Authors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Eficent</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="contributors">
|
||||
<h2><a class="toc-backref" href="#id6">Contributors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Jordi Ballester (EFICENT) <<a class="reference external" href="mailto:jordi.ballester@eficent.com">jordi.ballester@eficent.com</a>>.</li>
|
||||
<li>Enric Tobella <<a class="reference external" href="mailto:etobella@creublanca.es">etobella@creublanca.es</a>></li>
|
||||
<li>Atte Isopuro <<a class="reference external" href="mailto:atte.isopuro@avoin.systems">atte.isopuro@avoin.systems</a>></li>
|
||||
<li>Lois Rilo <<a class="reference external" href="mailto:lois.rilo@eficent.com">lois.rilo@eficent.com</a>></li>
|
||||
<li>Raul Martin <<a class="reference external" href="mailto:raul.martin@braintec-group.com">raul.martin@braintec-group.com</a>></li>
|
||||
<li>Serpent Consulting Services Pvt. Ltd. <<a class="reference external" href="mailto:support@serpentcs.com">support@serpentcs.com</a>></li>
|
||||
<li><a class="reference external" href="https://www.opensourceintegrators.com">Open Source Integrators</a><ul>
|
||||
<li>Maxime Chambreuil <<a class="reference external" href="mailto:mchambreuil@opensourceintegrators.com">mchambreuil@opensourceintegrators.com</a>></li>
|
||||
<li>Steve Campbell <<a class="reference external" href="mailto:scampbell@opensourceintegrators.com">scampbell@opensourceintegrators.com</a>></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="maintainers">
|
||||
<h2><a class="toc-backref" href="#id7">Maintainers</a></h2>
|
||||
<p>This module is maintained by the OCA.</p>
|
||||
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
|
||||
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||
mission is to support the collaborative development of Odoo features and
|
||||
promote its widespread use.</p>
|
||||
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/stock-logistics-warehouse/tree/12.0/stock_request">OCA/stock-logistics-warehouse</a> project on GitHub.</p>
|
||||
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
1
stock_request/tests/__init__.py
Normal file
1
stock_request/tests/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import test_stock_request
|
||||
995
stock_request/tests/test_stock_request.py
Normal file
995
stock_request/tests/test_stock_request.py
Normal file
@@ -0,0 +1,995 @@
|
||||
# Copyright 2017 Eficent Business and IT Consulting Services S.L.
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0).
|
||||
|
||||
from collections import Counter
|
||||
from datetime import datetime
|
||||
|
||||
from odoo import exceptions, fields
|
||||
from odoo.tests import common
|
||||
|
||||
|
||||
class TestStockRequest(common.TransactionCase):
|
||||
def setUp(self):
|
||||
super(TestStockRequest, self).setUp()
|
||||
|
||||
# common models
|
||||
self.stock_request = self.env["stock.request"]
|
||||
self.request_order = self.env["stock.request.order"]
|
||||
|
||||
# refs
|
||||
self.stock_request_user_group = self.env.ref(
|
||||
"stock_request.group_stock_request_user"
|
||||
)
|
||||
self.stock_request_manager_group = self.env.ref(
|
||||
"stock_request.group_stock_request_manager"
|
||||
)
|
||||
self.main_company = self.env.ref("base.main_company")
|
||||
self.warehouse = self.env.ref("stock.warehouse0")
|
||||
self.categ_unit = self.env.ref("uom.product_uom_categ_unit")
|
||||
self.virtual_loc = self.env.ref("stock.stock_location_customers")
|
||||
|
||||
# common data
|
||||
self.company_2 = self.env["res.company"].create(
|
||||
{"name": "Comp2", "parent_id": self.main_company.id}
|
||||
)
|
||||
self.company_2_address = (
|
||||
self.env["res.partner"]
|
||||
.with_context(company_id=self.company_2.id)
|
||||
.create({"name": "Peñiscola"})
|
||||
)
|
||||
self.wh2 = self.env["stock.warehouse"].search(
|
||||
[("company_id", "=", self.company_2.id)], limit=1
|
||||
)
|
||||
self.stock_request_user = self._create_user(
|
||||
"stock_request_user",
|
||||
[self.stock_request_user_group.id],
|
||||
[self.main_company.id, self.company_2.id],
|
||||
)
|
||||
self.stock_request_manager = self._create_user(
|
||||
"stock_request_manager",
|
||||
[self.stock_request_manager_group.id],
|
||||
[self.main_company.id, self.company_2.id],
|
||||
)
|
||||
self.product = self._create_product("SH", "Shoes", False)
|
||||
self.product_company_2 = self._create_product(
|
||||
"SH_2", "Shoes", self.company_2.id
|
||||
)
|
||||
|
||||
self.ressuply_loc = self.env["stock.location"].create(
|
||||
{
|
||||
"name": "Ressuply",
|
||||
"location_id": self.warehouse.view_location_id.id,
|
||||
"usage": "internal",
|
||||
"company_id": self.main_company.id,
|
||||
}
|
||||
)
|
||||
|
||||
self.ressuply_loc_2 = self.env["stock.location"].create(
|
||||
{
|
||||
"name": "Ressuply",
|
||||
"location_id": self.wh2.view_location_id.id,
|
||||
"usage": "internal",
|
||||
"company_id": self.company_2.id,
|
||||
}
|
||||
)
|
||||
|
||||
self.route = self.env["stock.location.route"].create(
|
||||
{
|
||||
"name": "Transfer",
|
||||
"product_categ_selectable": False,
|
||||
"product_selectable": True,
|
||||
"company_id": self.main_company.id,
|
||||
"sequence": 10,
|
||||
}
|
||||
)
|
||||
|
||||
self.route_2 = self.env["stock.location.route"].create(
|
||||
{
|
||||
"name": "Transfer",
|
||||
"product_categ_selectable": False,
|
||||
"product_selectable": True,
|
||||
"company_id": self.company_2.id,
|
||||
"sequence": 10,
|
||||
}
|
||||
)
|
||||
|
||||
self.uom_dozen = self.env["uom.uom"].create(
|
||||
{
|
||||
"name": "Test-DozenA",
|
||||
"category_id": self.categ_unit.id,
|
||||
"factor_inv": 12,
|
||||
"uom_type": "bigger",
|
||||
"rounding": 0.001,
|
||||
}
|
||||
)
|
||||
|
||||
self.env["stock.rule"].create(
|
||||
{
|
||||
"name": "Transfer",
|
||||
"route_id": self.route.id,
|
||||
"location_src_id": self.ressuply_loc.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
"action": "pull",
|
||||
"picking_type_id": self.warehouse.int_type_id.id,
|
||||
"procure_method": "make_to_stock",
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"company_id": self.main_company.id,
|
||||
}
|
||||
)
|
||||
|
||||
self.env["stock.rule"].create(
|
||||
{
|
||||
"name": "Transfer",
|
||||
"route_id": self.route_2.id,
|
||||
"location_src_id": self.ressuply_loc_2.id,
|
||||
"location_id": self.wh2.lot_stock_id.id,
|
||||
"action": "pull",
|
||||
"picking_type_id": self.wh2.int_type_id.id,
|
||||
"procure_method": "make_to_stock",
|
||||
"warehouse_id": self.wh2.id,
|
||||
"company_id": self.company_2.id,
|
||||
}
|
||||
)
|
||||
|
||||
def _create_user(self, name, group_ids, company_ids):
|
||||
return (
|
||||
self.env["res.users"]
|
||||
.with_context({"no_reset_password": True})
|
||||
.create(
|
||||
{
|
||||
"name": name,
|
||||
"password": "demo",
|
||||
"login": name,
|
||||
"email": "@".join([name, "test.com"]),
|
||||
"groups_id": [(6, 0, group_ids)],
|
||||
"company_ids": [(6, 0, company_ids)],
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
def _create_product(self, default_code, name, company_id, **vals):
|
||||
return self.env["product.product"].create(
|
||||
dict(
|
||||
name=name,
|
||||
default_code=default_code,
|
||||
uom_id=self.env.ref("uom.product_uom_unit").id,
|
||||
company_id=company_id,
|
||||
type="product",
|
||||
**vals
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class TestStockRequestBase(TestStockRequest):
|
||||
def setUp(self):
|
||||
super(TestStockRequestBase, self).setUp()
|
||||
|
||||
def test_defaults(self):
|
||||
vals = {
|
||||
"product_id": self.product.id,
|
||||
"product_uom_id": self.product.uom_id.id,
|
||||
"product_uom_qty": 5.0,
|
||||
}
|
||||
stock_request = (
|
||||
self.stock_request.with_user(self.stock_request_user)
|
||||
.with_context(company_id=self.main_company.id)
|
||||
.create(vals)
|
||||
)
|
||||
|
||||
self.assertEqual(stock_request.requested_by, self.stock_request_user)
|
||||
|
||||
self.assertEqual(stock_request.warehouse_id, self.warehouse)
|
||||
|
||||
self.assertEqual(stock_request.location_id, self.warehouse.lot_stock_id)
|
||||
|
||||
def test_defaults_order(self):
|
||||
vals = {}
|
||||
order = (
|
||||
self.request_order.with_user(self.stock_request_user)
|
||||
.with_context(company_id=self.main_company.id)
|
||||
.create(vals)
|
||||
)
|
||||
|
||||
self.assertEqual(order.requested_by, self.stock_request_user)
|
||||
|
||||
self.assertEqual(order.warehouse_id, self.warehouse)
|
||||
|
||||
self.assertEqual(order.location_id, self.warehouse.lot_stock_id)
|
||||
|
||||
def test_onchanges_order(self):
|
||||
expected_date = fields.Datetime.now()
|
||||
vals = {
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
"expected_date": expected_date,
|
||||
"stock_request_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_id": self.product.id,
|
||||
"product_uom_id": self.product.uom_id.id,
|
||||
"product_uom_qty": 5.0,
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
"expected_date": expected_date,
|
||||
},
|
||||
)
|
||||
],
|
||||
}
|
||||
order = self.request_order.with_user(self.stock_request_user).new(vals)
|
||||
self.stock_request_user.company_id = self.company_2
|
||||
order.company_id = self.company_2
|
||||
|
||||
order.onchange_company_id()
|
||||
|
||||
stock_request = order.stock_request_ids
|
||||
self.assertEqual(order.warehouse_id, self.wh2)
|
||||
self.assertEqual(order.location_id, self.wh2.lot_stock_id)
|
||||
self.assertEqual(order.warehouse_id, stock_request.warehouse_id)
|
||||
|
||||
procurement_group = self.env["procurement.group"].create({"name": "TEST"})
|
||||
order.procurement_group_id = procurement_group
|
||||
order.onchange_procurement_group_id()
|
||||
self.assertEqual(
|
||||
order.procurement_group_id, order.stock_request_ids.procurement_group_id
|
||||
)
|
||||
|
||||
order.procurement_group_id = procurement_group
|
||||
order.onchange_procurement_group_id()
|
||||
self.assertEqual(
|
||||
order.procurement_group_id, order.stock_request_ids.procurement_group_id
|
||||
)
|
||||
order.picking_policy = "one"
|
||||
|
||||
order.onchange_picking_policy()
|
||||
self.assertEqual(order.picking_policy, order.stock_request_ids.picking_policy)
|
||||
|
||||
order.expected_date = datetime.now()
|
||||
order.onchange_expected_date()
|
||||
self.assertEqual(order.expected_date, order.stock_request_ids.expected_date)
|
||||
|
||||
order.requested_by = self.stock_request_manager
|
||||
order.onchange_requested_by()
|
||||
self.assertEqual(order.requested_by, order.stock_request_ids.requested_by)
|
||||
|
||||
def test_onchanges(self):
|
||||
self.product.route_ids = [(6, 0, self.route.ids)]
|
||||
vals = {
|
||||
"product_uom_id": self.product.uom_id.id,
|
||||
"product_uom_qty": 5.0,
|
||||
"company_id": self.main_company.id,
|
||||
}
|
||||
stock_request = self.stock_request.with_user(self.stock_request_user).new(vals)
|
||||
stock_request.product_id = self.product
|
||||
vals = stock_request.default_get(["warehouse_id", "company_id"])
|
||||
stock_request.update(vals)
|
||||
stock_request.onchange_product_id()
|
||||
self.assertIn(self.route.id, stock_request.route_ids.ids)
|
||||
|
||||
self.stock_request_user.company_id = self.company_2
|
||||
stock_request.company_id = self.company_2
|
||||
stock_request.onchange_company_id()
|
||||
|
||||
self.assertEqual(stock_request.warehouse_id, self.wh2)
|
||||
self.assertEqual(stock_request.location_id, self.wh2.lot_stock_id)
|
||||
|
||||
product = self.env["product.product"].create(
|
||||
{
|
||||
"name": "Wheat",
|
||||
"uom_id": self.env.ref("uom.product_uom_kgm").id,
|
||||
"uom_po_id": self.env.ref("uom.product_uom_kgm").id,
|
||||
}
|
||||
)
|
||||
|
||||
# Test onchange_product_id
|
||||
stock_request.product_id = product
|
||||
res = stock_request.onchange_product_id()
|
||||
|
||||
self.assertEqual(
|
||||
res["domain"]["product_uom_id"],
|
||||
[("category_id", "=", product.uom_id.category_id.id)],
|
||||
)
|
||||
self.assertEqual(
|
||||
stock_request.product_uom_id, self.env.ref("uom.product_uom_kgm")
|
||||
)
|
||||
|
||||
stock_request.product_id = self.env["product.product"]
|
||||
res = stock_request.onchange_product_id()
|
||||
|
||||
self.assertEqual(res["domain"]["product_uom_id"], [])
|
||||
|
||||
# Test onchange_warehouse_id
|
||||
wh2_2 = (
|
||||
self.env["stock.warehouse"]
|
||||
.with_context(company_id=self.company_2.id)
|
||||
.create(
|
||||
{
|
||||
"name": "C2_2",
|
||||
"code": "C2_2",
|
||||
"company_id": self.company_2.id,
|
||||
"partner_id": self.company_2_address.id,
|
||||
}
|
||||
)
|
||||
)
|
||||
stock_request.warehouse_id = wh2_2
|
||||
stock_request.onchange_warehouse_id()
|
||||
|
||||
self.assertEqual(stock_request.warehouse_id, wh2_2)
|
||||
|
||||
self.stock_request_user.company_id = self.main_company
|
||||
stock_request.warehouse_id = self.warehouse
|
||||
stock_request.onchange_warehouse_id()
|
||||
|
||||
self.assertEqual(stock_request.company_id, self.main_company)
|
||||
self.assertEqual(stock_request.location_id, self.warehouse.lot_stock_id)
|
||||
|
||||
def test_stock_request_order_validations_01(self):
|
||||
""" Testing the discrepancy in warehouse_id between
|
||||
stock request and order"""
|
||||
expected_date = fields.Datetime.now()
|
||||
vals = {
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.wh2.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
"expected_date": expected_date,
|
||||
"stock_request_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_id": self.product.id,
|
||||
"product_uom_id": self.product.uom_id.id,
|
||||
"product_uom_qty": 5.0,
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
"expected_date": expected_date,
|
||||
},
|
||||
)
|
||||
],
|
||||
}
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
self.request_order.with_user(self.stock_request_user).create(vals)
|
||||
|
||||
def test_stock_request_order_validations_02(self):
|
||||
""" Testing the discrepancy in location_id between
|
||||
stock request and order"""
|
||||
expected_date = fields.Datetime.now()
|
||||
vals = {
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.wh2.lot_stock_id.id,
|
||||
"expected_date": expected_date,
|
||||
"stock_request_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_id": self.product.id,
|
||||
"product_uom_id": self.product.uom_id.id,
|
||||
"product_uom_qty": 5.0,
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
"expected_date": expected_date,
|
||||
},
|
||||
)
|
||||
],
|
||||
}
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
self.request_order.with_user(self.stock_request_user).create(vals)
|
||||
|
||||
def test_stock_request_order_validations_03(self):
|
||||
""" Testing the discrepancy in requested_by between
|
||||
stock request and order"""
|
||||
expected_date = fields.Datetime.now()
|
||||
vals = {
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
"requested_by": self.stock_request_user.id,
|
||||
"expected_date": expected_date,
|
||||
"stock_request_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_id": self.product.id,
|
||||
"product_uom_id": self.product.uom_id.id,
|
||||
"product_uom_qty": 5.0,
|
||||
"requested_by": self.stock_request_manager.id,
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
"expected_date": expected_date,
|
||||
},
|
||||
)
|
||||
],
|
||||
}
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
self.request_order.with_user(self.stock_request_user).create(vals)
|
||||
|
||||
def test_stock_request_order_validations_04(self):
|
||||
""" Testing the discrepancy in procurement_group_id between
|
||||
stock request and order"""
|
||||
procurement_group = self.env["procurement.group"].create(
|
||||
{"name": "Procurement"}
|
||||
)
|
||||
expected_date = fields.Datetime.now()
|
||||
vals = {
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
"procurement_group_id": procurement_group.id,
|
||||
"expected_date": expected_date,
|
||||
"stock_request_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_id": self.product.id,
|
||||
"product_uom_id": self.product.uom_id.id,
|
||||
"product_uom_qty": 5.0,
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
"expected_date": expected_date,
|
||||
},
|
||||
)
|
||||
],
|
||||
}
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
self.request_order.with_user(self.stock_request_user).create(vals)
|
||||
|
||||
def test_stock_request_order_validations_05(self):
|
||||
""" Testing the discrepancy in company between
|
||||
stock request and order"""
|
||||
expected_date = fields.Datetime.now()
|
||||
vals = {
|
||||
"company_id": self.company_2.id,
|
||||
"warehouse_id": self.wh2.id,
|
||||
"location_id": self.wh2.lot_stock_id.id,
|
||||
"expected_date": expected_date,
|
||||
"stock_request_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_id": self.product.id,
|
||||
"product_uom_id": self.product.uom_id.id,
|
||||
"product_uom_qty": 5.0,
|
||||
"company_id": self.company_2.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
"expected_date": expected_date,
|
||||
},
|
||||
)
|
||||
],
|
||||
}
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
self.request_order.with_user(self.stock_request_user).create(vals)
|
||||
|
||||
def test_stock_request_order_validations_06(self):
|
||||
""" Testing the discrepancy in expected dates between
|
||||
stock request and order"""
|
||||
expected_date = fields.Datetime.now()
|
||||
child_expected_date = "2015-01-01"
|
||||
vals = {
|
||||
"company_id": self.company_2.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
"expected_date": expected_date,
|
||||
"stock_request_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_id": self.product.id,
|
||||
"product_uom_id": self.product.uom_id.id,
|
||||
"product_uom_qty": 5.0,
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
"expected_date": child_expected_date,
|
||||
},
|
||||
)
|
||||
],
|
||||
}
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
self.request_order.create(vals)
|
||||
|
||||
def test_stock_request_order_validations_07(self):
|
||||
""" Testing the discrepancy in picking policy between
|
||||
stock request and order"""
|
||||
expected_date = fields.Datetime.now()
|
||||
vals = {
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
"picking_policy": "one",
|
||||
"expected_date": expected_date,
|
||||
"stock_request_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_id": self.product.id,
|
||||
"product_uom_id": self.product.uom_id.id,
|
||||
"product_uom_qty": 5.0,
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
"expected_date": expected_date,
|
||||
},
|
||||
)
|
||||
],
|
||||
}
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
self.request_order.with_user(self.stock_request_user).create(vals)
|
||||
|
||||
def test_stock_request_validations_01(self):
|
||||
vals = {
|
||||
"product_id": self.product.id,
|
||||
"product_uom_id": self.env.ref("uom.product_uom_kgm").id,
|
||||
"product_uom_qty": 5.0,
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
}
|
||||
# Select a UoM that is incompatible with the product's UoM
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
self.stock_request.with_user(self.stock_request_user).create(vals)
|
||||
|
||||
def test_stock_request_validations_02(self):
|
||||
vals = {
|
||||
"product_id": self.product.id,
|
||||
"product_uom_id": self.product.uom_id.id,
|
||||
"product_uom_qty": 5.0,
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
}
|
||||
|
||||
stock_request = self.stock_request.with_user(self.stock_request_user).create(
|
||||
vals
|
||||
)
|
||||
|
||||
# With no route found, should raise an error
|
||||
with self.assertRaises(exceptions.UserError):
|
||||
stock_request.action_confirm()
|
||||
|
||||
def test_create_request_01(self):
|
||||
expected_date = fields.Datetime.now()
|
||||
vals = {
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
"expected_date": expected_date,
|
||||
"stock_request_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_id": self.product.id,
|
||||
"product_uom_id": self.product.uom_id.id,
|
||||
"product_uom_qty": 5.0,
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
"expected_date": expected_date,
|
||||
},
|
||||
)
|
||||
],
|
||||
}
|
||||
|
||||
order = self.request_order.with_user(self.stock_request_user).create(vals)
|
||||
|
||||
stock_request = order.stock_request_ids
|
||||
|
||||
self.product.route_ids = [(6, 0, self.route.ids)]
|
||||
order.with_user(self.stock_request_user).action_confirm()
|
||||
self.assertEqual(order.state, "open")
|
||||
self.assertEqual(stock_request.state, "open")
|
||||
|
||||
self.assertEqual(len(order.picking_ids), 1)
|
||||
self.assertEqual(len(order.move_ids), 1)
|
||||
self.assertEqual(len(stock_request.picking_ids), 1)
|
||||
self.assertEqual(len(stock_request.move_ids), 1)
|
||||
self.assertEqual(
|
||||
stock_request.move_ids[0].location_dest_id, stock_request.location_id
|
||||
)
|
||||
self.assertEqual(stock_request.qty_in_progress, stock_request.product_uom_qty)
|
||||
self.env["stock.quant"].create(
|
||||
{
|
||||
"product_id": self.product.id,
|
||||
"location_id": self.ressuply_loc.id,
|
||||
"quantity": 5.0,
|
||||
}
|
||||
)
|
||||
picking = stock_request.picking_ids[0]
|
||||
picking.with_user(self.stock_request_manager).action_confirm()
|
||||
self.assertEqual(stock_request.qty_in_progress, 5.0)
|
||||
self.assertEqual(stock_request.qty_done, 0.0)
|
||||
picking.with_user(self.stock_request_manager).action_assign()
|
||||
self.assertEqual(picking.origin, order.name)
|
||||
packout1 = picking.move_line_ids[0]
|
||||
packout1.qty_done = 5
|
||||
picking.with_user(self.stock_request_manager).action_done()
|
||||
self.assertEqual(stock_request.qty_in_progress, 0.0)
|
||||
self.assertEqual(stock_request.qty_done, stock_request.product_uom_qty)
|
||||
self.assertEqual(order.state, "done")
|
||||
self.assertEqual(stock_request.state, "done")
|
||||
|
||||
def test_create_request_02(self):
|
||||
"""Use different UoM's"""
|
||||
|
||||
vals = {
|
||||
"product_id": self.product.id,
|
||||
"product_uom_id": self.uom_dozen.id,
|
||||
"product_uom_qty": 1.0,
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
}
|
||||
|
||||
stock_request = self.stock_request.with_user(self.stock_request_user).create(
|
||||
vals
|
||||
)
|
||||
|
||||
self.product.route_ids = [(6, 0, self.route.ids)]
|
||||
stock_request.with_user(self.stock_request_manager).action_confirm()
|
||||
self.assertEqual(stock_request.state, "open")
|
||||
self.assertEqual(len(stock_request.picking_ids), 1)
|
||||
self.assertEqual(len(stock_request.move_ids), 1)
|
||||
self.assertEqual(
|
||||
stock_request.move_ids[0].location_dest_id, stock_request.location_id
|
||||
)
|
||||
self.assertEqual(stock_request.qty_in_progress, stock_request.product_uom_qty)
|
||||
self.env["stock.quant"].create(
|
||||
{
|
||||
"product_id": self.product.id,
|
||||
"location_id": self.ressuply_loc.id,
|
||||
"quantity": 12.0,
|
||||
}
|
||||
)
|
||||
picking = stock_request.picking_ids[0]
|
||||
picking.with_user(self.stock_request_manager).action_confirm()
|
||||
self.assertEqual(stock_request.qty_in_progress, 1.0)
|
||||
self.assertEqual(stock_request.qty_done, 0.0)
|
||||
picking.with_user(self.stock_request_manager).action_assign()
|
||||
packout1 = picking.move_line_ids[0]
|
||||
packout1.qty_done = 1
|
||||
picking.with_user(self.stock_request_manager).action_done()
|
||||
self.assertEqual(stock_request.qty_in_progress, 0.0)
|
||||
self.assertEqual(stock_request.qty_done, stock_request.product_uom_qty)
|
||||
self.assertEqual(stock_request.state, "done")
|
||||
|
||||
def test_create_request_03(self):
|
||||
"""Multiple stock requests"""
|
||||
vals = {
|
||||
"product_id": self.product.id,
|
||||
"product_uom_id": self.product.uom_id.id,
|
||||
"product_uom_qty": 4.0,
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
}
|
||||
|
||||
stock_request_1 = (
|
||||
self.env["stock.request"].with_user(self.stock_request_user).create(vals)
|
||||
)
|
||||
stock_request_2 = (
|
||||
self.env["stock.request"]
|
||||
.with_user(self.stock_request_manager.id)
|
||||
.create(vals)
|
||||
)
|
||||
stock_request_2.product_uom_qty = 6.0
|
||||
self.product.route_ids = [(6, 0, self.route.ids)]
|
||||
stock_request_1.with_user(self.stock_request_manager).action_confirm()
|
||||
stock_request_2.with_user(self.stock_request_manager).action_confirm()
|
||||
self.assertEqual(len(stock_request_1.picking_ids), 1)
|
||||
self.assertEqual(stock_request_1.picking_ids, stock_request_2.picking_ids)
|
||||
self.assertEqual(stock_request_1.move_ids, stock_request_2.move_ids)
|
||||
self.env["stock.quant"].create(
|
||||
{
|
||||
"product_id": self.product.id,
|
||||
"location_id": self.ressuply_loc.id,
|
||||
"quantity": 10.0,
|
||||
}
|
||||
)
|
||||
picking = stock_request_1.picking_ids[0]
|
||||
picking.with_user(self.stock_request_manager).action_confirm()
|
||||
picking.with_user(self.stock_request_manager).action_assign()
|
||||
packout1 = picking.move_line_ids[0]
|
||||
packout1.qty_done = 10
|
||||
picking.with_user(self.stock_request_manager).action_done()
|
||||
|
||||
def test_cancel_request(self):
|
||||
expected_date = fields.Datetime.now()
|
||||
vals = {
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
"expected_date": expected_date,
|
||||
"stock_request_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_id": self.product.id,
|
||||
"product_uom_id": self.product.uom_id.id,
|
||||
"product_uom_qty": 5.0,
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
"expected_date": expected_date,
|
||||
},
|
||||
)
|
||||
],
|
||||
}
|
||||
|
||||
order = self.request_order.with_user(self.stock_request_user).create(vals)
|
||||
|
||||
self.product.route_ids = [(6, 0, self.route.ids)]
|
||||
order.with_user(self.stock_request_user).action_confirm()
|
||||
stock_request = order.stock_request_ids
|
||||
self.assertEqual(len(order.picking_ids), 1)
|
||||
self.assertEqual(len(order.move_ids), 1)
|
||||
self.assertEqual(len(stock_request.picking_ids), 1)
|
||||
self.assertEqual(len(stock_request.move_ids), 1)
|
||||
self.assertEqual(
|
||||
stock_request.move_ids[0].location_dest_id, stock_request.location_id
|
||||
)
|
||||
self.assertEqual(stock_request.qty_in_progress, stock_request.product_uom_qty)
|
||||
self.env["stock.quant"].create(
|
||||
{
|
||||
"product_id": self.product.id,
|
||||
"location_id": self.ressuply_loc.id,
|
||||
"quantity": 5.0,
|
||||
}
|
||||
)
|
||||
picking = stock_request.picking_ids[0]
|
||||
picking.with_user(self.stock_request_user).action_confirm()
|
||||
self.assertEqual(stock_request.qty_in_progress, 5.0)
|
||||
self.assertEqual(stock_request.qty_done, 0.0)
|
||||
picking.with_user(self.stock_request_manager).action_assign()
|
||||
order.with_user(self.stock_request_manager).action_cancel()
|
||||
|
||||
self.assertEqual(stock_request.qty_in_progress, 0.0)
|
||||
self.assertEqual(stock_request.qty_done, 0.0)
|
||||
self.assertEqual(len(stock_request.picking_ids), 0)
|
||||
|
||||
# Set the request back to draft
|
||||
order.with_user(self.stock_request_user).action_draft()
|
||||
self.assertEqual(order.state, "draft")
|
||||
self.assertEqual(stock_request.state, "draft")
|
||||
|
||||
# Re-confirm. We expect new pickings to be created
|
||||
order.with_user(self.stock_request_user).action_confirm()
|
||||
self.assertEqual(len(stock_request.picking_ids), 1)
|
||||
self.assertEqual(len(stock_request.move_ids), 2)
|
||||
|
||||
def test_view_actions(self):
|
||||
expected_date = fields.Datetime.now()
|
||||
vals = {
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
"expected_date": expected_date,
|
||||
"stock_request_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_id": self.product.id,
|
||||
"product_uom_id": self.product.uom_id.id,
|
||||
"product_uom_qty": 5.0,
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
"expected_date": expected_date,
|
||||
},
|
||||
)
|
||||
],
|
||||
}
|
||||
|
||||
order = self.request_order.create(vals)
|
||||
self.product.route_ids = [(6, 0, self.route.ids)]
|
||||
|
||||
order.with_user(self.stock_request_manager).action_confirm()
|
||||
stock_request = order.stock_request_ids
|
||||
self.assertTrue(stock_request.picking_ids)
|
||||
self.assertTrue(order.picking_ids)
|
||||
|
||||
action = order.action_view_transfer()
|
||||
self.assertEqual("domain" in action.keys(), True)
|
||||
self.assertEqual("views" in action.keys(), True)
|
||||
self.assertEqual(action["res_id"], order.picking_ids[0].id)
|
||||
|
||||
action = order.action_view_stock_requests()
|
||||
self.assertEqual("domain" in action.keys(), True)
|
||||
self.assertEqual("views" in action.keys(), True)
|
||||
self.assertEqual(action["res_id"], stock_request[0].id)
|
||||
|
||||
action = stock_request.action_view_transfer()
|
||||
self.assertEqual("domain" in action.keys(), True)
|
||||
self.assertEqual("views" in action.keys(), True)
|
||||
self.assertEqual(action["res_id"], stock_request.picking_ids[0].id)
|
||||
|
||||
action = stock_request.picking_ids[0].action_view_stock_request()
|
||||
self.assertEqual(action["type"], "ir.actions.act_window")
|
||||
self.assertEqual(action["res_id"], stock_request.id)
|
||||
|
||||
def test_stock_request_constrains(self):
|
||||
vals = {
|
||||
"product_id": self.product.id,
|
||||
"product_uom_id": self.product.uom_id.id,
|
||||
"product_uom_qty": 5.0,
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
}
|
||||
|
||||
stock_request = self.stock_request.with_user(self.stock_request_user).create(
|
||||
vals
|
||||
)
|
||||
|
||||
# Cannot assign a warehouse that belongs to another company
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
stock_request.warehouse_id = self.wh2
|
||||
# Cannot assign a product that belongs to another company
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
stock_request.product_id = self.product_company_2
|
||||
# Cannot assign a location that belongs to another company
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
stock_request.location_id = self.wh2.lot_stock_id
|
||||
# Cannot assign a route that belongs to another company
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
stock_request.route_id = self.route_2
|
||||
|
||||
def test_stock_request_order_from_products(self):
|
||||
product_a1 = self._create_product("CODEA1", "Product A1", self.main_company.id)
|
||||
template_a = product_a1.product_tmpl_id
|
||||
product_a2 = self._create_product(
|
||||
"CODEA2", "Product A2", self.main_company.id, product_tmpl_id=template_a.id
|
||||
)
|
||||
product_a3 = self._create_product(
|
||||
"CODEA3", "Product A3", self.main_company.id, product_tmpl_id=template_a.id
|
||||
)
|
||||
product_b1 = self._create_product("CODEB1", "Product B1", self.main_company.id)
|
||||
template_b = product_b1.product_tmpl_id
|
||||
# One archived variant of B
|
||||
self._create_product(
|
||||
"CODEB2",
|
||||
"Product B2",
|
||||
self.main_company.id,
|
||||
product_tmpl_id=template_b.id,
|
||||
active=False,
|
||||
)
|
||||
order = self.request_order
|
||||
|
||||
# Selecting some variants and creating an order
|
||||
preexisting = order.search([])
|
||||
wanted_products = product_a1 + product_a2 + product_b1
|
||||
action = order._create_from_product_multiselect(wanted_products)
|
||||
new_order = order.search([]) - preexisting
|
||||
self.assertEqual(len(new_order), 1)
|
||||
self.assertEqual(
|
||||
action["res_id"],
|
||||
new_order.id,
|
||||
msg="Returned action references the wrong record",
|
||||
)
|
||||
self.assertEqual(
|
||||
Counter(wanted_products),
|
||||
Counter(new_order.stock_request_ids.mapped("product_id")),
|
||||
msg="Not all wanted products were ordered",
|
||||
)
|
||||
|
||||
# Selecting a template and creating an order
|
||||
preexisting = order.search([])
|
||||
action = order._create_from_product_multiselect(template_a)
|
||||
new_order = order.search([]) - preexisting
|
||||
self.assertEqual(len(new_order), 1)
|
||||
self.assertEqual(
|
||||
action["res_id"],
|
||||
new_order.id,
|
||||
msg="Returned action references the wrong record",
|
||||
)
|
||||
self.assertEqual(
|
||||
Counter(product_a1 + product_a2 + product_a3),
|
||||
Counter(new_order.stock_request_ids.mapped("product_id")),
|
||||
msg="Not all of the template's variants were ordered",
|
||||
)
|
||||
|
||||
# Selecting a template
|
||||
preexisting = order.search([])
|
||||
action = order._create_from_product_multiselect(template_a + template_b)
|
||||
new_order = order.search([]) - preexisting
|
||||
self.assertEqual(len(new_order), 1)
|
||||
self.assertEqual(
|
||||
action["res_id"],
|
||||
new_order.id,
|
||||
msg="Returned action references the wrong record",
|
||||
)
|
||||
self.assertEqual(
|
||||
Counter(product_a1 + product_a2 + product_a3 + product_b1),
|
||||
Counter(new_order.stock_request_ids.mapped("product_id")),
|
||||
msg="Inactive variant was ordered though it shouldn't have been",
|
||||
)
|
||||
|
||||
# If a user does not have stock request rights, they can still trigger
|
||||
# the action from the products, so test that they get a friendlier
|
||||
# error message.
|
||||
self.stock_request_user.groups_id -= self.stock_request_user_group
|
||||
with self.assertRaisesRegexp(
|
||||
exceptions.UserError,
|
||||
"Unfortunately it seems you do not have the necessary rights "
|
||||
"for creating stock requests. Please contact your "
|
||||
"administrator.",
|
||||
):
|
||||
order.with_user(self.stock_request_user)._create_from_product_multiselect(
|
||||
template_a + template_b
|
||||
)
|
||||
|
||||
# Empty recordsets should just return False
|
||||
self.assertFalse(
|
||||
order._create_from_product_multiselect(self.env["product.product"])
|
||||
)
|
||||
|
||||
# Wrong model should just raise ValidationError
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
order._create_from_product_multiselect(self.stock_request_user)
|
||||
|
||||
def test_allow_virtual_location(self):
|
||||
self.main_company.stock_request_allow_virtual_loc = True
|
||||
vals = {
|
||||
"product_id": self.product.id,
|
||||
"product_uom_id": self.product.uom_id.id,
|
||||
"product_uom_qty": 5.0,
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.virtual_loc.id,
|
||||
}
|
||||
stock_request = self.stock_request.with_user(self.stock_request_user).create(
|
||||
vals
|
||||
)
|
||||
stock_request.onchange_allow_virtual_location()
|
||||
self.assertTrue(stock_request.allow_virtual_location)
|
||||
vals = {
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.virtual_loc.id,
|
||||
}
|
||||
order = self.request_order.with_user(self.stock_request_user).create(vals)
|
||||
order.onchange_allow_virtual_location()
|
||||
self.assertTrue(order.allow_virtual_location)
|
||||
|
||||
def test_onchange_wh_no_effect_from_order(self):
|
||||
expected_date = fields.Datetime.now()
|
||||
vals = {
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.virtual_loc.id,
|
||||
"expected_date": expected_date,
|
||||
"stock_request_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_id": self.product.id,
|
||||
"product_uom_id": self.product.uom_id.id,
|
||||
"product_uom_qty": 5.0,
|
||||
"company_id": self.main_company.id,
|
||||
"warehouse_id": self.warehouse.id,
|
||||
"location_id": self.virtual_loc.id,
|
||||
"expected_date": expected_date,
|
||||
},
|
||||
)
|
||||
],
|
||||
}
|
||||
order = self.request_order.with_user(self.stock_request_user).create(vals)
|
||||
order.stock_request_ids.onchange_warehouse_id()
|
||||
self.assertEqual(order.stock_request_ids[0].location_id, self.virtual_loc)
|
||||
26
stock_request/views/product.xml
Normal file
26
stock_request/views/product.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="action_variant_generate_stock_request_orders" model="ir.actions.server">
|
||||
<field name="name">Request Stock</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="state">code</field>
|
||||
<field name="model_id" ref="product.model_product_product"/>
|
||||
<field name="binding_model_id" ref="product.model_product_product"/>
|
||||
<field name="code">
|
||||
action = records.env['stock.request.order']._create_from_product_multiselect(records)
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_template_generate_stock_request_orders" model="ir.actions.server">
|
||||
<field name="name">Request Stock</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="state">code</field>
|
||||
<field name="model_id" ref="product.model_product_template"/>
|
||||
<field name="binding_model_id" ref="product.model_product_template"/>
|
||||
<field name="code">
|
||||
action = records.env['stock.request.order']._create_from_product_multiselect(records)
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
116
stock_request/views/res_config_settings_views.xml
Normal file
116
stock_request/views/res_config_settings_views.xml
Normal file
@@ -0,0 +1,116 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<!--
|
||||
Copyright 2018 Creu Blanca
|
||||
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="res_config_settings_view_form" model="ir.ui.view">
|
||||
<field name="name">res.config.settings.view.form.inherit.stock_request</field>
|
||||
<field name="model">res.config.settings</field>
|
||||
<field name="inherit_id" ref="base.res_config_settings_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[hasclass('settings')]" position="inside">
|
||||
<div class="app_settings_block"
|
||||
data-string="Stock Request" data-key="stock_request"
|
||||
groups="stock_request.group_stock_request_manager">
|
||||
<h2>Orders & Configuration</h2>
|
||||
<div class="row mt16 o_settings_container" id="stock_request">
|
||||
<div class="col-xs-12 col-md-6 o_setting_box">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="group_stock_request_order"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label string="Enable Orders"
|
||||
for="group_stock_request_order"/>
|
||||
<div class="text-muted">
|
||||
Activates Stock Request Orders
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-6 o_setting_box">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="stock_request_allow_virtual_loc"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label string="Allow All Locations Types" for="stock_request_allow_virtual_loc"/>
|
||||
<div class="text-muted">
|
||||
By default only internal and transit locations are allowed in Stock Request and Orders.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-6 o_setting_box">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="module_stock_request_submit"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label string="Enable Submitted State"
|
||||
for="module_stock_request_purchase"/>
|
||||
<div class="text-muted">
|
||||
Add State to Stock Request and Stock Request Orders if activated.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2>Purchases</h2>
|
||||
<div class="row mt16 o_settings_container" id="stock_request_purchase">
|
||||
<div class="col-xs-12 col-md-6 o_setting_box">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="module_stock_request_purchase"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label string="Enable Stock Requests for Purchases"
|
||||
for="module_stock_request_purchase"/>
|
||||
<div class="text-muted">
|
||||
Use Purchases with Stock Requests
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2>Kanban</h2>
|
||||
<div class="row mt16 o_settings_container" id="stock_request_purchase">
|
||||
<div class="col-xs-12 col-md-6 o_setting_box">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="module_stock_request_kanban"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label string="Enable Stock Requests Kanban cards"
|
||||
for="module_stock_request_purchase"/>
|
||||
<div class="text-muted">
|
||||
Use Kanban cards for consumable products
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2>Analytic</h2>
|
||||
<div class="row mt16 o_settings_container" id="stock_request_analytic">
|
||||
<div class="col-xs-12 col-md-6 o_setting_box">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="module_stock_request_analytic"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label string="Enable Analytic Accounting in Stock Requests"
|
||||
for="module_stock_request_analytic"/>
|
||||
<div class="text-muted">
|
||||
Analytic accounting in Stock Requests
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_stock_request_config" model="ir.actions.act_window">
|
||||
<field name="name">Settings</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">res.config.settings</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">inline</field>
|
||||
<field name="context">{'module' : 'stock_request'}</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
31
stock_request/views/stock_move_views.xml
Normal file
31
stock_request/views/stock_move_views.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="view_stock_move_operations" model="ir.ui.view">
|
||||
<field name="name">stock.move.operations.form</field>
|
||||
<field name="model">stock.move</field>
|
||||
<field name="inherit_id" ref="stock.view_stock_move_operations"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="move_line_ids" position="after">
|
||||
<newline/>
|
||||
<field name="allocation_ids"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_move_form" model="ir.ui.view">
|
||||
<field name="name">stock.move.form</field>
|
||||
<field name="model">stock.move</field>
|
||||
<field name="inherit_id" ref="stock.view_move_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<group name="linked_group" position="after">
|
||||
<newline/>
|
||||
<group name="allocations"
|
||||
string="Stock Request Allocations">
|
||||
<field name="allocation_ids"/>
|
||||
</group>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
24
stock_request/views/stock_picking_views.xml
Normal file
24
stock_request/views/stock_picking_views.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="view_picking_form" model="ir.ui.view">
|
||||
<field name="name">stock.picking.form</field>
|
||||
<field name="model">stock.picking</field>
|
||||
<field name="inherit_id" ref="stock.view_picking_form"/>
|
||||
<field eval="12" name="priority"/>
|
||||
<field name="arch" type="xml">
|
||||
<div name="button_box" position="inside">
|
||||
<button type="object"
|
||||
name="action_view_stock_request"
|
||||
class="oe_stat_button"
|
||||
icon="fa-chain"
|
||||
attrs="{'invisible':[('stock_request_ids', '=', [])]}">
|
||||
<field name="stock_request_count" widget="statinfo"
|
||||
string="Stock Requests"/>
|
||||
<field name="stock_request_ids" invisible="1"/>
|
||||
</button>
|
||||
</div>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
53
stock_request/views/stock_request_allocation_views.xml
Normal file
53
stock_request/views/stock_request_allocation_views.xml
Normal file
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2017 Eficent
|
||||
License LGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
|
||||
<odoo>
|
||||
|
||||
<record id="view_stock_request_allocation_tree" model="ir.ui.view">
|
||||
<field name="name">stock.request.allocation.tree</field>
|
||||
<field name="model">stock.request.allocation</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Stock Request Allocations">
|
||||
<field name="stock_request_id"/>
|
||||
<field name="stock_move_id"/>
|
||||
<field name="product_id"/>
|
||||
<field name="requested_product_uom_qty"/>
|
||||
<field name="product_uom_id"
|
||||
options="{'no_open': True, 'no_create': True}" groups="uom.group_uom"/>
|
||||
<field name="requested_product_qty"/>
|
||||
<field name="allocated_product_qty"/>
|
||||
<field name="open_product_qty" />
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_stock_request_allocation_form" model="ir.ui.view">
|
||||
<field name="name">stock.request.allocation.form</field>
|
||||
<field name="model">stock.request.allocation</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Stock Request Allocations">
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field name="stock_request_id"/>
|
||||
<field name="stock_move_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="product_id"/>
|
||||
<field name="requested_product_uom_qty"/>
|
||||
<field name="product_uom_id"
|
||||
options="{'no_open': True, 'no_create': True}"
|
||||
groups="uom.group_uom"/>
|
||||
<field name="requested_product_qty"/>
|
||||
<field name="allocated_product_qty"/>
|
||||
<field name="open_product_qty" />
|
||||
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
46
stock_request/views/stock_request_menu.xml
Normal file
46
stock_request/views/stock_request_menu.xml
Normal file
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<menuitem
|
||||
id="menu_stock_request_root"
|
||||
name="Stock Requests"
|
||||
groups="stock_request.group_stock_request_user,stock_request.group_stock_request_manager"
|
||||
web_icon="stock_request,static/description/icon.png"
|
||||
sequence="100"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_stock_request_operations"
|
||||
parent="menu_stock_request_root"
|
||||
name="Operations"
|
||||
sequence="10"/>
|
||||
|
||||
<menuitem id="stock_request_order_menu"
|
||||
name="Stock Request Orders"
|
||||
parent="menu_stock_request_operations"
|
||||
action="stock_request_order_action"
|
||||
groups="group_stock_request_order"
|
||||
sequence="20"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_stock_request"
|
||||
action="action_stock_request_form"
|
||||
name="Stock Requests" parent="menu_stock_request_operations"
|
||||
sequence="30"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_stock_request_master_data"
|
||||
parent="menu_stock_request_root"
|
||||
name="Master Data"
|
||||
sequence="100"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_stock_request_master_data"
|
||||
parent="menu_stock_request_root"
|
||||
name="Master Data"
|
||||
sequence="100"/>
|
||||
|
||||
<menuitem id="menu_stock_request_config" name="Settings"
|
||||
parent="menu_stock_request_root"
|
||||
sequence="999" action="action_stock_request_config"
|
||||
groups="base.group_system"/>
|
||||
|
||||
</odoo>
|
||||
137
stock_request/views/stock_request_order_views.xml
Normal file
137
stock_request/views/stock_request_order_views.xml
Normal file
@@ -0,0 +1,137 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
|
||||
<record model="ir.ui.view" id="stock_request_order_tree">
|
||||
<field name="name">stock.request.order.tree</field>
|
||||
<field name="model">stock.request.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Stock requests">
|
||||
<field name="name"/>
|
||||
<field name="warehouse_id"
|
||||
groups="stock.group_stock_multi_locations"/>
|
||||
<field name="location_id"
|
||||
groups="stock.group_stock_multi_locations"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="stock_request_order_form">
|
||||
<field name="name">stock.request.order.form</field>
|
||||
<field name="model">stock.request.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Stock request">
|
||||
<header>
|
||||
<button name="action_confirm"
|
||||
string="Confirm" type="object"
|
||||
attrs="{'invisible': [('state', 'not in', ['draft'])]}"/>
|
||||
<button name="action_cancel" states="draft,open"
|
||||
type="object" string="Cancel"/>
|
||||
<button name="action_draft" states="cancel" type="object"
|
||||
string="Set to Draft"/>
|
||||
<field name="state" widget="statusbar"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<field name="picking_ids" invisible="1"/>
|
||||
<button type="object"
|
||||
name="action_view_transfer"
|
||||
class="oe_stat_button"
|
||||
icon="fa-truck"
|
||||
attrs="{'invisible': [('picking_count', '=', 0)]}"
|
||||
groups="stock.group_stock_user">
|
||||
<field name="picking_count" widget="statinfo"
|
||||
string="Transfers"/>
|
||||
</button>
|
||||
<button type="object"
|
||||
name="action_view_stock_requests"
|
||||
class="oe_stat_button"
|
||||
icon="fa-chain"
|
||||
attrs="{'invisible': [('state', '=', 'draft')]}"
|
||||
groups="stock.group_stock_user"
|
||||
>
|
||||
<field name="stock_request_count" widget="statinfo"
|
||||
string="Stock Requests"/>
|
||||
</button>
|
||||
</div>
|
||||
<div class="oe_title">
|
||||
<label for="name" string="Stock Request"/>
|
||||
<h1>
|
||||
<field name="name" readonly="1"/>
|
||||
</h1>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="expected_date"/>
|
||||
<field name="picking_policy"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="warehouse_id" widget="selection"
|
||||
groups="stock.group_stock_multi_locations"/>
|
||||
<field name="location_id"
|
||||
groups="stock.group_stock_multi_locations"/>
|
||||
<field name="allow_virtual_location" invisible="1"/>
|
||||
<field name="procurement_group_id"
|
||||
groups="stock.group_adv_location"/>
|
||||
<field name="company_id"
|
||||
groups="base.group_multi_company"
|
||||
options="{'no_create': True}"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page name="items" string="Items">
|
||||
<field name="stock_request_ids" context="{
|
||||
'default_expected_date':expected_date,
|
||||
'default_picking_policy': picking_policy,
|
||||
'default_warehouse_id': warehouse_id,
|
||||
'default_location_id': location_id,
|
||||
'default_procurement_group_id': procurement_group_id,
|
||||
'default_company_id': company_id,
|
||||
'default_state': state,
|
||||
}" attrs="{'readonly': [('state', '!=', 'draft')]}">
|
||||
<tree editable="bottom">
|
||||
<field name="name" readonly="1"/>
|
||||
<field name="product_id"/>
|
||||
<field name="product_uom_id"
|
||||
options="{'no_open': True, 'no_create': True}"
|
||||
groups="uom.group_uom"/>
|
||||
<field name="route_id"
|
||||
options="{'no_create': True}"
|
||||
groups="stock.group_stock_multi_locations"/>
|
||||
<field name="route_ids" invisible="1"/>
|
||||
<field name="product_uom_qty"/>
|
||||
<field name="qty_in_progress"/>
|
||||
<field name="qty_done"/>
|
||||
<field name="expected_date" invisible="1"/>
|
||||
<field name="picking_policy"
|
||||
invisible="1"/>
|
||||
<field name="warehouse_id" invisible="1"/>
|
||||
<field name="location_id" invisible="1"/>
|
||||
<field name="procurement_group_id"
|
||||
invisible="1"/>
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids"
|
||||
widget="mail_followers"/>
|
||||
<field name="activity_ids" widget="mail_activity"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window"
|
||||
id="stock_request_order_action">
|
||||
<field name="name">Stock Request Orders</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">stock.request.order</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
143
stock_request/views/stock_request_views.xml
Normal file
143
stock_request/views/stock_request_views.xml
Normal file
@@ -0,0 +1,143 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2017 Eficent
|
||||
License LGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
|
||||
<odoo>
|
||||
|
||||
<record id="view_stock_request_tree" model="ir.ui.view">
|
||||
<field name="name">stock.request.tree</field>
|
||||
<field name="model">stock.request</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Stock Requests" decoration-muted="state == 'cancel'" decoration-bf="message_needaction==True">
|
||||
<field name="message_needaction" invisible="1"/>
|
||||
<field name="name"/>
|
||||
<field name="warehouse_id" groups="stock.group_stock_multi_locations"/>
|
||||
<field name="location_id" groups="stock.group_stock_multi_locations"/>
|
||||
<field name="allow_virtual_location" invisible="1"/>
|
||||
<field name="route_id" options="{'no_create': True}" groups="stock.group_stock_multi_locations"/>
|
||||
<field name="product_id"/>
|
||||
<field name="product_uom_id"
|
||||
options="{'no_open': True, 'no_create': True}" groups="uom.group_uom"/>
|
||||
<field name="product_uom_qty"/>
|
||||
<field name="qty_in_progress" />
|
||||
<field name="qty_done" />
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="stock_request_search">
|
||||
<field name="name">stock.request.search</field>
|
||||
<field name="model">stock.request</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Stock Requests Search">
|
||||
<field name="name" string="Stock Requests"/>
|
||||
<field name="warehouse_id"/>
|
||||
<field name="location_id" groups="stock.group_stock_multi_locations"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="product_id"/>
|
||||
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter name="warehouse" string="Warehouse" domain="[]" context="{'group_by':'warehouse_id'}"/>
|
||||
<filter name="location" string="Location" domain="[]" context="{'group_by':'location_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_stock_request_form" model="ir.ui.view">
|
||||
<field name="name">stock.request.form</field>
|
||||
<field name="model">stock.request</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Stock Requests">
|
||||
<header>
|
||||
<button name="action_confirm"
|
||||
string="Confirm" type="object"
|
||||
attrs="{'invisible': [('state', 'not in', ['draft'])]}"/>
|
||||
<button name="action_cancel" states="draft,open"
|
||||
type="object" string="Cancel"/>
|
||||
<button name="action_draft" states="cancel" type="object"
|
||||
string="Set to Draft"/>
|
||||
<button name="action_done"
|
||||
string="Done" type="object"
|
||||
attrs="{'invisible': [('state', 'not in', ['open'])]}"/>
|
||||
<field name="state" widget="statusbar"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<field name="picking_ids" invisible="1"/>
|
||||
<button type="object"
|
||||
name="action_view_transfer"
|
||||
class="oe_stat_button"
|
||||
icon="fa-truck"
|
||||
attrs="{'invisible': [('picking_count', '=', 0)]}"
|
||||
groups="stock.group_stock_user">
|
||||
<field name="picking_count" widget="statinfo"
|
||||
string="Transfers"/>
|
||||
</button>
|
||||
</div>
|
||||
<div class="oe_title">
|
||||
<label for="name" string="Stock Request"/>
|
||||
<h1>
|
||||
<field name="name" readonly="1"/>
|
||||
</h1>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="order_id" readonly="1" groups="stock_request.group_stock_request_order"/>
|
||||
<field name="product_id"/>
|
||||
<field name="expected_date"/>
|
||||
<field name="picking_policy"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="warehouse_id" widget="selection" groups="stock.group_stock_multi_locations"/>
|
||||
<field name="location_id" groups="stock.group_stock_multi_locations"
|
||||
domain="['|', ('company_id', '=', company_id), ('company_id', '=', False)]"/>
|
||||
<field name="route_id"
|
||||
options="{'no_create': True}" groups="stock.group_stock_multi_locations"/>
|
||||
<field name="route_ids" invisible="1"/>
|
||||
<field name="procurement_group_id"
|
||||
groups="stock.group_adv_location"/>
|
||||
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
|
||||
</group>
|
||||
<group name="quantities">
|
||||
<label for="product_uom_qty"/>
|
||||
<div>
|
||||
<field name="product_uom_qty"
|
||||
class="oe_inline"/>
|
||||
<field name="product_uom_id"
|
||||
class="oe_inline"
|
||||
options="{'no_open': True, 'no_create': True}"
|
||||
groups="uom.group_uom"/>
|
||||
</div>
|
||||
<field name="qty_in_progress" />
|
||||
<field name="qty_done" />
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<!--Empty notebook to inherit pages from other related modules-->
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
<field name="activity_ids" widget="mail_activity"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_stock_request_form" model="ir.actions.act_window">
|
||||
<field name="name">Stock Requests</field>
|
||||
<field name="res_model">stock.request</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="view_stock_request_tree"/>
|
||||
<field name="search_view_id" ref="stock_request_search" />
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to add a Stock Request.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user