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")