Merge branch 'version-14-hotfix' into gross-and-net-profit-fix

This commit is contained in:
Anoop
2023-05-22 17:23:03 +05:30
committed by GitHub
17 changed files with 127 additions and 40 deletions

View File

@@ -905,7 +905,7 @@ frappe.ui.form.on('Payment Entry', {
function(d) { return flt(d.amount) })); function(d) { return flt(d.amount) }));
frm.set_value("difference_amount", difference_amount - total_deductions + frm.set_value("difference_amount", difference_amount - total_deductions +
frm.doc.base_total_taxes_and_charges); flt(frm.doc.base_total_taxes_and_charges));
frm.events.hide_unhide_fields(frm); frm.events.hide_unhide_fields(frm);
}, },

View File

@@ -302,7 +302,7 @@ def get_invoice_vouchers(parties, tax_details, company, party_type="Supplier"):
"docstatus": 1, "docstatus": 1,
} }
if not tax_details.get("consider_party_ledger_amount") and doctype != "Sales Invoice": if doctype != "Sales Invoice":
filters.update( filters.update(
{"apply_tds": 1, "tax_withholding_category": tax_details.get("tax_withholding_category")} {"apply_tds": 1, "tax_withholding_category": tax_details.get("tax_withholding_category")}
) )

View File

@@ -110,9 +110,9 @@ class TestTaxWithholdingCategory(unittest.TestCase):
invoices.append(pi1) invoices.append(pi1)
# Cumulative threshold is 30000 # Cumulative threshold is 30000
# Threshold calculation should be on both the invoices # Threshold calculation should be only on the Second invoice
# TDS should be applied only on 1000 # Second didn't breach, no TDS should be applied
self.assertEqual(pi1.taxes[0].tax_amount, 1000) self.assertEqual(pi1.taxes, [])
for d in reversed(invoices): for d in reversed(invoices):
d.cancel() d.cancel()

View File

@@ -425,7 +425,7 @@ class Asset(AccountsController):
depreciation_amount += value_after_depreciation - finance_book.expected_value_after_useful_life depreciation_amount += value_after_depreciation - finance_book.expected_value_after_useful_life
skip_row = True skip_row = True
if depreciation_amount > 0: if flt(depreciation_amount, self.precision("gross_purchase_amount")) > 0:
self._add_depreciation_row( self._add_depreciation_row(
schedule_date, schedule_date,
depreciation_amount, depreciation_amount,
@@ -1287,9 +1287,11 @@ def get_straight_line_or_manual_depr_amount(asset, row):
) )
# if the Depreciation Schedule is being prepared for the first time # if the Depreciation Schedule is being prepared for the first time
else: else:
return (flt(asset.gross_purchase_amount) - flt(row.expected_value_after_useful_life)) / flt( return (
row.total_number_of_depreciations flt(asset.gross_purchase_amount)
) - flt(asset.opening_accumulated_depreciation)
- flt(row.expected_value_after_useful_life)
) / flt(row.total_number_of_depreciations - asset.number_of_depreciations_booked)
def get_wdv_or_dd_depr_amount( def get_wdv_or_dd_depr_amount(

View File

@@ -649,7 +649,7 @@ class TestDepreciationMethods(AssetSetup):
) )
self.assertEqual(asset.status, "Draft") self.assertEqual(asset.status, "Draft")
expected_schedules = [["2032-12-31", 30000.0, 77095.89], ["2033-06-06", 12904.11, 90000.0]] expected_schedules = [["2032-12-31", 42904.11, 90000.0]]
schedules = [ schedules = [
[cstr(d.schedule_date), flt(d.depreciation_amount, 2), d.accumulated_depreciation_amount] [cstr(d.schedule_date), flt(d.depreciation_amount, 2), d.accumulated_depreciation_amount]
for d in asset.get("schedules") for d in asset.get("schedules")

View File

@@ -689,7 +689,6 @@ class SubcontractingController(StockController):
"actual_qty": flt(item.rejected_qty) * flt(item.conversion_factor), "actual_qty": flt(item.rejected_qty) * flt(item.conversion_factor),
"serial_no": cstr(item.rejected_serial_no).strip(), "serial_no": cstr(item.rejected_serial_no).strip(),
"incoming_rate": 0.0, "incoming_rate": 0.0,
"recalculate_rate": 1,
}, },
) )
) )

View File

@@ -7,4 +7,6 @@ def execute():
frappe.reload_doc("manufacturing", "doctype", "work_order") frappe.reload_doc("manufacturing", "doctype", "work_order")
frappe.reload_doc("manufacturing", "doctype", "work_order_item") frappe.reload_doc("manufacturing", "doctype", "work_order_item")
frappe.db.sql("""UPDATE `tabWork Order Item` SET amount = rate * required_qty""") frappe.db.sql(
"""UPDATE `tabWork Order Item` SET amount = ifnull(rate, 0.0) * ifnull(required_qty, 0.0)"""
)

