diff --git a/multi_branch_base/__init__.py b/multi_branch_base/__init__.py new file mode 100644 index 000000000..575d860d4 --- /dev/null +++ b/multi_branch_base/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from . import models +from . import wizard +from . import report diff --git a/multi_branch_base/__manifest__.py b/multi_branch_base/__manifest__.py new file mode 100644 index 000000000..ad662fbff --- /dev/null +++ b/multi_branch_base/__manifest__.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +{ + 'name': "Multi Branch Operations", + 'version': "14.0.1.0.0", + 'summary': """ Multiple Branch Unit Operation Setup for All + Modules In Odoo""", + 'description': """Multiple Branch Unit Operation Setup for All + Modules In Odoo, Branch, Branch Operations, Multiple Branch, Branch Setup""", + 'author': "Cybrosys Techno Solutions", + 'company': "Cybrosys Techno Solutions", + 'maintainer': "Cybrosys Techno Solutions", + 'website': "https://www.cybrosys.com", + 'category': 'Tools', + 'depends': ['sale_management', + 'sale_stock', 'purchase_stock', + 'stock_account'], + 'data': [ + 'security/branch_security.xml', + 'security/ir.model.access.csv', + 'views/res_branch_views.xml', + 'views/branch_product_template_views.xml', + 'views/branch_res_partner_views.xml', + 'views/branch_sale_order_views.xml', + 'views/branch_purchase_order_views.xml', + 'views/branch_res_users_views.xml', + 'views/branch_stock_picking_views.xml', + 'views/branch_account_move_views.xml', + 'views/branch_account_payment_views.xml', + 'views/branch_account_journal.xml', + 'views/branch_account_views.xml', + 'views/branch_stock_warehouse_views.xml', + 'views/branch_report_template.xml', + ], + 'images': ['static/description/banner.jpg'], + 'license': "AGPL-3", + 'installable': True, + 'application': False +} diff --git a/multi_branch_base/doc/RELEASE_NOTES.md b/multi_branch_base/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..d24266811 --- /dev/null +++ b/multi_branch_base/doc/RELEASE_NOTES.md @@ -0,0 +1,8 @@ +## Module + +#### 16.01.2022 +#### Version 14.0.1.0.0 +##### ADD +- Initial commit + + diff --git a/multi_branch_base/models/__init__.py b/multi_branch_base/models/__init__.py new file mode 100644 index 000000000..68024aea1 --- /dev/null +++ b/multi_branch_base/models/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from . import res_branch +from . import branch_res_partner +from . import branch_res_users +from . import branch_stock_picking +from . import branch_product_template +from . import branch_sale_order +from . import branch_purchase_order +from . import branch_account_move +from . import branch_account_payment +from . import branch_account_journal +from . import branch_account_account +from . import branch_stock_warehouse diff --git a/multi_branch_base/models/branch_account_account.py b/multi_branch_base/models/branch_account_account.py new file mode 100644 index 000000000..b96a47189 --- /dev/null +++ b/multi_branch_base/models/branch_account_account.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import models, fields + + +class AccountAccount(models.Model): + """inherited account account""" + _inherit = "account.account" + + def _get_branch_domain(self): + """methode to get branch domain""" + company = self.env.company + branch_ids = self.env.user.branch_ids + branch = branch_ids.filtered( + lambda branch: branch.company_id == company) + return [('id', 'in', branch.ids)] + + branch_id = fields.Many2one('res.branch', string='Branch', store=True, + domain=_get_branch_domain, + help='Leave this field empty if this account is' + ' shared between all branches') diff --git a/multi_branch_base/models/branch_account_journal.py b/multi_branch_base/models/branch_account_journal.py new file mode 100644 index 000000000..48234cf26 --- /dev/null +++ b/multi_branch_base/models/branch_account_journal.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import models, fields, api + + +class AccountJournal(models.Model): + """inherited account journal""" + _inherit = "account.journal" + + def _get_branch_domain(self): + """methode to get branch domain""" + company = self.env.company + branch_ids = self.env.user.branch_ids + branch = branch_ids.filtered( + lambda branch: branch.company_id == company) + return [('id', 'in', branch.ids)] + + branch_id = fields.Many2one('res.branch', string='Branch', + domain=_get_branch_domain, + help='Leave this field empty if this journal is' + ' shared between all branches') + + default_account_id = fields.Many2one( + comodel_name='account.account', check_company=True, copy=False, + ondelete='restrict', + string='Default Account', + domain="[('deprecated', '=', False), ('company_id', '=', company_id)," + "'|', ('user_type_id', '=', default_account_type), " + "('user_type_id', 'in', type_control_ids)," + "('user_type_id.type', 'not in', ('receivable', 'payable'))," + "'|',('branch_id', '=', branch_id), ('branch_id', '=', False)]") + + suspense_account_id = fields.Many2one( + comodel_name='account.account', check_company=True, ondelete='restrict', + readonly=False, store=True, + compute='_compute_suspense_account_id', + help="Bank statements transactions will be posted on the suspense " + "account until the final reconciliation " + "allowing finding the right account.", string='Suspense Account', + domain=lambda self: "[('deprecated', '=', False), " + "('company_id', '=', company_id), \ + ('user_type_id.type', 'not in', " + "('receivable', 'payable')), \ + ('user_type_id', '=', %s), '|'," + "('branch_id', '=', branch_id), " + "('branch_id', '=', False)]" % self.env.ref( + 'account.data_account_type_current_liabilities').id) + + profit_account_id = fields.Many2one( + comodel_name='account.account', check_company=True, + help="Used to register a profit when the ending balance of a cash " + "register differs from what the system computes", + string='Profit Account', + domain=lambda self: "[('deprecated', '=', False), " + "('company_id', '=', company_id), \ + ('user_type_id.type', 'not in', " + "('receivable', 'payable')), \ + ('user_type_id', 'in', %s)," + "'|', ('branch_id', '=', branch_id), " + "('branch_id', '=', False)]" % [ + self.env.ref( + 'account.data_account_type_revenue').id, + self.env.ref( + 'account.data_account_type_other_income').id]) + + loss_account_id = fields.Many2one( + comodel_name='account.account', check_company=True, + help="Used to register a loss when the ending balance of a cash " + "register differs from what the system computes", + string='Loss Account', + domain=lambda self: "[('deprecated', '=', False), " + "('company_id', '=', company_id), \ + ('user_type_id.type', 'not in', " + "('receivable', 'payable')), \ + ('user_type_id', '=', %s), '|', " + "('branch_id', '=', branch_id), " + "('branch_id', '=', False)]" % self.env.ref( + 'account.data_account_type_expenses').id) + + @api.onchange('branch_id') + def onchange_branch_id(self): + """onchange methode""" + self.default_account_id = False + self.suspense_account_id = False + self.profit_account_id = False + self.loss_account_id = False diff --git a/multi_branch_base/models/branch_account_move.py b/multi_branch_base/models/branch_account_move.py new file mode 100644 index 000000000..43078a5ad --- /dev/null +++ b/multi_branch_base/models/branch_account_move.py @@ -0,0 +1,198 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import models, fields, api, _ +from odoo.exceptions import UserError +from odoo.exceptions import ValidationError + + +class AccountMove(models.Model): + """inherited account move""" + _inherit = "account.move" + + @api.model + def _search_default_journal(self, journal_types): + """methode to set default journal""" + if len(self.env.user.branch_ids) == 1: + branch_id = self.env.user.branch_id.id + domain = [('branch_id', '=', self.branch_id), + ('type', 'in', journal_types)] + journal = None + if self._context.get('default_currency_id'): + currency_domain = domain + [ + ('currency_id', '=', self._context['default_currency_id'])] + journal = self.env['account.journal'].search(currency_domain, + limit=1) + if not journal: + journal = self.env['account.journal'].search(domain, limit=1) + if not journal: + domain = [('type', 'in', journal_types), + ('branch_id', '=', False)] + journal = self.env['account.journal'].search(domain, limit=1) + if not journal: + branch = self.env.user.branch_id + error_msg = _( + "No journal could be found in %(branch)s branch for " + "any of those types: %(journal_types)s", + branch=branch.name, + journal_types=', '.join(journal_types), + ) + raise UserError(error_msg) + return journal + else: + company_id = self.company_id.id if self.company_id else self._context.get('default_company_id', + self.env.company.id) + + domain = [('company_id', '=', company_id), + ('type', 'in', journal_types)] + journal = None + if self._context.get('default_currency_id'): + currency_domain = domain + [ + ('currency_id', '=', self._context['default_currency_id'])] + journal = self.env['account.journal'].search(currency_domain, + limit=1) + if not journal: + journal = self.env['account.journal'].search(domain, limit=1) + if not journal: + company = self.env['res.company'].browse(company_id) + error_msg = _( + "No journal could be found in company %(company_name)s for " + "any of those types: %(journal_types)s", + company_name=company.display_name, + journal_types=', '.join(journal_types), + ) + raise UserError(error_msg) + + return journal + + def _get_default_branch(self): + branch = False + if len(self.env.user.branch_ids) == 1: + branch = self.env.user.branch_id + return branch + + def _get_branch_domain(self): + """methode to get branch domain""" + company = self.env.company + branch_ids = self.env.user.branch_ids + branch = branch_ids.filtered( + lambda branch: branch.company_id == company) + return [('id', 'in', branch.ids)] + + branch_id = fields.Many2one('res.branch', string='Branch', store=True, + readonly=False, + default=_get_default_branch, + domain=_get_branch_domain) + + @api.onchange('branch_id') + def onchange_branch_id(self): + """onchange methode""" + move_type = self._context.get('default_move_type', 'entry') + if move_type in self.get_sale_types(include_receipts=True): + journal_types = ['sale'] + elif move_type in self.get_purchase_types(include_receipts=True): + journal_types = ['purchase'] + else: + journal_types = self._context.get('default_move_journal_types', ['general']) + branch_id = self.branch_id.id + domain = [('branch_id', '=', branch_id), + ('type', 'in', journal_types)] + journal = None + if self._context.get('default_currency_id'): + currency_domain = domain + [ + ('currency_id', '=', self._context['default_currency_id'])] + journal = self.env['account.journal'].search(currency_domain, + limit=1) + if not journal: + journal = self.env['account.journal'].search(domain, limit=1) + if not journal: + domain = [('type', 'in', journal_types), + ('branch_id', '=', False)] + journal = self.env['account.journal'].search(domain, limit=1) + if not journal and journal_types: + branch = self.branch_id + error_msg = _( + "No journal could be found in %(branch)s branch for " + "any of those types: %(journal_types)s", + branch=branch.name, + journal_types=', '.join(journal_types), + ) + raise UserError(error_msg) + self.journal_id = journal + + @api.depends('company_id', 'invoice_filter_type_domain') + def _compute_suitable_journal_ids(self): + """methode to compute suitable journal ids""" + if self.branch_id: + for m in self: + journal_type = m.invoice_filter_type_domain or 'general' + branch_id = m.branch_id.id #or self.env.user.branch_id.id + domain = [('type', '=', journal_type), + '|', ('branch_id', '=', branch_id), + ('branch_id', '=', False)] + m.suitable_journal_ids = self.env['account.journal'].search( + domain) + + else: + for m in self: + journal_type = m.invoice_filter_type_domain or 'general' + company_id = m.company_id.id if m.company_id else self.env.company.id + domain = [('company_id', '=', company_id), + ('branch_id', '=', False), + ('type', '=', journal_type)] + m.suitable_journal_ids = self.env['account.journal'].search( + domain) + + @api.constrains('branch_id', 'line_ids') + def _check_move_line_branch_id(self): + """methode to check branch of accounts and entry""" + for move in self: + branches = move.line_ids.account_id.branch_id + if branches and branches != move.branch_id: + bad_accounts = move.line_ids.account_id.filtered( + lambda a: a.branch_id and a.branch_id != move.branch_id) + raise ValidationError(_( + "Your items contains accounts from %(line_branch)s branch" + " whereas your entry belongs to %(move_branch)s branch. " + "\n Please change the branch of your entry or remove the " + "accounts from other branches (%(bad_accounts)s).", + line_branch=', '.join(branches.mapped('name')), + move_branch=move.branch_id.name, + bad_accounts=', '.join(bad_accounts.mapped('name')), + )) + + +class AccountMoveLine(models.Model): + """inherited account move line""" + _inherit = "account.move.line" + + branch_id = fields.Many2one('res.branch', related='move_id.branch_id', + string='Branch', store=True) + + account_id = fields.Many2one( + 'account.account', string='Account', + index=True, ondelete="cascade", + domain="[('deprecated', '=', False), ('company_id', '=', 'company_id')," + "('is_off_balance', '=', False), '|', " + "('branch_id', '=', branch_id), ('branch_id', '=', False)]", + check_company=True, + tracking=True) diff --git a/multi_branch_base/models/branch_account_payment.py b/multi_branch_base/models/branch_account_payment.py new file mode 100644 index 000000000..327345698 --- /dev/null +++ b/multi_branch_base/models/branch_account_payment.py @@ -0,0 +1,108 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import models, fields, api, _ +from odoo.exceptions import ValidationError + + +class AccountMove(models.Model): + """inherited account payment""" + _inherit = "account.payment" + + destination_account_id = fields.Many2one( + comodel_name='account.account', + string='Destination Account', + store=True, readonly=False, + compute='_compute_destination_account_id', + domain="[('user_type_id.type', 'in', ('receivable', 'payable')), " + "('company_id', '=', company_id)," + "'|', ('branch_id', '=', branch_id), ('branch_id', '=', False)]", + check_company=True) + + @api.constrains('branch_id') + def _check_payment_branch_id(self): + """methode to check branch of accounts and entry""" + for payment in self: + branch = payment.destination_account_id.branch_id + if branch and branch != payment.branch_id: + raise ValidationError(_( + "Your payment belongs to '%s' branch whereas the account" + " belongs to '%s' branch.", payment.branch_id.name, + branch.name)) + + @api.depends('journal_id', 'branch_id', 'partner_id', 'partner_type', + 'is_internal_transfer') + def _compute_destination_account_id(self): + """methode to compute destination account""" + if self.branch_id: + self.destination_account_id = False + for pay in self: + if pay.is_internal_transfer: + pay.destination_account_id = \ + pay.journal_id.company_id.transfer_account_id + elif pay.partner_type == 'customer': + # Receive money from invoice or send money to refund it. + if pay.partner_id: + pay.destination_account_id = \ + pay.partner_id.with_company( + pay.company_id).property_account_receivable_id + else: + destination_account = self.env[ + 'account.account'].search([ + ('company_id', '=', pay.company_id.id), + ('branch_id', '=', pay.branch_id.id), + ('internal_type', '=', 'receivable'), + ], limit=1) + pay.destination_account_id = destination_account + if not destination_account: + destination_account = self.env[ + 'account.account'].search([ + ('company_id', '=', pay.company_id.id), + ('branch_id', '=', False), + ('internal_type', '=', 'receivable'), + ], limit=1) + pay.destination_account_id = destination_account + elif pay.partner_type == 'supplier': + # Send money to pay a bill or receive money to refund it. + if pay.partner_id: + pay.destination_account_id = \ + pay.partner_id.with_company( + pay.company_id).property_account_payable_id + else: + destination_account = self.env[ + 'account.account'].search([ + ('company_id', '=', pay.company_id.id), + ('branch_id', '=', pay.branch_id.id), + ('internal_type', '=', 'payable'), + ], limit=1) + pay.destination_account_id = destination_account + if not destination_account: + destination_account = self.env[ + 'account.account'].search([ + ('company_id', '=', pay.company_id.id), + ('branch_id', '=', False), + ('internal_type', '=', 'payable'), + ], limit=1) + pay.destination_account_id = destination_account + else: + res = super(AccountMove, self)._compute_destination_account_id() + return res diff --git a/multi_branch_base/models/branch_product_template.py b/multi_branch_base/models/branch_product_template.py new file mode 100644 index 000000000..e4fa7e603 --- /dev/null +++ b/multi_branch_base/models/branch_product_template.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import models, fields, api + + +class ProductTemplate(models.Model): + """inherited product""" + _inherit = 'product.template' + + + + branch_id = fields.Many2one("res.branch", string='Branch', store=True, + readonly=False, + compute="_compute_branch") + + @api.depends('company_id') + def _compute_branch(self): + for order in self: + company = self.env.company + so_company = order.company_id if order.company_id else self.env.company + branch_ids = self.env.user.branch_ids + branch = branch_ids.filtered( + lambda branch: branch.company_id == so_company) + if branch: + order.branch_id = branch.ids[0] + else: + order.branch_id = False diff --git a/multi_branch_base/models/branch_purchase_order.py b/multi_branch_base/models/branch_purchase_order.py new file mode 100644 index 000000000..9ac4204a4 --- /dev/null +++ b/multi_branch_base/models/branch_purchase_order.py @@ -0,0 +1,189 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import models, fields, api, _ +from odoo.exceptions import UserError +from odoo.addons.purchase.models.purchase import PurchaseOrder as Purchase +from odoo.exceptions import ValidationError + + +class PurchaseOrder(models.Model): + """inherited purchase order""" + _inherit = 'purchase.order' + + branch_id = fields.Many2one("res.branch", string='Branch', store=True, + readonly=False, + compute="_compute_branch") + + @api.depends('company_id') + def _compute_branch(self): + for order in self: + company = self.env.company + so_company = order.company_id if order.company_id else self.env.company + branch_ids = self.env.user.branch_ids + branch = branch_ids.filtered( + lambda branch: branch.company_id == so_company) + if branch: + order.branch_id = branch.ids[0] + else: + order.branch_id = False + + @api.model + def _get_picking_type(self, company_id): + """methode to set default picking type""" + if len(self.env.user.branch_ids) == 1: + picking_type = self.env['stock.picking.type'].search( + [('code', '=', 'incoming'), + ('warehouse_id.branch_id', '=', company_id)]) + if not picking_type: + picking_type = self.env['stock.picking.type'].search( + [('code', '=', 'incoming'), + ('warehouse_id.branch_id', '=', False)]) + if not picking_type: + error_msg = _( + "No warehouse could be found in the '%s' branch", + self.env.user.branch_id.name + ) + raise UserError(error_msg) + return picking_type[:1] + else: + res = super(PurchaseOrder, self)._get_picking_type(company_id) + return res + + @api.model + def _default_picking_type(self): + """methode to get default picking type""" + if len(self.env.user.branch_ids) == 1: + branch = self.env.user.branch_id + if branch: + return self._get_picking_type(branch.id) + else: + return self._get_picking_type(self.env.context.get('company_id') + or self.env.company.id) + + picking_type_id = fields.Many2one( + 'stock.picking.type', 'Deliver To', + states=Purchase.READONLY_STATES, + required=True, + default=_default_picking_type, + domain="[('code','=','incoming'), " + "('warehouse_id.company_id', '=', company_id)," + "'|', ('warehouse_id.branch_id', '=', branch_id)," + "('warehouse_id.branch_id', '=', False),]", + help="This will determine operation type" + " of incoming shipment") + + @api.constrains('branch_id', 'partner_id') + def _check_partner_branch_id(self): + """methode to check branch of partner and purchase order""" + for order in self: + branch = order.partner_id.branch_id + if branch and branch != order.branch_id: + raise ValidationError(_( + "Your quotation vendor is from %(partner_branch)s " + "branch whereas your quotation belongs to %(quote_branch)s" + " branch \n Please change the " + "branch of your quotation or remove the vendor from " + "other branch.", + partner_branch=branch.name, + quote_branch=order.branch_id.name, + )) + + @api.constrains('branch_id', 'order_line') + def _check_order_line_branch_id(self): + """methode to check branch of products and purchase order""" + for order in self: + branches = order.order_line.product_id.branch_id + if branches and branches != order.branch_id: + bad_products = order.order_line.product_id.filtered( + lambda p: p.branch_id and p.branch_id != order.branch_id) + raise ValidationError(_( + "Your quotation contains products from %(product_branch)s " + "branch whereas your quotation belongs to %(quote_branch)s" + " branch \n Please change the " + "branch of your quotation or remove the products from " + "other branches (%(bad_products)s).", + product_branch=', '.join(branches.mapped('name')), + quote_branch=order.branch_id.name, + bad_products=', '.join(bad_products.mapped('display_name')), + )) + + def _prepare_invoice(self): + """override prepare_invoice function to include branch""" + invoice_vals = super(PurchaseOrder, self)._prepare_invoice() + branch_id = self.branch_id.id + domain = [('branch_id', '=', branch_id), + ('type', '=', 'purchase'), ('company_id', '=', self.company_id.id)] + journal = None + + if self._context.get('default_currency_id'): + currency_domain = domain + [ + ('currency_id', '=', self._context['default_currency_id'])] + journal = self.env['account.journal'].search(currency_domain, + limit=1) + + if not journal: + journal = self.env['account.journal'].search(domain, limit=1) + if not journal: + domain = [('type', '=', 'purchase'), + ('branch_id', '=', False), ('company_id', '=', self.company_id.id)] + journal = self.env['account.journal'].search(domain, limit=1) + if not journal: + error_msg = _( + "No journal could be found in the'%s' branch" + " for any of those types: purchase", self.branch_id.name,) + raise UserError(error_msg) + invoice_vals['branch_id'] = self.branch_id.id or False + invoice_vals['journal_id'] = journal.id + return invoice_vals + + @api.onchange('branch_id') + def onchange_branch_id(self): + """onchange function""" + if self.branch_id and self.branch_id not in self.env.user.branch_ids and self.env.user.branch_ids: + raise UserError("Unauthorised Branch") + self.picking_type_id = False + if self.branch_id: + picking_type = self.env['stock.picking.type'].sudo().search( + [('branch_id', '=', self.branch_id.id), ('company_id', '=', self.company_id.id)], limit=1) + self.picking_type_id = picking_type + if not picking_type: + picking_type = self.env['stock.picking.type'].sudo().search( + [('branch_id', '=', False), ('company_id', '=', self.company_id.id)], limit=1) + self.picking_type_id = picking_type + if not picking_type: + error_msg = _( + "No warehouse could be found in the '%s' branch", + self.branch_id.name + ) + raise UserError(error_msg) + else: + self.picking_type_id = self.env['stock.picking.type'].sudo().search( + [('branch_id', '=', False), ('company_id', '=', self.company_id.id)], limit=1) + + +class PurchaseOrderLine(models.Model): + """inherited purchase order line""" + _inherit = 'purchase.order.line' + + branch_id = fields.Many2one(related='order_id.branch_id', string='Branch', + store=True) diff --git a/multi_branch_base/models/branch_res_partner.py b/multi_branch_base/models/branch_res_partner.py new file mode 100644 index 000000000..7ca4f3ba0 --- /dev/null +++ b/multi_branch_base/models/branch_res_partner.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import models, fields, api + + +class BranchPartner(models.Model): + """inherited partner""" + _inherit = "res.partner" + + branch_id = fields.Many2one("res.branch", string='Branch', store=True, + readonly=False, + compute="_compute_branch") + + @api.depends('company_id') + def _compute_branch(self): + for order in self: + company = self.env.company + so_company = order.company_id if order.company_id else self.env.company + branch_ids = self.env.user.branch_ids + branch = branch_ids.filtered( + lambda branch: branch.company_id == so_company) + if branch: + order.branch_id = branch.ids[0] + else: + order.branch_id = False + + @api.model + def default_get(self, default_fields): + """Add the company of the parent as default if we are creating a + child partner.Also take the parent lang by default if any, otherwise, + fallback to default DB lang.""" + values = super().default_get(default_fields) + parent = self.env["res.partner"] + if 'parent_id' in default_fields and values.get('parent_id'): + parent = self.browse(values.get('parent_id')) + values['branch_id'] = parent.branch_id.id + return values + + @api.onchange('parent_id', 'branch_id') + def _onchange_parent_id(self): + """methode to set branch on changing the parent company""" + if self.parent_id: + self.branch_id = self.parent_id.branch_id.id + + def write(self, vals): + """override write methode""" + if vals.get('branch_id'): + branch_id = vals['branch_id'] + for partner in self: + # if partner.child_ids: + for child in partner.child_ids: + child.write({'branch_id': branch_id}) + else: + for partner in self: + # if partner.child_ids: + for child in partner.child_ids: + child.write({'branch_id': False}) + result = super(BranchPartner, self).write(vals) + return result diff --git a/multi_branch_base/models/branch_res_users.py b/multi_branch_base/models/branch_res_users.py new file mode 100644 index 000000000..346958e19 --- /dev/null +++ b/multi_branch_base/models/branch_res_users.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import models, fields, api, _ +from odoo import exceptions +from odoo.exceptions import UserError + + +class ResUsers(models.Model): + """inherited res users""" + _inherit = "res.users" + + branch_ids = fields.Many2many('res.branch', string='Allowed Branches', + domain="[('company_id', '=', company_ids)]") + branch_id = fields.Many2one("res.branch", string='Default Branch', + default=False, + domain="[('id', '=', branch_ids)]") + + @api.constrains('branch_id') + def branch_constrains(self): + """branch constrains""" + company = self.env.company + for user in self: + if user.branch_id and user.branch_id.company_id != company: + raise exceptions.UserError(_("Sorry! The selected Branch does " + "not belong to the current Company" + " '%s'", company.name)) + + def _get_default_warehouse_id(self): + """methode to get default warehouse id""" + if self.property_warehouse_id: + return self.property_warehouse_id + # !!! Any change to the following search domain should probably + # be also applied in sale_stock/models/sale_order.py/_init_column. + if len(self.env.user.branch_ids) == 1: + warehouse = self.env['stock.warehouse'].search([ + ('branch_id', '=', self.env.user.branch_id.id)], limit=1) + if not warehouse: + warehouse = self.env['stock.warehouse'].search([ + ('branch_id', '=', False)], limit=1) + if not warehouse: + error_msg = _( + "No warehouse could be found in the '%s' branch", + self.env.user.branch_id.name + ) + raise UserError(error_msg) + return warehouse + else: + return self.env['stock.warehouse'].search([ + ('company_id', '=', self.env.company.id)], limit=1) diff --git a/multi_branch_base/models/branch_sale_order.py b/multi_branch_base/models/branch_sale_order.py new file mode 100644 index 000000000..2e4bd8188 --- /dev/null +++ b/multi_branch_base/models/branch_sale_order.py @@ -0,0 +1,167 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import models, fields, api, _ +from odoo.exceptions import UserError +from odoo.exceptions import ValidationError + + +class SaleOrder(models.Model): + """inherited sale order""" + _inherit = 'sale.order' + + @api.model + def _default_warehouse_id(self): + """methode to get default warehouse id""" + # !!! Any change to the default value may have to be repercuted + # on _init_column() below. + return self.env.user._get_default_warehouse_id() + + branch_id = fields.Many2one("res.branch", string='Branch', store=True, + readonly=False, + compute="_compute_branch") + warehouse_id = fields.Many2one( + 'stock.warehouse', string='Warehouse', + required=True, readonly=True, states={'draft': [('readonly', False)], + 'sent': [('readonly', False)]}, + default=_default_warehouse_id, check_company=True, + ) + + @api.depends('company_id') + def _compute_branch(self): + for order in self: + company = self.env.company + so_company = order.company_id if order.company_id else self.env.company + branch_ids = self.env.user.branch_ids + branch = branch_ids.filtered( + lambda branch: branch.company_id == so_company) + if branch: + order.branch_id = branch.ids[0] + else: + order.branch_id = False + + + @api.constrains('branch_id', 'partner_id') + def _check_partner_branch_id(self): + """methode to check branch of partner and sale order""" + for order in self: + branch = order.partner_id.branch_id + if branch and branch != order.branch_id: + raise ValidationError(_( + "Your quotation customer have company branch " + "%(partner_branch)s whereas your quotation belongs to " + "company branch %(quote_branch)s. \n Please change the " + "company of your quotation or change the customer from " + "other branch", + partner_branch=branch.name, + quote_branch=order.branch_id.name, + )) + + @api.constrains('branch_id', 'order_line') + def _check_order_line_branch_id(self): + """methode to check branch of products and sale order""" + for order in self: + branches = order.order_line.product_id.branch_id + if branches and branches != order.branch_id: + bad_products = order.order_line.product_id.filtered( + lambda p: p.branch_id and p.branch_id != order.branch_id) + raise ValidationError(_( + "Your quotation contains products from company branch " + "%(product_branch)s whereas your quotation belongs to " + "company branch %(quote_branch)s. \n Please change the " + "company of your quotation or remove the products from " + "other companies (%(bad_products)s).", + product_branch=', '.join(branches.mapped('name')), + quote_branch=order.branch_id.name, + bad_products=', '.join(bad_products.mapped('display_name')), + )) + + + + def _prepare_invoice(self): + """override prepare_invoice function to include branch""" + invoice_vals = super(SaleOrder, self)._prepare_invoice() + branch_id = self.branch_id.id + domain = [('branch_id', '=', branch_id), + ('type', '=', 'sale'), + ('code', '!=', 'POSS'),('company_id', '=', self.company_id.id)] + + journal = None + if self._context.get('default_currency_id'): + currency_domain = domain + [ + ('currency_id', '=', self._context['default_currency_id'])] + journal = self.env['account.journal'].search(currency_domain, + limit=1) + + if not journal: + journal = self.env['account.journal'].search(domain, limit=1) + if not journal: + domain = [('type', '=', 'sale'), ('code', '!=', 'POSS'), + ('branch_id', '=', False), ('company_id', '=', self.company_id.id)] + journal = self.env['account.journal'].search(domain, limit=1) + if not journal: + error_msg = _( + "No journal could be found in the '%s' branch" + " for any of those types: sale", + self.branch_id.name, + ) + raise UserError(error_msg) + + invoice_vals['branch_id'] = self.branch_id.id or False + invoice_vals['journal_id'] = journal.id + return invoice_vals + + @api.onchange('branch_id') + def onchange_branch_id(self): + """onchange methode""" + + if self.branch_id and self.branch_id not in self.env.user.branch_ids and self.env.user.branch_ids: + raise UserError("Unauthorised Branch") + self.warehouse_id = False + if self.branch_id: + warehouse = self.env['stock.warehouse'].sudo().search( + [('branch_id', '=', self.branch_id.id), ('company_id', '=', self.company_id.id)], limit=1) + self.warehouse_id = warehouse + if not warehouse: + + warehouse = self.env['stock.warehouse'].sudo().search([ + ('branch_id', '=', False), ('company_id', '=', self.company_id.id)], limit=1) + self.warehouse_id = warehouse + if not warehouse: + error_msg = _( + "No warehouse could be found in the '%s' branch", + self.branch_id.name + ) + raise UserError(error_msg) + else: + + self.warehouse_id = self.env['stock.warehouse'].sudo().search([ + ('branch_id', '=', False), ('company_id', '=', self.company_id.id)], + limit=1) + + +class SaleOrderLine(models.Model): + """inherited purchase order line""" + _inherit = 'sale.order.line' + + branch_id = fields.Many2one(related='order_id.branch_id', + string='Branch', store=True) diff --git a/multi_branch_base/models/branch_stock_picking.py b/multi_branch_base/models/branch_stock_picking.py new file mode 100644 index 000000000..51cfefa81 --- /dev/null +++ b/multi_branch_base/models/branch_stock_picking.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import models, fields, api + + +class StockPicking(models.Model): + """inherited stock.picking""" + _inherit = "stock.picking" + + branch_id = fields.Many2one("res.branch", string='Branch', store=True, + readonly=False, + compute="_compute_branch") + + @api.depends('company_id', 'sale_id', 'purchase_id') + def _compute_branch(self): + for order in self: + company = self.env.company + so_company = order.company_id if order.company_id else self.env.company + branch_ids = self.env.user.branch_ids + branch = branch_ids.filtered( + lambda branch: branch.company_id == so_company) + if branch: + order.branch_id = branch.ids[0] + else: + order.branch_id = False + if order.sale_id or order.purchase_id: + if order.sale_id.branch_id: + order.branch_id = order.sale_id.branch_id + if order.purchase_id.branch_id: + order.branch_id = order.purchase_id.branch_id + + + + # @api.onchange('branch_id') + # def onchange_branch_id(self): + # """onchange methode""" + # self.picking_type_id = False + # self.location_id = False + # self.location_dest_id = False + + @api.depends('sale_id', 'purchase_id') + def _compute_branch_id(self): + """methode to compute branch""" + for record in self: + record.branch_id = False + if record.sale_id.branch_id: + record.branch_id = record.sale_id.branch_id + if record.purchase_id.branch_id: + record.branch_id = record.purchase_id.branch_id + + +class StockPickingTypes(models.Model): + """inherited stock picking type""" + _inherit = "stock.picking.type" + + branch_id = fields.Many2one('res.branch', string='Branch', store=True, + related='warehouse_id.branch_id') diff --git a/multi_branch_base/models/branch_stock_warehouse.py b/multi_branch_base/models/branch_stock_warehouse.py new file mode 100644 index 000000000..2f005e023 --- /dev/null +++ b/multi_branch_base/models/branch_stock_warehouse.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import models, fields, api + + +class StockWarehouse(models.Model): + """inherited stock warehouse""" + _inherit = "stock.warehouse" + + @api.model + def _get_default_branch(self): + """methode to get default branch""" + branch_id = self.env.user.branch_id + return branch_id + + def _get_branch_domain(self): + """methode to get branch domain""" + company = self.env.company + branch_ids = self.env.user.branch_ids + branch = branch_ids.filtered( + lambda branch: branch.company_id == company) + return [('id', 'in', branch.ids)] + + branch_id = fields.Many2one('res.branch', string='Branch', store=True, + default=_get_default_branch, + domain=_get_branch_domain, + help='Leave this field empty if this warehouse ' + ' is shared between all branches') + + +class BranchStockMove(models.Model): + """inherited stock.move""" + _inherit = 'stock.move' + + branch_id = fields.Many2one('res.branch', readonly=True, store=True, + related='picking_id.branch_id') + + +class BranchStockMoveLine(models.Model): + """inherited stock move line""" + _inherit = 'stock.move.line' + + branch_id = fields.Many2one('res.branch', readonly=True, store=True, + related='move_id.branch_id') + + +class BranchStockValuationLayer(models.Model): + """Inherited Stock Valuation Layer""" + _inherit = 'stock.valuation.layer' + + branch_id = fields.Many2one('res.branch', readonly=True, store=True, + related='stock_move_id.branch_id') diff --git a/multi_branch_base/models/res_branch.py b/multi_branch_base/models/res_branch.py new file mode 100644 index 000000000..28bcf6579 --- /dev/null +++ b/multi_branch_base/models/res_branch.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +import logging +from odoo import models, fields + + +_logger = logging.getLogger(__name__) + + +class Branch(models.Model): + """res branch""" + _name = "res.branch" + _description = 'Company Branches' + _order = 'name' + + name = fields.Char(string='Branch', required=True, store=True) + company_id = fields.Many2one('res.company', required=True, string='Company') + street = fields.Char() + street2 = fields.Char() + zip = fields.Char() + city = fields.Char() + state_id = fields.Many2one( + 'res.country.state', + string="Fed. State", domain="[('country_id', '=?', country_id)]" + ) + country_id = fields.Many2one('res.country', string="Country") + email = fields.Char(store=True, ) + phone = fields.Char(store=True) + website = fields.Char(readonly=False) + + _sql_constraints = [ + ('name_uniq', 'unique (name)', 'The Branch name must be unique !') + ] diff --git a/multi_branch_base/report/__init__.py b/multi_branch_base/report/__init__.py new file mode 100644 index 000000000..f6f2b7035 --- /dev/null +++ b/multi_branch_base/report/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from . import branch_sale_order_report +from . import branch_purchase_order_report +from . import branch_account_invoice_report diff --git a/multi_branch_base/report/branch_account_invoice_report.py b/multi_branch_base/report/branch_account_invoice_report.py new file mode 100644 index 000000000..05f1a3778 --- /dev/null +++ b/multi_branch_base/report/branch_account_invoice_report.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import fields, models + + +class AccountInvoiceReport(models.Model): + """inherited invoice report""" + _inherit = "account.invoice.report" + + branch_id = fields.Many2one('res.branch', 'Branch', readonly=True) + + def _select(self): + """select""" + return super(AccountInvoiceReport, self)._select() +\ + ", move.branch_id as branch_id" + + def _group_by(self): + """group by""" + return super(AccountInvoiceReport, self)._group_by() + \ + ", move.branch_id" diff --git a/multi_branch_base/report/branch_purchase_order_report.py b/multi_branch_base/report/branch_purchase_order_report.py new file mode 100644 index 000000000..1b6878cfb --- /dev/null +++ b/multi_branch_base/report/branch_purchase_order_report.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import fields, models + + +class PurchaseReport(models.Model): + """inherited purchase report""" + _inherit = "purchase.report" + + branch_id = fields.Many2one('res.branch', 'Branch', readonly=True) + + def _select(self): + """select""" + return super(PurchaseReport, self)._select() + \ + ", po.branch_id as branch_id" + + def _group_by(self): + """group by""" + return super(PurchaseReport, self)._group_by() + \ + ", po.branch_id" diff --git a/multi_branch_base/report/branch_sale_order_report.py b/multi_branch_base/report/branch_sale_order_report.py new file mode 100644 index 000000000..98cd34a0a --- /dev/null +++ b/multi_branch_base/report/branch_sale_order_report.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import fields, models + + +class SaleReport(models.Model): + _inherit = "sale.report" + + branch_id = fields.Many2one('res.branch', 'Branch', readonly=True) + + def _query(self, with_clause='', fields={}, groupby='', from_clause=''): + """query""" + fields['branch_id'] = ", s.branch_id as branch_id" + groupby += ', s.branch_id' + return super(SaleReport, self)._query(with_clause, fields, groupby, + from_clause) diff --git a/multi_branch_base/security/branch_security.xml b/multi_branch_base/security/branch_security.xml new file mode 100644 index 000000000..ed1f7ddc5 --- /dev/null +++ b/multi_branch_base/security/branch_security.xml @@ -0,0 +1,152 @@ + + + + + + + + branch rule portal + + + + [('id','in', user.branch_ids.ids)] + + + branch rule employee + + + + [('id','in', user.branch_ids.ids)] + + + branch rule public + + + + [('id','in', user.branch_ids.ids)] + + + branch rule erp manager + + + + [(1,'=',1)] + + + + + + Product multi-branch + + ['|',('branch_id','=',False),('branch_id', 'in', user.branch_ids.ids)] + + + + Sales Order multi-branch + + ['|',('branch_id','=',False),('branch_id', 'in', user.branch_ids.ids)] + + + + Sales Order Line multi-branch + + ['|',('branch_id','=',False),('branch_id', 'in', user.branch_ids.ids)] + + + + Purchase Order multi-branch + + ['|',('branch_id','=',False),('branch_id', 'in', user.branch_ids.ids)] + + + + Purchase Order Line multi-branch + + ['|',('branch_id','=',False),('branch_id', 'in', user.branch_ids.ids)] + + + + Account multi-branch + + ['|',('branch_id','=',False),('branch_id', 'in', user.branch_ids.ids)] + + + + Journal multi-branch + + ['|',('branch_id','=',False),('branch_id', 'in', user.branch_ids.ids)] + + + + Branch Account Entry + + ['|',('branch_id','=',False),('branch_id', 'in', user.branch_ids.ids)] + + + + Entry lines + + ['|',('branch_id','=',False),('branch_id', 'in', user.branch_ids.ids)] + + + + Account payment branch rule + + ['|',('branch_id','=',False),('branch_id', 'in', user.branch_ids.ids)] + + + + stock_picking multi-branch + + ['|',('branch_id','=',False),('branch_id', 'in', user.branch_ids.ids)] + + + + Stock Operation Type multi-branch + + ['|',('branch_id','=',False),('branch_id', 'in', user.branch_ids.ids)] + + + + Warehouse multi-branch + + ['|',('branch_id','=',False),('branch_id', 'in', user.branch_ids.ids)] + + + + stock_move multi-branch + + ['|',('branch_id','=',False),('branch_id', 'in', user.branch_ids.ids)] + + + + stock_move_line multi-branch + + ['|',('branch_id','=',False),('branch_id', 'in', user.branch_ids.ids)] + + + + Stock Valuation Layer Multibranch + + ['|',('branch_id','=',False),('branch_id', 'in', user.branch_ids.ids)] + + + + Invoice Analysis multi-branch + + ['|',('branch_id','=',False),('branch_id', 'in', user.branch_ids.ids)] + + + + Sales Order Analysis multi-branch + + ['|',('branch_id','=',False),('branch_id', 'in', user.branch_ids.ids)] + + + + Purchase Order Report multi-branch + + ['|',('branch_id','=',False),('branch_id', 'in', user.branch_ids.ids)] + + + \ No newline at end of file diff --git a/multi_branch_base/security/ir.model.access.csv b/multi_branch_base/security/ir.model.access.csv new file mode 100644 index 000000000..b8fc286b6 --- /dev/null +++ b/multi_branch_base/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_res_branch_group_erp_manager,res_branch_group_erp_manager,model_res_branch,base.group_erp_manager,1,1,1,1 +access_res_branch_group_user,res_branch_group_user,model_res_branch,,1,0,0,0 diff --git a/multi_branch_base/static/description/assets/icons/check.png b/multi_branch_base/static/description/assets/icons/check.png new file mode 100644 index 000000000..c8e85f51d Binary files /dev/null and b/multi_branch_base/static/description/assets/icons/check.png differ diff --git a/multi_branch_base/static/description/assets/icons/chevron.png b/multi_branch_base/static/description/assets/icons/chevron.png new file mode 100644 index 000000000..2089293d6 Binary files /dev/null and b/multi_branch_base/static/description/assets/icons/chevron.png differ diff --git a/multi_branch_base/static/description/assets/icons/cogs.png b/multi_branch_base/static/description/assets/icons/cogs.png new file mode 100644 index 000000000..95d0bad62 Binary files /dev/null and b/multi_branch_base/static/description/assets/icons/cogs.png differ diff --git a/multi_branch_base/static/description/assets/icons/consultation.png b/multi_branch_base/static/description/assets/icons/consultation.png new file mode 100644 index 000000000..8319d4baa Binary files /dev/null and b/multi_branch_base/static/description/assets/icons/consultation.png differ diff --git a/multi_branch_base/static/description/assets/icons/ecom-black.png b/multi_branch_base/static/description/assets/icons/ecom-black.png new file mode 100644 index 000000000..a9385ff13 Binary files /dev/null and b/multi_branch_base/static/description/assets/icons/ecom-black.png differ diff --git a/multi_branch_base/static/description/assets/icons/education-black.png b/multi_branch_base/static/description/assets/icons/education-black.png new file mode 100644 index 000000000..3eb09b27b Binary files /dev/null and b/multi_branch_base/static/description/assets/icons/education-black.png differ diff --git a/multi_branch_base/static/description/assets/icons/hotel-black.png b/multi_branch_base/static/description/assets/icons/hotel-black.png new file mode 100644 index 000000000..130f613be Binary files /dev/null and b/multi_branch_base/static/description/assets/icons/hotel-black.png differ diff --git a/multi_branch_base/static/description/assets/icons/license.png b/multi_branch_base/static/description/assets/icons/license.png new file mode 100644 index 000000000..a5869797e Binary files /dev/null and b/multi_branch_base/static/description/assets/icons/license.png differ diff --git a/multi_branch_base/static/description/assets/icons/lifebuoy.png b/multi_branch_base/static/description/assets/icons/lifebuoy.png new file mode 100644 index 000000000..658d56ccc Binary files /dev/null and b/multi_branch_base/static/description/assets/icons/lifebuoy.png differ diff --git a/multi_branch_base/static/description/assets/icons/logo.png b/multi_branch_base/static/description/assets/icons/logo.png new file mode 100644 index 000000000..478462d3e Binary files /dev/null and b/multi_branch_base/static/description/assets/icons/logo.png differ diff --git a/multi_branch_base/static/description/assets/icons/manufacturing-black.png b/multi_branch_base/static/description/assets/icons/manufacturing-black.png new file mode 100644 index 000000000..697eb0e9f Binary files /dev/null and b/multi_branch_base/static/description/assets/icons/manufacturing-black.png differ diff --git a/multi_branch_base/static/description/assets/icons/pos-black.png b/multi_branch_base/static/description/assets/icons/pos-black.png new file mode 100644 index 000000000..97c0f90c1 Binary files /dev/null and b/multi_branch_base/static/description/assets/icons/pos-black.png differ diff --git a/multi_branch_base/static/description/assets/icons/puzzle.png b/multi_branch_base/static/description/assets/icons/puzzle.png new file mode 100644 index 000000000..65cf854e7 Binary files /dev/null and b/multi_branch_base/static/description/assets/icons/puzzle.png differ diff --git a/multi_branch_base/static/description/assets/icons/restaurant-black.png b/multi_branch_base/static/description/assets/icons/restaurant-black.png new file mode 100644 index 000000000..4a35eb939 Binary files /dev/null and b/multi_branch_base/static/description/assets/icons/restaurant-black.png differ diff --git a/multi_branch_base/static/description/assets/icons/service-black.png b/multi_branch_base/static/description/assets/icons/service-black.png new file mode 100644 index 000000000..301ab51cb Binary files /dev/null and b/multi_branch_base/static/description/assets/icons/service-black.png differ diff --git a/multi_branch_base/static/description/assets/icons/trading-black.png b/multi_branch_base/static/description/assets/icons/trading-black.png new file mode 100644 index 000000000..9398ba2f1 Binary files /dev/null and b/multi_branch_base/static/description/assets/icons/trading-black.png differ diff --git a/multi_branch_base/static/description/assets/icons/training.png b/multi_branch_base/static/description/assets/icons/training.png new file mode 100644 index 000000000..884ca024d Binary files /dev/null and b/multi_branch_base/static/description/assets/icons/training.png differ diff --git a/multi_branch_base/static/description/assets/icons/update.png b/multi_branch_base/static/description/assets/icons/update.png new file mode 100644 index 000000000..ecbc5a01a Binary files /dev/null and b/multi_branch_base/static/description/assets/icons/update.png differ diff --git a/multi_branch_base/static/description/assets/icons/user.png b/multi_branch_base/static/description/assets/icons/user.png new file mode 100644 index 000000000..6ffb23d9f Binary files /dev/null and b/multi_branch_base/static/description/assets/icons/user.png differ diff --git a/multi_branch_base/static/description/assets/icons/wrench.png b/multi_branch_base/static/description/assets/icons/wrench.png new file mode 100644 index 000000000..6c04dea0f Binary files /dev/null and b/multi_branch_base/static/description/assets/icons/wrench.png differ diff --git a/multi_branch_base/static/description/assets/modules/1.png b/multi_branch_base/static/description/assets/modules/1.png new file mode 100644 index 000000000..1217263a6 Binary files /dev/null and b/multi_branch_base/static/description/assets/modules/1.png differ diff --git a/multi_branch_base/static/description/assets/modules/2.png b/multi_branch_base/static/description/assets/modules/2.png new file mode 100644 index 000000000..6f604a403 Binary files /dev/null and b/multi_branch_base/static/description/assets/modules/2.png differ diff --git a/multi_branch_base/static/description/assets/modules/3.png b/multi_branch_base/static/description/assets/modules/3.png new file mode 100644 index 000000000..6f28da108 Binary files /dev/null and b/multi_branch_base/static/description/assets/modules/3.png differ diff --git a/multi_branch_base/static/description/assets/modules/4.png b/multi_branch_base/static/description/assets/modules/4.png new file mode 100644 index 000000000..3afc14722 Binary files /dev/null and b/multi_branch_base/static/description/assets/modules/4.png differ diff --git a/multi_branch_base/static/description/assets/modules/5.png b/multi_branch_base/static/description/assets/modules/5.png new file mode 100644 index 000000000..cea66b05f Binary files /dev/null and b/multi_branch_base/static/description/assets/modules/5.png differ diff --git a/multi_branch_base/static/description/assets/modules/6.png b/multi_branch_base/static/description/assets/modules/6.png new file mode 100644 index 000000000..0c9bb377e Binary files /dev/null and b/multi_branch_base/static/description/assets/modules/6.png differ diff --git a/multi_branch_base/static/description/assets/screenshots/hero.png b/multi_branch_base/static/description/assets/screenshots/hero.png new file mode 100644 index 000000000..df1f8b7af Binary files /dev/null and b/multi_branch_base/static/description/assets/screenshots/hero.png differ diff --git a/multi_branch_base/static/description/assets/screenshots/mb01.png b/multi_branch_base/static/description/assets/screenshots/mb01.png new file mode 100644 index 000000000..946574849 Binary files /dev/null and b/multi_branch_base/static/description/assets/screenshots/mb01.png differ diff --git a/multi_branch_base/static/description/assets/screenshots/mb02.png b/multi_branch_base/static/description/assets/screenshots/mb02.png new file mode 100644 index 000000000..74906f1fe Binary files /dev/null and b/multi_branch_base/static/description/assets/screenshots/mb02.png differ diff --git a/multi_branch_base/static/description/assets/screenshots/mb03.png b/multi_branch_base/static/description/assets/screenshots/mb03.png new file mode 100644 index 000000000..f670ffdb2 Binary files /dev/null and b/multi_branch_base/static/description/assets/screenshots/mb03.png differ diff --git a/multi_branch_base/static/description/assets/screenshots/mb04.png b/multi_branch_base/static/description/assets/screenshots/mb04.png new file mode 100644 index 000000000..878b649ec Binary files /dev/null and b/multi_branch_base/static/description/assets/screenshots/mb04.png differ diff --git a/multi_branch_base/static/description/assets/screenshots/mb05.png b/multi_branch_base/static/description/assets/screenshots/mb05.png new file mode 100644 index 000000000..a5d7ed609 Binary files /dev/null and b/multi_branch_base/static/description/assets/screenshots/mb05.png differ diff --git a/multi_branch_base/static/description/assets/screenshots/mb06.png b/multi_branch_base/static/description/assets/screenshots/mb06.png new file mode 100644 index 000000000..0d952e484 Binary files /dev/null and b/multi_branch_base/static/description/assets/screenshots/mb06.png differ diff --git a/multi_branch_base/static/description/assets/screenshots/mb07.png b/multi_branch_base/static/description/assets/screenshots/mb07.png new file mode 100644 index 000000000..d2c98f061 Binary files /dev/null and b/multi_branch_base/static/description/assets/screenshots/mb07.png differ diff --git a/multi_branch_base/static/description/assets/screenshots/mb08.png b/multi_branch_base/static/description/assets/screenshots/mb08.png new file mode 100644 index 000000000..6995c692c Binary files /dev/null and b/multi_branch_base/static/description/assets/screenshots/mb08.png differ diff --git a/multi_branch_base/static/description/assets/screenshots/mb09.png b/multi_branch_base/static/description/assets/screenshots/mb09.png new file mode 100644 index 000000000..b855d73d9 Binary files /dev/null and b/multi_branch_base/static/description/assets/screenshots/mb09.png differ diff --git a/multi_branch_base/static/description/assets/screenshots/mb10.png b/multi_branch_base/static/description/assets/screenshots/mb10.png new file mode 100644 index 000000000..9a0570042 Binary files /dev/null and b/multi_branch_base/static/description/assets/screenshots/mb10.png differ diff --git a/multi_branch_base/static/description/assets/screenshots/mb11.png b/multi_branch_base/static/description/assets/screenshots/mb11.png new file mode 100644 index 000000000..67276ee3a Binary files /dev/null and b/multi_branch_base/static/description/assets/screenshots/mb11.png differ diff --git a/multi_branch_base/static/description/assets/screenshots/mb12.png b/multi_branch_base/static/description/assets/screenshots/mb12.png new file mode 100644 index 000000000..2645c39c0 Binary files /dev/null and b/multi_branch_base/static/description/assets/screenshots/mb12.png differ diff --git a/multi_branch_base/static/description/assets/screenshots/mb13.png b/multi_branch_base/static/description/assets/screenshots/mb13.png new file mode 100644 index 000000000..d3a80272d Binary files /dev/null and b/multi_branch_base/static/description/assets/screenshots/mb13.png differ diff --git a/multi_branch_base/static/description/assets/screenshots/mb14.png b/multi_branch_base/static/description/assets/screenshots/mb14.png new file mode 100644 index 000000000..fd9d90bba Binary files /dev/null and b/multi_branch_base/static/description/assets/screenshots/mb14.png differ diff --git a/multi_branch_base/static/description/banner.jpg b/multi_branch_base/static/description/banner.jpg new file mode 100644 index 000000000..812dc6a4a Binary files /dev/null and b/multi_branch_base/static/description/banner.jpg differ diff --git a/multi_branch_base/static/description/icon.png b/multi_branch_base/static/description/icon.png new file mode 100644 index 000000000..0d4ff2c28 Binary files /dev/null and b/multi_branch_base/static/description/icon.png differ diff --git a/multi_branch_base/static/description/images/checked.png b/multi_branch_base/static/description/images/checked.png new file mode 100644 index 000000000..e6c63d582 Binary files /dev/null and b/multi_branch_base/static/description/images/checked.png differ diff --git a/multi_branch_base/static/description/images/modules/approval_image.png b/multi_branch_base/static/description/images/modules/approval_image.png new file mode 100644 index 000000000..84fe94e80 Binary files /dev/null and b/multi_branch_base/static/description/images/modules/approval_image.png differ diff --git a/multi_branch_base/static/description/images/modules/dynamic_image.png b/multi_branch_base/static/description/images/modules/dynamic_image.png new file mode 100644 index 000000000..74ce220e6 Binary files /dev/null and b/multi_branch_base/static/description/images/modules/dynamic_image.png differ diff --git a/multi_branch_base/static/description/images/modules/mulitple-ref_image.png b/multi_branch_base/static/description/images/modules/mulitple-ref_image.png new file mode 100644 index 000000000..e0964f1e3 Binary files /dev/null and b/multi_branch_base/static/description/images/modules/mulitple-ref_image.png differ diff --git a/multi_branch_base/static/description/images/modules/pos_image.png b/multi_branch_base/static/description/images/modules/pos_image.png new file mode 100644 index 000000000..c5932894b Binary files /dev/null and b/multi_branch_base/static/description/images/modules/pos_image.png differ diff --git a/multi_branch_base/static/description/images/modules/shopify_image.png b/multi_branch_base/static/description/images/modules/shopify_image.png new file mode 100644 index 000000000..c6d92c16d Binary files /dev/null and b/multi_branch_base/static/description/images/modules/shopify_image.png differ diff --git a/multi_branch_base/static/description/index.html b/multi_branch_base/static/description/index.html new file mode 100644 index 000000000..9608a56c1 --- /dev/null +++ b/multi_branch_base/static/description/index.html @@ -0,0 +1,902 @@ +
+
+
+
+ +
+
+
+ Community +
+
+ Enterprise +
+ +
+
+
+
+ +
+
+
+

