feat: Putaway

This commit is contained in:
marination 2020-11-12 09:54:44 +05:30
parent 29a8994506
commit c1b0e65f9f
6 changed files with 242 additions and 0 deletions

View File

@ -0,0 +1,18 @@
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Putaway Rule', {
setup: function(frm) {
frm.set_query("warehouse", function() {
return {
"filters": {
"company": frm.doc.company,
"is_group": 0
}
};
});
}
// refresh: function(frm) {
// }
});

View File

@ -0,0 +1,111 @@
{
"actions": [],
"autoname": "format:{item_code}-{warehouse}",
"creation": "2020-11-09 11:39:46.489501",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"disable",
"item_code",
"item_name",
"warehouse",
"col_break_capacity",
"company",
"capacity",
"priority",
"stock_uom"
],
"fields": [
{
"fieldname": "item_code",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Item",
"options": "Item",
"reqd": 1
},
{
"fetch_from": "item_code.item_name",
"fieldname": "item_name",
"fieldtype": "Data",
"label": "Item Name",
"read_only": 1
},
{
"fieldname": "warehouse",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Warehouse",
"options": "Warehouse",
"reqd": 1
},
{
"fieldname": "col_break_capacity",
"fieldtype": "Column Break"
},
{
"default": "0",
"fieldname": "capacity",
"fieldtype": "Float",
"in_list_view": 1,
"label": "Capacity",
"reqd": 1
},
{
"default": "item_code.stock_uom",
"fieldname": "stock_uom",
"fieldtype": "Link",
"label": "Stock UOM",
"options": "UOM",
"read_only": 1
},
{
"default": "1",
"fieldname": "priority",
"fieldtype": "Int",
"label": "Priority"
},
{
"fieldname": "company",
"fieldtype": "Link",
"in_standard_filter": 1,
"label": "Company",
"options": "Company",
"reqd": 1
},
{
"default": "0",
"depends_on": "eval:!doc.__islocal",
"fieldname": "disable",
"fieldtype": "Check",
"label": "Disable"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2020-11-10 17:06:27.151335",
"modified_by": "Administrator",
"module": "Stock",
"name": "Putaway Rule",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@ -0,0 +1,93 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
import copy
from frappe import _
from frappe.utils import flt
from frappe.model.document import Document
class PutawayRule(Document):
def validate(self):
self.validate_duplicate_rule()
self.validate_warehouse_and_company()
self.validate_capacity()
self.validate_priority()
def validate_duplicate_rule(self):
existing_rule = frappe.db.exists("Putaway Rule", {"item_code": self.item_code, "warehouse": self.warehouse})
if existing_rule and existing_rule != self.name:
frappe.throw(_("Putaway Rule already exists for Item {0} in Warehouse {1}.")
.format(frappe.bold(self.item_code), frappe.bold(self.warehouse)),
title=_("Duplicate"))
def validate_priority(self):
if self.priority < 1:
frappe.throw(_("Priority cannot be lesser than 1."), title=_("Invalid Priority"))
def validate_warehouse_and_company(self):
company = frappe.db.get_value("Warehouse", self.warehouse, "company")
if company != self.company:
frappe.throw(_("Warehouse {0} does not belong to Company {1}.")
.format(frappe.bold(self.warehouse), frappe.bold(self.company)),
title=_("Invalid Warehouse"))
def validate_capacity(self):
# check if capacity is lesser than current balance in warehouse
pass
@frappe.whitelist()
def get_ordered_putaway_rules(item_code, company, qty):
"""Returns an ordered list of putaway rules to apply on an item."""
# get enabled putaway rules for this item code in this company that have pending capacity
# order the rules by priority first
# if same priority, order by pending capacity (capacity - get how much stock is in the warehouse)
# return this list
# [{'name': "something", "free space": 20}, {'name': "something", "free space": 10}]
@frappe.whitelist()
def apply_putaway_rule(items, company):
""" Applies Putaway Rule on line items.
items: List of line items in a Purchase Receipt
company: Company in Purchase Receipt
"""
items_not_accomodated = []
for item in items:
item_qty = item.qty
at_capacity, rules = get_ordered_putaway_rules(item.item_code, company, item_qty)
if not rules:
if at_capacity:
items_not_accomodated.append([item.item_code, item_qty])
continue
item_row_updated = False
for rule in rules:
while item_qty > 0:
if not item_row_updated:
# update pre-existing row
item.qty = rule.qty
item.warehouse = rule.warehouse
item_row_updated = True
else:
# add rows for split quantity
added_row = copy.deepcopy(item)
added_row.qty = rule.qty
added_row.warehouse = rule.warehouse
items.append(added_row)
item_qty -= flt(rule.qty)
# if pending qty after applying rules, add row without warehouse
if item_qty > 0:
added_row = copy.deepcopy(item)
added_row.qty = item_qty
added_row.warehouse = ''
items.append(added_row)
items_not_accomodated.append([item.item_code, item_qty])
# need to check pricing rule, item tax impact

View File

@ -0,0 +1,10 @@
frappe.listview_settings['Putaway Rule'] = {
add_fields: ["disable"],
get_indicator: (doc) => {
if (doc.disable) {
return [__("Disabled"), "darkgrey", "disable,=,1"];
} else {
return [__("Active"), "blue", "disable,=,0"];
};
}
};

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals
# import frappe
import unittest
class TestPutawayRule(unittest.TestCase):
pass