import pytz from stdnum.in_ import pan, gstin from odoo import Command, _, api, fields, models from odoo.exceptions import RedirectWarning class ResCompany(models.Model): _inherit = 'res.company' l10n_in_upi_id = fields.Char(string="UPI Id") l10n_in_hsn_code_digit = fields.Selection( selection=[ ("4", "4 Digits (turnover < 5 CR.)"), ("6", "6 Digits (turnover > 5 CR.)"), ("8", "8 Digits"), ], string="HSN Code Digit", compute="_compute_l10n_in_hsn_code_digit", store=True, readonly=False, ) l10n_in_edi_production_env = fields.Boolean( string="Indian Production Environment", help="Enable the use of production credentials", groups="base.group_system", default=True, ) l10n_in_pan_entity_id = fields.Many2one( related="partner_id.l10n_in_pan_entity_id", string="PAN", store=True, readonly=False, help="PAN enables the department to link all transactions of the person with the department.\n" "These transactions include taxpayments, TDS/TCS credits, returns of income/wealth/gift/FBT," "specified transactions, correspondence, and so on.\n" "Thus, PAN acts as an identifier for the person with the tax department.", ) l10n_in_pan_type = fields.Selection(related="l10n_in_pan_entity_id.type", string="PAN Type") l10n_in_tan = fields.Char(related="partner_id.l10n_in_tan", string="TAN", readonly=False) l10n_in_gst_state_warning = fields.Char(related="partner_id.l10n_in_gst_state_warning") # TDS/TCS settings l10n_in_tds_feature = fields.Boolean( string="TDS", compute="_compute_l10n_in_parent_based_features", inverse="_inverse_l10n_in_tds_feature", recursive=True, store=True, ) l10n_in_tcs_feature = fields.Boolean( string="TCS", compute="_compute_l10n_in_parent_based_features", inverse="_inverse_l10n_in_tcs_feature", recursive=True, store=True, ) l10n_in_withholding_account_id = fields.Many2one( comodel_name='account.account', string="TDS Account", check_company=True, ) l10n_in_withholding_journal_id = fields.Many2one( comodel_name='account.journal', string="TDS Journal", check_company=True, ) # GST settings l10n_in_is_gst_registered = fields.Boolean( string="Registered Under GST", compute="_compute_l10n_in_parent_based_features", inverse="_inverse_l10n_in_is_gst_registered", recursive=True, store=True, ) l10n_in_gstin_status_feature = fields.Boolean(string="Check GST Number Status") def _inverse_l10n_in_tds_feature(self): for company in self: self._activate_l10n_in_taxes(['tds_group'], company, company.l10n_in_tds_feature) def _inverse_l10n_in_tcs_feature(self): for company in self: self._activate_l10n_in_taxes(['tcs_group'], company, company.l10n_in_tcs_feature) def _inverse_l10n_in_is_gst_registered(self): for company in self: gst_group_refs = [ 'sgst_group', 'cgst_group', 'igst_group', 'cess_group', 'gst_group', 'exempt_group', 'nil_rated_group', 'non_gst_supplies_group', ] if company.l10n_in_is_gst_registered: self._activate_l10n_in_taxes(gst_group_refs, company, True) # Set sale and purchase tax accounts when user registered under GST. company.account_sale_tax_id = self.env['account.chart.template'].with_company(company).ref('sgst_sale_5', raise_if_not_found=False) company.account_purchase_tax_id = self.env['account.chart.template'].with_company(company).ref('sgst_purchase_5', raise_if_not_found=False) else: self._activate_l10n_in_taxes(gst_group_refs, company, False) company.account_sale_tax_id = False company.account_purchase_tax_id = False @api.depends('parent_id.l10n_in_tds_feature', 'parent_id.l10n_in_tcs_feature', 'parent_id.l10n_in_is_gst_registered') def _compute_l10n_in_parent_based_features(self): for company in self: if company.parent_id: company.l10n_in_tds_feature = company.parent_id.l10n_in_tds_feature company.l10n_in_tcs_feature = company.parent_id.l10n_in_tcs_feature company.l10n_in_is_gst_registered = company.parent_id.l10n_in_is_gst_registered def _activate_l10n_in_taxes(self, group_refs, company, active=True): tax_group_ids = [ tax_group.id for group_ref in group_refs if (tax_group := self.env['account.chart.template'].with_company(company).ref(group_ref, raise_if_not_found=False)) ] if tax_group_ids: taxes = self.env['account.tax'].with_company(company).with_context(active_test=False).search([ ('tax_group_id', 'in', tax_group_ids), ('active', '!=', active) ]) taxes.write({'active': active}) @api.depends('vat') def _compute_l10n_in_hsn_code_digit(self): for record in self: if record.country_code == "IN" and record.vat: record.l10n_in_hsn_code_digit = "4" else: record.l10n_in_hsn_code_digit = False @api.onchange('vat') def onchange_vat(self): self.partner_id.onchange_vat() @api.model_create_multi def create(self, vals_list): res = super().create(vals_list) # Update Fiscal Positions for new branch res._update_l10n_in_fiscal_position() return res def write(self, vals): res = super().write(vals) if vals.get('vat'): # Enable GST(l10n_in_is_gst_registered) when a valid GSTIN(vat) is applied. self._update_l10n_in_is_gst_registered() if (vals.get('state_id') or vals.get('country_id')) and not self.env.context.get('delay_account_group_sync'): # Update Fiscal Positions for companies setting up state for the first time self._update_l10n_in_fiscal_position() return res def _update_l10n_in_fiscal_position(self): companies_need_update_fp = self.filtered(lambda c: c.parent_ids[0].chart_template == 'in') for company in companies_need_update_fp: ChartTemplate = self.env['account.chart.template'].with_company(company) fiscal_position_data = ChartTemplate._get_in_account_fiscal_position() for values in fiscal_position_data.values(): values['tax_ids'] = [Command.set([ xml_id for xml_id in values['tax_ids'][0][2] if ChartTemplate.ref(xml_id, raise_if_not_found=False) ])] ChartTemplate._load_data({'account.fiscal.position': fiscal_position_data}) def _update_l10n_in_is_gst_registered(self): for company in self: if company.country_code == "IN" and company.vat: company.l10n_in_is_gst_registered = company.partner_id.check_vat_in(company.vat) def action_update_state_as_per_gstin(self): self.ensure_one() self.partner_id.action_update_state_as_per_gstin() def _check_tax_return_configuration(self): """ Check if the company is properly configured for tax returns. :raises RedirectWarning: if something is wrong configured. """ if self.country_code != 'IN': return super()._check_tax_return_configuration() is_l10n_in_reports_installed = 'l10n_in_reports' in self.env['ir.module.module']._installed() if not is_l10n_in_reports_installed: msg = _("First enable GST e-Filing feature from configuration for company %s.", (self.name)) action = self.env.ref("account.action_account_config") raise RedirectWarning(msg, action.id, _('Go to configuration'))