1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
class AccountMove(models.Model):
_inherit = "account.move"
@api.depends('amount_total')
def _compute_amount_total_words(self):
for invoice in self:
invoice.amount_total_words = invoice.currency_id.amount_to_text(invoice.amount_total)
amount_total_words = fields.Char("Total (In Words)", compute="_compute_amount_total_words")
l10n_in_gst_treatment = fields.Selection([
('regular', 'Registered Business - Regular'),
('composition', 'Registered Business - Composition'),
('unregistered', 'Unregistered Business'),
('consumer', 'Consumer'),
('overseas', 'Overseas'),
('special_economic_zone', 'Special Economic Zone'),
('deemed_export', 'Deemed Export')
], string="GST Treatment", readonly=True, states={'draft': [('readonly', False)]})
l10n_in_state_id = fields.Many2one('res.country.state', string="Location of supply")
l10n_in_company_country_code = fields.Char(related='company_id.country_id.code', string="Country code")
l10n_in_gstin = fields.Char(string="GSTIN")
# For Export invoice this data is need in GSTR report
l10n_in_shipping_bill_number = fields.Char('Shipping bill number', readonly=True, states={'draft': [('readonly', False)]})
l10n_in_shipping_bill_date = fields.Date('Shipping bill date', readonly=True, states={'draft': [('readonly', False)]})
l10n_in_shipping_port_code_id = fields.Many2one('l10n_in.port.code', 'Port code', states={'draft': [('readonly', False)]})
l10n_in_reseller_partner_id = fields.Many2one('res.partner', 'Reseller', domain=[('vat', '!=', False)], help="Only Registered Reseller", readonly=True, states={'draft': [('readonly', False)]})
@api.onchange('partner_id')
def _onchange_partner_id(self):
"""Use journal type to define document type because not miss state in any entry including POS entry"""
if self.l10n_in_company_country_code == 'IN':
self.l10n_in_gst_treatment = self.partner_id.l10n_in_gst_treatment
return super()._onchange_partner_id()
@api.model
def _l10n_in_get_indian_state(self, partner):
"""In tax return filing, If customer is not Indian in that case place of supply is must set to Other Territory.
So we set Other Territory in l10n_in_state_id when customer(partner) is not Indian
Also we raise if state is not set in Indian customer.
State is big role under GST because tax type is depend on.for more information check this https://www.cbic.gov.in/resources//htdocs-cbec/gst/Integrated%20goods%20&%20Services.pdf"""
if partner.country_id and partner.country_id.code == 'IN' and not partner.state_id:
raise ValidationError(_("State is missing from address in '%s'. First set state after post this invoice again.", partner.name))
elif partner.country_id and partner.country_id.code != 'IN':
return self.env.ref('l10n_in.state_in_ot')
return partner.state_id
@api.model
def _get_tax_grouping_key_from_tax_line(self, tax_line):
# OVERRIDE to group taxes also by product.
res = super()._get_tax_grouping_key_from_tax_line(tax_line)
if tax_line.move_id.journal_id.company_id.country_id.code == 'IN':
res['product_id'] = tax_line.product_id.id
res['product_uom_id'] = tax_line.product_uom_id
return res
@api.model
def _get_tax_grouping_key_from_base_line(self, base_line, tax_vals):
# OVERRIDE to group taxes also by product.
res = super()._get_tax_grouping_key_from_base_line(base_line, tax_vals)
if base_line.move_id.journal_id.company_id.country_id.code == 'IN':
res['product_id'] = base_line.product_id.id
res['product_uom_id'] = base_line.product_uom_id
return res
@api.model
def _get_tax_key_for_group_add_base(self, line):
# DEPRECATED: TO BE REMOVED IN MASTER
tax_key = super(AccountMove, self)._get_tax_key_for_group_add_base(line)
tax_key += [
line.product_id.id,
line.product_uom_id,
]
return tax_key
def _l10n_in_get_shipping_partner(self):
"""Overwrite in sale"""
self.ensure_one()
return self.partner_id
@api.model
def _l10n_in_get_shipping_partner_gstin(self, shipping_partner):
"""Overwrite in sale"""
return shipping_partner.vat
def _post(self, soft=True):
"""Use journal type to define document type because not miss state in any entry including POS entry"""
posted = super()._post(soft)
gst_treatment_name_mapping = {k: v for k, v in
self._fields['l10n_in_gst_treatment']._description_selection(self.env)}
for move in posted.filtered(lambda m: m.l10n_in_company_country_code == 'IN'):
"""Check state is set in company/sub-unit"""
company_unit_partner = move.journal_id.l10n_in_gstin_partner_id or move.journal_id.company_id
if not company_unit_partner.state_id:
raise ValidationError(_(
"State is missing from your company/unit %(company_name)s (%(company_id)s).\nFirst set state in your company/unit.",
company_name=company_unit_partner.name,
company_id=company_unit_partner.id
))
elif self.journal_id.type == 'purchase':
move.l10n_in_state_id = company_unit_partner.state_id
shipping_partner = move._l10n_in_get_shipping_partner()
# In case of shipping address does not have GSTN then also check customer(partner_id) GSTN
# This happens when Bill-to Ship-to transaction where shipping(Ship-to) address is unregistered and customer(Bill-to) is registred.
move.l10n_in_gstin = move._l10n_in_get_shipping_partner_gstin(shipping_partner) or move.partner_id.vat
if not move.l10n_in_gstin and move.l10n_in_gst_treatment in ['regular', 'composition', 'special_economic_zone', 'deemed_export']:
raise ValidationError(_(
"Partner %(partner_name)s (%(partner_id)s) GSTIN is required under GST Treatment %(name)s",
partner_name=shipping_partner.name,
partner_id=shipping_partner.id,
name=gst_treatment_name_mapping.get(move.l10n_in_gst_treatment)
))
if self.journal_id.type == 'sale':
move.l10n_in_state_id = self._l10n_in_get_indian_state(shipping_partner)
if not move.l10n_in_state_id:
move.l10n_in_state_id = self._l10n_in_get_indian_state(move.partner_id)
#still state is not set then assumed that transaction is local like PoS so set state of company unit
if not move.l10n_in_state_id:
move.l10n_in_state_id = company_unit_partner.state_id
return posted
|