Merge pull request #28269 from marination/pr-return-ux

refactor:  (ux) Accepted/Rejected/Received Qty UX
This commit is contained in:
Marica 2021-11-16 18:00:42 +05:30 committed by GitHub
commit 6bd0c1dbf1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 504 additions and 162 deletions

View File

@ -13,6 +13,7 @@ from erpnext.accounts.doctype.account.test_account import create_account, get_in
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
from erpnext.buying.doctype.supplier.test_supplier import create_supplier from erpnext.buying.doctype.supplier.test_supplier import create_supplier
from erpnext.controllers.accounts_controller import get_payment_terms from erpnext.controllers.accounts_controller import get_payment_terms
from erpnext.controllers.buying_controller import QtyMismatchError
from erpnext.exceptions import InvalidCurrency from erpnext.exceptions import InvalidCurrency
from erpnext.projects.doctype.project.test_project import make_project from erpnext.projects.doctype.project.test_project import make_project
from erpnext.stock.doctype.item.test_item import create_item from erpnext.stock.doctype.item.test_item import create_item
@ -35,6 +36,27 @@ class TestPurchaseInvoice(unittest.TestCase):
def tearDownClass(self): def tearDownClass(self):
unlink_payment_on_cancel_of_invoice(0) unlink_payment_on_cancel_of_invoice(0)
def test_purchase_invoice_received_qty(self):
"""
1. Test if received qty is validated against accepted + rejected
2. Test if received qty is auto set on save
"""
pi = make_purchase_invoice(
qty=1,
rejected_qty=1,
received_qty=3,
item_code="_Test Item Home Desktop 200",
rejected_warehouse = "_Test Rejected Warehouse - _TC",
update_stock=True, do_not_save=True)
self.assertRaises(QtyMismatchError, pi.save)
pi.items[0].received_qty = 0
pi.save()
self.assertEqual(pi.items[0].received_qty, 2)
# teardown
pi.delete()
def test_gl_entries_without_perpetual_inventory(self): def test_gl_entries_without_perpetual_inventory(self):
frappe.db.set_value("Company", "_Test Company", "round_off_account", "Round Off - _TC") frappe.db.set_value("Company", "_Test Company", "round_off_account", "Round Off - _TC")
pi = frappe.copy_doc(test_records[0]) pi = frappe.copy_doc(test_records[0])

View File