+ Multi Branch Operations

+

+ Multiple Branch Unit Operation Setup for All + Modules In Odoo +

+ +
+
+ + +
+
+

+ Overview +

+
+ +
+

+ Multi Branch module helps to manage the operations of multiple branches of a single company. + You can manage multiple branches and all the operations of different branches of in the Inventory, + Accounting, Sales and Purchase applications by installing this single module. + After installing the module, the administrator can create multiple branches for the company by providing the details from + Settings -> Users and Companies -> Branches. Allowed branches and default branch can be set for each user from + Settings -> Users and Companies -> Users. Once it is configured, the user can access the all branches which are allowed for the particular user. +

+ +
+
+ +
+
+

+ Features +

+
+ +
+
+ +
+
+

+ + Create Branches for the Company.

+ +
+
+ +
+
+ +
+
+

+ + Branch for User.

+ +
+
+ +
+
+ +
+
+

+ + Branch on Product.

+ +
+
+ +
+
+ +
+
+

+ + Branch on Partner.

+ +
+
+ +
+
+ +
+
+

+ + Branch on Journal.

+ +
+
+ +
+
+ +
+
+

+ + Branch on Account.

+ +
+
+ +
+
+ +
+
+

+ + Branch on Customer Vendor Payments.

+ +
+
+ +
+
+ +
+
+

