Skip to content

Commit

Permalink
feat: Reserved Stock Report
Browse files Browse the repository at this point in the history
  • Loading branch information
s-aga-r committed Aug 3, 2023
1 parent 78a9fa8 commit 48b546d
Show file tree
Hide file tree
Showing 5 changed files with 436 additions and 0 deletions.
Empty file.
167 changes: 167 additions & 0 deletions erpnext/stock/report/reserved_stock/reserved_stock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt

frappe.query_reports["Reserved Stock"] = {
filters: [
{
fieldname: "company",
label: __("Company"),
fieldtype: "Link",
options: "Company",
reqd: 1,
default: frappe.defaults.get_user_default("Company"),
},
{
fieldname: "from_date",
label: __("From Date"),
fieldtype: "Date",
default: frappe.datetime.add_months(
frappe.datetime.get_today(),
-1
),
reqd: 1,
},
{
fieldname: "to_date",
label: __("To Date"),
fieldtype: "Date",
default: frappe.datetime.get_today(),
reqd: 1,
},
{
fieldname: "item_code",
label: __("Item"),
fieldtype: "Link",
options: "Item",
get_query: () => ({
filters: {
is_stock_item: 1,
},
}),
},
{
fieldname: "warehouse",
label: __("Warehouse"),
fieldtype: "Link",
options: "Warehouse",
get_query: () => ({
filters: {
is_group: 0,
company: frappe.query_report.get_filter_value("company"),
},
}),
},
{
fieldname: "stock_reservation_entry",
label: __("Stock Reservation Entry"),
fieldtype: "Link",
options: "Stock Reservation Entry",
get_query: () => ({
filters: {
docstatus: 1,
company: frappe.query_report.get_filter_value("company"),
},
}),
},
{
fieldname: "voucher_type",
label: __("Voucher Type"),
fieldtype: "Link",
options: "DocType",
default: "Sales Order",
get_query: () => ({
filters: {
name: ["in", ["Sales Order"]],
}
}),
},
{
fieldname: "voucher_no",
label: __("Voucher No"),
fieldtype: "Dynamic Link",
options: "voucher_type",
get_query: () => ({
filters: {
docstatus: 1,
company: frappe.query_report.get_filter_value("company"),
},
}),
},
{
fieldname: "against_pick_list",
label: __("Against Pick List"),
fieldtype: "Link",
options: "Pick List",
get_query: () => ({
filters: {
docstatus: 1,
company: frappe.query_report.get_filter_value("company"),
},
}),
},
{
fieldname: "reservation_based_on",
label: __("Reservation Based On"),
fieldtype: "Select",
options: ["", "Qty", "Serial and Batch"],
},
{
fieldname: "status",
label: __("Status"),
fieldtype: "Select",
options: [
"",
"Partially Reserved",
"Reserved",
"Partially Delivered",
"Delivered",
],
},
{
fieldname: "project",
label: __("Project"),
fieldtype: "Link",
options: "Project",
get_query: () => ({
filters: {
company: frappe.query_report.get_filter_value("company"),
},
}),
},
],
formatter: (value, row, column, data, default_formatter) => {
value = default_formatter(value, row, column, data);

if (column.fieldname == "status") {
switch (data.status) {
case "Partially Reserved":
value = "<span style='color:orange'>" + value + "</span>";
break;
case "Reserved":
value = "<span style='color:blue'>" + value + "</span>";
break;
case "Partially Delivered":
value = "<span style='color:purple'>" + value + "</span>";
break;
case "Delivered":
value = "<span style='color:green'>" + value + "</span>";
break;
}
}
else if (column.fieldname == "delivered_qty") {
if (data.delivered_qty > 0) {
if (data.reserved_qty > data.delivered_qty) {
value = "<span style='color:blue'>" + value + "</span>";
}
else {
value = "<span style='color:green'>" + value + "</span>";
}
}
else {
value = "<span style='color:red'>" + value + "</span>";
}
}

return value;
},
};
26 changes: 26 additions & 0 deletions erpnext/stock/report/reserved_stock/reserved_stock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"add_total_row": 0,
"columns": [],
"creation": "2023-08-02 22:11:19.439620",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"filters": [],
"idx": 0,
"is_standard": "Yes",
"letterhead": null,
"modified": "2023-08-03 12:46:33.780222",
"modified_by": "Administrator",
"module": "Stock",
"name": "Reserved Stock",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "Stock Reservation Entry",
"report_name": "Reserved Stock",
"report_type": "Script Report",
"roles": [
{
"role": "System Manager"
}
]
}
192 changes: 192 additions & 0 deletions erpnext/stock/report/reserved_stock/reserved_stock.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt

