Date: Mon, 23 May 2022 10:08:20 +0530
Subject: [PATCH 08/48] fix: Use directly and style it as button instead of
using button
Since few email servers (like outlook) strips out link in the button making them unclickable.
(cherry picked from commit a29b92febc4397cebb251d4d3f34210e4fb85c21)
---
.../emails/request_for_quotation.html | 37 +++++++++++--------
1 file changed, 21 insertions(+), 16 deletions(-)
diff --git a/erpnext/templates/emails/request_for_quotation.html b/erpnext/templates/emails/request_for_quotation.html
index 3283987fab05..5b073e604ff9 100644
--- a/erpnext/templates/emails/request_for_quotation.html
+++ b/erpnext/templates/emails/request_for_quotation.html
@@ -1,24 +1,29 @@
{{_("Request for Quotation")}}
{{ supplier_salutation if supplier_salutation else ''}} {{ supplier_name }},
{{ message }}
-
{{_("The Request for Quotation can be accessed by clicking on the following button")}}:
-
-
- Submit your Quotation
-
-
-
-{{_("Regards")}},
-{{ user_fullname }}
-
+
+
+ {{ _("Submit your Quotation") }}
+
+
+
{% if update_password_link %}
-
+
{{_("Please click on the following button to set your new password")}}:
+
+ {{_("Set Password") }}
+
+
+
+{% endif %}
-
- {{_("Update Password") }}
-
+ {{_("Regards")}},
+ {{ user_fullname }}
-
-{% endif %}
From ddee0893e62d3392d288455c963efc93d0b126b3 Mon Sep 17 00:00:00 2001
From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com>
Date: Mon, 23 May 2022 12:02:30 +0530
Subject: [PATCH 09/48] fix translation German "Designation" (backport #31082)
(#31093)
fix translation German "Designation" (#31082)
changed "Bezeichnung" to "Position" as the is more precice in the field of employment which erpnext refers to here
(cherry picked from commit 348a674df968dd9fe754fc8e85eef9cb51c227f4)
Co-authored-by: Wolfram Schmidt
---
erpnext/translations/de.csv | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv
index 329fd3b1b9cb..545d0dde0447 100644
--- a/erpnext/translations/de.csv
+++ b/erpnext/translations/de.csv
@@ -1695,7 +1695,7 @@ No Permission,Keine Berechtigung,
No Remarks,Keine Anmerkungen,
No Result to submit,Kein Ergebnis zur Einreichung,
No Salary Structure assigned for Employee {0} on given date {1},Keine Gehaltsstruktur für Mitarbeiter {0} am angegebenen Datum {1} zugewiesen,
-No Staffing Plans found for this Designation,Für diese Bezeichnung wurden keine Stellenpläne gefunden,
+No Staffing Plans found for this Designation,Für diese Position wurden keine Stellenpläne gefunden,
No Student Groups created.,Keine Studentengruppen erstellt.,
No Students in,Keine Studenten in,
No Tax Withholding data found for the current Fiscal Year.,Keine Steuerverweigerungsdaten für das aktuelle Geschäftsjahr gefunden.,
@@ -2021,7 +2021,7 @@ Please select BOM in BOM field for Item {0},Bitte aus dem Stücklistenfeld eine
Please select Category first,Bitte zuerst Kategorie auswählen,
Please select Charge Type first,Bitte zuerst Chargentyp auswählen,
Please select Company,Bitte Unternehmen auswählen,
-Please select Company and Designation,Bitte wählen Sie Unternehmen und Stelle,
+Please select Company and Designation,Bitte wählen Sie Unternehmen und Position,
Please select Company and Posting Date to getting entries,"Bitte wählen Sie Unternehmen und Buchungsdatum, um Einträge zu erhalten",
Please select Company first,Bitte zuerst Unternehmen auswählen,
Please select Completion Date for Completed Asset Maintenance Log,Bitte wählen Sie Fertigstellungsdatum für das abgeschlossene Wartungsprotokoll für den Vermögenswert,
@@ -2765,7 +2765,7 @@ Split,Teilt,
Split Batch,Split Batch,
Split Issue,Split-Problem,
Sports,Sport,
-Staffing Plan {0} already exist for designation {1},Personalplan {0} existiert bereits für Bezeichnung {1},
+Staffing Plan {0} already exist for designation {1},Personalplan {0} existiert bereits für Position {1},
Standard,Standard,
Standard Buying,Standard-Kauf,
Standard Selling,Standard-Vertrieb,
@@ -3703,7 +3703,7 @@ Delivered Quantity,Gelieferte Menge,
Delivery Notes,Lieferscheine,
Depreciated Amount,Abschreibungsbetrag,
Description,Beschreibung,
-Designation,Bezeichnung,
+Designation,Position,
Difference Value,Differenzwert,
Dimension Filter,Dimensionsfilter,
Disabled,Deaktiviert,
@@ -3913,7 +3913,7 @@ Please enter Difference Account or set default Stock Adjustment Accoun
Please enter GSTIN and state for the Company Address {0},Bitte geben Sie GSTIN ein und geben Sie die Firmenadresse {0} an.,
Please enter Item Code to get item taxes,"Bitte geben Sie den Artikelcode ein, um die Artikelsteuern zu erhalten",
Please enter Warehouse and Date,Bitte geben Sie Lager und Datum ein,
-Please enter the designation,Bitte geben Sie die Bezeichnung ein,
+Please enter the designation,Bitte geben Sie die Position ein,
Please login as a Marketplace User to edit this item.,"Bitte melden Sie sich als Marketplace-Benutzer an, um diesen Artikel zu bearbeiten.",
Please login as a Marketplace User to report this item.,"Bitte melden Sie sich als Marketplace-Benutzer an, um diesen Artikel zu melden.",
Please select Template Type to download template,"Bitte wählen Sie Vorlagentyp , um die Vorlage herunterzuladen",
@@ -6235,7 +6235,7 @@ Checking this will create Lab Test(s) specified in the Sales Invoice on submissi
Create Sample Collection document for Lab Test,Erstellen Sie ein Probensammeldokument für den Labortest,
Checking this will create a Sample Collection document every time you create a Lab Test,"Wenn Sie dies aktivieren, wird jedes Mal, wenn Sie einen Labortest erstellen, ein Probensammeldokument erstellt",
Employee name and designation in print,Name und Bezeichnung des Mitarbeiters im Druck,
-Check this if you want the Name and Designation of the Employee associated with the User who submits the document to be printed in the Lab Test Report.,"Aktivieren Sie diese Option, wenn Sie möchten, dass der Name und die Bezeichnung des Mitarbeiters, der dem Benutzer zugeordnet ist, der das Dokument einreicht, im Labortestbericht gedruckt werden.",
+Check this if you want the Name and Designation of the Employee associated with the User who submits the document to be printed in the Lab Test Report.,"Aktivieren Sie diese Option, wenn Sie möchten, dass der Name und die Position des Mitarbeiters, der dem Benutzer zugeordnet ist, der das Dokument einreicht, im Labortestbericht gedruckt werden.",
Do not print or email Lab Tests without Approval,Drucken oder senden Sie Labortests nicht ohne Genehmigung per E-Mail,
Checking this will restrict printing and emailing of Lab Test documents unless they have the status as Approved.,"Wenn Sie dies aktivieren, wird das Drucken und E-Mailen von Labortestdokumenten eingeschränkt, sofern diese nicht den Status "Genehmigt" haben.",
Custom Signature in Print,Kundenspezifische Unterschrift im Druck,
@@ -6491,7 +6491,7 @@ Department Approver,Abteilungsgenehmiger,
Approver,Genehmiger,
Required Skills,Benötigte Fähigkeiten,
Skills,Kompetenzen,
-Designation Skill,Bezeichnung Fähigkeit,
+Designation Skill,Positions Fähigkeit,
Skill,Fertigkeit,
Driver,Fahrer/-in,
HR-DRI-.YYYY.-,HR-DRI-.YYYY.-,
@@ -6790,7 +6790,7 @@ Select Employees,Mitarbeiter auswählen,
Employment Type (optional),Anstellungsart (optional),
Branch (optional),Zweigstelle (optional),
Department (optional),Abteilung (optional),
-Designation (optional),Bezeichnung (optional),
+Designation (optional),Position (optional),
Employee Grade (optional),Dienstgrad (optional),
Employee (optional),Mitarbeiter (optional),
Allocate Leaves,Blätter zuweisen,
@@ -7761,7 +7761,7 @@ Authorized Value,Autorisierter Wert,
Applicable To (Role),Anwenden auf (Rolle),
Applicable To (Employee),Anwenden auf (Mitarbeiter),
Applicable To (User),Anwenden auf (Benutzer),
-Applicable To (Designation),Anwenden auf (Bezeichnung),
+Applicable To (Designation),Anwenden auf (Position),
Approving Role (above authorized value),Genehmigende Rolle (über dem autorisierten Wert),
Approving User (above authorized value),Genehmigender Benutzer (über dem autorisierten Wert),
Brand Defaults,Markenstandards,
@@ -8937,7 +8937,7 @@ Requesting Practitioner,Praktizierender anfordern,
Requesting Department,Abteilung anfordern,
Employee (Lab Technician),Mitarbeiter (Labortechniker),
Lab Technician Name,Name des Labortechnikers,
-Lab Technician Designation,Bezeichnung des Labortechnikers,
+Lab Technician Designation,Position des Labortechnikers,
Compound Test Result,Zusammengesetztes Testergebnis,
Organism Test Result,Organismustestergebnis,
Sensitivity Test Result,Empfindlichkeitstestergebnis,
From f6b2f36ca80c85490a12a5c61a9042028fff59ae Mon Sep 17 00:00:00 2001
From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com>
Date: Mon, 23 May 2022 15:13:13 +0530
Subject: [PATCH 10/48] test: search test failing because of stale data
(backport #31098) (#31099)
test: search test failing because of stale data (#31098)
(cherry picked from commit a36174afdf09e70e636aca2125a6cb092fb24735)
Co-authored-by: Ankush Menat
---
erpnext/tests/test_search.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/erpnext/tests/test_search.py b/erpnext/tests/test_search.py
index ffe9a5ae5410..3685828667ca 100644
--- a/erpnext/tests/test_search.py
+++ b/erpnext/tests/test_search.py
@@ -8,6 +8,7 @@ class TestSearch(unittest.TestCase):
# Search for the word "cond", part of the word "conduire" (Lead) in french.
def test_contact_search_in_foreign_language(self):
try:
+ frappe.local.lang_full_dict = None # reset cached translations
frappe.local.lang = "fr"
output = filter_dynamic_link_doctypes(
"DocType", "cond", "name", 0, 20, {"fieldtype": "HTML", "fieldname": "contact_html"}
From 3984f04a49649b168c4a6cef29c444e25d1415a3 Mon Sep 17 00:00:00 2001
From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com>
Date: Mon, 23 May 2022 15:20:47 +0530
Subject: [PATCH 11/48] fix: Job Card excess transfer behaviour (backport
#31054) (#31096)
* fix: Job Card excess transfer behaviour
- Block excess transfer of items if not allowed in settings
- Behaviour made consistent with js behaviour (button disappears if not pending and not allowed in settings)
- Test for same case
(cherry picked from commit e07ce6efe0afde1bdbade6cbed9f53ac0dd236f0)
# Conflicts:
# erpnext/manufacturing/doctype/job_card/test_job_card.py
* chore: Run `_validate_over_transfer` only if excess transfer is blocked in settings
(cherry picked from commit 9f6e10663b77489ba1f98ede96e30c23682c111a)
* chore: conflicts
* chore: missing conflict resolution changes
Co-authored-by: marination
Co-authored-by: Ankush Menat
---
.../doctype/job_card/job_card.py | 51 +++++++++++++++----
.../doctype/job_card/test_job_card.py | 26 ++++++++++
.../stock/doctype/stock_entry/stock_entry.py | 2 +-
3 files changed, 68 insertions(+), 11 deletions(-)
diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py
index fcdda33b7fb3..cc2f8c60e586 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card.py
+++ b/erpnext/manufacturing/doctype/job_card/job_card.py
@@ -42,6 +42,10 @@ class JobCardCancelError(frappe.ValidationError):
pass
+class JobCardOverTransferError(frappe.ValidationError):
+ pass
+
+
class JobCard(Document):
def onload(self):
excess_transfer = frappe.db.get_single_value(
@@ -522,23 +526,50 @@ def get_current_operation_data(self):
},
)
- def set_transferred_qty_in_job_card(self, ste_doc):
+ def set_transferred_qty_in_job_card_item(self, ste_doc):
+ from frappe.query_builder.functions import Sum
+
+ def _validate_over_transfer(row, transferred_qty):
+ "Block over transfer of items if not allowed in settings."
+ required_qty = frappe.db.get_value("Job Card Item", row.job_card_item, "required_qty")
+ is_excess = flt(transferred_qty) > flt(required_qty)
+ if is_excess:
+ frappe.throw(
+ _(
+ "Row #{0}: Cannot transfer more than Required Qty {1} for Item {2} against Job Card {3}"
+ ).format(
+ row.idx, frappe.bold(required_qty), frappe.bold(row.item_code), ste_doc.job_card
+ ),
+ title=_("Excess Transfer"),
+ exc=JobCardOverTransferError,
+ )
+
for row in ste_doc.items:
if not row.job_card_item:
continue
- qty = frappe.db.sql(
- """ SELECT SUM(qty) from `tabStock Entry Detail` sed, `tabStock Entry` se
- WHERE sed.job_card_item = %s and se.docstatus = 1 and sed.parent = se.name and
- se.purpose = 'Material Transfer for Manufacture'
- """,
- (row.job_card_item),
- )[0][0]
+ sed = frappe.qb.DocType("Stock Entry Detail")
+ se = frappe.qb.DocType("Stock Entry")
+ transferred_qty = (
+ frappe.qb.from_(sed)
+ .join(se)
+ .on(sed.parent == se.name)
+ .select(Sum(sed.qty))
+ .where(
+ (sed.job_card_item == row.job_card_item)
+ & (se.docstatus == 1)
+ & (se.purpose == "Material Transfer for Manufacture")
+ )
+ ).run()[0][0]
+
+ allow_excess = frappe.db.get_single_value("Manufacturing Settings", "job_card_excess_transfer")
+ if not allow_excess:
+ _validate_over_transfer(row, transferred_qty)
- frappe.db.set_value("Job Card Item", row.job_card_item, "transferred_qty", flt(qty))
+ frappe.db.set_value("Job Card Item", row.job_card_item, "transferred_qty", flt(transferred_qty))
def set_transferred_qty(self, update_status=False):
- "Set total FG Qty for which RM was transferred."
+ "Set total FG Qty in Job Card for which RM was transferred."
if not self.items:
self.transferred_qty = self.for_quantity if self.docstatus == 1 else 0
diff --git a/erpnext/manufacturing/doctype/job_card/test_job_card.py b/erpnext/manufacturing/doctype/job_card/test_job_card.py
index 943bc9737724..b5371af2ccbd 100644
--- a/erpnext/manufacturing/doctype/job_card/test_job_card.py
+++ b/erpnext/manufacturing/doctype/job_card/test_job_card.py
@@ -7,6 +7,7 @@
from frappe.utils.data import add_to_date, now
from erpnext.manufacturing.doctype.job_card.job_card import (
+ JobCardOverTransferError,
OperationMismatchError,
OverlapError,
make_corrective_job_card,
@@ -162,6 +163,7 @@ def test_job_card_multiple_materials_transfer(self):
# transfer was made for 2 fg qty in first transfer Stock Entry
self.assertEqual(transfer_entry_2.fg_completed_qty, 0)
+ @change_settings("Manufacturing Settings", {"job_card_excess_transfer": 1})
def test_job_card_excess_material_transfer(self):
"Test transferring more than required RM against Job Card."
self.transfer_material_against = "Job Card"
@@ -204,6 +206,30 @@ def test_job_card_excess_material_transfer(self):
# JC is Completed with excess transfer
self.assertEqual(job_card.status, "Completed")
+ @change_settings("Manufacturing Settings", {"job_card_excess_transfer": 0})
+ def test_job_card_excess_material_transfer_block(self):
+
+ self.transfer_material_against = "Job Card"
+ self.source_warehouse = "Stores - _TC"
+
+ self.generate_required_stock(self.work_order)
+
+ job_card_name = frappe.db.get_value("Job Card", {"work_order": self.work_order.name})
+
+ # fully transfer both RMs
+ transfer_entry_1 = make_stock_entry_from_jc(job_card_name)
+ transfer_entry_1.insert()
+ transfer_entry_1.submit()
+
+ # transfer extra qty of both RM due to previously damaged RM
+ transfer_entry_2 = make_stock_entry_from_jc(job_card_name)
+ # deliberately change 'For Quantity'
+ transfer_entry_2.fg_completed_qty = 1
+ transfer_entry_2.items[0].qty = 5
+ transfer_entry_2.items[1].qty = 3
+ transfer_entry_2.insert()
+ self.assertRaises(JobCardOverTransferError, transfer_entry_2.submit)
+
def test_job_card_partial_material_transfer(self):
"Test partial material transfer against Job Card"
self.transfer_material_against = "Job Card"
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 70161d763390..52011afefd18 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -1137,7 +1137,7 @@ def _validate_work_order(pro_doc):
if self.job_card:
job_doc = frappe.get_doc("Job Card", self.job_card)
job_doc.set_transferred_qty(update_status=True)
- job_doc.set_transferred_qty_in_job_card(self)
+ job_doc.set_transferred_qty_in_job_card_item(self)
if self.work_order:
pro_doc = frappe.get_doc("Work Order", self.work_order)
From c2a08f1285638c8f0cfa267fee5e306407b4dc73 Mon Sep 17 00:00:00 2001
From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com>
Date: Tue, 24 May 2022 10:41:50 +0530
Subject: [PATCH 12/48] chore: error logging for auto material requests
(backport #31103) (#31105)
chore: error logging for auto material requests (#31103)
(cherry picked from commit ecb39d81e021f786f5a4ded3c344cf4f5c71bc26)
Co-authored-by: Ankush Menat
---
erpnext/stock/reorder_item.py | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/erpnext/stock/reorder_item.py b/erpnext/stock/reorder_item.py
index a96ffefd474b..f2594f65fab9 100644
--- a/erpnext/stock/reorder_item.py
+++ b/erpnext/stock/reorder_item.py
@@ -253,11 +253,14 @@ def notify_errors(exceptions_list):
)
for exception in exceptions_list:
- exception = json.loads(exception)
- error_message = """{0}
""".format(
- _(exception.get("message"))
- )
- content += error_message
+ try:
+ exception = json.loads(exception)
+ error_message = """{0}
""".format(
+ _(exception.get("message"))
+ )
+ content += error_message
+ except Exception:
+ pass
content += _("Regards,") + " " + _("Administrator")
From 42e7a86a3b86672dc1cd102b7452ce1b85ce2957 Mon Sep 17 00:00:00 2001
From: Rucha Mahabal
Date: Tue, 18 Jan 2022 14:36:22 +0530
Subject: [PATCH 13/48] feat(Employee Advance): add 'Returned' and 'Partly
Claimed and Returned' status
---
.../employee_advance/employee_advance.json | 42 +++++++++++++++--
.../employee_advance/employee_advance.py | 47 ++++++++++++++-----
.../hr/doctype/expense_claim/expense_claim.js | 2 +-
.../hr/doctype/expense_claim/expense_claim.py | 34 +++++++-------
4 files changed, 92 insertions(+), 33 deletions(-)
diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.json b/erpnext/hr/doctype/employee_advance/employee_advance.json
index 3a561216ccae..1b838ad98638 100644
--- a/erpnext/hr/doctype/employee_advance/employee_advance.json
+++ b/erpnext/hr/doctype/employee_advance/employee_advance.json
@@ -2,7 +2,7 @@
"actions": [],
"allow_import": 1,
"autoname": "naming_series:",
- "creation": "2017-10-09 14:26:29.612365",
+ "creation": "2022-01-17 18:36:51.450395",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
@@ -121,7 +121,7 @@
"fieldtype": "Select",
"label": "Status",
"no_copy": 1,
- "options": "Draft\nPaid\nUnpaid\nClaimed\nCancelled",
+ "options": "Draft\nPaid\nUnpaid\nClaimed\nReturned\nPartly Claimed and Returned\nCancelled",
"read_only": 1
},
{
@@ -200,7 +200,7 @@
],
"is_submittable": 1,
"links": [],
- "modified": "2021-09-11 18:38:38.617478",
+ "modified": "2022-01-17 19:33:52.345823",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee Advance",
@@ -236,5 +236,41 @@
"search_fields": "employee,employee_name",
"sort_field": "modified",
"sort_order": "DESC",
+ "states": [
+ {
+ "color": "Red",
+ "custom": 1,
+ "title": "Draft"
+ },
+ {
+ "color": "Green",
+ "custom": 1,
+ "title": "Paid"
+ },
+ {
+ "color": "Orange",
+ "custom": 1,
+ "title": "Unpaid"
+ },
+ {
+ "color": "Blue",
+ "custom": 1,
+ "title": "Claimed"
+ },
+ {
+ "color": "Gray",
+ "title": "Returned"
+ },
+ {
+ "color": "Yellow",
+ "title": "Partly Claimed and Returned"
+ },
+ {
+ "color": "Red",
+ "custom": 1,
+ "title": "Cancelled"
+ }
+ ],
+ "title_field": "employee_name",
"track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.py b/erpnext/hr/doctype/employee_advance/employee_advance.py
index 3d4023d3195a..7605d209ad14 100644
--- a/erpnext/hr/doctype/employee_advance/employee_advance.py
+++ b/erpnext/hr/doctype/employee_advance/employee_advance.py
@@ -30,18 +30,41 @@ def validate(self):
def on_cancel(self):
self.ignore_linked_doctypes = "GL Entry"
- def set_status(self):
+ def set_status(self, update=False):
+ precision = self.precision("paid_amount")
+ total_amount = flt(flt(self.claimed_amount) + flt(self.return_amount), precision)
+ status = None
+
if self.docstatus == 0:
- self.status = "Draft"
- if self.docstatus == 1:
- if self.claimed_amount and flt(self.claimed_amount) == flt(self.paid_amount):
- self.status = "Claimed"
- elif self.paid_amount and self.advance_amount == flt(self.paid_amount):
- self.status = "Paid"
+ status = "Draft"
+ elif self.docstatus == 1:
+ if flt(self.claimed_amount) > 0 and flt(self.claimed_amount, precision) == flt(
+ self.paid_amount, precision
+ ):
+ status = "Claimed"
+ elif flt(self.return_amount) > 0 and flt(self.return_amount, precision) == flt(
+ self.paid_amount, precision
+ ):
+ status = "Returned"
+ elif (
+ flt(self.claimed_amount) > 0
+ and (flt(self.return_amount) > 0)
+ and total_amount == flt(self.paid_amount, precision)
+ ):
+ status = "Partly Claimed and Returned"
+ elif flt(self.paid_amount) > 0 and flt(self.advance_amount, precision) == flt(
+ self.paid_amount, precision
+ ):
+ status = "Paid"
else:
- self.status = "Unpaid"
+ status = "Unpaid"
elif self.docstatus == 2:
- self.status = "Cancelled"
+ status = "Cancelled"
+
+ if update:
+ self.db_set("status", status)
+ else:
+ self.status = status
def set_total_advance_paid(self):
gle = frappe.qb.DocType("GL Entry")
@@ -89,8 +112,7 @@ def set_total_advance_paid(self):
self.db_set("paid_amount", paid_amount)
self.db_set("return_amount", return_amount)
- self.set_status()
- frappe.db.set_value("Employee Advance", self.name, "status", self.status)
+ self.set_status(update=True)
def update_claimed_amount(self):
claimed_amount = (
@@ -112,8 +134,7 @@ def update_claimed_amount(self):
frappe.db.set_value("Employee Advance", self.name, "claimed_amount", flt(claimed_amount))
self.reload()
- self.set_status()
- frappe.db.set_value("Employee Advance", self.name, "status", self.status)
+ self.set_status(update=True)
@frappe.whitelist()
diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.js b/erpnext/hr/doctype/expense_claim/expense_claim.js
index 047945787d7b..af80b63845e8 100644
--- a/erpnext/hr/doctype/expense_claim/expense_claim.js
+++ b/erpnext/hr/doctype/expense_claim/expense_claim.js
@@ -171,7 +171,7 @@ frappe.ui.form.on("Expense Claim", {
['docstatus', '=', 1],
['employee', '=', frm.doc.employee],
['paid_amount', '>', 0],
- ['status', '!=', 'Claimed']
+ ['status', 'not in', ['Claimed', 'Returned', 'Partly Claimed and Returned']]
]
};
});
diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.py b/erpnext/hr/doctype/expense_claim/expense_claim.py
index 311a1eb81c80..89d86c1bc7ce 100644
--- a/erpnext/hr/doctype/expense_claim/expense_claim.py
+++ b/erpnext/hr/doctype/expense_claim/expense_claim.py
@@ -414,25 +414,27 @@ def get_expense_claim_account(expense_claim_type, company):
@frappe.whitelist()
def get_advances(employee, advance_id=None):
+ advance = frappe.qb.DocType("Employee Advance")
+
+ query = frappe.qb.from_(advance).select(
+ advance.name,
+ advance.posting_date,
+ advance.paid_amount,
+ advance.claimed_amount,
+ advance.advance_account,
+ )
+
if not advance_id:
- condition = "docstatus=1 and employee={0} and paid_amount > 0 and paid_amount > claimed_amount + return_amount".format(
- frappe.db.escape(employee)
+ query = query.where(
+ (advance.docstatus == 1)
+ & (advance.employee == employee)
+ & (advance.paid_amount > 0)
+ & (advance.status.notin(["Claimed", "Returned", "Partly Claimed and Returned"]))
)
else:
- condition = "name={0}".format(frappe.db.escape(advance_id))
-
- return frappe.db.sql(
- """
- select
- name, posting_date, paid_amount, claimed_amount, advance_account
- from
- `tabEmployee Advance`
- where {0}
- """.format(
- condition
- ),
- as_dict=1,
- )
+ query = query.where(advance.name == advance_id)
+
+ return query.run(as_dict=True)
@frappe.whitelist()
From cac9e245b62a4f35c78720c2a250ce5c687be35d Mon Sep 17 00:00:00 2001
From: Rucha Mahabal
Date: Tue, 18 Jan 2022 14:36:38 +0530
Subject: [PATCH 14/48] patch: Employee Advance return statuses
---
erpnext/patches.txt | 2 ++
.../v13_0/update_employee_advance_status.py | 29 +++++++++++++++++++
2 files changed, 31 insertions(+)
create mode 100644 erpnext/patches/v13_0/update_employee_advance_status.py
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 1ff33c7f7bfb..85780501def6 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -366,3 +366,5 @@ erpnext.patches.v13_0.education_deprecation_warning
erpnext.patches.v13_0.requeue_recoverable_reposts
erpnext.patches.v13_0.create_accounting_dimensions_in_orders
erpnext.patches.v13_0.set_per_billed_in_return_delivery_note
+erpnext.patches.v13_0.update_employee_advance_status
+
diff --git a/erpnext/patches/v13_0/update_employee_advance_status.py b/erpnext/patches/v13_0/update_employee_advance_status.py
new file mode 100644
index 000000000000..fc9e05e836d2
--- /dev/null
+++ b/erpnext/patches/v13_0/update_employee_advance_status.py
@@ -0,0 +1,29 @@
+import frappe
+
+
+def execute():
+ frappe.reload_doc("hr", "doctype", "employee_advance")
+
+ advance = frappe.qb.DocType("Employee Advance")
+ (
+ frappe.qb.update(advance)
+ .set(advance.status, "Returned")
+ .where(
+ (advance.docstatus == 1)
+ & ((advance.return_amount) & (advance.paid_amount == advance.return_amount))
+ & (advance.status == "Paid")
+ )
+ ).run()
+
+ (
+ frappe.qb.update(advance)
+ .set(advance.status, "Partly Claimed and Returned")
+ .where(
+ (advance.docstatus == 1)
+ & (
+ (advance.claimed_amount & advance.return_amount)
+ & (advance.paid_amount == (advance.return_amount + advance.claimed_amount))
+ )
+ & (advance.status == "Paid")
+ )
+ ).run()
From d59c3d21423639c13055309ec30bfc2b04c44545 Mon Sep 17 00:00:00 2001
From: Rucha Mahabal
Date: Tue, 18 Jan 2022 14:38:16 +0530
Subject: [PATCH 15/48] fix: employee advance status update on return via
additional salary
---
erpnext/payroll/doctype/additional_salary/additional_salary.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/erpnext/payroll/doctype/additional_salary/additional_salary.py b/erpnext/payroll/doctype/additional_salary/additional_salary.py
index f57d9d37cf1e..18bd3b7733c0 100644
--- a/erpnext/payroll/doctype/additional_salary/additional_salary.py
+++ b/erpnext/payroll/doctype/additional_salary/additional_salary.py
@@ -124,6 +124,8 @@ def update_return_amount_in_employee_advance(self):
return_amount += self.amount
frappe.db.set_value("Employee Advance", self.ref_docname, "return_amount", return_amount)
+ advance = frappe.get_doc("Employee Advance", self.ref_docname)
+ advance.set_status(update=True)
def update_employee_referral(self, cancel=False):
if self.ref_doctype == "Employee Referral":
From 806752111eadbe7b3679d13620c64dc38488ae50 Mon Sep 17 00:00:00 2001
From: Rucha Mahabal
Date: Tue, 18 Jan 2022 18:35:25 +0530
Subject: [PATCH 16/48] test: employee advance status
---
.../employee_advance/employee_advance.py | 2 +
.../employee_advance/test_employee_advance.py | 77 +++++++++++++++++++
2 files changed, 79 insertions(+)
diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.py b/erpnext/hr/doctype/employee_advance/employee_advance.py
index 7605d209ad14..2378482364df 100644
--- a/erpnext/hr/doctype/employee_advance/employee_advance.py
+++ b/erpnext/hr/doctype/employee_advance/employee_advance.py
@@ -286,6 +286,7 @@ def make_return_entry(
"party_type": "Employee",
"party": employee,
"is_advance": "Yes",
+ "cost_center": erpnext.get_default_cost_center(company),
},
)
@@ -303,6 +304,7 @@ def make_return_entry(
"account_currency": bank_cash_account.account_currency,
"account_type": bank_cash_account.account_type,
"exchange_rate": flt(exchange_rate) if bank_cash_account.account_currency == currency else 1,
+ "cost_center": erpnext.get_default_cost_center(company),
},
)
diff --git a/erpnext/hr/doctype/employee_advance/test_employee_advance.py b/erpnext/hr/doctype/employee_advance/test_employee_advance.py
index 9b006ffcffe5..a8ff6a794d6c 100644
--- a/erpnext/hr/doctype/employee_advance/test_employee_advance.py
+++ b/erpnext/hr/doctype/employee_advance/test_employee_advance.py
@@ -12,8 +12,13 @@
EmployeeAdvanceOverPayment,
create_return_through_additional_salary,
make_bank_entry,
+ make_return_entry,
)
from erpnext.hr.doctype.expense_claim.expense_claim import get_advances
+from erpnext.hr.doctype.expense_claim.test_expense_claim import (
+ get_payable_account,
+ make_expense_claim,
+)
from erpnext.payroll.doctype.salary_component.test_salary_component import create_salary_component
from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure
@@ -53,9 +58,79 @@ def test_paid_amount_on_pe_cancellation(self):
self.assertEqual(advance.paid_amount, 0)
self.assertEqual(advance.status, "Unpaid")
+ def test_claimed_and_returned_status(self):
+ # Claimed Status check, full amount claimed
+ payable_account = get_payable_account("_Test Company")
+ claim = make_expense_claim(
+ payable_account, 1000, 1000, "_Test Company", "Travel Expenses - _TC", do_not_submit=True
+ )
+
+ advance = make_employee_advance(claim.employee)
+ pe = make_payment_entry(advance)
+ pe.submit()
+
+ claim = get_advances_for_claim(claim, advance.name)
+ claim.save()
+ claim.submit()
+
+ advance.reload()
+ self.assertEqual(advance.claimed_amount, 1000)
+ self.assertEqual(advance.status, "Claimed")
+
+ # cancel claim; status should be Paid
+ claim.cancel()
+ advance.reload()
+ self.assertEqual(advance.claimed_amount, 0)
+ self.assertEqual(advance.status, "Paid")
+
+ # Partly Claimed and Returned status check
+ # 500 Claimed, 500 Returned
+ claim = make_expense_claim(
+ payable_account, 500, 500, "_Test Company", "Travel Expenses - _TC", do_not_submit=True
+ )
+
+ advance = make_employee_advance(claim.employee)
+ pe = make_payment_entry(advance)
+ pe.submit()
+
+ claim = get_advances_for_claim(claim, advance.name, amount=500)
+ claim.save()
+ claim.submit()
+
+ advance.reload()
+ self.assertEqual(advance.claimed_amount, 500)
+ self.assertEqual(advance.status, "Paid")
+
+ entry = make_return_entry(
+ employee=advance.employee,
+ company=advance.company,
+ employee_advance_name=advance.name,
+ return_amount=flt(advance.paid_amount - advance.claimed_amount),
+ advance_account=advance.advance_account,
+ mode_of_payment=advance.mode_of_payment,
+ currency=advance.currency,
+ exchange_rate=advance.exchange_rate,
+ )
+
+ entry = frappe.get_doc(entry)
+ entry.insert()
+ entry.submit()
+
+ advance.reload()
+ self.assertEqual(advance.return_amount, 500)
+ self.assertEqual(advance.status, "Partly Claimed and Returned")
+
+ # Cancel return entry; status should change to Paid
+ entry.cancel()
+ advance.reload()
+ self.assertEqual(advance.return_amount, 0)
+ self.assertEqual(advance.status, "Paid")
+
def test_repay_unclaimed_amount_from_salary(self):
employee_name = make_employee("_T@employe.advance")
advance = make_employee_advance(employee_name, {"repay_unclaimed_amount_from_salary": 1})
+ pe = make_payment_entry(advance)
+ pe.submit()
args = {"type": "Deduction"}
create_salary_component("Advance Salary - Deduction", **args)
@@ -85,11 +160,13 @@ def test_repay_unclaimed_amount_from_salary(self):
advance.reload()
self.assertEqual(advance.return_amount, 1000)
+ self.assertEqual(advance.status, "Returned")
# update advance return amount on additional salary cancellation
additional_salary.cancel()
advance.reload()
self.assertEqual(advance.return_amount, 700)
+ self.assertEqual(advance.status, "Paid")
def tearDown(self):
frappe.db.rollback()
From b265ca467c6ff2d406786fb43b1c96281644b007 Mon Sep 17 00:00:00 2001
From: Rucha Mahabal
Date: Tue, 1 Mar 2022 21:40:39 +0530
Subject: [PATCH 17/48] test: test advance filters in expense claim and
cancelled status
---
.../employee_advance/employee_advance.py | 1 +
.../employee_advance/test_employee_advance.py | 40 +++++++++++++++++--
2 files changed, 37 insertions(+), 4 deletions(-)
diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.py b/erpnext/hr/doctype/employee_advance/employee_advance.py
index 2378482364df..c1876b117576 100644
--- a/erpnext/hr/doctype/employee_advance/employee_advance.py
+++ b/erpnext/hr/doctype/employee_advance/employee_advance.py
@@ -29,6 +29,7 @@ def validate(self):
def on_cancel(self):
self.ignore_linked_doctypes = "GL Entry"
+ self.set_status(update=True)
def set_status(self, update=False):
precision = self.precision("paid_amount")
diff --git a/erpnext/hr/doctype/employee_advance/test_employee_advance.py b/erpnext/hr/doctype/employee_advance/test_employee_advance.py
index a8ff6a794d6c..44d68c948335 100644
--- a/erpnext/hr/doctype/employee_advance/test_employee_advance.py
+++ b/erpnext/hr/doctype/employee_advance/test_employee_advance.py
@@ -24,6 +24,9 @@
class TestEmployeeAdvance(unittest.TestCase):
+ def setUp(self):
+ frappe.db.delete("Employee Advance")
+
def test_paid_amount_and_status(self):
employee_name = make_employee("_T@employe.advance")
advance = make_employee_advance(employee_name)
@@ -58,8 +61,12 @@ def test_paid_amount_on_pe_cancellation(self):
self.assertEqual(advance.paid_amount, 0)
self.assertEqual(advance.status, "Unpaid")
- def test_claimed_and_returned_status(self):
- # Claimed Status check, full amount claimed
+ advance.cancel()
+ advance.reload()
+ self.assertEqual(advance.status, "Cancelled")
+
+ def test_claimed_status(self):
+ # CLAIMED Status check, full amount claimed
payable_account = get_payable_account("_Test Company")
claim = make_expense_claim(
payable_account, 1000, 1000, "_Test Company", "Travel Expenses - _TC", do_not_submit=True
@@ -77,13 +84,28 @@ def test_claimed_and_returned_status(self):
self.assertEqual(advance.claimed_amount, 1000)
self.assertEqual(advance.status, "Claimed")
+ # advance should not be shown in claims
+ advances = get_advances(claim.employee)
+ advances = [entry.name for entry in advances]
+ self.assertTrue(advance.name not in advances)
+
# cancel claim; status should be Paid
claim.cancel()
advance.reload()
self.assertEqual(advance.claimed_amount, 0)
self.assertEqual(advance.status, "Paid")
- # Partly Claimed and Returned status check
+ def test_partly_claimed_and_returned_status(self):
+ payable_account = get_payable_account("_Test Company")
+ claim = make_expense_claim(
+ payable_account, 1000, 1000, "_Test Company", "Travel Expenses - _TC", do_not_submit=True
+ )
+
+ advance = make_employee_advance(claim.employee)
+ pe = make_payment_entry(advance)
+ pe.submit()
+
+ # PARTLY CLAIMED AND RETURNED status check
# 500 Claimed, 500 Returned
claim = make_expense_claim(
payable_account, 500, 500, "_Test Company", "Travel Expenses - _TC", do_not_submit=True
@@ -120,12 +142,22 @@ def test_claimed_and_returned_status(self):
self.assertEqual(advance.return_amount, 500)
self.assertEqual(advance.status, "Partly Claimed and Returned")
- # Cancel return entry; status should change to Paid
+ # advance should not be shown in claims
+ advances = get_advances(claim.employee)
+ advances = [entry.name for entry in advances]
+ self.assertTrue(advance.name not in advances)
+
+ # Cancel return entry; status should change to PAID
entry.cancel()
advance.reload()
self.assertEqual(advance.return_amount, 0)
self.assertEqual(advance.status, "Paid")
+ # advance should be shown in claims
+ advances = get_advances(claim.employee)
+ advances = [entry.name for entry in advances]
+ self.assertTrue(advance.name in advances)
+
def test_repay_unclaimed_amount_from_salary(self):
employee_name = make_employee("_T@employe.advance")
advance = make_employee_advance(employee_name, {"repay_unclaimed_amount_from_salary": 1})
From 78e9e66d63955b95e6b2f1c10b92c55973207234 Mon Sep 17 00:00:00 2001
From: Rucha Mahabal
Date: Mon, 23 May 2022 19:49:05 +0530
Subject: [PATCH 18/48] fix: replace document states with list settings
---
.../employee_advance/employee_advance.json | 37 +------------------
.../employee_advance/employee_advance_list.js | 15 ++++++++
2 files changed, 16 insertions(+), 36 deletions(-)
create mode 100644 erpnext/hr/doctype/employee_advance/employee_advance_list.js
diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.json b/erpnext/hr/doctype/employee_advance/employee_advance.json
index 1b838ad98638..8b2eea113379 100644
--- a/erpnext/hr/doctype/employee_advance/employee_advance.json
+++ b/erpnext/hr/doctype/employee_advance/employee_advance.json
@@ -200,7 +200,7 @@
],
"is_submittable": 1,
"links": [],
- "modified": "2022-01-17 19:33:52.345823",
+ "modified": "2022-05-23 19:33:52.345823",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee Advance",
@@ -236,41 +236,6 @@
"search_fields": "employee,employee_name",
"sort_field": "modified",
"sort_order": "DESC",
- "states": [
- {
- "color": "Red",
- "custom": 1,
- "title": "Draft"
- },
- {
- "color": "Green",
- "custom": 1,
- "title": "Paid"
- },
- {
- "color": "Orange",
- "custom": 1,
- "title": "Unpaid"
- },
- {
- "color": "Blue",
- "custom": 1,
- "title": "Claimed"
- },
- {
- "color": "Gray",
- "title": "Returned"
- },
- {
- "color": "Yellow",
- "title": "Partly Claimed and Returned"
- },
- {
- "color": "Red",
- "custom": 1,
- "title": "Cancelled"
- }
- ],
"title_field": "employee_name",
"track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/employee_advance/employee_advance_list.js b/erpnext/hr/doctype/employee_advance/employee_advance_list.js
new file mode 100644
index 000000000000..433669a71f3c
--- /dev/null
+++ b/erpnext/hr/doctype/employee_advance/employee_advance_list.js
@@ -0,0 +1,15 @@
+frappe.listview_settings["Employee Advance"] = {
+ get_indicator: function(doc) {
+ let status_color = {
+ "Draft": "red",
+ "Submitted": "blue",
+ "Cancelled": "red",
+ "Paid": "green",
+ "Unpaid": "orange",
+ "Claimed": "blue",
+ "Returned": "gray",
+ "Partly Claimed and Returned": "yellow"
+ };
+ return [__(doc.status), status_color[doc.status], "status,=,"+doc.status];
+ }
+};
\ No newline at end of file
From e9968cc6fc3589467794fa4bbe0c41fbba1e7af2 Mon Sep 17 00:00:00 2001
From: Ankush Menat
Date: Tue, 24 May 2022 14:32:56 +0530
Subject: [PATCH 19/48] chore: disable feed for material request
---
erpnext/stock/doctype/material_request/material_request.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py
index 55c9ac47e4c8..3474ca0db683 100644
--- a/erpnext/stock/doctype/material_request/material_request.py
+++ b/erpnext/stock/doctype/material_request/material_request.py
@@ -24,7 +24,7 @@
class MaterialRequest(BuyingController):
def get_feed(self):
- return _("{0}: {1}").format(self.status, self.material_request_type)
+ return
def check_if_already_pulled(self):
pass
From 34928d29f1ff8c823217b9d5b7b751a7ab6c5b0e Mon Sep 17 00:00:00 2001
From: Rucha Mahabal
Date: Tue, 24 May 2022 18:14:06 +0530
Subject: [PATCH 20/48] fix: remove bad default for Membership From Date
---
erpnext/non_profit/doctype/membership/membership.py | 4 ----
1 file changed, 4 deletions(-)
diff --git a/erpnext/non_profit/doctype/membership/membership.py b/erpnext/non_profit/doctype/membership/membership.py
index f29005a6d4b9..835e2db85198 100644
--- a/erpnext/non_profit/doctype/membership/membership.py
+++ b/erpnext/non_profit/doctype/membership/membership.py
@@ -61,10 +61,6 @@ def validate_membership_period(self):
frappe.throw(_("You can only renew if your membership expires within 30 days"))
self.from_date = add_days(last_membership.to_date, 1)
- elif frappe.session.user == "Administrator":
- self.from_date = self.from_date
- else:
- self.from_date = nowdate()
if frappe.db.get_single_value("Non Profit Settings", "billing_cycle") == "Yearly":
self.to_date = add_years(self.from_date, 1)
From 168a9d417b57e6441da7e9446100e0de62aeaea5 Mon Sep 17 00:00:00 2001
From: Rucha Mahabal
Date: Tue, 24 May 2022 18:16:56 +0530
Subject: [PATCH 21/48] fix: don't capture payments with invoice_id as
donations
- if donations and subscriptions are set up in the same dashboard, membership payments also trigger payment webhook
- in order to differentiate there is already a check for RP's auto generated description but if subscriptions are configured using subscription links, RP doesn't send descriptions
- use invoice_id to ignore such payments instead
---
erpnext/non_profit/doctype/donation/donation.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/erpnext/non_profit/doctype/donation/donation.py b/erpnext/non_profit/doctype/donation/donation.py
index 8e5ac5b61bf4..ed4b3d05b3ff 100644
--- a/erpnext/non_profit/doctype/donation/donation.py
+++ b/erpnext/non_profit/doctype/donation/donation.py
@@ -100,7 +100,9 @@ def capture_razorpay_donations(*args, **kwargs):
return
# to avoid capturing subscription payments as donations
- if payment.description and "subscription" in str(payment.description).lower():
+ if payment.invoice_id or (
+ payment.description and "subscription" in str(payment.description).lower()
+ ):
return
donor = get_donor(payment.email)
From 2ea331852ac61eacc86019b208d0af785499d4c2 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Fri, 20 May 2022 15:33:03 +0530
Subject: [PATCH 22/48] fix(India): Async issue in company address trigger
(cherry picked from commit c41f9f046fb987d942298db99b5b1cf64f8b7684)
---
erpnext/regional/india/taxes.js | 3 +++
1 file changed, 3 insertions(+)
diff --git a/erpnext/regional/india/taxes.js b/erpnext/regional/india/taxes.js
index 5f6dcdeb9227..c0e6b91a1c06 100644
--- a/erpnext/regional/india/taxes.js
+++ b/erpnext/regional/india/taxes.js
@@ -1,6 +1,7 @@
erpnext.setup_auto_gst_taxation = (doctype) => {
frappe.ui.form.on(doctype, {
company_address: function(frm) {
+ console.log("#########");
frm.trigger('get_tax_template');
},
shipping_address: function(frm) {
@@ -22,6 +23,7 @@ erpnext.setup_auto_gst_taxation = (doctype) => {
'shipping_address': frm.doc.shipping_address || '',
'shipping_address_name': frm.doc.shipping_address_name || '',
'customer_address': frm.doc.customer_address || '',
+ 'company_address': frm.doc.company_address,
'supplier_address': frm.doc.supplier_address,
'customer': frm.doc.customer,
'supplier': frm.doc.supplier,
@@ -39,6 +41,7 @@ erpnext.setup_auto_gst_taxation = (doctype) => {
},
debounce: 2000,
callback: function(r) {
+ console.log(r.message);
if(r.message) {
frm.set_value('taxes_and_charges', r.message.taxes_and_charges);
frm.set_value('taxes', r.message.taxes);
From 559fc509e7e61a874a95292c383c73bd16f17489 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Fri, 20 May 2022 15:34:03 +0530
Subject: [PATCH 23/48] chore: Linting issues
(cherry picked from commit 8fd0b3b9f50dfc7794b68fabb136d28c2913e196)
---
erpnext/regional/india/taxes.js | 2 --
1 file changed, 2 deletions(-)
diff --git a/erpnext/regional/india/taxes.js b/erpnext/regional/india/taxes.js
index c0e6b91a1c06..88973e36b6ab 100644
--- a/erpnext/regional/india/taxes.js
+++ b/erpnext/regional/india/taxes.js
@@ -1,7 +1,6 @@
erpnext.setup_auto_gst_taxation = (doctype) => {
frappe.ui.form.on(doctype, {
company_address: function(frm) {
- console.log("#########");
frm.trigger('get_tax_template');
},
shipping_address: function(frm) {
@@ -41,7 +40,6 @@ erpnext.setup_auto_gst_taxation = (doctype) => {
},
debounce: 2000,
callback: function(r) {
- console.log(r.message);
if(r.message) {
frm.set_value('taxes_and_charges', r.message.taxes_and_charges);
frm.set_value('taxes', r.message.taxes);
From ea6d754f734e8db76fa035acf30e97f3b24e7870 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Fri, 20 May 2022 08:31:37 +0530
Subject: [PATCH 24/48] fix: Loan repayment entries for payroll payable account
(cherry picked from commit 3128f9603ed74d08855c367a4b75bdc76f56399b)
---
.../doctype/loan_repayment/loan_repayment.py | 2 --
erpnext/payroll/doctype/payroll_entry/payroll_entry.py | 10 ++++++++++
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
index 9a43c2aec63e..d3840bfb2e25 100644
--- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
+++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
@@ -449,8 +449,6 @@ def make_gl_entries(self, cancel=0, adv_adj=0):
"remarks": remarks,
"cost_center": self.cost_center,
"posting_date": getdate(self.posting_date),
- "party_type": self.applicant_type if self.repay_from_salary else "",
- "party": self.applicant if self.repay_from_salary else "",
}
)
)
diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
index 60d38f4ca492..5f2af74dca68 100644
--- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
+++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
@@ -15,6 +15,7 @@
comma_and,
date_diff,
flt,
+ get_link_to_form,
getdate,
)
@@ -44,6 +45,7 @@ def on_submit(self):
def before_submit(self):
self.validate_employee_details()
+ self.validate_payroll_payable_account()
if self.validate_attendance:
if self.validate_employee_attendance():
frappe.throw(_("Cannot Submit, Employees left to mark attendance"))
@@ -65,6 +67,14 @@ def validate_employee_details(self):
if len(emp_with_sal_slip):
frappe.throw(_("Salary Slip already exists for {0}").format(comma_and(emp_with_sal_slip)))
+ def validate_payroll_payable_account(self):
+ if frappe.db.get_value("Account", self.payroll_payable_account, "account_type"):
+ frappe.throw(
+ _(
+ "Account type cannot be set for payroll payable account {0}, please remove and try again"
+ ).format(frappe.bold(get_link_to_form("Account", self.payroll_payable_account)))
+ )
+
def on_cancel(self):
frappe.delete_doc(
"Salary Slip",
From ce3a21eb039453d4786dfd0871a278b588039d80 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Wed, 25 May 2022 11:51:07 +0530
Subject: [PATCH 25/48] fix: Handle missing HSN Codes
---
erpnext/regional/report/gstr_1/gstr_1.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py
index 373e6e502ba0..602a71c3b8ec 100644
--- a/erpnext/regional/report/gstr_1/gstr_1.py
+++ b/erpnext/regional/report/gstr_1/gstr_1.py
@@ -449,7 +449,7 @@ def get_items_based_on_tax_rate(self):
hsn_code = self.item_hsn_map.get(item_code)
tax_rate = 0
taxable_value = items.get(item_code)
- for rates in hsn_wise_tax_rate.get(hsn_code):
+ for rates in hsn_wise_tax_rate.get(hsn_code, []):
if taxable_value > rates.get("minimum_taxable_value"):
tax_rate = rates.get("tax_rate")
From 216c32f4bc13376335ae31bd09fe6b5c01855ba2 Mon Sep 17 00:00:00 2001
From: Saqib Ansari
Date: Wed, 25 May 2022 12:12:35 +0530
Subject: [PATCH 26/48] fix: timesheet fetching in sales invoice
---
.../doctype/sales_invoice/sales_invoice.js | 49 +++++++++++++------
1 file changed, 33 insertions(+), 16 deletions(-)
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index c6a110dcab6e..dfa22641a5e2 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -475,7 +475,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
let row = frappe.get_doc(d.doctype, d.name)
set_timesheet_detail_rate(row.doctype, row.name, me.frm.doc.currency, row.timesheet_detail)
});
- frm.trigger("calculate_timesheet_totals");
+ this.frm.trigger("calculate_timesheet_totals");
}
}
});
@@ -885,27 +885,44 @@ frappe.ui.form.on('Sales Invoice', {
set_timesheet_data: function(frm, timesheets) {
frm.clear_table("timesheets")
- timesheets.forEach(timesheet => {
+ timesheets.forEach(async (timesheet) => {
if (frm.doc.currency != timesheet.currency) {
- frappe.call({
- method: "erpnext.setup.utils.get_exchange_rate",
- args: {
- from_currency: timesheet.currency,
- to_currency: frm.doc.currency
- },
- callback: function(r) {
- if (r.message) {
- exchange_rate = r.message;
- frm.events.append_time_log(frm, timesheet, exchange_rate);
- }
- }
- });
+ const exchange_rate = await frm.events.get_exchange_rate(
+ frm, timesheet.currency, frm.doc.currency
+ )
+ frm.events.append_time_log(frm, timesheet, exchange_rate)
} else {
frm.events.append_time_log(frm, timesheet, 1.0);
}
});
},
+ async get_exchange_rate(frm, from_currency, to_currency) {
+ if (
+ frm.exchange_rates
+ && frm.exchange_rates[from_currency]
+ && frm.exchange_rates[from_currency][to_currency]
+ ) {
+ return frm.exchange_rates[from_currency][to_currency];
+ }
+
+ return frappe.call({
+ method: "erpnext.setup.utils.get_exchange_rate",
+ args: {
+ from_currency,
+ to_currency
+ },
+ callback: function(r) {
+ if (r.message) {
+ // cache exchange rates
+ frm.exchange_rates = frm.exchange_rates || {};
+ frm.exchange_rates[from_currency] = frm.exchange_rates[from_currency] || {};
+ frm.exchange_rates[from_currency][to_currency] = r.message;
+ }
+ }
+ });
+ },
+
append_time_log: function(frm, time_log, exchange_rate) {
const row = frm.add_child("timesheets");
row.activity_type = time_log.activity_type;
@@ -916,7 +933,7 @@ frappe.ui.form.on('Sales Invoice', {
row.billing_hours = time_log.billing_hours;
row.billing_amount = flt(time_log.billing_amount) * flt(exchange_rate);
row.timesheet_detail = time_log.name;
- row.project_name = time_log.project_name;
+ row.project_name = time_log.project_name;
frm.refresh_field("timesheets");
frm.trigger("calculate_timesheet_totals");
From 98eb7da06acdd18c2c667363fbf017a013d338c9 Mon Sep 17 00:00:00 2001
From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com>
Date: Wed, 25 May 2022 12:24:09 +0530
Subject: [PATCH 27/48] fix(pos): paid amount calculation for multicurrency
invoice (#31122)
---
.../public/js/controllers/taxes_and_totals.js | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index 2b1b0e3576b4..fe23ff381265 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -767,11 +767,23 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
if(this.frm.doc.is_pos && (update_paid_amount===undefined || update_paid_amount)) {
$.each(this.frm.doc['payments'] || [], function(index, data) {
if(data.default && payment_status && total_amount_to_pay > 0) {
- let base_amount = flt(total_amount_to_pay, precision("base_amount", data));
+ let base_amount, amount;
+
+ if (me.frm.doc.party_account_currency == me.frm.doc.currency) {
+ // if customer/supplier currency is same as company currency
+ // total_amount_to_pay is already in customer/supplier currency
+ // so base_amount has to be calculated using total_amount_to_pay
+ base_amount = flt(total_amount_to_pay * me.frm.doc.conversion_rate, precision("base_amount", data));
+ amount = flt(total_amount_to_pay, precision("amount", data));
+ } else {
+ base_amount = flt(total_amount_to_pay, precision("base_amount", data));
+ amount = flt(total_amount_to_pay / me.frm.doc.conversion_rate, precision("amount", data));
+ }
+
frappe.model.set_value(data.doctype, data.name, "base_amount", base_amount);
- let amount = flt(total_amount_to_pay / me.frm.doc.conversion_rate, precision("amount", data));
frappe.model.set_value(data.doctype, data.name, "amount", amount);
payment_status = false;
+
} else if(me.frm.doc.paid_amount) {
frappe.model.set_value(data.doctype, data.name, "amount", 0.0);
}
From 228f10bf30b0c9e304927b5a877cc0730a66ab7c Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Thu, 12 Aug 2021 15:39:07 +0530
Subject: [PATCH 28/48] fix: Account currency validation for first transaction
(cherry picked from commit 80c85dd17cf0c0fdcf07d2e0c2151b2852a0c611)
# Conflicts:
# erpnext/controllers/accounts_controller.py
---
erpnext/controllers/accounts_controller.py | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 7d41c84acfca..d821915a4cf5 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -44,6 +44,12 @@
set_print_templates_for_taxes,
)
from erpnext.controllers.sales_and_purchase_return import validate_return
+<<<<<<< HEAD
+=======
+from erpnext.accounts.party import get_party_account_currency, validate_party_frozen_disabled, get_party_gle_currency
+from erpnext.accounts.doctype.pricing_rule.utils import (apply_pricing_rule_on_transaction,
+ apply_pricing_rule_for_free_items, get_applied_pricing_rules)
+>>>>>>> 80c85dd17c (fix: Account currency validation for first transaction)
from erpnext.exceptions import InvalidCurrency
from erpnext.setup.utils import get_exchange_rate
from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
@@ -169,6 +175,7 @@ def validate(self):
self.validate_party()
self.validate_currency()
+ self.validate_party_account_currency()
if self.doctype in ["Purchase Invoice", "Sales Invoice"]:
pos_check_field = "is_pos" if self.doctype == "Sales Invoice" else "is_paid"
@@ -1445,6 +1452,19 @@ def validate_currency(self):
# at quotation / sales order level and we shouldn't stop someone
# from creating a sales invoice if sales order is already created
+ def validate_party_account_currency(self):
+ if self.doctype not in ('Sales Invoice', 'Purchase Invoice'):
+ return
+
+ party_type, party = self.get_party()
+ party_gle_currency = get_party_gle_currency(party_type, party, self.company)
+ party_account = self.get('debit_to') if self.doctype == 'Sales Invoice' else self.get('credit_to')
+ party_account_currency = get_account_currency(party_account)
+
+ if not party_gle_currency and (party_account_currency != self.currency):
+ frappe.throw(_("Party Account {0} currency and document currency should be same").format(frappe.bold(party_account)))
+
+
def delink_advance_entries(self, linked_doc_name):
total_allocated_amount = 0
for adv in self.advances:
From 7f853b1f0febad2a33548558f2f0556801c0196f Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Sun, 15 Aug 2021 21:18:13 +0530
Subject: [PATCH 29/48] fix: Add party account validation for journal entry
(cherry picked from commit f00620a3ca8d507dc947b82abdb5a90c6759bde5)
---
.../accounts/doctype/journal_entry/journal_entry.py | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 8660c18bf950..ba0b1416d7e6 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -51,6 +51,7 @@ def validate(self):
self.validate_party()
self.validate_entries_for_advance()
self.validate_multi_currency()
+ self.validate_party_account_currency()
self.set_amounts_in_company_currency()
self.validate_debit_credit_amount()
@@ -655,6 +656,18 @@ def validate_multi_currency(self):
self.set_exchange_rate()
+ def validate_party_account_currency(self):
+ for d in self.get("accounts"):
+ if self.party_type not in ('Customer', 'Supplier'):
+ continue
+
+ party_gle_currency = get_party_gle_currency(self.party_type, self.party, self.company)
+ party_account_currency = get_account_currency(d.account)
+
+ if not party_gle_currency and (party_account_currency != self.currency):
+ frappe.throw(_("Row {0}: Party Account {1} currency and document currency should be same").format(
+ frappe.bold(d.idx), frappe.bold(d.account)))
+
def set_amounts_in_company_currency(self):
for d in self.get("accounts"):
d.debit_in_account_currency = flt(
From 09a42a122f0a446d73942d9b8a69149721379e42 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Sun, 15 Aug 2021 21:19:18 +0530
Subject: [PATCH 30/48] fix: Healthcare module accounting test cases
(cherry picked from commit bcaf4752952f4aa7819c057ce61c8bd2ef69df78)
# Conflicts:
# erpnext/healthcare/doctype/lab_test/test_lab_test.py
---
erpnext/healthcare/doctype/lab_test/test_lab_test.py | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/erpnext/healthcare/doctype/lab_test/test_lab_test.py b/erpnext/healthcare/doctype/lab_test/test_lab_test.py
index 06c02d1ea079..754ee94c3965 100644
--- a/erpnext/healthcare/doctype/lab_test/test_lab_test.py
+++ b/erpnext/healthcare/doctype/lab_test/test_lab_test.py
@@ -163,8 +163,14 @@ def create_sales_invoice():
sales_invoice.patient = patient
sales_invoice.customer = frappe.db.get_value("Patient", patient, "customer")
sales_invoice.due_date = getdate()
+<<<<<<< HEAD
sales_invoice.company = "_Test Company"
sales_invoice.debit_to = get_receivable_account("_Test Company")
+=======
+ sales_invoice.company = '_Test Company'
+ sales_invoice.currency = 'INR'
+ sales_invoice.debit_to = get_receivable_account('_Test Company')
+>>>>>>> bcaf475295 (fix: Healthcare module accounting test cases)
tests = [insulin_resistance_template, blood_test_template]
for entry in tests:
From 9d43a90eb08ddbcb80a7b488b9696762058e69cc Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Mon, 16 Aug 2021 10:40:26 +0530
Subject: [PATCH 31/48] Revert "fix: Add party account validation for journal
entry"
This reverts commit f00620a3ca8d507dc947b82abdb5a90c6759bde5.
(cherry picked from commit 0a618817dc76e7da00e8ae16521bf554b5fd9704)
---
.../accounts/doctype/journal_entry/journal_entry.py | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index ba0b1416d7e6..8660c18bf950 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -51,7 +51,6 @@ def validate(self):
self.validate_party()
self.validate_entries_for_advance()
self.validate_multi_currency()
- self.validate_party_account_currency()
self.set_amounts_in_company_currency()
self.validate_debit_credit_amount()
@@ -656,18 +655,6 @@ def validate_multi_currency(self):
self.set_exchange_rate()
- def validate_party_account_currency(self):
- for d in self.get("accounts"):
- if self.party_type not in ('Customer', 'Supplier'):
- continue
-
- party_gle_currency = get_party_gle_currency(self.party_type, self.party, self.company)
- party_account_currency = get_account_currency(d.account)
-
- if not party_gle_currency and (party_account_currency != self.currency):
- frappe.throw(_("Row {0}: Party Account {1} currency and document currency should be same").format(
- frappe.bold(d.idx), frappe.bold(d.account)))
-
def set_amounts_in_company_currency(self):
for d in self.get("accounts"):
d.debit_in_account_currency = flt(
From 8f969fbd666a9db6c934afbb50958e41b4039159 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Sat, 21 Aug 2021 23:05:48 +0530
Subject: [PATCH 32/48] test: Update test cases for currency change validation
(cherry picked from commit 60915e874d9f466618b313be65023a62591d0f97)
# Conflicts:
# erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py
# erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
# erpnext/healthcare/doctype/therapy_plan/therapy_plan.py
# erpnext/non_profit/doctype/membership/membership.py
---
.../test_period_closing_voucher.py | 8 +++++++
erpnext/controllers/accounts_controller.py | 3 +++
.../patient_appointment.py | 12 ++++++++++
.../doctype/therapy_plan/therapy_plan.py | 11 ++++++++++
.../doctype/membership/membership.py | 22 +++++++++++++++++++
.../doctype/membership/test_membership.py | 2 +-
6 files changed, 57 insertions(+), 1 deletion(-)
diff --git a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py
index 8e0e62d5f8c2..a61f32c3d1ef 100644
--- a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py
+++ b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py
@@ -78,6 +78,10 @@ def test_cost_center_wise_posting(self):
expense_account="Cost of Goods Sold - TPC",
rate=400,
debit_to="Debtors - TPC",
+<<<<<<< HEAD
+=======
+ currency="USD"
+>>>>>>> 60915e874d (test: Update test cases for currency change validation)
)
create_sales_invoice(
company=company,
@@ -86,6 +90,10 @@ def test_cost_center_wise_posting(self):
expense_account="Cost of Goods Sold - TPC",
rate=200,
debit_to="Debtors - TPC",
+<<<<<<< HEAD
+=======
+ currency="USD"
+>>>>>>> 60915e874d (test: Update test cases for currency change validation)
)
pcv = self.make_period_closing_voucher(submit=False)
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index d821915a4cf5..60ff067a91f7 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -1456,6 +1456,9 @@ def validate_party_account_currency(self):
if self.doctype not in ('Sales Invoice', 'Purchase Invoice'):
return
+ if self.is_opening == 'Yes':
+ return
+
party_type, party = self.get_party()
party_gle_currency = get_party_gle_currency(party_type, party, self.company)
party_account = self.get('debit_to') if self.doctype == 'Sales Invoice' else self.get('credit_to')
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
index b6e30060437e..131767797dbf 100755
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
@@ -22,6 +22,7 @@
manage_fee_validity,
)
from erpnext.hr.doctype.employee.employee import is_holiday
+<<<<<<< HEAD
class MaximumCapacityError(frappe.ValidationError):
@@ -31,6 +32,11 @@ class MaximumCapacityError(frappe.ValidationError):
class OverlapError(frappe.ValidationError):
pass
+=======
+from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_receivable_account, get_income_account
+from erpnext.healthcare.utils import check_fee_validity, get_service_item_and_practitioner_charge, manage_fee_validity
+from erpnext import get_company_currency
+>>>>>>> 60915e874d (test: Update test cases for currency change validation)
class PatientAppointment(Document):
def validate(self):
@@ -251,7 +257,13 @@ def invoice_appointment(appointment_doc):
def create_sales_invoice(appointment_doc):
sales_invoice = frappe.new_doc("Sales Invoice")
sales_invoice.patient = appointment_doc.patient
+<<<<<<< HEAD
sales_invoice.customer = frappe.get_value("Patient", appointment_doc.patient, "customer")
+=======
+ sales_invoice.customer = frappe.get_value('Patient', appointment_doc.patient, 'customer')
+ sales_invoice.currency = frappe.get_value('Customer', sales_invoice.customer, 'default_currency') \
+ or get_company_currency(appointment_doc.currency)
+>>>>>>> 60915e874d (test: Update test cases for currency change validation)
sales_invoice.appointment = appointment_doc.name
sales_invoice.due_date = getdate()
sales_invoice.company = appointment_doc.company
diff --git a/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py
index 44f0a9785c44..b82894c366b9 100644
--- a/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py
+++ b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py
@@ -4,8 +4,13 @@
import frappe
from frappe.model.document import Document
+<<<<<<< HEAD
from frappe.utils import flt
+=======
+from frappe.utils import flt, today
+from erpnext import get_company_currency
+>>>>>>> 60915e874d (test: Update test cases for currency change validation)
class TherapyPlan(Document):
def validate(self):
@@ -71,7 +76,13 @@ def make_sales_invoice(reference_name, patient, company, therapy_plan_template):
si = frappe.new_doc("Sales Invoice")
si.company = company
si.patient = patient
+<<<<<<< HEAD
si.customer = frappe.db.get_value("Patient", patient, "customer")
+=======
+ si.customer = frappe.db.get_value('Patient', patient, 'customer')
+ si.currency = frappe.get_value('Customer', si.customer, 'default_currency') \
+ or get_company_currency(si.company)
+>>>>>>> 60915e874d (test: Update test cases for currency change validation)
item = frappe.db.get_value("Therapy Plan Template", therapy_plan_template, "linked_item")
price_list, price_list_currency = frappe.db.get_values(
diff --git a/erpnext/non_profit/doctype/membership/membership.py b/erpnext/non_profit/doctype/membership/membership.py
index 835e2db85198..c420a2879b7f 100644
--- a/erpnext/non_profit/doctype/membership/membership.py
+++ b/erpnext/non_profit/doctype/membership/membership.py
@@ -13,8 +13,12 @@
from frappe.utils import add_days, add_months, add_years, get_link_to_form, getdate, nowdate
import erpnext
+<<<<<<< HEAD
from erpnext.non_profit.doctype.member.member import create_member
+=======
+from erpnext import get_company_currency
+>>>>>>> 60915e874d (test: Update test cases for currency change validation)
class Membership(Document):
def validate(self):
@@ -198,6 +202,7 @@ def generate_and_send_invoice(self):
def make_invoice(membership, member, plan, settings):
+<<<<<<< HEAD
invoice = frappe.get_doc(
{
"doctype": "Sales Invoice",
@@ -209,6 +214,23 @@ def make_invoice(membership, member, plan, settings):
"items": [{"item_code": plan.linked_item, "rate": membership.amount, "qty": 1}],
}
)
+=======
+ invoice = frappe.get_doc({
+ "doctype": "Sales Invoice",
+ "customer": member.customer,
+ "debit_to": settings.membership_debit_account,
+ "currency": membership.currency or get_company_currency(settings.company),
+ "company": settings.company,
+ "is_pos": 0,
+ "items": [
+ {
+ "item_code": plan.linked_item,
+ "rate": membership.amount,
+ "qty": 1
+ }
+ ]
+ })
+>>>>>>> 60915e874d (test: Update test cases for currency change validation)
invoice.set_missing_values()
invoice.insert()
invoice.submit()
diff --git a/erpnext/non_profit/doctype/membership/test_membership.py b/erpnext/non_profit/doctype/membership/test_membership.py
index aef34a69606e..d73c2bed5f4a 100644
--- a/erpnext/non_profit/doctype/membership/test_membership.py
+++ b/erpnext/non_profit/doctype/membership/test_membership.py
@@ -94,7 +94,7 @@ def make_membership(member, payload={}):
"member": member,
"membership_status": "Current",
"membership_type": "_rzpy_test_milythm",
- "currency": "INR",
+ "currency": "USD",
"paid": 1,
"from_date": nowdate(),
"amount": 100,
From e28f6b7d312e9a06346700a9f9627a21c06d64d9 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Sun, 22 Aug 2021 18:05:24 +0530
Subject: [PATCH 33/48] test: fix property name
(cherry picked from commit c10a22529c8b612ca31d2221700e45184426753d)
# Conflicts:
# erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
---
.../doctype/patient_appointment/patient_appointment.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
index 131767797dbf..713e5b3501e5 100755
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
@@ -262,8 +262,12 @@ def create_sales_invoice(appointment_doc):
=======
sales_invoice.customer = frappe.get_value('Patient', appointment_doc.patient, 'customer')
sales_invoice.currency = frappe.get_value('Customer', sales_invoice.customer, 'default_currency') \
+<<<<<<< HEAD
or get_company_currency(appointment_doc.currency)
>>>>>>> 60915e874d (test: Update test cases for currency change validation)
+=======
+ or get_company_currency(appointment_doc.company)
+>>>>>>> c10a22529c (test: fix property name)
sales_invoice.appointment = appointment_doc.name
sales_invoice.due_date = getdate()
sales_invoice.company = appointment_doc.company
From 4727482737e96aeefa04aa4b22ab3afd78b20ca2 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Sun, 22 Aug 2021 23:48:23 +0530
Subject: [PATCH 34/48] test: Set default currency for patient
(cherry picked from commit 30876a105ca9ebb7f51741068b50385ca5a915c5)
# Conflicts:
# erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
---
.../test_patient_appointment.py | 39 +++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
index 048547a93223..274f1afdaae7 100644
--- a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
@@ -235,6 +235,7 @@ def test_invalid_healthcare_service_unit_validation(self):
)
ip_record1 = frappe.get_doc("Inpatient Record", ip_record.name)
mark_invoiced_inpatient_occupancy(ip_record1)
+<<<<<<< HEAD
discharge_patient(ip_record1, now_datetime())
def test_payment_should_be_mandatory_for_new_patient_appointment(self):
@@ -415,6 +416,44 @@ def create_practitioner(id=0, medical_department=None):
return practitioner.name
+=======
+ discharge_patient(ip_record1)
+
+
+def create_healthcare_docs():
+ patient = create_patient()
+ practitioner = frappe.db.exists('Healthcare Practitioner', '_Test Healthcare Practitioner')
+ medical_department = frappe.db.exists('Medical Department', '_Test Medical Department')
+
+ if not medical_department:
+ medical_department = frappe.new_doc('Medical Department')
+ medical_department.department = '_Test Medical Department'
+ medical_department.save(ignore_permissions=True)
+ medical_department = medical_department.name
+
+ if not practitioner:
+ practitioner = frappe.new_doc('Healthcare Practitioner')
+ practitioner.first_name = '_Test Healthcare Practitioner'
+ practitioner.gender = 'Female'
+ practitioner.department = medical_department
+ practitioner.op_consulting_charge = 500
+ practitioner.inpatient_visit_charge = 500
+ practitioner.save(ignore_permissions=True)
+ practitioner = practitioner.name
+
+ return patient, medical_department, practitioner
+
+def create_patient():
+ patient = frappe.db.exists('Patient', '_Test Patient')
+ if not patient:
+ patient = frappe.new_doc('Patient')
+ patient.first_name = '_Test Patient'
+ patient.sex = 'Female'
+ patient.default_currency = 'INR'
+ patient.save(ignore_permissions=True)
+ patient = patient.name
+ return patient
+>>>>>>> 30876a105c (test: Set default currency for patient)
def create_encounter(appointment):
if appointment:
From d10c2e50bee2256b43039d7d09b53dc01e72160d Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Thu, 26 Aug 2021 17:13:36 +0530
Subject: [PATCH 35/48] fix: Party account validation in JV
(cherry picked from commit 417d6abcf48668d053b413dae577f7c775c08416)
# Conflicts:
# erpnext/accounts/doctype/journal_entry/journal_entry.py
---
.../doctype/journal_entry/journal_entry.py | 22 +++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 8660c18bf950..a7c52dd24d04 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -26,6 +26,13 @@
)
from erpnext.controllers.accounts_controller import AccountsController
from erpnext.hr.doctype.expense_claim.expense_claim import update_reimbursed_amount
+<<<<<<< HEAD
+=======
+from erpnext.accounts.doctype.invoice_discounting.invoice_discounting \
+ import get_party_account_based_on_invoice_discounting
+from erpnext.accounts.deferred_revenue import get_deferred_booking_accounts
+from erpnext.accounts.party import get_party_gle_currency
+>>>>>>> 417d6abcf4 (fix: Party account validation in JV)
class StockAccountInvalidTransaction(frappe.ValidationError):
@@ -49,6 +56,7 @@ def validate(self):
self.clearance_date = None
self.validate_party()
+ self.validate_party_account_currency()
self.validate_entries_for_advance()
self.validate_multi_currency()
self.set_amounts_in_company_currency()
@@ -327,11 +335,25 @@ def validate_party(self):
account_type = frappe.db.get_value("Account", d.account, "account_type")
if account_type in ["Receivable", "Payable"]:
if not (d.party_type and d.party):
+<<<<<<< HEAD
frappe.throw(
_("Row {0}: Party Type and Party is required for Receivable / Payable account {1}").format(
d.idx, d.account
)
)
+=======
+ frappe.throw(_("Row {0}: Party Type and Party is required for Receivable / Payable account {1}").format(d.idx, d.account))
+
+ def validate_party_account_currency(self):
+ for d in self.get("accounts"):
+ if d.party_type in ('Customer', 'Supplier'):
+ party_gle_currency = get_party_gle_currency(d.party_type, d.party, self.company)
+ party_account_currency = get_account_currency(d.account)
+ party_currency = frappe.db.get_value(d.party_type, d.party, 'default_currency')
+
+ if not party_gle_currency and (party_account_currency != party_currency):
+ frappe.throw(_("Party Account {0} currency and default party currency should be same").format(frappe.bold(d.account)))
+>>>>>>> 417d6abcf4 (fix: Party account validation in JV)
def check_credit_limit(self):
customers = list(
From 4ca6cdca7621e40093abe43d016124798ede25ea Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Sun, 15 May 2022 21:10:52 +0530
Subject: [PATCH 36/48] fix: Remove validation from Journal Entry
(cherry picked from commit 5b8726405d54c2a0601d379dbc78482e19858cda)
# Conflicts:
# erpnext/accounts/doctype/journal_entry/journal_entry.py
---
erpnext/accounts/doctype/journal_entry/journal_entry.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index a7c52dd24d04..7bd978561baf 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -56,7 +56,6 @@ def validate(self):
self.clearance_date = None
self.validate_party()
- self.validate_party_account_currency()
self.validate_entries_for_advance()
self.validate_multi_currency()
self.set_amounts_in_company_currency()
@@ -341,6 +340,7 @@ def validate_party(self):
d.idx, d.account
)
)
+<<<<<<< HEAD
=======
frappe.throw(_("Row {0}: Party Type and Party is required for Receivable / Payable account {1}").format(d.idx, d.account))
@@ -354,6 +354,8 @@ def validate_party_account_currency(self):
if not party_gle_currency and (party_account_currency != party_currency):
frappe.throw(_("Party Account {0} currency and default party currency should be same").format(frappe.bold(d.account)))
>>>>>>> 417d6abcf4 (fix: Party account validation in JV)
+=======
+>>>>>>> 5b8726405d (fix: Remove validation from Journal Entry)
def check_credit_limit(self):
customers = list(
From 0628785c646a221b66277f8fb22c1e9dddfefbfc Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Mon, 16 May 2022 10:52:58 +0530
Subject: [PATCH 37/48] test: Update test cases
(cherry picked from commit 65232edfd5634cb270a20cab076d2ad3cc644e28)
# Conflicts:
# erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py
# erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
---
.../test_period_closing_voucher.py | 15 +++++++-
.../doctype/pricing_rule/test_pricing_rule.py | 35 +++++++++++++++++++
2 files changed, 49 insertions(+), 1 deletion(-)
diff --git a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py
index a61f32c3d1ef..8a8e186a826a 100644
--- a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py
+++ b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py
@@ -79,9 +79,14 @@ def test_cost_center_wise_posting(self):
rate=400,
debit_to="Debtors - TPC",
<<<<<<< HEAD
+<<<<<<< HEAD
=======
currency="USD"
>>>>>>> 60915e874d (test: Update test cases for currency change validation)
+=======
+ currency="USD",
+ customer="_Test Customer USD",
+>>>>>>> 65232edfd5 (test: Update test cases)
)
create_sales_invoice(
company=company,
@@ -91,9 +96,14 @@ def test_cost_center_wise_posting(self):
rate=200,
debit_to="Debtors - TPC",
<<<<<<< HEAD
+<<<<<<< HEAD
=======
currency="USD"
>>>>>>> 60915e874d (test: Update test cases for currency change validation)
+=======
+ currency="USD",
+ customer="_Test Customer USD",
+>>>>>>> 65232edfd5 (test: Update test cases)
)
pcv = self.make_period_closing_voucher(submit=False)
@@ -127,14 +137,17 @@ def test_period_closing_with_finance_book_entries(self):
surplus_account = create_account()
cost_center = create_cost_center("Test Cost Center 1")
- create_sales_invoice(
+ si = create_sales_invoice(
company=company,
income_account="Sales - TPC",
expense_account="Cost of Goods Sold - TPC",
cost_center=cost_center,
rate=400,
debit_to="Debtors - TPC",
+ currency="USD",
+ customer="_Test Customer USD",
)
+
jv = make_journal_entry(
account1="Cash - TPC",
account2="Sales - TPC",
diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
index 4b81a7d6a239..709f0a52eecb 100644
--- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
@@ -768,6 +768,41 @@ def test_remove_pricing_rule(self):
frappe.get_doc("Item Price", {"item_code": "Water Flask"}).delete()
item.delete()
+<<<<<<< HEAD
+=======
+ def test_multiple_pricing_rules_with_min_qty(self):
+ make_pricing_rule(
+ discount_percentage=20,
+ selling=1,
+ priority=1,
+ min_qty=4,
+ apply_multiple_pricing_rules=1,
+ title="_Test Pricing Rule with Min Qty - 1",
+ )
+ make_pricing_rule(
+ discount_percentage=10,
+ selling=1,
+ priority=2,
+ min_qty=4,
+ apply_multiple_pricing_rules=1,
+ title="_Test Pricing Rule with Min Qty - 2",
+ )
+
+ si = create_sales_invoice(do_not_submit=True, customer="_Test Customer 1", qty=1)
+ item = si.items[0]
+ item.stock_qty = 1
+ si.save()
+ self.assertFalse(item.discount_percentage)
+ item.qty = 5
+ item.stock_qty = 5
+ si.save()
+ self.assertEqual(item.discount_percentage, 30)
+ si.delete()
+
+ frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule with Min Qty - 1")
+ frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule with Min Qty - 2")
+
+>>>>>>> 65232edfd5 (test: Update test cases)
test_dependencies = ["Campaign"]
From 761669c7ca73448ba5306816f9b412a0b6cbd425 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Wed, 25 May 2022 15:42:47 +0530
Subject: [PATCH 38/48] chore: Update test case
(cherry picked from commit bc3473770947ed5796a8e7d6fa718b2a55f326eb)
# Conflicts:
# erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
---
erpnext/accounts/party.py | 15 ++++++
.../purchase_receipt/test_purchase_receipt.py | 52 +++++++++++++++++++
2 files changed, 67 insertions(+)
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index b76ce29b5050..177624ca0322 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -898,3 +898,18 @@ def get_default_contact(doctype, name):
return None
else:
return None
+
+
+def add_party_account(party_type, party, company, account):
+ doc = frappe.get_doc(party_type, party)
+ account_exists = False
+ for d in doc.get("accounts"):
+ if d.account == account:
+ account_exists = True
+
+ if not account_exists:
+ accounts = {"company": company, "account": account}
+
+ doc.append("accounts", accounts)
+
+ doc.save()
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index 65c30de09786..441bfc1b63ca 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -1295,6 +1295,58 @@ def test_po_to_pi_and_po_to_pr_worflow_partial(self):
self.assertEqual(pr.status, "To Bill")
self.assertAlmostEqual(pr.per_billed, 50.0, places=2)
+<<<<<<< HEAD
+=======
+ def test_purchase_receipt_with_exchange_rate_difference(self):
+ from erpnext.accounts.doctype.purchase_invoice.purchase_invoice import (
+ make_purchase_receipt as create_purchase_receipt,
+ )
+ from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import (
+ make_purchase_invoice as create_purchase_invoice,
+ )
+ from erpnext.accounts.party import add_party_account
+
+ add_party_account(
+ "Supplier",
+ "_Test Supplier USD",
+ "_Test Company with perpetual inventory",
+ "_Test Payable USD - TCP1",
+ )
+
+ pi = create_purchase_invoice(
+ company="_Test Company with perpetual inventory",
+ cost_center="Main - TCP1",
+ warehouse="Stores - TCP1",
+ expense_account="_Test Account Cost for Goods Sold - TCP1",
+ currency="USD",
+ conversion_rate=70,
+ supplier="_Test Supplier USD",
+ )
+
+ pr = create_purchase_receipt(pi.name)
+ pr.conversion_rate = 80
+ pr.items[0].purchase_invoice = pi.name
+ pr.items[0].purchase_invoice_item = pi.items[0].name
+
+ pr.save()
+ pr.submit()
+
+ # Get exchnage gain and loss account
+ exchange_gain_loss_account = frappe.db.get_value(
+ "Company", pr.company, "exchange_gain_loss_account"
+ )
+
+ # fetching the latest GL Entry with exchange gain and loss account account
+ amount = frappe.db.get_value(
+ "GL Entry", {"account": exchange_gain_loss_account, "voucher_no": pr.name}, "credit"
+ )
+ discrepancy_caused_by_exchange_rate_diff = abs(
+ pi.items[0].base_net_amount - pr.items[0].base_net_amount
+ )
+
+ self.assertEqual(discrepancy_caused_by_exchange_rate_diff, amount)
+
+>>>>>>> bc34737709 (chore: Update test case)
def test_payment_terms_are_fetched_when_creating_purchase_invoice(self):
from erpnext.accounts.doctype.payment_entry.test_payment_entry import (
create_payment_terms_template,
From f724f6d1bbd727789b6136b5adb390323927f5f2 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Wed, 25 May 2022 19:04:20 +0530
Subject: [PATCH 39/48] chore: Resolve conflicts
---
.../doctype/journal_entry/journal_entry.py | 30 +--
.../test_period_closing_voucher.py | 15 +-
.../doctype/pricing_rule/test_pricing_rule.py | 35 ---
erpnext/controllers/accounts_controller.py | 22 +-
.../patient_appointment.py | 22 +-
.../test_patient_appointment.py | 209 ++----------------
.../doctype/therapy_plan/therapy_plan.py | 14 +-
.../doctype/membership/membership.py | 25 +--
.../purchase_receipt/test_purchase_receipt.py | 52 -----
9 files changed, 48 insertions(+), 376 deletions(-)
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 7bd978561baf..cc6e6137a138 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -17,7 +17,7 @@
from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import (
get_party_tax_withholding_details,
)
-from erpnext.accounts.party import get_party_account
+from erpnext.accounts.party import get_party_account, get_party_gle_currency
from erpnext.accounts.utils import (
get_account_currency,
get_balance_on,
@@ -26,13 +26,6 @@
)
from erpnext.controllers.accounts_controller import AccountsController
from erpnext.hr.doctype.expense_claim.expense_claim import update_reimbursed_amount
-<<<<<<< HEAD
-=======
-from erpnext.accounts.doctype.invoice_discounting.invoice_discounting \
- import get_party_account_based_on_invoice_discounting
-from erpnext.accounts.deferred_revenue import get_deferred_booking_accounts
-from erpnext.accounts.party import get_party_gle_currency
->>>>>>> 417d6abcf4 (fix: Party account validation in JV)
class StockAccountInvalidTransaction(frappe.ValidationError):
@@ -334,28 +327,25 @@ def validate_party(self):
account_type = frappe.db.get_value("Account", d.account, "account_type")
if account_type in ["Receivable", "Payable"]:
if not (d.party_type and d.party):
-<<<<<<< HEAD
frappe.throw(
_("Row {0}: Party Type and Party is required for Receivable / Payable account {1}").format(
d.idx, d.account
)
)
-<<<<<<< HEAD
-=======
- frappe.throw(_("Row {0}: Party Type and Party is required for Receivable / Payable account {1}").format(d.idx, d.account))
-
+
def validate_party_account_currency(self):
for d in self.get("accounts"):
- if d.party_type in ('Customer', 'Supplier'):
+ if d.party_type in ("Customer", "Supplier"):
party_gle_currency = get_party_gle_currency(d.party_type, d.party, self.company)
party_account_currency = get_account_currency(d.account)
- party_currency = frappe.db.get_value(d.party_type, d.party, 'default_currency')
-
+ party_currency = frappe.db.get_value(d.party_type, d.party, "default_currency")
+
if not party_gle_currency and (party_account_currency != party_currency):
- frappe.throw(_("Party Account {0} currency and default party currency should be same").format(frappe.bold(d.account)))
->>>>>>> 417d6abcf4 (fix: Party account validation in JV)
-=======
->>>>>>> 5b8726405d (fix: Remove validation from Journal Entry)
+ frappe.throw(
+ _("Party Account {0} currency and default party currency should be same").format(
+ frappe.bold(d.account)
+ )
+ )
def check_credit_limit(self):
customers = list(
diff --git a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py
index 8a8e186a826a..a944a3738328 100644
--- a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py
+++ b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py
@@ -78,16 +78,10 @@ def test_cost_center_wise_posting(self):
expense_account="Cost of Goods Sold - TPC",
rate=400,
debit_to="Debtors - TPC",
-<<<<<<< HEAD
-<<<<<<< HEAD
-=======
- currency="USD"
->>>>>>> 60915e874d (test: Update test cases for currency change validation)
-=======
currency="USD",
customer="_Test Customer USD",
->>>>>>> 65232edfd5 (test: Update test cases)
)
+
create_sales_invoice(
company=company,
cost_center=cost_center2,
@@ -95,15 +89,8 @@ def test_cost_center_wise_posting(self):
expense_account="Cost of Goods Sold - TPC",
rate=200,
debit_to="Debtors - TPC",
-<<<<<<< HEAD
-<<<<<<< HEAD
-=======
- currency="USD"
->>>>>>> 60915e874d (test: Update test cases for currency change validation)
-=======
currency="USD",
customer="_Test Customer USD",
->>>>>>> 65232edfd5 (test: Update test cases)
)
pcv = self.make_period_closing_voucher(submit=False)
diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
index 709f0a52eecb..4b81a7d6a239 100644
--- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
@@ -768,41 +768,6 @@ def test_remove_pricing_rule(self):
frappe.get_doc("Item Price", {"item_code": "Water Flask"}).delete()
item.delete()
-<<<<<<< HEAD
-=======
- def test_multiple_pricing_rules_with_min_qty(self):
- make_pricing_rule(
- discount_percentage=20,
- selling=1,
- priority=1,
- min_qty=4,
- apply_multiple_pricing_rules=1,
- title="_Test Pricing Rule with Min Qty - 1",
- )
- make_pricing_rule(
- discount_percentage=10,
- selling=1,
- priority=2,
- min_qty=4,
- apply_multiple_pricing_rules=1,
- title="_Test Pricing Rule with Min Qty - 2",
- )
-
- si = create_sales_invoice(do_not_submit=True, customer="_Test Customer 1", qty=1)
- item = si.items[0]
- item.stock_qty = 1
- si.save()
- self.assertFalse(item.discount_percentage)
- item.qty = 5
- item.stock_qty = 5
- si.save()
- self.assertEqual(item.discount_percentage, 30)
- si.delete()
-
- frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule with Min Qty - 1")
- frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule with Min Qty - 2")
-
->>>>>>> 65232edfd5 (test: Update test cases)
test_dependencies = ["Campaign"]
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 60ff067a91f7..01586b3de1c7 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -35,6 +35,7 @@
from erpnext.accounts.party import (
get_party_account,
get_party_account_currency,
+ get_party_gle_currency,
validate_party_frozen_disabled,
)
from erpnext.accounts.utils import get_account_currency, get_fiscal_years, validate_fiscal_year
@@ -44,12 +45,6 @@
set_print_templates_for_taxes,
)
from erpnext.controllers.sales_and_purchase_return import validate_return
-<<<<<<< HEAD
-=======
-from erpnext.accounts.party import get_party_account_currency, validate_party_frozen_disabled, get_party_gle_currency
-from erpnext.accounts.doctype.pricing_rule.utils import (apply_pricing_rule_on_transaction,
- apply_pricing_rule_for_free_items, get_applied_pricing_rules)
->>>>>>> 80c85dd17c (fix: Account currency validation for first transaction)
from erpnext.exceptions import InvalidCurrency
from erpnext.setup.utils import get_exchange_rate
from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
@@ -1453,20 +1448,25 @@ def validate_currency(self):
# from creating a sales invoice if sales order is already created
def validate_party_account_currency(self):
- if self.doctype not in ('Sales Invoice', 'Purchase Invoice'):
+ if self.doctype not in ("Sales Invoice", "Purchase Invoice"):
return
- if self.is_opening == 'Yes':
+ if self.is_opening == "Yes":
return
party_type, party = self.get_party()
party_gle_currency = get_party_gle_currency(party_type, party, self.company)
- party_account = self.get('debit_to') if self.doctype == 'Sales Invoice' else self.get('credit_to')
+ party_account = (
+ self.get("debit_to") if self.doctype == "Sales Invoice" else self.get("credit_to")
+ )
party_account_currency = get_account_currency(party_account)
if not party_gle_currency and (party_account_currency != self.currency):
- frappe.throw(_("Party Account {0} currency and document currency should be same").format(frappe.bold(party_account)))
-
+ frappe.throw(
+ _("Party Account {0} currency and document currency should be same").format(
+ frappe.bold(party_account)
+ )
+ )
def delink_advance_entries(self, linked_doc_name):
total_allocated_amount = 0
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
index 713e5b3501e5..db61e0d9c55e 100755
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
@@ -12,6 +12,7 @@
from frappe.model.mapper import get_mapped_doc
from frappe.utils import flt, get_link_to_form, get_time, getdate
+from erpnext import get_company_currency
from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import (
get_income_account,
get_receivable_account,
@@ -22,7 +23,6 @@
manage_fee_validity,
)
from erpnext.hr.doctype.employee.employee import is_holiday
-<<<<<<< HEAD
class MaximumCapacityError(frappe.ValidationError):
@@ -32,11 +32,6 @@ class MaximumCapacityError(frappe.ValidationError):
class OverlapError(frappe.ValidationError):
pass
-=======
-from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_receivable_account, get_income_account
-from erpnext.healthcare.utils import check_fee_validity, get_service_item_and_practitioner_charge, manage_fee_validity
-from erpnext import get_company_currency
->>>>>>> 60915e874d (test: Update test cases for currency change validation)
class PatientAppointment(Document):
def validate(self):
@@ -257,17 +252,12 @@ def invoice_appointment(appointment_doc):
def create_sales_invoice(appointment_doc):
sales_invoice = frappe.new_doc("Sales Invoice")
sales_invoice.patient = appointment_doc.patient
-<<<<<<< HEAD
+
sales_invoice.customer = frappe.get_value("Patient", appointment_doc.patient, "customer")
-=======
- sales_invoice.customer = frappe.get_value('Patient', appointment_doc.patient, 'customer')
- sales_invoice.currency = frappe.get_value('Customer', sales_invoice.customer, 'default_currency') \
-<<<<<<< HEAD
- or get_company_currency(appointment_doc.currency)
->>>>>>> 60915e874d (test: Update test cases for currency change validation)
-=======
- or get_company_currency(appointment_doc.company)
->>>>>>> c10a22529c (test: fix property name)
+ sales_invoice.currency = frappe.get_value(
+ "Customer", sales_invoice.customer, "default_currency"
+ ) or get_company_currency(appointment_doc.currency)
+
sales_invoice.appointment = appointment_doc.name
sales_invoice.due_date = getdate()
sales_invoice.company = appointment_doc.company
diff --git a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
index 274f1afdaae7..21c481dac42b 100644
--- a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
@@ -235,206 +235,24 @@ def test_invalid_healthcare_service_unit_validation(self):
)
ip_record1 = frappe.get_doc("Inpatient Record", ip_record.name)
mark_invoiced_inpatient_occupancy(ip_record1)
-<<<<<<< HEAD
- discharge_patient(ip_record1, now_datetime())
-
- def test_payment_should_be_mandatory_for_new_patient_appointment(self):
- frappe.db.set_value("Healthcare Settings", None, "enable_free_follow_ups", 1)
- frappe.db.set_value("Healthcare Settings", None, "automate_appointment_invoicing", 1)
- frappe.db.set_value("Healthcare Settings", None, "max_visits", 3)
- frappe.db.set_value("Healthcare Settings", None, "valid_days", 30)
-
- patient = create_patient()
- assert check_is_new_patient(patient)
- payment_required = check_payment_fields_reqd(patient)
- assert payment_required is True
-
- def test_sales_invoice_should_be_generated_for_new_patient_appointment(self):
- patient, practitioner = create_healthcare_docs()
- frappe.db.set_value("Healthcare Settings", None, "automate_appointment_invoicing", 1)
- invoice_count = frappe.db.count("Sales Invoice")
-
- assert check_is_new_patient(patient)
- create_appointment(patient, practitioner, nowdate())
- new_invoice_count = frappe.db.count("Sales Invoice")
-
- assert new_invoice_count == invoice_count + 1
-
- def test_overlap_appointment(self):
- from erpnext.healthcare.doctype.patient_appointment.patient_appointment import OverlapError
-
- patient, practitioner = create_healthcare_docs(id=1)
- patient_1, practitioner_1 = create_healthcare_docs(id=2)
- service_unit = create_service_unit(id=0)
- service_unit_1 = create_service_unit(id=1)
- appointment = create_appointment(
- patient, practitioner, nowdate(), service_unit=service_unit
- ) # valid
-
- # patient and practitioner cannot have overlapping appointments
- appointment = create_appointment(
- patient, practitioner, nowdate(), service_unit=service_unit, save=0
- )
- self.assertRaises(OverlapError, appointment.save)
- appointment = create_appointment(
- patient, practitioner, nowdate(), service_unit=service_unit_1, save=0
- ) # diff service unit
- self.assertRaises(OverlapError, appointment.save)
- appointment = create_appointment(
- patient, practitioner, nowdate(), save=0
- ) # with no service unit link
- self.assertRaises(OverlapError, appointment.save)
-
- # patient cannot have overlapping appointments with other practitioners
- appointment = create_appointment(
- patient, practitioner_1, nowdate(), service_unit=service_unit, save=0
- )
- self.assertRaises(OverlapError, appointment.save)
- appointment = create_appointment(
- patient, practitioner_1, nowdate(), service_unit=service_unit_1, save=0
- )
- self.assertRaises(OverlapError, appointment.save)
- appointment = create_appointment(patient, practitioner_1, nowdate(), save=0)
- self.assertRaises(OverlapError, appointment.save)
-
- # practitioner cannot have overlapping appointments with other patients
- appointment = create_appointment(
- patient_1, practitioner, nowdate(), service_unit=service_unit, save=0
- )
- self.assertRaises(OverlapError, appointment.save)
- appointment = create_appointment(
- patient_1, practitioner, nowdate(), service_unit=service_unit_1, save=0
- )
- self.assertRaises(OverlapError, appointment.save)
- appointment = create_appointment(patient_1, practitioner, nowdate(), save=0)
- self.assertRaises(OverlapError, appointment.save)
-
- def test_service_unit_capacity(self):
- from erpnext.healthcare.doctype.patient_appointment.patient_appointment import (
- MaximumCapacityError,
- OverlapError,
- )
-
- practitioner = create_practitioner()
- capacity = 3
- overlap_service_unit_type = create_service_unit_type(
- id=10, allow_appointments=1, overlap_appointments=1
- )
- overlap_service_unit = create_service_unit(
- id=100, service_unit_type=overlap_service_unit_type, service_unit_capacity=capacity
- )
-
- for i in range(0, capacity):
- patient = create_patient(id=i)
- create_appointment(patient, practitioner, nowdate(), service_unit=overlap_service_unit) # valid
- appointment = create_appointment(
- patient, practitioner, nowdate(), service_unit=overlap_service_unit, save=0
- ) # overlap
- self.assertRaises(OverlapError, appointment.save)
-
- patient = create_patient(id=capacity)
- appointment = create_appointment(
- patient, practitioner, nowdate(), service_unit=overlap_service_unit, save=0
- )
- self.assertRaises(MaximumCapacityError, appointment.save)
-
- def test_patient_appointment_should_consider_permissions_while_fetching_appointments(self):
- patient, practitioner = create_healthcare_docs()
- create_appointment(patient, practitioner, nowdate())
-
- patient, new_practitioner = create_healthcare_docs(id=2)
- create_appointment(patient, new_practitioner, nowdate())
-
- roles = [{"doctype": "Has Role", "role": "Physician"}]
- user = create_user(roles=roles)
- new_practitioner = frappe.get_doc("Healthcare Practitioner", new_practitioner)
- new_practitioner.user_id = user.email
- new_practitioner.save()
-
- frappe.set_user(user.name)
- appointments = frappe.get_list("Patient Appointment")
- assert len(appointments) == 1
-
- frappe.set_user("Administrator")
- appointments = frappe.get_list("Patient Appointment")
- assert len(appointments) == 2
-
-
-def create_healthcare_docs(id=0):
- patient = create_patient(id)
- practitioner = create_practitioner(id)
-
- return patient, practitioner
-
-
-def create_patient(
- id=0, patient_name=None, email=None, mobile=None, customer=None, create_user=False
-):
- if frappe.db.exists("Patient", {"firstname": f"_Test Patient {str(id)}"}):
- patient = frappe.db.get_value("Patient", {"first_name": f"_Test Patient {str(id)}"}, ["name"])
- return patient
-
- patient = frappe.new_doc("Patient")
- patient.first_name = patient_name if patient_name else f"_Test Patient {str(id)}"
- patient.sex = "Female"
- patient.mobile = mobile
- patient.email = email
- patient.customer = customer
- patient.invite_user = create_user
- patient.save(ignore_permissions=True)
-
- return patient.name
-
-
-def create_medical_department(id=0):
- if frappe.db.exists("Medical Department", f"_Test Medical Department {str(id)}"):
- return f"_Test Medical Department {str(id)}"
-
- medical_department = frappe.new_doc("Medical Department")
- medical_department.department = f"_Test Medical Department {str(id)}"
- medical_department.save(ignore_permissions=True)
-
- return medical_department.name
-
-
-def create_practitioner(id=0, medical_department=None):
- if frappe.db.exists(
- "Healthcare Practitioner", {"firstname": f"_Test Healthcare Practitioner {str(id)}"}
- ):
- practitioner = frappe.db.get_value(
- "Healthcare Practitioner", {"firstname": f"_Test Healthcare Practitioner {str(id)}"}, ["name"]
- )
- return practitioner
-
- practitioner = frappe.new_doc("Healthcare Practitioner")
- practitioner.first_name = f"_Test Healthcare Practitioner {str(id)}"
- practitioner.gender = "Female"
- practitioner.department = medical_department or create_medical_department(id)
- practitioner.op_consulting_charge = 500
- practitioner.inpatient_visit_charge = 500
- practitioner.save(ignore_permissions=True)
-
- return practitioner.name
-
-=======
discharge_patient(ip_record1)
def create_healthcare_docs():
patient = create_patient()
- practitioner = frappe.db.exists('Healthcare Practitioner', '_Test Healthcare Practitioner')
- medical_department = frappe.db.exists('Medical Department', '_Test Medical Department')
+ practitioner = frappe.db.exists("Healthcare Practitioner", "_Test Healthcare Practitioner")
+ medical_department = frappe.db.exists("Medical Department", "_Test Medical Department")
if not medical_department:
- medical_department = frappe.new_doc('Medical Department')
- medical_department.department = '_Test Medical Department'
+ medical_department = frappe.new_doc("Medical Department")
+ medical_department.department = "_Test Medical Department"
medical_department.save(ignore_permissions=True)
medical_department = medical_department.name
if not practitioner:
- practitioner = frappe.new_doc('Healthcare Practitioner')
- practitioner.first_name = '_Test Healthcare Practitioner'
- practitioner.gender = 'Female'
+ practitioner = frappe.new_doc("Healthcare Practitioner")
+ practitioner.first_name = "_Test Healthcare Practitioner"
+ practitioner.gender = "Female"
practitioner.department = medical_department
practitioner.op_consulting_charge = 500
practitioner.inpatient_visit_charge = 500
@@ -443,17 +261,18 @@ def create_healthcare_docs():
return patient, medical_department, practitioner
+
def create_patient():
- patient = frappe.db.exists('Patient', '_Test Patient')
+ patient = frappe.db.exists("Patient", "_Test Patient")
if not patient:
- patient = frappe.new_doc('Patient')
- patient.first_name = '_Test Patient'
- patient.sex = 'Female'
- patient.default_currency = 'INR'
+ patient = frappe.new_doc("Patient")
+ patient.first_name = "_Test Patient"
+ patient.sex = "Female"
+ patient.default_currency = "INR"
patient.save(ignore_permissions=True)
patient = patient.name
return patient
->>>>>>> 30876a105c (test: Set default currency for patient)
+
def create_encounter(appointment):
if appointment:
diff --git a/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py
index b82894c366b9..6cb2a24e6af1 100644
--- a/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py
+++ b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py
@@ -4,13 +4,10 @@
import frappe
from frappe.model.document import Document
-<<<<<<< HEAD
from frappe.utils import flt
-=======
-from frappe.utils import flt, today
from erpnext import get_company_currency
->>>>>>> 60915e874d (test: Update test cases for currency change validation)
+
class TherapyPlan(Document):
def validate(self):
@@ -76,13 +73,10 @@ def make_sales_invoice(reference_name, patient, company, therapy_plan_template):
si = frappe.new_doc("Sales Invoice")
si.company = company
si.patient = patient
-<<<<<<< HEAD
si.customer = frappe.db.get_value("Patient", patient, "customer")
-=======
- si.customer = frappe.db.get_value('Patient', patient, 'customer')
- si.currency = frappe.get_value('Customer', si.customer, 'default_currency') \
- or get_company_currency(si.company)
->>>>>>> 60915e874d (test: Update test cases for currency change validation)
+ si.currency = frappe.get_value(
+ "Customer", si.customer, "default_currency"
+ ) or get_company_currency(si.company)
item = frappe.db.get_value("Therapy Plan Template", therapy_plan_template, "linked_item")
price_list, price_list_currency = frappe.db.get_values(
diff --git a/erpnext/non_profit/doctype/membership/membership.py b/erpnext/non_profit/doctype/membership/membership.py
index c420a2879b7f..7f7abd065949 100644
--- a/erpnext/non_profit/doctype/membership/membership.py
+++ b/erpnext/non_profit/doctype/membership/membership.py
@@ -13,12 +13,9 @@
from frappe.utils import add_days, add_months, add_years, get_link_to_form, getdate, nowdate
import erpnext
-<<<<<<< HEAD
+from erpnext import get_company_currency
from erpnext.non_profit.doctype.member.member import create_member
-=======
-from erpnext import get_company_currency
->>>>>>> 60915e874d (test: Update test cases for currency change validation)
class Membership(Document):
def validate(self):
@@ -202,35 +199,17 @@ def generate_and_send_invoice(self):
def make_invoice(membership, member, plan, settings):
-<<<<<<< HEAD
invoice = frappe.get_doc(
{
"doctype": "Sales Invoice",
"customer": member.customer,
"debit_to": settings.membership_debit_account,
- "currency": membership.currency,
+ "currency": membership.currency or get_company_currency(settings.company),
"company": settings.company,
"is_pos": 0,
"items": [{"item_code": plan.linked_item, "rate": membership.amount, "qty": 1}],
}
)
-=======
- invoice = frappe.get_doc({
- "doctype": "Sales Invoice",
- "customer": member.customer,
- "debit_to": settings.membership_debit_account,
- "currency": membership.currency or get_company_currency(settings.company),
- "company": settings.company,
- "is_pos": 0,
- "items": [
- {
- "item_code": plan.linked_item,
- "rate": membership.amount,
- "qty": 1
- }
- ]
- })
->>>>>>> 60915e874d (test: Update test cases for currency change validation)
invoice.set_missing_values()
invoice.insert()
invoice.submit()
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index 441bfc1b63ca..65c30de09786 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -1295,58 +1295,6 @@ def test_po_to_pi_and_po_to_pr_worflow_partial(self):
self.assertEqual(pr.status, "To Bill")
self.assertAlmostEqual(pr.per_billed, 50.0, places=2)
-<<<<<<< HEAD
-=======
- def test_purchase_receipt_with_exchange_rate_difference(self):
- from erpnext.accounts.doctype.purchase_invoice.purchase_invoice import (
- make_purchase_receipt as create_purchase_receipt,
- )
- from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import (
- make_purchase_invoice as create_purchase_invoice,
- )
- from erpnext.accounts.party import add_party_account
-
- add_party_account(
- "Supplier",
- "_Test Supplier USD",
- "_Test Company with perpetual inventory",
- "_Test Payable USD - TCP1",
- )
-
- pi = create_purchase_invoice(
- company="_Test Company with perpetual inventory",
- cost_center="Main - TCP1",
- warehouse="Stores - TCP1",
- expense_account="_Test Account Cost for Goods Sold - TCP1",
- currency="USD",
- conversion_rate=70,
- supplier="_Test Supplier USD",
- )
-
- pr = create_purchase_receipt(pi.name)
- pr.conversion_rate = 80
- pr.items[0].purchase_invoice = pi.name
- pr.items[0].purchase_invoice_item = pi.items[0].name
-
- pr.save()
- pr.submit()
-
- # Get exchnage gain and loss account
- exchange_gain_loss_account = frappe.db.get_value(
- "Company", pr.company, "exchange_gain_loss_account"
- )
-
- # fetching the latest GL Entry with exchange gain and loss account account
- amount = frappe.db.get_value(
- "GL Entry", {"account": exchange_gain_loss_account, "voucher_no": pr.name}, "credit"
- )
- discrepancy_caused_by_exchange_rate_diff = abs(
- pi.items[0].base_net_amount - pr.items[0].base_net_amount
- )
-
- self.assertEqual(discrepancy_caused_by_exchange_rate_diff, amount)
-
->>>>>>> bc34737709 (chore: Update test case)
def test_payment_terms_are_fetched_when_creating_purchase_invoice(self):
from erpnext.accounts.doctype.payment_entry.test_payment_entry import (
create_payment_terms_template,
From 3fab8a22133e963a06892a415feb1f8168e795a1 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Wed, 25 May 2022 19:20:09 +0530
Subject: [PATCH 40/48] chore: Remove unintended changes
---
.../doctype/journal_entry/journal_entry.py | 16 +-
.../doctype/lab_test/test_lab_test.py | 6 -
.../patient_appointment.py | 6 -
.../test_patient_appointment.py | 216 +++++++++++++++---
.../doctype/therapy_plan/therapy_plan.py | 5 -
5 files changed, 180 insertions(+), 69 deletions(-)
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index cc6e6137a138..8660c18bf950 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -17,7 +17,7 @@
from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import (
get_party_tax_withholding_details,
)
-from erpnext.accounts.party import get_party_account, get_party_gle_currency
+from erpnext.accounts.party import get_party_account
from erpnext.accounts.utils import (
get_account_currency,
get_balance_on,
@@ -333,20 +333,6 @@ def validate_party(self):
)
)
- def validate_party_account_currency(self):
- for d in self.get("accounts"):
- if d.party_type in ("Customer", "Supplier"):
- party_gle_currency = get_party_gle_currency(d.party_type, d.party, self.company)
- party_account_currency = get_account_currency(d.account)
- party_currency = frappe.db.get_value(d.party_type, d.party, "default_currency")
-
- if not party_gle_currency and (party_account_currency != party_currency):
- frappe.throw(
- _("Party Account {0} currency and default party currency should be same").format(
- frappe.bold(d.account)
- )
- )
-
def check_credit_limit(self):
customers = list(
set(
diff --git a/erpnext/healthcare/doctype/lab_test/test_lab_test.py b/erpnext/healthcare/doctype/lab_test/test_lab_test.py
index 754ee94c3965..06c02d1ea079 100644
--- a/erpnext/healthcare/doctype/lab_test/test_lab_test.py
+++ b/erpnext/healthcare/doctype/lab_test/test_lab_test.py
@@ -163,14 +163,8 @@ def create_sales_invoice():
sales_invoice.patient = patient
sales_invoice.customer = frappe.db.get_value("Patient", patient, "customer")
sales_invoice.due_date = getdate()
-<<<<<<< HEAD
sales_invoice.company = "_Test Company"
sales_invoice.debit_to = get_receivable_account("_Test Company")
-=======
- sales_invoice.company = '_Test Company'
- sales_invoice.currency = 'INR'
- sales_invoice.debit_to = get_receivable_account('_Test Company')
->>>>>>> bcaf475295 (fix: Healthcare module accounting test cases)
tests = [insulin_resistance_template, blood_test_template]
for entry in tests:
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
index db61e0d9c55e..b6e30060437e 100755
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
@@ -12,7 +12,6 @@
from frappe.model.mapper import get_mapped_doc
from frappe.utils import flt, get_link_to_form, get_time, getdate
-from erpnext import get_company_currency
from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import (
get_income_account,
get_receivable_account,
@@ -252,12 +251,7 @@ def invoice_appointment(appointment_doc):
def create_sales_invoice(appointment_doc):
sales_invoice = frappe.new_doc("Sales Invoice")
sales_invoice.patient = appointment_doc.patient
-
sales_invoice.customer = frappe.get_value("Patient", appointment_doc.patient, "customer")
- sales_invoice.currency = frappe.get_value(
- "Customer", sales_invoice.customer, "default_currency"
- ) or get_company_currency(appointment_doc.currency)
-
sales_invoice.appointment = appointment_doc.name
sales_invoice.due_date = getdate()
sales_invoice.company = appointment_doc.company
diff --git a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
index 21c481dac42b..048547a93223 100644
--- a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
@@ -235,43 +235,185 @@ def test_invalid_healthcare_service_unit_validation(self):
)
ip_record1 = frappe.get_doc("Inpatient Record", ip_record.name)
mark_invoiced_inpatient_occupancy(ip_record1)
- discharge_patient(ip_record1)
-
-
-def create_healthcare_docs():
- patient = create_patient()
- practitioner = frappe.db.exists("Healthcare Practitioner", "_Test Healthcare Practitioner")
- medical_department = frappe.db.exists("Medical Department", "_Test Medical Department")
-
- if not medical_department:
- medical_department = frappe.new_doc("Medical Department")
- medical_department.department = "_Test Medical Department"
- medical_department.save(ignore_permissions=True)
- medical_department = medical_department.name
-
- if not practitioner:
- practitioner = frappe.new_doc("Healthcare Practitioner")
- practitioner.first_name = "_Test Healthcare Practitioner"
- practitioner.gender = "Female"
- practitioner.department = medical_department
- practitioner.op_consulting_charge = 500
- practitioner.inpatient_visit_charge = 500
- practitioner.save(ignore_permissions=True)
- practitioner = practitioner.name
-
- return patient, medical_department, practitioner
-
-
-def create_patient():
- patient = frappe.db.exists("Patient", "_Test Patient")
- if not patient:
- patient = frappe.new_doc("Patient")
- patient.first_name = "_Test Patient"
- patient.sex = "Female"
- patient.default_currency = "INR"
- patient.save(ignore_permissions=True)
- patient = patient.name
- return patient
+ discharge_patient(ip_record1, now_datetime())
+
+ def test_payment_should_be_mandatory_for_new_patient_appointment(self):
+ frappe.db.set_value("Healthcare Settings", None, "enable_free_follow_ups", 1)
+ frappe.db.set_value("Healthcare Settings", None, "automate_appointment_invoicing", 1)
+ frappe.db.set_value("Healthcare Settings", None, "max_visits", 3)
+ frappe.db.set_value("Healthcare Settings", None, "valid_days", 30)
+
+ patient = create_patient()
+ assert check_is_new_patient(patient)
+ payment_required = check_payment_fields_reqd(patient)
+ assert payment_required is True
+
+ def test_sales_invoice_should_be_generated_for_new_patient_appointment(self):
+ patient, practitioner = create_healthcare_docs()
+ frappe.db.set_value("Healthcare Settings", None, "automate_appointment_invoicing", 1)
+ invoice_count = frappe.db.count("Sales Invoice")
+
+ assert check_is_new_patient(patient)
+ create_appointment(patient, practitioner, nowdate())
+ new_invoice_count = frappe.db.count("Sales Invoice")
+
+ assert new_invoice_count == invoice_count + 1
+
+ def test_overlap_appointment(self):
+ from erpnext.healthcare.doctype.patient_appointment.patient_appointment import OverlapError
+
+ patient, practitioner = create_healthcare_docs(id=1)
+ patient_1, practitioner_1 = create_healthcare_docs(id=2)
+ service_unit = create_service_unit(id=0)
+ service_unit_1 = create_service_unit(id=1)
+ appointment = create_appointment(
+ patient, practitioner, nowdate(), service_unit=service_unit
+ ) # valid
+
+ # patient and practitioner cannot have overlapping appointments
+ appointment = create_appointment(
+ patient, practitioner, nowdate(), service_unit=service_unit, save=0
+ )
+ self.assertRaises(OverlapError, appointment.save)
+ appointment = create_appointment(
+ patient, practitioner, nowdate(), service_unit=service_unit_1, save=0
+ ) # diff service unit
+ self.assertRaises(OverlapError, appointment.save)
+ appointment = create_appointment(
+ patient, practitioner, nowdate(), save=0
+ ) # with no service unit link
+ self.assertRaises(OverlapError, appointment.save)
+
+ # patient cannot have overlapping appointments with other practitioners
+ appointment = create_appointment(
+ patient, practitioner_1, nowdate(), service_unit=service_unit, save=0
+ )
+ self.assertRaises(OverlapError, appointment.save)
+ appointment = create_appointment(
+ patient, practitioner_1, nowdate(), service_unit=service_unit_1, save=0
+ )
+ self.assertRaises(OverlapError, appointment.save)
+ appointment = create_appointment(patient, practitioner_1, nowdate(), save=0)
+ self.assertRaises(OverlapError, appointment.save)
+
+ # practitioner cannot have overlapping appointments with other patients
+ appointment = create_appointment(
+ patient_1, practitioner, nowdate(), service_unit=service_unit, save=0
+ )
+ self.assertRaises(OverlapError, appointment.save)
+ appointment = create_appointment(
+ patient_1, practitioner, nowdate(), service_unit=service_unit_1, save=0
+ )
+ self.assertRaises(OverlapError, appointment.save)
+ appointment = create_appointment(patient_1, practitioner, nowdate(), save=0)
+ self.assertRaises(OverlapError, appointment.save)
+
+ def test_service_unit_capacity(self):
+ from erpnext.healthcare.doctype.patient_appointment.patient_appointment import (
+ MaximumCapacityError,
+ OverlapError,
+ )
+
+ practitioner = create_practitioner()
+ capacity = 3
+ overlap_service_unit_type = create_service_unit_type(
+ id=10, allow_appointments=1, overlap_appointments=1
+ )
+ overlap_service_unit = create_service_unit(
+ id=100, service_unit_type=overlap_service_unit_type, service_unit_capacity=capacity
+ )
+
+ for i in range(0, capacity):
+ patient = create_patient(id=i)
+ create_appointment(patient, practitioner, nowdate(), service_unit=overlap_service_unit) # valid
+ appointment = create_appointment(
+ patient, practitioner, nowdate(), service_unit=overlap_service_unit, save=0
+ ) # overlap
+ self.assertRaises(OverlapError, appointment.save)
+
+ patient = create_patient(id=capacity)
+ appointment = create_appointment(
+ patient, practitioner, nowdate(), service_unit=overlap_service_unit, save=0
+ )
+ self.assertRaises(MaximumCapacityError, appointment.save)
+
+ def test_patient_appointment_should_consider_permissions_while_fetching_appointments(self):
+ patient, practitioner = create_healthcare_docs()
+ create_appointment(patient, practitioner, nowdate())
+
+ patient, new_practitioner = create_healthcare_docs(id=2)
+ create_appointment(patient, new_practitioner, nowdate())
+
+ roles = [{"doctype": "Has Role", "role": "Physician"}]
+ user = create_user(roles=roles)
+ new_practitioner = frappe.get_doc("Healthcare Practitioner", new_practitioner)
+ new_practitioner.user_id = user.email
+ new_practitioner.save()
+
+ frappe.set_user(user.name)
+ appointments = frappe.get_list("Patient Appointment")
+ assert len(appointments) == 1
+
+ frappe.set_user("Administrator")
+ appointments = frappe.get_list("Patient Appointment")
+ assert len(appointments) == 2
+
+
+def create_healthcare_docs(id=0):
+ patient = create_patient(id)
+ practitioner = create_practitioner(id)
+
+ return patient, practitioner
+
+
+def create_patient(
+ id=0, patient_name=None, email=None, mobile=None, customer=None, create_user=False
+):
+ if frappe.db.exists("Patient", {"firstname": f"_Test Patient {str(id)}"}):
+ patient = frappe.db.get_value("Patient", {"first_name": f"_Test Patient {str(id)}"}, ["name"])
+ return patient
+
+ patient = frappe.new_doc("Patient")
+ patient.first_name = patient_name if patient_name else f"_Test Patient {str(id)}"
+ patient.sex = "Female"
+ patient.mobile = mobile
+ patient.email = email
+ patient.customer = customer
+ patient.invite_user = create_user
+ patient.save(ignore_permissions=True)
+
+ return patient.name
+
+
+def create_medical_department(id=0):
+ if frappe.db.exists("Medical Department", f"_Test Medical Department {str(id)}"):
+ return f"_Test Medical Department {str(id)}"
+
+ medical_department = frappe.new_doc("Medical Department")
+ medical_department.department = f"_Test Medical Department {str(id)}"
+ medical_department.save(ignore_permissions=True)
+
+ return medical_department.name
+
+
+def create_practitioner(id=0, medical_department=None):
+ if frappe.db.exists(
+ "Healthcare Practitioner", {"firstname": f"_Test Healthcare Practitioner {str(id)}"}
+ ):
+ practitioner = frappe.db.get_value(
+ "Healthcare Practitioner", {"firstname": f"_Test Healthcare Practitioner {str(id)}"}, ["name"]
+ )
+ return practitioner
+
+ practitioner = frappe.new_doc("Healthcare Practitioner")
+ practitioner.first_name = f"_Test Healthcare Practitioner {str(id)}"
+ practitioner.gender = "Female"
+ practitioner.department = medical_department or create_medical_department(id)
+ practitioner.op_consulting_charge = 500
+ practitioner.inpatient_visit_charge = 500
+ practitioner.save(ignore_permissions=True)
+
+ return practitioner.name
def create_encounter(appointment):
diff --git a/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py
index 6cb2a24e6af1..44f0a9785c44 100644
--- a/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py
+++ b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py
@@ -6,8 +6,6 @@
from frappe.model.document import Document
from frappe.utils import flt
-from erpnext import get_company_currency
-
class TherapyPlan(Document):
def validate(self):
@@ -74,9 +72,6 @@ def make_sales_invoice(reference_name, patient, company, therapy_plan_template):
si.company = company
si.patient = patient
si.customer = frappe.db.get_value("Patient", patient, "customer")
- si.currency = frappe.get_value(
- "Customer", si.customer, "default_currency"
- ) or get_company_currency(si.company)
item = frappe.db.get_value("Therapy Plan Template", therapy_plan_template, "linked_item")
price_list, price_list_currency = frappe.db.get_values(
From 611d1af526839ff4ceb5628be5fff385c37c9294 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Wed, 25 May 2022 17:58:30 +0530
Subject: [PATCH 41/48] fix: Loan Doc query in Bank Reconciliation Statement
(cherry picked from commit 147fc8fde704bc8c96dac2a24686cf7af5f7712b)
---
.../bank_reconciliation_statement.py | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py
index f3ccc868c4cb..e5950b764ee3 100644
--- a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py
+++ b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py
@@ -198,11 +198,12 @@ def get_loan_entries(filters):
amount_field = (loan_doc.disbursed_amount).as_("credit")
posting_date = (loan_doc.disbursement_date).as_("posting_date")
account = loan_doc.disbursement_account
+ salary_condition = loan_doc.docstatus == 1
else:
amount_field = (loan_doc.amount_paid).as_("debit")
posting_date = (loan_doc.posting_date).as_("posting_date")
account = loan_doc.payment_account
-
+ salary_condition = loan_doc.repay_from_salary == 0
query = (
frappe.qb.from_(loan_doc)
.select(
@@ -214,15 +215,13 @@ def get_loan_entries(filters):
posting_date,
)
.where(loan_doc.docstatus == 1)
+ .where(salary_condition)
.where(account == filters.get("account"))
.where(posting_date <= getdate(filters.get("report_date")))
.where(ifnull(loan_doc.clearance_date, "4000-01-01") > getdate(filters.get("report_date")))
)
- if doctype == "Loan Repayment":
- query.where(loan_doc.repay_from_salary == 0)
-
- entries = query.run(as_dict=1)
+ entries = query.run(as_dict=1, debug=1)
loan_docs.extend(entries)
return loan_docs
@@ -267,15 +266,17 @@ def get_loan_amount(filters):
amount_field = Sum(loan_doc.disbursed_amount)
posting_date = (loan_doc.disbursement_date).as_("posting_date")
account = loan_doc.disbursement_account
+ salary_condition = loan_doc.docstatus == 1
else:
amount_field = Sum(loan_doc.amount_paid)
posting_date = (loan_doc.posting_date).as_("posting_date")
account = loan_doc.payment_account
-
+ salary_condition = loan_doc.repay_from_salary == 0
amount = (
frappe.qb.from_(loan_doc)
.select(amount_field)
.where(loan_doc.docstatus == 1)
+ .where(salary_condition)
.where(account == filters.get("account"))
.where(posting_date > getdate(filters.get("report_date")))
.where(ifnull(loan_doc.clearance_date, "4000-01-01") <= getdate(filters.get("report_date")))
From 74ddf261e92ba6d85afac1d86b9e3316c2f01f82 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Wed, 25 May 2022 17:59:40 +0530
Subject: [PATCH 42/48] chore: Linting Issues
(cherry picked from commit a1f53f8d31aa22e56fded4b75c9d53839043c3d0)
---
.../bank_reconciliation_statement.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py
index e5950b764ee3..5c70a404ef7c 100644
--- a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py
+++ b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py
@@ -221,7 +221,7 @@ def get_loan_entries(filters):
.where(ifnull(loan_doc.clearance_date, "4000-01-01") > getdate(filters.get("report_date")))
)
- entries = query.run(as_dict=1, debug=1)
+ entries = query.run(as_dict=1)
loan_docs.extend(entries)
return loan_docs
From cd00cb2fb730d59708b71b0b526af47fd3b8e7c5 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Wed, 25 May 2022 18:10:42 +0530
Subject: [PATCH 43/48] chore: Linting Issues
(cherry picked from commit 9e4a36089eef11902f1f3c8b5759ab42e50b8b00)
---
.../bank_reconciliation_statement.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py
index 5c70a404ef7c..c41d0d10ffee 100644
--- a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py
+++ b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py
@@ -204,6 +204,7 @@ def get_loan_entries(filters):
posting_date = (loan_doc.posting_date).as_("posting_date")
account = loan_doc.payment_account
salary_condition = loan_doc.repay_from_salary == 0
+
query = (
frappe.qb.from_(loan_doc)
.select(
From f14e9b7502aebde4c77305253cb704730a9accd1 Mon Sep 17 00:00:00 2001
From: xdlumertz
Date: Wed, 25 May 2022 11:09:59 -0300
Subject: [PATCH 44/48] fix: Chart data for monthly periodicity in Cash Flow
report (#31039)
fix: Chart data for monthly periodicity in Cash Flow report
(cherry picked from commit c5e922c76bced414679fbaad33d9a50d0b2c62f4)
---
erpnext/accounts/report/cash_flow/cash_flow.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/erpnext/accounts/report/cash_flow/cash_flow.py b/erpnext/accounts/report/cash_flow/cash_flow.py
index 7929d4aa2aef..ee924f86a6a1 100644
--- a/erpnext/accounts/report/cash_flow/cash_flow.py
+++ b/erpnext/accounts/report/cash_flow/cash_flow.py
@@ -263,7 +263,10 @@ def get_report_summary(summary_data, currency):
def get_chart_data(columns, data):
labels = [d.get("label") for d in columns[2:]]
datasets = [
- {"name": account.get("account").replace("'", ""), "values": [account.get("total")]}
+ {
+ "name": account.get("account").replace("'", ""),
+ "values": [account.get(d.get("fieldname")) for d in columns[2:]],
+ }
for account in data
if account.get("parent_account") == None and account.get("currency")
]
From 14422eaf59e24d2d1b6dbcd3dfd9825f1adea2fd Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Wed, 25 May 2022 20:06:31 +0530
Subject: [PATCH 45/48] chore: Update test cases
---
erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py | 2 +-
erpnext/healthcare/doctype/lab_test/test_lab_test.py | 1 +
.../doctype/patient_appointment/patient_appointment.py | 4 ++++
erpnext/healthcare/doctype/therapy_plan/therapy_plan.py | 5 +++++
4 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
index 4b81a7d6a239..5701402811ec 100644
--- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
@@ -712,7 +712,7 @@ def test_multiple_pricing_rules_with_min_qty(self):
title="_Test Pricing Rule with Min Qty - 2",
)
- si = create_sales_invoice(do_not_submit=True, customer="_Test Customer 1", qty=1, currency="USD")
+ si = create_sales_invoice(do_not_submit=True, customer="_Test Customer 1", qty=1)
item = si.items[0]
item.stock_qty = 1
si.save()
diff --git a/erpnext/healthcare/doctype/lab_test/test_lab_test.py b/erpnext/healthcare/doctype/lab_test/test_lab_test.py
index 06c02d1ea079..c08820f36be0 100644
--- a/erpnext/healthcare/doctype/lab_test/test_lab_test.py
+++ b/erpnext/healthcare/doctype/lab_test/test_lab_test.py
@@ -164,6 +164,7 @@ def create_sales_invoice():
sales_invoice.customer = frappe.db.get_value("Patient", patient, "customer")
sales_invoice.due_date = getdate()
sales_invoice.company = "_Test Company"
+ sales_invoice.currency = "INR"
sales_invoice.debit_to = get_receivable_account("_Test Company")
tests = [insulin_resistance_template, blood_test_template]
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
index b6e30060437e..34aa8650e197 100755
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
@@ -12,6 +12,7 @@
from frappe.model.mapper import get_mapped_doc
from frappe.utils import flt, get_link_to_form, get_time, getdate
+from erpnext import get_company_currency
from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import (
get_income_account,
get_receivable_account,
@@ -252,6 +253,9 @@ def create_sales_invoice(appointment_doc):
sales_invoice = frappe.new_doc("Sales Invoice")
sales_invoice.patient = appointment_doc.patient
sales_invoice.customer = frappe.get_value("Patient", appointment_doc.patient, "customer")
+ sales_invoice.currency = frappe.get_value(
+ "Customer", sales_invoice.customer, "default_currency"
+ ) or get_company_currency(appointment_doc.currency)
sales_invoice.appointment = appointment_doc.name
sales_invoice.due_date = getdate()
sales_invoice.company = appointment_doc.company
diff --git a/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py
index 44f0a9785c44..6cb2a24e6af1 100644
--- a/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py
+++ b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py
@@ -6,6 +6,8 @@
from frappe.model.document import Document
from frappe.utils import flt
+from erpnext import get_company_currency
+
class TherapyPlan(Document):
def validate(self):
@@ -72,6 +74,9 @@ def make_sales_invoice(reference_name, patient, company, therapy_plan_template):
si.company = company
si.patient = patient
si.customer = frappe.db.get_value("Patient", patient, "customer")
+ si.currency = frappe.get_value(
+ "Customer", si.customer, "default_currency"
+ ) or get_company_currency(si.company)
item = frappe.db.get_value("Therapy Plan Template", therapy_plan_template, "linked_item")
price_list, price_list_currency = frappe.db.get_values(
From 3d51d125bfeac08d47c5bb61193e7874ad7fdc9e Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Wed, 25 May 2022 23:52:40 +0530
Subject: [PATCH 46/48] chore: Update test case
---
.../doctype/patient_appointment/patient_appointment.py | 3 ++-
.../doctype/patient_appointment/test_patient_appointment.py | 1 +
erpnext/projects/doctype/timesheet/test_timesheet.py | 4 +++-
3 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
index 34aa8650e197..0d98fff04ff7 100755
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
@@ -255,7 +255,8 @@ def create_sales_invoice(appointment_doc):
sales_invoice.customer = frappe.get_value("Patient", appointment_doc.patient, "customer")
sales_invoice.currency = frappe.get_value(
"Customer", sales_invoice.customer, "default_currency"
- ) or get_company_currency(appointment_doc.currency)
+ ) or get_company_currency(appointment_doc.company)
+
sales_invoice.appointment = appointment_doc.name
sales_invoice.due_date = getdate()
sales_invoice.company = appointment_doc.company
diff --git a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
index 048547a93223..05e6b9cfe0d0 100644
--- a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
@@ -379,6 +379,7 @@ def create_patient(
patient.mobile = mobile
patient.email = email
patient.customer = customer
+ patient.default_currency = "INR"
patient.invite_user = create_user
patient.save(ignore_permissions=True)
diff --git a/erpnext/projects/doctype/timesheet/test_timesheet.py b/erpnext/projects/doctype/timesheet/test_timesheet.py
index 57bfd5b60743..7298c037a709 100644
--- a/erpnext/projects/doctype/timesheet/test_timesheet.py
+++ b/erpnext/projects/doctype/timesheet/test_timesheet.py
@@ -84,7 +84,9 @@ def test_sales_invoice_from_timesheet(self):
emp = make_employee("test_employee_6@salary.com")
timesheet = make_timesheet(emp, simulate=True, is_billable=1)
- sales_invoice = make_sales_invoice(timesheet.name, "_Test Item", "_Test Customer")
+ sales_invoice = make_sales_invoice(
+ timesheet.name, "_Test Item", "_Test Customer", currency="INR"
+ )
sales_invoice.due_date = nowdate()
sales_invoice.submit()
timesheet = frappe.get_doc("Timesheet", timesheet.name)
From 7df829f9cc9c73a068d1c4f7940a2c74242c7705 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Thu, 26 May 2022 09:03:18 +0530
Subject: [PATCH 47/48] chore: Update test case
---
.../erpnext_integrations/connectors/shopify_connection.py | 6 ++++++
.../doctype/shopify_settings/test_shopify_settings.py | 1 +
2 files changed, 7 insertions(+)
diff --git a/erpnext/erpnext_integrations/connectors/shopify_connection.py b/erpnext/erpnext_integrations/connectors/shopify_connection.py
index 4579a274ffa5..f28afbcd83a2 100644
--- a/erpnext/erpnext_integrations/connectors/shopify_connection.py
+++ b/erpnext/erpnext_integrations/connectors/shopify_connection.py
@@ -4,6 +4,7 @@
from frappe import _
from frappe.utils import cint, cstr, flt, get_datetime, get_request_session, getdate, nowdate
+from erpnext import get_company_currency
from erpnext.erpnext_integrations.doctype.shopify_log.shopify_log import (
dump_request_data,
make_shopify_log,
@@ -143,6 +144,10 @@ def create_sales_order(shopify_order, shopify_settings, company=None):
"taxes": get_order_taxes(shopify_order, shopify_settings),
"apply_discount_on": "Grand Total",
"discount_amount": get_discounted_amount(shopify_order),
+ "currency": frappe.get_value(
+ "Customer", customer or shopify_settings.default_customer, "default_currency"
+ )
+ or get_company_currency(shopify_settings.company),
}
)
@@ -178,6 +183,7 @@ def create_sales_invoice(shopify_order, shopify_settings, so, old_order_sync=Fal
si.set_posting_time = 1
si.posting_date = posting_date
si.due_date = posting_date
+ si.currency = so.currency
si.naming_series = shopify_settings.sales_invoice_series or "SI-Shopify-"
si.flags.ignore_mandatory = True
set_cost_center(si.items, shopify_settings.cost_center)
diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/test_shopify_settings.py b/erpnext/erpnext_integrations/doctype/shopify_settings/test_shopify_settings.py
index 7cc45d2115f4..47d6d438b065 100644
--- a/erpnext/erpnext_integrations/doctype/shopify_settings/test_shopify_settings.py
+++ b/erpnext/erpnext_integrations/doctype/shopify_settings/test_shopify_settings.py
@@ -58,6 +58,7 @@ def setup_shopify(cls):
"warehouse": "_Test Warehouse - _TC",
"cash_bank_account": "Cash - _TC",
"account": "Cash - _TC",
+ "company": "_Test Company",
"customer_group": "_Test Customer Group",
"cost_center": "Main - _TC",
"taxes": [{"shopify_tax": "International Shipping", "tax_account": "Legal Expenses - _TC"}],
From 8c2f2033615ec14a042ed4e69394b9933cbc450a Mon Sep 17 00:00:00 2001
From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com>
Date: Thu, 26 May 2022 10:32:10 +0530
Subject: [PATCH 48/48] fix: change project's actual_start_date fieldtype from
Data to Date (backport #31085) (#31135)
Co-authored-by: sersaber <93864988+sersaber@users.noreply.github.com>
Co-authored-by: Rucha Mahabal
---
erpnext/projects/doctype/project/project.json | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/erpnext/projects/doctype/project/project.json b/erpnext/projects/doctype/project/project.json
index 2570df70261f..4aeef81cbfbb 100644
--- a/erpnext/projects/doctype/project/project.json
+++ b/erpnext/projects/doctype/project/project.json
@@ -234,7 +234,7 @@
},
{
"fieldname": "actual_start_date",
- "fieldtype": "Data",
+ "fieldtype": "Date",
"label": "Actual Start Date",
"read_only": 1
},
@@ -458,7 +458,7 @@
"index_web_pages_for_search": 1,
"links": [],
"max_attachments": 4,
- "modified": "2021-04-28 16:36:11.654632",
+ "modified": "2022-05-25 22:45:06.108499",
"modified_by": "Administrator",
"module": "Projects",
"name": "Project",
@@ -502,4 +502,4 @@
"timeline_field": "customer",
"title_field": "project_name",
"track_seen": 1
-}
\ No newline at end of file
+}