View File

@@ -91,6 +91,12 @@ frappe.ui.form.on("Sales Invoice", {
}); });
frappe.ui.form.on('Purchase Invoice', { frappe.ui.form.on('Purchase Invoice', {
setup: (frm) => {
frm.make_methods = {
'Landed Cost Voucher': function () { frm.trigger('create_landedcost_voucher') },
}
},
mode_of_payment: function(frm) { mode_of_payment: function(frm) {
get_payment_mode_account(frm, frm.doc.mode_of_payment, function(account){ get_payment_mode_account(frm, frm.doc.mode_of_payment, function(account){
frm.set_value('cash_bank_account', account); frm.set_value('cash_bank_account', account);
@@ -99,6 +105,20 @@ frappe.ui.form.on('Purchase Invoice', {
payment_terms_template: function() { payment_terms_template: function() {
cur_frm.trigger("disable_due_date"); cur_frm.trigger("disable_due_date");
},
create_landedcost_voucher: function (frm) {
let lcv = frappe.model.get_new_doc('Landed Cost Voucher');
lcv.company = frm.doc.company;
let lcv_receipt = frappe.model.get_new_doc('Landed Cost Purchase Invoice');
lcv_receipt.receipt_document_type = 'Purchase Invoice';
lcv_receipt.receipt_document = frm.doc.name;
lcv_receipt.supplier = frm.doc.supplier;
lcv_receipt.grand_total = frm.doc.grand_total;
lcv.purchase_receipts = [lcv_receipt];
frappe.set_route("Form", lcv.doctype, lcv.name);
} }
}); });

View File

@@ -288,7 +288,7 @@ def _make_sales_order(source_name, target_doc=None, ignore_permissions=False):
) )
# sales team # sales team
for d in customer.get("sales_team"): for d in customer.get("sales_team") or []:
target.append( target.append(
"sales_team", "sales_team",
{ {

View File

@@ -25,15 +25,12 @@
"documentation_url": "https://docs.erpnext.com/docs/v14/user/manual/en/setting-up/company-setup", "documentation_url": "https://docs.erpnext.com/docs/v14/user/manual/en/setting-up/company-setup",
"idx": 0, "idx": 0,
"is_complete": 0, "is_complete": 0,
"modified": "2023-05-16 13:13:24.043792", "modified": "2023-05-20 19:45:03.936741",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Setup", "module": "Setup",
"name": "Home", "name": "Home",
"owner": "Administrator", "owner": "Administrator",
"steps": [ "steps": [
{
"step": "Navigation Help"
},
{ {
"step": "Create an Item" "step": "Create an Item"
}, },
@@ -47,7 +44,7 @@
"step": "Create a Quotation" "step": "Create a Quotation"
} }
], ],
"subtitle": "Item, Customer, Supplier, Navigation Help and Quotation", "subtitle": "Item, Customer, Supplier and Quotation",
"success_message": "You're ready to start your journey with ERPNext", "success_message": "You're ready to start your journey with ERPNext",
"title": "Let's begin your journey with ERPNext" "title": "Let's begin your journey with ERPNext"
} }

View File

@@ -9,7 +9,7 @@
"is_complete": 0, "is_complete": 0,
"is_single": 0, "is_single": 0,
"is_skipped": 0, "is_skipped": 0,
"modified": "2023-05-16 12:54:54.112364", "modified": "2023-05-16 20:01:34.202622",
"modified_by": "Administrator", "modified_by": "Administrator",
"name": "Create a Customer", "name": "Create a Customer",
"owner": "Administrator", "owner": "Administrator",

View File

@@ -9,7 +9,7 @@
"is_complete": 0, "is_complete": 0,
"is_single": 0, "is_single": 0,
"is_skipped": 0, "is_skipped": 0,
"modified": "2023-05-16 12:55:08.610113", "modified": "2023-05-19 15:32:55.069257",
"modified_by": "Administrator", "modified_by": "Administrator",
"name": "Create a Supplier", "name": "Create a Supplier",
"owner": "Administrator", "owner": "Administrator",

View File

@@ -29,6 +29,7 @@ class PickList(Document):
self.validate_for_qty() self.validate_for_qty()
def before_save(self): def before_save(self):
self.update_status()
self.set_item_locations() self.set_item_locations()
# set percentage picked in SO # set percentage picked in SO
@@ -89,20 +90,20 @@ class PickList(Document):
self.update_reference_qty() self.update_reference_qty()
self.update_sales_order_picking_status() self.update_sales_order_picking_status()
def update_status(self, status=None, update_modified=True): def update_status(self, status=None):
if not status: if not status:
if self.docstatus == 0: if self.docstatus == 0:
status = "Draft" status = "Draft"
elif self.docstatus == 1: elif self.docstatus == 1:
if self.status == "Draft": if target_document_exists(self.name, self.purpose):
status = "Open"
elif target_document_exists(self.name, self.purpose):
status = "Completed" status = "Completed"
else:
status = "Open"
elif self.docstatus == 2: elif self.docstatus == 2:
status = "Cancelled" status = "Cancelled"
if status: if status:
frappe.db.set_value("Pick List", self.name, "status", status, update_modified=update_modified) self.db_set("status", status)
def update_reference_qty(self): def update_reference_qty(self):
packed_items = [] packed_items = []

View File

@@ -33,5 +33,40 @@ frappe.query_reports["Stock and Account Value Comparison"] = {
"fieldtype": "Date", "fieldtype": "Date",
"default": frappe.datetime.get_today(), "default": frappe.datetime.get_today(),
}, },
] ],
get_datatable_options(options) {
return Object.assign(options, {
checkboxColumn: true,
});
},
onload(report) {
report.page.add_inner_button(__("Create Reposting Entries"), function() {
let message = `<div>
<p>
Reposting Entries will change the value of
accounts Stock In Hand, and Stock Expenses
in the Trial Balance report and will also change
the Balance Value in the Stock Balance report.
</p>
<p>Are you sure you want to create Reposting Entries?</p>
</div>
`;
frappe.confirm(__(message), () => {
let indexes = frappe.query_report.datatable.rowmanager.getCheckedRows();
let selected_rows = indexes.map(i => frappe.query_report.data[i]);
frappe.call({
method: "erpnext.stock.report.stock_and_account_value_comparison.stock_and_account_value_comparison.create_reposting_entries",
args: {
rows: selected_rows,
company: frappe.query_report.get_filter_values().company
}
});
});
});
}
}; };

View File

@@ -4,6 +4,7 @@
import frappe import frappe
from frappe import _ from frappe import _
from frappe.utils import get_link_to_form, parse_json
import erpnext import erpnext
from erpnext.accounts.utils import get_currency_precision, get_stock_accounts from erpnext.accounts.utils import get_currency_precision, get_stock_accounts
@@ -134,3 +135,35 @@ def get_columns(filters):
"width": "120", "width": "120",
}, },
] ]
@frappe.whitelist()
def create_reposting_entries(rows, company):
if isinstance(rows, str):
rows = parse_json(rows)
entries = []
for row in rows:
row = frappe._dict(row)
try:
doc = frappe.get_doc(
{
"doctype": "Repost Item Valuation",
"based_on": "Transaction",
"status": "Queued",
"voucher_type": row.voucher_type,
"voucher_no": row.voucher_no,
"posting_date": row.posting_date,
"company": company,
"allow_nagative_stock": 1,
}
).submit()
entries.append(get_link_to_form("Repost Item Valuation", doc.name))
except frappe.DuplicateEntryError:
pass
if entries:
entries = ", ".join(entries)
frappe.msgprint(_(f"Reposting entries created: {entries}"))

