Compare commits

..

1 Commits

Author SHA1 Message Date
Anand Baburajan
bf586f705e Revert "fix: gst_hsn_code is ambiguous on gst reports" 2023-07-10 23:19:59 +05:30
18 changed files with 467 additions and 352 deletions

View File

@@ -1,38 +0,0 @@
# This action:
#
# 1. Generates release notes using github API.
# 2. Strips unnecessary info like chore/style etc from notes.
# 3. Updates release info.
# This action needs to be maintained on all branches that do releases.
name: 'Release Notes'
on:
workflow_dispatch:
inputs:
tag_name:
description: 'Tag of release like v13.0.0'
required: true
type: string
release:
types: [released]
permissions:
contents: read
jobs:
regen-notes:
name: 'Regenerate release notes'
runs-on: ubuntu-latest
steps:
- name: Update notes
run: |
NEW_NOTES=$(gh api --method POST -H "Accept: application/vnd.github+json" /repos/frappe/erpnext/releases/generate-notes -f tag_name=$RELEASE_TAG | jq -r '.body' | sed -E '/^\* (chore|ci|test|docs|style)/d' )
RELEASE_ID=$(gh api -H "Accept: application/vnd.github+json" /repos/frappe/erpnext/releases/tags/$RELEASE_TAG | jq -r '.id')
gh api --method PATCH -H "Accept: application/vnd.github+json" /repos/frappe/erpnext/releases/$RELEASE_ID -f body="$NEW_NOTES"
env:
GH_TOKEN: ${{ secrets.RELEASE_TOKEN }}
RELEASE_TAG: ${{ github.event.inputs.tag_name || github.event.release.tag_name }}

View File

@@ -4,7 +4,7 @@ import frappe
from erpnext.hooks import regional_overrides
__version__ = "13.52.6"
__version__ = "13.42.7"
def get_default_company(user=None):

View File

