mirror of
https://github.com/frappe/erpnext.git
synced 2026-04-28 02:58:30 +00:00
Merge pull request #51440 from rohitwaghchaure/rc-2
chore: v16 beta RC 2
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"chart_name": "Profit and Loss",
|
||||
"chart_type": "Report",
|
||||
"creation": "2020-07-17 11:25:34.448572",
|
||||
"creation": "2025-04-01 20:38:16.986176",
|
||||
"docstatus": 0,
|
||||
"doctype": "Dashboard Chart",
|
||||
"dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"from_fiscal_year\":\"erpnext.utils.get_fiscal_year()\",\"to_fiscal_year\":\"erpnext.utils.get_fiscal_year()\"}",
|
||||
@@ -9,7 +9,7 @@
|
||||
"idx": 0,
|
||||
"is_public": 1,
|
||||
"is_standard": 1,
|
||||
"modified": "2023-07-19 13:08:56.470390",
|
||||
"modified": "2025-12-19 12:37:31.673782",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Profit and Loss",
|
||||
@@ -17,8 +17,9 @@
|
||||
"owner": "Administrator",
|
||||
"report_name": "Profit and Loss Statement",
|
||||
"roles": [],
|
||||
"show_values_over_chart": 1,
|
||||
"timeseries": 0,
|
||||
"type": "Bar",
|
||||
"type": "Line",
|
||||
"use_report_chart": 1,
|
||||
"y_axis": []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ class BankClearance(Document):
|
||||
)
|
||||
|
||||
msg += "</ul>"
|
||||
frappe.throw(_(msg))
|
||||
msgprint(_(msg))
|
||||
return
|
||||
|
||||
if not entries_to_update:
|
||||
|
||||
@@ -30,8 +30,7 @@
|
||||
"label": "Payment Entry",
|
||||
"oldfieldname": "voucher_id",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "payment_document",
|
||||
"width": "50"
|
||||
"options": "payment_document"
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
@@ -69,7 +68,7 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"columns": 1,
|
||||
"fieldname": "cheque_number",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
@@ -79,8 +78,10 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "cheque_date",
|
||||
"fieldtype": "Date",
|
||||
"in_list_view": 1,
|
||||
"label": "Cheque Date",
|
||||
"oldfieldname": "cheque_date",
|
||||
"oldfieldtype": "Date",
|
||||
@@ -96,17 +97,19 @@
|
||||
"oldfieldtype": "Date"
|
||||
}
|
||||
],
|
||||
"grid_page_length": 50,
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:06:37.609319",
|
||||
"modified": "2025-12-17 14:33:45.913311",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Clearance Detail",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"row_format": "Dynamic",
|
||||
"sort_field": "creation",
|
||||
"sort_order": "ASC",
|
||||
"states": []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,6 +304,7 @@ def create_payment_entry_bts(
|
||||
project=None,
|
||||
cost_center=None,
|
||||
allow_edit=None,
|
||||
company_bank_account=None,
|
||||
):
|
||||
# Create a new payment entry based on the bank transaction
|
||||
bank_transaction = frappe.db.get_values(
|
||||
@@ -345,6 +346,9 @@ def create_payment_entry_bts(
|
||||
pe.project = project
|
||||
pe.cost_center = cost_center
|
||||
|
||||
if company_bank_account:
|
||||
pe.bank_account = company_bank_account
|
||||
|
||||
pe.validate()
|
||||
|
||||
if allow_edit:
|
||||
|
||||
@@ -50,6 +50,9 @@ class BankTransaction(Document):
|
||||
self.handle_excluded_fee()
|
||||
self.update_allocated_amount()
|
||||
|
||||
def on_discard(self):
|
||||
self.db_set("status", "Cancelled")
|
||||
|
||||
def validate(self):
|
||||
self.validate_included_fee()
|
||||
self.validate_duplicate_references()
|
||||
|
||||
@@ -9,8 +9,8 @@ frappe.listview_settings["Invoice Discounting"] = {
|
||||
return [__("Disbursed"), "blue", "status,=,Disbursed"];
|
||||
} else if (doc.status == "Settled") {
|
||||
return [__("Settled"), "orange", "status,=,Settled"];
|
||||
} else if (doc.status == "Canceled") {
|
||||
return [__("Canceled"), "red", "status,=,Canceled"];
|
||||
} else if (doc.status == "Cancelled") {
|
||||
return [__("Cancelled"), "red", "status,=,Cancelled"];
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -427,7 +427,15 @@ frappe.ui.form.on("Payment Entry", {
|
||||
|
||||
if (frm.doc.payment_type == "Internal Transfer") {
|
||||
$.each(
|
||||
["party", "party_type", "paid_from", "paid_to", "references", "total_allocated_amount"],
|
||||
[
|
||||
"party",
|
||||
"party_type",
|
||||
"paid_from",
|
||||
"paid_to",
|
||||
"references",
|
||||
"total_allocated_amount",
|
||||
"party_name",
|
||||
],
|
||||
function (i, field) {
|
||||
frm.set_value(field, null);
|
||||
}
|
||||
|
||||
@@ -100,7 +100,10 @@ class PaymentRequest(Document):
|
||||
subscription_plans: DF.Table[SubscriptionPlanDetail]
|
||||
swift_number: DF.ReadOnly | None
|
||||
transaction_date: DF.Date | None
|
||||
|
||||
# end: auto-generated types
|
||||
def on_discard(self):
|
||||
self.db_set("status", "Cancelled")
|
||||
|
||||
def validate(self):
|
||||
if self.get("__islocal"):
|
||||
|
||||
@@ -35,7 +35,10 @@ class ProcessPaymentReconciliation(Document):
|
||||
]
|
||||
to_invoice_date: DF.Date | None
|
||||
to_payment_date: DF.Date | None
|
||||
|
||||
# end: auto-generated types
|
||||
def on_discard(self):
|
||||
self.db_set("status", "Cancelled")
|
||||
|
||||
def validate(self):
|
||||
self.validate_receivable_payable_account()
|
||||
|
||||
@@ -36,7 +36,10 @@ class ProcessPeriodClosingVoucher(Document):
|
||||
parent_pcv: DF.Link
|
||||
status: DF.Literal["Queued", "Running", "Paused", "Completed", "Cancelled"]
|
||||
z_opening_balances: DF.Table[ProcessPeriodClosingVoucherDetail]
|
||||
|
||||
# end: auto-generated types
|
||||
def on_discard(self):
|
||||
self.db_set("status", "Cancelled")
|
||||
|
||||
def validate(self):
|
||||
self.status = "Queued"
|
||||
|
||||
@@ -115,6 +115,10 @@ class RepostAccountingLedger(Document):
|
||||
def generate_preview(self):
|
||||
from erpnext.accounts.report.general_ledger.general_ledger import get_columns as get_gl_columns
|
||||
|
||||
if not self.vouchers:
|
||||
frappe.msgprint(_("Add vouchers to generate preview."))
|
||||
return
|
||||
|
||||
gl_columns = []
|
||||
gl_data = []
|
||||
|
||||
@@ -142,6 +146,7 @@ class RepostAccountingLedger(Document):
|
||||
account_repost_doc=self.name,
|
||||
is_async=True,
|
||||
job_name=job_name,
|
||||
enqueue_after_commit=True,
|
||||
)
|
||||
frappe.msgprint(_("Repost has started in the background"))
|
||||
else:
|
||||
|
||||
@@ -25,7 +25,6 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
||||
get_accounting_dimensions,
|
||||
)
|
||||
from erpnext.accounts.doctype.subscription_plan.subscription_plan import get_plan_rate
|
||||
from erpnext.accounts.party import get_party_account_currency
|
||||
|
||||
|
||||
class InvoiceCancelled(frappe.ValidationError):
|
||||
@@ -432,7 +431,6 @@ class Subscription(Document):
|
||||
items_list = self.get_items_from_plans(self.plans, is_prorate())
|
||||
|
||||
for item in items_list:
|
||||
item["cost_center"] = self.cost_center
|
||||
invoice.append("items", item)
|
||||
|
||||
# Taxes
|
||||
|
||||
@@ -653,7 +653,7 @@ def reset_settings():
|
||||
|
||||
def create_subscription(**kwargs):
|
||||
subscription = frappe.new_doc("Subscription")
|
||||
subscription.party_type = (kwargs.get("party_type") or "Customer",)
|
||||
subscription.party_type = kwargs.get("party_type") or "Customer"
|
||||
subscription.company = kwargs.get("company") or "_Test Company"
|
||||
subscription.party = kwargs.get("party") or "_Test Customer"
|
||||
subscription.trial_period_start = kwargs.get("trial_period_start")
|
||||
|
||||
@@ -1214,8 +1214,6 @@ class TestTaxWithholdingCategory(IntegrationTestCase):
|
||||
# First invoice - below threshold, should be under withheld
|
||||
pi = create_purchase_invoice(supplier="Test TDS Supplier6", rate=4000, do_not_save=True)
|
||||
pi.apply_tds = 1
|
||||
pi.tax_withholding_category = "Test Multi Invoice Category"
|
||||
pi.save()
|
||||
pi.submit()
|
||||
invoices.append(pi)
|
||||
|
||||
@@ -1478,7 +1476,6 @@ class TestTaxWithholdingCategory(IntegrationTestCase):
|
||||
|
||||
pi = create_purchase_invoice(supplier="Test TDS Supplier6", rate=12000, do_not_save=True)
|
||||
pi.apply_tds = 1
|
||||
pi.tax_withholding_category = "Test Multi Invoice Category"
|
||||
advances = pi.get_advance_entries()
|
||||
pi.append(
|
||||
"advances",
|
||||
@@ -2096,7 +2093,6 @@ class TestTaxWithholdingCategory(IntegrationTestCase):
|
||||
# Create purchase invoice that settles the payment entry
|
||||
pi = create_purchase_invoice(supplier="Test TDS Supplier6", rate=8000, do_not_save=True)
|
||||
pi.apply_tds = 1
|
||||
pi.tax_withholding_category = "Test Multi Invoice Category"
|
||||
advances = pi.get_advance_entries()
|
||||
pi.append(
|
||||
"advances",
|
||||
@@ -2719,7 +2715,6 @@ class TestTaxWithholdingCategory(IntegrationTestCase):
|
||||
# Create purchase invoice with manual override
|
||||
pi = create_purchase_invoice(supplier="Test TDS Supplier6", rate=20000, do_not_save=True)
|
||||
pi.apply_tds = 1
|
||||
pi.tax_withholding_category = "Test Multi Invoice Category"
|
||||
pi.ignore_tax_withholding_threshold = 1
|
||||
pi.save()
|
||||
|
||||
@@ -2749,7 +2744,6 @@ class TestTaxWithholdingCategory(IntegrationTestCase):
|
||||
|
||||
# Step 2: Create Purchase Invoice with partial adjustment and manual rate change
|
||||
pi = create_purchase_invoice(supplier="Test TDS Supplier8", rate=80000, do_not_save=True)
|
||||
pi.tax_withholding_category = "Test Multi Invoice Category"
|
||||
pi.override_tax_withholding_entries = 1 # Enable manual override
|
||||
pi.tax_withholding_entries = []
|
||||
|
||||
@@ -2790,6 +2784,7 @@ class TestTaxWithholdingCategory(IntegrationTestCase):
|
||||
)
|
||||
|
||||
pi.save()
|
||||
pi.reload()
|
||||
pi.submit()
|
||||
|
||||
# Step 3: Verify the tax withholding entries
|
||||
@@ -2870,7 +2865,6 @@ class TestTaxWithholdingCategory(IntegrationTestCase):
|
||||
|
||||
# Step 2: Create Purchase Invoice with partial adjustment and manual rate change
|
||||
pi = create_purchase_invoice(supplier="Test TDS Supplier8", rate=80000, do_not_save=True)
|
||||
pi.tax_withholding_category = "Test Multi Invoice Category"
|
||||
pi.override_tax_withholding_entries = 1 # Enable manual override
|
||||
pi.tax_withholding_entries = []
|
||||
|
||||
@@ -2911,6 +2905,7 @@ class TestTaxWithholdingCategory(IntegrationTestCase):
|
||||
)
|
||||
|
||||
pi.save()
|
||||
pi.reload()
|
||||
pi.submit()
|
||||
|
||||
# Step 3: Verify the tax withholding entries
|
||||
@@ -2993,7 +2988,6 @@ class TestTaxWithholdingCategory(IntegrationTestCase):
|
||||
self.validate_tax_withholding_entries("Payment Entry", pe.name, pe_expected)
|
||||
|
||||
pi = create_purchase_invoice(supplier="Test TDS Supplier8", rate=50000, do_not_save=True)
|
||||
pi.tax_withholding_category = "Test Multi Invoice Category"
|
||||
pi.override_tax_withholding_entries = 1
|
||||
pi.tax_withholding_entries = []
|
||||
|
||||
|
||||
@@ -377,30 +377,23 @@ class TaxWithholdingController:
|
||||
return category_names
|
||||
|
||||
def calculate(self):
|
||||
# Always get category details first for account mapping
|
||||
self.category_details = self._get_category_details()
|
||||
|
||||
self._update_taxable_amounts()
|
||||
|
||||
if not self.doc.override_tax_withholding_entries:
|
||||
self._generate_withholding_entries()
|
||||
|
||||
# Final processing - entry status and tax_update
|
||||
self._process_withholding_entries()
|
||||
|
||||
def _generate_withholding_entries(self):
|
||||
# Clear existing entries
|
||||
self.doc.tax_withholding_entries = []
|
||||
|
||||
# Calculate taxable amounts for each category
|
||||
self._update_taxable_amounts()
|
||||
|
||||
# Apply threshold rules
|
||||
self._evaluate_thresholds()
|
||||
|
||||
# Generate entries for each category
|
||||
for category in self.category_details.values():
|
||||
self.entries += self._create_entries_for_category(category)
|
||||
|
||||
# Add all generated entries to the document
|
||||
self.doc.extend("tax_withholding_entries", self.entries)
|
||||
|
||||
def _create_entries_for_category(self, category):
|
||||
|
||||
@@ -1063,3 +1063,21 @@ def add_party_account(party_type, party, company, account):
|
||||
|
||||
def render_address(address, check_permissions=True):
|
||||
return frappe.call(_render_address, address, check_permissions=check_permissions)
|
||||
|
||||
|
||||
def validate_party_currency_before_merging(party_type, old_party, new_party):
|
||||
for company in frappe.get_all("Company"):
|
||||
old_party_currency = get_party_gle_currency(party_type, old_party, company.name)
|
||||
new_party_currency = get_party_gle_currency(party_type, new_party, company.name)
|
||||
|
||||
if old_party_currency and new_party_currency and old_party_currency != new_party_currency:
|
||||
frappe.throw(
|
||||
_(
|
||||
"Cannot merge {0} '{1}' into '{2}' as both have existing accounting entries in different currencies for company '{3}'."
|
||||
).format(
|
||||
party_type,
|
||||
old_party,
|
||||
new_party,
|
||||
company.name,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"label": "Profit and Loss"
|
||||
}
|
||||
],
|
||||
"content": "[{\"id\":\"nDhfcJYbKH\",\"type\":\"chart\",\"data\":{\"chart_name\":\"Profit and Loss\",\"col\":12}},{\"id\":\"VVvJ1lUcfc\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Outgoing Bills\",\"col\":3}},{\"id\":\"Vlj2FZtlHV\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Incoming Bills\",\"col\":3}},{\"id\":\"VVVjQVAhPf\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Incoming Payment\",\"col\":3}},{\"id\":\"DySNdlysIW\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Outgoing Payment\",\"col\":3}},{\"id\":\"tHb3yxthkR\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"id\":\"DnNtsmxpty\",\"type\":\"card\",\"data\":{\"card_name\":\"Accounting Masters\",\"col\":4}},{\"id\":\"nKKr6fjgjb\",\"type\":\"card\",\"data\":{\"card_name\":\"Payments\",\"col\":4}},{\"id\":\"KlqilF5R_V\",\"type\":\"card\",\"data\":{\"card_name\":\"Tax Masters\",\"col\":4}},{\"id\":\"jTUy8LB0uw\",\"type\":\"card\",\"data\":{\"card_name\":\"Cost Center and Budgeting\",\"col\":4}},{\"id\":\"Wn2lhs7WLn\",\"type\":\"card\",\"data\":{\"card_name\":\"Multi Currency\",\"col\":4}},{\"id\":\"PAQMqqNkBM\",\"type\":\"card\",\"data\":{\"card_name\":\"Banking\",\"col\":4}},{\"id\":\"kxhoaiqdLq\",\"type\":\"card\",\"data\":{\"card_name\":\"Opening and Closing\",\"col\":4}},{\"id\":\"q0MAlU2j_Z\",\"type\":\"card\",\"data\":{\"card_name\":\"Subscription Management\",\"col\":4}},{\"id\":\"ptm7T6Hwu-\",\"type\":\"card\",\"data\":{\"card_name\":\"Share Management\",\"col\":4}}]",
|
||||
"content": "[{\"id\":\"nDhfcJYbKH\",\"type\":\"chart\",\"data\":{\"chart_name\":\"Profit and Loss\",\"col\":12}},{\"id\":\"VVvJ1lUcfc\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Outgoing Bills\",\"col\":3}},{\"id\":\"Vlj2FZtlHV\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Incoming Bills\",\"col\":3}},{\"id\":\"VVVjQVAhPf\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Incoming Payment\",\"col\":3}},{\"id\":\"DySNdlysIW\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Outgoing Payment\",\"col\":3}},{\"id\":\"tHb3yxthkR\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"id\":\"DnNtsmxpty\",\"type\":\"card\",\"data\":{\"card_name\":\"Accounting Masters\",\"col\":4}},{\"id\":\"nKKr6fjgjb\",\"type\":\"card\",\"data\":{\"card_name\":\"Payments\",\"col\":4}},{\"id\":\"KlqilF5R_V\",\"type\":\"card\",\"data\":{\"card_name\":\"Tax Masters\",\"col\":4}},{\"id\":\"jTUy8LB0uw\",\"type\":\"card\",\"data\":{\"card_name\":\"Cost Center and Budgeting\",\"col\":4}},{\"id\":\"Wn2lhs7WLn\",\"type\":\"card\",\"data\":{\"card_name\":\"Multi Currency\",\"col\":4}},{\"id\":\"PAQMqqNkBM\",\"type\":\"card\",\"data\":{\"card_name\":\"Banking\",\"col\":4}},{\"id\":\"kxhoaiqdLq\",\"type\":\"card\",\"data\":{\"card_name\":\"Opening and Closing\",\"col\":4}},{\"id\":\"q0MAlU2j_Z\",\"type\":\"card\",\"data\":{\"card_name\":\"Subscription Management\",\"col\":4}},{\"id\":\"ptm7T6Hwu-\",\"type\":\"card\",\"data\":{\"card_name\":\"Share Management\",\"col\":4}}]",
|
||||
"creation": "2020-03-02 15:41:59.515192",
|
||||
"custom_blocks": [],
|
||||
"docstatus": 0,
|
||||
@@ -14,7 +14,7 @@
|
||||
"for_user": "",
|
||||
"hide_custom": 0,
|
||||
"icon": "accounting",
|
||||
"idx": 0,
|
||||
"idx": 3,
|
||||
"indicator_color": "",
|
||||
"is_hidden": 0,
|
||||
"label": "Accounting",
|
||||
@@ -587,25 +587,25 @@
|
||||
"type": "Link"
|
||||
}
|
||||
],
|
||||
"modified": "2025-11-17 14:35:00.910131",
|
||||
"modified": "2025-12-24 13:20:34.857205",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounting",
|
||||
"number_cards": [
|
||||
{
|
||||
"label": "Total Outgoing Bills",
|
||||
"label": "Outgoing Bills",
|
||||
"number_card_name": "Total Outgoing Bills"
|
||||
},
|
||||
{
|
||||
"label": "Total Incoming Bills",
|
||||
"label": "Incoming Bills",
|
||||
"number_card_name": "Total Incoming Bills"
|
||||
},
|
||||
{
|
||||
"label": "Total Incoming Payment",
|
||||
"label": "Incoming Payment",
|
||||
"number_card_name": "Total Incoming Payment"
|
||||
},
|
||||
{
|
||||
"label": "Total Outgoing Payment",
|
||||
"label": "Outgoing Payment",
|
||||
"number_card_name": "Total Outgoing Payment"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
{
|
||||
"charts": [],
|
||||
"content": "[{\"id\":\"nKKr6fjgjb\",\"type\":\"card\",\"data\":{\"card_name\":\"Ledgers\",\"col\":4}},{\"id\":\"p7NY6MHe2Y\",\"type\":\"card\",\"data\":{\"card_name\":\"Financial Statements\",\"col\":4}},{\"id\":\"3AK1Zf0oew\",\"type\":\"card\",\"data\":{\"card_name\":\"Profitability\",\"col\":4}},{\"id\":\"Q_hBCnSeJY\",\"type\":\"card\",\"data\":{\"card_name\":\"Other Reports\",\"col\":4}}]",
|
||||
"app": "erpnext",
|
||||
"charts": [
|
||||
{
|
||||
"chart_name": "Profit and Loss",
|
||||
"label": "Profit and Loss"
|
||||
}
|
||||
],
|
||||
"content": "[{\"id\":\"tS7ZWzC24I\",\"type\":\"chart\",\"data\":{\"chart_name\":\"Profit and Loss\",\"col\":12}},{\"id\":\"8Ej2KxPxOt\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"p7NY6MHe2Y\",\"type\":\"card\",\"data\":{\"card_name\":\"Financial Statements\",\"col\":4}},{\"id\":\"nKKr6fjgjb\",\"type\":\"card\",\"data\":{\"card_name\":\"Ledgers\",\"col\":4}},{\"id\":\"3AK1Zf0oew\",\"type\":\"card\",\"data\":{\"card_name\":\"Profitability\",\"col\":4}},{\"id\":\"Q_hBCnSeJY\",\"type\":\"card\",\"data\":{\"card_name\":\"Other Reports\",\"col\":4}}]",
|
||||
"creation": "2024-01-05 16:09:16.766939",
|
||||
"custom_blocks": [],
|
||||
"docstatus": 0,
|
||||
"doctype": "Workspace",
|
||||
"for_user": "",
|
||||
"hide_custom": 0,
|
||||
"icon": "file",
|
||||
"icon": "table",
|
||||
"idx": 0,
|
||||
"indicator_color": "",
|
||||
"is_hidden": 0,
|
||||
@@ -260,7 +266,7 @@
|
||||
"type": "Link"
|
||||
}
|
||||
],
|
||||
"modified": "2024-01-18 22:13:07.596844",
|
||||
"modified": "2025-12-24 12:49:25.266357",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Financial Reports",
|
||||
@@ -273,5 +279,6 @@
|
||||
"roles": [],
|
||||
"sequence_id": 5.0,
|
||||
"shortcuts": [],
|
||||
"title": "Financial Reports"
|
||||
}
|
||||
"title": "Financial Reports",
|
||||
"type": "Workspace"
|
||||
}
|
||||
|
||||
@@ -1,204 +0,0 @@
|
||||
{
|
||||
"charts": [],
|
||||
"content": "[{\"id\":\"rMMsfn2eB4\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Shortcuts</b></span>\",\"col\":12}},{\"id\":\"G984SgVRJN\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Invoice\",\"col\":3}},{\"id\":\"F9f4I1viNr\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Payment Entry\",\"col\":3}},{\"id\":\"1ArNvt9qhz\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Journal Entry\",\"col\":3}},{\"id\":\"4IBBOIxfqW\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Payable\",\"col\":3}},{\"id\":\"B7-uxs8tkU\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"jAcOH-cC-Q\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"id\":\"7dj93PEUjW\",\"type\":\"card\",\"data\":{\"card_name\":\"Invoicing\",\"col\":4}},{\"id\":\"_Cb7C8XdJJ\",\"type\":\"card\",\"data\":{\"card_name\":\"Payments\",\"col\":4}},{\"id\":\"9yseIkdG50\",\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}}]",
|
||||
"creation": "2024-01-05 15:29:11.144373",
|
||||
"custom_blocks": [],
|
||||
"docstatus": 0,
|
||||
"doctype": "Workspace",
|
||||
"for_user": "",
|
||||
"hide_custom": 0,
|
||||
"icon": "arrow-left",
|
||||
"idx": 0,
|
||||
"indicator_color": "",
|
||||
"is_hidden": 0,
|
||||
"label": "Payables",
|
||||
"links": [
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Invoicing",
|
||||
"link_count": 2,
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Purchase Invoice",
|
||||
"link_count": 0,
|
||||
"link_to": "Purchase Invoice",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Supplier",
|
||||
"link_count": 0,
|
||||
"link_to": "Supplier",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Payments",
|
||||
"link_count": 3,
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Payment Entry",
|
||||
"link_count": 0,
|
||||
"link_to": "Payment Entry",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Journal Entry",
|
||||
"link_count": 0,
|
||||
"link_to": "Journal Entry",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Payment Reconciliation",
|
||||
"link_count": 0,
|
||||
"link_to": "Payment Reconciliation",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Reports",
|
||||
"link_count": 7,
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Accounts Payable",
|
||||
"link_count": 0,
|
||||
"link_to": "Accounts Payable",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Accounts Payable Summary",
|
||||
"link_count": 0,
|
||||
"link_to": "Accounts Payable Summary",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Purchase Register",
|
||||
"link_count": 0,
|
||||
"link_to": "Purchase Register",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Item-wise Purchase Register",
|
||||
"link_count": 0,
|
||||
"link_to": "Item-wise Purchase Register",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Purchase Order Analysis",
|
||||
"link_count": 0,
|
||||
"link_to": "Purchase Order Analysis",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Received Items To Be Billed",
|
||||
"link_count": 0,
|
||||
"link_to": "Received Items To Be Billed",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Supplier Ledger Summary",
|
||||
"link_count": 0,
|
||||
"link_to": "Supplier Ledger Summary",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
}
|
||||
],
|
||||
"modified": "2024-01-18 22:09:46.221549",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payables",
|
||||
"number_cards": [],
|
||||
"owner": "Administrator",
|
||||
"parent_page": "Accounting",
|
||||
"public": 1,
|
||||
"quick_lists": [],
|
||||
"restrict_to_domain": "",
|
||||
"roles": [],
|
||||
"sequence_id": 3.0,
|
||||
"shortcuts": [
|
||||
{
|
||||
"doc_view": "",
|
||||
"label": "Accounts Payable",
|
||||
"link_to": "Accounts Payable",
|
||||
"type": "Report"
|
||||
},
|
||||
{
|
||||
"doc_view": "",
|
||||
"label": "Purchase Invoice",
|
||||
"link_to": "Purchase Invoice",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"doc_view": "",
|
||||
"label": "Journal Entry",
|
||||
"link_to": "Journal Entry",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"doc_view": "",
|
||||
"label": "Payment Entry",
|
||||
"link_to": "Payment Entry",
|
||||
"type": "DocType"
|
||||
}
|
||||
],
|
||||
"title": "Payables"
|
||||
}
|
||||
@@ -1,254 +0,0 @@
|
||||
{
|
||||
"charts": [],
|
||||
"content": "[{\"id\":\"vikWSkNm6_\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Shortcuts</b></span>\",\"col\":12}},{\"id\":\"G984SgVRJN\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Invoice\",\"col\":3}},{\"id\":\"5yHldR0JNk\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"POS Invoice\",\"col\":3}},{\"id\":\"F9f4I1viNr\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Payment Entry\",\"col\":3}},{\"id\":\"1ArNvt9qhz\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Journal Entry\",\"col\":3}},{\"id\":\"4IBBOIxfqW\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Receivable\",\"col\":3}},{\"id\":\"ILlIxJuexy\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Cost Center\",\"col\":3}},{\"id\":\"B7-uxs8tkU\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"tHb3yxthkR\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"id\":\"jLgv00c6ek\",\"type\":\"card\",\"data\":{\"card_name\":\"Invoicing\",\"col\":4}},{\"id\":\"npwfXlz0u1\",\"type\":\"card\",\"data\":{\"card_name\":\"Payments\",\"col\":4}},{\"id\":\"am70C27Jrb\",\"type\":\"card\",\"data\":{\"card_name\":\"Dunning\",\"col\":4}},{\"id\":\"xOHTyD8b5l\",\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}}]",
|
||||
"creation": "2024-01-05 15:29:21.084241",
|
||||
"custom_blocks": [],
|
||||
"docstatus": 0,
|
||||
"doctype": "Workspace",
|
||||
"for_user": "",
|
||||
"hide_custom": 0,
|
||||
"icon": "arrow-right",
|
||||
"idx": 0,
|
||||
"indicator_color": "",
|
||||
"is_hidden": 0,
|
||||
"label": "Receivables",
|
||||
"links": [
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Invoicing",
|
||||
"link_count": 2,
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Sales Invoice",
|
||||
"link_count": 0,
|
||||
"link_to": "Sales Invoice",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Customer",
|
||||
"link_count": 0,
|
||||
"link_to": "Customer",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Payments",
|
||||
"link_count": 4,
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Payment Entry",
|
||||
"link_count": 0,
|
||||
"link_to": "Payment Entry",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Payment Request",
|
||||
"link_count": 0,
|
||||
"link_to": "Payment Request",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Payment Reconciliation",
|
||||
"link_count": 0,
|
||||
"link_to": "Payment Reconciliation",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Payment Gateway Account",
|
||||
"link_count": 0,
|
||||
"link_to": "Payment Gateway Account",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Dunning",
|
||||
"link_count": 2,
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Dunning",
|
||||
"link_count": 0,
|
||||
"link_to": "Dunning",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Dunning Type",
|
||||
"link_count": 0,
|
||||
"link_to": "Dunning Type",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Reports",
|
||||
"link_count": 6,
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
{
|
||||
"dependencies": "Sales Invoice",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Accounts Receivable",
|
||||
"link_count": 0,
|
||||
"link_to": "Accounts Receivable",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Sales Invoice",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Accounts Receivable Summary",
|
||||
"link_count": 0,
|
||||
"link_to": "Accounts Receivable Summary",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Sales Invoice",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Sales Register",
|
||||
"link_count": 0,
|
||||
"link_to": "Sales Register",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Sales Invoice",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Item-wise Sales Register",
|
||||
"link_count": 0,
|
||||
"link_to": "Item-wise Sales Register",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Sales Invoice",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Sales Order Analysis",
|
||||
"link_count": 0,
|
||||
"link_to": "Sales Order Analysis",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Sales Invoice",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Delivered Items To Be Billed",
|
||||
"link_count": 0,
|
||||
"link_to": "Delivered Items To Be Billed",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
}
|
||||
],
|
||||
"modified": "2024-01-18 22:11:51.474477",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Receivables",
|
||||
"number_cards": [],
|
||||
"owner": "Administrator",
|
||||
"parent_page": "Accounting",
|
||||
"public": 1,
|
||||
"quick_lists": [],
|
||||
"restrict_to_domain": "",
|
||||
"roles": [],
|
||||
"sequence_id": 4.0,
|
||||
"shortcuts": [
|
||||
{
|
||||
"color": "Grey",
|
||||
"doc_view": "List",
|
||||
"label": "POS Invoice",
|
||||
"link_to": "POS Invoice",
|
||||
"stats_filter": "[]",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"color": "Grey",
|
||||
"doc_view": "List",
|
||||
"label": "Cost Center",
|
||||
"link_to": "Cost Center",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"doc_view": "",
|
||||
"label": "Sales Invoice",
|
||||
"link_to": "Sales Invoice",
|
||||
"stats_filter": "[]",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"doc_view": "",
|
||||
"label": "Journal Entry",
|
||||
"link_to": "Journal Entry",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"doc_view": "",
|
||||
"label": "Payment Entry",
|
||||
"link_to": "Payment Entry",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"doc_view": "",
|
||||
"label": "Accounts Receivable",
|
||||
"link_to": "Accounts Receivable",
|
||||
"type": "Report"
|
||||
}
|
||||
],
|
||||
"title": "Receivables"
|
||||
}
|
||||
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"app": "erpnext",
|
||||
"charts": [
|
||||
{
|
||||
"chart_name": "Asset Value Analytics",
|
||||
"label": "Asset Value Analytics"
|
||||
}
|
||||
],
|
||||
"content": "[{\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Assets\",\"col\":12}},{\"type\":\"chart\",\"data\":{\"chart_name\":\"Asset Value Analytics\",\"col\":12}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Asset\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Asset Category\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Fixed Asset Register\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Assets\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Maintenance\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}}]",
|
||||
"content": "[{\"id\":\"Q-Cl7bMXDm\",\"type\":\"chart\",\"data\":{\"chart_name\":\"Asset Value Analytics\",\"col\":12}},{\"id\":\"gsSQjvl0Tx\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"xRYRq1sW1O\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"id\":\"Kx2j5N9BKZ\",\"type\":\"card\",\"data\":{\"card_name\":\"Assets\",\"col\":4}},{\"id\":\"jeNsxtLaH3\",\"type\":\"card\",\"data\":{\"card_name\":\"Maintenance\",\"col\":4}},{\"id\":\"EX5e3NvL51\",\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}}]",
|
||||
"creation": "2020-03-02 15:43:27.634865",
|
||||
"custom_blocks": [],
|
||||
"docstatus": 0,
|
||||
@@ -182,6 +183,7 @@
|
||||
"link_to": "Asset Maintenance",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"report_ref_doctype": "Asset Maintenance",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
@@ -193,10 +195,11 @@
|
||||
"link_to": "Asset Activity",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"report_ref_doctype": "Asset Activity",
|
||||
"type": "Link"
|
||||
}
|
||||
],
|
||||
"modified": "2024-01-05 17:40:34.570041",
|
||||
"modified": "2025-12-31 16:22:38.132729",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Assets",
|
||||
"name": "Assets",
|
||||
@@ -208,27 +211,7 @@
|
||||
"restrict_to_domain": "",
|
||||
"roles": [],
|
||||
"sequence_id": 7.0,
|
||||
"shortcuts": [
|
||||
{
|
||||
"label": "Asset",
|
||||
"link_to": "Asset",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"label": "Asset Category",
|
||||
"link_to": "Asset Category",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"label": "Fixed Asset Register",
|
||||
"link_to": "Fixed Asset Register",
|
||||
"type": "Report"
|
||||
},
|
||||
{
|
||||
"label": "Dashboard",
|
||||
"link_to": "Asset",
|
||||
"type": "Dashboard"
|
||||
}
|
||||
],
|
||||
"title": "Assets"
|
||||
}
|
||||
"shortcuts": [],
|
||||
"title": "Assets",
|
||||
"type": "Workspace"
|
||||
}
|
||||
|
||||
@@ -248,6 +248,23 @@ frappe.ui.form.on("Request for Quotation", {
|
||||
}
|
||||
refresh_field("items");
|
||||
},
|
||||
|
||||
email_template(frm) {
|
||||
if (frm.doc.email_template) {
|
||||
frappe.db
|
||||
.get_value("Email Template", frm.doc.email_template, [
|
||||
"use_html",
|
||||
"response",
|
||||
"response_html",
|
||||
])
|
||||
.then((r) => {
|
||||
frm.set_value(
|
||||
"message_for_supplier",
|
||||
r.message.use_html ? r.message.response_html : r.message.response
|
||||
);
|
||||
});
|
||||
}
|
||||
},
|
||||
preview: (frm) => {
|
||||
let dialog = new frappe.ui.Dialog({
|
||||
title: __("Preview Email"),
|
||||
|
||||
@@ -139,8 +139,6 @@
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"fetch_from": "email_template.response",
|
||||
"fetch_if_empty": 1,
|
||||
"fieldname": "message_for_supplier",
|
||||
"fieldtype": "Text Editor",
|
||||
"in_list_view": 1,
|
||||
@@ -322,7 +320,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-03-03 16:48:39.856779",
|
||||
"modified": "2025-12-29 14:44:18.934901",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Request for Quotation",
|
||||
@@ -393,4 +391,4 @@
|
||||
"sort_field": "creation",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ class RequestforQuotation(BuyingController):
|
||||
def before_validate(self):
|
||||
self.set_has_unit_price_items()
|
||||
self.flags.allow_zero_qty = self.has_unit_price_items
|
||||
self.set_message_for_supplier()
|
||||
|
||||
def validate(self):
|
||||
self.validate_duplicate_supplier()
|
||||
@@ -90,6 +91,13 @@ class RequestforQuotation(BuyingController):
|
||||
not row.qty for row in self.get("items") if (row.item_code and not row.qty)
|
||||
)
|
||||
|
||||
def set_message_for_supplier(self):
|
||||
if self.email_template and not self.message_for_supplier:
|
||||
data = frappe.get_value(
|
||||
"Email Template", self.email_template, ["use_html", "response", "response_html"], as_dict=True
|
||||
)
|
||||
self.message_for_supplier = data.response_html if data.use_html else data.response
|
||||
|
||||
def validate_duplicate_supplier(self):
|
||||
supplier_list = [d.supplier for d in self.suppliers]
|
||||
if len(supplier_list) != len(set(supplier_list)):
|
||||
|
||||
@@ -14,6 +14,7 @@ from frappe.model.naming import set_name_by_naming_series, set_name_from_naming_
|
||||
from erpnext.accounts.party import (
|
||||
get_dashboard_info,
|
||||
validate_party_accounts,
|
||||
validate_party_currency_before_merging,
|
||||
)
|
||||
from erpnext.controllers.website_list_for_contact import add_role_for_portal_user
|
||||
from erpnext.utilities.transaction_base import TransactionBase
|
||||
@@ -213,6 +214,10 @@ class Supplier(TransactionBase):
|
||||
|
||||
delete_contact_and_address("Supplier", self.name)
|
||||
|
||||
def before_rename(self, olddn, newdn, merge=False):
|
||||
if merge:
|
||||
validate_party_currency_before_merging("Supplier", olddn, newdn)
|
||||
|
||||
def after_rename(self, olddn, newdn, merge=False):
|
||||
if frappe.defaults.get_global_default("supp_master_name") == "Supplier Name":
|
||||
self.db_set("supplier_name", newdn)
|
||||
|
||||
@@ -45,7 +45,7 @@ class SupplierScorecardCriteria(Document):
|
||||
mylist = re.finditer(regex, test_formula, re.MULTILINE | re.DOTALL)
|
||||
for _dummy1, match in enumerate(mylist):
|
||||
for _dummy2 in range(0, len(match.groups())):
|
||||
test_formula = test_formula.replace("{" + match.group(1) + "}", "0")
|
||||
test_formula = test_formula.replace("{" + match.group(1) + "}", "1")
|
||||
|
||||
try:
|
||||
frappe.safe_eval(test_formula, None, {"max": max, "min": min})
|
||||
|
||||
@@ -17,7 +17,6 @@ class TestSupplierScorecardCriteria(IntegrationTestCase):
|
||||
def test_formula_validate(self):
|
||||
delete_test_scorecards()
|
||||
self.assertRaises(frappe.ValidationError, frappe.get_doc(test_bad_criteria[1]).insert)
|
||||
self.assertRaises(frappe.ValidationError, frappe.get_doc(test_bad_criteria[2]).insert)
|
||||
|
||||
|
||||
def delete_test_scorecards():
|
||||
@@ -68,16 +67,8 @@ test_bad_criteria = [
|
||||
"name": "Fake Criteria 2",
|
||||
"weight": 40.0,
|
||||
"doctype": "Supplier Scorecard Criteria",
|
||||
"formula": "(({cost_of_on_time_shipments} / {tot_cost_shipments}))* 100", # Force 0 divided by 0
|
||||
"formula": "(({cost_of_on_time_shipments} {cost_of_on_time_shipments} / {tot_cost_shipments}))* 100", # Two variables beside eachother
|
||||
"criteria_name": "Fake Criteria 2",
|
||||
"max_score": 100.0,
|
||||
},
|
||||
{
|
||||
"name": "Fake Criteria 3",
|
||||
"weight": 40.0,
|
||||
"doctype": "Supplier Scorecard Criteria",
|
||||
"formula": "(({cost_of_on_time_shipments} {cost_of_on_time_shipments} / {tot_cost_shipments}))* 100", # Two variables beside eachother
|
||||
"criteria_name": "Fake Criteria 3",
|
||||
"max_score": 100.0,
|
||||
},
|
||||
]
|
||||
|
||||
@@ -188,7 +188,7 @@ def find_variant(template, args, variant_item_code=None):
|
||||
|
||||
for attribute, value in args.items():
|
||||
for row in variant.attributes:
|
||||
if row.attribute == attribute and row.attribute_value == cstr(value):
|
||||
if row.attribute == _(attribute) and row.attribute_value == cstr(value):
|
||||
# this row matches
|
||||
match_count += 1
|
||||
break
|
||||
@@ -209,7 +209,7 @@ def create_variant(item, args, use_template_image=False):
|
||||
variant_attributes = []
|
||||
|
||||
for d in template.attributes:
|
||||
variant_attributes.append({"attribute": d.attribute, "attribute_value": args.get(d.attribute)})
|
||||
variant_attributes.append({"attribute": d.attribute, "attribute_value": args.get(_(d.attribute))})
|
||||
|
||||
variant.set("attributes", variant_attributes)
|
||||
copy_attributes_to_variant(template, variant)
|
||||
|
||||
@@ -1022,10 +1022,19 @@ class SellingController(StockController):
|
||||
|
||||
|
||||
def set_default_income_account_for_item(obj):
|
||||
for d in obj.get("items"):
|
||||
if d.item_code:
|
||||
if getattr(d, "income_account", None):
|
||||
set_item_default(d.item_code, obj.company, "income_account", d.income_account)
|
||||
"""Set income account as default for items in the transaction.
|
||||
|
||||
Updates the item default income account for each item in the transaction
|
||||
if it differs from the company's default income account.
|
||||
|
||||
Args:
|
||||
obj: Transaction document containing items table with income_account field
|
||||
"""
|
||||
company_default = frappe.get_cached_value("Company", obj.company, "default_income_account")
|
||||
for d in obj.get("items", default=[]):
|
||||
income_account = getattr(d, "income_account", None)
|
||||
if d.item_code and income_account and income_account != company_default:
|
||||
set_item_default(d.item_code, obj.company, "income_account", income_account)
|
||||
|
||||
|
||||
def get_serial_and_batch_bundle(child, parent, delivery_note_child=None):
|
||||
|
||||
@@ -184,6 +184,9 @@ class StatusUpdater(Document):
|
||||
Installation Note: Update Installed Qty, Update Percent Qty and Validate over installation
|
||||
"""
|
||||
|
||||
def on_discard(self):
|
||||
self.db_set("status", "Cancelled")
|
||||
|
||||
def update_prevdoc_status(self):
|
||||
self.update_qty()
|
||||
self.validate_qty()
|
||||
|
||||
@@ -1401,6 +1401,7 @@ def make_rm_stock_entry(
|
||||
|
||||
stock_entry.set_stock_entry_type()
|
||||
|
||||
over_transfer_allowance = frappe.get_single_value("Buying Settings", "over_transfer_allowance")
|
||||
for fg_item_code in fg_item_code_list:
|
||||
for rm_item in rm_items:
|
||||
if (
|
||||
@@ -1408,14 +1409,27 @@ def make_rm_stock_entry(
|
||||
or rm_item.get("item_code") == fg_item_code
|
||||
):
|
||||
rm_item_code = rm_item.get("rm_item_code")
|
||||
qty = rm_item.get("qty") or max(
|
||||
rm_item.get("required_qty") - rm_item.get("total_supplied_qty"), 0
|
||||
)
|
||||
if qty <= 0 and rm_item.get("total_supplied_qty"):
|
||||
per_transferred = (
|
||||
flt(
|
||||
rm_item.get("total_supplied_qty") / rm_item.get("required_qty"),
|
||||
frappe.db.get_default("float_precision"),
|
||||
)
|
||||
* 100
|
||||
)
|
||||
if per_transferred >= 100 + over_transfer_allowance:
|
||||
continue
|
||||
|
||||
items_dict = {
|
||||
rm_item_code: {
|
||||
rm_detail_field: rm_item.get("name"),
|
||||
"item_name": rm_item.get("item_name")
|
||||
or item_wh.get(rm_item_code, {}).get("item_name", ""),
|
||||
"description": item_wh.get(rm_item_code, {}).get("description", ""),
|
||||
"qty": rm_item.get("qty")
|
||||
or max(rm_item.get("required_qty") - rm_item.get("total_supplied_qty"), 0),
|
||||
"qty": qty,
|
||||
"from_warehouse": rm_item.get("warehouse")
|
||||
or rm_item.get("reserve_warehouse"),
|
||||
"to_warehouse": subcontract_order.supplier_warehouse,
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
"in_standard_filter": 1,
|
||||
"label": "Status",
|
||||
"no_copy": 1,
|
||||
"options": "Unsigned\nActive\nInactive"
|
||||
"options": "Unsigned\nActive\nInactive\nCancelled"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
@@ -257,11 +257,11 @@
|
||||
"grid_page_length": 50,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-06-19 17:48:45.049007",
|
||||
"modified": "2025-12-24 21:33:51.240497",
|
||||
"modified_by": "Administrator",
|
||||
"module": "CRM",
|
||||
"name": "Contract",
|
||||
"naming_rule": "Expression (old style)",
|
||||
"naming_rule": "Expression",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
|
||||
@@ -43,7 +43,7 @@ class Contract(Document):
|
||||
signed_on: DF.Datetime | None
|
||||
signee: DF.Data | None
|
||||
start_date: DF.Date | None
|
||||
status: DF.Literal["Unsigned", "Active", "Inactive"]
|
||||
status: DF.Literal["Unsigned", "Active", "Inactive", "Cancelled"]
|
||||
# end: auto-generated types
|
||||
|
||||
def validate(self):
|
||||
@@ -61,6 +61,9 @@ class Contract(Document):
|
||||
def before_submit(self):
|
||||
self.signed_by_company = frappe.session.user
|
||||
|
||||
def on_discard(self):
|
||||
self.db_set("status", "Cancelled")
|
||||
|
||||
def before_update_after_submit(self):
|
||||
self.update_contract_status()
|
||||
self.update_fulfilment_status()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"app": "erpnext",
|
||||
"creation": "2025-11-17 13:19:04.309749",
|
||||
"creation": "2025-11-17 20:55:11.854086",
|
||||
"docstatus": 0,
|
||||
"doctype": "Desktop Icon",
|
||||
"hidden": 0,
|
||||
@@ -10,7 +10,7 @@
|
||||
"label": "Accounting",
|
||||
"link_to": "Accounting",
|
||||
"link_type": "Workspace",
|
||||
"modified": "2025-11-17 13:33:35.788242",
|
||||
"modified": "2025-12-31 16:06:04.678577",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Accounting",
|
||||
"owner": "Administrator",
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
{
|
||||
"app": "erpnext",
|
||||
"creation": "2025-11-17 13:19:04.299276",
|
||||
"creation": "2025-11-17 20:55:11.845676",
|
||||
"docstatus": 0,
|
||||
"doctype": "Desktop Icon",
|
||||
"hidden": 0,
|
||||
"icon": "assets",
|
||||
"icon_type": "Link",
|
||||
"idx": 8,
|
||||
"idx": 1,
|
||||
"label": "Assets",
|
||||
"link_to": "Assets",
|
||||
"link_type": "Workspace",
|
||||
"logo_url": "/assets/erpnext/desktop_icons/asset.svg",
|
||||
"modified": "2025-11-17 17:41:41.635533",
|
||||
"modified": "2025-12-22 13:07:02.129228",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Assets",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "",
|
||||
"parent_icon": "ERPNext",
|
||||
"roles": [],
|
||||
"standard": 1
|
||||
}
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
"icon_type": "Link",
|
||||
"idx": 5,
|
||||
"label": "Banking",
|
||||
"link_to": "Bank Reconciliation Tool",
|
||||
"link_to": "Bank Clearance",
|
||||
"link_type": "DocType",
|
||||
"modified": "2025-11-19 15:57:20.139306",
|
||||
"modified": "2025-12-22 16:53:37.020794",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Banking",
|
||||
"owner": "Administrator",
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
{
|
||||
"app": "erpnext",
|
||||
"creation": "2025-11-17 13:19:04.327790",
|
||||
"creation": "2025-11-17 20:55:11.868134",
|
||||
"docstatus": 0,
|
||||
"doctype": "Desktop Icon",
|
||||
"hidden": 0,
|
||||
"icon": "buying",
|
||||
"icon_type": "Link",
|
||||
"idx": 3,
|
||||
"idx": 1,
|
||||
"label": "Buying",
|
||||
"link_to": "Buying",
|
||||
"link_type": "Workspace",
|
||||
"logo_url": "/assets/erpnext/desktop_icons/buying.svg",
|
||||
"modified": "2025-11-17 17:38:19.203107",
|
||||
"modified": "2025-12-22 13:06:55.022406",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Buying",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "",
|
||||
"parent_icon": "ERPNext",
|
||||
"roles": [],
|
||||
"standard": 1
|
||||
}
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
{
|
||||
"app": "erpnext",
|
||||
"creation": "2025-11-17 13:19:04.340610",
|
||||
"creation": "2025-11-17 20:55:11.876996",
|
||||
"docstatus": 0,
|
||||
"doctype": "Desktop Icon",
|
||||
"hidden": 0,
|
||||
"icon": "crm",
|
||||
"icon_type": "Link",
|
||||
"idx": 7,
|
||||
"idx": 1,
|
||||
"label": "CRM",
|
||||
"link_to": "CRM",
|
||||
"link_type": "Workspace",
|
||||
"logo_url": "/assets/erpnext/desktop_icons/crm.svg",
|
||||
"modified": "2025-11-17 19:39:59.734778",
|
||||
"modified": "2025-12-22 13:06:47.900639",
|
||||
"modified_by": "Administrator",
|
||||
"name": "CRM",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "",
|
||||
"parent_icon": "ERPNext",
|
||||
"roles": [],
|
||||
"standard": 1
|
||||
}
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
{
|
||||
"app": "erpnext",
|
||||
"creation": "2025-11-05 12:11:24.655043",
|
||||
"creation": "2025-11-17 20:55:11.772622",
|
||||
"docstatus": 0,
|
||||
"doctype": "Desktop Icon",
|
||||
"hidden": 0,
|
||||
"icon": "file",
|
||||
"icon_type": "Link",
|
||||
"idx": 7,
|
||||
"idx": 0,
|
||||
"label": "Financial Reports",
|
||||
"link_to": "Financial Reports",
|
||||
"link_type": "Workspace",
|
||||
"modified": "2025-11-17 13:34:48.074533",
|
||||
"modified": "2025-12-31 16:07:27.060176",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Financial Reports",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "Accounts",
|
||||
"roles": [],
|
||||
"sidebar": "",
|
||||
"standard": 1
|
||||
}
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
{
|
||||
"app": "erpnext",
|
||||
"creation": "2025-11-17 13:19:04.269805",
|
||||
"creation": "2025-11-17 20:55:11.824443",
|
||||
"docstatus": 0,
|
||||
"doctype": "Desktop Icon",
|
||||
"hidden": 0,
|
||||
"icon": "organization",
|
||||
"icon_type": "Link",
|
||||
"idx": 5,
|
||||
"idx": 1,
|
||||
"label": "Manufacturing",
|
||||
"link_to": "Manufacturing",
|
||||
"link_type": "Workspace",
|
||||
"logo_url": "/assets/erpnext/desktop_icons/manufacturing.svg",
|
||||
"modified": "2025-11-17 17:40:14.207766",
|
||||
"modified": "2025-12-22 13:07:15.536476",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Manufacturing",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "",
|
||||
"parent_icon": "ERPNext",
|
||||
"roles": [],
|
||||
"standard": 1
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"app": "erpnext",
|
||||
"creation": "2025-11-12 15:15:15.824801",
|
||||
"docstatus": 0,
|
||||
"doctype": "Desktop Icon",
|
||||
"hidden": 0,
|
||||
"icon": "panel-top-open",
|
||||
"icon_type": "Link",
|
||||
"idx": 2,
|
||||
"label": "Opening & Closing",
|
||||
"link_to": "Period Closing Voucher",
|
||||
"link_type": "DocType",
|
||||
"modified": "2025-11-19 15:59:14.805915",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Opening & Closing",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "Accounts",
|
||||
"roles": [],
|
||||
"standard": 1
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"app": "erpnext",
|
||||
"creation": "2025-11-17 13:19:04.255041",
|
||||
"docstatus": 0,
|
||||
"doctype": "Desktop Icon",
|
||||
"hidden": 0,
|
||||
"icon": "arrow-left",
|
||||
"icon_type": "Link",
|
||||
"idx": 0,
|
||||
"label": "Payables",
|
||||
"link_to": "Payables",
|
||||
"link_type": "Workspace",
|
||||
"modified": "2025-11-17 15:53:14.737052",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Payables",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "Accounts",
|
||||
"roles": [],
|
||||
"standard": 1
|
||||
}
|
||||
@@ -1,21 +1,20 @@
|
||||
{
|
||||
"app": "erpnext",
|
||||
"creation": "2025-11-17 13:19:04.293376",
|
||||
"creation": "2025-11-17 20:55:11.841426",
|
||||
"docstatus": 0,
|
||||
"doctype": "Desktop Icon",
|
||||
"hidden": 0,
|
||||
"icon": "project",
|
||||
"icon_type": "Link",
|
||||
"idx": 9,
|
||||
"idx": 1,
|
||||
"label": "Projects",
|
||||
"link_to": "Projects",
|
||||
"link_type": "Workspace",
|
||||
"logo_url": "/assets/erpnext/desktop_icons/projects.svg",
|
||||
"modified": "2025-11-17 17:42:29.470661",
|
||||
"modified": "2025-12-22 13:07:07.027692",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Projects",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "",
|
||||
"parent_icon": "ERPNext",
|
||||
"roles": [],
|
||||
"standard": 1
|
||||
}
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
{
|
||||
"app": "erpnext",
|
||||
"creation": "2025-11-17 13:19:04.281193",
|
||||
"creation": "2025-11-17 20:55:11.828716",
|
||||
"docstatus": 0,
|
||||
"doctype": "Desktop Icon",
|
||||
"hidden": 0,
|
||||
"icon": "quality",
|
||||
"icon_type": "Link",
|
||||
"idx": 9,
|
||||
"idx": 1,
|
||||
"label": "Quality",
|
||||
"link_to": "Quality",
|
||||
"link_type": "Workspace",
|
||||
"logo_url": "/assets/erpnext/desktop_icons/quality.svg",
|
||||
"modified": "2025-11-17 17:42:48.371889",
|
||||
"modified": "2025-12-22 13:07:13.506034",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Quality",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "",
|
||||
"parent_icon": "ERPNext",
|
||||
"roles": [],
|
||||
"standard": 1
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"app": "erpnext",
|
||||
"creation": "2025-11-17 13:19:04.249828",
|
||||
"docstatus": 0,
|
||||
"doctype": "Desktop Icon",
|
||||
"hidden": 0,
|
||||
"icon": "arrow-right",
|
||||
"icon_type": "Link",
|
||||
"idx": 0,
|
||||
"label": "Receivables",
|
||||
"link_to": "Receivables",
|
||||
"link_type": "Workspace",
|
||||
"modified": "2025-11-17 15:53:24.958812",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Receivables",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "Accounts",
|
||||
"roles": [],
|
||||
"standard": 1
|
||||
}
|
||||
@@ -1,21 +1,20 @@
|
||||
{
|
||||
"app": "erpnext",
|
||||
"creation": "2025-11-17 13:19:04.335051",
|
||||
"creation": "2025-11-17 20:55:11.872574",
|
||||
"docstatus": 0,
|
||||
"doctype": "Desktop Icon",
|
||||
"hidden": 0,
|
||||
"icon": "sell",
|
||||
"icon_type": "Link",
|
||||
"idx": 2,
|
||||
"idx": 1,
|
||||
"label": "Selling",
|
||||
"link_to": "Selling",
|
||||
"link_type": "Workspace",
|
||||
"logo_url": "/assets/erpnext/desktop_icons/selling.svg",
|
||||
"modified": "2025-11-17 17:37:59.847865",
|
||||
"modified": "2025-12-22 13:06:51.346923",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Selling",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "",
|
||||
"parent_icon": "ERPNext",
|
||||
"roles": [],
|
||||
"standard": 1
|
||||
}
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
{
|
||||
"app": "erpnext",
|
||||
"creation": "2025-11-17 13:19:04.304517",
|
||||
"creation": "2025-11-17 20:55:11.849904",
|
||||
"docstatus": 0,
|
||||
"doctype": "Desktop Icon",
|
||||
"hidden": 0,
|
||||
"icon": "stock",
|
||||
"icon_type": "Link",
|
||||
"idx": 4,
|
||||
"idx": 1,
|
||||
"label": "Stock",
|
||||
"link_to": "Stock",
|
||||
"link_type": "Workspace",
|
||||
"logo_url": "/assets/erpnext/desktop_icons/stock.svg",
|
||||
"modified": "2025-11-17 17:38:40.957627",
|
||||
"modified": "2025-12-22 13:07:00.130510",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Stock",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "",
|
||||
"parent_icon": "ERPNext",
|
||||
"roles": [],
|
||||
"standard": 1
|
||||
}
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
"hidden": 0,
|
||||
"icon": "monitor-check",
|
||||
"icon_type": "Link",
|
||||
"idx": 6,
|
||||
"idx": 99,
|
||||
"label": "Subscription",
|
||||
"link_to": "Subscription",
|
||||
"link_type": "DocType",
|
||||
"modified": "2025-11-19 16:02:32.686833",
|
||||
"modified": "2025-12-22 17:04:08.800434",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Subscription",
|
||||
"owner": "Administrator",
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
{
|
||||
"app": "erpnext",
|
||||
"creation": "2025-11-17 13:19:04.288298",
|
||||
"creation": "2025-11-17 20:55:11.837227",
|
||||
"docstatus": 0,
|
||||
"doctype": "Desktop Icon",
|
||||
"hidden": 0,
|
||||
"icon": "support",
|
||||
"icon_type": "Link",
|
||||
"idx": 10,
|
||||
"idx": 1,
|
||||
"label": "Support",
|
||||
"link_to": "Support",
|
||||
"link_type": "Workspace",
|
||||
"logo_url": "/assets/erpnext/desktop_icons/support.svg",
|
||||
"modified": "2025-11-17 17:43:09.335445",
|
||||
"modified": "2025-12-22 13:07:11.812983",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Support",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "",
|
||||
"parent_icon": "ERPNext",
|
||||
"roles": [],
|
||||
"standard": 1
|
||||
}
|
||||
|
||||
@@ -8,13 +8,14 @@
|
||||
"icon_type": "Link",
|
||||
"idx": 3,
|
||||
"label": "Taxes",
|
||||
"link_to": "Item Tax Template",
|
||||
"link_to": "Sales Taxes and Charges Template",
|
||||
"link_type": "DocType",
|
||||
"modified": "2025-11-19 15:58:21.226664",
|
||||
"modified": "2025-12-31 16:59:14.978584",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Taxes",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "Accounts",
|
||||
"roles": [],
|
||||
"sidebar": "",
|
||||
"standard": 1
|
||||
}
|
||||
|
||||
1450
erpnext/locale/ar.po
1450
erpnext/locale/ar.po
File diff suppressed because it is too large
Load Diff
1452
erpnext/locale/bs.po
1452
erpnext/locale/bs.po
File diff suppressed because it is too large
Load Diff
1450
erpnext/locale/cs.po
1450
erpnext/locale/cs.po
File diff suppressed because it is too large
Load Diff
1450
erpnext/locale/da.po
1450
erpnext/locale/da.po
File diff suppressed because it is too large
Load Diff
1450
erpnext/locale/de.po
1450
erpnext/locale/de.po
File diff suppressed because it is too large
Load Diff
1452
erpnext/locale/eo.po
1452
erpnext/locale/eo.po
File diff suppressed because it is too large
Load Diff
1450
erpnext/locale/es.po
1450
erpnext/locale/es.po
File diff suppressed because it is too large
Load Diff
1504
erpnext/locale/fa.po
1504
erpnext/locale/fa.po
File diff suppressed because it is too large
Load Diff
1450
erpnext/locale/fr.po
1450
erpnext/locale/fr.po
File diff suppressed because it is too large
Load Diff
1452
erpnext/locale/hr.po
1452
erpnext/locale/hr.po
File diff suppressed because it is too large
Load Diff
1450
erpnext/locale/hu.po
1450
erpnext/locale/hu.po
File diff suppressed because it is too large
Load Diff
1450
erpnext/locale/id.po
1450
erpnext/locale/id.po
File diff suppressed because it is too large
Load Diff
1450
erpnext/locale/it.po
1450
erpnext/locale/it.po
File diff suppressed because it is too large
Load Diff
1450
erpnext/locale/my.po
1450
erpnext/locale/my.po
File diff suppressed because it is too large
Load Diff
1450
erpnext/locale/nb.po
1450
erpnext/locale/nb.po
File diff suppressed because it is too large
Load Diff
1450
erpnext/locale/nl.po
1450
erpnext/locale/nl.po
File diff suppressed because it is too large
Load Diff
1450
erpnext/locale/pl.po
1450
erpnext/locale/pl.po
File diff suppressed because it is too large
Load Diff
1450
erpnext/locale/pt.po
1450
erpnext/locale/pt.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1452
erpnext/locale/ru.po
1452
erpnext/locale/ru.po
File diff suppressed because it is too large
Load Diff
1450
erpnext/locale/sl.po
1450
erpnext/locale/sl.po
File diff suppressed because it is too large
Load Diff
1452
erpnext/locale/sr.po
1452
erpnext/locale/sr.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1452
erpnext/locale/sv.po
1452
erpnext/locale/sv.po
File diff suppressed because it is too large
Load Diff
1450
erpnext/locale/ta.po
1450
erpnext/locale/ta.po
File diff suppressed because it is too large
Load Diff
1450
erpnext/locale/th.po
1450
erpnext/locale/th.po
File diff suppressed because it is too large
Load Diff
1450
erpnext/locale/tr.po
1450
erpnext/locale/tr.po
File diff suppressed because it is too large
Load Diff
1450
erpnext/locale/vi.po
1450
erpnext/locale/vi.po
File diff suppressed because it is too large
Load Diff
1450
erpnext/locale/zh.po
1450
erpnext/locale/zh.po
File diff suppressed because it is too large
Load Diff
@@ -19,6 +19,20 @@ frappe.ui.form.on("BOM", {
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query("operation", "items", function () {
|
||||
if (!frm.doc.operations?.length) {
|
||||
frappe.throw(__("Please add Operations first."));
|
||||
}
|
||||
|
||||
let operations = frm.doc.operations.map((d) => d.operation);
|
||||
|
||||
return {
|
||||
filters: {
|
||||
name: ["in", operations],
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query("bom_no", "operations", function (doc, cdt, cdn) {
|
||||
let row = locals[cdt][cdn];
|
||||
return {
|
||||
|
||||
@@ -1036,10 +1036,14 @@ class BOM(WebsiteGenerator):
|
||||
return erpnext.get_company_currency(self.company)
|
||||
|
||||
def add_to_cur_exploded_items(self, args):
|
||||
if self.cur_exploded_items.get(args.item_code):
|
||||
self.cur_exploded_items[args.item_code]["stock_qty"] += args.stock_qty
|
||||
key = args.item_code
|
||||
if args.operation:
|
||||
key = (args.item_code, args.operation)
|
||||
|
||||
if self.cur_exploded_items.get(key):
|
||||
self.cur_exploded_items[key]["stock_qty"] += args.stock_qty
|
||||
else:
|
||||
self.cur_exploded_items[args.item_code] = args
|
||||
self.cur_exploded_items[key] = args
|
||||
|
||||
def get_child_exploded_items(self, bom_no, stock_qty, operation=None):
|
||||
"""Add all items from Flat BOM of child BOM"""
|
||||
@@ -1275,7 +1279,7 @@ def get_bom_items_as_dict(
|
||||
):
|
||||
item_dict = {}
|
||||
|
||||
group_by_cond = "group by item_code, stock_uom"
|
||||
group_by_cond = "group by item_code, stock_uom, operation"
|
||||
if frappe.get_cached_value("BOM", bom, "track_semi_finished_goods"):
|
||||
fetch_exploded = 0
|
||||
group_by_cond = "group by item_code, operation_row_id, stock_uom"
|
||||
@@ -1360,6 +1364,9 @@ def get_bom_items_as_dict(
|
||||
if item.operation_row_id:
|
||||
key = (item.item_code, item.operation_row_id)
|
||||
|
||||
if item.operation:
|
||||
key = (item.item_code, item.operation)
|
||||
|
||||
if item.get("is_phantom_item"):
|
||||
data = get_bom_items_as_dict(
|
||||
item.get("bom_no"),
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from collections import OrderedDict
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe import _, bold
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import cint, flt, sbool
|
||||
from pypika.terms import ValueWrapper
|
||||
@@ -78,6 +78,29 @@ class BOMCreator(Document):
|
||||
|
||||
def validate(self):
|
||||
self.validate_items()
|
||||
self.validate_duplicate_item()
|
||||
|
||||
def validate_duplicate_item(self):
|
||||
# If same items added multiple times under same parent, raise error
|
||||
item_map = {}
|
||||
for row in self.items:
|
||||
if not row.fg_reference_id:
|
||||
continue
|
||||
|
||||
key = (row.item_code, row.fg_reference_id)
|
||||
if key in item_map:
|
||||
parent_item_code = next(
|
||||
item.item_code for item in self.items if item.name == row.fg_reference_id
|
||||
)
|
||||
|
||||
frappe.throw(
|
||||
_(
|
||||
"Item {0} added multiple times under the same parent item {1} at rows {2} and {3}"
|
||||
).format(bold(row.item_code), bold(parent_item_code), item_map[key], row.idx),
|
||||
title=_("Duplicate Item Under Same Parent"),
|
||||
)
|
||||
else:
|
||||
item_map[key] = row.idx
|
||||
|
||||
def validate_items(self):
|
||||
for row in self.items:
|
||||
@@ -182,7 +205,7 @@ class BOMCreator(Document):
|
||||
else:
|
||||
row.rate = flt(self.get_raw_material_cost(row.item_code) * row.conversion_factor)
|
||||
|
||||
row.amount = flt(row.rate * row.qty)
|
||||
row.amount = flt(row.rate) * flt(row.qty)
|
||||
amount += flt(row.amount)
|
||||
|
||||
return amount
|
||||
|
||||
@@ -147,8 +147,10 @@
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.parenttype == \"Routing\"",
|
||||
"description": "If you want to run operations in parallel, keep the same sequence ID for them.",
|
||||
"fieldname": "sequence_id",
|
||||
"fieldtype": "Int",
|
||||
"in_list_view": 1,
|
||||
"label": "Sequence ID"
|
||||
},
|
||||
{
|
||||
@@ -295,7 +297,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-08-12 19:27:20.682797",
|
||||
"modified": "2026-01-01 17:15:59.806874",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "BOM Operation",
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"label": "Status",
|
||||
"options": "Queued\nIn Progress\nCompleted\nFailed"
|
||||
"options": "Queued\nIn Progress\nCompleted\nFailed\nCancelled"
|
||||
},
|
||||
{
|
||||
"fieldname": "amended_from",
|
||||
@@ -98,11 +98,11 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:06:41.658172",
|
||||
"modified": "2025-12-24 12:27:06.478893",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "BOM Update Log",
|
||||
"naming_rule": "Expression (old style)",
|
||||
"naming_rule": "Expression",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
@@ -131,8 +131,9 @@
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"row_format": "Dynamic",
|
||||
"sort_field": "creation",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ class BOMUpdateLog(Document):
|
||||
error_log: DF.Link | None
|
||||
new_bom: DF.Link | None
|
||||
processed_boms: DF.LongText | None
|
||||
status: DF.Literal["Queued", "In Progress", "Completed", "Failed"]
|
||||
status: DF.Literal["Queued", "In Progress", "Completed", "Failed", "Cancelled"]
|
||||
update_type: DF.Literal["Replace BOM", "Update Cost"]
|
||||
# end: auto-generated types
|
||||
|
||||
@@ -64,6 +64,9 @@ class BOMUpdateLog(Document):
|
||||
|
||||
self.status = "Queued"
|
||||
|
||||
def on_discard(self):
|
||||
self.db_set("status", "Cancelled")
|
||||
|
||||
def validate_boms_are_specified(self):
|
||||
if self.update_type == "Replace BOM" and not (self.current_bom and self.new_bom):
|
||||
frappe.throw(
|
||||
|
||||
@@ -405,7 +405,8 @@
|
||||
"fieldname": "employee",
|
||||
"fieldtype": "Table MultiSelect",
|
||||
"label": "Employee",
|
||||
"options": "Job Card Time Log"
|
||||
"options": "Job Card Time Log",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "serial_no",
|
||||
@@ -625,7 +626,7 @@
|
||||
"grid_page_length": 50,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-08-04 15:47:54.514290",
|
||||
"modified": "2025-12-22 14:20:07.817118",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Job Card",
|
||||
|
||||
@@ -144,6 +144,9 @@ class JobCard(Document):
|
||||
self.set_onload("work_order_closed", self.is_work_order_closed())
|
||||
self.set_onload("has_stock_entry", self.has_stock_entry())
|
||||
|
||||
def on_discard(self):
|
||||
self.db_set("status", "Cancelled")
|
||||
|
||||
def has_stock_entry(self):
|
||||
return frappe.db.exists("Stock Entry", {"job_card": self.name, "docstatus": ["!=", 2]})
|
||||
|
||||
@@ -162,6 +165,7 @@ class JobCard(Document):
|
||||
self.set_total_completed_qty_from_sub_operations()
|
||||
|
||||
self.validate_work_order()
|
||||
self.set_employees()
|
||||
|
||||
def on_update(self):
|
||||
self.validate_job_card_qty()
|
||||
@@ -631,11 +635,6 @@ class JobCard(Document):
|
||||
row = self.append("time_logs", args)
|
||||
row.db_update()
|
||||
|
||||
def set_employees(self, employees):
|
||||
for name in employees:
|
||||
self.append("employee", {"employee": name.get("employee"), "completed_qty": 0.0})
|
||||
self.save()
|
||||
|
||||
def update_sub_operation_status(self):
|
||||
if not self.sub_operations:
|
||||
return
|
||||
@@ -1230,6 +1229,12 @@ class JobCard(Document):
|
||||
if self.is_work_order_closed():
|
||||
frappe.throw(_("You can't make any changes to Job Card since Work Order is closed."))
|
||||
|
||||
def set_employees(self):
|
||||
self.employee = []
|
||||
for item in self.time_logs:
|
||||
if not any(d.employee == item.employee for d in self.employee):
|
||||
self.append("employee", {"employee": item.employee, "completed_qty": 0.0})
|
||||
|
||||
def is_work_order_closed(self):
|
||||
if self.work_order:
|
||||
status = frappe.get_value("Work Order", self.work_order)
|
||||
@@ -1285,10 +1290,8 @@ class JobCard(Document):
|
||||
|
||||
self.set_status(update_status=update_status)
|
||||
|
||||
if not self.employee and kwargs.employees:
|
||||
self.set_employees(kwargs.employees)
|
||||
|
||||
self.validate_time_logs(save=True)
|
||||
self.save()
|
||||
|
||||
def update_workstation_status(self):
|
||||
status_map = {
|
||||
@@ -1329,17 +1332,15 @@ class JobCard(Document):
|
||||
kwargs = frappe._dict(kwargs)
|
||||
|
||||
if kwargs.end_time:
|
||||
if kwargs.for_quantity:
|
||||
self.for_quantity = kwargs.for_quantity
|
||||
|
||||
self.add_time_logs(
|
||||
to_time=kwargs.end_time,
|
||||
completed_qty=kwargs.qty,
|
||||
employees=self.employee,
|
||||
sub_operation=kwargs.get("sub_operation"),
|
||||
)
|
||||
|
||||
if kwargs.for_quantity:
|
||||
self.for_quantity = kwargs.for_quantity
|
||||
|
||||
self.save()
|
||||
else:
|
||||
self.add_time_logs(completed_qty=kwargs.qty, employees=self.employee)
|
||||
self.save()
|
||||
|
||||
@@ -119,6 +119,9 @@ class ProductionPlan(Document):
|
||||
frappe.db.get_single_value("Stock Settings", "enable_stock_reservation"),
|
||||
)
|
||||
|
||||
def on_discard(self):
|
||||
self.db_set("status", "Cancelled")
|
||||
|
||||
def validate(self):
|
||||
self.set_pending_qty_in_row_without_reference()
|
||||
self.calculate_total_planned_qty()
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Status",
|
||||
"options": "Planned\nMPS Generated",
|
||||
"options": "Planned\nMPS Generated\nCancelled",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
@@ -166,7 +166,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-11-13 16:33:49.682684",
|
||||
"modified": "2025-12-24 11:40:44.263700",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Sales Forecast",
|
||||
|
||||
@@ -33,9 +33,12 @@ class SalesForecast(Document):
|
||||
parent_warehouse: DF.Link
|
||||
posting_date: DF.Date | None
|
||||
selected_items: DF.TableMultiSelect[SalesForecastItem]
|
||||
status: DF.Literal["Planned", "MPS Generated"]
|
||||
status: DF.Literal["Planned", "MPS Generated", "Cancelled"]
|
||||
# end: auto-generated types
|
||||
|
||||
def on_discard(self):
|
||||
self.db_set("status", "Cancelled")
|
||||
|
||||
def validate(self):
|
||||
self.validate_demand_qty()
|
||||
|
||||
|
||||
@@ -180,6 +180,9 @@ class WorkOrder(Document):
|
||||
|
||||
return False
|
||||
|
||||
def on_discard(self):
|
||||
self.db_set("status", "Cancelled")
|
||||
|
||||
def validate(self):
|
||||
self.validate_production_item()
|
||||
if self.bom_no:
|
||||
|
||||
@@ -454,4 +454,5 @@ erpnext.patches.v16_0.populate_budget_distribution_total
|
||||
erpnext.patches.v16_0.set_mr_picked_qty
|
||||
erpnext.patches.v16_0.update_tax_withholding_field_in_payment_entry
|
||||
erpnext.patches.v16_0.migrate_tax_withholding_data
|
||||
|
||||
erpnext.patches.v16_0.update_corrected_cancelled_status
|
||||
erpnext.patches.v16_0.fix_barcode_typo
|
||||
|
||||
7
erpnext/patches/v16_0/fix_barcode_typo.py
Normal file
7
erpnext/patches/v16_0/fix_barcode_typo.py
Normal file
@@ -0,0 +1,7 @@
|
||||
import frappe
|
||||
|
||||
|
||||
def execute():
|
||||
frappe.qb.update("Item Barcode").set("barcode_type", "EAN-13").where(
|
||||
frappe.qb.Field("barcode_type") == "EAN-12"
|
||||
).run()
|
||||
@@ -1,6 +1,10 @@
|
||||
import frappe
|
||||
from frappe.utils import add_months, flt, get_first_day, get_last_day
|
||||
|
||||
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
||||
get_accounting_dimensions,
|
||||
)
|
||||
|
||||
|
||||
def execute():
|
||||
remove_old_property_setter()
|
||||
@@ -79,6 +83,10 @@ def create_new_budget_from_row(budget_doc, fiscal_year, account_row, percentage_
|
||||
for field in core_fields:
|
||||
new_budget.set(field, budget_doc.get(field))
|
||||
|
||||
for fieldname in get_accounting_dimensions():
|
||||
if budget_doc.get(fieldname):
|
||||
new_budget.set(fieldname, budget_doc.get(fieldname))
|
||||
|
||||
new_budget.from_fiscal_year = fiscal_year.name
|
||||
new_budget.to_fiscal_year = fiscal_year.name
|
||||
new_budget.budget_start_date = fiscal_year.year_start_date
|
||||
|
||||
16
erpnext/patches/v16_0/update_corrected_cancelled_status.py
Normal file
16
erpnext/patches/v16_0/update_corrected_cancelled_status.py
Normal file
@@ -0,0 +1,16 @@
|
||||
import frappe
|
||||
|
||||
|
||||
def execute():
|
||||
stock_closing_entry = frappe.qb.DocType("Stock Closing Entry")
|
||||
call_log = frappe.qb.DocType("Call Log")
|
||||
|
||||
# updating stock closing entry status to cancelled from canceled
|
||||
(
|
||||
frappe.qb.update(stock_closing_entry)
|
||||
.set(stock_closing_entry.status, "Cancelled")
|
||||
.where(stock_closing_entry.status == "Canceled")
|
||||
).run()
|
||||
|
||||
# updating call log status to cancelled from canceled
|
||||
(frappe.qb.update(call_log).set(call_log.status, "Cancelled").where(call_log.status == "Canceled")).run()
|
||||
@@ -8,6 +8,7 @@ from frappe.tests import IntegrationTestCase
|
||||
from frappe.utils import add_to_date, now_datetime, nowdate
|
||||
|
||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||
from erpnext.projects.doctype.task.test_task import create_task
|
||||
from erpnext.projects.doctype.timesheet.timesheet import OverlapError, make_sales_invoice
|
||||
from erpnext.setup.doctype.employee.test_employee import make_employee
|
||||
from erpnext.tests.utils import ERPNextTestSuite
|
||||
@@ -22,6 +23,55 @@ class TestTimesheet(ERPNextTestSuite):
|
||||
def setUp(self):
|
||||
frappe.db.delete("Timesheet")
|
||||
|
||||
def test_timesheet_post_update(self):
|
||||
frappe.get_doc(
|
||||
{
|
||||
"doctype": "Property Setter",
|
||||
"doctype_or_field": "DocField",
|
||||
"doc_type": "Timesheet",
|
||||
"field_name": "time_logs",
|
||||
"property": "allow_on_submit",
|
||||
"property_type": "Check",
|
||||
"value": "1",
|
||||
}
|
||||
).insert(ignore_permissions=True)
|
||||
|
||||
task = create_task("Test Task 1")
|
||||
|
||||
timesheet = frappe.new_doc("Timesheet")
|
||||
timesheet.append(
|
||||
"time_logs",
|
||||
{
|
||||
"task": task.name,
|
||||
"from_time": now_datetime(),
|
||||
"to_time": now_datetime() + datetime.timedelta(hours=1),
|
||||
"company": "_Test Company",
|
||||
},
|
||||
)
|
||||
|
||||
timesheet.save()
|
||||
timesheet.submit()
|
||||
task.reload()
|
||||
self.assertEqual(task.actual_time, 1)
|
||||
timesheet.append(
|
||||
"time_logs",
|
||||
{
|
||||
"task": task.name,
|
||||
"from_time": now_datetime(),
|
||||
"to_time": now_datetime() + datetime.timedelta(hours=2),
|
||||
"hours": 2,
|
||||
},
|
||||
)
|
||||
|
||||
timesheet.save()
|
||||
task.reload()
|
||||
self.assertEqual(task.actual_time, 3)
|
||||
|
||||
frappe.db.delete(
|
||||
"Property Setter",
|
||||
{"doc_type": "Timesheet", "field_name": "time_logs", "property": "allow_on_submit"},
|
||||
)
|
||||
|
||||
def test_timesheet_base_amount(self):
|
||||
emp = make_employee("test_employee_6@salary.com")
|
||||
timesheet = make_timesheet(emp, simulate=True, is_billable=1)
|
||||
|
||||
@@ -73,6 +73,13 @@ class Timesheet(Document):
|
||||
self.calculate_percentage_billed()
|
||||
self.set_dates()
|
||||
|
||||
def on_discard(self):
|
||||
self.db_set("status", "Cancelled")
|
||||
|
||||
def on_update_after_submit(self):
|
||||
self.validate_mandatory_fields()
|
||||
self.update_task_and_project()
|
||||
|
||||
def calculate_hours(self):
|
||||
for row in self.time_logs:
|
||||
if row.to_time and row.from_time:
|
||||
|
||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
@@ -361,6 +361,21 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
|
||||
mandatory_depends_on:
|
||||
"eval:doc.action=='Create Voucher' && doc.document_type=='Payment Entry'",
|
||||
},
|
||||
{
|
||||
fieldname: "bank_account",
|
||||
fieldtype: "Link",
|
||||
label: "Company Bank Account",
|
||||
options: "Bank Account",
|
||||
depends_on: "eval:doc.party",
|
||||
get_query: function () {
|
||||
return {
|
||||
filters: {
|
||||
is_company_account: 1,
|
||||
company: this.company,
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldname: "project",
|
||||
fieldtype: "Link",
|
||||
@@ -511,6 +526,7 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
|
||||
mode_of_payment: values.mode_of_payment,
|
||||
project: values.project,
|
||||
cost_center: values.cost_center,
|
||||
company_bank_account: values?.bank_account || this?.bank_account,
|
||||
},
|
||||
callback: (response) => {
|
||||
const alert_string = __("Bank Transaction {0} added as Payment Entry", [
|
||||
@@ -582,6 +598,7 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
|
||||
project: values.project,
|
||||
cost_center: values.cost_center,
|
||||
allow_edit: true,
|
||||
company_bank_account: values?.bank_account || this?.bank_account,
|
||||
},
|
||||
callback: (r) => {
|
||||
const doc = frappe.model.sync(r.message);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user