Compare commits

..

3 Commits

Author SHA1 Message Date
rohitwaghchaure
2530b56421 chore: fix conflicts 2024-10-29 15:20:15 +05:30
rohitwaghchaure
3fd89d75d6 chore: fix conflicts 2024-10-29 15:15:39 +05:30
rohitwaghchaure
63e9da92b2 fix: work order finish button not showing (#43875)
(cherry picked from commit 0a70be5b99)

# Conflicts:
#	erpnext/manufacturing/doctype/job_card/job_card.js
#	erpnext/manufacturing/doctype/job_card/job_card.py
2024-10-28 11:52:19 +00:00
35 changed files with 95 additions and 286 deletions

View File

@@ -4,7 +4,7 @@ import inspect
import frappe
from frappe.utils.user import is_website_user
__version__ = "15.40.0"
__version__ = "15.28.2"
def get_default_company(user=None):

View File

@@ -58,7 +58,7 @@ frappe.ui.form.on("Accounting Dimension", {
},
label: function (frm) {
frm.set_value("fieldname", frm.doc.label.replace(/ /g, "_").replace(/-/g, "_").toLowerCase());
frm.set_value("fieldname", frappe.model.scrub(frm.doc.label));
},
document_type: function (frm) {

View File

@@ -7,7 +7,6 @@ import json
import frappe
from frappe import _, scrub
from frappe.custom.doctype.custom_field.custom_field import create_custom_field
from frappe.database.schema import validate_column_name
from frappe.model import core_doctypes_list
from frappe.model.document import Document
from frappe.utils import cstr
@@ -61,7 +60,6 @@ class AccountingDimension(Document):
if not self.is_new():
self.validate_document_type_change()
validate_column_name(self.fieldname)
self.validate_dimension_defaults()
def validate_document_type_change(self):

View File

@@ -323,7 +323,6 @@ class PaymentReconciliation(Document):
"posting_date": inv.posting_date,
"currency": inv.currency,
"cost_center": inv.cost_center,
"remarks": inv.remarks,
}
)
)

View File

@@ -14,7 +14,7 @@
"amount",
"difference_amount",
"sec_break1",
"remarks",
"remark",
"currency",
"exchange_rate",
"cost_center"
@@ -74,6 +74,12 @@
"fieldname": "sec_break1",
"fieldtype": "Section Break"
},
{
"fieldname": "remark",
"fieldtype": "Small Text",
"label": "Remark",
"read_only": 1
},
{
"fieldname": "currency",
"fieldtype": "Link",
@@ -99,18 +105,12 @@
"fieldtype": "Link",
"label": "Cost Center",
"options": "Cost Center"
},
{
"fieldname": "remarks",
"fieldtype": "Small Text",
"label": "Remarks",
"read_only": 1
}
],
"is_virtual": 1,
"istable": 1,
"links": [],
"modified": "2024-10-29 16:24:43.021230",
"modified": "2023-11-17 17:33:34.818530",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Reconciliation Payment",

View File

@@ -27,7 +27,7 @@ class PaymentReconciliationPayment(Document):
reference_name: DF.DynamicLink | None
reference_row: DF.Data | None
reference_type: DF.Link | None
remarks: DF.SmallText | None
remark: DF.SmallText | None
# end: auto-generated types
@staticmethod

View File

@@ -14,7 +14,6 @@
"party_details",
"party_type",
"party",
"party_name",
"column_break_4",
"reference_doctype",
"reference_name",
@@ -423,19 +422,13 @@
"label": "Party Account Currency",
"options": "Currency",
"read_only": 1
},
{
"fieldname": "party_name",
"fieldtype": "Data",
"label": "Party Name",
"read_only": 1
}
],
"in_create": 1,
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2024-10-23 12:23:40.117336",
"modified": "2024-09-16 17:50:54.440090",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Request",
@@ -474,4 +467,4 @@
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}
}

View File

