Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: release v14 #44102

Merged
merged 29 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
b1e205f
fix: subcontracting receipt has no reference field for purchase order
Ninad1306 Nov 7, 2024
0cdb4cb
Merge pull request #44014 from Ninad1306/dashboard_links
sagarvora Nov 7, 2024
1446aa3
fix: NoneType while updating ordered_qty in SO for removed items
Oct 21, 2024
82cd42b
Merge pull request #44023 from frappe/mergify/bp/version-14-hotfix/pr…
ruthra-kumar Nov 8, 2024
440ada1
refactor: add "margin_type" and "margin_rate_or_amount" to no copy
NethminaHiker360 Oct 28, 2024
093b4f9
Merge pull request #44026 from frappe/mergify/bp/version-14-hotfix/pr…
ruthra-kumar Nov 8, 2024
d73cc83
fix: tyeerror while saving pick list
Nov 10, 2024
3df783b
Merge pull request #44069 from frappe/mergify/bp/version-14-hotfix/pr…
rohitwaghchaure Nov 11, 2024
c12d5f6
fix: task path (backport #44073) (#44077)
mergify[bot] Nov 11, 2024
f2aa71c
chore: update `CODEOWNERS` (backport #44074) (#44080)
mergify[bot] Nov 11, 2024
6b149f5
fix: populate payment schedule from payment terms (backport #44082) (…
mergify[bot] Nov 11, 2024
599581e
fix: exception on register reports when filtered on cost center
Vishv-024 Oct 16, 2024
a98fe7a
test: basic report output
ruthra-kumar Nov 8, 2024
964ac05
test: journals with cost center
ruthra-kumar Nov 11, 2024
a8a89f9
refactor(test): fix incorrect assertion
ruthra-kumar Nov 11, 2024
4f7d534
refactor(test): pass all mandatory fields
ruthra-kumar Nov 11, 2024
71a1e50
refactor(test): assertion refactoring and exact decimals
ruthra-kumar Nov 11, 2024
558fac6
chore: use FrappeTestCase
ruthra-kumar Nov 11, 2024
fd9fd8f
chore: filter report output
ruthra-kumar Nov 11, 2024
7fb5f17
Merge pull request #44087 from frappe/mergify/bp/version-14-hotfix/pr…
ruthra-kumar Nov 11, 2024
ea38a1f
fix: Drop Shipping address based on customer shopping address
Nihantra-Patel Nov 13, 2024
d258684
Merge pull request #44119 from frappe/mergify/bp/version-14-hotfix/pr…
Nihantra-Patel Nov 13, 2024
2acee05
refactor: 'Partly Billed' status for Purchase Receipt
ruthra-kumar Nov 13, 2024
44988c8
Merge pull request #44126 from frappe/mergify/copy/version-14-hotfix/…
ruthra-kumar Nov 13, 2024
3e2fa16
feat: Partly billed status in Purchase Receipt (#39543)
deepeshgarg007 Jan 29, 2024
cbe92fe
Merge pull request #44128 from frappe/mergify/bp/version-14-hotfix/pr…
ruthra-kumar Nov 13, 2024
da6c6dc
fix: update per_billed value in Purchase Receipt while creating Debit…
Navin-S-R Nov 13, 2024
030df0d
chore: fix conflicts
rohitwaghchaure Nov 13, 2024
ddac2c5
Merge pull request #44114 from frappe/mergify/bp/version-14-hotfix/pr…
ruthra-kumar Nov 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@
# the repo. Unless a later match takes precedence,

erpnext/accounts/ @deepeshgarg007 @ruthra-kumar
erpnext/assets/ @anandbaburajan @deepeshgarg007
erpnext/assets/ @khushi8112 @deepeshgarg007
erpnext/loan_management/ @deepeshgarg007
erpnext/regional @deepeshgarg007 @ruthra-kumar
erpnext/selling @deepeshgarg007 @ruthra-kumar
erpnext/support/ @deepeshgarg007
pos*

erpnext/buying/ @rohitwaghchaure @s-aga-r
erpnext/maintenance/ @rohitwaghchaure @s-aga-r
erpnext/manufacturing/ @rohitwaghchaure @s-aga-r
erpnext/quality_management/ @rohitwaghchaure @s-aga-r
erpnext/stock/ @rohitwaghchaure @s-aga-r
erpnext/subcontracting @rohitwaghchaure @s-aga-r
erpnext/buying/ @rohitwaghchaure
erpnext/maintenance/ @rohitwaghchaure
erpnext/manufacturing/ @rohitwaghchaure
erpnext/quality_management/ @rohitwaghchaure
erpnext/stock/ @rohitwaghchaure
erpnext/subcontracting @rohitwaghchaure

erpnext/controllers/ @deepeshgarg007 @rohitwaghchaure
erpnext/patches/ @deepeshgarg007

.github/ @deepeshgarg007
pyproject.toml @ankush
pyproject.toml @akhilnarang
179 changes: 179 additions & 0 deletions erpnext/accounts/report/sales_register/test_sales_register.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
import frappe
from frappe.tests.utils import FrappeTestCase
from frappe.utils import getdate, today

from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.accounts.report.sales_register.sales_register import execute
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin


class TestItemWiseSalesRegister(AccountsTestMixin, FrappeTestCase):
def setUp(self):
self.create_company()
self.create_customer()
self.create_item()
self.create_child_cost_center()

def tearDown(self):
frappe.db.rollback()

def create_child_cost_center(self):
cc_name = "South Wing"
if frappe.db.exists("Cost Center", cc_name):
cc = frappe.get_doc("Cost Center", cc_name)
else:
parent = frappe.db.get_value("Cost Center", self.cost_center, "parent_cost_center")
cc = frappe.get_doc(
{
"doctype": "Cost Center",
"company": self.company,
"is_group": False,
"parent_cost_center": parent,
"cost_center_name": cc_name,
}
)
cc = cc.save()
self.south_cc = cc.name

def create_sales_invoice(self, rate=100, do_not_submit=False):
si = create_sales_invoice(
item=self.item,
company=self.company,
customer=self.customer,
debit_to=self.debit_to,
posting_date=today(),
parent_cost_center=self.cost_center,
cost_center=self.cost_center,
rate=rate,
price_list_rate=rate,
do_not_save=1,
)
si = si.save()
if not do_not_submit:
si = si.submit()
return si

def test_basic_report_output(self):
si = self.create_sales_invoice(rate=98)

filters = frappe._dict({"from_date": today(), "to_date": today(), "company": self.company})
report = execute(filters)

res = [x for x in report[1] if x.get("voucher_no") == si.name]

expected_result = {
"voucher_type": si.doctype,
"voucher_no": si.name,
"posting_date": getdate(),
"customer": self.customer,
"receivable_account": self.debit_to,
"net_total": 98.0,
"grand_total": 98.0,
"debit": 98.0,
}

report_output = {k: v for k, v in res[0].items() if k in expected_result}
self.assertDictEqual(report_output, expected_result)

def test_journal_with_cost_center_filter(self):
je1 = frappe.get_doc(
{
"doctype": "Journal Entry",
"voucher_type": "Journal Entry",
"company": self.company,
"posting_date": getdate(),
"accounts": [
{
"account": self.debit_to,
"party_type": "Customer",
"party": self.customer,
"credit_in_account_currency": 77,
"credit": 77,
"is_advance": "Yes",
"cost_center": self.cost_center,
},
{
"account": self.cash,
"debit_in_account_currency": 77,
"debit": 77,
},
],
}
)
je1.submit()

je2 = frappe.get_doc(
{
"doctype": "Journal Entry",
"voucher_type": "Journal Entry",
"company": self.company,
"posting_date": getdate(),
"accounts": [
{
"account": self.debit_to,
"party_type": "Customer",
"party": self.customer,
"credit_in_account_currency": 98,
"credit": 98,
"is_advance": "Yes",
"cost_center": self.south_cc,
},
{
"account": self.cash,
"debit_in_account_currency": 98,
"debit": 98,
},
],
}
)
je2.submit()

filters = frappe._dict(
{
"from_date": today(),
"to_date": today(),
"company": self.company,
"include_payments": True,
"customer": self.customer,
"cost_center": self.cost_center,
}
)
report_output = execute(filters)[1]
filtered_output = [x for x in report_output if x.get("voucher_no") == je1.name]
self.assertEqual(len(filtered_output), 1)
expected_result = {
"voucher_type": je1.doctype,
"voucher_no": je1.name,
"posting_date": je1.posting_date,
"customer": self.customer,
"receivable_account": self.debit_to,
"net_total": 77.0,
"credit": 77.0,
}
result_fields = {k: v for k, v in filtered_output[0].items() if k in expected_result}
self.assertDictEqual(result_fields, expected_result)

filters = frappe._dict(
{
"from_date": today(),
"to_date": today(),
"company": self.company,
"include_payments": True,
"customer": self.customer,
"cost_center": self.south_cc,
}
)
report_output = execute(filters)[1]
filtered_output = [x for x in report_output if x.get("voucher_no") == je2.name]
self.assertEqual(len(filtered_output), 1)
expected_result = {
"voucher_type": je2.doctype,
"voucher_no": je2.name,
"posting_date": je2.posting_date,
"customer": self.customer,
"receivable_account": self.debit_to,
"net_total": 98.0,
"credit": 98.0,
}
result_output = {k: v for k, v in filtered_output[0].items() if k in expected_result}
self.assertDictEqual(result_output, expected_result)
8 changes: 6 additions & 2 deletions erpnext/accounts/report/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,9 @@ def get_journal_entries(filters, args):
)
.orderby(je.posting_date, je.name, order=Order.desc)
)
query = apply_common_conditions(filters, query, doctype="Journal Entry", payments=True)
query = apply_common_conditions(
filters, query, doctype="Journal Entry", child_doctype="Journal Entry Account", payments=True
)

journal_entries = query.run(as_dict=True)
return journal_entries
Expand Down Expand Up @@ -306,7 +308,9 @@ def apply_common_conditions(filters, query, doctype, child_doctype=None, payment
query = query.where(parent_doc.posting_date <= filters.to_date)

if payments:
if filters.get("cost_center"):
if doctype == "Journal Entry" and filters.get("cost_center"):
query = query.where(child_doc.cost_center == filters.cost_center)
elif filters.get("cost_center"):
query = query.where(parent_doc.cost_center == filters.cost_center)
else:
if filters.get("cost_center"):
Expand Down
6 changes: 4 additions & 2 deletions erpnext/buying/doctype/purchase_order/purchase_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,9 +456,11 @@ def update_ordered_qty_in_so_for_removed_items(self, removed_items):
if not self.is_against_so():
return
for item in removed_items:
prev_ordered_qty = frappe.get_cached_value(
"Sales Order Item", item.get("sales_order_item"), "ordered_qty"
prev_ordered_qty = (
frappe.get_cached_value("Sales Order Item", item.get("sales_order_item"), "ordered_qty")
or 0.0
)

frappe.db.set_value(
"Sales Order Item", item.get("sales_order_item"), "ordered_qty", prev_ordered_qty - item.qty
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def get_data():
},
{
"label": _("Sub-contracting"),
"items": ["Subcontracting Order", "Subcontracting Receipt", "Stock Entry"],
"items": ["Subcontracting Order", "Stock Entry"],
},
{"label": _("Internal"), "items": ["Sales Order"]},
],
Expand Down
3 changes: 2 additions & 1 deletion erpnext/controllers/status_updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ def validate_status(status, options):
],
"Purchase Receipt": [
["Draft", None],
["To Bill", "eval:self.per_billed < 100 and self.docstatus == 1"],
["To Bill", "eval:self.per_billed == 0 and self.docstatus == 1"],
["Partly Billed", "eval:self.per_billed > 0 and self.per_billed < 100 and self.docstatus == 1"],
["Return Issued", "eval:self.per_returned == 100 and self.docstatus == 1"],
["Completed", "eval:self.per_billed == 100 and self.docstatus == 1"],
["Cancelled", "eval:self.docstatus==2"],
Expand Down
4 changes: 2 additions & 2 deletions erpnext/projects/doctype/task/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,14 +118,14 @@ def validate_dependencies_for_template_task(self):
def validate_parent_template_task(self):
if self.parent_task:
if not frappe.db.get_value("Task", self.parent_task, "is_template"):
parent_task_format = f"""<a href="#Form/Task/{self.parent_task}">{self.parent_task}</a>"""
parent_task_format = f"""<a href="/app/task/{self.parent_task}">{self.parent_task}</a>"""
frappe.throw(_("Parent Task {0} is not a Template Task").format(parent_task_format))

def validate_depends_on_tasks(self):
if self.depends_on:
for task in self.depends_on:
if not frappe.db.get_value("Task", task.task, "is_template"):
dependent_task_format = f"""<a href="#Form/Task/{task.task}">{task.task}</a>"""
dependent_task_format = f"""<a href="/app/task/{task.task}">{task.task}</a>"""
frappe.throw(_("Dependent Task {0} is not a Template Task").format(dependent_task_format))

def validate_completed_on(self):
Expand Down
13 changes: 9 additions & 4 deletions erpnext/public/js/controllers/transaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -822,9 +822,14 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe

if (frappe.meta.get_docfield(this.frm.doctype, "shipping_address") &&
['Purchase Order', 'Purchase Receipt', 'Purchase Invoice'].includes(this.frm.doctype)) {
erpnext.utils.get_shipping_address(this.frm, function() {
set_party_account(set_pricing);
});
let is_drop_ship = me.frm.doc.items.some(item => item.delivered_by_supplier);

if (!is_drop_ship) {
console.log('get_shipping_address');
erpnext.utils.get_shipping_address(this.frm, function() {
set_party_account(set_pricing);
});
}

} else {
set_party_account(set_pricing);
Expand Down Expand Up @@ -2213,7 +2218,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
payment_terms_template() {
var me = this;
const doc = this.frm.doc;
if(doc.payment_terms_template && doc.doctype !== 'Delivery Note' && doc.is_return == 0) {
if(doc.payment_terms_template && doc.doctype !== 'Delivery Note' && !doc.is_return) {
var posting_date = doc.posting_date || doc.transaction_date;
frappe.call({
method: "erpnext.controllers.accounts_controller.get_payment_terms",
Expand Down
16 changes: 13 additions & 3 deletions erpnext/selling/doctype/sales_order/sales_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -1035,6 +1035,8 @@ def update_item(source, target, source_parent):
"discount_percentage",
"discount_amount",
"pricing_rules",
"margin_type",
"margin_rate_or_amount",
],
"postprocess": update_item,
"condition": lambda doc: doc.ordered_qty < doc.stock_qty
Expand Down Expand Up @@ -1088,9 +1090,17 @@ def set_missing_values(source, target):
target.payment_schedule = []

if is_drop_ship_order(target):
target.customer = source.customer
target.customer_name = source.customer_name
target.shipping_address = source.shipping_address_name
if source.shipping_address_name:
target.shipping_address = source.shipping_address_name
target.shipping_address_display = source.shipping_address
else:
target.shipping_address = source.customer_address
target.shipping_address_display = source.address_display

target.customer_contact_person = source.contact_person
target.customer_contact_display = source.contact_display
target.customer_contact_mobile = source.contact_mobile
target.customer_contact_email = source.contact_email
else:
target.customer = target.customer_name = target.shipping_address = None

Expand Down
2 changes: 1 addition & 1 deletion erpnext/stock/doctype/pick_list/pick_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def validate_stock_qty(self):
"actual_qty",
)

if row.qty > bin_qty:
if row.qty > flt(bin_qty):
frappe.throw(
_(
"At Row #{0}: The picked quantity {1} for the item {2} is greater than available stock {3} in the warehouse {4}."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -885,7 +885,7 @@
"no_copy": 1,
"oldfieldname": "status",
"oldfieldtype": "Select",
"options": "\nDraft\nTo Bill\nCompleted\nReturn Issued\nCancelled\nClosed",
"options": "\nDraft\nPartly Billed\nTo Bill\nCompleted\nReturn Issued\nCancelled\nClosed",
"print_hide": 1,
"print_width": "150px",
"read_only": 1,
Expand Down Expand Up @@ -1242,7 +1242,7 @@
"idx": 261,
"is_submittable": 1,
"links": [],
"modified": "2024-03-20 16:05:31.713453",
"modified": "2024-11-13 16:55:14.129055",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt",
Expand Down
11 changes: 9 additions & 2 deletions erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
Original file line number Diff line number Diff line change
Expand Up @@ -883,17 +883,24 @@ def get_billed_amount_against_po(po_items):

def update_billing_percentage(pr_doc, update_modified=True, adjust_incoming_rate=False):
# Update Billing % based on pending accepted qty
buying_settings = frappe.get_single("Buying Settings")

total_amount, total_billed_amount = 0, 0
item_wise_returned_qty = get_item_wise_returned_qty(pr_doc)

for item in pr_doc.items:
returned_qty = flt(item_wise_returned_qty.get(item.name))
returned_amount = flt(returned_qty) * flt(item.rate)
pending_amount = flt(item.amount) - returned_amount
total_billable_amount = pending_amount if item.billed_amt <= pending_amount else item.billed_amt
if buying_settings.bill_for_rejected_quantity_in_purchase_invoice:
pending_amount = flt(item.amount)

total_billable_amount = abs(flt(item.amount))
if pending_amount > 0:
total_billable_amount = pending_amount if item.billed_amt <= pending_amount else item.billed_amt

total_amount += total_billable_amount
total_billed_amount += flt(item.billed_amt)
total_billed_amount += abs(flt(item.billed_amt))

if pr_doc.get("is_return") and not total_amount and total_billed_amount:
total_amount = total_billed_amount
Expand Down
Loading
Loading