+ + Branch on Customer Invoice.

+ +
+
+ +
+
+ +
+
+

+ + Branch on Vendor Bill.

+ +
+
+ +
+
+ +
+
+

+ + Branch on Warehouse.

+ +
+
+ +
+
+ +
+
+

+ + Branch on Operation Types.

+ +
+
+ +
+
+ +
+
+

+ + Branch on transfer.

+ +
+
+ +
+
+ +
+
+

+ + Branch on Sales flow.

+ +
+
+ +
+
+ +
+
+

+ + Branch on Purchase flow.

+ +
+
+ +
+
+ +
+
+

+ + Branch on Reports.

+ +
+
+ +
+ +
+
+

+ Screenshots +

+
+ +
+

+ Branch Creation

+

+ Administrator can create Branches for the + company from Settings -> Users & Companies -> Branches -> Create +

+ +
+ +
+

+ Allowed & Default Branch

+

+ Allowed branches and default branch can be set for each user. + The showing Branches will be based on the allowed Companies + for the particular user +

+ +
+ +
+

+ Product

+

+ Branch can be set for products. + If a product is shared between branches then it is suggested to + keep branch field as empty +

+ +
+ +
+

+ Partners

+

+ Branch can be set for partners +

+ +
+ +
+

+ Journal

+

