mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-20 21:49:18 +00:00
chore: release v15 (#42308)
* fix(Warehouse): add buttons only if the user can use them (cherry picked from commit10ae5aaf52) * fix: missing discount on POS Credit Notes (cherry picked from commit1049550951) * chore: rename test suite for payable report (cherry picked from commit9474f72776) * refactor: test suite for item-wise sales register (cherry picked from commit3aaa22e672) * refactor(test): use each instance UOM for assertion (cherry picked from commitcf4fbfb601) * fix: slowness in reposting dependent vouchers. (backport #42282) (#42292) fix: slowness in reposting dependent vouchers. (#42282) (cherry picked from commitb17696a8ae) Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com> * refactor(test): clear old records * fix: keep status as In Progress for RIV for Timeout Error (backport #42274) (#42296) fix: keep status as In Progress for RIV for Timeout Error (#42274) (cherry picked from commit10280d6140) Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com> * fix: cost center filter by company (backport #42297) (#42299) fix: cost center filter by company (#42297) (cherry picked from commit9838f7e6ba) Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com> * feat: configurable depreciation calculation via accounts settings (#42276) * feat: configurable depreciation calculation via accounts settings * refactor: code optimization * style: changes in description and label (cherry picked from commitb04da63aad) * fix: not able to submit LCV entry (backport #42303) (#42304) fix: not able to submit LCV entry (#42303) (cherry picked from commit9cf92eaeab) Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com> * fix: While submitting PCV ensure previous FY is closed (backport #42284) (#42300) fix: While submitting PCV ensure previous FY is closed (#42284) (cherry picked from commitd0bbc8ca70) Co-authored-by: Nabin Hait <nabinhait@gmail.com> --------- Co-authored-by: barredterra <14891507+barredterra@users.noreply.github.com> Co-authored-by: ruthra kumar <ruthra@erpnext.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com> Co-authored-by: Khushi Rawat <142375893+khushi8112@users.noreply.github.com>
This commit is contained in:
@@ -55,6 +55,8 @@
|
|||||||
"post_change_gl_entries",
|
"post_change_gl_entries",
|
||||||
"assets_tab",
|
"assets_tab",
|
||||||
"asset_settings_section",
|
"asset_settings_section",
|
||||||
|
"calculate_depr_using_total_days",
|
||||||
|
"column_break_gjcc",
|
||||||
"book_asset_depreciation_entry_automatically",
|
"book_asset_depreciation_entry_automatically",
|
||||||
"closing_settings_tab",
|
"closing_settings_tab",
|
||||||
"period_closing_settings_section",
|
"period_closing_settings_section",
|
||||||
@@ -462,6 +464,17 @@
|
|||||||
"fieldname": "enable_immutable_ledger",
|
"fieldname": "enable_immutable_ledger",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Enable Immutable Ledger"
|
"label": "Enable Immutable Ledger"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_gjcc",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"description": "Enable this option to calculate daily depreciation by considering the total number of days in the entire depreciation period, (including leap years) while using daily pro-rata based depreciation",
|
||||||
|
"fieldname": "calculate_depr_using_total_days",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Calculate daily depreciation using total days in depreciation period"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "icon-cog",
|
"icon": "icon-cog",
|
||||||
@@ -469,7 +482,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-05-11 23:19:44.673975",
|
"modified": "2024-07-12 00:24:20.957726",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Accounts Settings",
|
"name": "Accounts Settings",
|
||||||
@@ -498,4 +511,4 @@
|
|||||||
"sort_order": "ASC",
|
"sort_order": "ASC",
|
||||||
"states": [],
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
@@ -33,6 +33,7 @@ class AccountsSettings(Document):
|
|||||||
book_deferred_entries_based_on: DF.Literal["Days", "Months"]
|
book_deferred_entries_based_on: DF.Literal["Days", "Months"]
|
||||||
book_deferred_entries_via_journal_entry: DF.Check
|
book_deferred_entries_via_journal_entry: DF.Check
|
||||||
book_tax_discount_loss: DF.Check
|
book_tax_discount_loss: DF.Check
|
||||||
|
calculate_depr_using_total_days: DF.Check
|
||||||
check_supplier_invoice_uniqueness: DF.Check
|
check_supplier_invoice_uniqueness: DF.Check
|
||||||
credit_controller: DF.Link | None
|
credit_controller: DF.Link | None
|
||||||
delete_linked_ledger_entries: DF.Check
|
delete_linked_ledger_entries: DF.Check
|
||||||
|
|||||||
@@ -481,6 +481,43 @@ class TestJournalEntry(unittest.TestCase):
|
|||||||
for field in self.fields:
|
for field in self.fields:
|
||||||
self.assertEqual(self.expected_gle[i][field], gl_entries[i][field])
|
self.assertEqual(self.expected_gle[i][field], gl_entries[i][field])
|
||||||
|
|
||||||
|
def test_negative_debit_and_credit_with_same_account_head(self):
|
||||||
|
from erpnext.accounts.general_ledger import process_gl_map
|
||||||
|
|
||||||
|
# Create JV with defaut cost center - _Test Cost Center
|
||||||
|
frappe.db.set_single_value("Accounts Settings", "merge_similar_account_heads", 0)
|
||||||
|
|
||||||
|
jv = make_journal_entry("_Test Bank - _TC", "_Test Bank - _TC", 100 * -1, save=True)
|
||||||
|
jv.append(
|
||||||
|
"accounts",
|
||||||
|
{
|
||||||
|
"account": "_Test Cash - _TC",
|
||||||
|
"debit": 100 * -1,
|
||||||
|
"credit": 100 * -1,
|
||||||
|
"debit_in_account_currency": 100 * -1,
|
||||||
|
"credit_in_account_currency": 100 * -1,
|
||||||
|
"exchange_rate": 1,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
jv.flags.ignore_validate = True
|
||||||
|
jv.save()
|
||||||
|
|
||||||
|
self.assertEqual(len(jv.accounts), 3)
|
||||||
|
|
||||||
|
gl_map = jv.build_gl_map()
|
||||||
|
|
||||||
|
for row in gl_map:
|
||||||
|
if row.account == "_Test Cash - _TC":
|
||||||
|
self.assertEqual(row.debit_in_account_currency, 100 * -1)
|
||||||
|
self.assertEqual(row.credit_in_account_currency, 100 * -1)
|
||||||
|
|
||||||
|
gl_map = process_gl_map(gl_map, False)
|
||||||
|
|
||||||
|
for row in gl_map:
|
||||||
|
if row.account == "_Test Cash - _TC":
|
||||||
|
self.assertEqual(row.debit_in_account_currency, 100)
|
||||||
|
self.assertEqual(row.credit_in_account_currency, 100)
|
||||||
|
|
||||||
|
|
||||||
def make_journal_entry(
|
def make_journal_entry(
|
||||||
account1,
|
account1,
|
||||||
|
|||||||
@@ -136,18 +136,28 @@ class PeriodClosingVoucher(AccountsController):
|
|||||||
|
|
||||||
def check_if_previous_year_closed(self):
|
def check_if_previous_year_closed(self):
|
||||||
last_year_closing = add_days(self.year_start_date, -1)
|
last_year_closing = add_days(self.year_start_date, -1)
|
||||||
|
|
||||||
previous_fiscal_year = get_fiscal_year(last_year_closing, company=self.company, boolean=True)
|
previous_fiscal_year = get_fiscal_year(last_year_closing, company=self.company, boolean=True)
|
||||||
|
if not previous_fiscal_year:
|
||||||
|
return
|
||||||
|
|
||||||
if previous_fiscal_year and not frappe.db.exists(
|
previous_fiscal_year_start_date = previous_fiscal_year[0][1]
|
||||||
|
if not frappe.db.exists(
|
||||||
"GL Entry",
|
"GL Entry",
|
||||||
{"posting_date": ("<=", last_year_closing), "company": self.company, "is_cancelled": 0},
|
{
|
||||||
|
"posting_date": ("between", [previous_fiscal_year_start_date, last_year_closing]),
|
||||||
|
"company": self.company,
|
||||||
|
"is_cancelled": 0,
|
||||||
|
},
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
|
|
||||||
if previous_fiscal_year and not frappe.db.exists(
|
if not frappe.db.exists(
|
||||||
"Period Closing Voucher",
|
"Period Closing Voucher",
|
||||||
{"posting_date": ("<=", last_year_closing), "docstatus": 1, "company": self.company},
|
{
|
||||||
|
"posting_date": ("between", [previous_fiscal_year_start_date, last_year_closing]),
|
||||||
|
"docstatus": 1,
|
||||||
|
"company": self.company,
|
||||||
|
},
|
||||||
):
|
):
|
||||||
frappe.throw(_("Previous Year is not closed, please close it first"))
|
frappe.throw(_("Previous Year is not closed, please close it first"))
|
||||||
|
|
||||||
|
|||||||
@@ -505,6 +505,9 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends (
|
|||||||
return this.frm.call({
|
return this.frm.call({
|
||||||
doc: me.frm.doc,
|
doc: me.frm.doc,
|
||||||
method: "set_missing_values",
|
method: "set_missing_values",
|
||||||
|
args: {
|
||||||
|
for_validate: true,
|
||||||
|
},
|
||||||
callback: function (r) {
|
callback: function (r) {
|
||||||
if (!r.exc) {
|
if (!r.exc) {
|
||||||
if (r.message && r.message.print_format) {
|
if (r.message && r.message.print_format) {
|
||||||
|
|||||||
@@ -310,6 +310,18 @@ def check_if_in_list(gle, gl_map):
|
|||||||
def toggle_debit_credit_if_negative(gl_map):
|
def toggle_debit_credit_if_negative(gl_map):
|
||||||
for entry in gl_map:
|
for entry in gl_map:
|
||||||
# toggle debit, credit if negative entry
|
# toggle debit, credit if negative entry
|
||||||
|
if flt(entry.debit) < 0 and flt(entry.credit) < 0 and flt(entry.debit) == flt(entry.credit):
|
||||||
|
entry.credit *= -1
|
||||||
|
entry.debit *= -1
|
||||||
|
|
||||||
|
if (
|
||||||
|
flt(entry.debit_in_account_currency) < 0
|
||||||
|
and flt(entry.credit_in_account_currency) < 0
|
||||||
|
and flt(entry.debit_in_account_currency) == flt(entry.credit_in_account_currency)
|
||||||
|
):
|
||||||
|
entry.credit_in_account_currency *= -1
|
||||||
|
entry.debit_in_account_currency *= -1
|
||||||
|
|
||||||
if flt(entry.debit) < 0:
|
if flt(entry.debit) < 0:
|
||||||
entry.credit = flt(entry.credit) - flt(entry.debit)
|
entry.credit = flt(entry.credit) - flt(entry.debit)
|
||||||
entry.debit = 0.0
|
entry.debit = 0.0
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from erpnext.accounts.report.accounts_payable.accounts_payable import execute
|
|||||||
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
|
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
|
||||||
|
|
||||||
|
|
||||||
class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
|
class TestAccountsPayable(AccountsTestMixin, FrappeTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.create_company()
|
self.create_company()
|
||||||
self.create_customer()
|
self.create_customer()
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
import frappe
|
||||||
|
from frappe.tests.utils import FrappeTestCase
|
||||||
|
from frappe.utils import getdate, today
|
||||||
|
|
||||||
|
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||||
|
from erpnext.accounts.report.item_wise_sales_register.item_wise_sales_register import execute
|
||||||
|
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
|
||||||
|
|
||||||
|
|
||||||
|
class TestItemWiseSalesRegister(AccountsTestMixin, FrappeTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.create_company()
|
||||||
|
self.create_customer()
|
||||||
|
self.create_item()
|
||||||
|
self.clear_old_entries()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
frappe.db.rollback()
|
||||||
|
|
||||||
|
def create_sales_invoice(self, do_not_submit=False):
|
||||||
|
si = create_sales_invoice(
|
||||||
|
item=self.item,
|
||||||
|
company=self.company,
|
||||||
|
customer=self.customer,
|
||||||
|
debit_to=self.debit_to,
|
||||||
|
posting_date=today(),
|
||||||
|
parent_cost_center=self.cost_center,
|
||||||
|
cost_center=self.cost_center,
|
||||||
|
rate=100,
|
||||||
|
price_list_rate=100,
|
||||||
|
do_not_save=1,
|
||||||
|
)
|
||||||
|
si = si.save()
|
||||||
|
if not do_not_submit:
|
||||||
|
si = si.submit()
|
||||||
|
return si
|
||||||
|
|
||||||
|
def test_basic_report_output(self):
|
||||||
|
si = self.create_sales_invoice()
|
||||||
|
|
||||||
|
filters = frappe._dict({"from_date": today(), "to_date": today(), "company": self.company})
|
||||||
|
report = execute(filters)
|
||||||
|
|
||||||
|
self.assertEqual(len(report[1]), 1)
|
||||||
|
|
||||||
|
expected_result = {
|
||||||
|
"item_code": si.items[0].item_code,
|
||||||
|
"invoice": si.name,
|
||||||
|
"posting_date": getdate(),
|
||||||
|
"customer": si.customer,
|
||||||
|
"debit_to": si.debit_to,
|
||||||
|
"company": self.company,
|
||||||
|
"income_account": si.items[0].income_account,
|
||||||
|
"stock_qty": 1.0,
|
||||||
|
"stock_uom": si.items[0].stock_uom,
|
||||||
|
"rate": 100.0,
|
||||||
|
"amount": 100.0,
|
||||||
|
"total_tax": 0,
|
||||||
|
"total_other_charges": 0,
|
||||||
|
"total": 100.0,
|
||||||
|
"currency": "INR",
|
||||||
|
}
|
||||||
|
|
||||||
|
report_output = {k: v for k, v in report[1][0].items() if k in expected_result}
|
||||||
|
self.assertDictEqual(report_output, expected_result)
|
||||||
@@ -701,20 +701,57 @@ def get_straight_line_or_manual_depr_amount(
|
|||||||
def get_daily_prorata_based_straight_line_depr(
|
def get_daily_prorata_based_straight_line_depr(
|
||||||
asset, row, schedule_idx, number_of_pending_depreciations, amount
|
asset, row, schedule_idx, number_of_pending_depreciations, amount
|
||||||
):
|
):
|
||||||
total_years = flt(number_of_pending_depreciations * row.frequency_of_depreciation) / 12
|
daily_depr_amount = get_daily_depr_amount(asset, row, schedule_idx, amount)
|
||||||
every_year_depr = amount / total_years
|
|
||||||
|
|
||||||
year_start_date = add_years(
|
|
||||||
row.depreciation_start_date, (row.frequency_of_depreciation * schedule_idx) // 12
|
|
||||||
)
|
|
||||||
year_end_date = add_days(add_years(year_start_date, 1), -1)
|
|
||||||
daily_depr_amount = every_year_depr / (date_diff(year_end_date, year_start_date) + 1)
|
|
||||||
from_date, total_depreciable_days = _get_total_days(
|
from_date, total_depreciable_days = _get_total_days(
|
||||||
row.depreciation_start_date, schedule_idx, row.frequency_of_depreciation
|
row.depreciation_start_date, schedule_idx, row.frequency_of_depreciation
|
||||||
)
|
)
|
||||||
return daily_depr_amount * total_depreciable_days
|
return daily_depr_amount * total_depreciable_days
|
||||||
|
|
||||||
|
|
||||||
|
def get_daily_depr_amount(asset, row, schedule_idx, amount):
|
||||||
|
if cint(frappe.db.get_single_value("Accounts Settings", "calculate_depr_using_total_days")):
|
||||||
|
total_days = (
|
||||||
|
date_diff(
|
||||||
|
get_last_day(
|
||||||
|
add_months(
|
||||||
|
row.depreciation_start_date,
|
||||||
|
flt(
|
||||||
|
row.total_number_of_depreciations
|
||||||
|
- asset.opening_number_of_booked_depreciations
|
||||||
|
- 1
|
||||||
|
)
|
||||||
|
* row.frequency_of_depreciation,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
add_days(
|
||||||
|
get_last_day(add_months(row.depreciation_start_date, -1 * row.frequency_of_depreciation)),
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
+ 1
|
||||||
|
)
|
||||||
|
|
||||||
|
return amount / total_days
|
||||||
|
else:
|
||||||
|
total_years = (
|
||||||
|
flt(
|
||||||
|
(row.total_number_of_depreciations - row.total_number_of_booked_depreciations)
|
||||||
|
* row.frequency_of_depreciation
|
||||||
|
)
|
||||||
|
/ 12
|
||||||
|
)
|
||||||
|
|
||||||
|
every_year_depr = amount / total_years
|
||||||
|
|
||||||
|
year_start_date = add_years(
|
||||||
|
row.depreciation_start_date, (row.frequency_of_depreciation * schedule_idx) // 12
|
||||||
|
)
|
||||||
|
year_end_date = add_days(add_years(year_start_date, 1), -1)
|
||||||
|
|
||||||
|
return every_year_depr / (date_diff(year_end_date, year_start_date) + 1)
|
||||||
|
|
||||||
|
|
||||||
def get_shift_depr_amount(asset_depr_schedule, asset, row, schedule_idx):
|
def get_shift_depr_amount(asset_depr_schedule, asset, row, schedule_idx):
|
||||||
if asset_depr_schedule.get("__islocal") and not asset.flags.shift_allocation:
|
if asset_depr_schedule.get("__islocal") and not asset.flags.shift_allocation:
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -75,6 +75,68 @@ class TestAssetDepreciationSchedule(FrappeTestCase):
|
|||||||
]
|
]
|
||||||
self.assertEqual(schedules, expected_schedules)
|
self.assertEqual(schedules, expected_schedules)
|
||||||
|
|
||||||
|
# Enable Checkbox to Calculate depreciation using total days in depreciation period
|
||||||
|
def test_daily_prorata_based_depr_after_enabling_configuration(self):
|
||||||
|
frappe.db.set_single_value("Accounts Settings", "calculate_depr_using_total_days", 1)
|
||||||
|
|
||||||
|
asset = create_asset(
|
||||||
|
calculate_depreciation=1,
|
||||||
|
depreciation_method="Straight Line",
|
||||||
|
daily_prorata_based=1,
|
||||||
|
gross_purchase_amount=1096,
|
||||||
|
available_for_use_date="2020-01-15",
|
||||||
|
depreciation_start_date="2020-01-31",
|
||||||
|
frequency_of_depreciation=1,
|
||||||
|
total_number_of_depreciations=36,
|
||||||
|
)
|
||||||
|
|
||||||
|
expected_schedule = [
|
||||||
|
["2020-01-31", 17.0, 17.0],
|
||||||
|
["2020-02-29", 29.0, 46.0],
|
||||||
|
["2020-03-31", 31.0, 77.0],
|
||||||
|
["2020-04-30", 30.0, 107.0],
|
||||||
|
["2020-05-31", 31.0, 138.0],
|
||||||
|
["2020-06-30", 30.0, 168.0],
|
||||||
|
["2020-07-31", 31.0, 199.0],
|
||||||
|
["2020-08-31", 31.0, 230.0],
|
||||||
|
["2020-09-30", 30.0, 260.0],
|
||||||
|
["2020-10-31", 31.0, 291.0],
|
||||||
|
["2020-11-30", 30.0, 321.0],
|
||||||
|
["2020-12-31", 31.0, 352.0],
|
||||||
|
["2021-01-31", 31.0, 383.0],
|
||||||
|
["2021-02-28", 28.0, 411.0],
|
||||||
|
["2021-03-31", 31.0, 442.0],
|
||||||
|
["2021-04-30", 30.0, 472.0],
|
||||||
|
["2021-05-31", 31.0, 503.0],
|
||||||
|
["2021-06-30", 30.0, 533.0],
|
||||||
|
["2021-07-31", 31.0, 564.0],
|
||||||
|
["2021-08-31", 31.0, 595.0],
|
||||||
|
["2021-09-30", 30.0, 625.0],
|
||||||
|
["2021-10-31", 31.0, 656.0],
|
||||||
|
["2021-11-30", 30.0, 686.0],
|
||||||
|
["2021-12-31", 31.0, 717.0],
|
||||||
|
["2022-01-31", 31.0, 748.0],
|
||||||
|
["2022-02-28", 28.0, 776.0],
|
||||||
|
["2022-03-31", 31.0, 807.0],
|
||||||
|
["2022-04-30", 30.0, 837.0],
|
||||||
|
["2022-05-31", 31.0, 868.0],
|
||||||
|
["2022-06-30", 30.0, 898.0],
|
||||||
|
["2022-07-31", 31.0, 929.0],
|
||||||
|
["2022-08-31", 31.0, 960.0],
|
||||||
|
["2022-09-30", 30.0, 990.0],
|
||||||
|
["2022-10-31", 31.0, 1021.0],
|
||||||
|
["2022-11-30", 30.0, 1051.0],
|
||||||
|
["2022-12-31", 31.0, 1082.0],
|
||||||
|
["2023-01-15", 14.0, 1096.0],
|
||||||
|
]
|
||||||
|
|
||||||
|
schedules = [
|
||||||
|
[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount]
|
||||||
|
for d in get_depr_schedule(asset.name, "Draft")
|
||||||
|
]
|
||||||
|
self.assertEqual(schedules, expected_schedule)
|
||||||
|
frappe.db.set_single_value("Accounts Settings", "calculate_depr_using_total_days", 0)
|
||||||
|
|
||||||
# Test for Written Down Value Method
|
# Test for Written Down Value Method
|
||||||
# Frequency of deprciation = 3
|
# Frequency of deprciation = 3
|
||||||
def test_for_daily_prorata_based_depreciation_wdv_method_frequency_3_months(self):
|
def test_for_daily_prorata_based_depreciation_wdv_method_frequency_3_months(self):
|
||||||
|
|||||||
@@ -289,6 +289,11 @@ def repost(doc):
|
|||||||
if isinstance(message, dict):
|
if isinstance(message, dict):
|
||||||
message = message.get("message")
|
message = message.get("message")
|
||||||
|
|
||||||
|
status = "Failed"
|
||||||
|
# If failed because of timeout, set status to In Progress
|
||||||
|
if traceback and "timeout" in traceback.lower():
|
||||||
|
status = "In Progress"
|
||||||
|
|
||||||
if traceback:
|
if traceback:
|
||||||
message += "<br><br>" + "<b>Traceback:</b> <br>" + traceback
|
message += "<br><br>" + "<b>Traceback:</b> <br>" + traceback
|
||||||
|
|
||||||
@@ -297,7 +302,7 @@ def repost(doc):
|
|||||||
doc.name,
|
doc.name,
|
||||||
{
|
{
|
||||||
"error_log": message,
|
"error_log": message,
|
||||||
"status": "Failed",
|
"status": status,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -40,32 +40,40 @@ frappe.ui.form.on("Warehouse", {
|
|||||||
if (!frm.is_new()) {
|
if (!frm.is_new()) {
|
||||||
frappe.contacts.render_address_and_contact(frm);
|
frappe.contacts.render_address_and_contact(frm);
|
||||||
|
|
||||||
let enable_toggle = frm.doc.disabled ? "Enable" : "Disable";
|
if (frm.has_perm("write")) {
|
||||||
frm.add_custom_button(__(enable_toggle), () => {
|
let enable_toggle = frm.doc.disabled ? "Enable" : "Disable";
|
||||||
frm.set_value("disabled", 1 - frm.doc.disabled);
|
frm.add_custom_button(__(enable_toggle), () => {
|
||||||
frm.save();
|
frm.set_value("disabled", 1 - frm.doc.disabled);
|
||||||
});
|
frm.save();
|
||||||
|
|
||||||
frm.add_custom_button(__("Stock Balance"), function () {
|
|
||||||
frappe.set_route("query-report", "Stock Balance", {
|
|
||||||
warehouse: frm.doc.name,
|
|
||||||
company: frm.doc.company,
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
frm.add_custom_button(
|
frm.add_custom_button(
|
||||||
frm.doc.is_group
|
frm.doc.is_group
|
||||||
? __("Convert to Ledger", null, "Warehouse")
|
? __("Convert to Ledger", null, "Warehouse")
|
||||||
: __("Convert to Group", null, "Warehouse"),
|
: __("Convert to Group", null, "Warehouse"),
|
||||||
function () {
|
function () {
|
||||||
convert_to_group_or_ledger(frm);
|
convert_to_group_or_ledger(frm);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("Stock Balance" in frappe.boot.user.all_reports) {
|
||||||
|
frm.add_custom_button(__("Stock Balance"), function () {
|
||||||
|
frappe.set_route("query-report", "Stock Balance", {
|
||||||
|
warehouse: frm.doc.name,
|
||||||
|
company: frm.doc.company,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
frappe.contacts.clear_address_and_contact(frm);
|
frappe.contacts.clear_address_and_contact(frm);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!frm.doc.is_group && frm.doc.__onload && frm.doc.__onload.account) {
|
if (
|
||||||
|
!frm.doc.is_group &&
|
||||||
|
frm.doc.__onload?.account &&
|
||||||
|
"General Ledger" in frappe.boot.user.all_reports
|
||||||
|
) {
|
||||||
frm.add_custom_button(__("General Ledger", null, "Warehouse"), function () {
|
frm.add_custom_button(__("General Ledger", null, "Warehouse"), function () {
|
||||||
frappe.route_options = {
|
frappe.route_options = {
|
||||||
account: frm.doc.__onload.account,
|
account: frm.doc.__onload.account,
|
||||||
|
|||||||
@@ -267,6 +267,8 @@ def repost_future_sle(
|
|||||||
"posting_time": args[i].get("posting_time"),
|
"posting_time": args[i].get("posting_time"),
|
||||||
"creation": args[i].get("creation"),
|
"creation": args[i].get("creation"),
|
||||||
"distinct_item_warehouses": distinct_item_warehouses,
|
"distinct_item_warehouses": distinct_item_warehouses,
|
||||||
|
"items_to_be_repost": args,
|
||||||
|
"current_index": i,
|
||||||
},
|
},
|
||||||
allow_negative_stock=allow_negative_stock,
|
allow_negative_stock=allow_negative_stock,
|
||||||
via_landed_cost_voucher=via_landed_cost_voucher,
|
via_landed_cost_voucher=via_landed_cost_voucher,
|
||||||
@@ -685,11 +687,20 @@ class update_entries_after:
|
|||||||
self.distinct_item_warehouses[key] = val
|
self.distinct_item_warehouses[key] = val
|
||||||
self.new_items_found = True
|
self.new_items_found = True
|
||||||
else:
|
else:
|
||||||
|
# Check if the dependent voucher is reposted
|
||||||
|
# If not, then do not add it to the list
|
||||||
|
if not self.is_dependent_voucher_reposted(dependant_sle):
|
||||||
|
return
|
||||||
|
|
||||||
existing_sle_posting_date = self.distinct_item_warehouses[key].get("sle", {}).get("posting_date")
|
existing_sle_posting_date = self.distinct_item_warehouses[key].get("sle", {}).get("posting_date")
|
||||||
|
|
||||||
dependent_voucher_detail_nos = self.get_dependent_voucher_detail_nos(key)
|
dependent_voucher_detail_nos = self.get_dependent_voucher_detail_nos(key)
|
||||||
|
|
||||||
if getdate(dependant_sle.posting_date) < getdate(existing_sle_posting_date):
|
if getdate(dependant_sle.posting_date) < getdate(existing_sle_posting_date):
|
||||||
|
if dependent_voucher_detail_nos and dependant_sle.voucher_detail_no in set(
|
||||||
|
dependent_voucher_detail_nos
|
||||||
|
):
|
||||||
|
return
|
||||||
|
|
||||||
val.sle_changed = True
|
val.sle_changed = True
|
||||||
dependent_voucher_detail_nos.append(dependant_sle.voucher_detail_no)
|
dependent_voucher_detail_nos.append(dependant_sle.voucher_detail_no)
|
||||||
val.dependent_voucher_detail_nos = dependent_voucher_detail_nos
|
val.dependent_voucher_detail_nos = dependent_voucher_detail_nos
|
||||||
@@ -703,6 +714,27 @@ class update_entries_after:
|
|||||||
val.dependent_voucher_detail_nos = dependent_voucher_detail_nos
|
val.dependent_voucher_detail_nos = dependent_voucher_detail_nos
|
||||||
self.distinct_item_warehouses[key] = val
|
self.distinct_item_warehouses[key] = val
|
||||||
|
|
||||||
|
def is_dependent_voucher_reposted(self, dependant_sle) -> bool:
|
||||||
|
# Return False if the dependent voucher is not reposted
|
||||||
|
|
||||||
|
if self.args.items_to_be_repost and self.args.current_index:
|
||||||
|
index = self.args.current_index
|
||||||
|
while index < len(self.args.items_to_be_repost):
|
||||||
|
if (
|
||||||
|
self.args.items_to_be_repost[index].get("item_code") == dependant_sle.item_code
|
||||||
|
and self.args.items_to_be_repost[index].get("warehouse") == dependant_sle.warehouse
|
||||||
|
):
|
||||||
|
if getdate(self.args.items_to_be_repost[index].get("posting_date")) > getdate(
|
||||||
|
dependant_sle.posting_date
|
||||||
|
):
|
||||||
|
self.args.items_to_be_repost[index]["posting_date"] = dependant_sle.posting_date
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
index += 1
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def get_dependent_voucher_detail_nos(self, key):
|
def get_dependent_voucher_detail_nos(self, key):
|
||||||
if "dependent_voucher_detail_nos" not in self.distinct_item_warehouses[key]:
|
if "dependent_voucher_detail_nos" not in self.distinct_item_warehouses[key]:
|
||||||
self.distinct_item_warehouses[key].dependent_voucher_detail_nos = []
|
self.distinct_item_warehouses[key].dependent_voucher_detail_nos = []
|
||||||
|
|||||||
@@ -31,6 +31,22 @@ frappe.ui.form.on("Subcontracting Order", {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
frm.set_query("cost_center", (doc) => {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
company: doc.company,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
frm.set_query("cost_center", "items", (doc) => {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
company: doc.company,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
frm.set_query("set_warehouse", () => {
|
frm.set_query("set_warehouse", () => {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
|
|||||||
@@ -174,6 +174,22 @@ frappe.ui.form.on("Subcontracting Receipt", {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
frm.set_query("cost_center", (doc) => {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
company: doc.company,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
frm.set_query("cost_center", "items", (doc) => {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
company: doc.company,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
frm.set_query("supplier_warehouse", () => {
|
frm.set_query("supplier_warehouse", () => {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
|
|||||||
Reference in New Issue
Block a user