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¶
| 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:
4. Void Claim¶
Method: void(ids, context)
Cancels/voids the claim.
Parameters:
- ids (list): Claim IDs
Example:
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)
Related Models¶
| 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, anddate_receivedfields are indexed withsearch=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.