View File

@@ -76,26 +76,14 @@ frappe.ui.form.on('Subcontracting Receipt', {
} }
}); });
let batch_no_field = frm.get_docfield("items", "batch_no"); let batch_no_field = frm.get_docfield('items', 'batch_no');
if (batch_no_field) { if (batch_no_field) {
batch_no_field.get_route_options_for_new_doc = function(row) { batch_no_field.get_route_options_for_new_doc = function(row) {
return { return {
"item": row.doc.item_code 'item': row.doc.item_code
} }
}; };
} }
frappe.db.get_single_value('Buying Settings', 'backflush_raw_materials_of_subcontract_based_on').then(val => {
if (val == 'Material Transferred for Subcontract') {
frm.fields_dict['supplied_items'].grid.grid_rows.forEach((grid_row) => {
grid_row.docfields.forEach((df) => {
if (df.fieldname == 'consumed_qty') {
df.read_only = 0;
}
});
});
}
});
}, },
refresh: (frm) => { refresh: (frm) => {
@@ -157,6 +145,8 @@ frappe.ui.form.on('Subcontracting Receipt', {
} }
}); });
}, __('Get Items From')); }, __('Get Items From'));
frm.fields_dict.supplied_items.grid.update_docfield_property('consumed_qty', 'read_only', frm.doc.__onload && frm.doc.__onload.backflush_based_on === 'BOM');
} }
}, },

View File

@@ -28,6 +28,14 @@ class SubcontractingReceipt(SubcontractingController):
}, },
] ]
def onload(self):
self.set_onload(
"backflush_based_on",
frappe.db.get_single_value(
"Buying Settings", "backflush_raw_materials_of_subcontract_based_on"
),
)
def update_status_updater_args(self): def update_status_updater_args(self):
if cint(self.is_return): if cint(self.is_return):
self.status_updater.extend( self.status_updater.extend(