diff --git a/addons/purchase_indent/__init__.py b/addons/purchase_indent/__init__.py
new file mode 100644
index 00000000..a31f3c40
--- /dev/null
+++ b/addons/purchase_indent/__init__.py
@@ -0,0 +1,4 @@
+# Part of Flectra See LICENSE file for full copyright and licensing details.
+
+from . import models
+from . import wizard
diff --git a/addons/purchase_indent/__manifest__.py b/addons/purchase_indent/__manifest__.py
new file mode 100644
index 00000000..f4733b40
--- /dev/null
+++ b/addons/purchase_indent/__manifest__.py
@@ -0,0 +1,31 @@
+# Part of Flectra See LICENSE file for full copyright and licensing details.
+
+{
+ 'name': 'Purchase Indent Flectra',
+ 'version': '1.0',
+ 'category': 'Purchase',
+ 'sequence': 10,
+ 'summary': 'Purchase Indent',
+ 'description': """
+ Purchase Indent and Agreements""",
+ 'author': 'Flectrahq',
+ 'website': 'https://www.flectrahq.com/',
+ 'depends': [
+ 'purchase',
+ 'purchase_requisition',
+ ],
+ 'data': [
+ 'security/ir.model.access.csv',
+ 'security/purchase_indent_security.xml',
+ 'wizard/wiz_requisition_request_view.xml',
+ 'views/purchase_indent_view.xml',
+ 'report/purchase_indent_reports.xml',
+ 'report/purchase_indent_template.xml',
+ ],
+ 'demo': [
+ 'demo/puchase_indent_demo.xml',
+ ],
+ 'installable': True,
+ 'application': True,
+ 'auto_install': False,
+}
diff --git a/addons/purchase_indent/demo/puchase_indent_demo.xml b/addons/purchase_indent/demo/puchase_indent_demo.xml
new file mode 100644
index 00000000..f96358d4
--- /dev/null
+++ b/addons/purchase_indent/demo/puchase_indent_demo.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+ Whiteboard
+
+
+ 2
+ 2.0
+
+
+
+
+
+
+
+ po
+
+
+
+
+
+
+ Whiteboard
+
+
+
+ 2
+ 2.0
+ 2.0
+
+
+
+
+
+ Whiteboard
+
+
+
+
+
+ 2
+ 100
+
+
+
+
+
diff --git a/addons/purchase_indent/i18n/purchase_indent.pot b/addons/purchase_indent/i18n/purchase_indent.pot
new file mode 100644
index 00000000..8a139cb0
--- /dev/null
+++ b/addons/purchase_indent/i18n/purchase_indent.pot
@@ -0,0 +1,673 @@
+# Translation of Flectra Server.
+# This file contains the translation of the following modules:
+# * purchase_indent
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Flectra Server 1.0alpha\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-01-24 05:17+0000\n"
+"PO-Revision-Date: 2018-01-24 05:17+0000\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: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_agreement_count
+msgid "# of Purchase Agreement"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_purchase_order_count
+msgid "# of Purchase Order"
+msgstr ""
+
+#. module: purchase_indent
+#: code:addons/purchase_indent/models/purchase_indent.py:194
+#, python-format
+msgid "%s (copy)"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.report_purchaseindent_document
+msgid "Purchase Indent"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.report_purchaseindent_document
+msgid "Category:"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.report_purchaseindent_document
+msgid "Indent Date:"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.report_purchaseindent_document
+msgid "Shipping address:"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.view_purchase_indent_form
+msgid "Agreement"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_requisition_request_requisition_type_id
+msgid "Agreement Type"
+msgstr ""
+
+#. module: purchase_indent
+#: code:addons/purchase_indent/models/purchase_indent.py:424
+#, python-format
+msgid "Can't cancel purchase indent which is requested by %s!"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.view_purchase_indent_form
+#: model:ir.ui.view,arch_db:purchase_indent.view_purchase_indent_search
+#: model:ir.ui.view,arch_db:purchase_indent.view_requisition_request_wizard
+#: selection:purchase.indent,state:0
+msgid "Cancel"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_category_id
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_requisition_request_category_id
+#: model:ir.ui.view,arch_db:purchase_indent.view_purchase_indent_search
+msgid "Category"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_dummy_wiz_indent_line_company_id
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_company_id
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_line_company_id
+msgid "Company"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.view_purchase_indent_form
+#: model:ir.ui.view,arch_db:purchase_indent.view_purchase_indent_search
+#: selection:purchase.indent,state:0
+#: selection:wiz.requisition.request,state:0
+msgid "Confirm"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.view_requisition_request_wizard
+msgid "Create Purchase Agreement"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.view_requisition_request_wizard
+msgid "Create RFQ"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.view_purchase_indent_form
+msgid "Create Requisition"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_dummy_wiz_indent_line_create_uid
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_create_uid
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_history_create_uid
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_line_create_uid
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_indent_line_create_uid
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_requisition_request_create_uid
+msgid "Created by"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_dummy_wiz_indent_line_create_date
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_create_date
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_history_create_date
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_line_create_date
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_indent_line_create_date
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_requisition_request_create_date
+msgid "Created on"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_history_date
+msgid "Date"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_picking_type_id
+msgid "Deliver To"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_dummy_wiz_indent_line_name
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_line_name
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_indent_line_name
+#: model:ir.ui.view,arch_db:purchase_indent.report_purchaseindent_document
+msgid "Description"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_default_location_dest_id_usage
+msgid "Destination Location Type"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_dummy_wiz_indent_line_display_name
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_display_name
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_history_display_name
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_line_display_name
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_indent_line_display_name
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_requisition_request_display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.view_purchase_indent_search
+#: selection:purchase.indent,state:0
+msgid "Done"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.view_purchase_indent_search
+#: selection:purchase.indent,state:0
+#: selection:wiz.requisition.request,state:0
+msgid "Draft"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_dest_address_id
+msgid "Drop Ship Address"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model,name:purchase_indent.model_dummy_wiz_indent_line
+msgid "Dummy Wizard Indent Line"
+msgstr ""
+
+#. module: purchase_indent
+#: code:addons/purchase_indent/models/purchase_indent.py:390
+#: model:ir.model.fields,field_description:purchase_indent.field_dummy_wiz_indent_line_expected_date
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_line_expected_date
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_indent_line_expected_date
+#: model:ir.ui.view,arch_db:purchase_indent.report_purchaseindent_document
+#, python-format
+msgid "Expected Date"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.view_purchase_indent_search
+msgid "Group By"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_intend_history_ids
+#: model:ir.ui.view,arch_db:purchase_indent.view_purchase_indent_form
+msgid "History"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_dummy_wiz_indent_line_id
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_history_id
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_id
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_line_id
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_indent_line_id
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_requisition_request_id
+msgid "ID"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_dummy_wiz_indent_line_purchase_indent_line_id
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_indent_line_purchase_indent_line_id
+msgid "Indent Line Ref"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_indent_line
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_requisition_request_dummy_wiz_indent_line
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_requisition_request_wiz_indent_line
+msgid "Indent Lines"
+msgstr ""
+
+#. module: purchase_indent
+#: code:addons/purchase_indent/models/purchase_indent.py:469
+#, python-format
+msgid "Invalid Action!\n"
+" You cannot delete a Purchase Indent which is not in 'Draft' or 'Cancel' State!"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_dummy_wiz_indent_line___last_update
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent___last_update
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_history___last_update
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_line___last_update
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_indent_line___last_update
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_requisition_request___last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_dummy_wiz_indent_line_write_uid
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_history_write_uid
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_line_write_uid
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_write_uid
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_indent_line_write_uid
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_requisition_request_write_uid
+msgid "Last Updated by"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_dummy_wiz_indent_line_write_date
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_history_write_date
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_line_write_date
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_write_date
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_indent_line_write_date
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_requisition_request_write_date
+msgid "Last Updated on"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.view_purchase_indent_search
+msgid "Name"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.view_requisition_request_wizard
+msgid "Next"
+msgstr ""
+
+#. module: purchase_indent
+#: code:addons/purchase_indent/models/purchase_indent.py:369
+#, python-format
+msgid "No Quantity were found for any line!"
+msgstr ""
+
+#. module: purchase_indent
+#: code:addons/purchase_indent/wizard/wiz_requisition_request.py:97
+#, python-format
+msgid "No Requisition Quantity were found for any line!"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.view_purchase_indent_form
+msgid "Open Record"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_indent_line_order_type
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_requisition_request_order_type
+msgid "Order Type"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_dummy_wiz_indent_line_partner_id
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_line_partner_id
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_partner_id
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_indent_line_partner_id
+msgid "Partner"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,help:purchase_indent.field_dummy_wiz_indent_line_partner_id
+#: model:ir.model.fields,help:purchase_indent.field_purchase_indent_line_partner_id
+#: model:ir.model.fields,help:purchase_indent.field_purchase_indent_partner_id
+msgid "Partner-related data of the user"
+msgstr ""
+
+#. module: purchase_indent
+#: code:addons/purchase_indent/models/purchase_indent.py:379
+#, python-format
+msgid "Please configure outgoing mail server"
+msgstr ""
+
+#. module: purchase_indent
+#: code:addons/purchase_indent/models/purchase_indent.py:416
+#, python-format
+msgid "Please configure your email"
+msgstr ""
+
+#. module: purchase_indent
+#: code:addons/purchase_indent/models/purchase_indent.py:374
+#, python-format
+msgid "Please contact your Administrator \n"
+" No user found under 'Purchase Manager'"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_dummy_wiz_indent_line_product_id
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_history_product_id
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_line_product_id
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_indent_line_product_id
+#: model:ir.ui.view,arch_db:purchase_indent.report_purchaseindent_document
+#: model:ir.ui.view,arch_db:purchase_indent.view_purchase_indent_form
+msgid "Product"
+msgstr ""
+
+#. module: purchase_indent
+#: code:addons/purchase_indent/models/purchase_indent.py:388
+#, python-format
+msgid "Product Name"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_dummy_wiz_indent_line_product_uom
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_line_product_uom
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_indent_line_product_uom
+msgid "Product Unit of Measure"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_history_purchase_requisition_id
+#: selection:wiz.requisition.request,order_type:0
+msgid "Purchase Agreement"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.actions.act_window,name:purchase_indent.action_flectra_purchase_indent
+#: model:ir.model,name:purchase_indent.model_purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_dummy_wiz_indent_line_purchase_indent_id
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_history_purchase_indent_id
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_line_purchase_indent_id
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_order_line_purchase_indent_ids
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_order_purchase_indent_ids
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_requisition_line_purchase_indent_ids
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_requisition_purchase_indent_ids
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_indent_line_purchase_indent_ids
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_requisition_request_purchase_indent_id
+#: model:ir.ui.menu,name:purchase_indent.menu_flectra_purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.view_purchase_indent_form
+msgid "Purchase Indent"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model,name:purchase_indent.model_purchase_indent_history
+msgid "Purchase Indent History"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model,name:purchase_indent.model_purchase_indent_line
+msgid "Purchase Indent Line"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_order_line_purchase_indent_line_id
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_requisition_line_purchase_indent_line_id
+msgid "Purchase Indent Line Ref"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model,name:purchase_indent.model_purchase_order
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_history_order_id
+#: selection:wiz.requisition.request,order_type:0
+msgid "Purchase Order"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model,name:purchase_indent.model_purchase_order_line
+msgid "Purchase Order Line"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model,name:purchase_indent.model_purchase_requisition
+msgid "Purchase Requisition"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model,name:purchase_indent.model_purchase_requisition_line
+msgid "Purchase Requisition Line"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.view_purchase_indent_form
+msgid "Purchases"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,help:purchase_indent.field_purchase_indent_dest_address_id
+msgid "Put an address if you want to deliver directly from the vendor to the customer.Otherwise, keep empty to deliver to your own company."
+msgstr ""
+
+#. module: purchase_indent
+#: code:addons/purchase_indent/models/purchase_indent.py:389
+#: model:ir.model.fields,field_description:purchase_indent.field_dummy_wiz_indent_line_dummy_product_qty
+#: model:ir.model.fields,field_description:purchase_indent.field_dummy_wiz_indent_line_product_qty
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_history_product_qty
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_indent_line_product_qty
+#, python-format
+msgid "Quantity"
+msgstr ""
+
+#. module: purchase_indent
+#: code:addons/purchase_indent/models/purchase_indent.py:561
+#: code:addons/purchase_indent/tests/test_purchase_indent.py:85
+#: code:addons/purchase_indent/tests/test_purchase_indent.py:90
+#, python-format
+msgid "Quantity (%s) can not be Negative!"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_name
+msgid "Reference"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.report_purchaseindent_document
+msgid "Remaining\n"
+" Quantity"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_dummy_wiz_indent_line_remaining_qty
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_history_remaining_qty
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_line_remaining_qty
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_indent_line_remaining_qty
+msgid "Remaining Quantity"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.report_purchaseindent_document
+msgid "Request\n"
+" Quantity"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_dummy_wiz_indent_line_indent_requ_date
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_request_date
+#: model:ir.ui.view,arch_db:purchase_indent.view_purchase_indent_search
+msgid "Request Date"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_line_product_qty
+msgid "Request Quantity"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.actions.report,name:purchase_indent.report_purchase_indent
+msgid "Request for Indent"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.view_purchase_indent_search
+msgid "Requestd By"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_user_id
+msgid "Requested By"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.report_purchaseindent_document
+msgid "Requested By:"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.view_purchase_indent_search
+#: selection:purchase.indent,state:0
+msgid "Requisition"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.report_purchaseindent_document
+msgid "Requisition\n"
+" Quantity"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_dummy_wiz_indent_line_requisition_qty
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_line_requisition_qty
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_indent_line_requisition_qty
+msgid "Requisition Quantity"
+msgstr ""
+
+#. module: purchase_indent
+#: code:addons/purchase_indent/wizard/wiz_requisition_request.py:395
+#, python-format
+msgid "Requisition Quantity (%s) can not be Negative!"
+msgstr ""
+
+#. module: purchase_indent
+#: code:addons/purchase_indent/models/purchase_indent.py:324
+#, python-format
+msgid "Requisition Quantity of ' %s ' is more than Remaining Quantity (%s)!"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.actions.act_window,name:purchase_indent.action_wiz_requisition_request
+#: model:ir.ui.view,arch_db:purchase_indent.view_requisition_request_wizard
+msgid "Requisition Request"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.view_purchase_indent_search
+msgid "Search Purchase Indent"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_dummy_wiz_indent_line_sequence
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_line_sequence
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_indent_line_sequence
+msgid "Sequence"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.view_purchase_indent_form
+msgid "Set to Draft"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.report_purchaseindent_document
+msgid "Sr"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_history_state
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_state
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_requisition_request_state
+#: model:ir.ui.view,arch_db:purchase_indent.view_purchase_indent_search
+msgid "State"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_indent_line_taxes_id
+msgid "Taxes"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,help:purchase_indent.field_purchase_indent_default_location_dest_id_usage
+msgid "Technical field used to display the Drop Ship Address"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,help:purchase_indent.field_purchase_indent_picking_type_id
+msgid "This will determine operation type of incoming shipment"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_purchase_indent_history_requisition_qty
+msgid "Transfer Quantity"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.report_purchaseindent_document
+msgid "Unit"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_indent_line_price_unit
+msgid "Unit Price"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.ui.view,arch_db:purchase_indent.report_purchaseindent_document
+msgid "VAT:"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_requisition_request_partner_id
+msgid "Vendor"
+msgstr ""
+
+#. module: purchase_indent
+#: code:addons/purchase_indent/models/purchase_indent.py:560
+#: code:addons/purchase_indent/wizard/wiz_requisition_request.py:394
+#, python-format
+msgid "Warning"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model.fields,field_description:purchase_indent.field_dummy_wiz_indent_line_wizard_indent_id
+#: model:ir.model.fields,field_description:purchase_indent.field_wiz_indent_line_wizard_indent_id
+msgid "Wiz Requisition Request"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model,name:purchase_indent.model_wiz_indent_line
+msgid "Wizard Indent Line"
+msgstr ""
+
+#. module: purchase_indent
+#: code:addons/purchase_indent/models/purchase_indent.py:191
+#, python-format
+msgid "You can not copy Purchase Agreement which have reference of Purchase Indent!"
+msgstr ""
+
+#. module: purchase_indent
+#: code:addons/purchase_indent/models/purchase_indent.py:142
+#, python-format
+msgid "You can not copy Purchase order which have reference of Purchase Indent!"
+msgstr ""
+
+#. module: purchase_indent
+#: code:addons/purchase_indent/models/purchase_indent.py:135
+#, python-format
+msgid "You can not delete Purchase order which have reference of Purchase Indent!"
+msgstr ""
+
+#. module: purchase_indent
+#: code:addons/purchase_indent/models/purchase_indent.py:184
+#, python-format
+msgid "You can not delete agreement which have reference of Purchase Indent!"
+msgstr ""
+
+#. module: purchase_indent
+#: code:addons/purchase_indent/models/purchase_indent.py:158
+#, python-format
+msgid "You can not delete line which have reference of Purchase Indent"
+msgstr ""
+
+#. module: purchase_indent
+#: code:addons/purchase_indent/models/purchase_indent.py:362
+#, python-format
+msgid "You can't confirm purchase indent which is requested by %s!"
+msgstr ""
+
+#. module: purchase_indent
+#: model:ir.model,name:purchase_indent.model_wiz_requisition_request
+msgid "wiz.requisition.request"
+msgstr ""
+
diff --git a/addons/purchase_indent/models/__init__.py b/addons/purchase_indent/models/__init__.py
new file mode 100644
index 00000000..4fadd208
--- /dev/null
+++ b/addons/purchase_indent/models/__init__.py
@@ -0,0 +1,3 @@
+# Part of Flectra See LICENSE file for full copyright and licensing details.
+
+from . import purchase_indent
diff --git a/addons/purchase_indent/models/purchase_indent.py b/addons/purchase_indent/models/purchase_indent.py
new file mode 100644
index 00000000..36220bd1
--- /dev/null
+++ b/addons/purchase_indent/models/purchase_indent.py
@@ -0,0 +1,637 @@
+# Part of Flectra See LICENSE file for full copyright and licensing details.
+
+from datetime import datetime
+
+from flectra.exceptions import Warning, AccessError
+from flectra.tools.misc import formatLang
+
+import flectra.addons.decimal_precision as dp
+from flectra import api, fields, models, _
+
+
+class PurchaseOrder(models.Model):
+ _inherit = 'purchase.order'
+
+ purchase_indent_ids = fields.Many2many(
+ 'purchase.indent', string='Purchase Indent')
+
+ @api.onchange('requisition_id')
+ def _onchange_requisition_id(self):
+ if not self.requisition_id:
+ return
+
+ requisition = self.requisition_id
+ if self.partner_id:
+ partner = self.partner_id
+ else:
+ partner = requisition.vendor_id
+ payment_term = partner.property_supplier_payment_term_id
+ company = requisition.company_id
+ currency = \
+ partner.property_purchase_currency_id or \
+ company.currency_id
+ FiscalPosition = self.env['account.fiscal.position']
+ fpos = FiscalPosition.get_fiscal_position(partner.id)
+ fpos = FiscalPosition.browse(fpos)
+
+ self.partner_id = partner.id
+ self.fiscal_position_id = fpos.id
+ self.payment_term_id = payment_term.id,
+ self.company_id = company.id
+ self.currency_id = currency.id
+ self.origin = requisition.name
+ self.partner_ref = requisition.name
+ self.notes = requisition.description
+ self.date_order = requisition.date_end or fields.Datetime.now()
+ self.picking_type_id = requisition.picking_type_id.id
+ if requisition.type_id.line_copy != 'copy':
+ return
+
+ order_lines = []
+ for line in requisition.line_ids:
+ product_lang = line.product_id.with_context({
+ 'lang': partner.lang,
+ 'partner_id': partner.id,
+ })
+ name = product_lang.display_name
+ if product_lang.description_purchase:
+ name += '\n' + product_lang.description_purchase
+
+ if fpos:
+ taxes_ids = fpos.map_tax(
+ line.product_id.supplier_taxes_id.filtered(
+ lambda tax: tax.company_id == company))
+ else:
+ taxes_ids = line.product_id.supplier_taxes_id.filtered(
+ lambda tax: tax.company_id == company).ids
+
+ if line.product_uom_id != line.product_id.uom_po_id:
+ product_qty = line.product_uom_id._compute_quantity(
+ line.product_qty, line.product_id.uom_po_id)
+ price_unit = line.product_uom_id._compute_price(
+ line.price_unit, line.product_id.uom_po_id)
+ else:
+ product_qty = line.product_qty
+ price_unit = line.price_unit
+
+ if requisition.type_id.quantity_copy != 'copy':
+ product_qty = 0
+
+ if company.currency_id != currency:
+ price_unit = requisition.company_id.currency_id.compute(
+ price_unit, currency)
+
+ order_lines.append((0, 0, {
+ 'name': name,
+ 'product_id': line.product_id.id,
+ 'product_uom': line.product_id.uom_po_id.id,
+ 'product_qty': product_qty,
+ 'price_unit': price_unit,
+ 'taxes_id': [(6, 0, taxes_ids)],
+ 'date_planned':
+ requisition.schedule_date or fields.Date.today(),
+ 'account_analytic_id': line.account_analytic_id.id,
+ 'purchase_indent_ids': [(6, 0, line.purchase_indent_ids.ids)],
+ 'purchase_indent_line_id': line.purchase_indent_line_id.id,
+ }))
+ self.order_line = order_lines
+
+ @api.multi
+ def button_draft(self):
+ self.env['purchase.indent'].set_qty_state_confirm(self, False)
+ return super(PurchaseOrder, self).button_draft()
+
+ @api.multi
+ def button_cancel(self):
+ res = super(PurchaseOrder, self).button_cancel()
+ for purchase_order_id in self:
+ self.env['purchase.indent'].set_qty_state_cancel(
+ purchase_order_id, False)
+ return res
+
+ @api.model
+ def create(self, vals):
+ if vals.get('requisition_id', False):
+ requisition_id = self.requisition_id.browse(
+ vals.get('requisition_id', False))
+ if requisition_id.purchase_indent_ids:
+ vals['purchase_indent_ids'] = \
+ [(6, 0, requisition_id.purchase_indent_ids.ids)]
+ return super(PurchaseOrder, self).create(vals)
+
+ @api.multi
+ def write(self, vals):
+ res = super(PurchaseOrder, self).write(vals)
+ if vals.get('requisition_id', False):
+ self.write({
+ 'purchase_indent_ids':
+ [(6, 0, self.requisition_id.purchase_indent_ids.ids)]})
+ return res
+
+ @api.multi
+ def unlink(self):
+ for record in self:
+ if record.purchase_indent_ids:
+ raise Warning(_("You can not delete Purchase order which \
+ have reference of Purchase Indent!"))
+ return super(PurchaseOrder, self).unlink()
+
+ @api.multi
+ def copy(self):
+ self.ensure_one()
+ if self.purchase_indent_ids:
+ raise Warning(_("You can not copy Purchase order which have \
+ reference of Purchase Indent!"))
+ return super(PurchaseOrder, self).copy()
+
+
+class PurchaseOrderLine(models.Model):
+ _inherit = 'purchase.order.line'
+
+ purchase_indent_line_id = fields.Many2one(
+ 'purchase.indent.line', 'Purchase Indent Line Ref')
+ purchase_indent_ids = fields.Many2many(
+ 'purchase.indent', string='Purchase Indent')
+
+ @api.multi
+ def unlink(self):
+ if self.purchase_indent_line_id:
+ raise Warning(_("You can not delete line which have \
+ reference of Purchase Indent"))
+ return super(PurchaseOrderLine, self).unlink()
+
+
+class PurchaseRequisition(models.Model):
+ _name = 'purchase.requisition'
+ _inherit = ['purchase.requisition']
+
+ purchase_indent_ids = fields.Many2many(
+ 'purchase.indent', string='Purchase Indent')
+
+ @api.multi
+ def action_draft(self):
+ self.env['purchase.indent'].set_qty_state_confirm(False, self)
+ return super(PurchaseRequisition, self).action_draft()
+
+ @api.multi
+ def action_cancel(self):
+ self.env['purchase.indent'].set_qty_state_cancel(False, self)
+ return super(PurchaseRequisition, self).action_cancel()
+
+ @api.multi
+ def unlink(self):
+ for record in self:
+ if record.purchase_indent_ids:
+ raise Warning(_("You can not delete agreement which have \
+ reference of Purchase Indent!"))
+ return super(PurchaseRequisition, self).unlink()
+
+ @api.multi
+ def copy(self, default=None):
+ self.ensure_one()
+ default = dict(default or {})
+ if self.purchase_indent_ids:
+ raise Warning(_("You can not copy Purchase Agreement which \
+ have reference of Purchase Indent!"))
+ default.update(
+ name=_("%s (copy)") % (self.name or ''))
+ return super(PurchaseRequisition, self).copy(default)
+
+
+class PurchaseRequisitionLine(models.Model):
+ _inherit = 'purchase.requisition.line'
+
+ purchase_indent_line_id = fields.Many2one(
+ 'purchase.indent.line', 'Purchase Indent Line Ref')
+ purchase_indent_ids = fields.Many2many(
+ 'purchase.indent', string='Purchase Indent')
+
+
+class PurchaseIndent(models.Model):
+ _name = 'purchase.indent'
+ _inherit = ['mail.thread', 'mail.activity.mixin']
+ _description = "Purchase Indent"
+
+ @api.multi
+ def _compute_order_count(self):
+ po_list = []
+ pa_list = []
+ for history_id in self.intend_history_ids:
+ if history_id.order_id:
+ po_list.append(history_id.order_id.id)
+ elif history_id.purchase_requisition_id:
+ pa_list.append(history_id.purchase_requisition_id.id)
+ self.purchase_order_count = len(list(set(po_list)))
+ self.agreement_count = len(list(set(pa_list)))
+
+ @api.model
+ def _default_picking_type(self):
+ type_obj = self.env['stock.picking.type']
+ company_id = \
+ self.env.context.get('company_id') or self.env.user.company_id.id
+ types = type_obj.search([('code', '=', 'incoming'),
+ ('warehouse_id.company_id', '=', company_id)])
+ if not types:
+ types = type_obj.search([('code', '=', 'incoming'),
+ ('warehouse_id', '=', False)])
+ return types[:1]
+
+ name = fields.Char(
+ 'Reference', index=True, copy=False,
+ readonly=True, track_visibility='onchange')
+ request_date = fields.Date(
+ 'Request Date', default=fields.Date.today(),
+ track_visibility='onchange')
+ category_id = fields.Many2one(
+ 'product.category', 'Category', track_visibility='onchange')
+ state = fields.Selection([
+ ('draft', 'Draft'), ('confirm', 'Confirm'),
+ ('requisition', 'Requisition'), ('done', 'Done'),
+ ('cancel', 'Cancel')], 'State',
+ default='draft', track_visibility='onchange')
+ indent_line = fields.One2many(
+ 'purchase.indent.line', 'purchase_indent_id', 'Indent Lines')
+ company_id = fields.Many2one(
+ 'res.company', string='Company', track_visibility='onchange')
+ user_id = fields.Many2one(
+ 'res.users', string='Requested By',
+ default=lambda self: self.env.uid,
+ readonly=True, track_visibility='onchange')
+ partner_id = fields.Many2one(
+ 'res.partner', related='user_id.partner_id',
+ string="Partner", track_visibility='onchange')
+ intend_history_ids = fields.One2many(
+ 'purchase.indent.history', 'purchase_indent_id', 'History')
+ purchase_order_count = fields.Integer(
+ compute='_compute_order_count', string='# of Purchase Order')
+ agreement_count = fields.Integer(
+ compute='_compute_order_count', string='# of Purchase Agreement')
+ dest_address_id = fields.Many2one(
+ 'res.partner', string='Drop Ship Address',
+ help="Put an address if you want to deliver directly from the vendor \
+ to the customer.Otherwise, keep empty to deliver to your own company.")
+ picking_type_id = fields.Many2one(
+ 'stock.picking.type', 'Deliver To', required=True,
+ default=_default_picking_type,
+ help="This will determine operation type of incoming shipment")
+ default_location_dest_id_usage = fields.Selection(
+ related='picking_type_id.default_location_dest_id.usage',
+ string='Destination Location Type',
+ help="Technical field used to display the Drop Ship Address",
+ readonly=True)
+
+ @api.multi
+ def set_qty_state_cancel(self, purchase_order_id=False,
+ purchase_agreement_id=False):
+ intend_history_ids = []
+ indent_line_obj = self.env['purchase.indent.line']
+ if purchase_order_id:
+ intend_history_ids = self.env['purchase.indent.history'].search([
+ ('order_id', '=', purchase_order_id.id),
+ ('purchase_requisition_id', '=', False)])
+ elif purchase_agreement_id:
+ intend_history_ids = self.env['purchase.indent.history'].search([
+ ('order_id', '=', False),
+ ('purchase_requisition_id', '=', purchase_agreement_id.id)])
+ for history_id in intend_history_ids:
+ indent_line_id = indent_line_obj.sudo().search([
+ ('product_id', '=', history_id.product_id.id),
+ ('purchase_indent_id', '=', history_id.purchase_indent_id.id)])
+ requisition_qty = \
+ indent_line_id.requisition_qty - history_id.requisition_qty
+ indent_line_id.write({'requisition_qty': requisition_qty})
+ history_id.purchase_indent_id.check_state()
+ history_id.date = datetime.now()
+
+ @api.multi
+ def set_qty_state_confirm(self, purchase_order_id=False,
+ purchase_agreement_id=False):
+ indent_line_obj = self.env['purchase.indent.line']
+ intend_history_ids = []
+ if purchase_order_id:
+ intend_history_ids = self.env['purchase.indent.history'].search([
+ ('order_id', '=', purchase_order_id.id),
+ ('state', '=', 'Cancelled')])
+ elif purchase_agreement_id:
+ intend_history_ids = self.env['purchase.indent.history'].search([
+ ('purchase_requisition_id', '=', purchase_agreement_id.id),
+ ('state', '=', 'Cancelled')])
+ for history_id in intend_history_ids:
+ indent_line_id = indent_line_obj.sudo().search([
+ ('product_id', '=', history_id.product_id.id),
+ ('purchase_indent_id', '=', history_id.purchase_indent_id.id)])
+ if indent_line_id.requisition_qty + history_id.requisition_qty > \
+ indent_line_id.product_qty:
+ remaining_qty = \
+ indent_line_id.product_qty - indent_line_id.requisition_qty
+ raise Warning(_("Requisition Quantity of ' %s ' is more than \
+ Remaining Quantity (%s)!") % (
+ history_id.product_id.name, formatLang(
+ self.env, remaining_qty, digits=2)))
+ requisition_qty = \
+ indent_line_id.requisition_qty + history_id.requisition_qty
+ indent_line_id.write({'requisition_qty': requisition_qty})
+ history_id.purchase_indent_id.check_state()
+ history_id.date = datetime.now()
+
+ @api.onchange('company_id')
+ def onchange_company_id(self):
+ res = {}
+ user_company_id = self.user_id.company_ids
+ res['domain'] = {'company_id': [
+ ('id', 'in', user_company_id.ids)]}
+ if len(user_company_id) == 1:
+ res['domain'] = {
+ 'company_id': [('id', '=', user_company_id.id)]}
+ self.company_id = user_company_id.id
+ return res
+
+ @api.multi
+ def check_duplicate_product(self):
+ product_dup_list = []
+ for line in self.indent_line:
+ if line.product_id.id not in product_dup_list:
+ product_dup_list.append(line.product_id.id)
+ else:
+ dup_line_id = self.env['purchase.indent.line'].search([
+ ('purchase_indent_id', '=', line.purchase_indent_id.id),
+ ('product_id', '=', line.product_id.id)], limit=1)
+ dup_line_id.product_qty += line.product_qty
+ line.unlink()
+
+ @api.multi
+ def action_confirm(self):
+ if self._uid != self.create_uid.id:
+ raise Warning(_("You can't confirm purchase indent which is \
+ requested by %s!") % (self.create_uid.name))
+ if not self.indent_line:
+ raise Warning(_('No Product Line(s) were found!'))
+ check_pro_qty = [
+ line.id for line in self.indent_line if line.product_qty]
+ if not check_pro_qty:
+ raise Warning(_("No Quantity were found for any line!"))
+ self.check_duplicate_product()
+ group_id = self.sudo().env.ref('purchase.group_purchase_manager')
+ if not group_id.users:
+ raise AccessError(
+ _("Please contact your Administrator \n \
+ No user found under 'Purchase Manager'"))
+ server_id = self.env['ir.mail_server'].search([])
+ if not server_id:
+ raise AccessError(
+ _("Please configure outgoing mail server"))
+ email_to = ",".join([user.email
+ for user in group_id.users if user.email])
+ recipient_ids = [user.partner_id.id for user in group_id.users]
+ if self.env.user.email:
+ product_qty = '''
+
+
+ ''' + _("Product Name") + ''' |
+ ''' + _("Quantity") + ''' |
+ ''' + _("Expected Date") + ''' |
+
'''
+ for line in self.indent_line:
+ qty = (str(formatLang(self.env, line.product_qty, digits=2)))
+ product_qty += '\
+ ' + str(line.product_id.name) + ' | \
+ ' + qty + ' | \
+ ' + str(line.expected_date) + ' | \
+
'
+ msg1 = 'Purchase Indent "%s" Confirmed by "%s" for following \
+ Products Details.
' % (self.name, self.env.user.name)
+ msg1 += ' %s
' % (product_qty)
+ create_values = {
+ 'body_html': msg1,
+ 'subject': 'Purchase Indent Confirmed by %s' % (
+ self.env.user.name),
+ 'email_from': self.env.user.email,
+ 'email_to': email_to,
+ 'model': 'purchase.indent',
+ 'res_id': self.id,
+ 'reply_to': '',
+ 'recipient_ids': [(6, 0, recipient_ids)],
+ }
+ email_id = self.env['mail.mail'].create(create_values)
+ email_id.send()
+ else:
+ raise AccessError(_("Please configure your email"))
+ self.state = 'confirm'
+
+ @api.multi
+ def action_cancel(self):
+ group_id = self.sudo().env.ref('purchase.group_purchase_manager')
+ if self._uid != self.create_uid.id \
+ and self._uid not in group_id.users.ids:
+ raise Warning(_("Can't cancel purchase indent which is \
+ requested by %s!") % (self.create_uid.name))
+ self.state = 'cancel'
+
+ @api.multi
+ def button_draft(self):
+ self.state = 'draft'
+
+ @api.model
+ def create(self, vals):
+ if vals.get('name', 'New') == 'New':
+ vals['name'] = \
+ self.env['ir.sequence'].next_by_code('purchase.indent') or '/'
+ return super(PurchaseIndent, self).create(vals)
+
+ @api.multi
+ def get_purchase_order_list(self):
+ order_list = [
+ history_id.order_id.id for history_id in self.intend_history_ids]
+ return {
+ 'name': 'Purchase Orders',
+ 'type': 'ir.actions.act_window',
+ 'view_type': 'form',
+ 'view_mode': 'tree,form,kanban,pivot,graph',
+ 'res_model': 'purchase.order',
+ 'domain': [('id', 'in', list(set(order_list)))],
+ }
+
+ @api.multi
+ def get_purchase_agreement_list(self):
+ pr_list = [history_id.purchase_requisition_id.id
+ for history_id in self.intend_history_ids]
+ return {
+ 'name': 'Purchase Agreements',
+ 'type': 'ir.actions.act_window',
+ 'view_type': 'form',
+ 'view_mode': 'tree,form',
+ 'res_model': 'purchase.requisition',
+ 'domain': [('id', 'in', list(set(pr_list)))],
+ }
+
+ @api.multi
+ def unlink(self):
+ for indent_id in self:
+ if indent_id.state not in ['draft', 'cancel']:
+ raise Warning(_("Invalid Action!\n You cannot delete a \
+ Purchase Indent which is not in 'Draft' or 'Cancel' State!"))
+ indent_id.indent_line.unlink()
+ return super(PurchaseIndent, self).unlink()
+
+ @api.multi
+ def check_state(self):
+ check = False
+ state = ''
+ for line in self.indent_line:
+ if line.requisition_qty \
+ and line.product_qty != line.requisition_qty:
+ state = 'requisition'
+ check = False
+ break
+ elif not line.requisition_qty:
+ if check:
+ state = 'requisition'
+ check = False
+ break
+ state = 'confirm'
+ check = False
+ else:
+ if line.product_qty != line.requisition_qty:
+ check = False
+ break
+ else:
+ check = True
+ if check:
+ state = 'done'
+ self.write({'state': state})
+
+
+class PurchaseIndentLine(models.Model):
+ _name = 'purchase.indent.line'
+ _description = "Purchase Indent Line"
+
+ @api.multi
+ @api.depends('requisition_qty', 'product_qty')
+ def _compute_get_rem_qty(self):
+ for self_id in self:
+ self_id.remaining_qty = \
+ self_id.product_qty - self_id.requisition_qty
+
+ purchase_indent_id = fields.Many2one('purchase.indent', 'Purchase Indent')
+ name = fields.Text(string='Description', required=True)
+ sequence = fields.Integer(string='Sequence', default=10)
+ product_qty = fields.Float(
+ string='Request Quantity', digits=dp.get_precision('Discount'))
+ expected_date = fields.Date(
+ string='Expected Date', index=True, default=fields.Date.today())
+ product_uom = fields.Many2one(
+ 'product.uom', string='Product Unit of Measure')
+ product_id = fields.Many2one(
+ 'product.product', string='Product',
+ change_default=True, required=True)
+ company_id = fields.Many2one(
+ 'res.company', related='purchase_indent_id.company_id',
+ string='Company', store=True, readonly=True)
+ requisition_qty = fields.Float(
+ string="Requisition Quantity",
+ digits=dp.get_precision('Discount'))
+ partner_id = fields.Many2one(
+ 'res.partner', related='purchase_indent_id.partner_id',
+ string='Partner', readonly=True, store=True)
+ remaining_qty = fields.Float(
+ compute="_compute_get_rem_qty", string='Remaining Quantity',
+ digits=dp.get_precision('Discount'), store=True)
+
+ @api.onchange('product_id')
+ def onchange_product_id(self):
+ result = {}
+ if not self.product_id:
+ return result
+ self.product_uom = self.product_id.uom_po_id or self.product_id.uom_id
+ result['domain'] = {'product_uom': [
+ ('category_id', '=', self.product_id.uom_id.category_id.id)]}
+ product_lang = self.product_id.with_context({
+ 'lang': self.partner_id.lang,
+ 'partner_id': self.partner_id.id,
+ })
+ self.name = product_lang.display_name
+ if product_lang.description_purchase:
+ self.name += '\n' + product_lang.description_purchase
+ return result
+
+ @api.onchange('product_qty')
+ def onchange_product_qty(self):
+ warning = {}
+ if self.product_qty < 0:
+ warning.update({
+ 'title': _("Warning"),
+ 'message': _("Quantity (%s) can not be Negative!") % (
+ formatLang(self.env, self.product_qty, digits=2))
+ })
+ self.product_qty = False
+ return {'warning': warning}
+
+
+class PurchaseIndentHistory(models.Model):
+ _name = 'purchase.indent.history'
+ _description = "Purchase Indent History"
+ _order = 'id desc'
+
+ @api.multi
+ @api.depends('order_id.state', 'purchase_requisition_id.state')
+ def _compute_get_state(self):
+ for history_id in self:
+ name = ""
+ if history_id.order_id:
+ po_dict = dict(history_id.order_id.fields_get(
+ allfields=['state'])['state']['selection'])
+ name = po_dict.get(history_id.order_id.state)
+ elif history_id.purchase_requisition_id:
+ pa_dict = dict(history_id.purchase_requisition_id.fields_get(
+ allfields=['state'])['state']['selection'])
+ name = pa_dict.get(history_id.purchase_requisition_id.state)
+ history_id.state = name
+
+ @api.multi
+ @api.depends('requisition_qty', 'product_qty', 'state')
+ def _compute_get_rem_qty(self):
+ for self_id in self:
+ if self_id.state == 'Cancelled':
+ self_id.remaining_qty = self_id.product_qty
+ else:
+ self_id.remaining_qty = \
+ self_id.product_qty - self_id.requisition_qty
+
+ purchase_indent_id = fields.Many2one('purchase.indent', 'Purchase Indent')
+ product_id = fields.Many2one(
+ 'product.product', string='Product',
+ domain=[('purchase_ok', '=', True)],
+ change_default=True, required=True)
+ order_id = fields.Many2one('purchase.order', 'Purchase Order')
+ purchase_requisition_id = fields.Many2one(
+ 'purchase.requisition', 'Purchase Agreement')
+ date = fields.Datetime('Date')
+ product_qty = fields.Float(
+ 'Quantity', digits=dp.get_precision('Discount'))
+ requisition_qty = fields.Float(
+ string="Transfer Quantity",
+ digits=dp.get_precision('Discount'))
+ state = fields.Char(compute='_compute_get_state', string='State',
+ store=True)
+ remaining_qty = fields.Float(
+ compute="_compute_get_rem_qty", string='Remaining Quantity',
+ digits=dp.get_precision('Discount'), store=True)
+
+ @api.multi
+ def open_form_view(self):
+ res_id = model = False
+ if self.order_id:
+ res_id = self.order_id.id
+ model = 'purchase.order'
+ elif self.purchase_requisition_id:
+ res_id = self.purchase_requisition_id.id
+ model = 'purchase.requisition'
+ return {
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'res_model': model,
+ 'res_id': res_id,
+ 'view_id': False,
+ 'type': 'ir.actions.act_window',
+ }
diff --git a/addons/purchase_indent/report/purchase_indent_reports.xml b/addons/purchase_indent/report/purchase_indent_reports.xml
new file mode 100644
index 00000000..fe1929e0
--- /dev/null
+++ b/addons/purchase_indent/report/purchase_indent_reports.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+ 'Request for Indent'+'-'+(object.name)
+
+
+
diff --git a/addons/purchase_indent/report/purchase_indent_template.xml b/addons/purchase_indent/report/purchase_indent_template.xml
new file mode 100644
index 00000000..ae3b473d
--- /dev/null
+++ b/addons/purchase_indent/report/purchase_indent_template.xml
@@ -0,0 +1,130 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Shipping address:
+
+
+
+
+
+
+
+
+ Purchase Indent
+
+
+
+
+
+
+
+
+
+ Sr |
+ Product |
+ Description |
+ Unit |
+ Expected Date
+ |
+ Request
+ Quantity
+ |
+ Requisition
+ Quantity
+ |
+ Remaining
+ Quantity
+ |
+
+
+
+
+
+ .
+ |
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+
+
+
+ Requested By: |
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/purchase_indent/security/ir.model.access.csv b/addons/purchase_indent/security/ir.model.access.csv
new file mode 100644
index 00000000..e21e9376
--- /dev/null
+++ b/addons/purchase_indent/security/ir.model.access.csv
@@ -0,0 +1,9 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_purchase_indent_line,access_purchase_indent_line,model_purchase_indent_line,purchase.group_purchase_manager,1,1,1,1
+access_purchase_indent,access_purchase_indent,model_purchase_indent,purchase.group_purchase_manager,1,1,1,1
+access_purchase_indent_history,access_purchase_indent_history,model_purchase_indent_history,purchase.group_purchase_manager,1,1,1,1
+access_purchase_indent_line_user,access_purchase_indent_line_user,model_purchase_indent_line,purchase.group_purchase_user,1,1,1,1
+access_purchase_indent_user,access_purchase_indent_user,model_purchase_indent,purchase.group_purchase_user,1,1,1,1
+access_purchase_indent_history_user,access_purchase_indent_history_user,model_purchase_indent_history,purchase.group_purchase_user,1,1,0,0
+access_ir_mail_server_user,access_ir_mail_server_user,base.model_ir_mail_server,purchase.group_purchase_user,1,0,0,0
+access_ir_mail_server_manager,access_ir_mail_server_manager,base.model_ir_mail_server,purchase.group_purchase_manager,1,0,0,0
diff --git a/addons/purchase_indent/security/purchase_indent_security.xml b/addons/purchase_indent/security/purchase_indent_security.xml
new file mode 100644
index 00000000..8d57f82d
--- /dev/null
+++ b/addons/purchase_indent/security/purchase_indent_security.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+ Purchase Indent multi-company
+
+
+
+ ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]
+
+
+
+
+ Purchase Indent Line multi-company
+
+
+
+ ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]
+
+
+
+
diff --git a/addons/purchase_indent/static/description/purchase-indent.png b/addons/purchase_indent/static/description/purchase-indent.png
new file mode 100644
index 00000000..9f75d746
Binary files /dev/null and b/addons/purchase_indent/static/description/purchase-indent.png differ
diff --git a/addons/purchase_indent/tests/__init__.py b/addons/purchase_indent/tests/__init__.py
new file mode 100644
index 00000000..10752aa5
--- /dev/null
+++ b/addons/purchase_indent/tests/__init__.py
@@ -0,0 +1,3 @@
+# Part of Flectra See LICENSE file for full copyright and licensing details.
+
+from . import test_purchase_indent
diff --git a/addons/purchase_indent/tests/test_purchase_indent.py b/addons/purchase_indent/tests/test_purchase_indent.py
new file mode 100644
index 00000000..67329bca
--- /dev/null
+++ b/addons/purchase_indent/tests/test_purchase_indent.py
@@ -0,0 +1,123 @@
+# Part of Flectra See LICENSE file for full copyright and licensing details.
+
+import logging
+from datetime import datetime
+
+from flectra.exceptions import Warning
+from flectra.tests.common import TransactionCase
+from flectra.tools.misc import formatLang
+
+from flectra import _
+
+
+class TestPurchaseIndent(TransactionCase):
+
+ def setUp(self):
+ super(TestPurchaseIndent, self).setUp()
+ self.PurchaseIndent = self.env['purchase.indent']
+ self.PurchaseIndentLine = self.env['purchase.indent.line']
+ self.Requisition_Req = self.env['wiz.requisition.request']
+
+ def test_00_purchase_indent_flow(self):
+ self.partner_id = self.env.ref('base.res_partner_address_12')
+ self.category_id = self.env.ref('product.product_category_5')
+ self.product_id_1 = self.env.ref('product.product_product_24')
+ self.product_id_2 = self.env.ref('product.product_product_16')
+ self.product_id_3 = self.env.ref('product.consu_delivery_03')
+ self.company_id = self.env.ref('base.main_company')
+ self.agreement_type_id = \
+ self.env.ref('purchase_requisition.type_multi')
+
+ purchase_indent_vals_1 = {
+ 'company_id': self.company_id.id,
+ 'category_id': self.category_id.id,
+ 'request_date': datetime.today(),
+ 'user_id': self.env.user.id,
+ 'indent_line': [
+ (0, 0, {
+ 'name': self.product_id_1.name,
+ 'product_id': self.product_id_1.id,
+ 'product_qty': 5.0,
+ 'product_uom': self.product_id_1.uom_po_id.id,
+ }),
+ (0, 0, {
+ 'name': self.product_id_2.name,
+ 'product_id': self.product_id_2.id,
+ 'product_qty': 15.0,
+ 'product_uom': self.product_id_2.uom_po_id.id,
+ })],
+ }
+
+ purchase_indent_vals_2 = {
+ 'company_id': self.company_id.id,
+ 'category_id': self.category_id.id,
+ 'request_date': datetime.today(),
+ 'user_id': self.env.user.id,
+ 'indent_line': [
+ (0, 0, {
+ 'name': self.product_id_3.name,
+ 'product_id': self.product_id_3.id,
+ 'product_qty': 20.0,
+ 'product_uom': self.product_id_3.uom_po_id.id,
+ }),
+ (0, 0, {
+ 'name': self.product_id_1.name,
+ 'product_id': self.product_id_1.id,
+ 'product_qty': 25.0,
+ 'product_uom': self.product_id_1.uom_po_id.id,
+ }),
+ (0, 0, {
+ 'name': self.product_id_2.name,
+ 'product_id': self.product_id_2.id,
+ 'product_qty': 5.0,
+ 'product_uom': self.product_id_2.uom_po_id.id,
+ })],
+ }
+ self.pi = self.PurchaseIndent.create(purchase_indent_vals_1)
+ self.pi_1 = self.PurchaseIndent.create(purchase_indent_vals_2)
+ self.assertTrue(
+ self.pi, 'Purchase Indent: no purchase indent created')
+ self.assertTrue(
+ self.pi_1, 'Purchase Indent: no purchase indent created')
+
+ for line in self.pi.indent_line:
+ if line.product_qty < 0:
+ raise Warning(_("Quantity (%s) can not be Negative!") % (
+ formatLang(self.env, line.product_qty, digits=2)))
+
+ for line in self.pi_1.indent_line:
+ if line.product_qty < 0:
+ raise Warning(_("Quantity (%s) can not be Negative!") % (
+ formatLang(self.env, line.product_qty, digits=2)))
+
+ self.pi.action_confirm()
+ self.pi_1.action_confirm()
+
+ requisition_id = self.Requisition_Req.create({
+ 'category_id': self.category_id.id,
+ 'order_type': 'po',
+ 'purchase_indent_id': self.pi.id,
+ })
+ requisition_id.onchange_purchase_indent_id()
+ requisition_id.dummy_wiz_indent_line[0].write({'requisition_qty': 5})
+ requisition_id.dummy_wiz_indent_line[2].write({'requisition_qty': 20})
+ requisition_id.act_next()
+ requisition_id.write({'partner_id': self.partner_id.id})
+ for line in requisition_id.wiz_indent_line:
+ line.write({'price_unit': 100})
+ requisition_id.action_create()
+ requisition_id_1 = self.Requisition_Req.create({
+ 'category_id': self.category_id.id,
+ 'order_type': 'pa',
+ 'purchase_indent_id': self.pi_1.id,
+ 'requisition_type_id': self.agreement_type_id.id,
+ })
+
+ requisition_id_1.onchange_purchase_indent_id()
+ requisition_id_1.dummy_wiz_indent_line[1].write({'requisition_qty': 4})
+ requisition_id_1.dummy_wiz_indent_line[2].write({'requisition_qty': 5})
+ requisition_id_1.act_next()
+ for line in requisition_id_1.wiz_indent_line:
+ line.write({'price_unit': 100})
+ requisition_id_1.action_create()
+ logging.info('\n\nSuccessful: Purchase Agreement Created!')
diff --git a/addons/purchase_indent/views/purchase_indent_view.xml b/addons/purchase_indent/views/purchase_indent_view.xml
new file mode 100644
index 00000000..37fc086b
--- /dev/null
+++ b/addons/purchase_indent/views/purchase_indent_view.xml
@@ -0,0 +1,171 @@
+
+
+
+
+ Purchase inherited form
+ purchase.order
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Purchase Requisition Inherited Form
+ purchase.requisition
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Purchase indent tree
+ purchase.indent
+
+
+
+
+
+
+
+
+
+
+
+
+
+ purchase.indent.form
+ purchase.indent
+
+
+
+
+
+
+ purchase.indent.search
+ purchase.indent
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Purchase Indent
+ purchase.indent
+ form
+ tree,form
+
+ {'search_default_confirm':1, 'search_default_requisition': 1}
+
+
+
+
+
+
+
+ Purchase Indent
+ purchase.indent
+ Indent/
+ 3
+
+
+
+
diff --git a/addons/purchase_indent/wizard/__init__.py b/addons/purchase_indent/wizard/__init__.py
new file mode 100644
index 00000000..b1cff651
--- /dev/null
+++ b/addons/purchase_indent/wizard/__init__.py
@@ -0,0 +1,3 @@
+# Part of Flectra See LICENSE file for full copyright and licensing details.
+
+from . import wiz_requisition_request
diff --git a/addons/purchase_indent/wizard/wiz_requisition_request.py b/addons/purchase_indent/wizard/wiz_requisition_request.py
new file mode 100644
index 00000000..b3076d53
--- /dev/null
+++ b/addons/purchase_indent/wizard/wiz_requisition_request.py
@@ -0,0 +1,416 @@
+# Part of Flectra See LICENSE file for full copyright and licensing details.
+
+from datetime import datetime
+
+from flectra.exceptions import Warning
+from flectra.tools.misc import formatLang
+
+import flectra.addons.decimal_precision as dp
+from flectra import api, fields, models, _
+
+
+class WizRequisitionRequest(models.TransientModel):
+ _name = 'wiz.requisition.request'
+
+ purchase_indent_id = fields.Many2one('purchase.indent', 'Purchase Indent')
+ partner_id = fields.Many2one(
+ 'res.partner', 'Vendor', domain="[('supplier','=',True)]")
+ wiz_indent_line = fields.One2many(
+ 'wiz.indent.line', 'wizard_indent_id', string='Indent Lines')
+ category_id = fields.Many2one(
+ 'product.category', 'Category', readonly=True)
+ state = fields.Selection(
+ [('draft', 'Draft'), ('confirm', 'Confirm')], default='draft')
+ dummy_wiz_indent_line = fields.One2many(
+ 'dummy.wiz.indent.line', 'wizard_indent_id', string='Indent Lines')
+ order_type = fields.Selection([
+ ('po', 'Purchase Order'),
+ ('pa', 'Purchase Agreement')], string='Order Type', default='po')
+ requisition_type_id = fields.Many2one(
+ 'purchase.requisition.type', string="Agreement Type")
+
+ @api.onchange('partner_id')
+ def onchange_partner_id(self):
+ obj_pro_sup = self.env['product.supplierinfo']
+ for line in self.wiz_indent_line:
+ pro_supplier_info_ids = obj_pro_sup.search([
+ ('product_tmpl_id', '=', line.product_id.product_tmpl_id.id),
+ ('name', '=', self.partner_id.id)])
+ if pro_supplier_info_ids:
+ line.price_unit = \
+ max([pro_sup_id.price
+ for pro_sup_id in pro_supplier_info_ids])
+
+ @api.onchange('purchase_indent_id')
+ def onchange_purchase_indent_id(self):
+ if self.state == 'draft':
+ purchase_indent_ids = self.purchase_indent_id.search([
+ ('category_id', '=', self.purchase_indent_id.category_id.id),
+ ('state', 'in', ['confirm', 'requisition']),
+ ('company_id', '=', self.purchase_indent_id.company_id.id)])
+ list_data = []
+ value = {}
+ for purchase_indent_id in purchase_indent_ids:
+ for indent_line_id in purchase_indent_id.indent_line:
+ if not indent_line_id.product_qty == \
+ indent_line_id.requisition_qty:
+ list_data.append(
+ (0, 0, {
+ 'partner_id': purchase_indent_id.partner_id.id,
+ 'name': indent_line_id.name,
+ 'product_id': indent_line_id.product_id.id,
+ 'product_qty': indent_line_id.product_qty,
+ 'dummy_product_qty':
+ indent_line_id.product_qty,
+ 'indent_requ_date':
+ purchase_indent_id.request_date,
+ 'expected_date': indent_line_id.expected_date,
+ 'product_uom': indent_line_id.product_uom.id,
+ 'purchase_indent_id': purchase_indent_id.id,
+ 'purchase_indent_line_id': indent_line_id.id,
+ 'wizard_indent_id': self.id
+ }))
+ value['dummy_wiz_indent_line'] = list_data
+ self.update(value)
+
+ @api.onchange('order_type')
+ def onchange_order_type(self):
+ if self.order_type == 'po':
+ self.requisition_type_id = False
+
+ @api.multi
+ def act_next(self):
+ wiz_line_object = self.env['wiz.indent.line']
+ dummy_wiz_line_object = self.env['dummy.wiz.indent.line']
+ dup_product_list = []
+ list_data = []
+ unique_list = []
+ check_requisition_qty = False
+
+ for line in self.dummy_wiz_indent_line:
+ if line.requisition_qty:
+ check_requisition_qty = True
+ line.requisition_qty = line.requisition_qty
+ if line.product_id.id not in dup_product_list:
+ dup_product_list.append(line.product_id.id)
+ if not check_requisition_qty:
+ raise Warning(_("No Requisition Quantity were \
+ found for any line!"))
+ msg = 'Following Requisition Quantity is greater than Remaining ' \
+ 'Quantity!\n'
+ check_warning = False
+ for line in self.dummy_wiz_indent_line:
+ if not line.requisition_qty:
+ continue
+ if line.requisition_qty > line.remaining_qty:
+ check_warning = True
+ msg += ("\n %s : Product (%s) => Requisition Quantity (%s) "
+ "and Remaining Quantity (%s)!") % (
+ line.purchase_indent_id.name, line.product_id.name,
+ formatLang(self.env, line.requisition_qty, digits=2),
+ formatLang(self.env, line.remaining_qty, digits=2))
+ if check_warning:
+ raise Warning(_(msg))
+ for line in self.dummy_wiz_indent_line:
+ if not line.requisition_qty:
+ continue
+ line_vals = {
+ 'purchase_indent_ids':
+ [(4, line.purchase_indent_id.id)],
+ 'partner_id': line.partner_id.id,
+ 'name': line.name,
+ 'product_id': line.product_id.id,
+ 'product_qty': line.requisition_qty,
+ 'product_uom': line.product_uom.id,
+ 'purchase_indent_line_id':
+ line.purchase_indent_line_id.id,
+ 'wizard_indent_id': self.id,
+ 'expected_date': line.expected_date,
+ 'taxes_id': [(6, 0, line.product_id.supplier_taxes_id.ids)],
+ }
+ if dup_product_list:
+ if line.product_id.id not in unique_list:
+ new_line_id = wiz_line_object.create(line_vals)
+ unique_list.append(line.product_id.id)
+ list_data.append(new_line_id.id)
+ else:
+ wiz_ids = dummy_wiz_line_object.search([
+ ('wizard_indent_id', '=', line.wizard_indent_id.id),
+ ('product_id', '=', line.product_id.id)])
+ wiz_indent_line_id = wiz_line_object.search([
+ ('wizard_indent_id', '=', self.id),
+ ('product_id', '=', line.product_id.id)])
+ indent_list = []
+ qty = 0.0
+ for wiz_id in wiz_ids:
+ indent_list.append(wiz_id.purchase_indent_id.id)
+ qty += wiz_id.requisition_qty
+ wiz_indent_line_id.write({
+ 'product_qty': qty,
+ 'purchase_indent_ids':
+ [(6, 0, list(set(indent_list)))]})
+ else:
+ new_line_id = wiz_line_object.create(line_vals)
+ list_data.append(new_line_id.id)
+ self.write(
+ {'state': 'confirm', 'wiz_indent_line': [(6, False, list_data)]})
+ view_id = \
+ self.env.ref('purchase_indent.view_requisition_request_wizard')
+ context = dict(self._context)
+ return {
+ 'views': [(view_id.id, 'form')],
+ 'view_id': view_id.id,
+ 'type': 'ir.actions.act_window',
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'res_model': 'wiz.requisition.request',
+ 'target': 'new',
+ 'res_id': self.id,
+ 'context': context,
+ }
+
+ @api.multi
+ def action_create(self):
+ list_data = []
+ purchase_order_id = purchase_requisition_id = False
+ obj_history_purchase_indent = self.env['purchase.indent.history']
+
+ if self.order_type == 'po':
+ vals = {
+ 'partner_id': self.partner_id.id,
+ 'state': 'draft',
+ 'company_id': self.purchase_indent_id.company_id.id,
+ }
+ purchase_order_id = self.env['purchase.order'].create(vals)
+ else:
+ vals = {
+ 'name': self.sudo().env['ir.sequence'].next_by_code(
+ 'purchase.order.requisition') or 'New',
+ 'type_id': self.requisition_type_id.id,
+ 'state': 'draft',
+ 'company_id': self.purchase_indent_id.company_id.id,
+ }
+ purchase_requisition_id = self.env[
+ 'purchase.requisition'].create(vals)
+ indent_list = []
+ for current_line in self.sudo().wiz_indent_line:
+ current_line.purchase_indent_ids.write({'state': 'requisition'})
+ indent_list.extend(current_line.purchase_indent_ids.ids)
+ line_vals = {
+ 'product_id': current_line.product_id.id,
+ 'product_qty': current_line.product_qty,
+ 'purchase_indent_ids':
+ [(6, 0, current_line.purchase_indent_ids.ids)],
+ 'purchase_indent_line_id':
+ current_line.purchase_indent_line_id.id,
+ }
+ if self.order_type == 'po':
+ line_vals.update({
+ 'name': current_line.name,
+ 'date_planned': current_line.expected_date,
+ 'partner_id': self.partner_id.id,
+ 'price_unit': current_line.price_unit,
+ 'taxes_id': [(6, 0, current_line.taxes_id.ids)],
+ 'product_uom': current_line.product_uom.id,
+ })
+ else:
+ line_vals.update({
+ 'product_uom_id': current_line.product_uom.id,
+ })
+ list_data.append((0, 0, line_vals))
+ if len(current_line.purchase_indent_ids.ids) > 1:
+ for data in self.sudo().dummy_wiz_indent_line:
+ if data.product_id.id == current_line.product_id.id:
+ product_qty = data.purchase_indent_line_id.product_qty
+ requisition_qty = \
+ data.purchase_indent_line_id.requisition_qty
+ before_qty = product_qty - requisition_qty
+ data.purchase_indent_line_id.requisition_qty +=\
+ data.requisition_qty
+ obj_history_purchase_indent.create({
+ 'purchase_indent_id': data.purchase_indent_id.id,
+ 'product_id': data.product_id.id,
+ 'order_id':
+ purchase_order_id and purchase_order_id.id,
+ 'purchase_requisition_id':
+ purchase_requisition_id and
+ purchase_requisition_id.id,
+ 'date': datetime.now(),
+ 'product_qty': before_qty,
+ 'requisition_qty': data.requisition_qty
+ })
+ else:
+ product_qty = current_line.purchase_indent_line_id.product_qty
+ requisition_qty = \
+ current_line.purchase_indent_line_id.requisition_qty
+ before_qty = product_qty - requisition_qty
+ current_line.purchase_indent_line_id.requisition_qty +=\
+ current_line.product_qty
+ obj_history_purchase_indent.create({
+ 'purchase_indent_id': current_line.purchase_indent_ids.id,
+ 'product_id': current_line.product_id.id,
+ 'order_id': purchase_order_id and purchase_order_id.id,
+ 'purchase_requisition_id':
+ purchase_requisition_id and purchase_requisition_id.id,
+ 'date': datetime.now(),
+ 'product_qty': before_qty,
+ 'requisition_qty': current_line.product_qty,
+ })
+ if purchase_order_id:
+ purchase_order_id.write({
+ 'order_line': list_data,
+ 'purchase_indent_ids': [(6, 0, indent_list)]})
+ elif purchase_requisition_id:
+ purchase_requisition_id.write({
+ 'line_ids': list_data,
+ 'purchase_indent_ids': [(6, 0, indent_list)]})
+ self.check_state()
+
+ @api.multi
+ def check_state(self):
+ purchase_indent_ids = self.purchase_indent_id.search([
+ ('category_id', '=', self.purchase_indent_id.category_id.id),
+ ('state', 'in', ['confirm', 'requisition']),
+ ('company_id', '=', self.purchase_indent_id.company_id.id)])
+ for purchase_indent_id in purchase_indent_ids:
+ check = False
+ for line in purchase_indent_id.indent_line:
+ if line.product_qty != line.requisition_qty:
+ check = False
+ break
+ else:
+ check = True
+ if check:
+ purchase_indent_id.write({'state': 'done'})
+
+
+class WizIndentLine(models.TransientModel):
+ _name = 'wiz.indent.line'
+ _description = "Wizard Indent Line"
+
+ @api.depends('purchase_indent_line_id',
+ 'purchase_indent_line_id.product_qty',
+ 'purchase_indent_line_id.requisition_qty')
+ @api.multi
+ def _compute_get_rem_qty(self):
+ for line_id in self:
+ remaining_qty = 0.0
+ if line_id.purchase_indent_line_id:
+ remaining_qty = \
+ line_id.purchase_indent_line_id.product_qty - \
+ line_id.purchase_indent_line_id.requisition_qty
+ line_id.remaining_qty = remaining_qty
+
+ purchase_indent_ids = fields.Many2many(
+ 'purchase.indent', string='Purchase Indent')
+ name = fields.Text(string='Description', required=True)
+ sequence = fields.Integer(string='Sequence', default=10)
+ product_qty = fields.Float(
+ string='Quantity', digits=dp.get_precision('Discount'))
+ expected_date = fields.Datetime(string='Expected Date', index=True)
+ product_uom = fields.Many2one(
+ 'product.uom', string='Product Unit of Measure')
+ product_id = fields.Many2one(
+ 'product.product', string='Product',
+ domain=[('purchase_ok', '=', True)],
+ change_default=True, required=True)
+ requisition_qty = fields.Float(
+ string="Requisition Quantity",
+ digits=dp.get_precision('Discount'))
+ wizard_indent_id = fields.Many2one(
+ 'wiz.requisition.request', 'Wiz Requisition Request')
+
+ partner_id = fields.Many2one('res.partner', string='Partner')
+ price_unit = fields.Float(
+ string='Unit Price', digits=dp.get_precision('Product Price'))
+ taxes_id = fields.Many2many(
+ 'account.tax', string='Taxes',
+ domain=['|', ('active', '=', False), ('active', '=', True)])
+ purchase_indent_line_id = fields.Many2one(
+ 'purchase.indent.line', string="Indent Line Ref")
+ remaining_qty = fields.Float(
+ compute='_compute_get_rem_qty', string='Remaining Quantity',
+ store=True)
+ order_type = fields.Selection(
+ related='wizard_indent_id.order_type', string='Order Type')
+
+
+class DummyWizIndentLine(models.TransientModel):
+ _name = 'dummy.wiz.indent.line'
+ _description = "Dummy Wizard Indent Line"
+
+ @api.depends('purchase_indent_line_id',
+ 'purchase_indent_line_id.product_qty',
+ 'purchase_indent_line_id.requisition_qty')
+ @api.multi
+ def _compute_get_rem_qty(self):
+ for line_id in self:
+ remaining_qty = 0.0
+ if line_id.purchase_indent_line_id:
+ remaining_qty = \
+ line_id.purchase_indent_line_id.product_qty - \
+ line_id.purchase_indent_line_id.requisition_qty
+ line_id.remaining_qty = remaining_qty
+
+ purchase_indent_id = fields.Many2one(
+ 'purchase.indent', 'Purchase Indent',
+ domain="[('id', '=', purchase_indent_id)]")
+ name = fields.Text(string='Description')
+ sequence = fields.Integer(string='Sequence', default=10)
+ product_qty = fields.Float(
+ string='Quantity', digits=dp.get_precision('Discount'))
+ dummy_product_qty = fields.Float(string='Quantity',
+ digits=dp.get_precision('Discount'))
+ expected_date = fields.Datetime(string='Expected Date', index=True)
+ product_uom = fields.Many2one(
+ 'product.uom', string='Product Unit of Measure')
+ product_id = fields.Many2one(
+ 'product.product', string='Product',
+ domain="[('purchase_ok', '=', True), ('id', '=', product_id)]",
+ change_default=True, required=True)
+ company_id = fields.Many2one(
+ 'res.company', related='purchase_indent_id.company_id',
+ string='Company', store=True, readonly=True)
+ requisition_qty = fields.Float(
+ string="Requisition Quantity",
+ digits=dp.get_precision('Product Unit of Measure'))
+ wizard_indent_id = fields.Many2one(
+ 'wiz.requisition.request', 'Wiz Requisition Request')
+ partner_id = fields.Many2one(
+ 'res.partner', related='purchase_indent_id.partner_id',
+ string='Partner', readonly=True, store=True)
+ indent_requ_date = fields.Date(
+ related='purchase_indent_id.request_date',
+ string='Request Date', readonly=True, store=True)
+ purchase_indent_line_id = fields.Many2one(
+ 'purchase.indent.line', string="Indent Line Ref")
+ remaining_qty = fields.Float(
+ compute='_compute_get_rem_qty', string='Remaining Quantity',
+ store=True)
+
+ @api.onchange('requisition_qty')
+ def onchange_requisition_qty(self):
+ warning = {}
+ if self.requisition_qty < 0:
+ warning.update({
+ 'title': _("Warning"),
+ 'message': _("Requisition Quantity (%s) can not be \
+ Negative!") % (
+ formatLang(self.env, self.requisition_qty, digits=2))
+ })
+ self.requisition_qty = False
+ return {'warning': warning}
+
+ @api.model
+ def create(self, values):
+ if values.get('dummy_product_qty', False):
+ values.update({'product_qty': values.get('dummy_product_qty')})
+ res = super(DummyWizIndentLine, self).create(values)
+ return res
+
+ @api.model
+ def write(self, values):
+ if values.get('dummy_product_qty', False):
+ values.update({'product_qty': values.get('dummy_product_qty')})
+ res = super(DummyWizIndentLine, self).write(values)
+ return res
diff --git a/addons/purchase_indent/wizard/wiz_requisition_request_view.xml b/addons/purchase_indent/wizard/wiz_requisition_request_view.xml
new file mode 100644
index 00000000..40d9d9b9
--- /dev/null
+++ b/addons/purchase_indent/wizard/wiz_requisition_request_view.xml
@@ -0,0 +1,101 @@
+
+
+
+
+
+ wiz.requisition.request.wizard
+ wiz.requisition.request
+
+
+
+
+
+
+ Requisition Request
+ ir.actions.act_window
+ wiz.requisition.request
+ form
+ form
+ new
+
+
+