@ -22,10 +22,10 @@
"received_qty", "received_qty",
"qty", "qty",
"rejected_qty", "rejected_qty",
"stock_uom",
"col_break2", "col_break2",
"uom", "uom",
"conversion_factor", "conversion_factor",
"stock_uom",
"stock_qty", "stock_qty",
"sec_break1", "sec_break1",
"price_list_rate", "price_list_rate",
@ -175,7 +175,8 @@
{ {
"fieldname": "received_qty", "fieldname": "received_qty",
"fieldtype": "Float", "fieldtype": "Float",
"label": "Received Qty" "label": "Received Qty",
"read_only": 1
}, },
{ {
"bold": 1, "bold": 1,
@ -223,7 +224,7 @@
{ {
"fieldname": "stock_qty", "fieldname": "stock_qty",
"fieldtype": "Float", "fieldtype": "Float",
"label": "Stock Qty", "label": "Accepted Qty in Stock UOM",
"print_hide": 1, "print_hide": 1,
"read_only": 1, "read_only": 1,
"reqd": 1 "reqd": 1
@ -870,10 +871,11 @@
"idx": 1, "idx": 1,
"istable": 1, "istable": 1,
"links": [], "links": [],
"modified": "2021-09-01 16:04:03.538643", "modified": "2021-11-15 17:04:07.191013",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Purchase Invoice Item", "name": "Purchase Invoice Item",
"naming_rule": "Random",
"owner": "Administrator", "owner": "Administrator",
"permissions": [], "permissions": [],
"sort_field": "modified", "sort_field": "modified",

View File

@ -3,7 +3,7 @@
import frappe import frappe
from frappe import _, msgprint from frappe import ValidationError, _, msgprint
from frappe.contacts.doctype.address.address import get_address_display from frappe.contacts.doctype.address.address import get_address_display
from frappe.utils import cint, cstr, flt, getdate from frappe.utils import cint, cstr, flt, getdate
@ -17,6 +17,9 @@ from erpnext.stock.get_item_details import get_conversion_factor
from erpnext.stock.utils import get_incoming_rate from erpnext.stock.utils import get_incoming_rate
class QtyMismatchError(ValidationError):
pass
class BuyingController(StockController, Subcontracting): class BuyingController(StockController, Subcontracting):
def get_feed(self): def get_feed(self):
@ -360,19 +363,15 @@ class BuyingController(StockController, Subcontracting):
def validate_accepted_rejected_qty(self): def validate_accepted_rejected_qty(self):
for d in self.get("items"): for d in self.get("items"):
self.validate_negative_quantity(d, ["received_qty","qty", "rejected_qty"]) self.validate_negative_quantity(d, ["received_qty","qty", "rejected_qty"])
if not flt(d.received_qty) and flt(d.qty):
d.received_qty = flt(d.qty) - flt(d.rejected_qty)
elif not flt(d.qty) and flt(d.rejected_qty): if not flt(d.received_qty) and (flt(d.qty) or flt(d.rejected_qty)):
d.qty = flt(d.received_qty) - flt(d.rejected_qty) d.received_qty = flt(d.qty) + flt(d.rejected_qty)
elif not flt(d.rejected_qty):
d.rejected_qty = flt(d.received_qty) - flt(d.qty)
val = flt(d.qty) + flt(d.rejected_qty)
# Check Received Qty = Accepted Qty + Rejected Qty # Check Received Qty = Accepted Qty + Rejected Qty
val = flt(d.qty) + flt(d.rejected_qty)
if (flt(val, d.precision("received_qty")) != flt(d.received_qty, d.precision("received_qty"))): if (flt(val, d.precision("received_qty")) != flt(d.received_qty, d.precision("received_qty"))):
frappe.throw(_("Accepted + Rejected Qty must be equal to Received quantity for Item {0}").format(d.item_code)) message = _("Row #{0}: Received Qty must be equal to Accepted + Rejected Qty for Item {1}").format(d.idx, d.item_code)
frappe.throw(msg=message, title=_("Mismatch"), exc=QtyMismatchError)
def validate_negative_quantity(self, item_row, field_list): def validate_negative_quantity(self, item_row, field_list):
if self.is_return: if self.is_return:

View File

@ -165,45 +165,33 @@ erpnext.buying.BuyingController = class BuyingController extends erpnext.Transac
} }
qty(doc, cdt, cdn) { qty(doc, cdt, cdn) {
var item = frappe.get_doc(cdt, cdn);
if ((doc.doctype == "Purchase Receipt") || (doc.doctype == "Purchase Invoice" && (doc.update_stock || doc.is_return))) { if ((doc.doctype == "Purchase Receipt") || (doc.doctype == "Purchase Invoice" && (doc.update_stock || doc.is_return))) {
frappe.model.round_floats_in(item, ["qty", "received_qty"]); this.calculate_received_qty(doc, cdt, cdn)
if(!doc.is_return && this.validate_negative_quantity(cdt, cdn, item, ["qty", "received_qty"])){ return }
if(!item.rejected_qty && item.qty) {
item.received_qty = item.qty;
}
frappe.model.round_floats_in(item, ["qty", "received_qty"]);
item.rejected_qty = flt(item.received_qty - item.qty, precision("rejected_qty", item));
item.received_stock_qty = flt(item.conversion_factor, precision("conversion_factor", item)) * flt(item.received_qty);
} }
super.qty(doc, cdt, cdn); super.qty(doc, cdt, cdn);
} }
rejected_qty(doc, cdt, cdn) {
this.calculate_received_qty(doc, cdt, cdn)
}
calculate_received_qty(doc, cdt, cdn){
var item = frappe.get_doc(cdt, cdn);
frappe.model.round_floats_in(item, ["qty", "rejected_qty"]);
if(!doc.is_return && this.validate_negative_quantity(cdt, cdn, item, ["qty", "rejected_qty"])){ return }
let received_qty = flt(item.qty + item.rejected_qty, precision("received_qty", item));
let received_stock_qty = flt(item.conversion_factor, precision("conversion_factor", item)) * flt(received_qty);
frappe.model.set_value(cdt, cdn, "received_qty", received_qty);
frappe.model.set_value(cdt, cdn, "received_stock_qty", received_stock_qty);
}
batch_no(doc, cdt, cdn) { batch_no(doc, cdt, cdn) {
super.batch_no(doc, cdt, cdn); super.batch_no(doc, cdt, cdn);
} }
received_qty(doc, cdt, cdn) {
this.calculate_accepted_qty(doc, cdt, cdn)
}
rejected_qty(doc, cdt, cdn) {
this.calculate_accepted_qty(doc, cdt, cdn)
}
calculate_accepted_qty(doc, cdt, cdn){
var item = frappe.get_doc(cdt, cdn);
frappe.model.round_floats_in(item, ["received_qty", "rejected_qty"]);
if(!doc.is_return && this.validate_negative_quantity(cdt, cdn, item, ["received_qty", "rejected_qty"])){ return }
item.qty = flt(item.received_qty - item.rejected_qty, precision("qty", item));
this.qty(doc, cdt, cdn);
}
validate_negative_quantity(cdt, cdn, item, fieldnames){ validate_negative_quantity(cdt, cdn, item, fieldnames){
if(!item || !fieldnames) { return } if(!item || !fieldnames) { return }

View File

@ -10,6 +10,7 @@ from frappe.utils import add_days, cint, cstr, flt, today
import erpnext import erpnext
from erpnext.accounts.doctype.account.test_account import get_inventory_account from erpnext.accounts.doctype.account.test_account import get_inventory_account
from erpnext.controllers.buying_controller import QtyMismatchError
from erpnext.stock.doctype.item.test_item import create_item, make_item from erpnext.stock.doctype.item.test_item import create_item, make_item
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice
from erpnext.stock.doctype.serial_no.serial_no import SerialNoDuplicateError, get_serial_nos from erpnext.stock.doctype.serial_no.serial_no import SerialNoDuplicateError, get_serial_nos
@ -22,20 +23,54 @@ class TestPurchaseReceipt(ERPNextTestCase):
def setUp(self): def setUp(self):
frappe.db.set_value("Buying Settings", None, "allow_multiple_items", 1) frappe.db.set_value("Buying Settings", None, "allow_multiple_items", 1)
def test_purchase_receipt_received_qty(self):
"""
1. Test if received qty is validated against accepted + rejected
2. Test if received qty is auto set on save
"""
pr = make_purchase_receipt(
qty=1,
rejected_qty=1,
received_qty=3,
item_code="_Test Item Home Desktop 200",
do_not_save=True
)
self.assertRaises(QtyMismatchError, pr.save)
pr.items[0].received_qty = 0
pr.save()
self.assertEqual(pr.items[0].received_qty, 2)
# teardown
pr.delete()
def test_reverse_purchase_receipt_sle(self): def test_reverse_purchase_receipt_sle(self):
pr = make_purchase_receipt(qty=0.5, item_code="_Test Item Home Desktop 200") pr = make_purchase_receipt(qty=0.5, item_code="_Test Item Home Desktop 200")
sl_entry = frappe.db.get_all("Stock Ledger Entry", {"voucher_type": "Purchase Receipt", sl_entry = frappe.db.get_all(
"voucher_no": pr.name}, ['actual_qty']) "Stock Ledger Entry",
{
"voucher_type": "Purchase Receipt",
"voucher_no": pr.name
},
['actual_qty']
)
self.assertEqual(len(sl_entry), 1) self.assertEqual(len(sl_entry), 1)
self.assertEqual(sl_entry[0].actual_qty, 0.5) self.assertEqual(sl_entry[0].actual_qty, 0.5)
pr.cancel() pr.cancel()
sl_entry_cancelled = frappe.db.get_all("Stock Ledger Entry", {"voucher_type": "Purchase Receipt", sl_entry_cancelled = frappe.db.get_all(
"voucher_no": pr.name}, ['actual_qty'], order_by='creation') "Stock Ledger Entry",
{
"voucher_type": "Purchase Receipt",
"voucher_no": pr.name
},
['actual_qty'],
order_by='creation'
)
self.assertEqual(len(sl_entry_cancelled), 2) self.assertEqual(len(sl_entry_cancelled), 2)
self.assertEqual(sl_entry_cancelled[1].actual_qty, -0.5) self.assertEqual(sl_entry_cancelled[1].actual_qty, -0.5)
@ -61,8 +96,15 @@ class TestPurchaseReceipt(ERPNextTestCase):
}] }]
}).insert() }).insert()
template = frappe.db.get_value('Payment Terms Template', '_Test Payment Terms Template For Purchase Invoice') template = frappe.db.get_value(
old_template_in_supplier = frappe.db.get_value("Supplier", "_Test Supplier", "payment_terms") "Payment Terms Template",
"_Test Payment Terms Template For Purchase Invoice"
)
old_template_in_supplier = frappe.db.get_value(
"Supplier",
"_Test Supplier",
"payment_terms"
)
frappe.db.set_value("Supplier", "_Test Supplier", "payment_terms", template) frappe.db.set_value("Supplier", "_Test Supplier", "payment_terms", template)
pr = make_purchase_receipt(do_not_save=True) pr = make_purchase_receipt(do_not_save=True)
@ -88,30 +130,59 @@ class TestPurchaseReceipt(ERPNextTestCase):
# teardown # teardown
pi.delete() # draft PI pi.delete() # draft PI
pr.cancel() pr.cancel()
frappe.db.set_value("Supplier", "_Test Supplier", "payment_terms", old_template_in_supplier) frappe.db.set_value(
frappe.get_doc('Payment Terms Template', '_Test Payment Terms Template For Purchase Invoice').delete() "Supplier",
"_Test Supplier",
"payment_terms",
old_template_in_supplier
)
frappe.get_doc(
"Payment Terms Template",
"_Test Payment Terms Template For Purchase Invoice"
).delete()
def test_purchase_receipt_no_gl_entry(self): def test_purchase_receipt_no_gl_entry(self):
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') existing_bin_qty, existing_bin_stock_value = frappe.db.get_value(
"Bin",
existing_bin_qty, existing_bin_stock_value = frappe.db.get_value("Bin", {"item_code": "_Test Item", {
"warehouse": "_Test Warehouse - _TC"}, ["actual_qty", "stock_value"]) "item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC"
},
["actual_qty", "stock_value"]
)
if existing_bin_qty < 0: if existing_bin_qty < 0:
make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=abs(existing_bin_qty)) make_stock_entry(
item_code="_Test Item",
target="_Test Warehouse - _TC",
qty=abs(existing_bin_qty)
)
pr = make_purchase_receipt() pr = make_purchase_receipt()
stock_value_difference = frappe.db.get_value("Stock Ledger Entry", stock_value_difference = frappe.db.get_value(
{"voucher_type": "Purchase Receipt", "voucher_no": pr.name, "Stock Ledger Entry",
"item_code": "_Test Item", "warehouse": "_Test Warehouse - _TC"}, "stock_value_difference") {
"voucher_type": "Purchase Receipt",
"voucher_no": pr.name,
"item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC"
},
"stock_value_difference"
)
self.assertEqual(stock_value_difference, 250) self.assertEqual(stock_value_difference, 250)
current_bin_stock_value = frappe.db.get_value("Bin", {"item_code": "_Test Item", current_bin_stock_value = frappe.db.get_value(
"warehouse": "_Test Warehouse - _TC"}, "stock_value") "Bin",
{
"item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC"
},
"stock_value"
)
self.assertEqual(current_bin_stock_value, existing_bin_stock_value + 250) self.assertEqual(current_bin_stock_value, existing_bin_stock_value + 250)
self.assertFalse(get_gl_entries("Purchase Receipt", pr.name)) self.assertFalse(get_gl_entries("Purchase Receipt", pr.name))
@ -133,13 +204,17 @@ class TestPurchaseReceipt(ERPNextTestCase):
pr = make_purchase_receipt(item_code=item.name, qty=5, rate=500) pr = make_purchase_receipt(item_code=item.name, qty=5, rate=500)
self.assertTrue(frappe.db.get_value('Batch', {'item': item.name, 'reference_name': pr.name})) self.assertTrue(
frappe.db.get_value('Batch', {'item': item.name, 'reference_name': pr.name})
)
pr.load_from_db() pr.load_from_db()
batch_no = pr.items[0].batch_no batch_no = pr.items[0].batch_no
pr.cancel() pr.cancel()
self.assertFalse(frappe.db.get_value('Batch', {'item': item.name, 'reference_name': pr.name})) self.assertFalse(
frappe.db.get_value('Batch', {'item': item.name, 'reference_name': pr.name})
)
self.assertFalse(frappe.db.get_all('Serial No', {'batch_no': batch_no})) self.assertFalse(frappe.db.get_all('Serial No', {'batch_no': batch_no}))
def test_duplicate_serial_nos(self): def test_duplicate_serial_nos(self):
@ -158,42 +233,78 @@ class TestPurchaseReceipt(ERPNextTestCase):
pr = make_purchase_receipt(item_code=item.name, qty=2, rate=500) pr = make_purchase_receipt(item_code=item.name, qty=2, rate=500)
pr.load_from_db() pr.load_from_db()
serial_nos = frappe.db.get_value('Stock Ledger Entry', serial_nos = frappe.db.get_value(
{'voucher_type': 'Purchase Receipt', 'voucher_no': pr.name, 'item_code': item.name}, 'serial_no') "Stock Ledger Entry",
{
"voucher_type": "Purchase Receipt",
"voucher_no": pr.name,
"item_code": item.name
},
"serial_no"
)
serial_nos = get_serial_nos(serial_nos) serial_nos = get_serial_nos(serial_nos)
self.assertEquals(get_serial_nos(pr.items[0].serial_no), serial_nos) self.assertEquals(get_serial_nos(pr.items[0].serial_no), serial_nos)
# Then tried to receive same serial nos in difference company # Then tried to receive same serial nos in difference company
pr_different_company = make_purchase_receipt(item_code=item.name, qty=2, rate=500, pr_different_company = make_purchase_receipt(
serial_no='\n'.join(serial_nos), company='_Test Company 1', do_not_submit=True, item_code=item.name,
warehouse = 'Stores - _TC1') qty=2,
rate=500,
serial_no='\n'.join(serial_nos),
company='_Test Company 1',
do_not_submit=True,
warehouse = 'Stores - _TC1'
)
self.assertRaises(SerialNoDuplicateError, pr_different_company.submit) self.assertRaises(SerialNoDuplicateError, pr_different_company.submit)
# Then made delivery note to remove the serial nos from stock # Then made delivery note to remove the serial nos from stock
dn = create_delivery_note(item_code=item.name, qty=2, rate = 1500, serial_no='\n'.join(serial_nos)) dn = create_delivery_note(
item_code=item.name,
qty=2,
rate=1500,
serial_no='\n'.join(serial_nos)
)
dn.load_from_db() dn.load_from_db()
self.assertEquals(get_serial_nos(dn.items[0].serial_no), serial_nos) self.assertEquals(get_serial_nos(dn.items[0].serial_no), serial_nos)
posting_date = add_days(today(), -3) posting_date = add_days(today(), -3)
# Try to receive same serial nos again in the same company with backdated. # Try to receive same serial nos again in the same company with backdated.
pr1 = make_purchase_receipt(item_code=item.name, qty=2, rate=500, pr1 = make_purchase_receipt(
posting_date=posting_date, serial_no='\n'.join(serial_nos), do_not_submit=True) item_code=item.name,
qty=2,
rate=500,
posting_date=posting_date,
serial_no='\n'.join(serial_nos),
do_not_submit=True
)
self.assertRaises(SerialNoExistsInFutureTransaction, pr1.submit) self.assertRaises(SerialNoExistsInFutureTransaction, pr1.submit)
# Try to receive same serial nos with different company with backdated. # Try to receive same serial nos with different company with backdated.
pr2 = make_purchase_receipt(item_code=item.name, qty=2, rate=500, pr2 = make_purchase_receipt(
posting_date=posting_date, serial_no='\n'.join(serial_nos), company='_Test Company 1', do_not_submit=True, item_code=item.name,
warehouse = 'Stores - _TC1') qty=2,
rate=500,
posting_date=posting_date,
serial_no='\n'.join(serial_nos),
company="_Test Company 1",
do_not_submit=True,
warehouse="Stores - _TC1"
)
self.assertRaises(SerialNoExistsInFutureTransaction, pr2.submit) self.assertRaises(SerialNoExistsInFutureTransaction, pr2.submit)
# Receive the same serial nos after the delivery note posting date and time # Receive the same serial nos after the delivery note posting date and time
make_purchase_receipt(item_code=item.name, qty=2, rate=500, serial_no='\n'.join(serial_nos)) make_purchase_receipt(
item_code=item.name,
qty=2,
rate=500,
serial_no='\n'.join(serial_nos)
)
# Raise the error for backdated deliver note entry cancel # Raise the error for backdated deliver note entry cancel
self.assertRaises(SerialNoExistsInFutureTransaction, dn.cancel) self.assertRaises(SerialNoExistsInFutureTransaction, dn.cancel)
@ -236,11 +347,23 @@ class TestPurchaseReceipt(ERPNextTestCase):
def test_subcontracting(self): def test_subcontracting(self):
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
frappe.db.set_value("Buying Settings", None, "backflush_raw_materials_of_subcontract_based_on", "BOM") frappe.db.set_value(
make_stock_entry(item_code="_Test Item", target="_Test Warehouse 1 - _TC", qty=100, basic_rate=100) "Buying Settings", None,
make_stock_entry(item_code="_Test Item Home Desktop 100", target="_Test Warehouse 1 - _TC", "backflush_raw_materials_of_subcontract_based_on", "BOM"
qty=100, basic_rate=100) )
pr = make_purchase_receipt(item_code="_Test FG Item", qty=10, rate=500, is_subcontracted="Yes")
make_stock_entry(
item_code="_Test Item", qty=100,
target="_Test Warehouse 1 - _TC", basic_rate=100
)
make_stock_entry(
item_code="_Test Item Home Desktop 100", qty=100,
target="_Test Warehouse 1 - _TC", basic_rate=100
)
pr = make_purchase_receipt(
item_code="_Test FG Item", qty=10,
rate=500, is_subcontracted="Yes"
)
self.assertEqual(len(pr.get("supplied_items")), 2) self.assertEqual(len(pr.get("supplied_items")), 2)
rm_supp_cost = sum(d.amount for d in pr.get("supplied_items")) rm_supp_cost = sum(d.amount for d in pr.get("supplied_items"))
@ -250,17 +373,33 @@ class TestPurchaseReceipt(ERPNextTestCase):
def test_subcontracting_gle_fg_item_rate_zero(self): def test_subcontracting_gle_fg_item_rate_zero(self):
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
frappe.db.set_value("Buying Settings", None, "backflush_raw_materials_of_subcontract_based_on", "BOM") frappe.db.set_value(
"Buying Settings", None,
"backflush_raw_materials_of_subcontract_based_on", "BOM"
)
se1 = make_stock_entry(item_code="_Test Item", target="Work In Progress - TCP1", se1 = make_stock_entry(
qty=100, basic_rate=100, company="_Test Company with perpetual inventory") item_code="_Test Item",
target="Work In Progress - TCP1",
qty=100, basic_rate=100,
company="_Test Company with perpetual inventory"
)
se2 = make_stock_entry(item_code="_Test Item Home Desktop 100", target="Work In Progress - TCP1", se2 = make_stock_entry(
qty=100, basic_rate=100, company="_Test Company with perpetual inventory") item_code="_Test Item Home Desktop 100",
target="Work In Progress - TCP1",
qty=100, basic_rate=100,
company="_Test Company with perpetual inventory"
)
pr = make_purchase_receipt(item_code="_Test FG Item", qty=10, rate=0, is_subcontracted="Yes", pr = make_purchase_receipt(
company="_Test Company with perpetual inventory", warehouse='Stores - TCP1', item_code="_Test FG Item",
supplier_warehouse='Work In Progress - TCP1') qty=10, rate=0,
is_subcontracted="Yes",
company="_Test Company with perpetual inventory",
warehouse="Stores - TCP1",
supplier_warehouse="Work In Progress - TCP1"
)
gl_entries = get_gl_entries("Purchase Receipt", pr.name) gl_entries = get_gl_entries("Purchase Receipt", pr.name)
@ -295,12 +434,22 @@ class TestPurchaseReceipt(ERPNextTestCase):
is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC") is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC")
# stock raw materials in a warehouse before transfer # stock raw materials in a warehouse before transfer
se1 = make_stock_entry(target="_Test Warehouse - _TC", make_stock_entry(
item_code = "Test Extra Item 1", qty=10, basic_rate=100) target="_Test Warehouse - _TC",
se2 = make_stock_entry(target="_Test Warehouse - _TC", item_code = "Test Extra Item 1",
item_code = "_Test FG Item", qty=1, basic_rate=100) qty=10, basic_rate=100
se3 = make_stock_entry(target="_Test Warehouse - _TC", )
item_code = "Test Extra Item 2", qty=1, basic_rate=100) make_stock_entry(
target="_Test Warehouse - _TC",
item_code = "_Test FG Item",
qty=1, basic_rate=100
)
make_stock_entry(
target="_Test Warehouse - _TC",
item_code = "Test Extra Item 2",
qty=1, basic_rate=100
)
rm_items = [ rm_items = [
{ {
"item_code": item_code, "item_code": item_code,
@ -334,11 +483,17 @@ class TestPurchaseReceipt(ERPNextTestCase):
def test_serial_no_supplier(self): def test_serial_no_supplier(self):
pr = make_purchase_receipt(item_code="_Test Serialized Item With Series", qty=1) pr = make_purchase_receipt(item_code="_Test Serialized Item With Series", qty=1)
self.assertEqual(frappe.db.get_value("Serial No", pr.get("items")[0].serial_no, "supplier"), pr_row_1_serial_no = pr.get("items")[0].serial_no
pr.supplier)
self.assertEqual(
frappe.db.get_value("Serial No", pr_row_1_serial_no, "supplier"),
pr.supplier
)
pr.cancel() pr.cancel()
self.assertFalse(frappe.db.get_value("Serial No", pr.get("items")[0].serial_no, "warehouse")) self.assertFalse(
frappe.db.get_value("Serial No", pr_row_1_serial_no, "warehouse")
)
def test_rejected_serial_no(self): def test_rejected_serial_no(self):
pr = frappe.copy_doc(test_records[0]) pr = frappe.copy_doc(test_records[0])
@ -365,18 +520,33 @@ class TestPurchaseReceipt(ERPNextTestCase):
pr.cancel() pr.cancel()
def test_purchase_return_partial(self): def test_purchase_return_partial(self):
pr = make_purchase_receipt(company="_Test Company with perpetual inventory", pr = make_purchase_receipt(
warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1") company="_Test Company with perpetual inventory",
warehouse = "Stores - TCP1",
supplier_warehouse = "Work in Progress - TCP1"
)
return_pr = make_purchase_receipt(company="_Test Company with perpetual inventory", return_pr = make_purchase_receipt(
warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1", company="_Test Company with perpetual inventory",
is_return=1, return_against=pr.name, qty=-2, do_not_submit=1) warehouse = "Stores - TCP1",
supplier_warehouse = "Work in Progress - TCP1",
is_return=1,
return_against=pr.name,
qty=-2,
do_not_submit=1
)
return_pr.items[0].purchase_receipt_item = pr.items[0].name return_pr.items[0].purchase_receipt_item = pr.items[0].name
return_pr.submit() return_pr.submit()
# check sle # check sle
outgoing_rate = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Purchase Receipt", outgoing_rate = frappe.db.get_value(
"voucher_no": return_pr.name}, "outgoing_rate") "Stock Ledger Entry",
{
"voucher_type": "Purchase Receipt",
"voucher_no": return_pr.name
},
"outgoing_rate"
)
self.assertEqual(outgoing_rate, 50) self.assertEqual(outgoing_rate, 50)
@ -440,11 +610,21 @@ class TestPurchaseReceipt(ERPNextTestCase):
pr.cancel() pr.cancel()
def test_purchase_return_full(self): def test_purchase_return_full(self):
pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", pr = make_purchase_receipt(
supplier_warehouse = "Work in Progress - TCP1") company="_Test Company with perpetual inventory",
warehouse = "Stores - TCP1",
supplier_warehouse = "Work in Progress - TCP1"
)
return_pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", return_pr = make_purchase_receipt(
supplier_warehouse = "Work in Progress - TCP1", is_return=1, return_against=pr.name, qty=-5, do_not_submit=1) company="_Test Company with perpetual inventory",
warehouse = "Stores - TCP1",
supplier_warehouse = "Work in Progress - TCP1",
is_return=1,
return_against=pr.name,
qty=-5,
do_not_submit=1
)
return_pr.items[0].purchase_receipt_item = pr.items[0].name return_pr.items[0].purchase_receipt_item = pr.items[0].name
return_pr.submit() return_pr.submit()
@ -466,15 +646,41 @@ class TestPurchaseReceipt(ERPNextTestCase):
rejected_warehouse="_Test Rejected Warehouse - TCP1" rejected_warehouse="_Test Rejected Warehouse - TCP1"
if not frappe.db.exists("Warehouse", rejected_warehouse): if not frappe.db.exists("Warehouse", rejected_warehouse):
get_warehouse(company = "_Test Company with perpetual inventory", get_warehouse(
abbr = " - TCP1", warehouse_name = "_Test Rejected Warehouse").name company = "_Test Company with perpetual inventory",
abbr = " - TCP1",
warehouse_name = "_Test Rejected Warehouse"
).name
pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1", received_qty=4, qty=2, rejected_warehouse=rejected_warehouse) pr = make_purchase_receipt(
company="_Test Company with perpetual inventory",
warehouse = "Stores - TCP1",
supplier_warehouse = "Work in Progress - TCP1",
qty=2,
rejected_qty=2,
rejected_warehouse=rejected_warehouse
)
return_pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1", is_return=1, return_against=pr.name, received_qty = -4, qty=-2, rejected_warehouse=rejected_warehouse) return_pr = make_purchase_receipt(
company="_Test Company with perpetual inventory",
warehouse = "Stores - TCP1",
supplier_warehouse = "Work in Progress - TCP1",
is_return=1,
return_against=pr.name,
qty=-2,
rejected_qty = -2,
rejected_warehouse=rejected_warehouse
)
actual_qty = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Purchase Receipt", actual_qty = frappe.db.get_value(
"voucher_no": return_pr.name, 'warehouse': return_pr.items[0].rejected_warehouse}, "actual_qty") "Stock Ledger Entry",
{
"voucher_type": "Purchase Receipt",
"voucher_no": return_pr.name,
"warehouse": return_pr.items[0].rejected_warehouse
},
"actual_qty"
)
self.assertEqual(actual_qty, -2) self.assertEqual(actual_qty, -2)
@ -499,8 +705,13 @@ class TestPurchaseReceipt(ERPNextTestCase):
"purchase_document_no": pr.name "purchase_document_no": pr.name
}) })
return_pr = make_purchase_receipt(item_code="_Test Serialized Item With Series", qty=-1, return_pr = make_purchase_receipt(
is_return=1, return_against=pr.name, serial_no=serial_no) item_code="_Test Serialized Item With Series",
qty=-1,
is_return=1,
return_against=pr.name,
serial_no=serial_no
)
_check_serial_no_values(serial_no, { _check_serial_no_values(serial_no, {
"warehouse": "", "warehouse": "",
@ -522,9 +733,21 @@ class TestPurchaseReceipt(ERPNextTestCase):
}) })
row.db_update() row.db_update()
pr = make_purchase_receipt(item_code=item_code, qty=1, uom="Box", conversion_factor=1.0) pr = make_purchase_receipt(
return_pr = make_purchase_receipt(item_code=item_code, qty=-10, uom="Unit", item_code=item_code,
stock_uom="Box", conversion_factor=0.1, is_return=1, return_against=pr.name) qty=1,
uom="Box",
conversion_factor=1.0
)
return_pr = make_purchase_receipt(
item_code=item_code,
qty=-10,
uom="Unit",
stock_uom="Box",
conversion_factor=0.1,
is_return=1,
return_against=pr.name
)
self.assertEqual(abs(return_pr.items[0].stock_qty), 1.0) self.assertEqual(abs(return_pr.items[0].stock_qty), 1.0)
@ -540,13 +763,19 @@ class TestPurchaseReceipt(ERPNextTestCase):
pr.submit() pr.submit()
update_purchase_receipt_status(pr.name, "Closed") update_purchase_receipt_status(pr.name, "Closed")
self.assertEqual(frappe.db.get_value("Purchase Receipt", pr.name, "status"), "Closed") self.assertEqual(
frappe.db.get_value("Purchase Receipt", pr.name, "status"), "Closed"
)
pr.reload() pr.reload()
pr.cancel() pr.cancel()
def test_pr_billing_status(self): def test_pr_billing_status(self):
# PO -> PR1 -> PI and PO -> PI and PO -> PR2 """Flow:
1. PO -> PR1 -> PI
2. PO -> PI
3. PO -> PR2.
"""
from erpnext.buying.doctype.purchase_order.purchase_order import ( from erpnext.buying.doctype.purchase_order.purchase_order import (
make_purchase_invoice as make_purchase_invoice_from_po, make_purchase_invoice as make_purchase_invoice_from_po,
) )
@ -610,21 +839,39 @@ class TestPurchaseReceipt(ERPNextTestCase):
pr_doc = make_purchase_receipt(item_code=item_code, pr_doc = make_purchase_receipt(item_code=item_code,
qty=1, serial_no = serial_no) qty=1, serial_no = serial_no)
self.assertEqual(serial_no, frappe.db.get_value("Serial No", self.assertEqual(
{"purchase_document_type": "Purchase Receipt", "purchase_document_no": pr_doc.name}, "name")) serial_no,
frappe.db.get_value(
"Serial No",
{
"purchase_document_type": "Purchase Receipt",
"purchase_document_no": pr_doc.name
},
"name"
)
)
pr_doc.cancel() pr_doc.cancel()
# check for the auto created serial nos # check for the auto created serial nos
item_code = "Test Auto Created Serial No" item_code = "Test Auto Created Serial No"
if not frappe.db.exists("Item", item_code): if not frappe.db.exists("Item", item_code):
item = make_item(item_code, dict(has_serial_no=1, serial_no_series="KLJL.###")) make_item(item_code, dict(has_serial_no=1, serial_no_series="KLJL.###"))
new_pr_doc = make_purchase_receipt(item_code=item_code, qty=1) new_pr_doc = make_purchase_receipt(item_code=item_code, qty=1)
serial_no = get_serial_nos(new_pr_doc.items[0].serial_no)[0] serial_no = get_serial_nos(new_pr_doc.items[0].serial_no)[0]
self.assertEqual(serial_no, frappe.db.get_value("Serial No", self.assertEqual(
{"purchase_document_type": "Purchase Receipt", "purchase_document_no": new_pr_doc.name}, "name")) serial_no,
frappe.db.get_value(
"Serial No",
{
"purchase_document_type": "Purchase Receipt",
"purchase_document_no": new_pr_doc.name
},
"name"
)
)
new_pr_doc.cancel() new_pr_doc.cancel()
@ -700,8 +947,12 @@ class TestPurchaseReceipt(ERPNextTestCase):
def test_purchase_receipt_cost_center(self): def test_purchase_receipt_cost_center(self):
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
cost_center = "_Test Cost Center for BS Account - TCP1" cost_center = "_Test Cost Center for BS Account - TCP1"
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company with perpetual inventory") create_cost_center(
cost_center_name="_Test Cost Center for BS Account",
company="_Test Company with perpetual inventory"
)
if not frappe.db.exists('Location', 'Test Location'): if not frappe.db.exists('Location', 'Test Location'):
frappe.get_doc({ frappe.get_doc({
@ -709,10 +960,16 @@ class TestPurchaseReceipt(ERPNextTestCase):
'location_name': 'Test Location' 'location_name': 'Test Location'
}).insert() }).insert()
pr = make_purchase_receipt(cost_center=cost_center, company="_Test Company with perpetual inventory", pr = make_purchase_receipt(
warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1") cost_center=cost_center,
company="_Test Company with perpetual inventory",
warehouse = "Stores - TCP1",
supplier_warehouse = "Work in Progress - TCP1"
)
stock_in_hand_account = get_inventory_account(pr.company, pr.get("items")[0].warehouse) stock_in_hand_account = get_inventory_account(
pr.company, pr.get("items")[0].warehouse
)
gl_entries = get_gl_entries("Purchase Receipt", pr.name) gl_entries = get_gl_entries("Purchase Receipt", pr.name)
self.assertTrue(gl_entries) self.assertTrue(gl_entries)
@ -736,9 +993,16 @@ class TestPurchaseReceipt(ERPNextTestCase):
'doctype': 'Location', 'doctype': 'Location',
'location_name': 'Test Location' 'location_name': 'Test Location'
}).insert() }).insert()
pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1")
stock_in_hand_account = get_inventory_account(pr.company, pr.get("items")[0].warehouse) pr = make_purchase_receipt(
company="_Test Company with perpetual inventory",
warehouse = "Stores - TCP1",
supplier_warehouse = "Work in Progress - TCP1"
)
stock_in_hand_account = get_inventory_account(
pr.company, pr.get("items")[0].warehouse
)
gl_entries = get_gl_entries("Purchase Receipt", pr.name) gl_entries = get_gl_entries("Purchase Receipt", pr.name)
self.assertTrue(gl_entries) self.assertTrue(gl_entries)
@ -766,7 +1030,11 @@ class TestPurchaseReceipt(ERPNextTestCase):
po = create_purchase_order() po = create_purchase_order()
pr = create_pr_against_po(po.name) pr = create_pr_against_po(po.name)
pr1 = make_purchase_receipt(is_return=1, return_against=pr.name, qty=-1, do_not_submit=True) pr1 = make_purchase_receipt(
qty=-1,
is_return=1, return_against=pr.name,
do_not_submit=True
)
pr1.items[0].purchase_order = po.name pr1.items[0].purchase_order = po.name
pr1.items[0].purchase_order_item = po.items[0].name pr1.items[0].purchase_order_item = po.items[0].name
pr1.items[0].purchase_receipt_item = pr.items[0].name pr1.items[0].purchase_receipt_item = pr.items[0].name
@ -799,7 +1067,11 @@ class TestPurchaseReceipt(ERPNextTestCase):
pi1.save() pi1.save()
pi1.submit() pi1.submit()
pr2 = make_purchase_receipt(is_return=1, return_against=pr1.name, qty=-2, do_not_submit=True) pr2 = make_purchase_receipt(
qty=-2,
is_return=1, return_against=pr1.name,
do_not_submit=True
)
pr2.items[0].purchase_receipt_item = pr1.items[0].name pr2.items[0].purchase_receipt_item = pr1.items[0].name
pr2.submit() pr2.submit()
@ -841,14 +1113,22 @@ class TestPurchaseReceipt(ERPNextTestCase):
pr1.cancel() pr1.cancel()
def test_stock_transfer_from_purchase_receipt_with_valuation(self): def test_stock_transfer_from_purchase_receipt_with_valuation(self):
create_warehouse("_Test Warehouse for Valuation", company="_Test Company with perpetual inventory", create_warehouse(
properties={"account": '_Test Account Stock In Hand - TCP1'}) "_Test Warehouse for Valuation",
company="_Test Company with perpetual inventory",
properties={"account": '_Test Account Stock In Hand - TCP1'}
)
pr1 = make_purchase_receipt(warehouse = '_Test Warehouse for Valuation - TCP1', pr1 = make_purchase_receipt(
company="_Test Company with perpetual inventory") warehouse = '_Test Warehouse for Valuation - TCP1',
company="_Test Company with perpetual inventory"
)
pr = make_purchase_receipt(company="_Test Company with perpetual inventory", pr = make_purchase_receipt(
warehouse = "Stores - TCP1", do_not_save=1) company="_Test Company with perpetual inventory",
warehouse = "Stores - TCP1",
do_not_save=1
)
pr.items[0].from_warehouse = '_Test Warehouse for Valuation - TCP1' pr.items[0].from_warehouse = '_Test Warehouse for Valuation - TCP1'
pr.supplier_warehouse = '' pr.supplier_warehouse = ''
@ -930,10 +1210,24 @@ class TestPurchaseReceipt(ERPNextTestCase):
} }
rm_items = [ rm_items = [
{"item_code":item_code,"rm_item_code":"Sub Contracted Raw Material 3","item_name":"_Test Item", {
"qty":300,"warehouse":"_Test Warehouse - _TC", "stock_uom":"Nos", "name": po.supplied_items[0].name}, "item_code":item_code,
{"item_code":item_code,"rm_item_code":"Sub Contracted Raw Material 3","item_name":"_Test Item", "rm_item_code":"Sub Contracted Raw Material 3",
"qty":200,"warehouse":"_Test Warehouse - _TC", "stock_uom":"Nos", "name": po.supplied_items[0].name} "item_name":"_Test Item",
"qty":300,
"warehouse":"_Test Warehouse - _TC",
"stock_uom":"Nos",
"name": po.supplied_items[0].name
},
{
"item_code":item_code,
"rm_item_code":"Sub Contracted Raw Material 3",
"item_name":"_Test Item",
"qty":200,
"warehouse":"_Test Warehouse - _TC",
"stock_uom":"Nos",
"name": po.supplied_items[0].name
}
] ]
rm_item_string = json.dumps(rm_items) rm_item_string = json.dumps(rm_items)
@ -943,8 +1237,14 @@ class TestPurchaseReceipt(ERPNextTestCase):
se.items[1].batch_no = ste2.items[0].batch_no se.items[1].batch_no = ste2.items[0].batch_no
se.submit() se.submit()
supplied_qty = frappe.db.get_value("Purchase Order Item Supplied", supplied_qty = frappe.db.get_value(
{"parent": po.name, "rm_item_code": "Sub Contracted Raw Material 3"}, "supplied_qty") "Purchase Order Item Supplied",
{
"parent": po.name,
"rm_item_code": "Sub Contracted Raw Material 3"
},
"supplied_qty"
)
self.assertEqual(supplied_qty, 500.00) self.assertEqual(supplied_qty, 500.00)
@ -1016,10 +1316,18 @@ class TestPurchaseReceipt(ERPNextTestCase):
company = '_Test Company with perpetual inventory' company = '_Test Company with perpetual inventory'
service_item = '_Test Non Stock Item' service_item = '_Test Non Stock Item'
before_test_value = frappe.db.get_value('Company', company, 'enable_perpetual_inventory_for_non_stock_items') before_test_value = frappe.db.get_value(
frappe.db.set_value('Company', company, 'enable_perpetual_inventory_for_non_stock_items', 1) 'Company', company, 'enable_perpetual_inventory_for_non_stock_items'
)
frappe.db.set_value(
'Company', company,
'enable_perpetual_inventory_for_non_stock_items', 1
)
srbnb_account = 'Stock Received But Not Billed - TCP1' srbnb_account = 'Stock Received But Not Billed - TCP1'
frappe.db.set_value('Company', company, 'service_received_but_not_billed', srbnb_account) frappe.db.set_value(
'Company', company,
'service_received_but_not_billed', srbnb_account
)
pr = make_purchase_receipt( pr = make_purchase_receipt(
company=company, item=service_item, company=company, item=service_item,
@ -1051,7 +1359,10 @@ class TestPurchaseReceipt(ERPNextTestCase):
self.assertEqual(len(item_one_gl_entry), 1) self.assertEqual(len(item_one_gl_entry), 1)
self.assertEqual(len(item_two_gl_entry), 1) self.assertEqual(len(item_two_gl_entry), 1)
frappe.db.set_value('Company', company, 'enable_perpetual_inventory_for_non_stock_items', before_test_value) frappe.db.set_value(
'Company', company,
'enable_perpetual_inventory_for_non_stock_items', before_test_value
)
def test_purchase_receipt_with_exchange_rate_difference(self): def test_purchase_receipt_with_exchange_rate_difference(self):
from erpnext.accounts.doctype.purchase_invoice.purchase_invoice import ( from erpnext.accounts.doctype.purchase_invoice.purchase_invoice import (
@ -1076,10 +1387,19 @@ class TestPurchaseReceipt(ERPNextTestCase):
pr.submit() pr.submit()
# Get exchnage gain and loss account # Get exchnage gain and loss account
exchange_gain_loss_account = frappe.db.get_value('Company', pr.company, 'exchange_gain_loss_account') exchange_gain_loss_account = frappe.db.get_value(
'Company', pr.company, 'exchange_gain_loss_account'
)
# fetching the latest GL Entry with exchange gain and loss account account # fetching the latest GL Entry with exchange gain and loss account account
amount = frappe.db.get_value('GL Entry', {'account': exchange_gain_loss_account, 'voucher_no': pr.name}, 'credit') amount = frappe.db.get_value(
'GL Entry',
{
'account': exchange_gain_loss_account,
'voucher_no': pr.name
},
'credit'
)
discrepancy_caused_by_exchange_rate_diff = abs(pi.items[0].base_net_amount - pr.items[0].base_net_amount) discrepancy_caused_by_exchange_rate_diff = abs(pi.items[0].base_net_amount - pr.items[0].base_net_amount)
self.assertEqual(discrepancy_caused_by_exchange_rate_diff, amount) self.assertEqual(discrepancy_caused_by_exchange_rate_diff, amount)
@ -1225,8 +1545,8 @@ def make_purchase_receipt(**args):
pr.return_against = args.return_against pr.return_against = args.return_against
pr.apply_putaway_rule = args.apply_putaway_rule pr.apply_putaway_rule = args.apply_putaway_rule
qty = args.qty or 5 qty = args.qty or 5
received_qty = args.received_qty or qty rejected_qty = args.rejected_qty or 0
rejected_qty = args.rejected_qty or flt(received_qty) - flt(qty) received_qty = args.received_qty or flt(rejected_qty) + flt(qty)
item_code = args.item or args.item_code or "_Test Item" item_code = args.item or args.item_code or "_Test Item"
uom = args.uom or frappe.db.get_value("Item", item_code, "stock_uom") or "_Test UOM" uom = args.uom or frappe.db.get_value("Item", item_code, "stock_uom") or "_Test UOM"
@ -1249,9 +1569,12 @@ def make_purchase_receipt(**args):
if args.get_multiple_items: if args.get_multiple_items:
pr.items = [] pr.items = []
for item in get_items(warehouse= args.warehouse, cost_center = args.cost_center or frappe.get_cached_value('Company', pr.company, 'cost_center')):
pr.append("items", item)
company_cost_center = frappe.get_cached_value('Company', pr.company, 'cost_center')
cost_center = args.cost_center or company_cost_center
for item in get_items(warehouse=args.warehouse, cost_center=cost_center):
pr.append("items", item)
if args.get_taxes_and_charges: if args.get_taxes_and_charges:
for tax in get_taxes(): for tax in get_taxes():

View File

@ -197,6 +197,7 @@
}, },
{ {
"bold": 1, "bold": 1,
"default": "0",
"fieldname": "received_qty", "fieldname": "received_qty",
"fieldtype": "Float", "fieldtype": "Float",
"label": "Received Quantity", "label": "Received Quantity",
@ -204,6 +205,7 @@
"oldfieldtype": "Currency", "oldfieldtype": "Currency",
"print_hide": 1, "print_hide": 1,
"print_width": "100px", "print_width": "100px",
"read_only": 1,
"reqd": 1, "reqd": 1,
"width": "100px" "width": "100px"
}, },
@ -219,8 +221,10 @@
"width": "100px" "width": "100px"
}, },
{ {
"columns": 1,
"fieldname": "rejected_qty", "fieldname": "rejected_qty",
"fieldtype": "Float", "fieldtype": "Float",
"in_list_view": 1,
"label": "Rejected Quantity", "label": "Rejected Quantity",
"oldfieldname": "rejected_qty", "oldfieldname": "rejected_qty",
"oldfieldtype": "Currency", "oldfieldtype": "Currency",
@ -327,7 +331,7 @@
}, },
{ {
"bold": 1, "bold": 1,
"columns": 3, "columns": 2,
"fieldname": "rate", "fieldname": "rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"in_list_view": 1, "in_list_view": 1,
@ -543,6 +547,7 @@
"fieldname": "stock_qty", "fieldname": "stock_qty",
"fieldtype": "Float", "fieldtype": "Float",
"label": "Accepted Qty in Stock UOM", "label": "Accepted Qty in Stock UOM",
"no_copy": 1,
"oldfieldname": "stock_qty", "oldfieldname": "stock_qty",
"oldfieldtype": "Currency", "oldfieldtype": "Currency",
"print_hide": 1, "print_hide": 1,
@ -882,7 +887,9 @@
"fieldname": "received_stock_qty", "fieldname": "received_stock_qty",
"fieldtype": "Float", "fieldtype": "Float",
"label": "Received Qty in Stock UOM", "label": "Received Qty in Stock UOM",
"print_hide": 1 "no_copy": 1,
"print_hide": 1,
"read_only": 1
}, },
{ {
"depends_on": "eval: doc.uom != doc.stock_uom", "depends_on": "eval: doc.uom != doc.stock_uom",
@ -969,10 +976,11 @@
"idx": 1, "idx": 1,
"istable": 1, "istable": 1,
"links": [], "links": [],
"modified": "2021-09-01 16:02:40.338597", "modified": "2021-11-15 15:46:10.591600",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Stock", "module": "Stock",
"name": "Purchase Receipt Item", "name": "Purchase Receipt Item",
"naming_rule": "Random",
"owner": "Administrator", "owner": "Administrator",
"permissions": [], "permissions": [],
"quick_entry": 1, "quick_entry": 1,