@@ -71,7 +71,6 @@ class PaymentRequest(Document):
outstanding_amount: DF.Currency
party: DF.DynamicLink | None
party_account_currency: DF.Link | None
party_name: DF.Data | None
party_type: DF.Link | None
payment_account: DF.ReadOnly | None
payment_channel: DF.Literal["", "Email", "Phone", "Other"]
@@ -610,7 +609,6 @@ def make_payment_request(**args):
"party_type": party_type,
"party": args.get("party") or ref_doc.get("customer"),
"bank_account": bank_account,
"party_name": args.get("party_name") or ref_doc.get("customer_name"),
}
)

View File

@@ -354,8 +354,7 @@ class PeriodClosingVoucher(AccountsController):
def get_account_closing_balances(self):
pl_closing_entries = self.get_closing_entries_for_pl_accounts()
bs_closing_entries = self.get_closing_entries_for_balance_sheet_accounts()
closing_entries_for_closing_account = self.get_closing_entries_for_closing_account()
closing_entries = pl_closing_entries + bs_closing_entries + closing_entries_for_closing_account
closing_entries = pl_closing_entries + bs_closing_entries
return closing_entries
def get_closing_entries_for_pl_accounts(self):
@@ -405,24 +404,12 @@ class PeriodClosingVoucher(AccountsController):
self.update_default_dimensions(closing_entry, dimensions)
return closing_entry
def get_closing_entries_for_closing_account(self):
closing_entries = copy.deepcopy(self.closing_account_gle)
for d in closing_entries:
d.period_closing_voucher = self.name
return closing_entries
def is_first_period_closing_voucher(self):
first_pcv = frappe.db.get_value(
return not frappe.db.exists(
"Period Closing Voucher",
{"company": self.company, "docstatus": 1},
"name",
order_by="period_end_date",
{"company": self.company, "docstatus": 1, "name": ("!=", self.name)},
)
if not first_pcv or first_pcv == self.name:
return True
def cancel_gl_entries(self):
if self.get_gle_count_against_current_pcv() > 5000:
frappe.enqueue(
@@ -455,7 +442,8 @@ def process_gl_and_closing_entries(doc):
make_gl_entries(gl_entries, merge_entries=False)
closing_entries = doc.get_account_closing_balances()
make_closing_entries(closing_entries, doc.name, doc.company, doc.period_end_date)
if closing_entries:
make_closing_entries(closing_entries, doc.name, doc.company, doc.period_end_date)
frappe.db.set_value(doc.doctype, doc.name, "gle_processing_status", "Completed")
except Exception as e:

View File

@@ -1593,11 +1593,7 @@ class PurchaseInvoice(BuyingController):
for proj, value in projects.items():
res = frappe.qb.from_(pj).select(pj.total_purchase_cost).where(pj.name == proj).for_update().run()
current_purchase_cost = res and res[0][0] or 0
# frappe.db.set_value("Project", proj, "total_purchase_cost", current_purchase_cost + value)
project_doc = frappe.get_doc("Project", proj)
project_doc.total_purchase_cost = current_purchase_cost + value
project_doc.calculate_gross_margin()
project_doc.db_update()
frappe.db.set_value("Project", proj, "total_purchase_cost", current_purchase_cost + value)
def validate_supplier_invoice(self):
if self.bill_date:

View File

@@ -505,8 +505,7 @@
"fieldtype": "Link",
"label": "Project",
"options": "Project",
"print_hide": 1,
"search_index": 1
"print_hide": 1
},
{
"allow_on_submit": 1,
@@ -975,7 +974,7 @@
"idx": 1,
"istable": 1,
"links": [],
"modified": "2024-10-28 15:06:19.246141",
"modified": "2024-07-19 12:12:42.449298",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",

View File

@@ -1734,11 +1734,9 @@ class SalesInvoice(SellingController):
)
def update_project(self):
unique_projects = list(set([d.project for d in self.get("items") if d.project]))
for p in unique_projects:
project = frappe.get_doc("Project", p)
if self.project:
project = frappe.get_doc("Project", self.project)
project.update_billed_amount()
project.calculate_gross_margin()
project.db_update()
def verify_payment_amount_is_positive(self):

View File

@@ -812,8 +812,7 @@
"fieldname": "project",
"fieldtype": "Link",
"label": "Project",
"options": "Project",
"search_index": 1
"options": "Project"
},
{
"depends_on": "eval:parent.update_stock == 1",
@@ -928,7 +927,7 @@
"idx": 1,
"istable": 1,
"links": [],
"modified": "2024-10-28 15:06:40.980995",
"modified": "2024-05-23 16:36:18.970862",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Item",

View File

@@ -514,7 +514,7 @@ def get_tds_amount(ldc, parties, inv, tax_details, vouchers):
payment_entry_filters.pop("apply_tax_withholding_amount", None)
payment_entry_filters.pop("tax_withholding_category", None)
supp_inv_credit_amt = frappe.db.get_value("Purchase Invoice", invoice_filters, field) or 0.0
supp_credit_amt = frappe.db.get_value("Purchase Invoice", invoice_filters, field) or 0.0
supp_jv_credit_amt = (
frappe.db.get_value(
@@ -538,7 +538,7 @@ def get_tds_amount(ldc, parties, inv, tax_details, vouchers):
group_by="payment_type",
)
supp_credit_amt = supp_jv_credit_amt
supp_credit_amt += supp_jv_credit_amt
supp_credit_amt += inv.tax_withholding_net_total
for type in payment_entry_amounts:
@@ -556,18 +556,18 @@ def get_tds_amount(ldc, parties, inv, tax_details, vouchers):
tax_withholding_net_total = inv.tax_withholding_net_total
if (threshold and tax_withholding_net_total >= threshold) or (
cumulative_threshold and (supp_credit_amt + supp_inv_credit_amt) >= cumulative_threshold
cumulative_threshold and supp_credit_amt >= cumulative_threshold
):
# Get net total again as TDS is calculated on net total
# Grand is used to just check for threshold breach
net_total = (
frappe.db.get_value("Purchase Invoice", invoice_filters, "sum(tax_withholding_net_total)") or 0.0
)
supp_credit_amt += net_total
if (cumulative_threshold and supp_credit_amt >= cumulative_threshold) and cint(
tax_details.tax_on_excess_amount
):
# Get net total again as TDS is calculated on net total
# Grand is used to just check for threshold breach
net_total = (
frappe.db.get_value("Purchase Invoice", invoice_filters, "sum(tax_withholding_net_total)")
or 0.0
)
net_total += inv.tax_withholding_net_total
supp_credit_amt = net_total - cumulative_threshold
if ldc and is_valid_certificate(ldc, inv.get("posting_date") or inv.get("transaction_date"), 0):

View File

@@ -121,46 +121,6 @@ class TestTaxWithholdingCategory(FrappeTestCase):
for d in reversed(invoices):
d.cancel()
def test_cumulative_threshold_with_party_ledger_amount_on_net_total(self):
invoices = []
frappe.db.set_value(
"Supplier", "Test TDS Supplier3", "tax_withholding_category", "Advance TDS Category"
)
# Invoice with tax and without exceeding single and cumulative thresholds
for _ in range(2):
pi = create_purchase_invoice(supplier="Test TDS Supplier3", rate=1000, do_not_save=True)
pi.apply_tds = 1
pi.append(
"taxes",
{
"category": "Total",
"charge_type": "Actual",
"account_head": "_Test Account VAT - _TC",
"cost_center": "Main - _TC",
"tax_amount": 500,
"description": "Test",
"add_deduct_tax": "Add",
},
)
pi.save()
pi.submit()
invoices.append(pi)
# Third Invoice exceeds single threshold and not exceeding cumulative threshold
pi1 = create_purchase_invoice(supplier="Test TDS Supplier3", rate=6000)
pi1.apply_tds = 1
pi1.save()
pi1.submit()
invoices.append(pi1)
# Cumulative threshold is 10,000
# Threshold calculation should be only on the third invoice
self.assertEqual(pi1.taxes[0].tax_amount, 800)
for d in reversed(invoices):
d.cancel()
def test_cumulative_threshold_tcs(self):
frappe.db.set_value(
"Customer", "Test TCS Customer", "tax_withholding_category", "Cumulative Threshold TCS"

View File

@@ -526,8 +526,7 @@ def get_invoice_tax_map(invoice_list, invoice_income_map, income_accounts, inclu
tax_details = frappe.db.sql(
"""select parent, account_head,
sum(base_tax_amount_after_discount_amount) as tax_amount
from `tabSales Taxes and Charges` where parent in (%s) and parenttype = 'Sales Invoice'
group by parent, account_head"""
from `tabSales Taxes and Charges` where parent in (%s) group by parent, account_head"""
% ", ".join(["%s"] * len(invoice_list)),
tuple(inv.name for inv in invoice_list),
as_dict=1,

View File

@@ -1969,7 +1969,6 @@ class QueryPaymentLedger:
ple.cost_center.as_("cost_center"),
Sum(ple.amount).as_("amount"),
Sum(ple.amount_in_account_currency).as_("amount_in_account_currency"),
ple.remarks,
)
.where(ple.delinked == 0)
.where(Criterion.all(filter_on_voucher_no))
@@ -2032,7 +2031,6 @@ class QueryPaymentLedger:
Table("vouchers").due_date,
Table("vouchers").currency,
Table("vouchers").cost_center.as_("cost_center"),
Table("vouchers").remarks,
)
.where(Criterion.all(filter_on_outstanding_amount))
)

View File

@@ -790,19 +790,14 @@ class Asset(AccountsController):
args.get("value_after_depreciation")
)
else:
value = flt(args.get("expected_value_after_useful_life")) / (
flt(self.gross_purchase_amount) - flt(self.opening_accumulated_depreciation)
)
value = flt(args.get("expected_value_after_useful_life")) / flt(self.gross_purchase_amount)
depreciation_rate = math.pow(
value,
1.0
/ (
(
(
flt(args.get("total_number_of_depreciations"), 2)
- flt(self.opening_number_of_booked_depreciations)
)
flt(args.get("total_number_of_depreciations"), 2)
* flt(args.get("frequency_of_depreciation"))
)
/ 12

View File

@@ -79,9 +79,6 @@ def validate_returned_items(doc):
if doc.doctype in ["Purchase Invoice", "Purchase Receipt", "Subcontracting Receipt"]:
select_fields += ",rejected_qty, received_qty"
if doc.doctype in ["Purchase Receipt", "Purchase Invoice"]:
select_fields += ",name"
for d in frappe.db.sql(
f"""select {select_fields} from `tab{doc.doctype} Item` where parent = %s""",
doc.return_against,
@@ -107,24 +104,15 @@ def validate_returned_items(doc):
items_returned = False
for d in doc.get("items"):
key = d.item_code
raise_exception = False
if doc.doctype in ["Purchase Receipt", "Purchase Invoice"]:
field = frappe.scrub(doc.doctype) + "_item"
if d.get(field):
key = (d.item_code, d.get(field))
raise_exception = True
if d.item_code and (flt(d.qty) < 0 or flt(d.get("received_qty")) < 0):
if key not in valid_items:
frappe.msgprint(
if d.item_code not in valid_items:
frappe.throw(
_("Row # {0}: Returned Item {1} does not exist in {2} {3}").format(
d.idx, d.item_code, doc.doctype, doc.return_against
),
raise_exception=raise_exception,
)
)
else:
ref = valid_items.get(key, frappe._dict())
ref = valid_items.get(d.item_code, frappe._dict())
validate_quantity(doc, d, ref, valid_items, already_returned_items)
if (
@@ -205,12 +193,8 @@ def validate_quantity(doc, args, ref, valid_items, already_returned_items):
def get_ref_item_dict(valid_items, ref_item_row):
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
key = ref_item_row.item_code
if ref_item_row.get("name"):
key = (ref_item_row.item_code, ref_item_row.name)
valid_items.setdefault(
key,
ref_item_row.item_code,
frappe._dict(
{
"qty": 0,
@@ -224,7 +208,7 @@ def get_ref_item_dict(valid_items, ref_item_row):
}
),
)
item_dict = valid_items[key]
item_dict = valid_items[ref_item_row.item_code]
item_dict["qty"] += ref_item_row.qty
item_dict["stock_qty"] += ref_item_row.get("stock_qty", 0)
if ref_item_row.get("rate", 0) > item_dict["rate"]:

View File

@@ -561,11 +561,11 @@ class SubcontractingController(StockController):
use_serial_batch_fields = frappe.db.get_single_value("Stock Settings", "use_serial_batch_fields")
if self.doctype == self.subcontract_data.order_doctype:
rm_obj.required_qty = flt(qty, rm_obj.precision("required_qty"))
rm_obj.amount = flt(rm_obj.required_qty * rm_obj.rate, rm_obj.precision("amount"))
rm_obj.required_qty = qty
rm_obj.amount = rm_obj.required_qty * rm_obj.rate
else:
rm_obj.consumed_qty = flt(qty, rm_obj.precision("consumed_qty"))
rm_obj.required_qty = flt(bom_item.required_qty or qty, rm_obj.precision("required_qty"))
rm_obj.consumed_qty = qty
rm_obj.required_qty = bom_item.required_qty or qty
rm_obj.serial_and_batch_bundle = None
setattr(
rm_obj, self.subcontract_data.order_field, item_row.get(self.subcontract_data.order_field)
@@ -664,8 +664,8 @@ class SubcontractingController(StockController):
self.__set_serial_nos(item_row, rm_obj)
def __set_consumed_qty(self, rm_obj, consumed_qty, required_qty=0):
rm_obj.required_qty = flt(required_qty, rm_obj.precision("required_qty"))
rm_obj.consumed_qty = flt(consumed_qty, rm_obj.precision("consumed_qty"))
rm_obj.required_qty = required_qty
rm_obj.consumed_qty = consumed_qty
def __set_serial_nos(self, item_row, rm_obj):
key = (rm_obj.rm_item_code, item_row.item_code, item_row.get(self.subcontract_data.order_field))

View File

@@ -1234,7 +1234,6 @@ def make_subcontracted_items():
"Subcontracted Item SA6": {},
"Subcontracted Item SA7": {},
"Subcontracted Item SA8": {},
"Subcontracted Item SA9": {"stock_uom": "Litre"},
}
for item, properties in sub_contracted_items.items():
@@ -1255,7 +1254,6 @@ def make_raw_materials():
"Subcontracted SRM Item 4": {"has_serial_no": 1, "serial_no_series": "SRII.####"},
"Subcontracted SRM Item 5": {"has_serial_no": 1, "serial_no_series": "SRIID.####"},
"Subcontracted SRM Item 8": {},
"Subcontracted SRM Item 9": {"stock_uom": "Litre"},
}
for item, properties in raw_materials.items():
@@ -1282,7 +1280,6 @@ def make_service_items():
"Subcontracted Service Item 6": {},
"Subcontracted Service Item 7": {},
"Subcontracted Service Item 8": {},
"Subcontracted Service Item 9": {},
}
for item, properties in service_items.items():

View File

@@ -127,8 +127,8 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller
fieldname: "prospect_name",
fieldtype: "Data",
default: frm.doc.company_name,
reqd: 1,
depends_on: "create_prospect",
mandatory_depends_on: "create_prospect",
}
);
}

View File

@@ -921,24 +921,6 @@ class JobCard(Document):
if doc.transfer_material_against == "Work Order" or doc.skip_transfer:
return
if self.items:
# sum of 'For Quantity' of Stock Entries against JC
self.transferred_qty = (
frappe.db.get_value(
"Stock Entry",
{
"job_card": self.name,
"work_order": self.work_order,
"docstatus": 1,
"purpose": "Material Transfer for Manufacture",
},
"sum(fg_completed_qty)",
)
or 0
)
self.db_set("transferred_qty", self.transferred_qty)
qty = 0
if self.work_order:
if doc.transfer_material_against == "Job Card" and not doc.skip_transfer:

View File

@@ -315,7 +315,7 @@ erpnext.patches.v15_0.update_asset_value_for_manual_depr_entries
erpnext.patches.v15_0.update_gpa_and_ndb_for_assdeprsch
erpnext.patches.v14_0.create_accounting_dimensions_for_closing_balance
erpnext.patches.v14_0.set_period_start_end_date_in_pcv
erpnext.patches.v14_0.update_closing_balances #29-10-2024
erpnext.patches.v14_0.update_closing_balances #14-07-2023
execute:frappe.db.set_single_value("Accounts Settings", "merge_similar_account_heads", 0)
erpnext.patches.v14_0.update_reference_type_in_journal_entry_accounts
erpnext.patches.v14_0.update_subscription_details

View File

@@ -24,11 +24,10 @@ def execute():
for pcv in get_period_closing_vouchers(company):
company_wise_order.setdefault(pcv.company, [])
if pcv.period_end_date not in company_wise_order[pcv.company]:
pcv_doc = frappe.get_doc("Period Closing Voucher", pcv.name)
pcv_doc.pl_accounts_reverse_gle = get_pcv_gl_entries_for_pl_accounts(pcv, gle_fields)
pcv_doc.closing_account_gle = get_pcv_gl_entries_for_closing_accounts(pcv, gle_fields)
closing_entries = pcv_doc.get_account_closing_balances()
make_closing_entries(closing_entries, pcv.name, pcv.company, pcv.period_end_date)
pcv.pl_accounts_reverse_gle = get_pcv_gl_entries(pcv, gle_fields)
closing_entries = pcv.get_account_closing_balances()
if closing_entries:
make_closing_entries(closing_entries, pcv.name, pcv.company, pcv.period_end_date)
company_wise_order[pcv.company].append(pcv.period_end_date)
i += 1
@@ -39,7 +38,6 @@ def get_gle_fields():
accounting_dimension_fields = get_accounting_dimensions()
gle_fields = [
"name",
"company",
"posting_date",
"account",
"account_currency",
@@ -63,27 +61,14 @@ def get_period_closing_vouchers(company):
)
def get_pcv_gl_entries_for_pl_accounts(pcv, gle_fields):
return get_gl_entries(pcv, gle_fields, {"account": ["!=", pcv.closing_account_head]})
def get_pcv_gl_entries_for_closing_accounts(pcv, gle_fields):
return get_gl_entries(pcv, gle_fields, {"account": pcv.closing_account_head})
def get_gl_entries(pcv, gle_fields, accounts_filter=None):
filters = {"voucher_no": pcv.name, "is_cancelled": 0}
if accounts_filter:
filters.update(accounts_filter)
def get_pcv_gl_entries(pcv, gle_fields):
gl_entries = frappe.db.get_all(
"GL Entry",
filters=filters,
filters={"voucher_no": pcv.name, "account": ["!=", pcv.closing_account_head], "is_cancelled": 0},
fields=gle_fields,
)
for entry in gl_entries:
entry["is_period_closing_voucher_entry"] = 1
entry["closing_date"] = pcv.period_end_date
entry["period_closing_voucher"] = pcv.name
return gl_entries

View File

@@ -93,14 +93,14 @@ class Project(Document):
def validate(self):
if not self.is_new():
self.copy_from_template() # nosemgrep
self.copy_from_template()
self.send_welcome_email()
self.update_costing()
self.update_percent_complete()
self.validate_from_to_dates("expected_start_date", "expected_end_date")
self.validate_from_to_dates("actual_start_date", "actual_end_date")
def copy_from_template(self): # nosemgrep
def copy_from_template(self):
"""
Copy tasks from template
"""
@@ -205,7 +205,7 @@ class Project(Document):
self.db_update()
def after_insert(self):
self.copy_from_template() # nosemgrep
self.copy_from_template()
if self.sales_order:
frappe.db.set_value("Sales Order", self.sales_order, "project", self.name)
@@ -324,13 +324,9 @@ class Project(Document):
self.total_sales_amount = total_sales_amount and total_sales_amount[0][0] or 0
def update_billed_amount(self):
# nosemgrep
total_billed_amount = frappe.db.sql(
"""select sum(base_net_amount)
from `tabSales Invoice Item` si_item, `tabSales Invoice` si
where si_item.parent = si.name
and if(si_item.project, si_item.project, si.project) = %s
and si.docstatus=1""",
"""select sum(base_net_total)
from `tabSales Invoice` where project = %s and docstatus=1""",
self.name,
)
@@ -680,8 +676,31 @@ def update_project_sales_billing():
return
# Else simply fallback to Daily
for project in frappe.get_all("Project", filters={"status": ["!=", "Cancelled"]}):
frappe.get_doc("Project", project.name).save()
exists_query = "(SELECT 1 from `tab{doctype}` where docstatus = 1 and project = `tabProject`.name)"
project_map = {}
for project_details in frappe.db.sql(
"""
SELECT name, 1 as order_exists, null as invoice_exists from `tabProject` where
exists {order_exists}
union
SELECT name, null as order_exists, 1 as invoice_exists from `tabProject` where
exists {invoice_exists}
""".format(
order_exists=exists_query.format(doctype="Sales Order"),
invoice_exists=exists_query.format(doctype="Sales Invoice"),
),
as_dict=True,
):
project = project_map.setdefault(
project_details.name, frappe.get_doc("Project", project_details.name)
)
if project_details.order_exists:
project.update_sales_amount()
if project_details.invoice_exists:
project.update_billed_amount()
for project in project_map.values():
project.save()
@frappe.whitelist()
@@ -732,6 +751,7 @@ def get_users_email(doc):
def calculate_total_purchase_cost(project: str | None = None):
if project:
pitem = qb.DocType("Purchase Invoice Item")
frappe.qb.DocType("Purchase Invoice Item")
total_purchase_cost = (
qb.from_(pitem)
.select(Sum(pitem.base_net_amount))

View File

@@ -22,46 +22,6 @@ class OverWorkLoggedError(frappe.ValidationError):
class Timesheet(Document):
# begin: auto-generated types
# This code is auto-generated. Do not modify anything in this block.
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from frappe.types import DF
from erpnext.projects.doctype.timesheet_detail.timesheet_detail import TimesheetDetail
amended_from: DF.Link | None
base_total_billable_amount: DF.Currency
base_total_billed_amount: DF.Currency
base_total_costing_amount: DF.Currency
company: DF.Link | None
currency: DF.Link | None
customer: DF.Link | None
department: DF.Link | None
employee: DF.Link | None
employee_name: DF.Data | None
end_date: DF.Date | None
exchange_rate: DF.Float
naming_series: DF.Literal["TS-.YYYY.-"]
note: DF.TextEditor | None
parent_project: DF.Link | None
per_billed: DF.Percent
sales_invoice: DF.Link | None
start_date: DF.Date | None
status: DF.Literal["Draft", "Submitted", "Billed", "Payslip", "Completed", "Cancelled"]
time_logs: DF.Table[TimesheetDetail]
title: DF.Data | None
total_billable_amount: DF.Currency
total_billable_hours: DF.Float
total_billed_amount: DF.Currency
total_billed_hours: DF.Float
total_costing_amount: DF.Currency
total_hours: DF.Float
user: DF.Link | None
# end: auto-generated types
def validate(self):
self.set_status()
self.validate_dates()

View File

@@ -15,7 +15,6 @@ def execute(filters=None):
filters=filters,
fields=[
"name",
"project_name",
"status",
"percent_complete",
"expected_start_date",
@@ -49,11 +48,6 @@ def get_columns():
"options": "Project",
"width": 200,
},
{
"fieldname": "project_name",
"label": _("Project Name"),
"width": 200,
},
{
"fieldname": "project_type",
"label": _("Type"),
@@ -88,7 +82,7 @@ def get_chart_data(data):
overdue = []
for project in data:
labels.append(project.project_name)
labels.append(project.name)
total.append(project.total_tasks)
completed.append(project.completed_tasks)
overdue.append(project.overdue_tasks)

View File

@@ -375,8 +375,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
recipient_id: me.frm.doc.contact_email,
payment_request_type: payment_request_type,
party_type: payment_request_type == 'Outward' ? "Supplier" : "Customer",
party: payment_request_type == 'Outward' ? me.frm.doc.supplier : me.frm.doc.customer,
party_name:payment_request_type == 'Outward' ? me.frm.doc.supplier_name : me.frm.doc.customer_name
party: payment_request_type == 'Outward' ? me.frm.doc.supplier : me.frm.doc.customer
},
callback: function(r) {
if(!r.exc){

View File

@@ -547,8 +547,6 @@ erpnext.PointOfSale.Controller = class {
async on_cart_update(args) {
frappe.dom.freeze();
if (this.frm.doc.set_warehouse != this.settings.warehouse)
this.frm.doc.set_warehouse = this.settings.warehouse;
let item_row = undefined;
try {
let { field, value, item } = args;

View File

@@ -350,11 +350,6 @@ erpnext.PointOfSale.Payment = class {
}
checkout() {
const frm = this.events.get_frm();
frm.cscript.calculate_outstanding_amount();
frm.refresh_field("outstanding_amount");
frm.refresh_field("paid_amount");
frm.refresh_field("base_paid_amount");
this.events.toggle_other_sections(true);
this.toggle_component(true);

View File

@@ -1020,6 +1020,7 @@ def make_sales_invoice(source_name, target_doc=None, args=None):
"parent": "delivery_note",
"so_detail": "so_detail",
"against_sales_order": "sales_order",
"serial_no": "serial_no",
"cost_center": "cost_center",
},
"postprocess": update_item,

View File

@@ -25,7 +25,6 @@ from erpnext.controllers.tests.test_subcontracting_controller import (
make_subcontracted_items,
set_backflush_based_on,
)
from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
from erpnext.stock.doctype.item.test_item import make_item
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
from erpnext.subcontracting.doctype.subcontracting_order.subcontracting_order import (
@@ -684,28 +683,6 @@ class TestSubcontractingOrder(FrappeTestCase):
self.assertEqual(requested_qty, new_requested_qty)
def test_subcontracting_order_rm_required_items_for_precision(self):
item_code = "Subcontracted Item SA9"
raw_materials = ["Subcontracted SRM Item 9"]
if not frappe.db.exists("BOM", {"item": item_code}):
make_bom(item=item_code, raw_materials=raw_materials, rate=100, rm_qty=1.04)
service_items = [
{
"warehouse": "_Test Warehouse - _TC",
"item_code": "Subcontracted Service Item 9",
"qty": 1, # 202.0656,
"rate": 100,
"fg_item": "Subcontracted Item SA9",
"fg_item_qty": 202.0656,
},
]
sco = get_subcontracting_order(service_items=service_items)
sco.reload()
self.assertEqual(sco.supplied_items[0].required_qty, 210.149)
def create_subcontracting_order(**args):
args = frappe._dict(args)

View File

@@ -331,12 +331,9 @@ class SubcontractingReceipt(SubcontractingController):
supplied_items_details[item.name] = {}
for supplied_item in supplied_items:
if supplied_item.rm_item_code not in supplied_items_details[item.name]:
supplied_items_details[item.name][supplied_item.rm_item_code] = 0.0
supplied_items_details[item.name][
supplied_item.rm_item_code
] += supplied_item.available_qty
] = supplied_item.available_qty
else:
for item in self.get("supplied_items"):
item.available_qty_for_consumption = supplied_items_details.get(item.reference_name, {}).get(

View File

@@ -173,11 +173,11 @@
<div class="col-xs-8 col-sm-10">
{{ d.item_code }}
<div class="text-muted small item-description">
{{ html2text(d.description or "") | truncate(140) }}
{{ html2text(d.description) | truncate(140) }}
</div>
<span class="text-muted mt-2 d-l-n order-qty">
{{ _("Qty ") }}({{ d.get_formatted("qty") }})
</span>
</div>
</div>
{% endmacro %}
{% endmacro %}