Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ADD] account_custom_duty: manage custom duties on import & export transactions #648

Draft
wants to merge 1 commit into
base: 18.0
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions account_custom_duty/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import models
from . import wizard
16 changes: 16 additions & 0 deletions account_custom_duty/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "Custom Duty on Import Export",
"summary": "Manage custom duty on import & export transactions.",
"description": "Provide functionality to calculate custom duties on import and export transactions in the accounting module.",
"category": "Accounting",
"version": "1.0",
"depends": ["accountant", "l10n_in"],
"data": [
"security/ir.model.access.csv",
"views/res_config_settings_views.xml",
"wizard/bill_entry_wizard_view.xml",
"views/account_move_views.xml",
],
"installable": True,
"license": "LGPL-3",
}
4 changes: 4 additions & 0 deletions account_custom_duty/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from . import res_company
from . import res_config_settings
from . import account_move

24 changes: 24 additions & 0 deletions account_custom_duty/models/account_move.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from odoo import _, fields, models
from odoo.exceptions import UserError

class AccountMove(models.Model):
_inherit = 'account.move'

#trace which invoice generated the custom duty journal entry.
custom_duty_journal_entry_id = fields.Many2one('account.move', string='Journal Entry of Custom Duty', readonly=True)

def action_open_bill_of_entry_wizard(self):
self.ensure_one()
if self.state != 'posted' or self.l10n_in_gst_treatment not in ['overseas', 'special_economic_zone', 'deemed_export']:
raise UserError('Action can only be performed on posted moves with GST treatment like overseas, special economic zone, or deemed export .')
return {
'name': 'Bill of Entry',
'type': 'ir.actions.act_window',
'view_mode': 'form',
'res_model': 'bill.entry.wizard',
'view_id': self.env.ref('account_custom_duty.bill_entry_wizard_view_form').id,
'target': 'new',
'context': {
'move_id': self.id
},
}
12 changes: 12 additions & 0 deletions account_custom_duty/models/res_company.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from odoo import fields, models

class ResCompany(models.Model):
_inherit = 'res.company'

is_import_export = fields.Boolean(string="Enable Import-Export Settings", store=True)
account_import_journal_id = fields.Many2one('account.journal', string="Default Import Journal")
account_import_custom_duty_account_id = fields.Many2one('account.account', string="Default Import Custom Duty Account")
account_import_tax_account_id = fields.Many2one('account.account', string="Default Import Tax Account")
account_export_journal_id = fields.Many2one('account.journal', string="Default Export Journal")
account_export_custom_duty_account_id = fields.Many2one('account.account', string="Default Export Custom Duty Account")
account_export_tax_account_id = fields.Many2one('account.account', string="Default Export Tax Account")
42 changes: 42 additions & 0 deletions account_custom_duty/models/res_config_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from odoo import fields, models

class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'

is_import_export = fields.Boolean(string="Enable Import-Export Settings", company_dependent=True, store=True)
account_import_journal_id = fields.Many2one(
'account.journal',
string="Default Import Journal",
related='company_id.account_import_journal_id',
readonly=False
)
account_import_custom_duty_account_id = fields.Many2one(
'account.account',
string="Default Import Custom Duty Account",
related='company_id.account_import_custom_duty_account_id',
readonly=False
)
account_import_tax_account_id = fields.Many2one(
'account.account',
string="Default Import Tax Account",
related='company_id.account_import_tax_account_id',
readonly=False
)
account_export_journal_id = fields.Many2one(
'account.journal',
string="Default Export Journal",
related='company_id.account_export_journal_id',
readonly=False
)
account_export_custom_duty_account_id = fields.Many2one(
'account.account',
string="Default Export Custom Duty Account",
related='company_id.account_export_custom_duty_account_id',
readonly=False
)
account_export_tax_account_id = fields.Many2one(
'account.account',
string="Default Export Tax Account",
related='company_id.account_export_tax_account_id',
readonly=False
)
3 changes: 3 additions & 0 deletions account_custom_duty/security/ir.model.access.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_bill_entry_wizard,access_bill_entry_wizard,model_bill_entry_wizard,account.group_account_user,1,1,1,1
access_bill_entry_details_wizard,access_bill_entry_details_wizard,model_bill_entry_details_wizard,account.group_account_user,1,1,1,1
28 changes: 28 additions & 0 deletions account_custom_duty/views/account_move_views.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="account_custom_duty_view_move_form" model="ir.ui.view">
<field name="name">account.custom.duty.view.move.form</field>
<field name="model">account.move</field>
<field name="inherit_id" ref="account.view_move_form" />
<field name="arch" type="xml">
<xpath expr="//form//button[@name='button_draft']" position="after">
<button name="action_open_bill_of_entry_wizard"
type="object"
class="oe_highlight"
string="Bill of Entry"
invisible="state != 'posted' or l10n_in_gst_treatment not in ['overseas','special_economic_zone','deemed_export'] or move_type != 'in_invoice'"
icon="fa-download"
/>
</xpath>
<xpath expr="//form/sheet/div[@name='button_box']/button" position="after">
<button type="action" class="oe_stat_button"
invisible="not custom_duty_journal_entry_id"
name="account.action_move_journal_line"
context="{'search_default_ref' : name}"
icon="fa-book">
<span name='journal_entries' widget='statinfo'>Journal Entry</span>
</button>
</xpath>
</field>
</record>
</odoo>
91 changes: 91 additions & 0 deletions account_custom_duty/views/res_config_settings_views.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<odoo>
<record id="res_config_settings_view_form" model="ir.ui.view">
<field name="name">res.config.settings.view.form.inherit.account.import.export.duty</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="account.res_config_settings_view_form" />
<field name="arch" type="xml">
<xpath expr="//block[@id='india_localization']" position="inside">