+ Branch for Journals +

+ +
+ +
+

+ Chart of Accounts

+

+ Branch for Chart of Accounts +

+ +
+ +
+

+ Warehouse

+

+ Branch can be set for Warehouse +

+ +
+ +
+

+ Operation Types

+

+ When a Warehouse is created the corresponding operation types for the + Warehouse will be automatically created.If the particular Warehouse + have a Branch, then the same Branch will be set for the operation + types too. +

+ +
+ +
+

+ Purchase Order

+

+ For the newly created PO branch will be set based on the user. +

+ +
+ +
+

+ Receipt

+

+ The receipt will be created once PO is confirmed.Here Destination Location and Branch will be set based on the Purchase Order Branch. + +

+ +
+ +
+

+ Bill

+

+ After validating the Receipt Vendor Bill can be created from the PO.For the created Bill Branch will be set as the branch selected for the PO + and Journal will be set accordingly. + +

+ +
+ +
+

+ Sale Order

+

+ On creating a new quotation/sale order the default branch set for + the user is set as the branch for the same if only one branch is allowed for the user.The warehouse used will + be the warehouse of the same branch. +

+ +
+ +
+

+ Delivery Order

+

+ On confirming a sale order the corresponding delivery order will be + created.The branch selected for the sale order will be populated as + the branch for the delivery order.Also the source location is + set accordingly. +

