Compare commits
1 Commits
v13.52.6
...
revert-360
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf586f705e |
38
.github/workflows/release_notes.yml
vendored
38
.github/workflows/release_notes.yml
vendored
@@ -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 }}
|
||||
@@ -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):
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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":
|
||||
|
||||
@@ -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 }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"):
|
||||
|
||||
@@ -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
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
Reference in New Issue
Block a user