f2364cf10f
vendor payment and email
253 lines
8.1 KiB
Python
253 lines
8.1 KiB
Python
from odoo import api, fields, models, _
|
||
from odoo.exceptions import UserError
|
||
|
||
class WarrantyClaim(models.Model):
|
||
_name = "bec.warranty.claim"
|
||
_description = "Warranty Claim"
|
||
_inherit = ["mail.thread", "mail.activity.mixin"]
|
||
_order = "create_date desc"
|
||
|
||
name = fields.Char("Claim Reference", required=True, copy=False, default="New", tracking=True)
|
||
install_date = fields.Date("Date of Install")
|
||
failure_date = fields.Date("Date of Failure")
|
||
resolution_type = fields.Selection(
|
||
[
|
||
("credit", "Credit"),
|
||
("replacement", "Replacement"),
|
||
],
|
||
string="Requested Resolution",
|
||
)
|
||
# Link to the customer and various parties
|
||
partner_id = fields.Many2one("res.partner", string="Customer", tracking=True)
|
||
manufacturer_id = fields.Many2one("warranty.manufacturer", string="Manufacturer")
|
||
true_vendor_id = fields.Many2one(
|
||
"res.partner",
|
||
string="True Vendor",
|
||
domain="[('supplier_rank', '>', 0)]",
|
||
tracking=True,
|
||
)
|
||
extra_recipient_ids = fields.Many2many(
|
||
"res.partner",
|
||
string="Additional Email Recipients",
|
||
help="Separate recipients you want CC'd on the warranty email.",
|
||
)
|
||
|
||
# Link to sales and invoices
|
||
sale_order_id = fields.Many2one("sale.order", string="Sales Order", tracking=True)
|
||
original_sale_order_id = fields.Many2one("sale.order", string="Original Sales Order")
|
||
|
||
# Customer invoices to attach
|
||
invoice_customer_ids = fields.Many2many(
|
||
"account.move",
|
||
"warranty_claim_customer_invoice_rel",
|
||
"claim_id", "move_id",
|
||
string="Customer Invoices",
|
||
domain="[('move_type', 'in', ('out_invoice', 'out_refund'))]",
|
||
)
|
||
|
||
# Vendor invoices to attach
|
||
invoice_vendor_ids = fields.Many2many(
|
||
"account.move",
|
||
"warranty_claim_vendor_invoice_rel",
|
||
"claim_id", "move_id",
|
||
string="Vendor Invoices",
|
||
domain="[('move_type', 'in', ('in_invoice', 'in_refund'))]",
|
||
)
|
||
|
||
# Technical / product fields
|
||
line_ids = fields.One2many(
|
||
"bec.warranty.claim.line",
|
||
"claim_id",
|
||
string="Claim Lines",
|
||
)
|
||
|
||
# customer credit (customer credit note / refund)
|
||
# customer_credit_id = fields.Many2one(
|
||
# 'account.move',
|
||
# string="Customer Credit",
|
||
# domain=[('move_type', '=', 'out_refund')],
|
||
# tracking=True,
|
||
# )
|
||
product_id = fields.Many2one("product.product", string="Product")
|
||
model = fields.Char("Model")
|
||
serial_number = fields.Char("Serial Number")
|
||
failure = fields.Text("Failure Description")
|
||
warranty_type = fields.Selection(
|
||
[
|
||
("90_day", "90 Day Warranty"),
|
||
("cabinet", "Cabinet Warranty"),
|
||
("compressor", "Compressor Warranty"),
|
||
("other", "Other"),
|
||
],
|
||
string="Warranty Type",
|
||
)
|
||
claim_date = fields.Date("Claim Date", default=fields.Date.context_today)
|
||
state = fields.Selection(
|
||
[
|
||
("draft", "Draft"),
|
||
("sent", "Sent to Vendor"),
|
||
("approved", "Approved"),
|
||
("rejected", "Rejected"),
|
||
("done", "Done"),
|
||
],
|
||
string="Status",
|
||
default="draft",
|
||
tracking=True,
|
||
)
|
||
|
||
company_id = fields.Many2one(
|
||
"res.company",
|
||
string="Company",
|
||
default=lambda self: self.env.company,
|
||
required=True,
|
||
)
|
||
compressor_tag_image = fields.Binary(
|
||
string="Compressor Tag Photo",
|
||
attachment=True,
|
||
help="Photo of the compressor nameplate/tag required for compressor warranty claims.",
|
||
)
|
||
@api.constrains("warranty_type", "compressor_tag_image")
|
||
def _check_compressor_tag_image_required(self):
|
||
for claim in self:
|
||
# adjust 'compressor' to your actual selection key
|
||
if claim.warranty_type == "compressor" and not claim.compressor_tag_image:
|
||
raise ValidationError(
|
||
_("A compressor tag photo is required for compressor warranty claims.")
|
||
)
|
||
|
||
currency_id = fields.Many2one(
|
||
"res.currency",
|
||
string="Currency",
|
||
related="company_id.currency_id",
|
||
store=True,
|
||
readonly=True,
|
||
)
|
||
|
||
vendor_move_id = fields.Many2one(
|
||
"account.move",
|
||
string="Vendor Credit / Invoice",
|
||
help="Vendor credit note or invoice used to reimburse this warranty claim.",
|
||
)
|
||
|
||
vendor_move_amount = fields.Monetary(
|
||
string="Vendor Amount",
|
||
currency_field="currency_id",
|
||
compute="_compute_vendor_move_amount",
|
||
store=False,
|
||
)
|
||
|
||
vendor_move_state = fields.Selection(
|
||
related="vendor_move_id.state",
|
||
string="Vendor Doc State",
|
||
readonly=True,
|
||
)
|
||
|
||
|
||
|
||
|
||
@api.depends("vendor_move_id")
|
||
def _compute_vendor_move_amount(self):
|
||
for claim in self:
|
||
claim.vendor_move_amount = claim.vendor_move_id.amount_total if claim.vendor_move_id else 0.0
|
||
|
||
@api.model
|
||
def create(self, vals):
|
||
if vals.get("name", "New") == "New":
|
||
seq = self.env.ref(
|
||
"odoo_warranty_claims.seq_warranty_claim",
|
||
raise_if_not_found=False
|
||
)
|
||
if seq:
|
||
vals["name"] = seq.next_by_id()
|
||
return super().create(vals)
|
||
|
||
def action_send_to_vendor(self):
|
||
"""Open email wizard prefilled with the warranty template."""
|
||
self.ensure_one()
|
||
|
||
# get template (adjust the XML ID if your template id is different)
|
||
template = self.env.ref(
|
||
"warranty_claim.mail_template_warranty_claim_90day",
|
||
raise_if_not_found=False,
|
||
)
|
||
compose_form = self.env.ref(
|
||
"mail.email_compose_message_wizard_form",
|
||
raise_if_not_found=False,
|
||
)
|
||
|
||
# move to Sent state right away (optional – comment this out if you prefer manual)
|
||
self.state = "sent"
|
||
|
||
ctx = {
|
||
"default_model": self._name,
|
||
"default_res_ids": [self.id],
|
||
"default_use_template": bool(template),
|
||
"default_template_id": template.id if template else False,
|
||
"default_composition_mode": "comment",
|
||
"force_email": True,
|
||
}
|
||
|
||
return {
|
||
"name": _("Send Warranty Email"),
|
||
"type": "ir.actions.act_window",
|
||
"res_model": "mail.compose.message",
|
||
"view_mode": "form",
|
||
"views": [(compose_form.id, "form")],
|
||
"target": "new",
|
||
"context": ctx,
|
||
}
|
||
|
||
def action_create_vendor_credit(self):
|
||
self.ensure_one()
|
||
|
||
move = self.env["account.move"].create({
|
||
"move_type": "in_refund",
|
||
"partner_id": self.true_vendor_id.id,
|
||
"invoice_date": fields.Date.today(),
|
||
"invoice_line_ids": [
|
||
(0, 0, {
|
||
"name": f"Warranty Claim {self.name}",
|
||
"quantity": 1,
|
||
"price_unit": self.product_id.standard_price * -1, # or reimburse amount
|
||
"account_id": self.env.company.warranty_expense_account_id.id if hasattr(self.env.company, 'warranty_expense_account_id') else None,
|
||
})
|
||
],
|
||
})
|
||
|
||
self.vendor_credit_id = move.id
|
||
|
||
return {
|
||
"name": "Vendor Credit Note",
|
||
"type": "ir.actions.act_window",
|
||
"res_model": "account.move",
|
||
"view_mode": "form",
|
||
"res_id": move.id,
|
||
"target": "current",
|
||
}
|
||
|
||
class WarrantyClaimLine(models.Model):
|
||
_name = "bec.warranty.claim.line"
|
||
_description = "Warranty Claim Line"
|
||
|
||
claim_id = fields.Many2one(
|
||
"bec.warranty.claim",
|
||
string="Warranty Claim",
|
||
required=True,
|
||
ondelete="cascade",
|
||
)
|
||
sale_line_id = fields.Many2one(
|
||
"sale.order.line",
|
||
string="Sales Order Line",
|
||
)
|
||
product_id = fields.Many2one(
|
||
"product.product",
|
||
string="Product",
|
||
required=True,
|
||
)
|
||
quantity = fields.Float(
|
||
string="Quantity",
|
||
default=1.0,
|
||
)
|
||
model = fields.Char("Model")
|
||
serial_number = fields.Char("Serial Number")
|
||
failure = fields.Text("Failure Description") |