<setting name="enable_import_export"
string="Import-Export Settings"
invisible="country_code != 'IN'"
help="Enable this to feature to apply custom duty on import/export transactions, including Bill of Entry and Shipping Bills."
company_dependent="1">
<field name="is_import_export" class="oe_inline" widget="checkbox" string="Import-Export"/>
</setting>

<setting string="Import" invisible="not is_import_export">
<div class="content-group">
<div class="row mt8">
<label for="account_import_journal_id" class="col-lg-5 o_light_label"
string="Journal" />
<field name="account_import_journal_id"
domain="[('type', '=', 'general'), ('active', '=', True)]"
/>
</div>
<div class="row mt8">
<label for="account_import_custom_duty_account_id"
class="col-lg-5 o_light_label"
string="Custom Duty Account" />
<field name="account_import_custom_duty_account_id"
domain="[('account_type', 'like', 'expense'), ('deprecated', '=', False)]"
/>
</div>
<div class="row mt8">
<label for="account_import_tax_account_id"
class="col-lg-5 o_light_label"
string="Default Tax Account" />
<field name="account_import_tax_account_id"
domain="[
'|',
('account_type', 'like', 'asset'),
('account_type', 'like', 'liability'),
('reconcile', '=', True),
('deprecated', '=', False)
]"
/>
</div>
</div>
</setting>
<setting string="Export" invisible="not is_import_export">
<div class="content-group">
<div class="row mt8">
<label for="account_export_journal_id" class="col-lg-5 o_light_label"
string="Journal" />
<field name="account_export_journal_id"
domain="[('type', '=', 'general'), ('active', '=', True)]"
/>
</div>
<div class="row mt8">
<label for="account_export_custom_duty_account_id"
class="col-lg-5 o_light_label"
string="Custom Duty Account" />
<field name="account_export_custom_duty_account_id"
domain="[
'|',
('account_type', 'like', 'income'),
('account_type', 'like', 'expense'),
('deprecated', '=', False)
]"
/>
</div>
<div class="row mt8">
<label for="account_export_tax_account_id"
class="col-lg-5 o_light_label"
string="Default Tax Account" />
<field name="account_export_tax_account_id"
domain="[
'|',
('account_type', 'like', 'asset'),
('account_type', 'like', 'liability'),
('reconcile', '=', True),
('deprecated', '=', False)
]"
/>
</div>
</div>
</setting>
</xpath>
</field>
</record>
</odoo>
2 changes: 2 additions & 0 deletions account_custom_duty/wizard/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import bill_entry_wizard
from . import bill_entry_details_wizard
46 changes: 46 additions & 0 deletions account_custom_duty/wizard/bill_entry_details_wizard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from odoo import api, fields, models
from odoo.exceptions import ValidationError


class BillEntryDetailsWizard(models.TransientModel):
_name = 'bill.entry.details.wizard'
_description = 'Bill Entry Details Wizard'

currency_id = fields.Many2one('res.currency', string='Currency', default=lambda self: self.env.company.currency_id)
wizard_id = fields.Many2one('bill.entry.wizard', string="Wizard Reference", ondelete='cascade')
move_line_id = fields.Many2one('account.move.line', string='Move Line', required=True)

product_id = fields.Many2one('product.product', string='Product', related='move_line_id.product_id')
quantity = fields.Float(string='Quantity', related='move_line_id.quantity')
price_unit = fields.Float(string='Unit Price', related='move_line_id.price_unit')

custom_currency_rate = fields.Monetary(string='Custom Currency Rate', currency_field='currency_id', related='wizard_id.custom_currency_rate')

custom_duty = fields.Monetary(string='Custom Duty & Additional Charges', currency_field='currency_id', default=0.0)
tax_ids = fields.Many2many('account.tax', string='Taxes', domain=[('type_tax_use', '=', 'purchase')])

assessable_value = fields.Monetary(string='Assessable Value', currency_field='currency_id', compute='_compute_assessable_value', default=0.0)
taxable_amount = fields.Monetary(string='Taxable Amount', currency_field='currency_id', compute='_compute_taxable_amount', default=0.0)
tax_amount = fields.Monetary(string='Tax Amount', currency_field='currency_id', compute='_compute_tax_amount', default=0.0)

@api.constrains('custom_duty')
def _check_positive_custom_duty(self):
for record in self:
if record.custom_duty < 0:
raise ValidationError("Custom Duty cannot be a negative amount.")

@api.depends('quantity', 'price_unit', 'wizard_id.custom_currency_rate')
def _compute_assessable_value(self):
for record in self:
record.assessable_value = (record.quantity * record.price_unit * record.wizard_id.custom_currency_rate)

@api.depends('assessable_value', 'custom_duty')
def _compute_taxable_amount(self):
for record in self:
record.taxable_amount = record.assessable_value + record.custom_duty

@api.depends('taxable_amount', 'tax_ids')
def _compute_tax_amount(self):
for record in self:
tax_factor = sum(record.tax_ids.mapped('amount')) / 100 if record.tax_ids else 0.0
record.tax_amount = record.taxable_amount * tax_factor
Loading