I have a rental object in Odoo 15.2, and I'm trying to create an invoice for a rental order programmatically using XML-RPC. I can see a "Create Invoice" button at the top, and when I hover over it, it displays the following information:
Object: sale.order, Modifiers: {"invisible":[["invoice_status","="to invoice"]]}, Button type: action, Action ID: 296
Is there a way to create an invoice using XML-RPC just like we can validate the invoice with the execute_kw method for purchase orders as shown below?
# To validate a purchase order
execute_kw('purchase.order', 'button_confirm', [purchase_order_id])
# What should I use to create an invoice for a sale order with Odoo XML-RPC?
execute_kw('account.invoice', '???????', [purchase_order_id])
I'm looking for guidance on how to create invoices for rental orders in Odoo 15.2 using XML-RPC and what specific method or action to call for this purpose. Any help would be greatly appreciated!
EDIT
For people who are googling, I've achieved what I want using the below code. Hope this helps the community. I'm using this for Odoo 17 (SAAS)
@app.route('/createInvoice', methods=['POST'])
def createInvoice():
try:
models = xmlrpc.client.ServerProxy('{}/xmlrpc/2/object'.format(url))
data = request.get_json()
if not data:
return jsonify({'message': 'No data received.'}), 400
sale_order_id = int(data.get('sale_order_id'))
product_id = int(data.get('product_variant_id'))
if not sale_order_id or not product_id:
return jsonify({'message': 'Invalid input data.'}), 400
# Fetch data related to the sale order
sale_order_data = models.execute_kw(db, uid, password, 'sale.order', 'read',
[sale_order_id],
{'fields': ['partner_id', 'invoice_status', 'name', 'order_line', 'picking_ids']})
if not sale_order_data:
return jsonify({'message': 'Sale order not found.'}), 404
invoice_id = None
# Iterate through each picking related to the sale order
for picking_line in sale_order_data[0].get('picking_ids', []):
picking_line_data = models.execute_kw(db, uid, password, 'stock.picking', 'search_read',
[[['id', '=', int(picking_line)],['product_id','=', int(product_id)]]], {})
# If picking data is found
if picking_line_data:
stock_picking_validate = models.execute_kw(db, uid, password, 'stock.picking', 'button_validate', [[picking_line]])
# Iterate through each line of the sale order
for lineId in sale_order_data[0].get('order_line', []):
sale_order_line = models.execute_kw(db, uid, password, 'sale.order.line', 'search_read',
[[["id", "=", lineId],['product_id','=', product_id]]], {})
if sale_order_line:
# Generate invoice for the sale order line
current_date = datetime.now().strftime('%Y-%m-%d')
context = {
'move_type': 'out_invoice',
'partner_id': sale_order_data[0]['partner_id'][0],
'invoice_origin': sale_order_data[0]['name'],
'invoice_date': current_date,
'partner_bank_id': 164, #Keep your bank ID
'l10n_in_gst_treatment': 'consumer', #Keep your GST treatment (Consumer or Supplier)
'ref': '',
'l10n_in_type_id': 1, #Eway Bill Document type - ID
'l10n_in_mode': '1', #Mode Of Transport - ID
'l10n_in_distance': 11, #Distance travelled by vehicle
'l10n_in_vehicle_type': 'R', #Vehicle Type - Char
'l10n_in_vehicle_no': 'AP00AA0000' #Vehicle Number - Char
}
# Create invoice in the system
invoice_id = models.execute_kw(db, uid, password, 'account.move', 'create', [context])
invoice_lines = []
# Populate invoice lines
for lineId in sale_order_data[0].get('order_line', []):
sale_order_line = models.execute_kw(db, uid, password, 'sale.order.line', 'read', [lineId], {})
invoice_lines.append((0, 0, {
'move_id': int(invoice_id),
'product_id': int(sale_order_line[0]['product_id'][0]),
'quantity': float(sale_order_line[0]['product_uom_qty']),
'price_unit': float(sale_order_line[0]['price_unit']),
'name': sale_order_line[0]['name']
}))
# Write invoice lines to the invoice
models.execute_kw(db, uid, password, 'account.move', 'write', [invoice_id, {'invoice_line_ids': invoice_lines}])
# Post the invoice
models.execute_kw(db, uid, password, 'account.move', 'action_post', [invoice_id])
# Find the invoice line ID
inv_line_id = models.execute_kw(db, uid, password, 'account.move.line', 'search',
[[['product_id', '=', sale_order_line[0]['product_id'][0]],
['move_id', '=', invoice_id],
['quantity', '=', sale_order_line[0]['product_uom_qty']]]])
# Update sale order line with invoice line and invoice status
models.execute_kw(db, uid, password, 'sale.order.line', 'write',
[lineId, {'invoice_lines': [(4, inv_line_id[0])], 'invoice_status': 'invoiced'}])
# Update sale order with invoice ID and invoice status
models.execute_kw(db, uid, password, 'sale.order', 'write',
[[sale_order_id], {'invoice_ids': [(4, invoice_id)], 'invoice_status': 'invoiced'}])
# Return response based on whether invoice was created or not
if invoice_id:
return jsonify({'invoice_id': invoice_id, 'message':'Invoice created successfully.'}), 200
else:
return jsonify({'message': 'No invoice created for the given conditions.'}), 200
# If no invoice was created
return jsonify({'message': 'No invoice created.'}), 404
except Exception as e:
print(f"An error occurred: {e}")
return jsonify({'message': 'An error occurred while processing the request.'}), 500