Merge branch 'develop' into fix_picked_qty_in_DN

This commit is contained in:
Marica 2021-04-05 16:24:53 +05:30 committed by GitHub
commit bc50193702
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 236 additions and 81 deletions

View File

@ -12,6 +12,10 @@ from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_pu
from erpnext.stock.doctype.item.test_item import make_item
class TestPOSInvoice(unittest.TestCase):
@classmethod
def setUpClass(cls):
frappe.db.sql("delete from `tabTax Rule`")
def tearDown(self):
if frappe.session.user != "Administrator":
frappe.set_user("Administrator")

View File

@ -14,10 +14,15 @@ test_records = frappe.get_test_records('Tax Rule')
from six import iteritems
class TestTaxRule(unittest.TestCase):
def setUp(self):
@classmethod
def setUpClass(cls):
frappe.db.set_value("Shopping Cart Settings", None, "enabled", 0)
@classmethod
def tearDownClass(cls):
frappe.db.sql("delete from `tabTax Rule`")
def tearDown(self):
def setUp(self):
frappe.db.sql("delete from `tabTax Rule`")
def test_conflict(self):

View File

@ -368,7 +368,6 @@ def make_purchase_receipt(source_name, target_doc=None):
"Purchase Order": {
"doctype": "Purchase Receipt",
"field_map": {
"per_billed": "per_billed",
"supplier_warehouse":"supplier_warehouse"
},
"validation": {

View File

@ -113,10 +113,10 @@ class calculate_taxes_and_totals(object):
item.rate_with_margin, item.base_rate_with_margin = self.calculate_margin(item)
if flt(item.rate_with_margin) > 0:
item.rate = flt(item.rate_with_margin * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate"))
if not item.discount_amount:
item.discount_amount = item.rate_with_margin - item.rate
elif not item.discount_percentage:
if item.discount_amount and not item.discount_percentage:
item.rate -= item.discount_amount
else:
item.discount_amount = item.rate_with_margin - item.rate
elif flt(item.price_list_rate) > 0:
item.discount_amount = item.price_list_rate - item.rate
elif flt(item.price_list_rate) > 0 and not item.discount_amount:
@ -808,4 +808,4 @@ class init_landed_taxes_and_totals(object):
def set_amounts_in_company_currency(self):
for d in self.doc.get(self.tax_field):
d.amount = flt(d.amount, d.precision("amount"))
d.base_amount = flt(d.amount * flt(d.exchange_rate), d.precision("base_amount"))
d.base_amount = flt(d.amount * flt(d.exchange_rate), d.precision("base_amount"))

View File

@ -81,15 +81,8 @@ class TestInpatientMedicationOrder(unittest.TestCase):
self.ip_record.reload()
discharge_patient(self.ip_record)
for entry in frappe.get_all('Inpatient Medication Entry'):
doc = frappe.get_doc('Inpatient Medication Entry', entry.name)
doc.cancel()
doc.delete()
for entry in frappe.get_all('Inpatient Medication Order'):
doc = frappe.get_doc('Inpatient Medication Order', entry.name)
doc.cancel()
doc.delete()
for doctype in ["Inpatient Medication Entry", "Inpatient Medication Order"]:
frappe.db.sql("delete from `tab{doctype}`".format(doctype=doctype))
def create_dosage_form():
if not frappe.db.exists('Dosage Form', 'Tablet'):

View File

@ -56,6 +56,7 @@ class TestLeaveApplication(unittest.TestCase):
@classmethod
def setUpClass(cls):
set_leave_approver()
frappe.db.sql("delete from tabAttendance where employee='_T-Employee-00001'")
def tearDown(self):
frappe.set_user("Administrator")
@ -230,8 +231,9 @@ class TestLeaveApplication(unittest.TestCase):
def test_optional_leave(self):
leave_period = get_leave_period()
today = nowdate()
from datetime import date
holiday_list = 'Test Holiday List for Optional Holiday'
optional_leave_date = add_days(today, 7)
if not frappe.db.exists('Holiday List', holiday_list):
frappe.get_doc(dict(
doctype = 'Holiday List',
@ -239,7 +241,7 @@ class TestLeaveApplication(unittest.TestCase):
from_date = add_months(today, -6),
to_date = add_months(today, 6),
holidays = [
dict(holiday_date = today, description = 'Test')
dict(holiday_date = optional_leave_date, description = 'Test')
]
)).insert()
employee = get_employee()
@ -255,7 +257,7 @@ class TestLeaveApplication(unittest.TestCase):
allocate_leaves(employee, leave_period, leave_type, 10)
date = add_days(today, - 1)
date = add_days(today, 6)
leave_application = frappe.get_doc(dict(
doctype = 'Leave Application',
@ -270,14 +272,14 @@ class TestLeaveApplication(unittest.TestCase):
# can only apply on optional holidays
self.assertRaises(NotAnOptionalHoliday, leave_application.insert)
leave_application.from_date = today
leave_application.to_date = today
leave_application.from_date = optional_leave_date
leave_application.to_date = optional_leave_date
leave_application.status = "Approved"
leave_application.insert()
leave_application.submit()
# check leave balance is reduced
self.assertEqual(get_leave_balance_on(employee.name, leave_type, today), 9)
self.assertEqual(get_leave_balance_on(employee.name, leave_type, optional_leave_date), 9)
def test_leaves_allowed(self):
employee = get_employee()
@ -341,7 +343,7 @@ class TestLeaveApplication(unittest.TestCase):
to_date = add_days(date, 4),
company = "_Test Company",
docstatus = 1,
status = "Approved"
status = "Approved"
))
self.assertRaises(frappe.ValidationError, leave_application.insert)
@ -363,7 +365,7 @@ class TestLeaveApplication(unittest.TestCase):
to_date = add_days(date, 4),
company = "_Test Company",
docstatus = 1,
status = "Approved"
status = "Approved"
))
self.assertTrue(leave_application.insert())
@ -393,7 +395,7 @@ class TestLeaveApplication(unittest.TestCase):
to_date = add_days(date, 4),
company = "_Test Company",
docstatus = 1,
status = "Approved"
status = "Approved"
))
self.assertRaises(frappe.ValidationError, leave_application.insert)
@ -508,7 +510,7 @@ class TestLeaveApplication(unittest.TestCase):
description = "_Test Reason",
company = "_Test Company",
docstatus = 1,
status = "Approved"
status = "Approved"
))
leave_application.submit()
leave_ledger_entry = frappe.get_all('Leave Ledger Entry', fields='*', filters=dict(transaction_name=leave_application.name))
@ -540,7 +542,7 @@ class TestLeaveApplication(unittest.TestCase):
description = "_Test Reason",
company = "_Test Company",
docstatus = 1,
status = "Approved"
status = "Approved"
))
leave_application.submit()