+ +
+ +
+

+ Invoice

+

+ For the invoice created for the sale order the branch will be set + based on the sale order.Here the journals are also set + based on the selected branch.If there is no available sales journal, + then the user can't create the invoice +

+ +
+ +
+ + + +
+
+

Suggested Products

+
+ + +
+
+ + + +
+
+
+

Our Services

+
+
+ +
+
+ +
+
+ Odoo + Customization
+
+ +
+
+ +
+
+ Odoo + Implementation
+
+ +
+
+ +
+
+ Odoo + Support
+
+ + +
+
+ +
+
+ Hire + Odoo + Developer
+
+ +
+
+ +
+
+ Odoo + Integration
+
+ +
+
+ +
+
+ Odoo + Migration
+
+ + +
+
+ +
+
+ Odoo + Consultancy
+
+ +
+
+ +
+
+ Odoo + Implementation
+
+ +
+
+ +
+
+ Odoo + Licensing Consultancy
+
+
+
+ + + +
+
+
+

Our Industries

+
+
+ +
+
+ +
+ Trading +
+

+ Easily procure + and + sell your products

+
+
+ +
+
+ +
+ POS +
+

+ Easy + configuration + and convivial experience

+
+
+ +
+
+ +
+ Education +
+

+ A platform for + educational management

