Yes. We only came up with a “dirty” method, hard-coding the automatic creation. Our server script looks like this:
sales_order = doc
#Sales Invoice
sales_invoice = frappe.get_doc({
"doctype": "Sales Invoice",
#"title": sales_order.title if sales_order.title else "{customer_name}",
"customer": sales_order.customer,
"customer_name": sales_order.customer.customer_name,
#"amended_from": sales_order.amended_from,
"company": sales_order.company,
"po_no": sales_order.po_no,
"po_date": sales_order.po_date,
"tax_id": sales_order.customer.tax_id,
"customer_address": sales_order.customer_address,
"address_display": sales_order.address_display,
"contact_person": sales_order.contact_person,
"contact_display": sales_order.contact_display,
"contact_mobile": sales_order.contact_mobile,
"contact_email": sales_order.contact_email,
"company_address": sales_order.company_address,
"company_address_display": sales_order.company_address_display,
"shipping_address_name": sales_order.shipping_address_name,
"shipping_address": sales_order.shipping_address,
"dispatch_address_name": sales_order.dispatch_address_name,
"dispatch_address": sales_order.dispatch_address,
"customer_group": sales_order.customer_group,
"territory": sales_order.territory,
"currency": sales_order.currency,
"conversion_rate": sales_order.conversion_rate,
"selling_price_list": sales_order.selling_price_list,
"price_list_currency": sales_order.price_list_currency,
"plc_conversion_rate": sales_order.plc_conversion_rate,
"ignore_pricing_rule": sales_order.ignore_pricing_rule if sales_order.ignore_pricing_rule else "0",
"set_warehouse": sales_order.set_warehouse,
"scan_barcode": sales_order.scan_barcode,
"posa_notes": sales_order.posa_notes,
"total_qty": sales_order.total_qty,
"base_total": sales_order.base_total,
"base_net_total": sales_order.base_net_total,
"total_net_weight": sales_order.total_net_weight,
"total": sales_order.total,
"net_total": sales_order.net_total,
"tax_category": sales_order.tax_category,
"shipping_rule": sales_order.shipping_rule,
"taxes_and_charges": sales_order.taxes_and_charges,
"other_charges_calculation": sales_order.other_charges_calculation,
"base_total_taxes_and_charges": sales_order.base_total_taxes_and_charges,
"total_taxes_and_charges": sales_order.total_taxes_and_charges,
"loyalty_points": sales_order.loyalty_points,
"loyalty_amount": sales_order.loyalty_amount,
"apply_discount_on": sales_order.apply_discount_on if sales_order.apply_discount_on else "Grand Total",
"base_discount_amount": sales_order.base_discount_amount,
"additional_discount_percentage": sales_order.additional_discount_percentage,
"discount_amount": sales_order.discount_amount,
"base_grand_total": sales_order.base_grand_total,
"base_rounding_adjustment": sales_order.base_rounding_adjustment,
"base_rounded_total": sales_order.base_rounded_total,
"base_in_words": sales_order.base_in_words,
"grand_total": sales_order.grand_total,
"rounding_adjustment": sales_order.rounding_adjustment,
"rounded_total": sales_order.rounded_total,
"in_words": sales_order.in_words,
"disable_rounded_total": sales_order.disable_rounded_total if sales_order.disable_rounded_total else "0",
"payment_terms_template": sales_order.payment_terms_template,
"tc_name": sales_order.tc_name,
"terms": sales_order.terms,
"is_internal_customer": sales_order.customer.is_internal_customer,
"represents_company": sales_order.customer.represents_company,
"project": sales_order.project,
"party_account_currency": sales_order.party_account_currency,
"source": sales_order.source,
"campaign": sales_order.campaign,
"language": sales_order.language,
"letter_head": sales_order.letter_head,
"select_print_heading": sales_order.select_print_heading,
"group_same_items": sales_order.group_same_items if sales_order.group_same_items else "0",
"sales_partner": sales_order.sales_partner,
"commission_rate": sales_order.commission_rate,
"total_commission": sales_order.total_commission,
"from_date": sales_order.from_date,
"to_date": sales_order.to_date,
"auto_repeat": sales_order.auto_repeat,
"status": "Paid"
})
#Sales Invoice Item
for item in sales_order.items:
sales_invoice.append("items", {
"item_code": item.item_code,
"customer_item_code": item.customer_item_code,
"posa_notes": item.posa_notes,
"item_name": item.item_name,
"description": item.description,
"item_group": item.item_group,
"brand": item.brand,
"image": item.image,
"image_view": item.image_view,
"qty": item.qty,
"stock_uom": item.stock_uom,
"uom": item.uom,
"conversion_factor": item.conversion_factor,
"stock_qty": item.stock_qty,
"price_list_rate": item.price_list_rate,
"base_price_list_rate": item.base_price_list_rate,
"margin_type": item.margin_type,
"margin_rate_or_amount": item.margin_rate_or_amount,
"rate_with_margin": item.rate_with_margin,
"discount_percentage": item.discount_percentage,
"discount_amount": item.discount_amount,
"base_rate_with_margin": item.base_rate_with_margin,
"rate": item.rate,
"amount": item.amount,
"item_tax_template": item.item_tax_template,
"base_rate": item.base_rate,
"base_amount": item.base_amount,
"pricing_rules": item.pricing_rules,
"stock_uom_rate": item.stock_uom_rate,
"is_free_item": item.is_free_item if item.is_free_item else "0",
"net_rate": item.net_rate,
"net_amount": item.net_amount,
"base_net_rate": item.base_net_rate,
"base_net_amount": item.base_net_amount,
"delivered_by_supplier": item.delivered_by_supplier if item.delivered_by_supplier else "0",
"weight_per_unit": item.weight_per_unit,
"total_weight": item.total_weight,
"weight_uom": item.weight_uom,
"warehouse": item.warehouse,
"target_warehouse": item.target_warehouse,
"actual_qty": item.actual_qty,
"delivered_qty": item.delivered_qty,
#"page_break": item.page_break if item.page_break else "0",
"item_tax_rate": item.item_tax_rate,
#Links
"sales_order": sales_order.name,
"so_detail": item.name
})
#Sales Invoice PRD
for detail in sales_order.pricing_rules:
sales_invoice.append("pricing_rules", {
"pricing_rule": detail.pricing_rule,
"item_code": detail.item_code,
"margin_type": detail.margin_type,
"rate_or_discount": detail.rate_or_discount,
#"child_docname": detail.child_docname,
"rule_applied": detail.rule_applied if detail.rule_applied else "1"
})
#Sales Invoice Packed Items
for item in sales_order.packed_items:
sales_invoice.append("packed_items", {
"parent_item": item.parent_item,
"item_code": item.item_code,
"item_name": item.item_name,
"description": item.description,
"warehouse": item.warehouse,
"target_warehouse": item.target_warehouse,
"conversion_factor": item.conversion_factor,
"qty": item.qty,
"uom": item.uom,
"serial_no": item.serial_no,
"batch_no": item.batch_no,
"actual_batch_qty": item.actual_batch_qty,
"actual_qty": item.actual_qty,
"projected_qty": item.projected_qty,
"incoming_rate": item.incoming_rate,
#"page_break": item.page_break if item.page_break else "0",
"prevdoc_doctype": item.prevdoc_doctype,
"parent_detail_docname": item.parent_detail_docname
})
#Sales Invoice Taxes and Charges
for detail in sales_order.taxes:
sales_invoice.append("taxes", {
"category": detail.category if detail.category else "Total",
"add_deduct_tax": detail.add_deduct_tax if detail.add_deduct_tax else "Add",
"charge_type": detail.charge_type if detail.charge_type else "On Net Total",
"row_id": detail.row_id,
"included_in_print_rate": detail.included_in_print_rate if detail.included_in_print_rate else "0",
"included_in_paid_amount": detail.included_in_paid_amount if detail.included_in_paid_amount else "0",
"account_head": detail.account_head,
"description": detail.description,
"rate": detail.rate,
"cost_center": detail.cost_center if detail.cost_center else ":Company",
"currency": detail.account_head.account_currency,
"tax_amount": detail.tax_amount,
"tax_amount_after_discount_amount": detail.tax_amount_after_discount_amount,
"total": detail.total,
"base_tax_amount": detail.base_tax_amount,
"base_total": detail.base_total,
"base_tax_amount_after_discount_amount": detail.base_tax_amount_after_discount_amount,
"item_wise_tax_detail": detail.item_wise_tax_detail
})
#Sales Invoice Payment Schedule
for detail in sales_order.payment_schedule:
sales_invoice.append("payment_schedule", {
"payment_term": detail.payment_term,
"description": detail.payment_term.description,
"due_date": detail.due_date,
"mode_of_payment": detail.mode_of_payment,
"invoice_portion": detail.invoice_portion,
"discount_type": detail.payment_term.discount_type,
"discount_date": detail.discount_date,
"discount": detail.payment_term.discount,
"payment_amount": detail.payment_amount,
"outstanding": detail.payment_amount,
"paid_amount": detail.paid_amount,
"discounted_amount": detail.discounted_amount if detail.discounted_amount else "0",
"base_payment_amount": detail.base_payment_amount
})
#Sales Invoice Sales Team
for detail in sales_order.sales_team:
sales_invoice.append("sales_team", {
"sales_person": detail.sales_person,
"contact_no": detail.contact_no,
"allocated_percentage": detail.allocated_percentage,
"allocated_amount": detail.allocated_amount,
"commission_rate": detail.commission_rate,
"incentives": detail.incentives
})
sales_invoice.insert()
frappe.msgprint("Created Sales Invoice.")