Skip to content

Commit

Permalink
[IMP] installments: inplement new feature in the module
Browse files Browse the repository at this point in the history
- Implemented cron job functionality in installments_cron.py
- Implemented  configuration settings in res_config_settings.py
- Managed installment-related documents in installments_documents.py
- Created XML views for installments and settings in installments_view.xml and
  res_config_setting_view.xml
  • Loading branch information
pkgu-odoo committed Sep 23, 2024
1 parent 3305815 commit 41b15c2
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 4 deletions.
3 changes: 2 additions & 1 deletion installments/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
'version': '1.0',
'category': 'Sales',
'author': 'odoo',
'depends': ['base', 'sale_subscription'],
'depends': ['base', 'sale_subscription', 'documents'],
'data': [
'security/ir.model.access.csv',
'wizard/action_open_emi_wizard_view.xml',
'data/installments_cron.xml',
'data/installments_product_data.xml',
'view/res_config_setting_view.xml',
'view/installments_view.xml'
Expand Down
12 changes: 12 additions & 0 deletions installments/data/installments_cron.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<odoo>
<record id="installment_penalty_scheduled_action" model="ir.cron">
<field name="name">Installment Penalty Scheduler</field>
<field name="model_id" ref="model_sale_order"/>
<field name="state">code</field>
<field name="code">model.schedule_penalty_invoices()</field>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="active" eval="True"/>
</record>
</odoo>
4 changes: 4 additions & 0 deletions installments/data/installments_product_data.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,8 @@
<record id="emi_product" model="product.product">
<field name="name">Monthly EMI</field>
</record>

<record id="product3" model="product.product">
<field name="name">Fine</field>
</record>
</odoo>
2 changes: 2 additions & 0 deletions installments/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
from . import res_config_settings
from . import installments_cron
from . import installments_documents
31 changes: 31 additions & 0 deletions installments/models/installments_cron.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from odoo import models, fields
from datetime import timedelta, datetime


class SaleOrder(models.Model):
_inherit = 'sale.order'

installment_amount = fields.Integer(string="Installment Amount")
is_installable = fields.Boolean(default=False)

def schedule_penalty_invoices(self):
unpaid_orders = self.search([('is_installable', '!=', False)])
for order in unpaid_orders:
penalty_percentage = self.env['ir.config_parameter'].get_param('installments.delay_penalty_perc', default=0)
penalty_days = int(self.env['ir.config_parameter'].get_param('installments.delay_penalty_process', default=0))
last_payment_date = max(order.invoice_ids.mapped('invoice_date')) if order.invoice_ids else order.date_order.date()
if datetime.now().date() == last_payment_date + timedelta(days=penalty_days):
penalty_amount = int(order.installment_amount * int(float(penalty_percentage))) / 100
vals_list = {
'move_type': 'out_invoice',
'partner_id': order.partner_id.id,
'invoice_line_ids': [(0, 0, {
'product_id': self.env.ref('installments.emi_product').id,
'quantity': 1,
'price_unit': penalty_amount,
'sale_line_ids': [(fields.Command.set(order.order_line.mapped('id')))]
})],
'invoice_date': fields.Date.today(),
}
invoice = self.env['account.move'].create(vals_list)
invoice.action_post()
89 changes: 89 additions & 0 deletions installments/models/installments_documents.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
from odoo import models


class InstallmentsDocuments(models.Model):
_inherit = 'sale.order'

def create_sale_order_folder(self):
"""
This method is responsible for creating or retrieving the Installments folder and
the specific folder for the sale order. It returns the folder where documents
will be uploaded.
"""
# Get or create the Installments parent folder
installments_folder = self.env["documents.folder"].search(
[("name", "=", "Installments")], limit=1
)
if not installments_folder:
installments_folder = self.env["documents.folder"].create(
{"name": "Installments"}
)
# Define the folder name based on sale order
folder_name = self.name.replace("/", "_")
# Check if a folder for the current sale order exists
folder = self.env["documents.folder"].search(
[
("name", "=", folder_name),
("parent_folder_id", "=", installments_folder.id),
],
limit=1,
)
# If the folder doesn't exist, create it
if not folder:
folder = self.env["documents.folder"].create(
{"name": folder_name, "parent_folder_id": installments_folder.id}
)
return folder

def action_upload_documents(self):
"""
This method retrieves required documents based on the configuration settings,
and uploads placeholders for the required documents in the folder created for the sale order.
"""
config_settings = self.env["ir.config_parameter"]
document_settings = {
"nid": "National ID (NID)",
"bank_statement": "Bank Statement",
"rental_contract": "Rental Contract",
"salary_components": "Salary Components",
"bank_rate_letter": "Bank Rate Letter",
"owernship_contract": "Ownership Contract",
}
# Get the required documents based on the configuration settings
required_documents = [
document_name
for setting_key, document_name in document_settings.items()
if config_settings.get_param(f"installments.{setting_key}", default=False)
]
for order in self:
# Call the function to create or get the folder for the sale order
folder = order.create_sale_order_folder()
# Create document placeholders for the required documents if they don't exist
for doc_name in required_documents:
existing_doc = self.env["documents.document"].search(
[
("folder_id", "=", folder.id),
("name", "=", doc_name),
("res_model", "=", "sale.order"),
("res_id", "=", order.id),
]
)
if not existing_doc:
self.env["documents.document"].create(
{
"name": doc_name,
"folder_id": folder.id,
"partner_id": order.partner_id.id,
"res_model": "sale.order",
"res_id": order.id,
}
)
# Return an action to display the documents in the folder
return {
"type": "ir.actions.act_window",
"name": "Documents",
"res_model": "documents.document",
"view_mode": "kanban,tree,form",
"domain": [("folder_id", "=", folder.id)],
"context": {"folder_id": folder.id},
}
8 changes: 7 additions & 1 deletion installments/view/installments_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='so_button_below_order_lines']" position="inside">
<xpath expr="//button[@name='action_open_discount_wizard']" position="before">
<button string="Add EMI"
name="%(installments.action_open_emi_wizard)d"
type="action"
class="btn btn-primary"/>
</xpath>
<xpath expr="//div[@name='button_box']" position="inside">
<button class="btn oe_stat_button btn-outline-secondary flex-grow-1 flex-lg-grow-0" name="action_upload_documents" type="object">
<i class="o_button_icon fa fa-fw fa-file-pdf-o"></i>
<span class="o_stat_text">Upload Documents</span>
</button>
</xpath>
</field>
</record>
</odoo>
6 changes: 4 additions & 2 deletions installments/wizard/action_open_emi_wizard.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,15 @@ def add_installment(self):
'product_id': self.env.ref('installments.installment_product').id,
'order_id': self.env.context.get('active_id'),
'name': "Installment",
'product_uom_qty' : 1,
'product_uom_qty': 1,
'price_unit': self.installment_amount
}, {
'product_id': self.env.ref('installments.emi_product').id,
'order_id': self.env.context.get('active_id'),
'name': "Monthly EMI",
'product_uom_qty' : 4,
'product_uom_qty': 4,
'price_unit': -(self.installment_amount)
}]
self.env['sale.order.line'].create(move_vals)
self.env['sale.order'].browse(self.env.context.get('active_id')).is_installable = True
self.env['sale.order'].browse(self.env.context.get('active_id')).installment_amount = self.installment_amount

0 comments on commit 41b15c2

Please sign in to comment.