+
+
+ +
+
+ +
+ Manufacturing +
+

+ Plan, track and + schedule your operations

+
+
+ +
+
+ +
+ E-commerce & Website +
+

+ Mobile + friendly, + awe-inspiring product pages

+
+
+ +
+
+ +
+ Service Management +
+

+ Keep track of + services and invoice

+
+
+ +
+
+ +
+ Restaurant +
+

+ Run your bar or + restaurant methodically

+
+
+ +
+
+ +
+ Hotel Management +
+

+ An + all-inclusive + hotel management application

+
+
+ +
+
+ + + + + +
+
+
+

Need Help?

+
+
+
+ + +
+ +
+ +
+ +
+ WhatsApp +
+
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+
+
+ + +
\ No newline at end of file diff --git a/multi_branch_base/views/branch_account_journal.xml b/multi_branch_base/views/branch_account_journal.xml new file mode 100644 index 000000000..e23d158b2 --- /dev/null +++ b/multi_branch_base/views/branch_account_journal.xml @@ -0,0 +1,27 @@ + + + + + + view.account.journal.form.inherit + account.journal + + + + + + + + + + view.account.journal.tree + account.journal + + + + + + + + + \ No newline at end of file diff --git a/multi_branch_base/views/branch_account_move_views.xml b/multi_branch_base/views/branch_account_move_views.xml new file mode 100644 index 000000000..068813e8d --- /dev/null +++ b/multi_branch_base/views/branch_account_move_views.xml @@ -0,0 +1,92 @@ + + + + + view.move.form.inherit + account.move + + + + + + + + + + + + + view.out.invoice.tree + account.move + + + + + + + + + + view.in.invoice.tree + account.move + + + + + + + + + + .view.account.invoice.filter.inherit + account.move + + + + + + + + + + view.move.line.form.inherit + account.move.line + + + + + + + + + .view.account.move.line.filter.inherit + account.move.line + + + + + + + + + .view.account.move.filter.inherit + account.move + + + + + + + + + + \ No newline at end of file diff --git a/multi_branch_base/views/branch_account_payment_views.xml b/multi_branch_base/views/branch_account_payment_views.xml new file mode 100644 index 000000000..308acc6f7 --- /dev/null +++ b/multi_branch_base/views/branch_account_payment_views.xml @@ -0,0 +1,55 @@ + + + + + view.account.payment.form.inherit + account.payment + + + + + + + + + + + + + view.payment.tree + account.payment + + + + + + + + + + view.supplier.payment.tree + account.payment + + + + + + + + + + .view.account.payment.search.inherit + account.payment + + + + + + + + + \ No newline at end of file diff --git a/multi_branch_base/views/branch_account_views.xml b/multi_branch_base/views/branch_account_views.xml new file mode 100644 index 000000000..31a70bb1f --- /dev/null +++ b/multi_branch_base/views/branch_account_views.xml @@ -0,0 +1,41 @@ + + + + + + view.account.form.inherit + account.account + + + + + + + + + + + + view.account.list.inherit + account.account + + + + + + + + + .view.account.search.inherit + account.account + + + + + + + + + \ No newline at end of file diff --git a/multi_branch_base/views/branch_product_template_views.xml b/multi_branch_base/views/branch_product_template_views.xml new file mode 100644 index 000000000..f7930a371 --- /dev/null +++ b/multi_branch_base/views/branch_product_template_views.xml @@ -0,0 +1,15 @@ + + + + + product.form.inherit + product.template + + + + + + + + + \ No newline at end of file diff --git a/multi_branch_base/views/branch_purchase_order_views.xml b/multi_branch_base/views/branch_purchase_order_views.xml new file mode 100644 index 000000000..6f90cb371 --- /dev/null +++ b/multi_branch_base/views/branch_purchase_order_views.xml @@ -0,0 +1,49 @@ + + + + + purchase.order.form.inherit + purchase.order + + + + + + + + + + purchase.order.search.view.inherit + purchase.order + + + + + + + + + + purchase.order.filter.inherit + purchase.order + + + + + + + + + + view.purchase.order.tree + purchase.order + + + + + + + + + + diff --git a/multi_branch_base/views/branch_report_template.xml b/multi_branch_base/views/branch_report_template.xml new file mode 100644 index 000000000..bf6818792 --- /dev/null +++ b/multi_branch_base/views/branch_report_template.xml @@ -0,0 +1,278 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/multi_branch_base/views/branch_res_partner_views.xml b/multi_branch_base/views/branch_res_partner_views.xml new file mode 100644 index 000000000..a140aceaa --- /dev/null +++ b/multi_branch_base/views/branch_res_partner_views.xml @@ -0,0 +1,16 @@ + + + + + res.partner.form.inherit + res.partner + + + + + + + + + \ No newline at end of file diff --git a/multi_branch_base/views/branch_res_users_views.xml b/multi_branch_base/views/branch_res_users_views.xml new file mode 100644 index 000000000..04ea2d728 --- /dev/null +++ b/multi_branch_base/views/branch_res_users_views.xml @@ -0,0 +1,18 @@ + + + + + res.users.form.inherit + res.users + + + + + + + + + + + + \ No newline at end of file diff --git a/multi_branch_base/views/branch_sale_order_views.xml b/multi_branch_base/views/branch_sale_order_views.xml new file mode 100644 index 000000000..cf7ffeafc --- /dev/null +++ b/multi_branch_base/views/branch_sale_order_views.xml @@ -0,0 +1,54 @@ + + + + + sale.order.form.inherit + sale.order + + + + + + + + + + + + + sale.order.search.view.inherit + sale.order + + + + + + + + + + sale.quotation.search.view.inherit + sale.order + + + + + + + + + + view.order.tree + sale.order + + + + + + + + + \ No newline at end of file diff --git a/multi_branch_base/views/branch_stock_picking_views.xml b/multi_branch_base/views/branch_stock_picking_views.xml new file mode 100644 index 000000000..55146c18d --- /dev/null +++ b/multi_branch_base/views/branch_stock_picking_views.xml @@ -0,0 +1,43 @@ + + + + + stock_picking.form.inherit + stock.picking + + + + + + + + + + + + + picking.internal.search.inherit + stock.picking + + + + + + + + + + view_picking.type.form.inherit + stock.picking.type + + + + + + + + + \ No newline at end of file diff --git a/multi_branch_base/views/branch_stock_warehouse_views.xml b/multi_branch_base/views/branch_stock_warehouse_views.xml new file mode 100644 index 000000000..3d9e4ab5e --- /dev/null +++ b/multi_branch_base/views/branch_stock_warehouse_views.xml @@ -0,0 +1,128 @@ + + + + + + view.warehouse.inherit + stock.warehouse + + + + + + + + + + view.warehouse.tree + stock.warehouse + + + + + + + + + + stock.move.form.inherit + stock.move + + + + + + + + + + stock.move.tree.inherit + stock.move + + + + + + + + + + stock.move.search.inherit + stock.move + + + + + + + + + + + stock.move.line.form.inherit + stock.move.line + + + + + + + + + + stock.move.line.tree.inherit + stock.move.line + + + + + + + + + + stock.move.line.search.inherit + stock.move.line + + + + + + + + + + + stock.valuation.form.inherit + stock.valuation.layer + + + + + + + + + + stock.valuation.tree.inherit + stock.valuation.layer + + + + + + + + + + stock.valuation.search.inherit + stock.valuation.layer + + + + + + + + + \ No newline at end of file diff --git a/multi_branch_base/views/res_branch_views.xml b/multi_branch_base/views/res_branch_views.xml new file mode 100644 index 000000000..20a15accb --- /dev/null +++ b/multi_branch_base/views/res_branch_views.xml @@ -0,0 +1,87 @@ + + + + + + res.branch.form + res.branch + +
+ +
+
+ + + + + + + + + + + + + + +
+
+
+
+ + + res.branch.tree + res.branch + + + + + + + + + + + res.branch.search + res.branch + + + + + + + + + + + + Branches + ir.actions.act_window + res.branch + tree,form + +

