Merge branch 'develop' into separate-discount-account
This commit is contained in:
commit
bfaaebde0d
@ -386,7 +386,6 @@ def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
|
|||||||
doc,
|
doc,
|
||||||
credit_account,
|
credit_account,
|
||||||
debit_account,
|
debit_account,
|
||||||
against,
|
|
||||||
amount,
|
amount,
|
||||||
base_amount,
|
base_amount,
|
||||||
end_date,
|
end_date,
|
||||||
@ -570,7 +569,6 @@ def book_revenue_via_journal_entry(
|
|||||||
doc,
|
doc,
|
||||||
credit_account,
|
credit_account,
|
||||||
debit_account,
|
debit_account,
|
||||||
against,
|
|
||||||
amount,
|
amount,
|
||||||
base_amount,
|
base_amount,
|
||||||
posting_date,
|
posting_date,
|
||||||
@ -591,6 +589,7 @@ def book_revenue_via_journal_entry(
|
|||||||
journal_entry.voucher_type = (
|
journal_entry.voucher_type = (
|
||||||
"Deferred Revenue" if doc.doctype == "Sales Invoice" else "Deferred Expense"
|
"Deferred Revenue" if doc.doctype == "Sales Invoice" else "Deferred Expense"
|
||||||
)
|
)
|
||||||
|
journal_entry.process_deferred_accounting = deferred_process
|
||||||
|
|
||||||
debit_entry = {
|
debit_entry = {
|
||||||
"account": credit_account,
|
"account": credit_account,
|
||||||
|
@ -205,10 +205,16 @@ def get_doctypes_with_dimensions():
|
|||||||
return frappe.get_hooks("accounting_dimension_doctypes")
|
return frappe.get_hooks("accounting_dimension_doctypes")
|
||||||
|
|
||||||
|
|
||||||
def get_accounting_dimensions(as_list=True):
|
def get_accounting_dimensions(as_list=True, filters=None):
|
||||||
|
|
||||||
|
if not filters:
|
||||||
|
filters = {"disabled": 0}
|
||||||
|
|
||||||
if frappe.flags.accounting_dimensions is None:
|
if frappe.flags.accounting_dimensions is None:
|
||||||
frappe.flags.accounting_dimensions = frappe.get_all(
|
frappe.flags.accounting_dimensions = frappe.get_all(
|
||||||
"Accounting Dimension", fields=["label", "fieldname", "disabled", "document_type"]
|
"Accounting Dimension",
|
||||||
|
fields=["label", "fieldname", "disabled", "document_type"],
|
||||||
|
filters=filters,
|
||||||
)
|
)
|
||||||
|
|
||||||
if as_list:
|
if as_list:
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"allow_auto_repeat": 1,
|
"allow_auto_repeat": 1,
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"autoname": "naming_series:",
|
"autoname": "naming_series:",
|
||||||
"creation": "2013-03-25 10:53:52",
|
"creation": "2022-01-25 10:29:58.717206",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "Document",
|
"document_type": "Document",
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
@ -13,6 +13,7 @@
|
|||||||
"voucher_type",
|
"voucher_type",
|
||||||
"naming_series",
|
"naming_series",
|
||||||
"finance_book",
|
"finance_book",
|
||||||
|
"process_deferred_accounting",
|
||||||
"reversal_of",
|
"reversal_of",
|
||||||
"tax_withholding_category",
|
"tax_withholding_category",
|
||||||
"column_break1",
|
"column_break1",
|
||||||
@ -524,13 +525,20 @@
|
|||||||
"label": "Reversal Of",
|
"label": "Reversal Of",
|
||||||
"options": "Journal Entry",
|
"options": "Journal Entry",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "process_deferred_accounting",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Process Deferred Accounting",
|
||||||
|
"options": "Process Deferred Accounting",
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-file-text",
|
"icon": "fa fa-file-text",
|
||||||
"idx": 176,
|
"idx": 176,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2022-01-04 13:39:36.485954",
|
"modified": "2022-04-06 17:18:46.865259",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Journal Entry",
|
"name": "Journal Entry",
|
||||||
@ -578,6 +586,7 @@
|
|||||||
"search_fields": "voucher_type,posting_date, due_date, cheque_no",
|
"search_fields": "voucher_type,posting_date, due_date, cheque_no",
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
"title_field": "title",
|
"title_field": "title",
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
@ -11,7 +11,7 @@ from erpnext.accounts.deferred_revenue import (
|
|||||||
convert_deferred_expense_to_expense,
|
convert_deferred_expense_to_expense,
|
||||||
convert_deferred_revenue_to_income,
|
convert_deferred_revenue_to_income,
|
||||||
)
|
)
|
||||||
from erpnext.accounts.general_ledger import make_reverse_gl_entries
|
from erpnext.accounts.general_ledger import make_gl_entries
|
||||||
|
|
||||||
|
|
||||||
class ProcessDeferredAccounting(Document):
|
class ProcessDeferredAccounting(Document):
|
||||||
@ -34,4 +34,4 @@ class ProcessDeferredAccounting(Document):
|
|||||||
filters={"against_voucher_type": self.doctype, "against_voucher": self.name},
|
filters={"against_voucher_type": self.doctype, "against_voucher": self.name},
|
||||||
)
|
)
|
||||||
|
|
||||||
make_reverse_gl_entries(gl_entries=gl_entries)
|
make_gl_entries(gl_entries=gl_entries, cancel=1)
|
||||||
|
@ -2240,6 +2240,14 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
check_gl_entries(self, si.name, expected_gle, "2019-01-30")
|
check_gl_entries(self, si.name, expected_gle, "2019-01-30")
|
||||||
|
|
||||||
|
def test_deferred_revenue_missing_account(self):
|
||||||
|
si = create_sales_invoice(posting_date="2019-01-10", do_not_submit=True)
|
||||||
|
si.items[0].enable_deferred_revenue = 1
|
||||||
|
si.items[0].service_start_date = "2019-01-10"
|
||||||
|
si.items[0].service_end_date = "2019-03-15"
|
||||||
|
|
||||||
|
self.assertRaises(frappe.ValidationError, si.save)
|
||||||
|
|
||||||
def test_fixed_deferred_revenue(self):
|
def test_fixed_deferred_revenue(self):
|
||||||
deferred_account = create_account(
|
deferred_account = create_account(
|
||||||
account_name="Deferred Revenue",
|
account_name="Deferred Revenue",
|
||||||
@ -3104,7 +3112,7 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
acc_settings = frappe.get_single("Accounts Settings")
|
acc_settings = frappe.get_single("Accounts Settings")
|
||||||
acc_settings.book_deferred_entries_via_journal_entry = 0
|
acc_settings.book_deferred_entries_via_journal_entry = 0
|
||||||
acc_settings.submit_journal_entriessubmit_journal_entries = 0
|
acc_settings.submit_journal_entries = 0
|
||||||
acc_settings.save()
|
acc_settings.save()
|
||||||
|
|
||||||
frappe.db.set_value("Accounts Settings", None, "acc_frozen_upto", None)
|
frappe.db.set_value("Accounts Settings", None, "acc_frozen_upto", None)
|
||||||
|
@ -180,6 +180,7 @@ class AccountsController(TransactionBase):
|
|||||||
else:
|
else:
|
||||||
self.validate_deferred_start_and_end_date()
|
self.validate_deferred_start_and_end_date()
|
||||||
|
|
||||||
|
self.validate_deferred_income_expense_account()
|
||||||
self.set_inter_company_account()
|
self.set_inter_company_account()
|
||||||
|
|
||||||
if self.doctype == "Purchase Invoice":
|
if self.doctype == "Purchase Invoice":
|
||||||
@ -208,6 +209,27 @@ class AccountsController(TransactionBase):
|
|||||||
(self.doctype, self.name),
|
(self.doctype, self.name),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def validate_deferred_income_expense_account(self):
|
||||||
|
field_map = {
|
||||||
|
"Sales Invoice": "deferred_revenue_account",
|
||||||
|
"Purchase Invoice": "deferred_expense_account",
|
||||||
|
}
|
||||||
|
|
||||||
|
for item in self.get("items"):
|
||||||
|
if item.get("enable_deferred_revenue") or item.get("enable_deferred_expense"):
|
||||||
|
if not item.get(field_map.get(self.doctype)):
|
||||||
|
default_deferred_account = frappe.db.get_value(
|
||||||
|
"Company", self.company, "default_" + field_map.get(self.doctype)
|
||||||
|
)
|
||||||
|
if not default_deferred_account:
|
||||||
|
frappe.throw(
|
||||||
|
_(
|
||||||
|
"Row #{0}: Please update deferred revenue/expense account in item row or default account in company master"
|
||||||
|
).format(item.idx)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
item.set(field_map.get(self.doctype), default_deferred_account)
|
||||||
|
|
||||||
def validate_deferred_start_and_end_date(self):
|
def validate_deferred_start_and_end_date(self):
|
||||||
for d in self.items:
|
for d in self.items:
|
||||||
if d.get("enable_deferred_revenue") or d.get("enable_deferred_expense"):
|
if d.get("enable_deferred_revenue") or d.get("enable_deferred_expense"):
|
||||||
|
@ -22,6 +22,9 @@ class QtyMismatchError(ValidationError):
|
|||||||
|
|
||||||
|
|
||||||
class BuyingController(StockController, Subcontracting):
|
class BuyingController(StockController, Subcontracting):
|
||||||
|
def __setup__(self):
|
||||||
|
self.flags.ignore_permlevel_for_fields = ["buying_price_list", "price_list_currency"]
|
||||||
|
|
||||||
def get_feed(self):
|
def get_feed(self):
|
||||||
if self.get("supplier_name"):
|
if self.get("supplier_name"):
|
||||||
return _("From {0} | {1} {2}").format(self.supplier_name, self.currency, self.grand_total)
|
return _("From {0} | {1} {2}").format(self.supplier_name, self.currency, self.grand_total)
|
||||||
|
@ -16,6 +16,9 @@ from erpnext.stock.utils import get_incoming_rate
|
|||||||
|
|
||||||
|
|
||||||
class SellingController(StockController):
|
class SellingController(StockController):
|
||||||
|
def __setup__(self):
|
||||||
|
self.flags.ignore_permlevel_for_fields = ["selling_price_list", "price_list_currency"]
|
||||||
|
|
||||||
def get_feed(self):
|
def get_feed(self):
|
||||||
return _("To {0} | {1} {2}").format(self.customer_name, self.currency, self.grand_total)
|
return _("To {0} | {1} {2}").format(self.customer_name, self.currency, self.grand_total)
|
||||||
|
|
||||||
|
@ -140,26 +140,6 @@ erpnext.maintenance.MaintenanceSchedule = class MaintenanceSchedule extends frap
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
start_date(doc, cdt, cdn) {
|
|
||||||
this.set_no_of_visits(doc, cdt, cdn);
|
|
||||||
}
|
|
||||||
|
|
||||||
end_date(doc, cdt, cdn) {
|
|
||||||
this.set_no_of_visits(doc, cdt, cdn);
|
|
||||||
}
|
|
||||||
|
|
||||||
periodicity(doc, cdt, cdn) {
|
|
||||||
this.set_no_of_visits(doc, cdt, cdn);
|
|
||||||
}
|
|
||||||
|
|
||||||
set_no_of_visits(doc, cdt, cdn) {
|
|
||||||
var item = frappe.get_doc(cdt, cdn);
|
|
||||||
let me = this;
|
|
||||||
if (item.start_date && item.periodicity) {
|
|
||||||
me.frm.call('validate_end_date_visits');
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extend_cscript(cur_frm.cscript, new erpnext.maintenance.MaintenanceSchedule({frm: cur_frm}));
|
extend_cscript(cur_frm.cscript, new erpnext.maintenance.MaintenanceSchedule({frm: cur_frm}));
|
||||||
|
@ -213,6 +213,26 @@ class MaintenanceSchedule(TransactionBase):
|
|||||||
if chk:
|
if chk:
|
||||||
throw(_("Maintenance Schedule {0} exists against {1}").format(chk[0][0], d.sales_order))
|
throw(_("Maintenance Schedule {0} exists against {1}").format(chk[0][0], d.sales_order))
|
||||||
|
|
||||||
|
def validate_items_table_change(self):
|
||||||
|
doc_before_save = self.get_doc_before_save()
|
||||||
|
if not doc_before_save:
|
||||||
|
return
|
||||||
|
for prev_item, item in zip(doc_before_save.items, self.items):
|
||||||
|
fields = [
|
||||||
|
"item_code",
|
||||||
|
"start_date",
|
||||||
|
"end_date",
|
||||||
|
"periodicity",
|
||||||
|
"sales_person",
|
||||||
|
"no_of_visits",
|
||||||
|
"serial_no",
|
||||||
|
]
|
||||||
|
for field in fields:
|
||||||
|
b_doc = prev_item.as_dict()
|
||||||
|
doc = item.as_dict()
|
||||||
|
if cstr(b_doc[field]) != cstr(doc[field]):
|
||||||
|
return True
|
||||||
|
|
||||||
def validate_no_of_visits(self):
|
def validate_no_of_visits(self):
|
||||||
return len(self.schedules) != sum(d.no_of_visits for d in self.items)
|
return len(self.schedules) != sum(d.no_of_visits for d in self.items)
|
||||||
|
|
||||||
@ -221,7 +241,7 @@ class MaintenanceSchedule(TransactionBase):
|
|||||||
self.validate_maintenance_detail()
|
self.validate_maintenance_detail()
|
||||||
self.validate_dates_with_periodicity()
|
self.validate_dates_with_periodicity()
|
||||||
self.validate_sales_order()
|
self.validate_sales_order()
|
||||||
if not self.schedules or self.validate_no_of_visits():
|
if not self.schedules or self.validate_items_table_change() or self.validate_no_of_visits():
|
||||||
self.generate_schedule()
|
self.generate_schedule()
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
|
@ -123,6 +123,36 @@ class TestMaintenanceSchedule(unittest.TestCase):
|
|||||||
|
|
||||||
frappe.db.rollback()
|
frappe.db.rollback()
|
||||||
|
|
||||||
|
def test_schedule_with_serials(self):
|
||||||
|
# Checks whether serials are automatically updated when changing in items table.
|
||||||
|
# Also checks if other fields trigger generate schdeule if changed in items table.
|
||||||
|
item_code = "_Test Serial Item"
|
||||||
|
make_serial_item_with_serial(item_code)
|
||||||
|
ms = make_maintenance_schedule(item_code=item_code, serial_no="TEST001, TEST002")
|
||||||
|
ms.save()
|
||||||
|
|
||||||
|
# Before Save
|
||||||
|
self.assertEqual(ms.schedules[0].serial_no, "TEST001, TEST002")
|
||||||
|
self.assertEqual(ms.schedules[0].sales_person, "Sales Team")
|
||||||
|
self.assertEqual(len(ms.schedules), 4)
|
||||||
|
self.assertFalse(ms.validate_items_table_change())
|
||||||
|
# After Save
|
||||||
|
ms.items[0].serial_no = "TEST001"
|
||||||
|
ms.items[0].sales_person = "_Test Sales Person"
|
||||||
|
ms.items[0].no_of_visits = 2
|
||||||
|
self.assertTrue(ms.validate_items_table_change())
|
||||||
|
ms.save()
|
||||||
|
self.assertEqual(ms.schedules[0].serial_no, "TEST001")
|
||||||
|
self.assertEqual(ms.schedules[0].sales_person, "_Test Sales Person")
|
||||||
|
self.assertEqual(len(ms.schedules), 2)
|
||||||
|
# When user manually deleted a row from schedules table.
|
||||||
|
ms.schedules.pop()
|
||||||
|
self.assertEqual(len(ms.schedules), 1)
|
||||||
|
ms.save()
|
||||||
|
self.assertEqual(len(ms.schedules), 2)
|
||||||
|
|
||||||
|
frappe.db.rollback()
|
||||||
|
|
||||||
|
|
||||||
def make_serial_item_with_serial(item_code):
|
def make_serial_item_with_serial(item_code):
|
||||||
serial_item_doc = create_item(item_code, is_stock_item=1)
|
serial_item_doc = create_item(item_code, is_stock_item=1)
|
||||||
|
@ -12,6 +12,9 @@ frappe.ui.form.on('Maintenance Visit', {
|
|||||||
// filters for serial no based on item code
|
// filters for serial no based on item code
|
||||||
if (frm.doc.maintenance_type === "Scheduled") {
|
if (frm.doc.maintenance_type === "Scheduled") {
|
||||||
let item_code = frm.doc.purposes[0].item_code;
|
let item_code = frm.doc.purposes[0].item_code;
|
||||||
|
if (!item_code) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "erpnext.maintenance.doctype.maintenance_schedule.maintenance_schedule.get_serial_nos_from_schedule",
|
method: "erpnext.maintenance.doctype.maintenance_schedule.maintenance_schedule.get_serial_nos_from_schedule",
|
||||||
args: {
|
args: {
|
||||||
|
@ -1144,6 +1144,56 @@ class TestWorkOrder(FrappeTestCase):
|
|||||||
for index, row in enumerate(ste_manu.get("items"), start=1):
|
for index, row in enumerate(ste_manu.get("items"), start=1):
|
||||||
self.assertEqual(index, row.idx)
|
self.assertEqual(index, row.idx)
|
||||||
|
|
||||||
|
@change_settings(
|
||||||
|
"Manufacturing Settings",
|
||||||
|
{"backflush_raw_materials_based_on": "Material Transferred for Manufacture"},
|
||||||
|
)
|
||||||
|
def test_work_order_multiple_material_transfer(self):
|
||||||
|
"""
|
||||||
|
Test transferring multiple RMs in separate Stock Entries.
|
||||||
|
"""
|
||||||
|
work_order = make_wo_order_test_record(planned_start_date=now(), qty=1)
|
||||||
|
test_stock_entry.make_stock_entry( # stock up RM
|
||||||
|
item_code="_Test Item",
|
||||||
|
target="_Test Warehouse - _TC",
|
||||||
|
qty=1,
|
||||||
|
basic_rate=5000.0,
|
||||||
|
)
|
||||||
|
test_stock_entry.make_stock_entry( # stock up RM
|
||||||
|
item_code="_Test Item Home Desktop 100",
|
||||||
|
target="_Test Warehouse - _TC",
|
||||||
|
qty=2,
|
||||||
|
basic_rate=1000.0,
|
||||||
|
)
|
||||||
|
|
||||||
|
transfer_entry = frappe.get_doc(
|
||||||
|
make_stock_entry(work_order.name, "Material Transfer for Manufacture", 1)
|
||||||
|
)
|
||||||
|
del transfer_entry.get("items")[0] # transfer only one RM
|
||||||
|
transfer_entry.submit()
|
||||||
|
|
||||||
|
# WO's "Material Transferred for Mfg" shows all is transferred, one RM is pending
|
||||||
|
work_order.reload()
|
||||||
|
self.assertEqual(work_order.material_transferred_for_manufacturing, 1)
|
||||||
|
self.assertEqual(work_order.required_items[0].transferred_qty, 0)
|
||||||
|
self.assertEqual(work_order.required_items[1].transferred_qty, 2)
|
||||||
|
|
||||||
|
final_transfer_entry = frappe.get_doc( # transfer last RM with For Quantity = 0
|
||||||
|
make_stock_entry(work_order.name, "Material Transfer for Manufacture", 0)
|
||||||
|
)
|
||||||
|
final_transfer_entry.save()
|
||||||
|
|
||||||
|
self.assertEqual(final_transfer_entry.fg_completed_qty, 0.0)
|
||||||
|
self.assertEqual(final_transfer_entry.items[0].qty, 1)
|
||||||
|
|
||||||
|
final_transfer_entry.submit()
|
||||||
|
work_order.reload()
|
||||||
|
|
||||||
|
# WO's "Material Transferred for Mfg" shows all is transferred, no RM is pending
|
||||||
|
self.assertEqual(work_order.material_transferred_for_manufacturing, 1)
|
||||||
|
self.assertEqual(work_order.required_items[0].transferred_qty, 1)
|
||||||
|
self.assertEqual(work_order.required_items[1].transferred_qty, 2)
|
||||||
|
|
||||||
|
|
||||||
def update_job_card(job_card, jc_qty=None):
|
def update_job_card(job_card, jc_qty=None):
|
||||||
employee = frappe.db.get_value("Employee", {"status": "Active"}, "name")
|
employee = frappe.db.get_value("Employee", {"status": "Active"}, "name")
|
||||||
|
@ -540,8 +540,10 @@ erpnext.work_order = {
|
|||||||
|| frm.doc.transfer_material_against == 'Job Card') ? 0 : 1;
|
|| frm.doc.transfer_material_against == 'Job Card') ? 0 : 1;
|
||||||
|
|
||||||
if (show_start_btn) {
|
if (show_start_btn) {
|
||||||
if ((flt(doc.material_transferred_for_manufacturing) < flt(doc.qty))
|
let pending_to_transfer = frm.doc.required_items.some(
|
||||||
&& frm.doc.status != 'Stopped') {
|
item => flt(item.transferred_qty) < flt(item.required_qty)
|
||||||
|
);
|
||||||
|
if (pending_to_transfer && frm.doc.status != 'Stopped') {
|
||||||
frm.has_start_btn = true;
|
frm.has_start_btn = true;
|
||||||
frm.add_custom_button(__('Create Pick List'), function() {
|
frm.add_custom_button(__('Create Pick List'), function() {
|
||||||
erpnext.work_order.create_pick_list(frm);
|
erpnext.work_order.create_pick_list(frm);
|
||||||
|
@ -1186,7 +1186,11 @@ def make_stock_entry(work_order_id, purpose, qty=None):
|
|||||||
stock_entry.from_bom = 1
|
stock_entry.from_bom = 1
|
||||||
stock_entry.bom_no = work_order.bom_no
|
stock_entry.bom_no = work_order.bom_no
|
||||||
stock_entry.use_multi_level_bom = work_order.use_multi_level_bom
|
stock_entry.use_multi_level_bom = work_order.use_multi_level_bom
|
||||||
stock_entry.fg_completed_qty = qty or (flt(work_order.qty) - flt(work_order.produced_qty))
|
# accept 0 qty as well
|
||||||
|
stock_entry.fg_completed_qty = (
|
||||||
|
qty if qty is not None else (flt(work_order.qty) - flt(work_order.produced_qty))
|
||||||
|
)
|
||||||
|
|
||||||
if work_order.bom_no:
|
if work_order.bom_no:
|
||||||
stock_entry.inspection_required = frappe.db.get_value(
|
stock_entry.inspection_required = frappe.db.get_value(
|
||||||
"BOM", work_order.bom_no, "inspection_required"
|
"BOM", work_order.bom_no, "inspection_required"
|
||||||
|
@ -78,8 +78,9 @@ frappe.query_reports["GSTR-1"] = {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
report.page.add_inner_button(__("Download as JSON"), function () {
|
report.page.add_inner_button(__("Download as JSON"), function () {
|
||||||
|
let filters = report.get_values();
|
||||||
|
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: 'erpnext.regional.report.gstr_1.gstr_1.get_json',
|
method: 'erpnext.regional.report.gstr_1.gstr_1.get_json',
|
||||||
args: {
|
args: {
|
||||||
|
@ -1803,7 +1803,9 @@ class StockEntry(StockController):
|
|||||||
or (desire_to_transfer > 0 and backflush_based_on == "Material Transferred for Manufacture")
|
or (desire_to_transfer > 0 and backflush_based_on == "Material Transferred for Manufacture")
|
||||||
or allow_overproduction
|
or allow_overproduction
|
||||||
):
|
):
|
||||||
item_dict[item]["qty"] = desire_to_transfer
|
# "No need for transfer but qty still pending to transfer" case can occur
|
||||||
|
# when transferring multiple RM in different Stock Entries
|
||||||
|
item_dict[item]["qty"] = desire_to_transfer if (desire_to_transfer > 0) else pending_to_issue
|
||||||
elif pending_to_issue > 0:
|
elif pending_to_issue > 0:
|
||||||
item_dict[item]["qty"] = pending_to_issue
|
item_dict[item]["qty"] = pending_to_issue
|
||||||
else:
|
else:
|
||||||
|
Loading…
Reference in New Issue
Block a user