fix: purchase invoice qty change not recalculate the consumed qty and added test cases for purchase invoice
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index a714ac7..00ef7d5 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -175,9 +175,7 @@
"hidden": 1,
"label": "Title",
"no_copy": 1,
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "naming_series",
@@ -189,9 +187,7 @@
"options": "ACC-PINV-.YYYY.-\nACC-PINV-RET-.YYYY.-",
"print_hide": 1,
"reqd": 1,
- "set_only_once": 1,
- "show_days": 1,
- "show_seconds": 1
+ "set_only_once": 1
},
{
"fieldname": "supplier",
@@ -203,9 +199,7 @@
"options": "Supplier",
"print_hide": 1,
"reqd": 1,
- "search_index": 1,
- "show_days": 1,
- "show_seconds": 1
+ "search_index": 1
},
{
"bold": 1,
@@ -217,9 +211,7 @@
"label": "Supplier Name",
"oldfieldname": "supplier_name",
"oldfieldtype": "Data",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fetch_from": "supplier.tax_id",
@@ -227,27 +219,21 @@
"fieldtype": "Read Only",
"label": "Tax Id",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "due_date",
"fieldtype": "Date",
"label": "Due Date",
"oldfieldname": "due_date",
- "oldfieldtype": "Date",
- "show_days": 1,
- "show_seconds": 1
+ "oldfieldtype": "Date"
},
{
"default": "0",
"fieldname": "is_paid",
"fieldtype": "Check",
"label": "Is Paid",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"default": "0",
@@ -255,25 +241,19 @@
"fieldtype": "Check",
"label": "Is Return (Debit Note)",
"no_copy": 1,
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"default": "0",
"fieldname": "apply_tds",
"fieldtype": "Check",
"label": "Apply Tax Withholding Amount",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "column_break1",
"fieldtype": "Column Break",
"oldfieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1,
"width": "50%"
},
{
@@ -283,17 +263,13 @@
"label": "Company",
"options": "Company",
"print_hide": 1,
- "remember_last_selected_value": 1,
- "show_days": 1,
- "show_seconds": 1
+ "remember_last_selected_value": 1
},
{
"fieldname": "cost_center",
"fieldtype": "Link",
"label": "Cost Center",
- "options": "Cost Center",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Cost Center"
},
{
"default": "Today",
@@ -305,9 +281,7 @@
"oldfieldtype": "Date",
"print_hide": 1,
"reqd": 1,
- "search_index": 1,
- "show_days": 1,
- "show_seconds": 1
+ "search_index": 1
},
{
"fieldname": "posting_time",
@@ -316,8 +290,6 @@
"no_copy": 1,
"print_hide": 1,
"print_width": "100px",
- "show_days": 1,
- "show_seconds": 1,
"width": "100px"
},
{
@@ -326,9 +298,7 @@
"fieldname": "set_posting_time",
"fieldtype": "Check",
"label": "Edit Posting Date and Time",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "amended_from",
@@ -340,58 +310,44 @@
"oldfieldtype": "Link",
"options": "Purchase Invoice",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"collapsible": 1,
"collapsible_depends_on": "eval:doc.on_hold",
"fieldname": "sb_14",
"fieldtype": "Section Break",
- "label": "Hold Invoice",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Hold Invoice"
},
{
"default": "0",
"fieldname": "on_hold",
"fieldtype": "Check",
- "label": "Hold Invoice",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Hold Invoice"
},
{
"depends_on": "eval:doc.on_hold",
"description": "Once set, this invoice will be on hold till the set date",
"fieldname": "release_date",
"fieldtype": "Date",
- "label": "Release Date",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Release Date"
},
{
"fieldname": "cb_17",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"depends_on": "eval:doc.on_hold",
"fieldname": "hold_comment",
"fieldtype": "Small Text",
- "label": "Reason For Putting On Hold",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Reason For Putting On Hold"
},
{
"collapsible": 1,
"collapsible_depends_on": "bill_no",
"fieldname": "supplier_invoice_details",
"fieldtype": "Section Break",
- "label": "Supplier Invoice Details",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Supplier Invoice Details"
},
{
"fieldname": "bill_no",
@@ -399,15 +355,11 @@
"label": "Supplier Invoice No",
"oldfieldname": "bill_no",
"oldfieldtype": "Data",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "column_break_15",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"fieldname": "bill_date",
@@ -416,17 +368,13 @@
"no_copy": 1,
"oldfieldname": "bill_date",
"oldfieldtype": "Date",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"depends_on": "return_against",
"fieldname": "returns",
"fieldtype": "Section Break",
- "label": "Returns",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Returns"
},
{
"depends_on": "return_against",
@@ -436,34 +384,26 @@
"no_copy": 1,
"options": "Purchase Invoice",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"collapsible": 1,
"fieldname": "section_addresses",
"fieldtype": "Section Break",
- "label": "Address and Contact",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Address and Contact"
},
{
"fieldname": "supplier_address",
"fieldtype": "Link",
"label": "Select Supplier Address",
"options": "Address",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "address_display",
"fieldtype": "Small Text",
"label": "Address",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "contact_person",
@@ -471,67 +411,51 @@
"in_global_search": 1,
"label": "Contact Person",
"options": "Contact",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "contact_display",
"fieldtype": "Small Text",
"label": "Contact",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "contact_mobile",
"fieldtype": "Small Text",
"label": "Mobile No",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "contact_email",
"fieldtype": "Small Text",
"label": "Contact Email",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "col_break_address",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"fieldname": "shipping_address",
"fieldtype": "Link",
"label": "Select Shipping Address",
"options": "Address",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "shipping_address_display",
"fieldtype": "Small Text",
"label": "Shipping Address",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"collapsible": 1,
"fieldname": "currency_and_price_list",
"fieldtype": "Section Break",
"label": "Currency and Price List",
- "options": "fa fa-tag",
- "show_days": 1,
- "show_seconds": 1
+ "options": "fa fa-tag"
},
{
"fieldname": "currency",
@@ -540,9 +464,7 @@
"oldfieldname": "currency",
"oldfieldtype": "Select",
"options": "Currency",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "conversion_rate",
@@ -551,24 +473,18 @@
"oldfieldname": "conversion_rate",
"oldfieldtype": "Currency",
"precision": "9",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "column_break2",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"fieldname": "buying_price_list",
"fieldtype": "Link",
"label": "Price List",
"options": "Price List",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "price_list_currency",
@@ -576,18 +492,14 @@
"label": "Price List Currency",
"options": "Currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "plc_conversion_rate",
"fieldtype": "Float",
"label": "Price List Exchange Rate",
"precision": "9",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"default": "0",
@@ -596,15 +508,11 @@
"label": "Ignore Pricing Rule",
"no_copy": 1,
"permlevel": 1,
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "sec_warehouse",
- "fieldtype": "Section Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Section Break"
},
{
"depends_on": "update_stock",
@@ -613,9 +521,7 @@
"fieldtype": "Link",
"label": "Set Accepted Warehouse",
"options": "Warehouse",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"depends_on": "update_stock",
@@ -625,15 +531,11 @@
"label": "Rejected Warehouse",
"no_copy": 1,
"options": "Warehouse",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "col_break_warehouse",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"default": "No",
@@ -641,33 +543,25 @@
"fieldtype": "Select",
"label": "Raw Materials Supplied",
"options": "No\nYes",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "items_section",
"fieldtype": "Section Break",
"oldfieldtype": "Section Break",
- "options": "fa fa-shopping-cart",
- "show_days": 1,
- "show_seconds": 1
+ "options": "fa fa-shopping-cart"
},
{
"default": "0",
"fieldname": "update_stock",
"fieldtype": "Check",
"label": "Update Stock",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "scan_barcode",
"fieldtype": "Data",
- "label": "Scan Barcode",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Scan Barcode"
},
{
"allow_bulk_edit": 1,
@@ -677,56 +571,43 @@
"oldfieldname": "entries",
"oldfieldtype": "Table",
"options": "Purchase Invoice Item",
- "reqd": 1,
- "show_days": 1,
- "show_seconds": 1
+ "reqd": 1
},
{
"fieldname": "pricing_rule_details",
"fieldtype": "Section Break",
- "label": "Pricing Rules",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Pricing Rules"
},
{
"fieldname": "pricing_rules",
"fieldtype": "Table",
"label": "Pricing Rule Detail",
"options": "Pricing Rule Detail",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"collapsible_depends_on": "supplied_items",
"fieldname": "raw_materials_supplied",
"fieldtype": "Section Break",
- "label": "Raw Materials Supplied",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Raw Materials Supplied"
},
{
+ "depends_on": "update_stock",
"fieldname": "supplied_items",
"fieldtype": "Table",
"label": "Supplied Items",
- "options": "Purchase Receipt Item Supplied",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "no_copy": 1,
+ "options": "Purchase Receipt Item Supplied"
},
{
"fieldname": "section_break_26",
- "fieldtype": "Section Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Section Break"
},
{
"fieldname": "total_qty",
"fieldtype": "Float",
"label": "Total Quantity",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "base_total",
@@ -734,9 +615,7 @@
"label": "Total (Company Currency)",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "base_net_total",
@@ -746,24 +625,18 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "column_break_28",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"fieldname": "total",
"fieldtype": "Currency",
"label": "Total",
"options": "currency",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "net_total",
@@ -773,56 +646,42 @@
"oldfieldtype": "Currency",
"options": "currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "total_net_weight",
"fieldtype": "Float",
"label": "Total Net Weight",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "taxes_section",
"fieldtype": "Section Break",
"oldfieldtype": "Section Break",
- "options": "fa fa-money",
- "show_days": 1,
- "show_seconds": 1
+ "options": "fa fa-money"
},
{
"fieldname": "tax_category",
"fieldtype": "Link",
"label": "Tax Category",
"options": "Tax Category",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "column_break_49",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"fieldname": "shipping_rule",
"fieldtype": "Link",
"label": "Shipping Rule",
"options": "Shipping Rule",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "section_break_51",
- "fieldtype": "Section Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Section Break"
},
{
"fieldname": "taxes_and_charges",
@@ -831,9 +690,7 @@
"oldfieldname": "purchase_other_charges",
"oldfieldtype": "Link",
"options": "Purchase Taxes and Charges Template",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "taxes",
@@ -841,17 +698,13 @@
"label": "Purchase Taxes and Charges",
"oldfieldname": "purchase_tax_details",
"oldfieldtype": "Table",
- "options": "Purchase Taxes and Charges",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Purchase Taxes and Charges"
},
{
"collapsible": 1,
"fieldname": "sec_tax_breakup",
"fieldtype": "Section Break",
- "label": "Tax Breakup",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Tax Breakup"
},
{
"fieldname": "other_charges_calculation",
@@ -860,17 +713,13 @@
"no_copy": 1,
"oldfieldtype": "HTML",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "totals",
"fieldtype": "Section Break",
"oldfieldtype": "Section Break",
- "options": "fa fa-money",
- "show_days": 1,
- "show_seconds": 1
+ "options": "fa fa-money"
},
{
"fieldname": "base_taxes_and_charges_added",
@@ -880,9 +729,7 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "base_taxes_and_charges_deducted",
@@ -892,9 +739,7 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "base_total_taxes_and_charges",
@@ -904,15 +749,11 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "column_break_40",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"fieldname": "taxes_and_charges_added",
@@ -922,9 +763,7 @@
"oldfieldtype": "Currency",
"options": "currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "taxes_and_charges_deducted",
@@ -934,9 +773,7 @@
"oldfieldtype": "Currency",
"options": "currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "total_taxes_and_charges",
@@ -944,18 +781,14 @@
"label": "Total Taxes and Charges",
"options": "currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"collapsible": 1,
"collapsible_depends_on": "discount_amount",
"fieldname": "section_break_44",
"fieldtype": "Section Break",
- "label": "Additional Discount",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Additional Discount"
},
{
"default": "Grand Total",
@@ -963,9 +796,7 @@
"fieldtype": "Select",
"label": "Apply Additional Discount On",
"options": "\nGrand Total\nNet Total",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "base_discount_amount",
@@ -973,38 +804,28 @@
"label": "Additional Discount Amount (Company Currency)",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "column_break_46",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"fieldname": "additional_discount_percentage",
"fieldtype": "Float",
"label": "Additional Discount Percentage",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "discount_amount",
"fieldtype": "Currency",
"label": "Additional Discount Amount",
"options": "currency",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "section_break_49",
- "fieldtype": "Section Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Section Break"
},
{
"fieldname": "base_grand_total",
@@ -1014,9 +835,7 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"depends_on": "eval:!doc.disable_rounded_total",
@@ -1026,9 +845,7 @@
"no_copy": 1,
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"depends_on": "eval:!doc.disable_rounded_total",
@@ -1038,9 +855,7 @@
"no_copy": 1,
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "base_in_words",
@@ -1050,17 +865,13 @@
"oldfieldname": "in_words",
"oldfieldtype": "Data",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "column_break8",
"fieldtype": "Column Break",
"oldfieldtype": "Column Break",
"print_hide": 1,
- "show_days": 1,
- "show_seconds": 1,
"width": "50%"
},
{
@@ -1071,9 +882,7 @@
"oldfieldname": "grand_total_import",
"oldfieldtype": "Currency",
"options": "currency",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"depends_on": "eval:!doc.disable_rounded_total",
@@ -1083,9 +892,7 @@
"no_copy": 1,
"options": "currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"depends_on": "eval:!doc.disable_rounded_total",
@@ -1095,9 +902,7 @@
"no_copy": 1,
"options": "currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "in_words",
@@ -1107,9 +912,7 @@
"oldfieldname": "in_words_import",
"oldfieldtype": "Data",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "total_advance",
@@ -1120,9 +923,7 @@
"oldfieldtype": "Currency",
"options": "party_account_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "outstanding_amount",
@@ -1133,18 +934,14 @@
"oldfieldtype": "Currency",
"options": "party_account_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"default": "0",
"depends_on": "grand_total",
"fieldname": "disable_rounded_total",
"fieldtype": "Check",
- "label": "Disable Rounded Total",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Disable Rounded Total"
},
{
"collapsible": 1,
@@ -1152,26 +949,20 @@
"depends_on": "eval:doc.is_paid===1||(doc.advances && doc.advances.length>0)",
"fieldname": "payments_section",
"fieldtype": "Section Break",
- "label": "Payments",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Payments"
},
{
"fieldname": "mode_of_payment",
"fieldtype": "Link",
"label": "Mode of Payment",
"options": "Mode of Payment",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "cash_bank_account",
"fieldtype": "Link",
"label": "Cash/Bank Account",
- "options": "Account",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Account"
},
{
"fieldname": "clearance_date",
@@ -1179,15 +970,11 @@
"label": "Clearance Date",
"no_copy": 1,
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "col_br_payments",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"depends_on": "is_paid",
@@ -1196,9 +983,7 @@
"label": "Paid Amount",
"no_copy": 1,
"options": "currency",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "base_paid_amount",
@@ -1207,9 +992,7 @@
"no_copy": 1,
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"collapsible": 1,
@@ -1217,9 +1000,7 @@
"depends_on": "grand_total",
"fieldname": "write_off",
"fieldtype": "Section Break",
- "label": "Write Off",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Write Off"
},
{
"fieldname": "write_off_amount",
@@ -1227,9 +1008,7 @@
"label": "Write Off Amount",
"no_copy": 1,
"options": "currency",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "base_write_off_amount",
@@ -1238,15 +1017,11 @@
"no_copy": 1,
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "column_break_61",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"depends_on": "eval:flt(doc.write_off_amount)!=0",
@@ -1254,9 +1029,7 @@
"fieldtype": "Link",
"label": "Write Off Account",
"options": "Account",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"depends_on": "eval:flt(doc.write_off_amount)!=0",
@@ -1264,9 +1037,7 @@
"fieldtype": "Link",
"label": "Write Off Cost Center",
"options": "Cost Center",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"collapsible": 1,
@@ -1276,17 +1047,13 @@
"label": "Advance Payments",
"oldfieldtype": "Section Break",
"options": "fa fa-money",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"default": "0",
"fieldname": "allocate_advances_automatically",
"fieldtype": "Check",
- "label": "Set Advances and Allocate (FIFO)",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Set Advances and Allocate (FIFO)"
},
{
"depends_on": "eval:!doc.allocate_advances_automatically",
@@ -1294,9 +1061,7 @@
"fieldtype": "Button",
"label": "Get Advances Paid",
"oldfieldtype": "Button",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "advances",
@@ -1306,26 +1071,20 @@
"oldfieldname": "advance_allocation_details",
"oldfieldtype": "Table",
"options": "Purchase Invoice Advance",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"collapsible": 1,
"collapsible_depends_on": "eval:(!doc.is_return)",
"fieldname": "payment_schedule_section",
"fieldtype": "Section Break",
- "label": "Payment Terms",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Payment Terms"
},
{
"fieldname": "payment_terms_template",
"fieldtype": "Link",
"label": "Payment Terms Template",
- "options": "Payment Terms Template",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Payment Terms Template"
},
{
"fieldname": "payment_schedule",
@@ -1333,9 +1092,7 @@
"label": "Payment Schedule",
"no_copy": 1,
"options": "Payment Schedule",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"collapsible": 1,
@@ -1343,33 +1100,25 @@
"fieldname": "terms_section_break",
"fieldtype": "Section Break",
"label": "Terms and Conditions",
- "options": "fa fa-legal",
- "show_days": 1,
- "show_seconds": 1
+ "options": "fa fa-legal"
},
{
"fieldname": "tc_name",
"fieldtype": "Link",
"label": "Terms",
"options": "Terms and Conditions",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "terms",
"fieldtype": "Text Editor",
- "label": "Terms and Conditions1",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Terms and Conditions1"
},
{
"collapsible": 1,
"fieldname": "printing_settings",
"fieldtype": "Section Break",
- "label": "Printing Settings",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Printing Settings"
},
{
"allow_on_submit": 1,
@@ -1377,9 +1126,7 @@
"fieldtype": "Link",
"label": "Letter Head",
"options": "Letter Head",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"allow_on_submit": 1,
@@ -1387,15 +1134,11 @@
"fieldname": "group_same_items",
"fieldtype": "Check",
"label": "Group same items",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "column_break_112",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"allow_on_submit": 1,
@@ -1407,18 +1150,14 @@
"oldfieldtype": "Link",
"options": "Print Heading",
"print_hide": 1,
- "report_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "report_hide": 1
},
{
"fieldname": "language",
"fieldtype": "Data",
"label": "Print Language",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"collapsible": 1,
@@ -1427,9 +1166,7 @@
"label": "More Information",
"oldfieldtype": "Section Break",
"options": "fa fa-file-text",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "credit_to",
@@ -1440,9 +1177,7 @@
"options": "Account",
"print_hide": 1,
"reqd": 1,
- "search_index": 1,
- "show_days": 1,
- "show_seconds": 1
+ "search_index": 1
},
{
"fieldname": "party_account_currency",
@@ -1452,9 +1187,7 @@
"no_copy": 1,
"options": "Currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"default": "No",
@@ -1464,9 +1197,7 @@
"oldfieldname": "is_opening",
"oldfieldtype": "Select",
"options": "No\nYes",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "against_expense_account",
@@ -1476,15 +1207,11 @@
"no_copy": 1,
"oldfieldname": "against_expense_account",
"oldfieldtype": "Small Text",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "column_break_63",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"default": "Draft",
@@ -1493,9 +1220,7 @@
"in_standard_filter": 1,
"label": "Status",
"options": "\nDraft\nReturn\nDebit Note Issued\nSubmitted\nPaid\nUnpaid\nOverdue\nCancelled\nInternal Transfer",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "inter_company_invoice_reference",
@@ -1504,9 +1229,7 @@
"no_copy": 1,
"options": "Sales Invoice",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "remarks",
@@ -1515,18 +1238,14 @@
"no_copy": 1,
"oldfieldname": "remarks",
"oldfieldtype": "Text",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"collapsible": 1,
"fieldname": "subscription_section",
"fieldtype": "Section Break",
"label": "Subscription Section",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"allow_on_submit": 1,
@@ -1535,9 +1254,7 @@
"fieldtype": "Date",
"label": "From Date",
"no_copy": 1,
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"allow_on_submit": 1,
@@ -1546,15 +1263,11 @@
"fieldtype": "Date",
"label": "To Date",
"no_copy": 1,
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "column_break_114",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"fieldname": "auto_repeat",
@@ -1563,32 +1276,24 @@
"no_copy": 1,
"options": "Auto Repeat",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"allow_on_submit": 1,
"depends_on": "eval: doc.auto_repeat",
"fieldname": "update_auto_repeat_reference",
"fieldtype": "Button",
- "label": "Update Auto Repeat Reference",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Update Auto Repeat Reference"
},
{
"collapsible": 1,
"fieldname": "accounting_dimensions_section",
"fieldtype": "Section Break",
- "label": "Accounting Dimensions ",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Accounting Dimensions "
},
{
"fieldname": "dimension_col_break",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"default": "0",
@@ -1596,9 +1301,7 @@
"fieldname": "is_internal_supplier",
"fieldtype": "Check",
"label": "Is Internal Supplier",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "tax_withholding_category",
@@ -1606,25 +1309,19 @@
"hidden": 1,
"label": "Tax Withholding Category",
"options": "Tax Withholding Category",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "billing_address",
"fieldtype": "Link",
"label": "Select Billing Address",
- "options": "Address",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Address"
},
{
"fieldname": "billing_address_display",
"fieldtype": "Small Text",
"label": "Billing Address",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "project",
@@ -1638,9 +1335,7 @@
"fieldname": "unrealized_profit_loss_account",
"fieldtype": "Link",
"label": "Unrealized Profit / Loss Account",
- "options": "Account",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Account"
},
{
"depends_on": "eval:doc.is_internal_supplier",
@@ -1649,9 +1344,7 @@
"fieldname": "represents_company",
"fieldtype": "Link",
"label": "Represents Company",
- "options": "Company",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Company"
},
{
"depends_on": "eval:doc.update_stock && doc.is_internal_supplier",
@@ -1663,8 +1356,6 @@
"options": "Warehouse",
"print_hide": 1,
"print_width": "50px",
- "show_days": 1,
- "show_seconds": 1,
"width": "50px"
},
{
@@ -1692,7 +1383,7 @@
"idx": 204,
"is_submittable": 1,
"links": [],
- "modified": "2021-06-09 12:30:25.632109",
+ "modified": "2021-06-15 18:20:56.806195",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 0ee0bc7..45d89ad 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -400,6 +400,7 @@
# because updating ordered qty in bin depends upon updated ordered qty in PO
if self.update_stock == 1:
self.update_stock_ledger()
+ self.set_consumed_qty_in_po()
from erpnext.stock.doctype.serial_no.serial_no import update_serial_nos_after_submit
update_serial_nos_after_submit(self, "items")
@@ -998,6 +999,7 @@
if self.update_stock == 1:
self.update_stock_ledger()
self.delete_auto_created_batches()
+ self.set_consumed_qty_in_po()
self.make_gl_entries_on_cancel()
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 1907885..0b0da5f 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -58,6 +58,11 @@
if self.doctype in ("Purchase Receipt", "Purchase Invoice"):
self.update_valuation_rate()
+ def onload(self):
+ super(BuyingController, self).onload()
+ self.set_onload("backflush_based_on", frappe.db.get_single_value('Buying Settings',
+ 'backflush_raw_materials_of_subcontract_based_on'))
+
def set_missing_values(self, for_validate=False):
super(BuyingController, self).set_missing_values(for_validate)
diff --git a/erpnext/controllers/subcontracting.py b/erpnext/controllers/subcontracting.py
index e81c0f5..db84162 100644
--- a/erpnext/controllers/subcontracting.py
+++ b/erpnext/controllers/subcontracting.py
@@ -40,9 +40,10 @@
self.purchase_orders = [d.purchase_order for d in self.items if d.purchase_order]
def __identify_change_in_item_table(self):
- self.changed_name = []
+ self.__changed_name = []
+ self.__reference_name = []
- if self.doctype == 'Purchase Order' or not self.get(self.raw_material_table):
+ if self.doctype == 'Purchase Order' or self.is_new():
self.set(self.raw_material_table, [])
return
@@ -51,17 +52,18 @@
return True
for n_row in self.items:
+ self.__reference_name.append(n_row.name)
if (n_row.name not in item_dict) or (n_row.item_code, n_row.qty) != item_dict[n_row.name]:
- self.changed_name.append(n_row.name)
+ self.__changed_name.append(n_row.name)
if item_dict.get(n_row.name):
del item_dict[n_row.name]
- self.changed_name.extend(item_dict.keys())
+ self.__changed_name.extend(item_dict.keys())
def __get_data_before_save(self):
item_dict = {}
- if self.doctype == 'Purchase Receipt' and self._doc_before_save:
+ if self.doctype in ['Purchase Receipt', 'Purchase Invoice'] and self._doc_before_save:
for row in self._doc_before_save.get('items'):
item_dict[row.name] = (row.item_code, row.qty)
@@ -149,7 +151,7 @@
def __get_received_items(self, doctype):
fields = []
- self.po_field = 'purchase_order' if doctype == 'Purchase Receipt' else 'po_detail'
+ self.po_field = 'purchase_order'
for field in ['name', self.po_field, 'parent']:
fields.append(f'`tab{doctype} Item`.`{field}`')
@@ -161,9 +163,9 @@
return frappe.get_all(f'{doctype}', fields = fields, filters = filters)
def __get_consumed_items(self, doctype, pr_items):
- return frappe.get_all(f'{doctype} Item Supplied',
+ return frappe.get_all('Purchase Receipt Item Supplied',
fields = ['serial_no', 'rm_item_code', 'reference_name', 'batch_no', 'consumed_qty', 'main_item_code'],
- filters = {'docstatus': 1, 'reference_name': ('in', list(pr_items))})
+ filters = {'docstatus': 1, 'reference_name': ('in', list(pr_items)), 'parenttype': doctype})
def __set_alternative_item_details(self, row):
if row.get('original_item'):
@@ -196,13 +198,16 @@
return frappe.get_all('BOM', fields = fields, filters=filters, order_by = f'`tab{doctype}`.`idx`') or []
def __remove_changed_rows(self):
- if not self.changed_name:
+ if not self.__changed_name:
return
i=1
self.set(self.raw_material_table, [])
for d in self._doc_before_save.supplied_items:
- if d.reference_name in self.changed_name:
+ if d.reference_name in self.__changed_name:
+ continue
+
+ if (d.reference_name not in self.__reference_name):
continue
d.idx = i
@@ -215,8 +220,8 @@
has_supplied_items = True if self.get(self.raw_material_table) else False
for row in self.items:
- if (self.doctype != 'Purchase Order' and ((self.changed_name and row.name not in self.changed_name)
- or (has_supplied_items and not self.changed_name))):
+ if (self.doctype != 'Purchase Order' and ((self.__changed_name and row.name not in self.__changed_name)
+ or (has_supplied_items and not self.__changed_name))):
continue
if self.doctype == 'Purchase Order' or self.backflush_based_on == 'BOM':
@@ -305,16 +310,18 @@
self.available_materials[key]['serial_no'].remove(sn)
def set_consumed_qty_in_po(self):
+ # Update consumed qty back in the purchase order
if self.is_subcontracted != 'Yes':
return
self.__get_purchase_orders()
- consumed_items, pr_items = self.__update_consumed_materials(self.doctype, return_consumed_items=True)
-
itemwise_consumed_qty = defaultdict(float)
- for row in consumed_items:
- key = (row.rm_item_code, row.main_item_code, pr_items.get(row.reference_name))
- itemwise_consumed_qty[key] += row.consumed_qty
+ for doctype in ['Purchase Receipt', 'Purchase Invoice']:
+ consumed_items, pr_items = self.__update_consumed_materials(doctype, return_consumed_items=True)
+
+ for row in consumed_items:
+ key = (row.rm_item_code, row.main_item_code, pr_items.get(row.reference_name))
+ itemwise_consumed_qty[key] += row.consumed_qty
self.__update_consumed_qty_in_po(itemwise_consumed_qty)
diff --git a/erpnext/public/js/controllers/buying.js b/erpnext/public/js/controllers/buying.js
index 680bf04..a657f59 100644
--- a/erpnext/public/js/controllers/buying.js
+++ b/erpnext/public/js/controllers/buying.js
@@ -122,10 +122,21 @@
this.set_from_product_bundle();
}
+ this.toggle_subcontracting_fields();
super.refresh();
- }
+ },
- supplier() {
+ toggle_subcontracting_fields: function() {
+ if (in_list(['Purchase Receipt', 'Purchase Invoice'], this.frm.doc.doctype)) {
+ this.frm.fields_dict.supplied_items.grid.update_docfield_property('consumed_qty',
+ 'read_only', this.frm.doc.__onload && this.frm.doc.__onload.backflush_based_on === 'BOM');
+
+ this.frm.set_df_property('supplied_items', 'cannot_add_rows', 1);
+ this.frm.set_df_property('supplied_items', 'cannot_delete_rows', 1);
+ }
+ },
+
+ supplier: function() {
var me = this;
erpnext.utils.get_party_details(this.frm, null, null, function(){
me.apply_price_list();
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
index 4f75617..0182ed5 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
@@ -75,15 +75,6 @@
}
frm.events.add_custom_buttons(frm);
- frm.trigger('toggle_subcontracting_fields');
- },
-
- toggle_subcontracting_fields: function(frm) {
- frm.fields_dict.supplied_items.grid.update_docfield_property('consumed_qty',
- 'read_only', frm.doc.__onload && frm.doc.__onload.backflush_based_on === 'BOM');
-
- frm.set_df_property('supplied_items', 'cannot_add_rows', 1);
- frm.set_df_property('supplied_items', 'cannot_delete_rows', 1);
},
add_custom_buttons: function(frm) {
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index 264561f..b8580f9 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -102,11 +102,6 @@
if self.get("items") and self.apply_putaway_rule and not self.get("is_return"):
apply_putaway_rule(self.doctype, self.get("items"), self.company)
- def onload(self):
- super(PurchaseReceipt, self).onload()
- self.set_onload("backflush_based_on", frappe.db.get_single_value('Buying Settings',
- 'backflush_raw_materials_of_subcontract_based_on'))
-
def validate(self):
self.validate_posting_time()
super(PurchaseReceipt, self).validate()
diff --git a/erpnext/tests/test_subcontracting.py b/erpnext/tests/test_subcontracting.py
index c1a458a..d2438f8 100644
--- a/erpnext/tests/test_subcontracting.py
+++ b/erpnext/tests/test_subcontracting.py
@@ -10,7 +10,7 @@
from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
from erpnext.buying.doctype.purchase_order.purchase_order import (make_rm_stock_entry,
- make_purchase_receipt, get_materials_from_supplier)
+ make_purchase_receipt, make_purchase_invoice, get_materials_from_supplier)
class TestSubcontracting(unittest.TestCase):
def setUp(self):
@@ -458,10 +458,273 @@
self.assertEqual(value.qty, details.qty)
self.assertEqual(value.batch_no, details.batch_no)
+
+ def test_item_with_batch_based_on_material_transfer_for_purchase_invoice(self):
+ '''
+ - Set backflush based on Material Transferred for Subcontract
+ - Create subcontracted PO for the item Subcontracted Item SA4 (has batch no).
+ - Transfer the components from Stores to Supplier warehouse with batch no and serial nos.
+ - Transfer the components in multiple batches with extra 2 qty for the batched item.
+ - Create the 3 purchase receipt against the PO and split Subcontracted Items into two batches.
+ - Keep the qty as 2 for Subcontracted Item in the purchase receipt.
+ - In the first purchase receipt the batched raw materials will be consumed 2 extra qty.
+ '''
+
+ set_backflush_based_on('Material Transferred for Subcontract')
+ item_code = 'Subcontracted Item SA4'
+ items = [{'warehouse': '_Test Warehouse - _TC', 'item_code': item_code, 'qty': 10, 'rate': 100}]
+
+ rm_items = [{'item_code': 'Subcontracted SRM Item 1', 'qty': 10},
+ {'item_code': 'Subcontracted SRM Item 2', 'qty': 10},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 3},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 3},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 3},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 3}
+ ]
+
+ itemwise_details = make_stock_in_entry(rm_items=rm_items)
+ po = create_purchase_order(rm_items = items, is_subcontracted="Yes",
+ supplier_warehouse="_Test Warehouse 1 - _TC")
+
+ for d in rm_items:
+ d['po_detail'] = po.items[0].name
+
+ make_stock_transfer_entry(po_no = po.name, main_item_code=item_code,
+ rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details))
+
+ pr1 = make_purchase_invoice(po.name)
+ pr1.update_stock = 1
+ pr1.items[0].qty = 2
+ pr1.items[0].expense_account = 'Stock Adjustment - _TC'
+ add_second_row_in_pr(pr1)
+ pr1.save()
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ qty = 4 if key != 'Subcontracted SRM Item 3' else 6
+ self.assertEqual(value.qty, qty)
+
+ pr1 = make_purchase_invoice(po.name)
+ pr1.update_stock = 1
+ pr1.items[0].expense_account = 'Stock Adjustment - _TC'
+ pr1.items[0].qty = 2
+ add_second_row_in_pr(pr1)
+ pr1.save()
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ self.assertEqual(value.qty, 4)
+
+ pr1 = make_purchase_invoice(po.name)
+ pr1.update_stock = 1
+ pr1.items[0].qty = 2
+ pr1.items[0].expense_account = 'Stock Adjustment - _TC'
+ pr1.save()
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ self.assertEqual(value.qty, 2)
+
+ def test_partial_transfer_serial_no_components_based_on_material_transfer_for_purchase_invoice(self):
+ '''
+ - Set backflush based on Material Transferred for Subcontract
+ - Create subcontracted PO for the item Subcontracted Item SA2.
+ - Transfer the partial components from Stores to Supplier warehouse with serial nos.
+ - Create partial purchase receipt against the PO and change the qty manually.
+ - Transfer the remaining components from Stores to Supplier warehouse with serial nos.
+ - Create purchase receipt for remaining qty against the PO and change the qty manually.
+ '''
+
+ set_backflush_based_on('Material Transferred for Subcontract')
+ item_code = 'Subcontracted Item SA2'
+ items = [{'warehouse': '_Test Warehouse - _TC', 'item_code': item_code, 'qty': 10, 'rate': 100}]
+
+ rm_items = [{'item_code': 'Subcontracted SRM Item 2', 'qty': 5}]
+
+ itemwise_details = make_stock_in_entry(rm_items=rm_items)
+ po = create_purchase_order(rm_items = items, is_subcontracted="Yes",
+ supplier_warehouse="_Test Warehouse 1 - _TC")
+
+ for d in rm_items:
+ d['po_detail'] = po.items[0].name
+
+ make_stock_transfer_entry(po_no = po.name, main_item_code=item_code,
+ rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details))
+
+ pr1 = make_purchase_invoice(po.name)
+ pr1.update_stock = 1
+ pr1.items[0].qty = 5
+ pr1.items[0].expense_account = 'Stock Adjustment - _TC'
+ pr1.save()
+
+ for key, value in get_supplied_items(pr1).items():
+ details = itemwise_details.get(key)
+ self.assertEqual(value.qty, 3)
+ self.assertEqual(sorted(value.serial_no), sorted(details.serial_no[0:3]))
+
+ pr1.load_from_db()
+ pr1.supplied_items[0].consumed_qty = 5
+ pr1.supplied_items[0].serial_no = '\n'.join(itemwise_details[pr1.supplied_items[0].rm_item_code]['serial_no'])
+ pr1.save()
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ details = itemwise_details.get(key)
+ self.assertEqual(value.qty, details.qty)
+ self.assertEqual(sorted(value.serial_no), sorted(details.serial_no))
+
+ itemwise_details = make_stock_in_entry(rm_items=rm_items)
+ for d in rm_items:
+ d['po_detail'] = po.items[0].name
+
+ make_stock_transfer_entry(po_no = po.name, main_item_code=item_code,
+ rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details))
+
+ pr1 = make_purchase_invoice(po.name)
+ pr1.update_stock = 1
+ pr1.items[0].expense_account = 'Stock Adjustment - _TC'
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ details = itemwise_details.get(key)
+ self.assertEqual(value.qty, details.qty)
+ self.assertEqual(sorted(value.serial_no), sorted(details.serial_no))
+
+ def test_partial_transfer_batch_based_on_material_transfer_for_purchase_invoice(self):
+ '''
+ - Set backflush based on Material Transferred for Subcontract
+ - Create subcontracted PO for the item Subcontracted Item SA6.
+ - Transfer the partial components from Stores to Supplier warehouse with batch.
+ - Create partial purchase receipt against the PO and change the qty manually.
+ - Transfer the remaining components from Stores to Supplier warehouse with batch.
+ - Create purchase receipt for remaining qty against the PO and change the qty manually.
+ '''
+
+ set_backflush_based_on('Material Transferred for Subcontract')
+ item_code = 'Subcontracted Item SA6'
+ items = [{'warehouse': '_Test Warehouse - _TC', 'item_code': item_code, 'qty': 10, 'rate': 100}]
+
+ rm_items = [{'item_code': 'Subcontracted SRM Item 3', 'qty': 5}]
+
+ itemwise_details = make_stock_in_entry(rm_items=rm_items)
+ po = create_purchase_order(rm_items = items, is_subcontracted="Yes",
+ supplier_warehouse="_Test Warehouse 1 - _TC")
+
+ for d in rm_items:
+ d['po_detail'] = po.items[0].name
+
+ make_stock_transfer_entry(po_no = po.name, main_item_code=item_code,
+ rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details))
+
+ pr1 = make_purchase_invoice(po.name)
+ pr1.update_stock = 1
+ pr1.items[0].qty = 5
+ pr1.items[0].expense_account = 'Stock Adjustment - _TC'
+ pr1.save()
+
+ transferred_batch_no = ''
+ for key, value in get_supplied_items(pr1).items():
+ details = itemwise_details.get(key)
+ self.assertEqual(value.qty, 3)
+ transferred_batch_no = details.batch_no
+ self.assertEqual(value.batch_no, details.batch_no)
+
+ pr1.load_from_db()
+ pr1.supplied_items[0].consumed_qty = 5
+ pr1.supplied_items[0].batch_no = list(transferred_batch_no.keys())[0]
+ pr1.save()
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ details = itemwise_details.get(key)
+ self.assertEqual(value.qty, details.qty)
+ self.assertEqual(value.batch_no, details.batch_no)
+
+ itemwise_details = make_stock_in_entry(rm_items=rm_items)
+ for d in rm_items:
+ d['po_detail'] = po.items[0].name
+
+ make_stock_transfer_entry(po_no = po.name, main_item_code=item_code,
+ rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details))
+
+ pr1 = make_purchase_invoice(po.name)
+ pr1.update_stock = 1
+ pr1.items[0].expense_account = 'Stock Adjustment - _TC'
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ details = itemwise_details.get(key)
+ self.assertEqual(value.qty, details.qty)
+ self.assertEqual(value.batch_no, details.batch_no)
+
+ def test_item_with_batch_based_on_bom_for_purchase_invoice(self):
+ '''
+ - Set backflush based on BOM
+ - Create subcontracted PO for the item Subcontracted Item SA4 (has batch no).
+ - Transfer the components from Stores to Supplier warehouse with batch no and serial nos.
+ - Transfer the components in multiple batches.
+ - Create the 3 purchase receipt against the PO and split Subcontracted Items into two batches.
+ - Keep the qty as 2 for Subcontracted Item in the purchase receipt.
+ '''
+
+ set_backflush_based_on('BOM')
+ item_code = 'Subcontracted Item SA4'
+ items = [{'warehouse': '_Test Warehouse - _TC', 'item_code': item_code, 'qty': 10, 'rate': 100}]
+
+ rm_items = [{'item_code': 'Subcontracted SRM Item 1', 'qty': 10},
+ {'item_code': 'Subcontracted SRM Item 2', 'qty': 10},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 3},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 3},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 3},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 1}
+ ]
+
+ itemwise_details = make_stock_in_entry(rm_items=rm_items)
+ po = create_purchase_order(rm_items = items, is_subcontracted="Yes",
+ supplier_warehouse="_Test Warehouse 1 - _TC")
+
+ for d in rm_items:
+ d['po_detail'] = po.items[0].name
+
+ make_stock_transfer_entry(po_no = po.name, main_item_code=item_code,
+ rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details))
+
+ pr1 = make_purchase_invoice(po.name)
+ pr1.update_stock = 1
+ pr1.items[0].qty = 2
+ pr1.items[0].expense_account = 'Stock Adjustment - _TC'
+ add_second_row_in_pr(pr1)
+ pr1.save()
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ self.assertEqual(value.qty, 4)
+
+ pr1 = make_purchase_invoice(po.name)
+ pr1.update_stock = 1
+ pr1.items[0].qty = 2
+ pr1.items[0].expense_account = 'Stock Adjustment - _TC'
+ add_second_row_in_pr(pr1)
+ pr1.save()
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ self.assertEqual(value.qty, 4)
+
+ pr1 = make_purchase_invoice(po.name)
+ pr1.update_stock = 1
+ pr1.items[0].qty = 2
+ pr1.items[0].expense_account = 'Stock Adjustment - _TC'
+ pr1.save()
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ self.assertEqual(value.qty, 2)
+
def add_second_row_in_pr(pr):
item_dict = {}
for column in ['item_code', 'item_name', 'qty', 'uom', 'warehouse', 'stock_uom',
- 'purchase_order', 'purchase_order_item', 'conversion_factor', 'rate']:
+ 'purchase_order', 'purchase_order_item', 'conversion_factor', 'rate', 'expense_account', 'po_detail']:
item_dict[column] = pr.items[0].get(column)
pr.append('items', item_dict)