+ Create a new Branch +

+ Create and manage branches for the companies that will be managed by Odoo from here. +

+
+
+ + +
+
\ No newline at end of file diff --git a/multi_branch_base/wizard/__init__.py b/multi_branch_base/wizard/__init__.py new file mode 100644 index 000000000..07e6db12a --- /dev/null +++ b/multi_branch_base/wizard/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from . import branch_account_payment_register diff --git a/multi_branch_base/wizard/branch_account_payment_register.py b/multi_branch_base/wizard/branch_account_payment_register.py new file mode 100644 index 000000000..b19628688 --- /dev/null +++ b/multi_branch_base/wizard/branch_account_payment_register.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import models, fields, api + + +class AccountPaymentRegister(models.TransientModel): + """inherited account payment register wizard models""" + _inherit = 'account.payment.register' + + branch_id = fields.Many2one('res.branch', store=True, readonly=False) + journal_id = fields.Many2one('account.journal', store=True, readonly=False, + compute='_compute_journal_id', + domain="[('company_id', '=', company_id), " + "('type', 'in', ('bank', 'cash'))]") + + @api.depends('company_id', 'source_currency_id') + def _compute_journal_id(self): + """methode to compute journal id based on current branch""" + self.ensure_one() + lines = self.line_ids._origin + branch = lines.branch_id + if branch: + for wizard in self: + domain = [ + ('type', 'in', ('bank', 'cash')), + ('branch_id', '=', branch.id), + ] + journal = None + if wizard.source_currency_id: + journal = self.env['account.journal'].search(domain + [ + ('currency_id', '=', wizard.source_currency_id.id)], + limit=1) + if not journal: + journal = self.env['account.journal'].search(domain, + limit=1) + if not journal: + domain = [ + ('type', 'in', ('bank', 'cash')), + ('branch_id', '=', False), + ] + journal = None + if wizard.source_currency_id: + journal = self.env['account.journal'].search(domain + [ + ('currency_id', '=', wizard.source_currency_id.id)], + limit=1) + if not journal: + journal = self.env['account.journal'].search(domain, + limit=1) + wizard.journal_id = journal + else: + res = super(AccountPaymentRegister, self)._compute_journal_id() + return res + + def _create_payment_vals_from_wizard(self): + """create payment values""" + self.ensure_one() + lines = self.line_ids._origin + branch = lines.branch_id + payment_vals = { + 'date': self.payment_date, + 'amount': self.amount, + 'payment_type': self.payment_type, + 'partner_type': self.partner_type, + 'ref': self.communication, + 'journal_id': self.journal_id.id, + 'branch_id': branch.id, + 'currency_id': self.currency_id.id, + 'partner_id': self.partner_id.id, + 'partner_bank_id': self.partner_bank_id.id, + 'payment_method_id': self.payment_method_id.id, + 'destination_account_id': self.line_ids[0].account_id.id + } + if not self.currency_id.is_zero( + self.payment_difference) and self.payment_difference_handling == 'reconcile': + payment_vals['write_off_line_vals'] = { + 'name': self.writeoff_label, + 'amount': self.payment_difference, + 'account_id': self.writeoff_account_id.id, + } + return payment_vals