Product Borrow Documentation¶
Overview¶
The Product Borrow module (product.borrow) manages the lending of inventory items to employees or projects. It provides a complete workflow for borrowing requests, item issuance, return tracking, and overdue monitoring. This module is essential for organizations that lend equipment, tools, or materials to employees.
Model Information¶
Model Name: product.borrow
Display Name: Borrow Request
Name Field: number
Key Fields: N/A
Features¶
- ✅ Automated sequence numbering
- ✅ State workflow management
- ✅ Overdue tracking
- ✅ Return tracking
- ✅ Integration with stock movements
- ✅ Document and comment attachments
State Workflow¶
| State | Description |
|---|---|
draft |
Initial state, request being prepared |
approved |
Request approved, ready for issuance |
done |
All items issued and returned, completed |
voided |
Request cancelled/voided |
Key Fields Reference¶
Header Fields¶
| Field | Type | Required | Description |
|---|---|---|---|
number |
Char | ✅ | Auto-generated borrow request number |
date |
Date | ✅ | Request date |
employee_id |
Many2One | ✅ | Employee borrowing items (hr.employee) |
project_id |
Many2One | ❌ | Associated project (project) |
borrow_for |
Char | ✅ | Purpose/reason for borrowing |
due_date |
Date | ✅ | Expected return date |
notes |
Text | ❌ | Additional notes or comments |
state |
Selection | ✅ | Current workflow state |
Computed Fields¶
| Field | Type | Description |
|---|---|---|
is_overdue |
Boolean | True if past due date and state is "approved" |
is_return_item |
Boolean | True if all borrowed items fully returned |
pickings |
Many2Many | Associated stock pickings (computed from stock_moves) |
Relationship Fields¶
| Field | Type | Description |
|---|---|---|
lines |
One2Many | Borrowed item lines (product.borrow.line) |
stock_moves |
One2Many | Stock movements for borrow/return |
comments |
One2Many | Comments and notes (message) |
documents |
One2Many | Attached documents (document) |
API Methods¶
1. Create Borrow Request¶
Method: create(vals, context)
Creates a new borrow request with auto-generated number.
Parameters:
vals = {
"date": "2025-10-27", # Required: Request date
"employee_id": 123, # Required: Employee ID
"borrow_for": "Field work equipment", # Required: Purpose
"due_date": "2025-11-10", # Required: Return date
"project_id": 456, # Optional: Project
"notes": "Handle with care", # Optional: Notes
"lines": [ # Optional: Items
("create", {
"product_id": 789,
"qty": 2,
"uom_id": 1,
"lot_id": 101
})
]
}
Returns: int - New record ID
Example:
# Create borrow request for tools
borrow_id = get_model("product.borrow").create({
"date": "2025-10-27",
"employee_id": employee_id,
"borrow_for": "Construction site tools",
"due_date": "2025-11-15",
"project_id": project_id,
"lines": [
("create", {
"product_id": drill_id,
"qty": 1,
"uom_id": unit_id
}),
("create", {
"product_id": hammer_id,
"qty": 2,
"uom_id": unit_id
})
]
})
2. Approve Borrow Request¶
Method: approve(ids, context)
Moves request from draft to approved state.
Example:
3. Complete Borrow Request¶
Method: set_done(ids, context)
Marks request as completed when all items returned.
Example:
4. Void Borrow Request¶
Method: void(ids, context)
Cancels/voids the borrow request.
Example:
5. Copy to Goods Issue Picking¶
Method: copy_to_picking(ids, context)
Creates a goods issue (outbound) picking for borrowing items.
Returns: Dictionary with navigation and flash message
Example:
result = get_model("product.borrow").copy_to_picking([borrow_id])
# Returns picking_id and navigation info
6. Copy to Goods Receipt Picking¶
Method: copy_to_pick_in(ids, context)
Creates a goods receipt (inbound) picking for returning items.
Example:
7. Delete Borrow Request¶
Method: delete(ids, context)
Deletes borrow request with validation.
Validation:
- Can only delete requests in draft state
- Cannot delete if stock moves exist
Computed Fields Functions¶
get_overdue(ids, context)¶
Returns True if due date is past and state is "approved".
get_return_item(ids, context)¶
Returns True if all borrowed items have been fully returned.
get_pickings(ids, context)¶
Returns list of unique picking IDs from stock moves.
Configuration Settings¶
Required Settings¶
| Setting | Location | Description |
|---|---|---|
product_borrow_journal_id |
settings (ID:1) | Journal for borrow transactions |
The journal must have:
- location_from_id: Source location (warehouse)
- location_to_id: Destination location (employee/temp)
Setup Example:
settings = get_model("settings").browse(1)
settings.write({
"product_borrow_journal_id": journal_id
})
journal = get_model("stock.journal").browse(journal_id)
journal.write({
"location_from_id": warehouse_loc_id,
"location_to_id": temp_loc_id
})
Related Models¶
| Model | Relationship | Description |
|---|---|---|
product.borrow.line |
One2Many | Borrow line items |
hr.employee |
Many2One | Employee borrowing items |
project |
Many2One | Associated project |
stock.picking |
Related | Goods issue/receipt pickings |
stock.move |
One2Many | Stock movements |
message |
One2Many | Comments |
document |
One2Many | Attachments |
Common Use Cases¶
Use Case 1: Complete Borrow and Return Workflow¶
# 1. Create borrow request
borrow_id = get_model("product.borrow").create({
"date": "2025-10-27",
"employee_id": employee_id,
"borrow_for": "Field equipment",
"due_date": "2025-11-10",
"lines": [
("create", {
"product_id": laptop_id,
"qty": 1,
"uom_id": unit_id
})
]
})
# 2. Approve request
get_model("product.borrow").approve([borrow_id])
# 3. Issue items
result = get_model("product.borrow").copy_to_picking([borrow_id])
pick = get_model("stock.picking").browse(result["picking_id"])
pick.set_done()
# 4. Return items
result = get_model("product.borrow").copy_to_pick_in([borrow_id])
return_pick = get_model("stock.picking").browse(result["picking_id"])
return_pick.set_done()
# 5. Complete borrow
get_model("product.borrow").set_done([borrow_id])
Use Case 2: Track Overdue Borrows¶
import time
current_date = time.strftime("%Y-%m-%d")
# Get approved borrows past due date
overdue_ids = get_model("product.borrow").search([
["state", "=", "approved"],
["due_date", "<", current_date]
])
for borrow in get_model("product.borrow").browse(overdue_ids):
print(f"Overdue: {borrow.number}")
print(f" Employee: {borrow.employee_id.name}")
print(f" Due: {borrow.due_date}")
for line in borrow.lines:
outstanding = line.issued_qty - line.returned_qty
if outstanding > 0:
print(f" - {line.product_id.name}: {outstanding} units")
Best Practices¶
1. Set Realistic Due Dates¶
from datetime import datetime, timedelta
due_date = (datetime.now() + timedelta(days=14)).strftime("%Y-%m-%d")
borrow_vals = {
"due_date": due_date, # ✅ 2 weeks from now
}
2. Track Serial Numbers for High-Value Items¶
borrow_lines = [
("create", {
"product_id": laptop_id,
"qty": 1,
"uom_id": unit_id,
"lot_id": serial_number_id # ✅ Track exact unit
})
]
3. Use Projects for Better Tracking¶
borrow_vals = {
"employee_id": employee_id,
"project_id": project_id, # ✅ Track by project
"borrow_for": "Project XYZ equipment",
}
Troubleshooting¶
"Missing borrow request journal in Inventory Setting"¶
Cause: product_borrow_journal_id not configured
Solution: Configure journal in settings
"Missing 'Location From' for journal"¶
Cause: Journal doesn't have source location
Solution: Set location_from_id on journal
"Can not delete borrow request"¶
Cause: Wrong state or stock moves exist
Solution: Only delete draft requests without moves
Version History¶
Last Updated: 2025-10-27
Model Version: product_borrow.py
Framework: Netforce
Additional Resources¶
- Product Borrow Line Documentation:
product.borrow.line - HR Employee Documentation:
hr.employee - Stock Picking Documentation:
stock.picking
This documentation is generated for developer onboarding and reference purposes.