Skip to content

Commit

Permalink
ci: track overrides for stock and manufacturing cycles
Browse files Browse the repository at this point in the history
  • Loading branch information
Rohan Bansal committed May 24, 2024
1 parent 1150314 commit 1841e05
Show file tree
Hide file tree
Showing 7 changed files with 218 additions and 127 deletions.
20 changes: 20 additions & 0 deletions .github/workflows/overrides.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Track Overrides

on:
pull_request:
branches:
- version-14
- version-15

jobs:
track_overrides:
runs-on: ubuntu-latest
name: Track Overrides
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Track Overrides
uses: diamorafaela/track-overrides@main
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
8 changes: 4 additions & 4 deletions inventory_tools/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,14 @@
# Override standard doctype classes

override_doctype_class = {
"Work Order": "inventory_tools.inventory_tools.overrides.work_order.InventoryToolsWorkOrder",
"Job Card": "inventory_tools.inventory_tools.overrides.job_card.InventoryToolsJobCard",
"Production Plan": "inventory_tools.inventory_tools.overrides.production_plan.InventoryToolsProductionPlan",
"Purchase Invoice": "inventory_tools.inventory_tools.overrides.purchase_invoice.InventoryToolsPurchaseInvoice",
"Purchase Order": "inventory_tools.inventory_tools.overrides.purchase_order.InventoryToolsPurchaseOrder",
"Purchase Receipt": "inventory_tools.inventory_tools.overrides.purchase_receipt.InventoryToolsPurchaseReceipt",
"Production Plan": "inventory_tools.inventory_tools.overrides.production_plan.InventoryToolsProductionPlan",
"Stock Entry": "inventory_tools.inventory_tools.overrides.stock_entry.InventoryToolsStockEntry",
"Job Card": "inventory_tools.inventory_tools.overrides.job_card.InventoryToolsJobCard",
"Sales Order": "inventory_tools.inventory_tools.overrides.sales_order.InventoryToolsSalesOrder",
"Stock Entry": "inventory_tools.inventory_tools.overrides.stock_entry.InventoryToolsStockEntry",
"Work Order": "inventory_tools.inventory_tools.overrides.work_order.InventoryToolsWorkOrder",
}


Expand Down
7 changes: 7 additions & 0 deletions inventory_tools/inventory_tools/overrides/job_card.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@

class InventoryToolsJobCard(JobCard):
def validate_job_card(self):
"""
HASH: 4d34b1ead73baf4c5430a2ecbe44b9e8468d7626
REPO: https://github.com/frappe/erpnext/
PATH: erpnext/manufacturing/doctype/job_card/job_card.py
METHOD: validate_job_card
"""

