Skip to content

Product Claim Documentation

Overview

The Product Claim module (product.claim) manages warranty claims, product defects, and repair processes. It provides a complete workflow for tracking defective products from receipt through repair or replacement, including supplier interactions and warranty management.


Model Information

Model Name: product.claim
Display Name: Claim Bill
Key Fields: N/A

Features

  • ✅ Automated sequence numbering
  • ✅ State workflow management
  • ✅ Warranty tracking
  • ✅ Repair process documentation
  • ✅ Integration with stock pickings
  • ✅ Document and comment attachments

State Workflow

draft → approved → done
       voided
State Description
draft Initial state, claim being prepared
approved Claim approved, processing underway
done Claim completed (repaired/replaced/discarded)
voided Claim cancelled/voided

Key Fields Reference

Header Fields

Field Type Required Description
number Char Auto-generated claim number
date_received Date Date product received for claim
product_id Many2One Defective product (product)
qty Decimal Quantity claimed
contact_id Many2One Customer/supplier contact (contact)
project_id Many2One Associated project (project)
defect Text Description of defect/problem
note Text Additional notes
state Selection Current workflow state

Warranty Fields

Field Type Description
warranty Boolean Whether product is under warranty
warranty_start Date Warranty start date
warranty_end Date Warranty end date
serial_no Char Serial number (deprecated)
lot_id Many2One Lot/Serial number (stock.lot)

Process Fields

Field Type Description
date_sent_sup Date Date sent to supplier
date_received_sup Date Date received from supplier
repair_details Text Repair work description
cause_damage Selection Root cause of damage
repair_process Selection How claim will be handled
action_token Selection Action taken to resolve

Replacement Fields

Field Type Description
repl_product_id Many2One Replacement product (product)
repl_qty Decimal Replacement quantity

Relationship Fields

Field Type Description
pickings One2Many Associated stock pickings
documents One2Many Attached documents (document)
comments One2Many Comments and notes (message)

Cause of Damage Options

Code Description
user Damaged by user
quality Failure due to quality issues
unidentified Unidentified cause

Repair Process Options

Code Description
repair_local Repair locally
send_supplier Send back to supplier
discard Discard (beyond repair)

Action Taken Options

Code Description
replace_new Replaced by new one
replace_used Replaced by used one
replace_charge Replaced / charging to customer
repair_charge Repaired / charging to customer

API Methods

1. Create Claim

Method: create(vals, context)

Creates a new product claim with auto-generated number.

Parameters:

vals = {
    "date_received": "2025-10-27",        # Required: Receipt date
    "product_id": 123,                     # Required: Product ID
    "qty": 1,                              # Required: Quantity
    "contact_id": 456,                     # Required: Customer/supplier
    "defect": "Screen not working",        # Optional: Defect description
    "warranty": True,                      # Optional: Under warranty
    "warranty_start": "2024-01-15",       # Optional: Warranty start
    "warranty_end": "2026-01-15",         # Optional: Warranty end
    "lot_id": 789,                         # Optional: Serial/lot
    "cause_damage": "quality",             # Optional: Damage cause
    "repair_process": "send_supplier",     # Optional: Repair method
    "project_id": 321                      # Optional: Project
}

Returns: int - New record ID

Example:

# Create warranty claim for defective laptop
claim_id = get_model("product.claim").create({
    "date_received": "2025-10-27",
    "product_id": laptop_id,
    "qty": 1,
    "contact_id": customer_id,
    "defect": "Battery not charging, screen flickering",
    "warranty": True,
    "warranty_start": "2024-06-01",
    "warranty_end": "2026-06-01",
    "lot_id": serial_lot_id,
    "cause_damage": "quality",
    "repair_process": "send_supplier"
})


2. Approve Claim

Method: approve(ids, context)

Moves claim from draft to approved state.

Parameters: - ids (list): Claim IDs

Example:

# Approve a claim
get_model("product.claim").approve([claim_id])

# Verify state changed
claim = get_model("product.claim").browse(claim_id)
assert claim.state == "approved"


3. Complete Claim

Method: set_done(ids, context)

Marks claim as completed.

Parameters: - ids (list): Claim IDs

Example:

