Merge pull request #35410 from rohitwaghchaure/fixed-negative-reserved-qty-for-production-plan
fix: Negative value in Reserved Qty for Production Plan
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index e16b1b1..7454332 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -1180,7 +1180,12 @@
if self.is_return:
fixed_asset_gl_entries = get_gl_entries_on_asset_regain(
- asset, item.base_net_amount, item.finance_book, self.get("doctype"), self.get("name")
+ asset,
+ item.base_net_amount,
+ item.finance_book,
+ self.get("doctype"),
+ self.get("name"),
+ self.get("posting_date"),
)
asset.db_set("disposal_date", None)
@@ -1208,7 +1213,12 @@
asset.reload()
fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(
- asset, item.base_net_amount, item.finance_book, self.get("doctype"), self.get("name")
+ asset,
+ item.base_net_amount,
+ item.finance_book,
+ self.get("doctype"),
+ self.get("name"),
+ self.get("posting_date"),
)
asset.db_set("disposal_date", self.posting_date)
diff --git a/erpnext/accounts/form_tour/sales_invoice/sales_invoice.json b/erpnext/accounts/form_tour/sales_invoice/sales_invoice.json
new file mode 100644
index 0000000..414b897
--- /dev/null
+++ b/erpnext/accounts/form_tour/sales_invoice/sales_invoice.json
@@ -0,0 +1,41 @@
+{
+ "creation": "2023-05-23 09:58:17.235916",
+ "docstatus": 0,
+ "doctype": "Form Tour",
+ "first_document": 0,
+ "idx": 0,
+ "include_name_field": 0,
+ "is_standard": 1,
+ "modified": "2023-05-23 13:10:56.227127",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Sales Invoice",
+ "owner": "Administrator",
+ "reference_doctype": "Sales Invoice",
+ "save_on_complete": 1,
+ "steps": [
+ {
+ "description": "Select a customer for whom this invoice is being prepared.",
+ "fieldname": "customer",
+ "fieldtype": "Link",
+ "has_next_condition": 1,
+ "is_table_field": 0,
+ "label": "Customer",
+ "next_step_condition": "eval: doc.customer",
+ "position": "Right",
+ "title": "Select Customer"
+ },
+ {
+ "child_doctype": "Sales Invoice Item",
+ "description": "Select item that you have sold along with quantity and rate.",
+ "fieldname": "items",
+ "fieldtype": "Table",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "parent_fieldname": "items",
+ "position": "Top",
+ "title": "Select Item"
+ }
+ ],
+ "title": "Sales Invoice"
+}
\ No newline at end of file
diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py
index f23ae2f..c64b917 100644
--- a/erpnext/assets/doctype/asset/depreciation.py
+++ b/erpnext/assets/doctype/asset/depreciation.py
@@ -307,7 +307,7 @@
je.company = asset.company
je.remark = "Scrap Entry for asset {0}".format(asset_name)
- for entry in get_gl_entries_on_asset_disposal(asset):
+ for entry in get_gl_entries_on_asset_disposal(asset, date):
entry.update({"reference_type": "Asset", "reference_name": asset_name})
je.append("accounts", entry)
@@ -434,8 +434,11 @@
def get_gl_entries_on_asset_regain(
- asset, selling_amount=0, finance_book=None, voucher_type=None, voucher_no=None
+ asset, selling_amount=0, finance_book=None, voucher_type=None, voucher_no=None, date=None
):
+ if not date:
+ date = getdate()
+
(
fixed_asset_account,
asset,
@@ -453,7 +456,7 @@
"debit_in_account_currency": asset.gross_purchase_amount,
"debit": asset.gross_purchase_amount,
"cost_center": depreciation_cost_center,
- "posting_date": getdate(),
+ "posting_date": date,
},
item=asset,
),
@@ -463,7 +466,7 @@
"credit_in_account_currency": accumulated_depr_amount,
"credit": accumulated_depr_amount,
"cost_center": depreciation_cost_center,
- "posting_date": getdate(),
+ "posting_date": date,
},
item=asset,
),
@@ -472,7 +475,7 @@
profit_amount = abs(flt(value_after_depreciation)) - abs(flt(selling_amount))
if profit_amount:
get_profit_gl_entries(
- asset, profit_amount, gl_entries, disposal_account, depreciation_cost_center
+ asset, profit_amount, gl_entries, disposal_account, depreciation_cost_center, date
)
if voucher_type and voucher_no:
@@ -484,8 +487,11 @@
def get_gl_entries_on_asset_disposal(
- asset, selling_amount=0, finance_book=None, voucher_type=None, voucher_no=None
+ asset, selling_amount=0, finance_book=None, voucher_type=None, voucher_no=None, date=None
):
+ if not date:
+ date = getdate()
+
(
fixed_asset_account,
asset,
@@ -503,7 +509,7 @@
"credit_in_account_currency": asset.gross_purchase_amount,
"credit": asset.gross_purchase_amount,
"cost_center": depreciation_cost_center,
- "posting_date": getdate(),
+ "posting_date": date,
},
item=asset,
),
@@ -513,7 +519,7 @@
"debit_in_account_currency": accumulated_depr_amount,
"debit": accumulated_depr_amount,
"cost_center": depreciation_cost_center,
- "posting_date": getdate(),
+ "posting_date": date,
},
item=asset,
),
@@ -522,7 +528,7 @@
profit_amount = flt(selling_amount) - flt(value_after_depreciation)
if profit_amount:
get_profit_gl_entries(
- asset, profit_amount, gl_entries, disposal_account, depreciation_cost_center
+ asset, profit_amount, gl_entries, disposal_account, depreciation_cost_center, date
)
if voucher_type and voucher_no:
@@ -556,8 +562,11 @@
def get_profit_gl_entries(
- asset, profit_amount, gl_entries, disposal_account, depreciation_cost_center
+ asset, profit_amount, gl_entries, disposal_account, depreciation_cost_center, date=None
):
+ if not date:
+ date = getdate()
+
debit_or_credit = "debit" if profit_amount < 0 else "credit"
gl_entries.append(
asset.get_gl_dict(
@@ -566,7 +575,7 @@
"cost_center": depreciation_cost_center,
debit_or_credit: abs(profit_amount),
debit_or_credit + "_in_account_currency": abs(profit_amount),
- "posting_date": getdate(),
+ "posting_date": date,
},
item=asset,
)
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index f3a9ba0..c64f296 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -356,6 +356,83 @@
si.cancel()
self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Partially Depreciated")
+ def test_gle_made_by_asset_sale_for_existing_asset(self):
+ from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
+
+ asset = create_asset(
+ calculate_depreciation=1,
+ available_for_use_date="2020-04-01",
+ purchase_date="2020-04-01",
+ expected_value_after_useful_life=0,
+ total_number_of_depreciations=5,
+ number_of_depreciations_booked=2,
+ frequency_of_depreciation=12,
+ depreciation_start_date="2023-03-31",
+ opening_accumulated_depreciation=24000,
+ gross_purchase_amount=60000,
+ submit=1,
+ )
+
+ expected_depr_values = [
+ ["2023-03-31", 12000, 36000],
+ ["2024-03-31", 12000, 48000],
+ ["2025-03-31", 12000, 60000],
+ ]
+
+ first_asset_depr_schedule = get_depr_schedule(asset.name, "Active")
+
+ for i, schedule in enumerate(first_asset_depr_schedule):
+ self.assertEqual(getdate(expected_depr_values[i][0]), schedule.schedule_date)
+ self.assertEqual(expected_depr_values[i][1], schedule.depreciation_amount)
+ self.assertEqual(expected_depr_values[i][2], schedule.accumulated_depreciation_amount)
+
+ post_depreciation_entries(date="2023-03-31")
+
+ si = create_sales_invoice(
+ item_code="Macbook Pro", asset=asset.name, qty=1, rate=40000, posting_date=getdate("2023-05-23")
+ )
+ asset.load_from_db()
+
+ self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Sold")
+
+ expected_values = [["2023-03-31", 12000, 36000], ["2023-05-23", 1742.47, 37742.47]]
+
+ second_asset_depr_schedule = get_depr_schedule(asset.name, "Active")
+
+ for i, schedule in enumerate(second_asset_depr_schedule):
+ self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date)
+ self.assertEqual(expected_values[i][1], schedule.depreciation_amount)
+ self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount)
+ self.assertTrue(schedule.journal_entry)
+
+ expected_gle = (
+ (
+ "_Test Accumulated Depreciations - _TC",
+ 37742.47,
+ 0.0,
+ ),
+ (
+ "_Test Fixed Asset - _TC",
+ 0.0,
+ 60000.0,
+ ),
+ (
+ "_Test Gain/Loss on Asset Disposal - _TC",
+ 0.0,
+ 17742.47,
+ ),
+ ("Debtors - _TC", 40000.0, 0.0),
+ )
+
+ gle = frappe.db.sql(
+ """select account, debit, credit from `tabGL Entry`
+ where voucher_type='Sales Invoice' and voucher_no = %s
+ order by account""",
+ si.name,
+ )
+
+ self.assertSequenceEqual(gle, expected_gle)
+
def test_asset_with_maintenance_required_status_after_sale(self):
asset = create_asset(
calculate_depreciation=1,
diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
index 5b910db..789ca6c 100644
--- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
+++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
@@ -443,6 +443,7 @@
item.get("finance_book") or self.get("finance_book"),
self.get("doctype"),
self.get("name"),
+ self.get("posting_date"),
)
asset.db_set("disposal_date", self.posting_date)
diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py
index ad5ec3d..8b359cd 100644
--- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py
+++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py
@@ -252,7 +252,10 @@
# if asset is being sold or scrapped
if date_of_disposal:
- from_date = asset_doc.available_for_use_date
+ from_date = add_months(
+ getdate(asset_doc.available_for_use_date),
+ (asset_doc.number_of_depreciations_booked * row.frequency_of_depreciation),
+ )
if self.depreciation_schedule:
from_date = self.depreciation_schedule[-1].schedule_date
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index c51c6ed..645abf2 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -157,7 +157,7 @@
"party_account_currency",
"inter_company_order_reference",
"is_old_subcontracting_flow",
- "dashboard"
+ "connections_tab"
],
"fields": [
{
@@ -1171,7 +1171,6 @@
"depends_on": "is_internal_supplier",
"fieldname": "set_from_warehouse",
"fieldtype": "Link",
- "ignore_user_permissions": 1,
"label": "Set From Warehouse",
"options": "Warehouse"
},
@@ -1186,12 +1185,6 @@
"label": "More Info"
},
{
- "fieldname": "dashboard",
- "fieldtype": "Tab Break",
- "label": "Dashboard",
- "show_dashboard": 1
- },
- {
"fieldname": "column_break_7",
"fieldtype": "Column Break"
},
@@ -1266,13 +1259,19 @@
"fieldname": "shipping_address_section",
"fieldtype": "Section Break",
"label": "Shipping Address"
+ },
+ {
+ "fieldname": "connections_tab",
+ "fieldtype": "Tab Break",
+ "label": "Connections",
+ "show_dashboard": 1
}
],
"icon": "fa fa-file-text",
"idx": 105,
"is_submittable": 1,
"links": [],
- "modified": "2023-05-07 20:18:09.196799",
+ "modified": "2023-05-24 11:16:41.195340",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.js b/erpnext/manufacturing/doctype/production_plan/production_plan.js
index ab7aa52..45a59cf 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.js
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.js
@@ -451,10 +451,14 @@
for_warehouse: row.warehouse
},
callback: function(r) {
- let {projected_qty, actual_qty} = r.message;
+ if (r.message) {
+ let {projected_qty, actual_qty} = r.message[0];
- frappe.model.set_value(cdt, cdn, 'projected_qty', projected_qty);
- frappe.model.set_value(cdt, cdn, 'actual_qty', actual_qty);
+ frappe.model.set_value(cdt, cdn, {
+ 'projected_qty': projected_qty,
+ 'actual_qty': actual_qty
+ });
+ }
}
})
}
diff --git a/erpnext/selling/form_tour/quotation/quotation.json b/erpnext/selling/form_tour/quotation/quotation.json
index 2a2aa5e..8c97700 100644
--- a/erpnext/selling/form_tour/quotation/quotation.json
+++ b/erpnext/selling/form_tour/quotation/quotation.json
@@ -2,9 +2,11 @@
"creation": "2021-11-23 12:00:36.138824",
"docstatus": 0,
"doctype": "Form Tour",
+ "first_document": 0,
"idx": 0,
+ "include_name_field": 0,
"is_standard": 1,
- "modified": "2021-11-23 12:02:48.010298",
+ "modified": "2023-05-23 12:51:48.684517",
"modified_by": "Administrator",
"module": "Selling",
"name": "Quotation",
@@ -14,51 +16,43 @@
"steps": [
{
"description": "Select a customer or lead for whom this quotation is being prepared. Let's select a Customer.",
- "field": "",
"fieldname": "quotation_to",
"fieldtype": "Link",
"has_next_condition": 0,
"is_table_field": 0,
"label": "Quotation To",
- "parent_field": "",
"position": "Right",
"title": "Quotation To"
},
{
"description": "Select a specific Customer to whom this quotation will be sent.",
- "field": "",
"fieldname": "party_name",
"fieldtype": "Dynamic Link",
"has_next_condition": 0,
"is_table_field": 0,
"label": "Party",
- "parent_field": "",
"position": "Right",
"title": "Party"
},
{
"child_doctype": "Quotation Item",
"description": "Select an item for which you will be quoting a price.",
- "field": "",
"fieldname": "items",
"fieldtype": "Table",
"has_next_condition": 0,
"is_table_field": 0,
"label": "Items",
- "parent_field": "",
"parent_fieldname": "items",
"position": "Bottom",
"title": "Items"
},
{
"description": "You can select pre-populated Sales Taxes and Charges from here.",
- "field": "",
"fieldname": "taxes",
"fieldtype": "Table",
"has_next_condition": 0,
"is_table_field": 0,
"label": "Sales Taxes and Charges",
- "parent_field": "",
"position": "Bottom",
"title": "Sales Taxes and Charges"
}
diff --git a/erpnext/setup/module_onboarding/home/home.json b/erpnext/setup/module_onboarding/home/home.json
index 1fd9679..7b0d77f 100644
--- a/erpnext/setup/module_onboarding/home/home.json
+++ b/erpnext/setup/module_onboarding/home/home.json
@@ -25,7 +25,7 @@
"documentation_url": "https://docs.erpnext.com/docs/v14/user/manual/en/setting-up/company-setup",
"idx": 0,
"is_complete": 0,
- "modified": "2023-05-20 19:45:03.936741",
+ "modified": "2023-05-23 13:20:19.703506",
"modified_by": "Administrator",
"module": "Setup",
"name": "Home",
@@ -38,10 +38,7 @@
"step": "Create a Customer"
},
{
- "step": "Create a Supplier"
- },
- {
- "step": "Create a Quotation"
+ "step": "Create Your First Sales Invoice"
}
],
"subtitle": "Item, Customer, Supplier and Quotation",
diff --git a/erpnext/setup/onboarding_step/create_a_customer/create_a_customer.json b/erpnext/setup/onboarding_step/create_a_customer/create_a_customer.json
index 5b0fd41..dc07578 100644
--- a/erpnext/setup/onboarding_step/create_a_customer/create_a_customer.json
+++ b/erpnext/setup/onboarding_step/create_a_customer/create_a_customer.json
@@ -9,7 +9,7 @@
"is_complete": 0,
"is_single": 0,
"is_skipped": 0,
- "modified": "2023-05-16 20:01:34.202622",
+ "modified": "2023-05-23 12:45:55.138580",
"modified_by": "Administrator",
"name": "Create a Customer",
"owner": "Administrator",
diff --git a/erpnext/setup/onboarding_step/create_an_item/create_an_item.json b/erpnext/setup/onboarding_step/create_an_item/create_an_item.json
index 15f36be..4115196 100644
--- a/erpnext/setup/onboarding_step/create_an_item/create_an_item.json
+++ b/erpnext/setup/onboarding_step/create_an_item/create_an_item.json
@@ -11,7 +11,7 @@
"is_complete": 0,
"is_single": 0,
"is_skipped": 0,
- "modified": "2023-05-16 12:56:40.355878",
+ "modified": "2023-05-23 12:43:08.484206",
"modified_by": "Administrator",
"name": "Create an Item",
"owner": "Administrator",
diff --git a/erpnext/setup/onboarding_step/create_your_first_sales_invoice/create_your_first_sales_invoice.json b/erpnext/setup/onboarding_step/create_your_first_sales_invoice/create_your_first_sales_invoice.json
new file mode 100644
index 0000000..96fa68e
--- /dev/null
+++ b/erpnext/setup/onboarding_step/create_your_first_sales_invoice/create_your_first_sales_invoice.json
@@ -0,0 +1,20 @@
+{
+ "action": "Create Entry",
+ "creation": "2020-05-14 17:48:21.019019",
+ "description": "# All about sales invoice\n\nA Sales Invoice is a bill that you send to your Customers against which the Customer makes the payment. Sales Invoice is an accounting transaction. On submission of Sales Invoice, the system updates the receivable and books income against a Customer Account.",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2023-05-22 21:20:15.589644",
+ "modified_by": "Administrator",
+ "name": "Create Your First Sales Invoice",
+ "owner": "Administrator",
+ "reference_document": "Sales Invoice",
+ "show_form_tour": 1,
+ "show_full_form": 1,
+ "title": "Create Your First Sales Invoice ",
+ "validate_action": 1
+}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py
index 74927c7..a9a9a1d 100644
--- a/erpnext/stock/doctype/pick_list/pick_list.py
+++ b/erpnext/stock/doctype/pick_list/pick_list.py
@@ -460,7 +460,7 @@
item_doc.qty if (docstatus == 1 and item_doc.stock_qty == 0) else item_doc.stock_qty
)
- while remaining_stock_qty > 0 and available_locations:
+ while flt(remaining_stock_qty) > 0 and available_locations:
item_location = available_locations.pop(0)
item_location = frappe._dict(item_location)