Merge branch 'version-13-hotfix' into e-commerce-refactor
This commit is contained in:
2
.github/workflows/semgrep.yml
vendored
2
.github/workflows/semgrep.yml
vendored
@@ -2,8 +2,6 @@ name: Semgrep
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request: { }
|
pull_request: { }
|
||||||
push:
|
|
||||||
branches: ["develop"]
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
semgrep:
|
semgrep:
|
||||||
|
|||||||
@@ -291,6 +291,7 @@ erpnext.patches.v13_0.rename_issue_status_hold_to_on_hold
|
|||||||
erpnext.patches.v13_0.bill_for_rejected_quantity_in_purchase_invoice
|
erpnext.patches.v13_0.bill_for_rejected_quantity_in_purchase_invoice
|
||||||
erpnext.patches.v13_0.update_job_card_details
|
erpnext.patches.v13_0.update_job_card_details
|
||||||
erpnext.patches.v13_0.update_level_in_bom #1234sswef
|
erpnext.patches.v13_0.update_level_in_bom #1234sswef
|
||||||
|
erpnext.patches.v13_0.add_missing_fg_item_for_stock_entry
|
||||||
erpnext.patches.v13_0.create_website_items
|
erpnext.patches.v13_0.create_website_items
|
||||||
erpnext.patches.v13_0.populate_e_commerce_settings
|
erpnext.patches.v13_0.populate_e_commerce_settings
|
||||||
erpnext.patches.v13_0.make_homepage_products_website_items
|
erpnext.patches.v13_0.make_homepage_products_website_items
|
||||||
|
|||||||
110
erpnext/patches/v13_0/add_missing_fg_item_for_stock_entry.py
Normal file
110
erpnext/patches/v13_0/add_missing_fg_item_for_stock_entry.py
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
# Copyright (c) 2020, Frappe and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
from frappe.utils import cstr, flt, cint
|
||||||
|
from erpnext.stock.stock_ledger import make_sl_entries
|
||||||
|
from erpnext.controllers.stock_controller import create_repost_item_valuation_entry
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
if not frappe.db.has_column('Work Order', 'has_batch_no'):
|
||||||
|
return
|
||||||
|
|
||||||
|
if cint(frappe.db.get_single_value('Manufacturing Settings', 'make_serial_no_batch_from_work_order')):
|
||||||
|
return
|
||||||
|
|
||||||
|
frappe.reload_doc('manufacturing', 'doctype', 'work_order')
|
||||||
|
filters = {
|
||||||
|
'docstatus': 1,
|
||||||
|
'produced_qty': ('>', 0),
|
||||||
|
'creation': ('>=', '2021-06-29 00:00:00'),
|
||||||
|
'has_batch_no': 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fields = ['name', 'production_item']
|
||||||
|
|
||||||
|
work_orders = [d.name for d in frappe.get_all('Work Order', filters = filters, fields=fields)]
|
||||||
|
|
||||||
|
if not work_orders:
|
||||||
|
return
|
||||||
|
|
||||||
|
repost_stock_entries = []
|
||||||
|
stock_entries = frappe.db.sql_list('''
|
||||||
|
SELECT
|
||||||
|
se.name
|
||||||
|
FROM
|
||||||
|
`tabStock Entry` se
|
||||||
|
WHERE
|
||||||
|
se.purpose = 'Manufacture' and se.docstatus < 2 and se.work_order in {work_orders}
|
||||||
|
and not exists(
|
||||||
|
select name from `tabStock Entry Detail` sed where sed.parent = se.name and sed.is_finished_item = 1
|
||||||
|
)
|
||||||
|
Order BY
|
||||||
|
se.posting_date, se.posting_time
|
||||||
|
'''.format(work_orders=tuple(work_orders)))
|
||||||
|
|
||||||
|
if stock_entries:
|
||||||
|
print('Length of stock entries', len(stock_entries))
|
||||||
|
|
||||||
|
for stock_entry in stock_entries:
|
||||||
|
doc = frappe.get_doc('Stock Entry', stock_entry)
|
||||||
|
doc.set_work_order_details()
|
||||||
|
doc.load_items_from_bom()
|
||||||
|
doc.calculate_rate_and_amount()
|
||||||
|
set_expense_account(doc)
|
||||||
|
doc.make_batches('t_warehouse')
|
||||||
|
|
||||||
|
if doc.docstatus == 0:
|
||||||
|
doc.save()
|
||||||
|
else:
|
||||||
|
repost_stock_entry(doc)
|
||||||
|
repost_stock_entries.append(doc)
|
||||||
|
|
||||||
|
for repost_doc in repost_stock_entries:
|
||||||
|
repost_future_sle_and_gle(repost_doc)
|
||||||
|
|
||||||
|
def set_expense_account(doc):
|
||||||
|
for row in doc.items:
|
||||||
|
if row.is_finished_item and not row.expense_account:
|
||||||
|
row.expense_account = frappe.get_cached_value('Company', doc.company, 'stock_adjustment_account')
|
||||||
|
|
||||||
|
def repost_stock_entry(doc):
|
||||||
|
doc.db_update()
|
||||||
|
for child_row in doc.items:
|
||||||
|
if child_row.is_finished_item:
|
||||||
|
child_row.db_update()
|
||||||
|
|
||||||
|
sl_entries = []
|
||||||
|
finished_item_row = doc.get_finished_item_row()
|
||||||
|
get_sle_for_target_warehouse(doc, sl_entries, finished_item_row)
|
||||||
|
|
||||||
|
if sl_entries:
|
||||||
|
try:
|
||||||
|
make_sl_entries(sl_entries, True)
|
||||||
|
except Exception:
|
||||||
|
print(f'SLE entries not posted for the stock entry {doc.name}')
|
||||||
|
traceback = frappe.get_traceback()
|
||||||
|
frappe.log_error(traceback)
|
||||||
|
|
||||||
|
def get_sle_for_target_warehouse(doc, sl_entries, finished_item_row):
|
||||||
|
for d in doc.get('items'):
|
||||||
|
if cstr(d.t_warehouse) and finished_item_row and d.name == finished_item_row.name:
|
||||||
|
sle = doc.get_sl_entries(d, {
|
||||||
|
"warehouse": cstr(d.t_warehouse),
|
||||||
|
"actual_qty": flt(d.transfer_qty),
|
||||||
|
"incoming_rate": flt(d.valuation_rate)
|
||||||
|
})
|
||||||
|
|
||||||
|
sle.recalculate_rate = 1
|
||||||
|
sl_entries.append(sle)
|
||||||
|
|
||||||
|
def repost_future_sle_and_gle(doc):
|
||||||
|
args = frappe._dict({
|
||||||
|
"posting_date": doc.posting_date,
|
||||||
|
"posting_time": doc.posting_time,
|
||||||
|
"voucher_type": doc.doctype,
|
||||||
|
"voucher_no": doc.name,
|
||||||
|
"company": doc.company
|
||||||
|
})
|
||||||
|
|
||||||
|
create_repost_item_valuation_entry(args)
|
||||||
@@ -133,6 +133,6 @@ def repost_entries():
|
|||||||
|
|
||||||
def get_repost_item_valuation_entries():
|
def get_repost_item_valuation_entries():
|
||||||
return frappe.db.sql(""" SELECT name from `tabRepost Item Valuation`
|
return frappe.db.sql(""" SELECT name from `tabRepost Item Valuation`
|
||||||
WHERE status != 'Completed' and creation <= %s and docstatus = 1
|
WHERE status in ('Queued', 'In Progress') and creation <= %s and docstatus = 1
|
||||||
ORDER BY timestamp(posting_date, posting_time) asc, creation asc
|
ORDER BY timestamp(posting_date, posting_time) asc, creation asc
|
||||||
""", now(), as_dict=1)
|
""", now(), as_dict=1)
|
||||||
|
|||||||
@@ -719,6 +719,10 @@ class StockEntry(StockController):
|
|||||||
frappe.throw(_("Multiple items cannot be marked as finished item"))
|
frappe.throw(_("Multiple items cannot be marked as finished item"))
|
||||||
|
|
||||||
if self.purpose == "Manufacture":
|
if self.purpose == "Manufacture":
|
||||||
|
if not finished_items:
|
||||||
|
frappe.throw(_('Finished Good has not set in the stock entry {0}')
|
||||||
|
.format(self.name))
|
||||||
|
|
||||||
allowance_percentage = flt(frappe.db.get_single_value("Manufacturing Settings",
|
allowance_percentage = flt(frappe.db.get_single_value("Manufacturing Settings",
|
||||||
"overproduction_percentage_for_work_order"))
|
"overproduction_percentage_for_work_order"))
|
||||||
|
|
||||||
|
|||||||
@@ -314,13 +314,16 @@ def update_included_uom_in_report(columns, result, include_uom, conversion_facto
|
|||||||
for row_idx, row in enumerate(result):
|
for row_idx, row in enumerate(result):
|
||||||
data = row.items() if is_dict_obj else enumerate(row)
|
data = row.items() if is_dict_obj else enumerate(row)
|
||||||
for key, value in data:
|
for key, value in data:
|
||||||
if key not in convertible_columns or not conversion_factors[row_idx-1]:
|
if key not in convertible_columns:
|
||||||
continue
|
continue
|
||||||
|
# If no conversion factor for the UOM, defaults to 1
|
||||||
|
if not conversion_factors[row_idx]:
|
||||||
|
conversion_factors[row_idx] = 1
|
||||||
|
|
||||||
if convertible_columns.get(key) == 'rate':
|
if convertible_columns.get(key) == 'rate':
|
||||||
new_value = flt(value) * conversion_factors[row_idx-1]
|
new_value = flt(value) * conversion_factors[row_idx]
|
||||||
else:
|
else:
|
||||||
new_value = flt(value) / conversion_factors[row_idx-1]
|
new_value = flt(value) / conversion_factors[row_idx]
|
||||||
|
|
||||||
if not is_dict_obj:
|
if not is_dict_obj:
|
||||||
row.insert(key+1, new_value)
|
row.insert(key+1, new_value)
|
||||||
|
|||||||
Reference in New Issue
Block a user