import frappe
from frappe import _
from frappe.query_builder.functions import Date


def execute(filters=None):
columns, data = [], []

validate_filters(filters)

columns = get_columns()
data = get_data(filters)

return columns, data


def validate_filters(filters):
if not filters:
frappe.throw(_("Please set filters"))

for field in ["company", "from_date", "to_date"]:
if not filters.get(field):
frappe.throw(_("Please set {0}").format(field))

if filters.get("from_date") > filters.get("to_date"):
frappe.throw(_("From Date cannot be greater than To Date"))


def get_data(filters):
sre = frappe.qb.DocType("Stock Reservation Entry")
query = (
frappe.qb.from_(sre)
.select(
sre.creation,
sre.warehouse,
sre.item_code,
sre.stock_uom,
sre.voucher_qty,
sre.reserved_qty,
sre.delivered_qty,
(sre.available_qty - sre.reserved_qty).as_("available_qty"),
sre.voucher_type,
sre.voucher_no,
sre.against_pick_list,
sre.name.as_("stock_reservation_entry"),
sre.status,
sre.project,
sre.company,
)
.where(
(sre.docstatus == 1)
& (sre.company == filters.get("company"))
& (
(Date(sre.creation) >= filters.get("from_date"))
& (Date(sre.creation) <= filters.get("to_date"))
)
)
)

for field in [
"company",
"item_code",
"warehouse",
"voucher_type",
"voucher_no",
"against_pick_list",
"reservation_based_on",
"status",
"project",
]:
if value := filters.get(field):
query = query.where((sre[field] == value))

if value := filters.get("stock_reservation_entry"):
query = query.where((sre.name == value))

data = query.run(as_list=True)

return data


def get_columns():
columns = [
{
"label": _("Date"),
"fieldname": "date",
"fieldtype": "Datetime",
"width": 150,
},
{
"fieldname": "warehouse",
"label": _("Warehouse"),
"fieldtype": "Link",
"options": "Warehouse",
"width": 150,
},
{
"fieldname": "item_code",
"label": _("Item"),
"fieldtype": "Link",
"options": "Item",
"width": 100,
},
{
"fieldname": "stock_uom",
"label": _("Stock UOM"),
"fieldtype": "Link",
"options": "UOM",
"width": 100,
},
{
"fieldname": "voucher_qty",
"label": _("Voucher Qty"),
"fieldtype": "Float",
"width": 110,
"convertible": "qty",
},
{
"fieldname": "reserved_qty",
"label": _("Reserved Qty"),
"fieldtype": "Float",
"width": 110,
"convertible": "qty",
},
{
"fieldname": "delivered_qty",
"label": _("Delivered Qty"),
"fieldtype": "Float",
"width": 110,
"convertible": "qty",
},
{
"fieldname": "available_qty",
"label": _("Available Qty to Reserve"),
"fieldtype": "Float",
"width": 120,
"convertible": "qty",
},
{
"fieldname": "voucher_type",
"label": _("Voucher Type"),
"fieldtype": "Data",
"options": "Warehouse",
"width": 110,
},
{
"fieldname": "voucher_no",
"label": _("Voucher No"),
"fieldtype": "Dynamic Link",
"options": "voucher_type",
"width": 120,
},
{
"fieldname": "against_pick_list",
"label": _("Against Pick List"),
"fieldtype": "Link",
"options": "Pick List",
"width": 130,
},
{
"fieldname": "stock_reservation_entry",
"label": _("Stock Reservation Entry"),
"fieldtype": "Link",
"options": "Stock Reservation Entry",
"width": 150,
},
{
"fieldname": "status",
"label": _("Status"),
"fieldtype": "Data",
"width": 120,
},
{
"fieldname": "project",
"label": _("Project"),
"fieldtype": "Link",
"options": "Project",
"width": 100,
},
{
"fieldname": "company",
"label": _("Company"),
"fieldtype": "Link",
"options": "Company",
"width": 110,
},
]

return columns
Loading

0 comments on commit 48b546d

Please sign in to comment.