diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f14ea5b..dd341b1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,7 @@ jobs: steps: - uses: actions/checkout@v2 - run: | - for reqfile in requirements.txt test-requirements.txt ; do + for reqfile in requirements.txt ; do if [ -f ${reqfile} ] ; then result=0 # reject non-comment lines that contain a / (i.e. URLs, relative paths) diff --git a/ssi_fixed_asset_from_inventory/README.rst b/ssi_fixed_asset_from_inventory/README.rst new file mode 100644 index 0000000..1515638 --- /dev/null +++ b/ssi_fixed_asset_from_inventory/README.rst @@ -0,0 +1,56 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +========================== +Fixed Asset From Inventory +========================== + + +Installation +============ + +To install this module, you need to: + +1. Clone the branch 14.0 of the repository https://github.com/open-synergy/opnsynid-fixed-asset +2. Add the path to this repository in your configuration (addons-path) +3. Update the module list (Must be on developer mode) +4. Go to menu *Apps -> Apps -> Main Apps* +5. Search For *Fixed Asset From Inventory* +6. Install the module + +Bug Tracker +=========== + +Bugs are tracked on `GitHub 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. + + +Credits +======= +Inspired + +Contributors +------------ +* Luc De Meyer (Noviat) +* Frédéric Clementi (camptocamp) +* Florian Dacosta (Akretion) +* Stéphane Bidoul (Acsone) +* Michael Viriyananda +* Andhitia Rama +* Nur Azmi + +Inspired By: +- account_asset_managemenet + +Maintainer +---------- + +.. image:: https://simetri-sinergi.id/logo.png + :alt: PT. Simetri Sinergi Indonesia + :target: https://simetri-sinergi.id.com + +This module is maintained by the PT. Simetri Sinergi Indonesia. diff --git a/ssi_fixed_asset_from_inventory/__init__.py b/ssi_fixed_asset_from_inventory/__init__.py new file mode 100644 index 0000000..06de823 --- /dev/null +++ b/ssi_fixed_asset_from_inventory/__init__.py @@ -0,0 +1,7 @@ +# Copyright 2022 OpenSynergy Indonesia +# Copyright 2022 PT. Simetri Sinergi Indonesia +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import ( + models, +) diff --git a/ssi_fixed_asset_from_inventory/__manifest__.py b/ssi_fixed_asset_from_inventory/__manifest__.py new file mode 100644 index 0000000..e15770a --- /dev/null +++ b/ssi_fixed_asset_from_inventory/__manifest__.py @@ -0,0 +1,40 @@ +# Copyright 2022 OpenSynergy Indonesia +# Copyright 2022 PT. Simetri Sinergi Indonesia +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +{ + "name": "Fixed Asset From Inventory", + "version": "14.0.1.0.0", + "category": "Accounting & Finance", + "website": "https://simetri-sinergi.id", + "author": "PT. Simetri Sinergi Indonesia, OpenSynergy Indonesia", + "license": "AGPL-3", + "application": False, + "installable": True, + "depends": [ + "ssi_stock_fixed_asset", + "ssi_master_data_mixin", + "ssi_transaction_confirm_mixin", + "ssi_transaction_done_mixin", + "ssi_transaction_cancel_mixin", + "ssi_accounting_entry_mixin", + "ssi_company_currency_mixin", + ], + "data": [ + "security/ir_module_category_data.xml", + "security/res_group_data.xml", + "security/ir.model.access.csv", + "security/ir_rule_data.xml", + "data/approval_template_data.xml", + "data/policy_template_data.xml", + "data/ir_sequence_data.xml", + "data/sequence_template_data.xml", + "data/account_journal_data.xml", + "views/fixed_asset_from_inventory_type_views.xml", + "views/fixed_asset_from_inventory_views.xml", + ], + "demo": [], + "images": [ + "static/description/banner.png", + ], +} diff --git a/ssi_fixed_asset_from_inventory/data/account_journal_data.xml b/ssi_fixed_asset_from_inventory/data/account_journal_data.xml new file mode 100644 index 0000000..de7807b --- /dev/null +++ b/ssi_fixed_asset_from_inventory/data/account_journal_data.xml @@ -0,0 +1,13 @@ + + + + + + Fixed Asset From Inventory + FAI + general + + + diff --git a/ssi_fixed_asset_from_inventory/data/approval_template_data.xml b/ssi_fixed_asset_from_inventory/data/approval_template_data.xml new file mode 100644 index 0000000..4969526 --- /dev/null +++ b/ssi_fixed_asset_from_inventory/data/approval_template_data.xml @@ -0,0 +1,27 @@ + + + + + + Standard + + + use_python + result = True + + + + + use_group + + + + diff --git a/ssi_fixed_asset_from_inventory/data/ir_sequence_data.xml b/ssi_fixed_asset_from_inventory/data/ir_sequence_data.xml new file mode 100644 index 0000000..67b777b --- /dev/null +++ b/ssi_fixed_asset_from_inventory/data/ir_sequence_data.xml @@ -0,0 +1,18 @@ + + + + + + Fixed Asset From Inventory + fixed_asset_from_inventory + FAI/%(range_year)s/ + + + + + + + + diff --git a/ssi_fixed_asset_from_inventory/data/policy_template_data.xml b/ssi_fixed_asset_from_inventory/data/policy_template_data.xml new file mode 100644 index 0000000..6fe4d21 --- /dev/null +++ b/ssi_fixed_asset_from_inventory/data/policy_template_data.xml @@ -0,0 +1,185 @@ + + + + + + Standard + + + + result=True + + + + + + + + + + use_group + + + + + + + + + + + + + result = False +if env.user.id in document.active_approver_user_ids.ids: + result = True + + + + + + + + + + + result = False +if env.user.id in document.active_approver_user_ids.ids: + result = True + + + + + + + + + + use_group + + + result = False +if not document.approval_template_id: + result = True + + + + + + + + + + use_group + + + + + + + + + + + + use_group + + + + + + + + + + + + use_group + + + + + diff --git a/ssi_fixed_asset_from_inventory/data/sequence_template_data.xml b/ssi_fixed_asset_from_inventory/data/sequence_template_data.xml new file mode 100644 index 0000000..3626f4f --- /dev/null +++ b/ssi_fixed_asset_from_inventory/data/sequence_template_data.xml @@ -0,0 +1,28 @@ + + + + + + Standard + + + / + + + use_python + result=True + + use_sequence + + + + + diff --git a/ssi_fixed_asset_from_inventory/models/__init__.py b/ssi_fixed_asset_from_inventory/models/__init__.py new file mode 100644 index 0000000..45fa2d4 --- /dev/null +++ b/ssi_fixed_asset_from_inventory/models/__init__.py @@ -0,0 +1,8 @@ +# Copyright 2022 OpenSynergy Indonesia +# Copyright 2022 PT. Simetri Sinergi Indonesia +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import ( + fixed_asset_from_inventory_type, + fixed_asset_from_inventory, +) diff --git a/ssi_fixed_asset_from_inventory/models/fixed_asset_from_inventory.py b/ssi_fixed_asset_from_inventory/models/fixed_asset_from_inventory.py new file mode 100644 index 0000000..cae48b1 --- /dev/null +++ b/ssi_fixed_asset_from_inventory/models/fixed_asset_from_inventory.py @@ -0,0 +1,353 @@ +# Copyright 2022 OpenSynergy Indonesia +# Copyright 2022 PT. Simetri Sinergi Indonesia +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + + +from odoo import api, fields, models + +from odoo.addons.ssi_decorator import ssi_decorator + + +class FixedAssetFromInventory(models.Model): + _name = "fixed_asset_from_inventory" + _inherit = [ + "mixin.transaction_confirm", + "mixin.transaction_done", + "mixin.transaction_cancel", + "mixin.company_currency", + "mixin.account_move", + "mixin.account_move_double_line", + ] + _description = "Fixed Asset From Inventory" + + # Multiple Approval Attribute + _approval_from_state = "draft" + _approval_to_state = "done" + _approval_state = "confirm" + _after_approved_method = "action_done" + + # Attributes related to add element on view automatically + _automatically_insert_view_element = True + + # Attributes related to add element on form view automatically + _automatically_insert_multiple_approval_page = True + _automatically_insert_done_policy_fields = False + _automatically_insert_done_button = False + + _statusbar_visible_label = "draft,confirm,done" + _policy_field_order = [ + "confirm_ok", + "approve_ok", + "reject_ok", + "restart_approval_ok", + "cancel_ok", + "terminate_ok", + "restart_ok", + "done_ok", + "manual_number_ok", + ] + _header_button_order = [ + "action_confirm", + "action_approve_approval", + "action_reject_approval", + "%(ssi_transaction_cancel_mixin.base_select_cancel_reason_action)d", + "action_restart", + ] + + # Attributes related to add element on search view automatically + _state_filter_order = [ + "dom_draft", + "dom_confirm", + "dom_reject", + "dom_done", + "dom_cancel", + "dom_terminate", + ] + + # Sequence attribute + _create_sequence_state = "done" + + _journal_id_field_name = "journal_id" + _move_id_field_name = "move_id" + _accounting_date_field_name = "date" + _currency_id_field_name = "company_currency_id" + _company_currency_id_field_name = "company_currency_id" + _number_field_name = "name" + + # Debit ML Attribute + _debit_account_id_field_name = "fixed_asset_account_id" + _debit_partner_id_field_name = False + _debit_analytic_account_id_field_name = False + _debit_label_field_name = "name" + _debit_product_id_field_name = "product_id" + _debit_uom_id_field_name = "uom_id" + _debit_quantity_field_name = "quantity" + _debit_price_unit_field_name = "amount" + _debit_currency_id_field_name = "company_currency_id" + _debit_company_currency_id_field_name = "company_currency_id" + _debit_amount_currency_field_name = "amount" + _debit_company_id_field_name = "company_id" + _debit_date_field_name = "date" + _debit_need_date_due = False + _debit_date_due_field_name = False + + # Credit ML Attribute + _credit_account_id_field_name = "inventory_account_id" + _credit_partner_id_field_name = False + _credit_analytic_account_id_field_name = False + _credit_label_field_name = "name" + _credit_product_id_field_name = "product_id" + _credit_uom_id_field_name = "uom_id" + _credit_quantity_field_name = "quantity" + _credit_price_unit_field_name = "amount" + _credit_currency_id_field_name = "company_currency_id" + _credit_company_currency_id_field_name = "company_currency_id" + _credit_amount_currency_field_name = "amount" + _credit_company_id_field_name = "company_id" + _credit_date_field_name = "date" + _credit_need_date_due = False + _credit_date_due_field_name = False + + date = fields.Date( + string="Date", + required=True, + readonly=True, + states={ + "draft": [ + ("readonly", False), + ], + }, + default=lambda self: self._default_date(), + ) + type_id = fields.Many2one( + string="Type", + comodel_name="fixed_asset_from_inventory_type", + required=True, + copy=True, + readonly=True, + states={"draft": [("readonly", False)]}, + ) + product_id = fields.Many2one( + string="Product", + comodel_name="product.product", + required=True, + copy=True, + readonly=True, + states={"draft": [("readonly", False)]}, + ) + uom_id = fields.Many2one( + related="product_id.uom_id", + ) + quantity = fields.Float( + string="Quantity", + required=True, + default=1.0, + ) + allowed_lot_ids = fields.Many2many( + string="Allowed Serisl Numbers", + comodel_name="stock.production.lot", + compute="_compute_allowed_lot_ids", + store=False, + ) + lot_id = fields.Many2one( + string="# Serial Number", + comodel_name="stock.production.lot", + required=True, + copy=True, + readonly=True, + states={"draft": [("readonly", False)]}, + ) + amount = fields.Monetary( + string="Amount", + currency_field="company_currency_id", + readonly=True, + ) + journal_id = fields.Many2one( + string="Journal", + comodel_name="account.journal", + required=True, + copy=True, + readonly=True, + states={"draft": [("readonly", False)]}, + ) + inventory_account_id = fields.Many2one( + string="Inventory Account", + comodel_name="account.account", + required=True, + copy=True, + readonly=True, + states={"draft": [("readonly", False)]}, + ) + fixed_asset_account_id = fields.Many2one( + string="Fixed Asset Account", + comodel_name="account.account", + required=True, + copy=True, + readonly=True, + states={"draft": [("readonly", False)]}, + ) + debit_move_line_id = fields.Many2one( + string="Debit Journal Item", + comodel_name="account.move.line", + copy=False, + readonly=True, + ondelete="restrict", + ) + credit_move_line_id = fields.Many2one( + string="Credit Journal Item", + comodel_name="account.move.line", + copy=False, + readonly=True, + ondelete="restrict", + ) + move_id = fields.Many2one( + string="Accounting Entry", + comodel_name="account.move", + copy=False, + readonly=True, + ondelete="restrict", + ) + fixed_asset_id = fields.Many2one( + string="# Fixed Asset", + comodel_name="fixed.asset.asset", + compute="_compute_fixed_asset_id", + store=True, + ) + + @api.model + def _default_date(self): + return fields.Date.today() + + @api.depends( + "debit_move_line_id", + ) + def _compute_fixed_asset_id(self): + for record in self: + result = False + if record.debit_move_line_id and record.debit_move_line_id.fixed_asset_ids: + result = record.debit_move_line_id.fixed_asset_ids[0] + record.fixed_asset_id = result + + @api.depends( + "product_id", + "company_id", + ) + def _compute_allowed_lot_ids(self): + Quant = self.env["stock.quant"] + for record in self: + record.allowed_lot_ids = [] + if record.company_id and record.product_id: + criteria = [ + ("company_id", "=", record.company_id.id), + ("product_id", "=", record.product_id.id), + ("location_id.usage", "=", "internal"), + ("lot_id.fixed_asset_id", "=", False), + ] + record.allowed_lot_ids = Quant.search(criteria).mapped("lot_id") + + @api.onchange( + "company_id", + "product_id", + ) + def onchange_lot_id(self): + self.lot_id = False + + @api.onchange("lot_id") + def onchange_amount(self): + self.amount = 0.0 + Quant = self.env["stock.quant"] + if self.lot_id: + criteria = [ + ("company_id", "=", self.company_id.id), + ("product_id", "=", self.product_id.id), + ("lot_id", "=", self.lot_id.id), + ("location_id.usage", "=", "internal"), + ] + quants = Quant.search(criteria) + if len(quants) > 0: + self.amount = quants[0].value + + @api.onchange( + "type_id", + ) + def onchange_journal_id(self): + self.journal_id = False + if self.type_id: + self.journal_id = self.type_id.journal_id + + @api.onchange( + "product_id", + "type_id", + ) + def onchange_fixed_asset_account_id(self): + self.fixed_asset_account_id = False + if self.product_id and self.type_id: + self.fixed_asset_account_id = self.product_id._get_product_account( + usage_code=self.type_id.fixed_asset_usage_id.code + ) + + @api.onchange( + "product_id", + "type_id", + ) + def onchange_inventory_account_id(self): + self.inventory_account_id = False + if self.product_id and self.type_id: + self.inventory_account_id = self.product_id._get_product_account( + usage_code=self.type_id.inventory_usage_id.code + ) + + @api.model + def _get_policy_field(self): + res = super(FixedAssetFromInventory, self)._get_policy_field() + policy_field = [ + "confirm_ok", + "approve_ok", + "done_ok", + "cancel_ok", + "reject_ok", + "restart_ok", + "restart_approval_ok", + "manual_number_ok", + ] + res += policy_field + return res + + @ssi_decorator.post_done_action() + def _create_accounting_entry(self): + if self.move_id: + return True + + self._create_standard_move() # Mixin + debit_ml, credit_ml = self._create_standard_ml() # Mixin + self.write( + { + "debit_move_line_id": debit_ml.id, + "credit_move_line_id": credit_ml.id, + } + ) + self._post_standard_move() # Mixin + debit_ml.action_create_fixed_asset() + self.lot_id.write( + { + "fixed_asset_id": debit_ml.fixed_asset_ids[0].id, + } + ) + + @ssi_decorator.post_cancel_action() + def _delete_accounting_entry(self): + self.ensure_one() + self.fixed_asset_id.unlink() + self.write( + { + "debit_move_line_id": False, + "credit_move_line_id": False, + } + ) + self._delete_standard_move() # Mixin + + @ssi_decorator.insert_on_form_view() + def _insert_form_element(self, view_arch): + if self._automatically_insert_view_element: + view_arch = self._reconfigure_statusbar_visible(view_arch) + return view_arch diff --git a/ssi_fixed_asset_from_inventory/models/fixed_asset_from_inventory_type.py b/ssi_fixed_asset_from_inventory/models/fixed_asset_from_inventory_type.py new file mode 100644 index 0000000..0763d6f --- /dev/null +++ b/ssi_fixed_asset_from_inventory/models/fixed_asset_from_inventory_type.py @@ -0,0 +1,32 @@ +# Copyright 2022 OpenSynergy Indonesia +# Copyright 2022 PT. Simetri Sinergi Indonesia +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class FixedAssetFromInventory(models.Model): + _name = "fixed_asset_from_inventory_type" + _inherit = [ + "mixin.master_data", + ] + _description = "Fixed Asset From Inventory Type" + + fixed_asset_usage_id = fields.Many2one( + string="Fixed Asset Usage", + comodel_name="product.usage_type", + required=True, + ondelete="restrict", + ) + inventory_usage_id = fields.Many2one( + string="Inventory Usage", + comodel_name="product.usage_type", + required=True, + ondelete="restrict", + ) + journal_id = fields.Many2one( + string="journal", + comodel_name="account.journal", + required=True, + ondelete="restrict", + ) diff --git a/ssi_fixed_asset_from_inventory/security/ir.model.access.csv b/ssi_fixed_asset_from_inventory/security/ir.model.access.csv new file mode 100644 index 0000000..f6f93a6 --- /dev/null +++ b/ssi_fixed_asset_from_inventory/security/ir.model.access.csv @@ -0,0 +1,6 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_fixed_asset_from_inventory_type_all,fixed_asset_from_inventory_type - all,model_fixed_asset_from_inventory_type,,1,0,0,0 +access_fixed_asset_from_inventory_type_configurator,fixed_asset_from_inventory_type - configurator,model_fixed_asset_from_inventory_type,fixed_asset_from_inventory_type_configurator_group,1,1,1,1 +access_fixed_asset_from_inventory_all,fixed_asset_from_inventory - all user,model_fixed_asset_from_inventory,,1,0,0,0 +access_fixed_asset_from_inventory_viewer,fixed_asset_from_inventory - viewer,model_fixed_asset_from_inventory,fixed_asset_from_inventory_viewer_group,1,0,0,0 +access_fixed_asset_from_inventory_user,fixed_asset_from_inventory - user,model_fixed_asset_from_inventory,fixed_asset_from_inventory_user_group,1,1,1,1 diff --git a/ssi_fixed_asset_from_inventory/security/ir_module_category_data.xml b/ssi_fixed_asset_from_inventory/security/ir_module_category_data.xml new file mode 100644 index 0000000..6aed380 --- /dev/null +++ b/ssi_fixed_asset_from_inventory/security/ir_module_category_data.xml @@ -0,0 +1,30 @@ + + + + + + Fixed Asset From Inventory + + + + + + Fixed Asset From Inventory + + + + diff --git a/ssi_fixed_asset_from_inventory/security/ir_rule_data.xml b/ssi_fixed_asset_from_inventory/security/ir_rule_data.xml new file mode 100644 index 0000000..0c899b9 --- /dev/null +++ b/ssi_fixed_asset_from_inventory/security/ir_rule_data.xml @@ -0,0 +1,56 @@ + + + + + Fixed Asset From Inventory - Responsible to own data + + + [ + ('user_id','=',user.id), + ] + + + + + + + + Fixed Asset From Inventory - Responsible to company data + + + [('company_id','=',user.company_id.id)] + + + + + + + + Fixed Asset From Inventory - Responsible to company and all child companies data + + + [('company_id','in',user.company_ids.ids)] + + + + + + + + Fixed Asset From Inventory - Responsible to all data + + + [(1,'=',1)] + + + + + + diff --git a/ssi_fixed_asset_from_inventory/security/res_group_data.xml b/ssi_fixed_asset_from_inventory/security/res_group_data.xml new file mode 100644 index 0000000..dfb8c7f --- /dev/null +++ b/ssi_fixed_asset_from_inventory/security/res_group_data.xml @@ -0,0 +1,87 @@ + + + + + Fixed Asset From Inventory Type + + + + + + + Viewer + + + + + User + + + + + + Validator + + + + + + + + Company + + + + + Company and All Child Companies + + + + + + All + + + + diff --git a/ssi_fixed_asset_from_inventory/static/description/banner.png b/ssi_fixed_asset_from_inventory/static/description/banner.png new file mode 100644 index 0000000..925345c Binary files /dev/null and b/ssi_fixed_asset_from_inventory/static/description/banner.png differ diff --git a/ssi_fixed_asset_from_inventory/static/description/icon.png b/ssi_fixed_asset_from_inventory/static/description/icon.png new file mode 100644 index 0000000..4c8e112 Binary files /dev/null and b/ssi_fixed_asset_from_inventory/static/description/icon.png differ diff --git a/ssi_fixed_asset_from_inventory/views/fixed_asset_from_inventory_type_views.xml b/ssi_fixed_asset_from_inventory/views/fixed_asset_from_inventory_type_views.xml new file mode 100644 index 0000000..0428181 --- /dev/null +++ b/ssi_fixed_asset_from_inventory/views/fixed_asset_from_inventory_type_views.xml @@ -0,0 +1,64 @@ + + + + + fixed_asset_from_inventory_type search + fixed_asset_from_inventory_type + + primary + + + + + + + + fixed_asset_from_inventory_type tree + fixed_asset_from_inventory_type + + primary + + + + + + + + fixed_asset_from_inventory_type form + fixed_asset_from_inventory_type + + primary + + + + + + + + + + + + + + + + + Fixed Asset From Inventory Types + fixed_asset_from_inventory_type + tree,form + + + + diff --git a/ssi_fixed_asset_from_inventory/views/fixed_asset_from_inventory_views.xml b/ssi_fixed_asset_from_inventory/views/fixed_asset_from_inventory_views.xml new file mode 100644 index 0000000..0bf9eab --- /dev/null +++ b/ssi_fixed_asset_from_inventory/views/fixed_asset_from_inventory_views.xml @@ -0,0 +1,94 @@ + + + + + fixed_asset_from_inventory - search + fixed_asset_from_inventory + + primary + + + + + + + + + fixed_asset_from_inventory - tree + fixed_asset_from_inventory + primary + + + + + + + + + + + + + + + + + fixed_asset_from_inventory - form + fixed_asset_from_inventory + primary + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Fixed Asset From Inventories + ir.actions.act_window + fixed_asset_from_inventory + tree,form + + + + + diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 0000000..8a027c0 --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1,2 @@ +git+https://github.com/open-synergy/ssi-mixin@14.0#subdirectory=setup/ssi_accounting_entry_mixin +git+https://github.com/open-synergy/ssi-stock@14.0#subdirectory=setup/ssi_stock_fixed_asset