# Mark as completed after repair/replacement
get_model("product.claim").set_done([claim_id])


4. Void Claim

Method: void(ids, context)

Cancels/voids the claim.

Parameters: - ids (list): Claim IDs

Example:

# Void a claim
get_model("product.claim").void([claim_id])


Search Functions

Search by Product

# Find all claims for a specific product
condition = [["product_id", "=", product_id]]
claims = get_model("product.claim").search(condition)

Search by Contact

# Find all claims from/for a specific customer/supplier
condition = [["contact_id", "=", contact_id]]
claims = get_model("product.claim").search(condition)

Search Warranty Claims

# Find all warranty claims
condition = [["warranty", "=", True]]
claims = get_model("product.claim").search(condition)

Search by Date Range

# Find claims received this month
condition = [
    ["date_received", ">=", "2025-10-01"],
    ["date_received", "<=", "2025-10-31"]
]
claims = get_model("product.claim").search(condition)

Search by Repair Process

# Find claims being sent to supplier
condition = [["repair_process", "=", "send_supplier"]]
claims = get_model("product.claim").search(condition)

Model Relationship Description
product Many2One Defective/claimed product
contact Many2One Customer or supplier
project Many2One Associated project
stock.lot Many2One Serial/lot tracking
stock.picking One2Many Related pickings (returns/replacements)
message One2Many Comments
document One2Many Attachments

Common Use Cases

Use Case 1: Warranty Claim - Send to Supplier

# 1. Create warranty claim
claim_id = get_model("product.claim").create({
    "date_received": "2025-10-27",
    "product_id": product_id,
    "qty": 1,
    "contact_id": customer_id,
    "defect": "Device not powering on",
    "warranty": True,
    "warranty_start": "2024-08-01",
    "warranty_end": "2026-08-01",
    "lot_id": serial_id,
    "cause_damage": "quality",
    "repair_process": "send_supplier"
})

# 2. Approve claim
get_model("product.claim").approve([claim_id])

# 3. Update when sent to supplier
claim = get_model("product.claim").browse(claim_id)
claim.write({"date_sent_sup": "2025-10-28"})

# 4. Update when received from supplier
claim.write({
    "date_received_sup": "2025-11-10",
    "repair_details": "Logic board replaced, tested OK",
    "action_token": "repair_charge"
})

# 5. Complete claim
claim.set_done()

Use Case 2: Non-Warranty Claim - Replace and Charge

# Create non-warranty claim with replacement
claim_id = get_model("product.claim").create({
    "date_received": "2025-10-27",
    "product_id": damaged_product_id,
    "qty": 1,
    "contact_id": customer_id,
    "defect": "Physical damage to casing",
    "warranty": False,  # Out of warranty
    "cause_damage": "user",  # User damaged
    "repair_process": "repair_local",
    "action_token": "replace_charge",  # Will charge customer
    "repl_product_id": replacement_product_id,
    "repl_qty": 1
})

# Approve and process
claim = get_model("product.claim").browse(claim_id)
claim.approve()

# Add repair details
claim.write({
    "repair_details": "Replaced with new unit, customer charged",
    "note": "Invoice #INV-2025-001 issued for replacement"
})

# Complete
claim.set_done()

Use Case 3: Quality Issue - Discard

# Create claim for defective product to discard
claim_id = get_model("product.claim").create({
    "date_received": "2025-10-27",
    "product_id": product_id,
    "qty": 5,
    "contact_id": supplier_id,
    "defect": "Manufacturing defect - multiple units affected",
    "warranty": True,
    "cause_damage": "quality",
    "repair_process": "discard",  # Beyond repair
    "action_token": "replace_new"  # Supplier replaces
})

claim = get_model("product.claim").browse(claim_id)
claim.approve()

# Document disposal
claim.write({
    "repair_details": "5 units discarded due to manufacturing defect",
    "note": "Supplier issued replacement order #PO-REP-001"
})

claim.set_done()

Best Practices

1. Always Track Serial Numbers for High-Value Items

# Good: Track serial number for warranty validation
claim_vals = {
    "product_id": laptop_id,
    "lot_id": serial_lot_id,  # ✅ Can verify warranty
    "warranty": True,
    "warranty_start": "2024-01-01",
    "warranty_end": "2026-01-01"
}