@@ -400,15 +400,6 @@ class JournalEntry(AccountsController):
d.idx, d.account
)
)
elif (
d.party_type
and frappe.db.get_value("Party Type", d.party_type, "account_type") != account_type
):
frappe.throw(
_("Row {0}: Account {1} and Party Type {2} have different account types").format(
d.idx, d.account, d.party_type
)
)
def check_credit_limit(self):
customers = list(

View File

@@ -206,7 +206,6 @@ class PaymentEntry(AccountsController):
elif latest.outstanding_amount < latest.invoice_amount and flt(
d.outstanding_amount, d.precision("outstanding_amount")
) != flt(latest.outstanding_amount, d.precision("outstanding_amount")):
frappe.throw(
_(
"{0} {1} has already been partly paid. Please use the 'Get Outstanding Invoice' or the 'Get Outstanding Orders' button to get the latest outstanding amounts."
@@ -1337,9 +1336,6 @@ def get_outstanding_reference_documents(args):
if args.get("party_type") == "Member":
return
if not args.get("get_outstanding_invoices") and not args.get("get_orders_to_be_billed"):
args["get_outstanding_invoices"] = True
# confirm that Supplier is not blocked
if args.get("party_type") == "Supplier":
supplier_status = get_supplier_block_status(args["party"])
@@ -1521,59 +1517,60 @@ def get_orders_to_be_billed(
cost_center=None,
filters=None,
):
voucher_type = None
if party_type == "Customer":
voucher_type = "Sales Order"
elif party_type == "Supplier":
voucher_type = "Purchase Order"
if not voucher_type:
return []
elif party_type == "Employee":
voucher_type = None
# Add cost center condition
doc = frappe.get_doc({"doctype": voucher_type})
condition = ""
if doc and hasattr(doc, "cost_center") and doc.cost_center:
condition = " and cost_center='%s'" % cost_center
if voucher_type:
doc = frappe.get_doc({"doctype": voucher_type})
condition = ""
if doc and hasattr(doc, "cost_center") and doc.cost_center:
condition = " and cost_center='%s'" % cost_center
if party_account_currency == company_currency:
grand_total_field = "base_grand_total"
rounded_total_field = "base_rounded_total"
else:
grand_total_field = "grand_total"
rounded_total_field = "rounded_total"
orders = []
if voucher_type:
if party_account_currency == company_currency:
grand_total_field = "base_grand_total"
rounded_total_field = "base_rounded_total"
else:
grand_total_field = "grand_total"
rounded_total_field = "rounded_total"
orders = frappe.db.sql(
"""
select
name as voucher_no,
if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) as invoice_amount,
(if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) - advance_paid) as outstanding_amount,
transaction_date as posting_date
from
`tab{voucher_type}`
where
{party_type} = %s
and docstatus = 1
and company = %s
and ifnull(status, "") != "Closed"
and if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) > advance_paid
and abs(100 - per_billed) > 0.01
{condition}
order by
transaction_date, name
""".format(
**{
"rounded_total_field": rounded_total_field,
"grand_total_field": grand_total_field,
"voucher_type": voucher_type,
"party_type": scrub(party_type),
"condition": condition,
}
),
(party, company),
as_dict=True,
)
orders = frappe.db.sql(
"""
select
name as voucher_no,
if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) as invoice_amount,
(if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) - advance_paid) as outstanding_amount,
transaction_date as posting_date
from
`tab{voucher_type}`
where
{party_type} = %s
and docstatus = 1
and company = %s
and ifnull(status, "") != "Closed"
and if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) > advance_paid
and abs(100 - per_billed) > 0.01
{condition}
order by
transaction_date, name
""".format(
**{
"rounded_total_field": rounded_total_field,
"grand_total_field": grand_total_field,
"voucher_type": voucher_type,
"party_type": scrub(party_type),
"condition": condition,
}
),
(party, company),
as_dict=True,
)
order_list = []
for d in orders:
@@ -1606,8 +1603,6 @@ def get_negative_outstanding_invoices(
cost_center=None,
condition=None,
):
if party_type not in ["Customer", "Supplier"]:
return []
voucher_type = "Sales Invoice" if party_type == "Customer" else "Purchase Invoice"
supplier_condition = ""
if voucher_type == "Purchase Invoice":

View File

@@ -63,7 +63,7 @@ frappe.ui.form.on('Asset Movement', {
fieldnames_to_be_altered = {
target_location: { read_only: 0, reqd: 1 },
source_location: { read_only: 1, reqd: 0 },
from_employee: { read_only: 0, reqd: 0 },
from_employee: { read_only: 0, reqd: 1 },
to_employee: { read_only: 1, reqd: 0 }
};
}

View File

@@ -63,20 +63,30 @@ class AssetMovement(Document):
frappe.throw(_("Source and Target Location cannot be same"))
if self.purpose == "Receipt":
if not (d.source_location or d.from_employee) and not (d.target_location or d.to_employee):
# only when asset is bought and first entry is made
if not d.source_location and not (d.target_location or d.to_employee):
frappe.throw(
_("Target Location or To Employee is required while receiving Asset {0}").format(d.asset)
)
elif d.from_employee and not d.target_location:
frappe.throw(
_("Target Location is required while receiving Asset {0} from an employee").format(d.asset)
)
elif d.to_employee and d.target_location:
frappe.throw(
_(
"Asset {0} cannot be received at a location and given to an employee in a single movement"
).format(d.asset)
)
elif d.source_location:
# when asset is received from an employee
if d.target_location and not d.from_employee:
frappe.throw(
_("From employee is required while receiving Asset {0} to a target location").format(
d.asset
)
)
if d.from_employee and not d.target_location:
frappe.throw(
_("Target Location is required while receiving Asset {0} from an employee").format(d.asset)
)
if d.to_employee and d.target_location:
frappe.throw(
_(
"Asset {0} cannot be received at a location and \
given to employee in a single movement"
).format(d.asset)
)
def validate_employee(self):
for d in self.assets:

View File

@@ -29,10 +29,6 @@ doctype_js = {
override_doctype_class = {"Address": "erpnext.accounts.custom.address.ERPNextAddress"}
override_whitelisted_methods = {
"frappe.www.contact.send_message": "erpnext.templates.utils.send_message"
}
welcome_email = "erpnext.setup.utils.welcome_email"
# setup wizard

View File

@@ -108,8 +108,8 @@ class EmployeeAdvance(Document):
EmployeeAdvanceOverPayment,
)
if flt(return_amount) > 0 and flt(return_amount) > (self.paid_amount - self.claimed_amount):
frappe.throw(_("Return amount cannot be greater than unclaimed amount"))
if flt(return_amount) > self.paid_amount - self.claimed_amount:
frappe.throw(_("Return amount cannot be greater unclaimed amount"))
self.db_set("paid_amount", paid_amount)
self.db_set("return_amount", return_amount)

View File

@@ -675,9 +675,10 @@ class ProductionPlan(Document):
material_request.flags.ignore_permissions = 1
material_request.run_method("set_missing_values")
material_request.save()
if self.get("submit_material_request"):
material_request.submit()
else:
material_request.save()
frappe.flags.mute_messages = False

View File

@@ -46,7 +46,6 @@ from erpnext.payroll.doctype.payroll_period.payroll_period import (
get_payroll_period,
get_period_factor,
)
from erpnext.payroll.utils import prepare_error_msg, sanitize_expression
from erpnext.utilities.transaction_base import TransactionBase
@@ -727,53 +726,32 @@ class SalarySlip(TransactionBase):
return data, default_data
def eval_condition_and_formula(self, struct_row, data):
def eval_condition_and_formula(self, d, data):
try:
condition = sanitize_expression(struct_row.condition)
condition = d.condition.strip().replace("\n", " ") if d.condition else None
if condition:
if not frappe.safe_eval(condition, self.whitelisted_globals, data):
return None
amount = struct_row.amount
if struct_row.amount_based_on_formula:
formula = sanitize_expression(struct_row.formula)
amount = d.amount
if d.amount_based_on_formula:
formula = d.formula.strip().replace("\n", " ") if d.formula else None
if formula:
amount = flt(
frappe.safe_eval(formula, self.whitelisted_globals, data), struct_row.precision("amount")
)
amount = flt(frappe.safe_eval(formula, self.whitelisted_globals, data), d.precision("amount"))
if amount:
data[struct_row.abbr] = amount
data[d.abbr] = amount
return amount
except NameError as ne:
message = prepare_error_msg(
row=struct_row,
error=ne,
expression=formula or condition,
description=_("This error can be due to missing or deleted field."),
except NameError as err:
frappe.throw(
_("{0} <br> This error can be due to missing or deleted field.").format(err),
title=_("Name error"),
)
frappe.throw(message, title=_("Name error"))
except SyntaxError as se:
message = prepare_error_msg(
row=struct_row,
error=se,
expression=formula or condition,
description=_("Please check the syntax of your formula."),
)
frappe.throw(message, title=_("Syntax error"))
except SyntaxError as err:
frappe.throw(_("Syntax error in formula or condition: {0}").format(err))
except Exception as e:
message = prepare_error_msg(
row=struct_row,
error=e,
expression=formula or condition,
description=_("This error can be due to invalid formula or condition."),
)
frappe.throw(message, title=_("Error in formula or condition"))
frappe.throw(_("Error in formula or condition: {0}").format(e))
raise
def add_employee_benefits(self, payroll_period):
for struct_row in self._salary_structure_doc.get("earnings"):

View File

@@ -1,66 +0,0 @@
from typing import Optional
import frappe
from frappe import _
from frappe.utils import get_link_to_form
def sanitize_expression(string: Optional[str] = None) -> Optional[str]:
"""
Sanitizes an expression string by removing leading/trailing spaces, newlines, and line boundaries.
Args:
string (Optional[str]): The input string to be sanitized (default: None).
Returns:
Optional[str]: The sanitized string or None if the input string is empty or None.
Example:
expression = "\r\n gross_pay > 10000\n "
sanitized_expr = sanitize_expression(expression)
"""
if not string:
return None
parts = string.strip().splitlines()
string = " ".join(parts)
return string
def prepare_error_msg(*, row: dict, error: str, expression: str, description: str) -> str:
"""
Prepares an error message string with formatted information about the error.
Args:
row (dict): A dictionary representing the row data.
error (str): The error message.
expression (str): The expression that caused the error.
description (str): Additional description or hint for the error (optional).
Returns:
str: The formatted error message string.
Example:
row = {
"parenttype": "Salary Structure",
"parent": "Salary Structure-00001",
"parentfield": "earnings",
"idx": 1
}
error = "SyntaxError: invalid syntax"
expression = " 200 if (gross_pay>10000 and month!= 'Feb')) else 0 "
description = "Check the syntax of the expression."
error_msg = prepare_error_msg(row=row, error=error, expression=expression, description=description)
"""
msg = _("Error in {0} while evaluating the {1} {2} at row {3}").format(
row.parentfield.title(), row.parenttype, get_link_to_form(row.parenttype, row.parent), row.idx
)
msg += "<br><br>{0}: {1}<br><br>{2}: {3}".format(
frappe.bold(_("Expression:")), expression, frappe.bold(_("Error:")), error
)
if description:
msg += "<br><br>{0}: {1}".format(frappe.bold(_("Hint:")), description)
return msg

View File

@@ -566,6 +566,7 @@ erpnext.utils.update_child_items = function(opts) {
fields.splice(3, 0, {
fieldtype: 'Float',
fieldname: "conversion_factor",
in_list_view: 1,
label: __("Conversion Factor"),
precision: get_precision('conversion_factor')
})
@@ -573,7 +574,6 @@ erpnext.utils.update_child_items = function(opts) {
new frappe.ui.Dialog({
title: __("Update Items"),
size: "extra-large",
fields: [
{
fieldname: "trans_items",

View File

@@ -3,6 +3,18 @@
if(!window.erpnext) window.erpnext = {};
// Add / update a new Lead / Communication
// subject, sender, description
frappe.send_message = function(opts, btn) {
return frappe.call({
type: "POST",
method: "erpnext.templates.utils.send_message",
btn: btn,
args: opts,
callback: opts.callback
});
};
erpnext.subscribe_to_newsletter = function(opts, btn) {
return frappe.call({
type: "POST",
@@ -12,3 +24,6 @@ erpnext.subscribe_to_newsletter = function(opts, btn) {
callback: opts.callback
});
}
// for backward compatibility
erpnext.send_message = frappe.send_message;

View File

@@ -213,8 +213,7 @@
"default": "0",
"fieldname": "disabled",
"fieldtype": "Check",
"label": "Disabled",
"search_index": 1
"label": "Disabled"
},
{
"default": "0",
@@ -957,7 +956,7 @@
"index_web_pages_for_search": 1,
"links": [],
"make_attachments_public": 1,
"modified": "2023-07-14 17:18:18.658942",
"modified": "2022-09-13 04:08:17.431731",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item",

View File

@@ -1,90 +1,370 @@
{
"actions": [],
"creation": "2015-05-19 05:12:30.344797",
"doctype": "DocType",
"document_type": "Other",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"variant_of",
"attribute",
"column_break_2",
"attribute_value",
"numeric_values",
"section_break_4",
"from_range",
"increment",
"column_break_8",
"to_range"
],
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "",
"beta": 0,
"creation": "2015-05-19 05:12:30.344797",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Other",
"editable_grid": 1,
"fields": [
{
"fieldname": "variant_of",
"fieldtype": "Link",
"label": "Variant Of",
"options": "Item",
"search_index": 1
},
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "variant_of",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Variant Of",
"length": 0,
"no_copy": 0,
"options": "Item",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"fieldname": "attribute",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Attribute",
"options": "Item Attribute",
"reqd": 1,
"search_index": 1
},
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "attribute",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Attribute",
"length": 0,
"no_copy": 0,
"options": "Item Attribute",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"fieldname": "column_break_2",
"fieldtype": "Column Break"
},
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_2",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"fieldname": "attribute_value",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Attribute Value"
},
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fieldname": "attribute_value",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Attribute Value",
"length": 0,
"no_copy": 0,
"options": "",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"default": "0",
"depends_on": "has_variants",
"fieldname": "numeric_values",
"fieldtype": "Check",
"label": "Numeric Values"
},
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "has_variants",
"fieldname": "numeric_values",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Numeric Values",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"depends_on": "numeric_values",
"fieldname": "section_break_4",
"fieldtype": "Section Break"
},
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "numeric_values",
"fieldname": "section_break_4",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"fieldname": "from_range",
"fieldtype": "Float",
"label": "From Range"
},
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fieldname": "from_range",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "From Range",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"fieldname": "increment",
"fieldtype": "Float",
"label": "Increment"
},
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fieldname": "increment",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Increment",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"fieldname": "column_break_8",
"fieldtype": "Column Break"
},
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_8",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"fieldname": "to_range",
"fieldtype": "Float",
"label": "To Range"
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fieldname": "to_range",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "To Range",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
"istable": 1,
"links": [],
"modified": "2023-07-14 17:15:19.112119",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item Variant Attribute",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC",
"states": []
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "",
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2019-01-03 15:36:59.129006",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item Variant Attribute",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 0,
"track_seen": 0,
"track_views": 0
}

View File

@@ -1944,32 +1944,6 @@ class TestPurchaseReceipt(FrappeTestCase):
ste5.reload()
self.assertEqual(ste5.items[0].valuation_rate, 275.00)
ste6 = make_stock_entry(
purpose="Material Transfer",
posting_date=add_days(today(), -3),
source=warehouse1,
target=warehouse,
item_code=item_code,
qty=20,
company=pr.company,
)
ste6.reload()
self.assertEqual(ste6.items[0].valuation_rate, 275.00)
ste7 = make_stock_entry(
purpose="Material Transfer",
posting_date=add_days(today(), -3),
source=warehouse,
target=warehouse1,
item_code=item_code,
qty=20,
company=pr.company,
)
ste7.reload()
self.assertEqual(ste7.items[0].valuation_rate, 275.00)
create_landed_cost_voucher("Purchase Receipt", pr.name, pr.company, charges=2500 * -1)
pr.reload()
@@ -1990,12 +1964,6 @@ class TestPurchaseReceipt(FrappeTestCase):
ste5.reload()
self.assertEqual(ste5.items[0].valuation_rate, valuation_rate)
ste6.reload()
self.assertEqual(ste6.items[0].valuation_rate, valuation_rate)
ste7.reload()
self.assertEqual(ste7.items[0].valuation_rate, valuation_rate)
def prepare_data_for_internal_transfer():
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier

View File

@@ -501,7 +501,7 @@ class update_entries_after(object):
def update_distinct_item_warehouses(self, dependant_sle):
key = (dependant_sle.item_code, dependant_sle.warehouse)
val = frappe._dict({"sle": dependant_sle, "dependent_voucher_detail_nos": []})
val = frappe._dict({"sle": dependant_sle})
if key not in self.distinct_item_warehouses:
self.distinct_item_warehouses[key] = val
@@ -510,26 +510,13 @@ class update_entries_after(object):
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)
if getdate(dependant_sle.posting_date) < getdate(existing_sle_posting_date):
val.sle_changed = True
self.distinct_item_warehouses[key] = val
self.new_items_found = True
elif dependant_sle.voucher_detail_no not in set(dependent_voucher_detail_nos):
# Future dependent voucher needs to be repost to get the correct stock value
# If dependent voucher has not reposted, then add it to the list
dependent_voucher_detail_nos.append(dependant_sle.voucher_detail_no)
self.new_items_found = True
val.dependent_voucher_detail_nos = dependent_voucher_detail_nos
elif self.distinct_item_warehouses[key].get("reposting_status"):
self.distinct_item_warehouses[key] = val
def get_dependent_voucher_detail_nos(self, key):
if "dependent_voucher_detail_nos" not in self.distinct_item_warehouses[key]:
self.distinct_item_warehouses[key].dependent_voucher_detail_nos = []
return self.distinct_item_warehouses[key].dependent_voucher_detail_nos
self.new_items_found = True
def process_sle(self, sle):
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
@@ -1175,7 +1162,6 @@ def get_sle_by_voucher_detail_no(voucher_detail_no, excluded_sle=None):
"qty_after_transaction",
"posting_date",
"posting_time",
"voucher_detail_no",
"timestamp(posting_date, posting_time) as timestamp",
],
as_dict=1,

View File

@@ -15,7 +15,7 @@
{% for item, taxes in itemised_tax.items() %}
<tr>
<td>{{ item }}</td>
<td class="text-right">
<td class='text-right'>
{% if doc.get('is_return') %}
{{ frappe.utils.fmt_money((itemised_taxable_amount.get(item, 0))|abs, None, doc.currency) }}
{% else %}
@@ -25,7 +25,7 @@
{% for tax_account in tax_accounts %}
{% set tax_details = taxes.get(tax_account) %}
{% if tax_details %}
<td class="text-right">
<td class='text-right'>
{% if tax_details.tax_rate or not tax_details.tax_amount %}
({{ tax_details.tax_rate }}%)
{% endif %}