View File

@ -52,7 +52,9 @@ def create_leave_ledger_entry(ref_doc, args, submit=True):
ledger.update(args)
if submit:
frappe.get_doc(ledger).submit()
doc = frappe.get_doc(ledger)
doc.flags.ignore_permissions = 1
doc.submit()
else:
delete_ledger_entry(ledger)

View File

@ -1,4 +1,5 @@
{
"actions": [],
"autoname": "LM-LSS-.#####",
"creation": "2019-09-06 11:33:34.709540",
"doctype": "DocType",
@ -14,6 +15,7 @@
"shortfall_amount",
"column_break_8",
"security_value",
"shortfall_percentage",
"section_break_8",
"process_loan_security_shortfall"
],
@ -85,10 +87,18 @@
{
"fieldname": "column_break_8",
"fieldtype": "Column Break"
},
{
"fieldname": "shortfall_percentage",
"fieldtype": "Percent",
"label": "Shortfall Percentage",
"read_only": 1
}
],
"in_create": 1,
"modified": "2019-10-24 06:24:26.128997",
"index_web_pages_for_search": 1,
"links": [],
"modified": "2021-04-01 08:13:43.263772",
"modified_by": "Administrator",
"module": "Loan Management",
"name": "Loan Security Shortfall",

View File

@ -22,7 +22,9 @@ def update_shortfall_status(loan, security_value):
if security_value >= loan_security_shortfall.shortfall_amount:
frappe.db.set_value("Loan Security Shortfall", loan_security_shortfall.name, {
"status": "Completed",
"shortfall_amount": loan_security_shortfall.shortfall_amount})
"shortfall_amount": loan_security_shortfall.shortfall_amount,
"shortfall_percentage": 0
})
else:
frappe.db.set_value("Loan Security Shortfall", loan_security_shortfall.name,
"shortfall_amount", loan_security_shortfall.shortfall_amount - security_value)
@ -65,7 +67,8 @@ def check_for_ltv_shortfall(process_loan_security_shortfall):
outstanding_amount = flt(loan.total_payment) - flt(loan.total_interest_payable) \
- flt(loan.total_principal_paid)
else:
outstanding_amount = loan.disbursed_amount
outstanding_amount = flt(loan.disbursed_amount) - flt(loan.total_interest_payable) \
- flt(loan.total_principal_paid)
pledged_securities = get_pledged_security_qty(loan.name)
ltv_ratio = ''
@ -81,14 +84,15 @@ def check_for_ltv_shortfall(process_loan_security_shortfall):
if current_ratio > ltv_ratio:
shortfall_amount = outstanding_amount - ((security_value * ltv_ratio) / 100)
create_loan_security_shortfall(loan.name, outstanding_amount, security_value, shortfall_amount,
process_loan_security_shortfall)
current_ratio, process_loan_security_shortfall)
elif loan_shortfall_map.get(loan.name):
shortfall_amount = outstanding_amount - ((security_value * ltv_ratio) / 100)
if shortfall_amount <= 0:
shortfall = loan_shortfall_map.get(loan.name)
update_pending_shortfall(shortfall)
def create_loan_security_shortfall(loan, loan_amount, security_value, shortfall_amount, process_loan_security_shortfall):
def create_loan_security_shortfall(loan, loan_amount, security_value, shortfall_amount, shortfall_ratio,
process_loan_security_shortfall):
existing_shortfall = frappe.db.get_value("Loan Security Shortfall", {"loan": loan, "status": "Pending"}, "name")
if existing_shortfall:
@ -101,6 +105,7 @@ def create_loan_security_shortfall(loan, loan_amount, security_value, shortfall_
ltv_shortfall.loan_amount = loan_amount
ltv_shortfall.security_value = security_value
ltv_shortfall.shortfall_amount = shortfall_amount
ltv_shortfall.shortfall_percentage = shortfall_ratio
ltv_shortfall.process_loan_security_shortfall = process_loan_security_shortfall
ltv_shortfall.save()
@ -114,6 +119,7 @@ def update_pending_shortfall(shortfall):
frappe.db.set_value("Loan Security Shortfall", shortfall,
{
"status": "Completed",
"shortfall_amount": 0
"shortfall_amount": 0,
"shortfall_percentage": 0
})

View File

@ -63,9 +63,11 @@ def get_active_loan_details(filters):
currency = erpnext.get_company_currency(filters.get('company'))
for loan in loan_details:
total_payment = loan.total_payment if loan.status == 'Disbursed' else loan.disbursed_amount
loan.update({
"sanctioned_amount": flt(sanctioned_amount_map.get(loan.applicant_name)),
"principal_outstanding": flt(loan.total_payment) - flt(loan.total_principal_paid) \
"principal_outstanding": flt(total_payment) - flt(loan.total_principal_paid) \
- flt(loan.total_interest_payable) - flt(loan.written_off_amount),
"total_repayment": flt(payments.get(loan.loan)),
"accrued_interest": flt(accrual_map.get(loan.loan, {}).get("accrued_interest")),

View File

@ -134,7 +134,13 @@ class TestBOM(unittest.TestCase):
bom.items[0].conversion_factor = 6
bom.insert()
reset_item_valuation_rate(item_code='_Test Item', qty=200, rate=200)
reset_item_valuation_rate(
item_code='_Test Item',
warehouse_list=frappe.get_all("Warehouse",
{"is_group":0, "company": bom.company}, pluck="name"),
qty=200,
rate=200
)
bom.update_cost()

View File

@ -13,8 +13,15 @@ from erpnext.manufacturing.doctype.workstation.test_workstation import make_work
from erpnext.manufacturing.doctype.work_order.test_work_order import make_wo_order_test_record
class TestRouting(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.item_code = "Test Routing Item - A"
@classmethod
def tearDownClass(cls):
frappe.db.sql('delete from tabBOM where item=%s', cls.item_code)
def test_sequence_id(self):
item_code = "Test Routing Item - A"
operations = [{"operation": "Test Operation A", "workstation": "Test Workstation A", "time_in_mins": 30},
{"operation": "Test Operation B", "workstation": "Test Workstation A", "time_in_mins": 20}]
@ -22,8 +29,8 @@ class TestRouting(unittest.TestCase):
setup_operations(operations)
routing_doc = create_routing(routing_name="Testing Route", operations=operations)
bom_doc = setup_bom(item_code=item_code, routing=routing_doc.name)
wo_doc = make_wo_order_test_record(production_item = item_code, bom_no=bom_doc.name)
bom_doc = setup_bom(item_code=self.item_code, routing=routing_doc.name)
wo_doc = make_wo_order_test_record(production_item = self.item_code, bom_no=bom_doc.name)
for row in routing_doc.operations:
self.assertEqual(row.sequence_id, row.idx)

View File

@ -371,14 +371,14 @@ class TestWorkOrder(unittest.TestCase):
def test_job_card(self):
stock_entries = []
data = frappe.get_cached_value('BOM',
{'docstatus': 1, 'with_operations': 1, 'company': '_Test Company'}, ['name', 'item'])
bom = frappe.get_doc('BOM', {
'docstatus': 1,
'with_operations': 1,
'company': '_Test Company'
})
bom, bom_item = data
bom_doc = frappe.get_doc('BOM', bom)
work_order = make_wo_order_test_record(item=bom_item, qty=1,
bom_no=bom, source_warehouse="_Test Warehouse - _TC")
work_order = make_wo_order_test_record(item=bom.item, qty=1,
bom_no=bom.name, source_warehouse="_Test Warehouse - _TC")
for row in work_order.required_items:
stock_entry_doc = test_stock_entry.make_stock_entry(item_code=row.item_code,
@ -390,14 +390,14 @@ class TestWorkOrder(unittest.TestCase):
stock_entries.append(ste)
job_cards = frappe.get_all('Job Card', filters = {'work_order': work_order.name})
self.assertEqual(len(job_cards), len(bom_doc.operations))
self.assertEqual(len(job_cards), len(bom.operations))
for i, job_card in enumerate(job_cards):
doc = frappe.get_doc("Job Card", job_card)
doc.append("time_logs", {
"from_time": now(),
"hours": i,
"to_time": add_to_date(now(), i),
"from_time": add_to_date(None, i),
"hours": 1,
"to_time": add_to_date(None, i + 1),
"completed_qty": doc.for_quantity
})
doc.submit()

View File

@ -763,3 +763,4 @@ erpnext.patches.v13_0.setup_gratuity_rule_for_india_and_uae
erpnext.patches.v13_0.setup_uae_vat_fields
execute:frappe.db.set_value('System Settings', None, 'app_name', 'ERPNext')
erpnext.patches.v13_0.rename_discharge_date_in_ip_record
erpnext.patches.v12_0.purchase_receipt_status

View File

@ -0,0 +1,30 @@
""" This patch fixes old purchase receipts (PR) where even after submitting
the PR, the `status` remains "Draft". `per_billed` field was copied over from previous
doc (PO), hence it is recalculated for setting new correct status of PR.
"""
import frappe
logger = frappe.logger("patch", allow_site=True, file_count=50)
def execute():
affected_purchase_receipts = frappe.db.sql(
"""select name from `tabPurchase Receipt`
where status = 'Draft' and per_billed = 100 and docstatus = 1"""
)
if not affected_purchase_receipts:
return
logger.info("purchase_receipt_status: begin patch, PR count: {}"
.format(len(affected_purchase_receipts)))
for pr in affected_purchase_receipts:
pr_name = pr[0]
logger.info("purchase_receipt_status: patching PR - {}".format(pr_name))
pr_doc = frappe.get_doc("Purchase Receipt", pr_name)
pr_doc.update_billing_status(update_modified=False)
pr_doc.set_status(update=True, update_modified=False)

View File

@ -6,6 +6,8 @@ def execute():
if "Healthcare" not in frappe.get_active_domains():
return
frappe.reload_doc("healthcare", "doctype", "Therapy Session")
frappe.reload_doc("healthcare", "doctype", "Inpatient Medication Order")
frappe.reload_doc("healthcare", "doctype", "Patient History Settings")
frappe.reload_doc("healthcare", "doctype", "Patient History Standard Document Type")
frappe.reload_doc("healthcare", "doctype", "Patient History Custom Document Type")

View File

@ -618,13 +618,16 @@ class SalarySlip(TransactionBase):
component_row = self.append(component_type)
for attr in (
'depends_on_payment_days', 'salary_component', 'abbr'
'depends_on_payment_days', 'salary_component',
'do_not_include_in_total', 'is_tax_applicable',
'is_flexible_benefit', 'variable_based_on_taxable_salary',
'exempted_from_income_tax'
):
component_row.set(attr, component_data.get(attr))
abbr = component_data.get('abbr') or component_data.get('salary_component_abbr')
component_row.set('abbr', abbr)
if additional_salary:
component_row.default_amount = 0
component_row.additional_amount = amount

View File

@ -100,7 +100,7 @@ class SalaryStructure(Document):
from_date=from_date, base=base, variable=variable, income_tax_slab=income_tax_slab)
else:
assign_salary_structure_for_employees(employees, self,
payroll_payable_account=payroll_payable_account,
payroll_payable_account=payroll_payable_account,
from_date=from_date, base=base, variable=variable, income_tax_slab=income_tax_slab)
else:
frappe.msgprint(_("No Employee Found"))

View File

@ -87,10 +87,10 @@ def get_doc_details(invoice):
invoice_date=invoice_date
))
def get_party_details(address_name):
def get_party_details(address_name, company_address=None, billing_address=None, shipping_address=None):
d = frappe.get_all('Address', filters={'name': address_name}, fields=['*'])[0]
if (not d.gstin
if ((not d.gstin and not shipping_address)
or not d.city
or not d.pincode
or not d.address_title
@ -108,8 +108,7 @@ def get_party_details(address_name):
# according to einvoice standard
pincode = 999999
return frappe._dict(dict(
gstin=d.gstin,
party_address_details = frappe._dict(dict(
legal_name=sanitize_for_json(d.address_title),
location=sanitize_for_json(d.city),
pincode=d.pincode,
@ -117,6 +116,9 @@ def get_party_details(address_name):
address_line1=sanitize_for_json(d.address_line1),
address_line2=sanitize_for_json(d.address_line2)
))
if d.gstin:
party_address_details.gstin = d.gstin
return party_address_details
def get_gstin_details(gstin):
if not hasattr(frappe.local, 'gstin_cache'):
@ -328,12 +330,12 @@ def make_einvoice(invoice):
item_list = get_item_list(invoice)
doc_details = get_doc_details(invoice)
invoice_value_details = get_invoice_value_details(invoice)
seller_details = get_party_details(invoice.company_address)
seller_details = get_party_details(invoice.company_address, company_address=1)
if invoice.gst_category == 'Overseas':
buyer_details = get_overseas_address_details(invoice.customer_address)
else:
buyer_details = get_party_details(invoice.customer_address)
buyer_details = get_party_details(invoice.customer_address, billing_address=1)
place_of_supply = get_place_of_supply(invoice, invoice.doctype)
if place_of_supply:
place_of_supply = place_of_supply.split('-')[0]
@ -346,7 +348,7 @@ def make_einvoice(invoice):
if invoice.gst_category == 'Overseas':
shipping_details = get_overseas_address_details(invoice.shipping_address_name)
else:
shipping_details = get_party_details(invoice.shipping_address_name)
shipping_details = get_party_details(invoice.shipping_address_name, shipping_address=1)
if invoice.is_pos and invoice.base_paid_amount:
payment_details = get_payment_details(invoice)
@ -394,7 +396,9 @@ def safe_json_load(json_string):
snippet = json_string[start:end]
frappe.throw(_("Error in input data. Please check for any special characters near following input: <br> {}").format(snippet))
def validate_einvoice(validations, einvoice, errors=[]):
def validate_einvoice(validations, einvoice, errors=None):
if errors is None:
errors = []
for fieldname, field_validation in validations.items():
value = einvoice.get(fieldname, None)
if not value or value == "None":

View File

@ -16,6 +16,11 @@ class TestShoppingCart(unittest.TestCase):
Note:
Shopping Cart == Quotation
"""
@classmethod
def tearDownClass(cls):
frappe.db.sql("delete from `tabTax Rule`")
def setUp(self):
frappe.set_user("Administrator")
create_test_contact_and_address()
@ -51,8 +56,8 @@ class TestShoppingCart(unittest.TestCase):
def test_add_to_cart(self):
self.login_as_customer()
# remove from cart
self.remove_all_items_from_cart()
# clear existing quotations
self.clear_existing_quotations()
# add first item
update_cart("_Test Item", 1)
@ -100,6 +105,7 @@ class TestShoppingCart(unittest.TestCase):
self.assertEqual(len(quotation.get("items")), 1)
def test_tax_rule(self):
self.create_tax_rule()
self.login_as_customer()
quotation = self.create_quotation()
@ -115,6 +121,13 @@ class TestShoppingCart(unittest.TestCase):
self.remove_test_quotation(quotation)
def create_tax_rule(self):
tax_rule = frappe.get_test_records("Tax Rule")[0]
try:
frappe.get_doc(tax_rule).insert()
except frappe.DuplicateEntryError:
pass
def create_quotation(self):
quotation = frappe.new_doc("Quotation")
@ -195,10 +208,15 @@ class TestShoppingCart(unittest.TestCase):
"_Test Contact For _Test Customer")
frappe.set_user("test_contact_customer@example.com")
def remove_all_items_from_cart(self):
quotation = _get_cart_quotation()
quotation.flags.ignore_permissions=True
quotation.delete()
def clear_existing_quotations(self):
quotations = frappe.get_all("Quotation", filters={
"party_name": get_party().name,
"order_type": "Shopping Cart",
"docstatus": 0
}, order_by="modified desc", pluck="name")
for quotation in quotations:
frappe.delete_doc("Quotation", quotation, ignore_permissions=True, force=True)
def create_user_if_not_exists(self, email, first_name = None):
if frappe.db.exists("User", email):

View File

@ -23,7 +23,7 @@ class TestPickList(unittest.TestCase):
'purpose': 'Opening Stock',
'expense_account': 'Temporary Opening - _TC',
'items': [{
'item_code': '_Test Item Home Desktop 100',
'item_code': '_Test Item',
'warehouse': '_Test Warehouse - _TC',
'valuation_rate': 100,
'qty': 5
@ -38,7 +38,7 @@ class TestPickList(unittest.TestCase):
'customer': '_Test Customer',
'items_based_on': 'Sales Order',
'locations': [{
'item_code': '_Test Item Home Desktop 100',
'item_code': '_Test Item',
'qty': 5,
'stock_qty': 5,
'conversion_factor': 1,
@ -48,7 +48,7 @@ class TestPickList(unittest.TestCase):
})
pick_list.set_item_locations()
self.assertEqual(pick_list.locations[0].item_code, '_Test Item Home Desktop 100')
self.assertEqual(pick_list.locations[0].item_code, '_Test Item')
self.assertEqual(pick_list.locations[0].warehouse, '_Test Warehouse - _TC')
self.assertEqual(pick_list.locations[0].qty, 5)
@ -238,7 +238,7 @@ class TestPickList(unittest.TestCase):
'purpose': 'Opening Stock',
'expense_account': 'Temporary Opening - _TC',
'items': [{
'item_code': '_Test Item Home Desktop 100',
'item_code': '_Test Item',
'warehouse': '_Test Warehouse - _TC',
'valuation_rate': 100,
'qty': 10
@ -252,7 +252,7 @@ class TestPickList(unittest.TestCase):
'customer': '_Test Customer',
'company': '_Test Company',
'items': [{
'item_code': '_Test Item Home Desktop 100',
'item_code': '_Test Item',
'qty': 10,
'delivery_date': frappe.utils.today()
}],
@ -265,14 +265,14 @@ class TestPickList(unittest.TestCase):
'customer': '_Test Customer',
'items_based_on': 'Sales Order',
'locations': [{
'item_code': '_Test Item Home Desktop 100',
'item_code': '_Test Item',
'qty': 5,
'stock_qty': 5,
'conversion_factor': 1,
'sales_order': '_T-Sales Order-1',
'sales_order_item': '_T-Sales Order-1_item',
}, {
'item_code': '_Test Item Home Desktop 100',
'item_code': '_Test Item',
'qty': 5,
'stock_qty': 5,
'conversion_factor': 1,
@ -282,12 +282,12 @@ class TestPickList(unittest.TestCase):
})
pick_list.set_item_locations()
self.assertEqual(pick_list.locations[0].item_code, '_Test Item Home Desktop 100')
self.assertEqual(pick_list.locations[0].item_code, '_Test Item')
self.assertEqual(pick_list.locations[0].warehouse, '_Test Warehouse - _TC')
self.assertEqual(pick_list.locations[0].qty, 5)
self.assertEqual(pick_list.locations[0].sales_order_item, '_T-Sales Order-1_item')
self.assertEqual(pick_list.locations[1].item_code, '_Test Item Home Desktop 100')
self.assertEqual(pick_list.locations[1].item_code, '_Test Item')
self.assertEqual(pick_list.locations[1].warehouse, '_Test Warehouse - _TC')
self.assertEqual(pick_list.locations[1].qty, 5)
self.assertEqual(pick_list.locations[1].sales_order_item, sales_order.items[0].name)
@ -358,4 +358,4 @@ class TestPickList(unittest.TestCase):
# pass
# def test_pick_list_from_material_request(self):
# pass
# pass

View File

@ -176,7 +176,7 @@ class PurchaseReceipt(BuyingController):
if flt(self.per_billed) < 100:
self.update_billing_status()
else:
self.status = "Completed"
self.db_set("status", "Completed")
# Updating stock ledger should always be called after updating prevdoc status,

View File

@ -191,7 +191,7 @@ class TestPurchaseReceipt(unittest.TestCase):
rm_supp_cost = sum([d.amount for d in pr.get("supplied_items")])
self.assertEqual(pr.get("items")[0].rm_supp_cost, flt(rm_supp_cost, 2))
pr.cancel()
def test_subcontracting_gle_fg_item_rate_zero(self):
@ -912,6 +912,57 @@ class TestPurchaseReceipt(unittest.TestCase):
ste1.cancel()
po.cancel()
def test_po_to_pi_and_po_to_pr_worflow_full(self):
"""Test following behaviour:
- Create PO
- Create PI from PO and submit
- Create PR from PO and submit
"""
from erpnext.buying.doctype.purchase_order import test_purchase_order
from erpnext.buying.doctype.purchase_order import purchase_order
po = test_purchase_order.create_purchase_order()
pi = purchase_order.make_purchase_invoice(po.name)
pi.submit()
pr = purchase_order.make_purchase_receipt(po.name)
pr.submit()
pr.load_from_db()
self.assertEqual(pr.status, "Completed")
self.assertEqual(pr.per_billed, 100)
def test_po_to_pi_and_po_to_pr_worflow_partial(self):
"""Test following behaviour:
- Create PO
- Create partial PI from PO and submit
- Create PR from PO and submit
"""
from erpnext.buying.doctype.purchase_order import test_purchase_order
from erpnext.buying.doctype.purchase_order import purchase_order
po = test_purchase_order.create_purchase_order()
pi = purchase_order.make_purchase_invoice(po.name)
pi.items[0].qty /= 2 # roughly 50%, ^ this function only creates PI with 1 item.
pi.submit()
pr = purchase_order.make_purchase_receipt(po.name)
pr.save()
# per_billed is only updated after submission.
self.assertEqual(flt(pr.per_billed), 0)
pr.submit()
pi.load_from_db()
pr.load_from_db()
self.assertEqual(pr.status, "To Bill")
self.assertAlmostEqual(pr.per_billed, 50.0, places=2)
def get_sl_entries(voucher_type, voucher_no):
return frappe.db.sql(""" select actual_qty, warehouse, stock_value_difference
from `tabStock Ledger Entry` where voucher_type=%s and voucher_no=%s

View File

@ -100,6 +100,13 @@ frappe.ui.form.on('Stock Entry', {
frm.add_fetch("bom_no", "inspection_required", "inspection_required");
erpnext.accounts.dimensions.setup_dimension_filters(frm, frm.doctype);
frappe.db.get_single_value('Stock Settings', 'disable_serial_no_and_batch_selector')
.then((value) => {
if (value) {
frappe.flags.hide_serial_batch_dialog = true;
}
});
},
setup_quality_inspection: function(frm) {
@ -721,7 +728,7 @@ frappe.ui.form.on('Stock Entry Detail', {
no_batch_serial_number_value = !d.batch_no;
}
if (no_batch_serial_number_value) {
if (no_batch_serial_number_value && !frappe.flags.hide_serial_batch_dialog) {
erpnext.stock.select_batch_and_serial_no(frm, d);
}
}

View File

@ -313,8 +313,8 @@ class TestStockLedgerEntry(unittest.TestCase):
# Set User with Stock User role but not Stock Manager
try:
frappe.set_user("test@example.com")
user = frappe.get_doc("User", "test@example.com")
frappe.set_user(user.name)
user.add_roles("Stock User")
user.remove_roles("Stock Manager")
@ -325,7 +325,9 @@ class TestStockLedgerEntry(unittest.TestCase):
# Block back-dated entry
self.assertRaises(BackDatedStockTransaction, back_dated_se_1.submit)
frappe.set_user("Administrator")
user.add_roles("Stock Manager")
frappe.set_user(user.name)
# Back dated entry allowed to Stock Manager
back_dated_se_2 = make_stock_entry(target="_Test Warehouse - _TC", qty=10, basic_rate=100,
@ -337,6 +339,7 @@ class TestStockLedgerEntry(unittest.TestCase):
finally:
frappe.db.set_value("Stock Settings", None, "role_allowed_to_create_edit_back_dated_transactions", None)
frappe.set_user("Administrator")
user.remove_roles("Stock Manager")
def create_repack_entry(**args):
@ -400,4 +403,4 @@ def create_items():
make_item(d, properties=properties)
return items
return items