# Bad: No serial tracking
claim_vals = {
    "product_id": laptop_id,  # ❌ Cannot verify which unit
    "warranty": True
}

2. Document Repair Process Thoroughly

# Good: Complete documentation
claim.write({
    "date_sent_sup": "2025-10-28",
    "date_received_sup": "2025-11-10",
    "repair_details": "Motherboard replaced (Part #MB-12345). "
                     "Tested all functions. Firmware updated to v2.1.",
    "action_token": "repair_charge"
})  # ✅ Clear audit trail

# Bad: Minimal documentation
claim.write({
    "repair_details": "Fixed"  # ❌ No useful information
})

3. Use Proper Cause and Action Codes

# Good: Accurate classification
if user_caused:
    cause = "user"
    action = "replace_charge"  # ✅ Customer pays
elif quality_issue and under_warranty:
    cause = "quality"
    action = "replace_new"  # ✅ Supplier covers

# Bad: Inconsistent logic
cause = "user"
action = "replace_new"  # ❌ Why give free replacement for user damage?

Reporting Examples

Report: Open Claims by Status

def get_open_claims_report():
    """Get all open claims organized by repair process"""

    claims = get_model("product.claim").search_browse([
        ["state", "in", ["draft", "approved"]]
    ])

    report = {
        "repair_local": [],
        "send_supplier": [],
        "discard": []
    }

    for claim in claims:
        process = claim.repair_process or "unassigned"
        if process not in report:
            report[process] = []

        report[process].append({
            "number": claim.number,
            "product": claim.product_id.name,
            "customer": claim.contact_id.name,
            "received": claim.date_received,
            "warranty": "Yes" if claim.warranty else "No",
            "defect": claim.defect
        })

    return report

# Usage
report = get_open_claims_report()
print(f"Local Repairs: {len(report['repair_local'])}")
print(f"Supplier Returns: {len(report['send_supplier'])}")
print(f"To Discard: {len(report['discard'])}")

Report: Warranty Analysis

def get_warranty_analysis(start_date, end_date):
    """Analyze warranty vs non-warranty claims"""

    claims = get_model("product.claim").search_browse([
        ["date_received", ">=", start_date],
        ["date_received", "<=", end_date]
    ])

    warranty_count = 0
    non_warranty_count = 0
    warranty_products = {}

    for claim in claims:
        if claim.warranty:
            warranty_count += 1
            prod_name = claim.product_id.name
            warranty_products[prod_name] = warranty_products.get(prod_name, 0) + 1
        else:
            non_warranty_count += 1

    return {
        "total_claims": len(claims),
        "warranty_claims": warranty_count,
        "non_warranty_claims": non_warranty_count,
        "warranty_rate": warranty_count / len(claims) if claims else 0,
        "top_warranty_products": sorted(
            warranty_products.items(),
            key=lambda x: x[1],
            reverse=True
        )[:10]
    }

# Usage
analysis = get_warranty_analysis("2025-01-01", "2025-10-27")
print(f"Warranty Rate: {analysis['warranty_rate']:.1%}")
print("Top Products with Warranty Claims:")
for prod, count in analysis['top_warranty_products']:
    print(f"  {prod}: {count} claims")

Performance Tips

1. Index on Search Fields

  • The product_id, contact_id, project_id, and date_received fields are indexed with search=True
  • Use these in search conditions for better performance

2. Batch Operations

# Efficient: Bulk update multiple claims
claim_ids = get_model("product.claim").search([
    ["state", "=", "approved"],
    ["repair_process", "=", "repair_local"]
])

for claim_id in claim_ids:
    # Process in batch
    pass

Troubleshooting

Claim number not generating

Cause: Missing sequence configuration
Solution: Ensure "claim" sequence type exists in system

Cannot track warranty period effectively

Cause: Warranty dates not set on product or claim
Solution: Always populate warranty_start and warranty_end fields


Version History

Last Updated: 2025-10-27
Model Version: product_claim.py
Framework: Netforce


Additional Resources

  • Product Documentation: product
  • Contact Documentation: contact
  • Stock Lot Documentation: stock.lot
  • Project Documentation: project

This documentation is generated for developer onboarding and reference purposes.