if (
self.work_order
and frappe.get_cached_value("Work Order", self.work_order, "status") == "Stopped"
Expand Down
100 changes: 57 additions & 43 deletions inventory_tools/inventory_tools/overrides/production_plan.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,57 @@
import json

import frappe
from erpnext.manufacturing.doctype.production_plan.production_plan import ProductionPlan
from erpnext.manufacturing.doctype.work_order.work_order import get_default_warehouse


class InventoryToolsProductionPlan(ProductionPlan):
@frappe.whitelist()
def make_work_order(self):
wo_list, po_list = [], []
subcontracted_po = {}
default_warehouses = get_default_warehouse()

self.make_work_order_for_finished_goods(wo_list, default_warehouses)
self.make_work_order_for_subassembly_items(wo_list, subcontracted_po, default_warehouses)
if frappe.get_value("Inventory Tools Settings", self.company, "create_purchase_orders"):
self.make_subcontracted_purchase_order(subcontracted_po, po_list)
self.show_list_created_message("Work Order", wo_list)
self.show_list_created_message("Purchase Order", po_list)

def make_work_order_for_subassembly_items(self, wo_list, subcontracted_po, default_warehouses):
for row in self.sub_assembly_items:
if row.type_of_manufacturing == "Subcontract":
subcontracted_po.setdefault(row.supplier, []).append(row)
if not frappe.get_value(
"Inventory Tools Settings", self.company, "enable_work_order_subcontracting"
):
continue

if row.type_of_manufacturing == "Material Request":
continue

work_order_data = {
"wip_warehouse": default_warehouses.get("wip_warehouse"),
"fg_warehouse": default_warehouses.get("fg_warehouse"),
"company": self.get("company"),
}

self.prepare_data_for_sub_assembly_items(row, work_order_data)
work_order = self.create_work_order(work_order_data)
if work_order:
wo_list.append(work_order)
import json

import frappe
from erpnext.manufacturing.doctype.production_plan.production_plan import ProductionPlan
from erpnext.manufacturing.doctype.work_order.work_order import get_default_warehouse


class InventoryToolsProductionPlan(ProductionPlan):
@frappe.whitelist()
def make_work_order(self):
"""
HASH: b087fb3d549462ea8c9d1e65e8622e952d4039f6
REPO: https://github.com/frappe/erpnext/
PATH: erpnext/manufacturing/doctype/production_plan/production_plan.py
METHOD: make_work_order
"""

wo_list, po_list = [], []
subcontracted_po = {}
default_warehouses = get_default_warehouse()

self.make_work_order_for_finished_goods(wo_list, default_warehouses)
self.make_work_order_for_subassembly_items(wo_list, subcontracted_po, default_warehouses)
if frappe.get_value("Inventory Tools Settings", self.company, "create_purchase_orders"):
self.make_subcontracted_purchase_order(subcontracted_po, po_list)
self.show_list_created_message("Work Order", wo_list)
self.show_list_created_message("Purchase Order", po_list)

def make_work_order_for_subassembly_items(self, wo_list, subcontracted_po, default_warehouses):
"""
HASH: b087fb3d549462ea8c9d1e65e8622e952d4039f6
REPO: https://github.com/frappe/erpnext/
PATH: erpnext/manufacturing/doctype/production_plan/production_plan.py
METHOD: make_work_order_for_subassembly_items
"""

for row in self.sub_assembly_items:
if row.type_of_manufacturing == "Subcontract":
subcontracted_po.setdefault(row.supplier, []).append(row)
if not frappe.get_value(
"Inventory Tools Settings", self.company, "enable_work_order_subcontracting"
):
continue

if row.type_of_manufacturing == "Material Request":
continue

work_order_data = {
"wip_warehouse": default_warehouses.get("wip_warehouse"),
"fg_warehouse": default_warehouses.get("fg_warehouse"),
"company": self.get("company"),
}

self.prepare_data_for_sub_assembly_items(row, work_order_data)
work_order = self.create_work_order(work_order_data)
if work_order:
wo_list.append(work_order)
15 changes: 15 additions & 0 deletions inventory_tools/inventory_tools/overrides/stock_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
class InventoryToolsStockEntry(StockEntry):
def check_if_operations_completed(self):
"""
HASH: 153e0ba81b62acc170a951a289363fff5579edc7
REPO: https://github.com/frappe/erpnext/
PATH: erpnext/stock/doctype/stock_entry/stock_entry.py
METHOD: check_if_operations_completed
Original code checks that the stock entry amount plus what's already produced in the WO
is not larger than any operation's completed quantity (plus the overallowance amount).
Since customized code rewires so stock entries happen via a Job Card, the function now
Expand Down Expand Up @@ -45,6 +50,11 @@ def check_if_operations_completed(self):

def validate_finished_goods(self):
"""
HASH: 153e0ba81b62acc170a951a289363fff5579edc7
REPO: https://github.com/frappe/erpnext/
PATH: erpnext/stock/doctype/stock_entry/stock_entry.py
METHOD: validate_finished_goods
1. Check if FG exists (mfg, repack)
2. Check if Multiple FG Items are present (mfg)
3. Check FG Item and Qty against WO if present (mfg)
Expand Down Expand Up @@ -105,6 +115,11 @@ def validate_finished_goods(self):

def get_pending_raw_materials(self, backflush_based_on=None):
"""
HASH: 153e0ba81b62acc170a951a289363fff5579edc7
REPO: https://github.com/frappe/erpnext/
PATH: erpnext/stock/doctype/stock_entry/stock_entry.py
METHOD: get_pending_raw_materials
issue (item quantity) that is pending to issue or desire to transfer,
whichever is less
"""
Expand Down
161 changes: 84 additions & 77 deletions inventory_tools/inventory_tools/overrides/warehouse.py
Original file line number Diff line number Diff line change
@@ -1,77 +1,84 @@
# Copyright (c) 2023, AgriTheory and contributors
# For license information, please see license.txt

import frappe
from frappe.desk.reportview import get_filters_cond, get_match_cond
from frappe.desk.search import search_link


@frappe.whitelist()
def update_warehouse_path(doc, method=None) -> None:
if not frappe.db.exists("Inventory Tools Settings", doc.company):
return
warehouse_path = frappe.db.get_value(
"Inventory Tools Settings", doc.company, "update_warehouse_path"
)
if not warehouse_path:
return

def get_parents(doc):
parents = [doc.warehouse_name]
parent = doc.parent_warehouse
while parent:
parent_name = frappe.get_value("Warehouse", parent, "warehouse_name")
if parent_name != "All Warehouses":
parents.append(parent_name)
parent = frappe.get_value("Warehouse", parent, "parent_warehouse")
else:
break
return parents

def _update_warehouse_path(doc):
parents = get_parents(doc)
if parents:
if len(parents) > 1:
if parents[1] in parents[0]:
parents[0] = parents[0].replace(parents[1], "")
parents[0] = parents[0].replace(" - ", "")
return " \u21D2 ".join(parents[::-1])
else:
return ""

doc.warehouse_path = _update_warehouse_path(doc)


@frappe.whitelist()
def warehouse_query(doctype, txt, searchfield, start, page_len, filters):
company = frappe.defaults.get_defaults().get("company")
if not company:
return search_link(doctype, txt, searchfield, start, page_len, filters)
if not frappe.db.exists("Inventory Tools Settings", company) and frappe.db.get_value(
"Inventory Tools Settings", company, "update_warehouse_path"
):
return search_link(doctype, txt, searchfield, start, page_len, filters)
else:
doctype = "Warehouse"
conditions = []
searchfields = frappe.get_meta(doctype).get_search_fields()
searchfields.remove("name")
searchfields = ["name"] + searchfields

return frappe.db.sql(
f"""SELECT {', '.join(searchfields)}
FROM `tabWarehouse`
WHERE `tabWarehouse`.`{searchfield}` like %(txt)s
{get_filters_cond(doctype, filters, conditions).replace("%", "%%")}
{get_match_cond(doctype).replace("%", "%%")}
ORDER BY
IF(LOCATE(%(_txt)s, name), LOCATE(%(_txt)s, name), 99999),
idx DESC, name
LIMIT %(start)s, %(page_len)s""",
{
"txt": "%" + txt + "%",
"_txt": txt.replace("%", ""),
"start": start or 0,
"page_len": page_len or 20,
},
)
# Copyright (c) 2023, AgriTheory and contributors
# For license information, please see license.txt

import frappe
from frappe.desk.reportview import get_filters_cond, get_match_cond
from frappe.desk.search import search_link


@frappe.whitelist()
def update_warehouse_path(doc, method=None) -> None:
if not frappe.db.exists("Inventory Tools Settings", doc.company):
return
warehouse_path = frappe.db.get_value(
"Inventory Tools Settings", doc.company, "update_warehouse_path"
)
if not warehouse_path:
return

def get_parents(doc):
parents = [doc.warehouse_name]
parent = doc.parent_warehouse
while parent:
parent_name = frappe.get_value("Warehouse", parent, "warehouse_name")
if parent_name != "All Warehouses":
parents.append(parent_name)
parent = frappe.get_value("Warehouse", parent, "parent_warehouse")
else:
break
return parents

def _update_warehouse_path(doc):
parents = get_parents(doc)
if parents:
if len(parents) > 1:
if parents[1] in parents[0]:
parents[0] = parents[0].replace(parents[1], "")
parents[0] = parents[0].replace(" - ", "")
return " \u21D2 ".join(parents[::-1])
else:
return ""

doc.warehouse_path = _update_warehouse_path(doc)


@frappe.whitelist()
def warehouse_query(doctype, txt, searchfield, start, page_len, filters):
"""
HASH: 4d34b1ead73baf4c5430a2ecbe44b9e8468d7626
REPO: https://github.com/frappe/erpnext/
PATH: erpnext/controllers/queries.py
METHOD: warehouse_query
"""

company = frappe.defaults.get_defaults().get("company")
if not company:
return search_link(doctype, txt, searchfield, start, page_len, filters)
if not frappe.db.exists("Inventory Tools Settings", company) and frappe.db.get_value(
"Inventory Tools Settings", company, "update_warehouse_path"
):
return search_link(doctype, txt, searchfield, start, page_len, filters)
else:
doctype = "Warehouse"
conditions = []
searchfields = frappe.get_meta(doctype).get_search_fields()
searchfields.remove("name")
searchfields = ["name"] + searchfields

return frappe.db.sql(
f"""SELECT {', '.join(searchfields)}
FROM `tabWarehouse`
WHERE `tabWarehouse`.`{searchfield}` like %(txt)s
{get_filters_cond(doctype, filters, conditions).replace("%", "%%")}
{get_match_cond(doctype).replace("%", "%%")}
ORDER BY
IF(LOCATE(%(_txt)s, name), LOCATE(%(_txt)s, name), 99999),
idx DESC, name
LIMIT %(start)s, %(page_len)s""",
{
"txt": "%" + txt + "%",
"_txt": txt.replace("%", ""),
"start": start or 0,
"page_len": page_len or 20,
},
)
Loading

0 comments on commit 1841e05

Please sign in to comment.