From 17e5f4132ca8f3bf3d3d6dbac11d197dd390a484 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Thu, 10 Aug 2017 11:03:26 +0530 Subject: [PATCH 01/52] [tests] less verbose logs --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index beab4e119a..f7d28be009 100644 --- a/.travis.yml +++ b/.travis.yml @@ -53,6 +53,6 @@ before_script: script: - set -e - - bench --verbose run-tests + - bench run-tests - sleep 5 - - bench --verbose run-ui-tests --app erpnext + - bench run-ui-tests --app erpnext From e97f5874117d454fd53c84bf163a750e30d1f51a Mon Sep 17 00:00:00 2001 From: Manas Solanki Date: Thu, 10 Aug 2017 11:17:38 +0530 Subject: [PATCH 02/52] send the email via the background worker in the payment request (#10350) --- .../doctype/payment_request/payment_request.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py index a4f8232280..44a3644a0c 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.py +++ b/erpnext/accounts/doctype/payment_request/payment_request.py @@ -11,6 +11,7 @@ from erpnext.accounts.party import get_party_account from erpnext.accounts.utils import get_account_currency from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry, get_company_defaults from frappe.integrations.utils import get_payment_gateway_controller +from frappe.utils.background_jobs import enqueue class PaymentRequest(Document): def validate(self): @@ -143,9 +144,15 @@ class PaymentRequest(Document): def send_email(self): """send email with payment link""" - frappe.sendmail(recipients=self.email_to, sender=None, subject=self.subject, - message=self.get_message(), attachments=[frappe.attach_print(self.reference_doctype, - self.reference_name, file_name=self.reference_name, print_format=self.print_format)]) + email_args = { + "recipients": self.email_to, + "sender": None, + "subject": self.subject, + "message": self.get_message(), + "now": True, + "attachments": [frappe.attach_print(self.reference_doctype, self.reference_name, + file_name=self.reference_name, print_format=self.print_format)]} + enqueue(method=frappe.sendmail, queue='short', timeout=300, async=True, **email_args) def get_message(self): """return message with payment gateway link""" From a854ea00a5102d05760943af53bbb0dd66678a9b Mon Sep 17 00:00:00 2001 From: Manas Solanki Date: Thu, 10 Aug 2017 11:20:58 +0530 Subject: [PATCH 03/52] mark holiday in the employee monthly attendance sheet (#10349) --- .../monthly_attendance_sheet.py | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py index 05d3df565a..bb200a997e 100644 --- a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py +++ b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py @@ -15,6 +15,12 @@ def execute(filters=None): att_map = get_attendance_list(conditions, filters) emp_map = get_employee_details() + holiday_list = [emp_map[d]["holiday_list"] for d in emp_map if emp_map[d]["holiday_list"]] + default_holiday_list = frappe.db.get_value("Company", filters.get("company"), "default_holiday_list") + holiday_list.append(default_holiday_list) + holiday_list = list(set(holiday_list)) + holiday_map = get_holiday(holiday_list, filters["month"]) + data = [] for emp in sorted(att_map): emp_det = emp_map.get(emp) @@ -27,7 +33,11 @@ def execute(filters=None): total_p = total_a = total_l = 0.0 for day in range(filters["total_days_in_month"]): status = att_map.get(emp).get(day + 1, "None") - status_map = {"Present": "P", "Absent": "A", "Half Day": "H", "On Leave": "L", "None": ""} + status_map = {"Present": "P", "Absent": "A", "Half Day": "HD", "On Leave": "L", "None": "", "Holiday":"H"} + if status == "None" and holiday_map: + emp_holiday_list = emp_det.holiday_list if emp_det.holiday_list else default_holiday_list + if (day+1) in holiday_map[emp_holiday_list]: + status = "Holiday" row.append(status_map[status]) if status == "Present": @@ -88,13 +98,21 @@ def get_conditions(filters): def get_employee_details(): emp_map = frappe._dict() - for d in frappe.db.sql("""select name, employee_name, designation, - department, branch, company - from tabEmployee""", as_dict=1): + for d in frappe.db.sql("""select name, employee_name, designation, department, branch, company, + holiday_list from tabEmployee""", as_dict=1): emp_map.setdefault(d.name, d) return emp_map +def get_holiday(holiday_list, month): + holiday_map = frappe._dict() + for d in holiday_list: + if d: + holiday_map.setdefault(d, frappe.db.sql_list('''select day(holiday_date) from `tabHoliday` + where parent=%s and month(holiday_date)=%s''', (d, month))) + + return holiday_map + @frappe.whitelist() def get_attendance_years(): year_list = frappe.db.sql_list("""select distinct YEAR(attendance_date) from tabAttendance ORDER BY YEAR(attendance_date) DESC""") From 5ae39ae79a84cbc421d87811cad194fa9179f30c Mon Sep 17 00:00:00 2001 From: Shreya Shah Date: Thu, 10 Aug 2017 16:20:47 +0530 Subject: [PATCH 04/52] Get Quotation requests and send emails to suppliers (#10356) --- .../test_request_for_quotation.js | 74 +++++++++++++++++++ erpnext/tests/ui/tests.txt | 1 + 2 files changed, 75 insertions(+) create mode 100644 erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.js diff --git a/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.js new file mode 100644 index 0000000000..75760bfcf1 --- /dev/null +++ b/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.js @@ -0,0 +1,74 @@ +QUnit.module('Buying'); + +QUnit.test("test: request_for_quotation", function(assert) { + assert.expect(14); + let done = assert.async(); + let date; + frappe.run_serially([ + () => { + date = frappe.datetime.add_days(frappe.datetime.now_date(), 10); + return frappe.tests.make('Request for Quotation', [ + {transaction_date: date}, + {company: 'Test Company'}, + {suppliers: [ + [ + {"supplier": 'Test Supplier'}, + {"email_id": 'test@supplier.com'} + ] + ]}, + {items: [ + [ + {"item_code": 'Test Product 4'}, + {"qty": 5}, + {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(),20)}, + {"warehouse": 'All Warehouses - TC'} + ] + ]}, + {message_for_supplier: 'Please supply the specified items at the best possible rates'}, + {tc_name: 'Test Term 1'} + ]); + }, + () => { + assert.ok(cur_frm.doc.transaction_date == date, "Date correct"); + assert.ok(cur_frm.doc.company == 'Test Company', "Company correct"); + assert.ok(cur_frm.doc.suppliers[0].supplier_name == 'Test Supplier', "Supplier name correct"); + assert.ok(cur_frm.doc.suppliers[0].contact == 'Contact 3-Test Supplier', "Contact correct"); + assert.ok(cur_frm.doc.suppliers[0].email_id == 'test@supplier.com', "Email id correct"); + assert.ok(cur_frm.doc.items[0].item_name == 'Test Product 4', "Item Name correct"); + assert.ok(cur_frm.doc.items[0].warehouse == 'All Warehouses - TC', "Warehouse correct"); + assert.ok(cur_frm.doc.message_for_supplier == 'Please supply the specified items at the best possible rates', "Reply correct"); + assert.ok(cur_frm.doc.tc_name == 'Test Term 1', "Term name correct"); + }, + () => frappe.timeout(0.3), + () => cur_frm.print_doc(), + () => frappe.timeout(1), + () => { + assert.ok($('.btn-print-print').is(':visible'), "Print Format Available"); + assert.ok($('.section-break+ .section-break .column-break:nth-child(1) .value').text().includes("Test Product 4"), "Print Preview Works"); + }, + () => cur_frm.print_doc(), + () => frappe.timeout(1), + () => frappe.click_button('Get items from'), + () => frappe.timeout(0.3), + () => frappe.click_link('Material Request'), + () => frappe.timeout(1), + () => { + assert.ok($('h4').text().includes('Select Material Requests'), "Getting items from material requests work"); + }, + () => frappe.click_button('Close'), + () => frappe.timeout(1), + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(1), + () => { + assert.ok(cur_frm.doc.docstatus == 1, "Quotation request submitted"); + }, + () => frappe.click_button('Send Supplier Emails'), + () => frappe.timeout(3), + () => { + assert.ok($('div.modal.fade.in > div.modal-dialog > div > div.modal-body.ui-front > div.msgprint').text().includes("Email sent to supplier Test Supplier"), "Send emails working"); + }, + () => frappe.click_button('Close'), + () => done() + ]); +}); \ No newline at end of file diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index 5634935793..0dc19babef 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -77,3 +77,4 @@ erpnext/schools/doctype/assessment_plan/test_assessment_plan.js erpnext/schools/doctype/assessment_result/test_assessment_result.js erpnext/schools/doctype/assessment_result_tool/test_assessment_result_tool.js erpnext/buying/doctype/supplier/test_supplier.js +erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.js \ No newline at end of file From dbb5154f3721a46497b8caad56419ad6f366e820 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Thu, 10 Aug 2017 21:06:09 +0530 Subject: [PATCH 05/52] Fixes in Order / Quotation (#10361) * Additions in Order Page for Sidebar Menu with "Order" page route * Adjust Columns in order_taxes.html to avoid number breaks for more precisions * Fields additions in transaction_row.html * [fix] style for order pages, indicator for quotation etc * [fix] style for order pages, indicator for quotation etc * [test] add timeout --- erpnext/hooks.py | 5 +- erpnext/public/css/website.css | 5 -- erpnext/public/less/website.less | 6 --- .../student_group/test_student_group.js | 2 +- .../selling/doctype/quotation/quotation.js | 4 -- .../selling/doctype/quotation/quotation.py | 8 +++ .../doctype/quotation/quotation_list.js | 8 ++- .../templates/includes/order/order_taxes.html | 12 ++--- .../templates/includes/transaction_row.html | 15 +++--- erpnext/templates/pages/order.html | 50 +++++++++++++++---- erpnext/templates/pages/order.py | 7 +-- 11 files changed, 74 insertions(+), 48 deletions(-) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index fc8d39b7ba..4df83afa10 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -50,7 +50,8 @@ calendars = ["Task", "Production Order", "Leave Application", "Sales Order", "Ho fixtures = ["Web Form"] -website_generators = ["Item Group", "Item", "BOM", "Sales Partner", "Job Opening", "Student Admission"] +website_generators = ["Item Group", "Item", "BOM", "Sales Partner", + "Job Opening", "Student Admission"] website_context = { "favicon": "/assets/erpnext/images/favicon.png", @@ -83,7 +84,7 @@ website_route_rules = [ {"from_route": "/quotations/", "to_route": "order", "defaults": { "doctype": "Quotation", - "parents": [{"label": _("Quotations"), "route": "quotation"}] + "parents": [{"label": _("Quotations"), "route": "quotations"}] } }, {"from_route": "/shipments", "to_route": "Delivery Note"}, diff --git a/erpnext/public/css/website.css b/erpnext/public/css/website.css index 0245675225..733194a10d 100644 --- a/erpnext/public/css/website.css +++ b/erpnext/public/css/website.css @@ -62,11 +62,6 @@ .featured-products { border-top: 1px solid #EBEFF2; } -.transaction-list-item:hover, -.transaction-list-item:active, -.transaction-list-item:focus { - background-color: #fafbfc; -} .transaction-list-item .indicator { font-weight: inherit; color: #8D99A6; diff --git a/erpnext/public/less/website.less b/erpnext/public/less/website.less index 79a89a050a..25172a1ffb 100644 --- a/erpnext/public/less/website.less +++ b/erpnext/public/less/website.less @@ -76,12 +76,6 @@ } .transaction-list-item { - &:hover, - &:active, - &:focus { - background-color: @light-bg; - } - .indicator { font-weight: inherit; color: @text-muted; diff --git a/erpnext/schools/doctype/student_group/test_student_group.js b/erpnext/schools/doctype/student_group/test_student_group.js index df72ae9598..634ad18254 100644 --- a/erpnext/schools/doctype/student_group/test_student_group.js +++ b/erpnext/schools/doctype/student_group/test_student_group.js @@ -57,7 +57,7 @@ QUnit.test('Test: Student Group', function(assert){ () => frappe.set_route("Form", ('Student Group/' + index)), () => frappe.timeout(0.5), () => frappe.tests.click_button('Get Students'), - () => frappe.timeout(0.5), + () => frappe.timeout(1), () => { assert.equal(cur_frm.doc.students.length, 5, 'Successfully fetched list of students'); }, diff --git a/erpnext/selling/doctype/quotation/quotation.js b/erpnext/selling/doctype/quotation/quotation.js index c149742fe3..3e5e52fe2a 100644 --- a/erpnext/selling/doctype/quotation/quotation.js +++ b/erpnext/selling/doctype/quotation/quotation.js @@ -38,10 +38,6 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({ var me = this; - if (doc.valid_till && frappe.datetime.get_diff(doc.valid_till, frappe.datetime.get_today()) < 0) { - this.frm.set_intro(__("Validity period of this quotation has ended")); - } - if (doc.__islocal) { this.frm.set_value('valid_till', frappe.datetime.add_months(doc.transaction_date, 1)) } diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index 5eb8b06ed8..1e6dbca04b 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -14,6 +14,14 @@ form_grid_templates = { } class Quotation(SellingController): + def set_indicator(self): + if self.docstatus==1: + self.indicator_color = 'blue' + self.indicator_title = 'Submitted' + if self.valid_till and getdate(self.valid_till) < getdate(nowdate()): + self.indicator_color = 'darkgrey' + self.indicator_title = 'Expired' + def validate(self): super(Quotation, self).validate() self.set_status() diff --git a/erpnext/selling/doctype/quotation/quotation_list.js b/erpnext/selling/doctype/quotation/quotation_list.js index 204ace13f4..8baf9b2518 100644 --- a/erpnext/selling/doctype/quotation/quotation_list.js +++ b/erpnext/selling/doctype/quotation/quotation_list.js @@ -1,9 +1,13 @@ frappe.listview_settings['Quotation'] = { add_fields: ["customer_name", "base_grand_total", "status", - "company", "currency"], + "company", "currency", 'valid_till'], get_indicator: function(doc) { if(doc.status==="Submitted") { - return [__("Submitted"), "blue", "status,=,Submitted"]; + if (doc.valid_till && doc.valid_till < frappe.datetime.nowdate()) { + return [__("Expired"), "darkgrey", "valid_till,<," + frappe.datetime.nowdate()]; + } else { + return [__("Submitted"), "blue", "status,=,Submitted"]; + } } else if(doc.status==="Ordered") { return [__("Ordered"), "green", "status,=,Ordered"]; } else if(doc.status==="Lost") { diff --git a/erpnext/templates/includes/order/order_taxes.html b/erpnext/templates/includes/order/order_taxes.html index 471576f4f5..462d77db61 100644 --- a/erpnext/templates/includes/order/order_taxes.html +++ b/erpnext/templates/includes/order/order_taxes.html @@ -1,22 +1,22 @@ {% if doc.taxes %}
-
{{ _("Net Total") }}
-
+
{{ _("Net Total") }}
+
{{ doc.get_formatted("net_total") }}
{% endif %} {% for d in doc.taxes %} {% if d.base_tax_amount > 0 %}
-
{{ d.description }}
-
+
{{ d.description }}
+
{{ d.get_formatted("base_tax_amount") }}
{% endif %} {% endfor %}
-
{{ _("Grand Total") }}
-
+
{{ _("Grand Total") }}
+
{{ doc.get_formatted("grand_total") }} diff --git a/erpnext/templates/includes/transaction_row.html b/erpnext/templates/includes/transaction_row.html index 10d76057d2..0e47f7d399 100644 --- a/erpnext/templates/includes/transaction_row.html +++ b/erpnext/templates/includes/transaction_row.html @@ -1,23 +1,22 @@
- diff --git a/erpnext/templates/pages/order.html b/erpnext/templates/pages/order.html index 2481808b4f..8a495b19ef 100644 --- a/erpnext/templates/pages/order.html +++ b/erpnext/templates/pages/order.html @@ -7,21 +7,44 @@ {% block title %}{{ doc.name }}{% endblock %} -{% block header %}

{{ doc.name }}

{% endblock %} +{% block header %} +

{{ doc.name }}

+{% endblock %} + +{% block header_actions %} +{{ _("Print") }} +{% endblock %} {% block page_content %}
- + {{ doc.indicator_title or doc.status or "Submitted" }}
{{ frappe.utils.formatdate(doc.transaction_date, 'medium') }} + {% if doc.valid_till %} +

+ {{ _("Valid Till") }}: {{ frappe.utils.formatdate(doc.valid_till, 'medium') }} +

+ {% endif %}
+

+{% if doc.doctype == 'Supplier Quotation' %} + {{ doc.supplier_name}} +{% else %} + {{ doc.customer_name}} +{% endif %} +{% if doc.contact_display %} +
+ {{ doc.contact_display }} +{% endif %} +

+ {% if doc._header %} {{ doc._header }} {% endif %} @@ -31,29 +54,29 @@
-
+
{{ _("Item") }}
-
+
{{ _("Quantity") }}
-
+
{{ _("Amount") }}
{% for d in doc.items %}
-
+
{{ item_name_and_description(d) }}
-
+
{{ d.qty }} {% if d.delivered_qty is defined and d.delivered_qty != None %}

{{ _("Delivered: {0}").format(d.delivered_qty) }}

{% endif %}
-
+
{{ d.get_formatted("amount") }}

{{ _("@ {0}").format(d.get_formatted("rate")) }}

@@ -72,8 +95,8 @@
-
-
+
+
{% if enabled_checkout %} {% if (doc.doctype=="Sales Order" and doc.per_billed <= 0) or (doc.doctype=="Sales Invoice" and doc.outstanding_amount > 0) %} @@ -86,7 +109,7 @@ {% endif %} {% endif %}
- + {% if attachments %}
@@ -106,4 +129,9 @@
{% endif %}
+{% if doc.terms %} +
+

{{ doc.terms }}

+
+{% endif %} {% endblock %} diff --git a/erpnext/templates/pages/order.py b/erpnext/templates/pages/order.py index 7551a0f9bb..110eb57504 100644 --- a/erpnext/templates/pages/order.py +++ b/erpnext/templates/pages/order.py @@ -15,7 +15,7 @@ def get_context(context): context.doc.set_indicator() if show_attachments(): - context.attachments = get_attachments(frappe.form_dict.doctype, frappe.form_dict.name) + context.attachments = get_attachments(frappe.form_dict.doctype, frappe.form_dict.name) context.parents = frappe.form_dict.parents context.title = frappe.form_dict.name @@ -28,5 +28,6 @@ def get_context(context): frappe.throw(_("Not Permitted"), frappe.PermissionError) def get_attachments(dt, dn): - return frappe.get_all("File", fields=["name", "file_name", "file_url", "is_private"], - filters = {"attached_to_name": dn, "attached_to_doctype": dt, "is_private":0}) + return frappe.get_all("File", + fields=["name", "file_name", "file_url", "is_private"], + filters = {"attached_to_name": dn, "attached_to_doctype": dt, "is_private":0}) From 9e30969243201371e3fc44515eae3dc11d7b248b Mon Sep 17 00:00:00 2001 From: Shreya Shah Date: Fri, 11 Aug 2017 12:02:35 +0530 Subject: [PATCH 06/52] Fetching items from material requests doctype (#10363) --- .../test_request_for_quotation.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.js index 75760bfcf1..6927d82b72 100644 --- a/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.js +++ b/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.js @@ -9,7 +9,7 @@ QUnit.test("test: request_for_quotation", function(assert) { date = frappe.datetime.add_days(frappe.datetime.now_date(), 10); return frappe.tests.make('Request for Quotation', [ {transaction_date: date}, - {company: 'Test Company'}, + {company: 'Wind Power LLC'}, {suppliers: [ [ {"supplier": 'Test Supplier'}, @@ -21,7 +21,7 @@ QUnit.test("test: request_for_quotation", function(assert) { {"item_code": 'Test Product 4'}, {"qty": 5}, {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(),20)}, - {"warehouse": 'All Warehouses - TC'} + {"warehouse": 'All Warehouses - WP'} ] ]}, {message_for_supplier: 'Please supply the specified items at the best possible rates'}, @@ -29,13 +29,13 @@ QUnit.test("test: request_for_quotation", function(assert) { ]); }, () => { - assert.ok(cur_frm.doc.transaction_date == date, "Date correct"); - assert.ok(cur_frm.doc.company == 'Test Company', "Company correct"); + assert.ok(cur_frm.doc.transaction_date == date, "Date correct"); + assert.ok(cur_frm.doc.company == 'Wind Power LLC', "Company correct"); assert.ok(cur_frm.doc.suppliers[0].supplier_name == 'Test Supplier', "Supplier name correct"); assert.ok(cur_frm.doc.suppliers[0].contact == 'Contact 3-Test Supplier', "Contact correct"); assert.ok(cur_frm.doc.suppliers[0].email_id == 'test@supplier.com', "Email id correct"); assert.ok(cur_frm.doc.items[0].item_name == 'Test Product 4', "Item Name correct"); - assert.ok(cur_frm.doc.items[0].warehouse == 'All Warehouses - TC', "Warehouse correct"); + assert.ok(cur_frm.doc.items[0].warehouse == 'All Warehouses - WP', "Warehouse correct"); assert.ok(cur_frm.doc.message_for_supplier == 'Please supply the specified items at the best possible rates', "Reply correct"); assert.ok(cur_frm.doc.tc_name == 'Test Term 1', "Term name correct"); }, @@ -52,10 +52,12 @@ QUnit.test("test: request_for_quotation", function(assert) { () => frappe.timeout(0.3), () => frappe.click_link('Material Request'), () => frappe.timeout(1), + () => frappe.click_button('Get Items'), + () => frappe.timeout(1), () => { - assert.ok($('h4').text().includes('Select Material Requests'), "Getting items from material requests work"); + assert.ok(cur_frm.doc.items[1].item_name == 'Test Product 1', "Getting items from material requests work"); }, - () => frappe.click_button('Close'), + () => cur_frm.save(), () => frappe.timeout(1), () => frappe.tests.click_button('Submit'), () => frappe.tests.click_button('Yes'), From 4157b64776b402a619c4737acbab2c8aa506c416 Mon Sep 17 00:00:00 2001 From: Vishal Dhayagude Date: Fri, 11 Aug 2017 12:06:16 +0530 Subject: [PATCH 07/52] [UI Test] Multiple UI Test for Stock Entry added (#10354) --- .../test_stock_entry_for_material_receipt.js | 32 +++++++++++++++++ .../test_stock_entry_for_material_transfer.js | 34 +++++++++++++++++++ erpnext/tests/ui/tests.txt | 4 ++- 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_receipt.js create mode 100644 erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_transfer.js diff --git a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_receipt.js b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_receipt.js new file mode 100644 index 0000000000..828738eb6c --- /dev/null +++ b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_receipt.js @@ -0,0 +1,32 @@ +QUnit.module('Stock'); + +QUnit.test("test material request", function(assert) { + assert.expect(2); + let done = assert.async(); + frappe.run_serially([ + () => { + return frappe.tests.make('Stock Entry', [ + {purpose:'Material Receipt'}, + {to_warehouse:'Stores - '+frappe.get_abbr(frappe.defaults.get_default('Company'))}, + {items: [ + [ + {'item_code': 'Test Product 1'}, + {'qty': 5}, + ] + ]}, + ]); + }, + () => cur_frm.save(), + () => frappe.click_button('Update Rate and Availability'), + () => { + // get_item_details + assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct"); + assert.ok(cur_frm.doc.total_incoming_value==500, " Incoming Value correct"); + }, + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), + () => done() + ]); +}); + diff --git a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_transfer.js b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_transfer.js new file mode 100644 index 0000000000..cdeb4ab04a --- /dev/null +++ b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_transfer.js @@ -0,0 +1,34 @@ +QUnit.module('Stock'); + +QUnit.test("test material request", function(assert) { + assert.expect(3); + let done = assert.async(); + frappe.run_serially([ + () => { + return frappe.tests.make('Stock Entry', [ + {purpose:'Material Transfer'}, + {from_warehouse:'Stores - '+frappe.get_abbr(frappe.defaults.get_default('Company'))}, + {to_warehouse:'Work In Progress - '+frappe.get_abbr(frappe.defaults.get_default('Company'))}, + {items: [ + [ + {'item_code': 'Test Product 1'}, + {'qty': 5}, + ] + ]}, + ]); + }, + () => cur_frm.save(), + () => frappe.click_button('Update Rate and Availability'), + () => { + // get_item_details + assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct"); + assert.ok(cur_frm.doc.total_outgoing_value==500, " Outgoing Value correct"); + assert.ok(cur_frm.doc.total_incoming_value==500, " Incoming Value correct"); + }, + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), + () => done() + ]); +}); + diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index 0dc19babef..6d9594dd40 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -55,6 +55,9 @@ erpnext/stock/doctype/material_request/tests/test_material_request.js erpnext/stock/doctype/material_request/tests/test_material_request_type_material_issue.js erpnext/stock/doctype/material_request/tests/test_material_request_type_material_transfer.js erpnext/stock/doctype/material_request/tests/test_material_request_type_manufacture.js +erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_issue.js +erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_receipt.js +erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_transfer.js erpnext/schools/doctype/grading_scale/test_grading_scale.js erpnext/schools/doctype/assessment_criteria_group/test_assessment_criteria_group.js erpnext/schools/doctype/assessment_criteria/test_assessment_criteria.js @@ -71,7 +74,6 @@ erpnext/schools/doctype/student_group_creation_tool/test_student_group_creation_ erpnext/schools/doctype/student_leave_application/test_student_leave_application.js erpnext/schools/doctype/student_attendance_tool/test_student_attendance_tool.js erpnext/schools/doctype/student_attendance/test_student_attendance.js -erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_issue.js erpnext/schools/doctype/assessment_group/test_assessment_group.js erpnext/schools/doctype/assessment_plan/test_assessment_plan.js erpnext/schools/doctype/assessment_result/test_assessment_result.js From 7273cb7f548a7604acdec48e311b17d7cc7af34f Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Fri, 11 Aug 2017 16:19:28 +0530 Subject: [PATCH 08/52] Track changes in Account doctype (#10373) --- erpnext/accounts/doctype/account/account.json | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/account/account.json b/erpnext/accounts/doctype/account/account.json index 0489f9a5f0..8de923f2e0 100644 --- a/erpnext/accounts/doctype/account/account.json +++ b/erpnext/accounts/doctype/account/account.json @@ -13,6 +13,7 @@ "editable_grid": 0, "fields": [ { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -42,6 +43,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -70,6 +72,7 @@ "width": "50%" }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -100,6 +103,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -130,6 +134,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -161,6 +166,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -190,6 +196,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -219,6 +226,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -250,6 +258,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -278,6 +287,7 @@ "width": "50%" }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -309,6 +319,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -341,6 +352,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -372,6 +384,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -404,6 +417,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -433,6 +447,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -461,6 +476,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -489,6 +505,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -528,7 +545,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-04-21 17:22:41.150984", + "modified": "2017-08-11 15:28:35.855809", "modified_by": "Administrator", "module": "Accounts", "name": "Account", @@ -641,6 +658,6 @@ "search_fields": "", "show_name_in_global_search": 1, "sort_order": "ASC", - "track_changes": 0, + "track_changes": 1, "track_seen": 0 } \ No newline at end of file From 22baba2cffac040e5d651d3e77d35c809b076c85 Mon Sep 17 00:00:00 2001 From: Vishal Dhayagude Date: Fri, 11 Aug 2017 17:17:30 +0530 Subject: [PATCH 09/52] [UI TEST] Test added for Delivery Note (#10376) --- .../delivery_note/test_delivery_note.js | 37 +++++++++++++++++++ erpnext/tests/ui/tests.txt | 1 + 2 files changed, 38 insertions(+) create mode 100644 erpnext/stock/doctype/delivery_note/test_delivery_note.js diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.js b/erpnext/stock/doctype/delivery_note/test_delivery_note.js new file mode 100644 index 0000000000..482f892997 --- /dev/null +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.js @@ -0,0 +1,37 @@ +QUnit.module('Stock'); + +QUnit.test("test delivery note", function(assert) { + assert.expect(2); + let done = assert.async(); + frappe.run_serially([ + () => { + return frappe.tests.make('Delivery Note', [ + {customer:'Test Customer 1'}, + {items: [ + [ + {'item_code': 'Test Product 1'}, + {'qty': 5}, + ] + ]}, + {shipping_address_name: 'Test1-Shipping'}, + {contact_person: 'Contact 1-Test Customer 1'}, + {taxes_and_charges: 'TEST In State GST'}, + {tc_name: 'Test Term 1'}, + {transporter_name:'TEST TRANSPORT'}, + {lr_no:'MH-04-FG 1111'} + ]); + }, + () => cur_frm.save(), + () => { + // get_item_details + assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct"); + assert.ok(cur_frm.doc.grand_total==590, " Grand Total correct"); + }, + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), + () => done() + ]); +}); + + diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index 6d9594dd40..e962ea62d6 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -51,6 +51,7 @@ erpnext/stock/doctype/warehouse/test_warehouse.js erpnext/manufacturing/doctype/production_order/test_production_order.js #long erpnext/accounts/page/pos/test_pos.js erpnext/selling/doctype/product_bundle/test_product_bundle.js +erpnext/stock/doctype/delivery_note/test_delivery_note.js erpnext/stock/doctype/material_request/tests/test_material_request.js erpnext/stock/doctype/material_request/tests/test_material_request_type_material_issue.js erpnext/stock/doctype/material_request/tests/test_material_request_type_material_transfer.js From 67e2ef30c4002f96ee33f5ecff72990f18216718 Mon Sep 17 00:00:00 2001 From: Shreya Shah Date: Mon, 14 Aug 2017 09:17:00 +0530 Subject: [PATCH 10/52] [UI test] Buying module - Get Supplier Quotations (#10375) * Get quotations for Suppliers * Calculate taxes and charges for Supplier quotations * Added paths for tests * Codacy fix * Improvised the page route function --- .../tests/test_supplier_quotation.js | 75 +++++++++++++++++++ ...upplier_quotation_for_taxes_and_charges.js | 62 +++++++++++++++ erpnext/tests/ui/tests.txt | 4 +- 3 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js create mode 100644 erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_taxes_and_charges.js diff --git a/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js new file mode 100644 index 0000000000..81e512ba2c --- /dev/null +++ b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js @@ -0,0 +1,75 @@ +QUnit.module('Buying'); + +QUnit.test("test: supplier quotation", function(assert) { + assert.expect(11); + let done = assert.async(); + let date; + + frappe.run_serially([ + () => { + date = frappe.datetime.add_days(frappe.datetime.now_date(), 10); + return frappe.tests.make('Supplier Quotation', [ + {supplier: 'Test Supplier'}, + {transaction_date: date}, + {company: 'Wind Power LLC'}, + {buying_price_list: 'Test-Buying-USD'}, + {currency: 'USD'}, + {items: [ + [ + {"item_code": 'Test Product 4'}, + {"qty": 5}, + {"uom": 'Unit'}, + {"rate": 200}, + {"warehouse": 'All Warehouses - WP'} + ] + ]}, + {apply_discount_on: 'Grand Total'}, + {additional_discount_percentage: 10}, + {tc_name: 'Test Term 1'}, + {terms: 'This is a term'} + ]); + }, + () => { + // Get Supplier details + assert.ok(cur_frm.doc.supplier == 'Test Supplier', "Supplier correct"); + assert.ok(cur_frm.doc.company == 'Wind Power LLC', "Company correct"); + // Get Contact details + assert.ok(cur_frm.doc.contact_display == 'Contact 3', "Conatct correct"); + assert.ok(cur_frm.doc.contact_email == 'test@supplier.com', "Email correct"); + // Get uom + assert.ok(cur_frm.doc.items[0].uom == 'Unit', "Multi uom correct"); + assert.ok(cur_frm.doc.total == 1000, "Total correct"); + // Calculate total after discount + assert.ok(cur_frm.doc.grand_total == 900, "Grand total correct"); + // Get terms + assert.ok(cur_frm.doc.tc_name == 'Test Term 1', "Terms correct"); + }, + + () => cur_frm.print_doc(), + () => frappe.timeout(1), + () => { + assert.ok($('.btn-print-print').is(':visible'), "Print Format Available"); + assert.ok($("table > tbody > tr > td:nth-child(3) > div").text().includes("Test Product 4"), "Print Preview Works As Expected"); + }, + () => cur_frm.print_doc(), + () => frappe.timeout(1), + () => frappe.click_button('Get items from'), + () => frappe.timeout(0.3), + () => frappe.click_link('Material Request'), + () => frappe.timeout(0.3), + () => frappe.click_button('Get Items'), + () => frappe.timeout(1), + () => { + // Get item from Material Requests + assert.ok(cur_frm.doc.items[1].item_name == 'Test Product 1', "Getting items from material requests work"); + }, + + () => cur_frm.save(), + () => frappe.timeout(1), + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), + + () => done() + ]); +}); \ No newline at end of file diff --git a/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_taxes_and_charges.js b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_taxes_and_charges.js new file mode 100644 index 0000000000..e1e393b67c --- /dev/null +++ b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_taxes_and_charges.js @@ -0,0 +1,62 @@ +QUnit.module('Buying'); + +QUnit.test("test: supplier quotation with taxes and charges", function(assert) { + assert.expect(3); + let done = assert.async(); + let supplier_quotation_name; + + frappe.run_serially([ + () => { + return frappe.tests.make('Supplier Quotation', [ + {supplier: 'Test Supplier'}, + {items: [ + [ + {"item_code": 'Test Product 4'}, + {"qty": 5}, + {"rate": 100}, + {"warehouse": 'Stores - WP'}, + ] + ]}, + ]); + }, + () => {supplier_quotation_name = cur_frm.doc.name;}, + () => frappe.set_route('Form', 'Purchase Taxes and Charges Template', 'New Purchase Taxes and Charges Template'), + () => frappe.timeout(1), + () => { + return frappe.tests.set_form_values(cur_frm, [ + {title:'TEST In State GST'}, + {taxes: [ + [ + {"charge_type": 'On Net Total'}, + {"account_head": 'CGST - WP'} + ], + [ + {"charge_type": 'On Net Total'}, + {"account_head": 'SGST - WP'} + ] + ]}, + ]); + }, + () => cur_frm.save(), + () => frappe.set_route('Form', 'Supplier Quotation', supplier_quotation_name), + () => frappe.timeout(1), + () => { + return frappe.tests.set_form_values(cur_frm, [ + {taxes_and_charges:'TEST In State GST'} + ]); + }, + + () => { + assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct"); + assert.ok(cur_frm.doc.total_taxes_and_charges == 45, "Taxes and charges correct"); + assert.ok(cur_frm.doc.grand_total == 545, "Grand total correct"); + }, + + () => cur_frm.save(), + () => frappe.timeout(0.3), + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), + () => done() + ]); +}); \ No newline at end of file diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index e962ea62d6..0bc61fa88d 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -80,4 +80,6 @@ erpnext/schools/doctype/assessment_plan/test_assessment_plan.js erpnext/schools/doctype/assessment_result/test_assessment_result.js erpnext/schools/doctype/assessment_result_tool/test_assessment_result_tool.js erpnext/buying/doctype/supplier/test_supplier.js -erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.js \ No newline at end of file +erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.js +erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js +erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_taxes_and_charges.js \ No newline at end of file From a5cb9ae8bdd7c810bf3241ea7525d378b91b05a4 Mon Sep 17 00:00:00 2001 From: Manas Solanki Date: Mon, 14 Aug 2017 09:50:15 +0530 Subject: [PATCH 11/52] send email via the background jobs (#10374) --- erpnext/hr/doctype/salary_slip/salary_slip.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index 2bd08c22c1..1d17613381 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -11,6 +11,7 @@ from frappe import msgprint, _ from erpnext.hr.doctype.process_payroll.process_payroll import get_start_end_dates from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee from erpnext.utilities.transaction_base import TransactionBase +from frappe.utils.background_jobs import enqueue class SalarySlip(TransactionBase): def autoname(self): @@ -396,9 +397,15 @@ class SalarySlip(TransactionBase): receiver = frappe.db.get_value("Employee", self.employee, "prefered_email") if receiver: - subj = 'Salary Slip - from {0} to {1}'.format(self.start_date, self.end_date) - frappe.sendmail([receiver], subject=subj, message = _("Please see attachment"), - attachments=[frappe.attach_print(self.doctype, self.name, file_name=self.name)], reference_doctype= self.doctype, reference_name= self.name) + email_args = { + "recipients": [receiver], + "message": _("Please see attachment"), + "subject": 'Salary Slip - from {0} to {1}'.format(self.start_date, self.end_date), + "attachments": [frappe.attach_print(self.doctype, self.name, file_name=self.name)], + "reference_doctype": self.doctype, + "reference_name": self.name + } + enqueue(method=frappe.sendmail, queue='short', timeout=300, async=True, **email_args) else: msgprint(_("{0}: Employee email not found, hence email not sent").format(self.employee_name)) From 7186131d6549527a0553f7d1cf823dae64fdad2f Mon Sep 17 00:00:00 2001 From: Vishal Dhayagude Date: Mon, 14 Aug 2017 12:22:04 +0530 Subject: [PATCH 12/52] [UI Test] sales invoice (#10394) * [UI Test] Sales Invoice * [UI Test] Sales Invoice --- .../sales_invoice/test_sales_invoice.js | 43 +++++++++++++++++++ erpnext/tests/ui/tests.txt | 3 +- 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 erpnext/accounts/doctype/sales_invoice/test_sales_invoice.js diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.js new file mode 100644 index 0000000000..35b255875e --- /dev/null +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.js @@ -0,0 +1,43 @@ +QUnit.module('Sales Invoice'); + +QUnit.test("test sales Invoice", function(assert) { + assert.expect(4); + let done = assert.async(); + frappe.run_serially([ + () => { + return frappe.tests.make('Sales Invoice', [ + {customer: 'Test Customer 1'}, + {items: [ + [ + {'qty': 5}, + {'item_code': 'Test Product 1'}, + ] + ]}, + {update_stock:1}, + {customer_address: 'Test1-Billing'}, + {shipping_address_name: 'Test1-Shipping'}, + {contact_person: 'Contact 1-Test Customer 1'}, + {taxes_and_charges: 'TEST In State GST'}, + {tc_name: 'Test Term 1'}, + {terms: 'This is Test'} + ]); + }, + () => cur_frm.save(), + () => { + // get_item_details + assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct"); + // get tax details + assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST', "Tax details correct"); + // get tax account head details + assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct"); + // grand_total Calculated + assert.ok(cur_frm.doc.grand_total==590, "Grad Total correct"); + + }, + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), + () => done() + ]); +}); + diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index 0bc61fa88d..68cfad6542 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -82,4 +82,5 @@ erpnext/schools/doctype/assessment_result_tool/test_assessment_result_tool.js erpnext/buying/doctype/supplier/test_supplier.js erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.js erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js -erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_taxes_and_charges.js \ No newline at end of file +erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_taxes_and_charges.js +erpnext/accounts/doctype/sales_invoice/test_sales_invoice.js \ No newline at end of file From 0973161ae5c5953ec71140b1fc0ddb38edfb1049 Mon Sep 17 00:00:00 2001 From: Makarand Bauskar Date: Mon, 14 Aug 2017 14:55:48 +0530 Subject: [PATCH 13/52] [docs] Translate the Schools Assessment section documentation to Spanish (#10398) * [docs] Translate the Schools app documentation to Spanish * [docs] Translate the Schools Student section documentation to Spanish * [docs] Translate the Schools SETUP section documentation to Spanish * [docs] Translate the Schools ADMISSION section documentation to Spanish * [docs] Translate the Schools FEES section documentation to Spanish * [docs] Translate the Schools SCHEDULE section documentation to Spanish * [docs] Translate the Schools Assessment section documentation to Spanish --- erpnext/docs/user/manual/es/index.txt | 1 + .../manual/es/schools/Assessment/__init__.py | 0 .../schools/Assessment/assessment_criteria.md | 13 +++++++++ .../es/schools/Assessment/assessment_group.md | 13 +++++++++ .../es/schools/Assessment/assessment_plan.md | 19 +++++++++++++ .../schools/Assessment/assessment_result.md | 7 +++++ .../Assessment/assessment_result_tool.md | 10 +++++++ .../es/schools/Assessment/grading_scale.md | 7 +++++ .../manual/es/schools/Assessment/index.md | 19 +++++++++++++ .../manual/es/schools/Assessment/index.txt | 6 ++++ .../docs/user/manual/es/schools/__init__.py | 0 .../manual/es/schools/admission/__init__.py | 0 .../user/manual/es/schools/admission/index.md | 7 +++++ .../manual/es/schools/admission/index.txt | 2 ++ .../schools/admission/program-enrollment.md | 7 +++++ .../es/schools/admission/student-applicant.md | 28 +++++++++++++++++++ .../user/manual/es/schools/fees/__init__.py | 0 .../manual/es/schools/fees/fee-category.md | 7 +++++ .../manual/es/schools/fees/fee-structure.md | 7 +++++ .../docs/user/manual/es/schools/fees/fees.md | 8 ++++++ .../docs/user/manual/es/schools/fees/index.md | 9 ++++++ .../user/manual/es/schools/fees/index.txt | 3 ++ erpnext/docs/user/manual/es/schools/index.md | 8 ++++++ erpnext/docs/user/manual/es/schools/index.txt | 6 ++++ .../manual/es/schools/schedule/__init__.py | 0 .../es/schools/schedule/course-schedule.md | 25 +++++++++++++++++ .../manual/es/schools/schedule/examination.md | 8 ++++++ .../user/manual/es/schools/schedule/index.md | 7 +++++ .../user/manual/es/schools/schedule/index.txt | 4 +++ .../es/schools/schedule/scheduling-tool.md | 23 +++++++++++++++ .../es/schools/schedule/student-attendance.md | 7 +++++ .../user/manual/es/schools/setup/__init__.py | 0 .../manual/es/schools/setup/academic-term.md | 6 ++++ .../manual/es/schools/setup/academic-year.md | 5 ++++ .../user/manual/es/schools/setup/course.md | 5 ++++ .../user/manual/es/schools/setup/index.md | 7 +++++ .../user/manual/es/schools/setup/index.txt | 6 ++++ .../manual/es/schools/setup/instructor.md | 5 ++++ .../user/manual/es/schools/setup/program.md | 5 ++++ .../docs/user/manual/es/schools/setup/room.md | 6 ++++ .../manual/es/schools/student/__init__.py | 0 .../user/manual/es/schools/student/index.md | 7 +++++ .../user/manual/es/schools/student/index.txt | 5 ++++ .../es/schools/student/student-batch.md | 8 ++++++ .../student/student-group-creation-tool.md | 8 ++++++ .../es/schools/student/student-group.md | 8 ++++++ .../manual/es/schools/student/student-log.md | 8 ++++++ .../user/manual/es/schools/student/student.md | 10 +++++++ 48 files changed, 360 insertions(+) create mode 100644 erpnext/docs/user/manual/es/schools/Assessment/__init__.py create mode 100644 erpnext/docs/user/manual/es/schools/Assessment/assessment_criteria.md create mode 100644 erpnext/docs/user/manual/es/schools/Assessment/assessment_group.md create mode 100644 erpnext/docs/user/manual/es/schools/Assessment/assessment_plan.md create mode 100644 erpnext/docs/user/manual/es/schools/Assessment/assessment_result.md create mode 100644 erpnext/docs/user/manual/es/schools/Assessment/assessment_result_tool.md create mode 100644 erpnext/docs/user/manual/es/schools/Assessment/grading_scale.md create mode 100644 erpnext/docs/user/manual/es/schools/Assessment/index.md create mode 100644 erpnext/docs/user/manual/es/schools/Assessment/index.txt create mode 100644 erpnext/docs/user/manual/es/schools/__init__.py create mode 100644 erpnext/docs/user/manual/es/schools/admission/__init__.py create mode 100644 erpnext/docs/user/manual/es/schools/admission/index.md create mode 100644 erpnext/docs/user/manual/es/schools/admission/index.txt create mode 100644 erpnext/docs/user/manual/es/schools/admission/program-enrollment.md create mode 100644 erpnext/docs/user/manual/es/schools/admission/student-applicant.md create mode 100644 erpnext/docs/user/manual/es/schools/fees/__init__.py create mode 100644 erpnext/docs/user/manual/es/schools/fees/fee-category.md create mode 100644 erpnext/docs/user/manual/es/schools/fees/fee-structure.md create mode 100644 erpnext/docs/user/manual/es/schools/fees/fees.md create mode 100644 erpnext/docs/user/manual/es/schools/fees/index.md create mode 100644 erpnext/docs/user/manual/es/schools/fees/index.txt create mode 100644 erpnext/docs/user/manual/es/schools/index.md create mode 100644 erpnext/docs/user/manual/es/schools/index.txt create mode 100644 erpnext/docs/user/manual/es/schools/schedule/__init__.py create mode 100644 erpnext/docs/user/manual/es/schools/schedule/course-schedule.md create mode 100644 erpnext/docs/user/manual/es/schools/schedule/examination.md create mode 100644 erpnext/docs/user/manual/es/schools/schedule/index.md create mode 100644 erpnext/docs/user/manual/es/schools/schedule/index.txt create mode 100644 erpnext/docs/user/manual/es/schools/schedule/scheduling-tool.md create mode 100644 erpnext/docs/user/manual/es/schools/schedule/student-attendance.md create mode 100644 erpnext/docs/user/manual/es/schools/setup/__init__.py create mode 100644 erpnext/docs/user/manual/es/schools/setup/academic-term.md create mode 100644 erpnext/docs/user/manual/es/schools/setup/academic-year.md create mode 100644 erpnext/docs/user/manual/es/schools/setup/course.md create mode 100644 erpnext/docs/user/manual/es/schools/setup/index.md create mode 100644 erpnext/docs/user/manual/es/schools/setup/index.txt create mode 100644 erpnext/docs/user/manual/es/schools/setup/instructor.md create mode 100644 erpnext/docs/user/manual/es/schools/setup/program.md create mode 100644 erpnext/docs/user/manual/es/schools/setup/room.md create mode 100644 erpnext/docs/user/manual/es/schools/student/__init__.py create mode 100644 erpnext/docs/user/manual/es/schools/student/index.md create mode 100644 erpnext/docs/user/manual/es/schools/student/index.txt create mode 100644 erpnext/docs/user/manual/es/schools/student/student-batch.md create mode 100644 erpnext/docs/user/manual/es/schools/student/student-group-creation-tool.md create mode 100644 erpnext/docs/user/manual/es/schools/student/student-group.md create mode 100644 erpnext/docs/user/manual/es/schools/student/student-log.md create mode 100644 erpnext/docs/user/manual/es/schools/student/student.md diff --git a/erpnext/docs/user/manual/es/index.txt b/erpnext/docs/user/manual/es/index.txt index d19ef97543..feb68a2fe0 100644 --- a/erpnext/docs/user/manual/es/index.txt +++ b/erpnext/docs/user/manual/es/index.txt @@ -1,2 +1,3 @@ introduction accounts +schools diff --git a/erpnext/docs/user/manual/es/schools/Assessment/__init__.py b/erpnext/docs/user/manual/es/schools/Assessment/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/docs/user/manual/es/schools/Assessment/assessment_criteria.md b/erpnext/docs/user/manual/es/schools/Assessment/assessment_criteria.md new file mode 100644 index 0000000000..92f338fd8b --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/Assessment/assessment_criteria.md @@ -0,0 +1,13 @@ +#Criterios de Evaluación + +Criterios de evaluación es el parámetro basado en el que se evalúa el estudiante. + +Assessment Criteria + +Después de la evaluación para un curso, las calificaciones obtenidas se ingresan en base a los criterios de evaluación. Por ejemplo, si la evaluación se llevó a cabo para el tema de la ciencia, entonces usted puede evaluar al estudiante en ciencia en varios criterios como la escritura, prácticas, presentación, etc + +Los Criterios de Evaluación se usan al programar el Plan de Evaluación para el Grupo de Estudiantes y el Curso. + +Assessment Plan Criteria + +{next} diff --git a/erpnext/docs/user/manual/es/schools/Assessment/assessment_group.md b/erpnext/docs/user/manual/es/schools/Assessment/assessment_group.md new file mode 100644 index 0000000000..7102888f28 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/Assessment/assessment_group.md @@ -0,0 +1,13 @@ +#Grupo de Evaluación + +La estructura del grupo de evaluación es un maestro donde se puede definir la jerarquía para el examen realizado en su instituto de educación. + +Por ejemplo, si realiza dos evaluaciones en un año académico, configure el Grupo de evaluación de la siguiente manera. + +Assessment Group Term + +En la misma línea, también puede definir varios Grupo de Evaluación basado sobre la evaluación llevada a cabo en su instituto. + +Assessment Group Term + +{next} diff --git a/erpnext/docs/user/manual/es/schools/Assessment/assessment_plan.md b/erpnext/docs/user/manual/es/schools/Assessment/assessment_plan.md new file mode 100644 index 0000000000..9d66c213f8 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/Assessment/assessment_plan.md @@ -0,0 +1,19 @@ +#Plan de Evaluación + +Para programar una evaluación/examinación para un Grupo de Estudiantes, para un curso específico, crea un Plan de Evaluación. En el plan de evaluación, puedes capturar detalles como: + +1. Escala de Calificaciones basada en qué calificaciones serán asignadas a los estudiantes. + +2. Fecha de planificación de la Evaluación + +3. Aula donde se va a llevar a cabo la evaluación + +4. Examinador y Supervisor + +Assessment Plan Details + +5. Los Criterios de Evaluación son la lista de criterios basados ​​en que cada estudiante en será evaluado y los grados serán asignados. + +Assessment Plan Criteria + +{next} diff --git a/erpnext/docs/user/manual/es/schools/Assessment/assessment_result.md b/erpnext/docs/user/manual/es/schools/Assessment/assessment_result.md new file mode 100644 index 0000000000..2d9409708d --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/Assessment/assessment_result.md @@ -0,0 +1,7 @@ +#Resultados de Evaluación + +El resultado de la evaluación es un registro de las calificaciones obtenidas por el estudiante para una evaluación específica. El resultado de la evaluación se crea en el backend en base a los puntos en [Herramienta de Resultados de Evaluación](/docs/user/manual/es/schools/assessment/assessment_result_tool.html). + +Assessment Result + +{next} diff --git a/erpnext/docs/user/manual/es/schools/Assessment/assessment_result_tool.md b/erpnext/docs/user/manual/es/schools/Assessment/assessment_result_tool.md new file mode 100644 index 0000000000..70e4ee3f2f --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/Assessment/assessment_result_tool.md @@ -0,0 +1,10 @@ +#Herramienta de resultados de la evaluación + + +Herramienta de resultados de evaluación le ayuda a ingresar las calificaciones obtenidas por los estudiantes para un curso específico. En esta herramienta, basada en el plan de evaluación, todos los estudiantes van a ser filtrados dentro de la herramienta de resultados de la evaluación. También, Columnas para los Criterios de Evaluación serán donde las calificaciones ganadas pueden ser ingresadas para cada Estudiante. + +Assessment Result Tool + +A medida que vaya introduciendo las notas para un Estudiante y cambie al siguiente alumno, en el backend, el registro de Resultados del Estudiante se creará automáticamente para ese Estudiante. + +{next} diff --git a/erpnext/docs/user/manual/es/schools/Assessment/grading_scale.md b/erpnext/docs/user/manual/es/schools/Assessment/grading_scale.md new file mode 100644 index 0000000000..9107f92a56 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/Assessment/grading_scale.md @@ -0,0 +1,7 @@ +#Escala de calificación + +En la escala de calificación, puedes definir varios grados y límites para los estudiantes. Basado en la calificación obtenida por el estudiante en la evaluación, el grado (Grade) será asignado. + +Grading Scale + +{next} diff --git a/erpnext/docs/user/manual/es/schools/Assessment/index.md b/erpnext/docs/user/manual/es/schools/Assessment/index.md new file mode 100644 index 0000000000..5b4c35a263 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/Assessment/index.md @@ -0,0 +1,19 @@ +#Evaluación + +Cada instituto de educación organiza evaluaciones / examenes para evaluar el progreso de sus estudiantes. En ERPNext, puedes gestionar completamente el proceso de evaluación para sus cuentas en ERPNext. + + + +A continuación se muestra el orden en el que debe configurar los masters en el módulo de evaluación. + +1. Criterio de Evaluación +2. Grupo de Evaluación +3. Escala de Evaluación + +Una vez tengas definido los Grupos de Estudiantes y Cursos, puedes programar una evaluación / examinación creando un Plan de Evaluación. + +Basado en el rendimiento del estudiante en la evaluación, puedes ingresar los resultados de la evaluación por un estudiante. Puedes ingresar todos los registros de los estudiantes usando la herramienta de resultados de evaluación. En esta herramienta, en la selecció del Plan de Evaluación, todos los estudiantes (De un grupo de estudiantes) van a ser buscados y mostrados. Puedes rápidamente ingresar los puntos obtenidos por cada estudiante en cada uno de los Criterios de Evaluación en una sola linea. + +### Temas + +{index} diff --git a/erpnext/docs/user/manual/es/schools/Assessment/index.txt b/erpnext/docs/user/manual/es/schools/Assessment/index.txt new file mode 100644 index 0000000000..61d744c721 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/Assessment/index.txt @@ -0,0 +1,6 @@ +assessment_criteria +assessment_group +grading_scale +assessment_plan +assessment_result_tool +assessment_result \ No newline at end of file diff --git a/erpnext/docs/user/manual/es/schools/__init__.py b/erpnext/docs/user/manual/es/schools/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/docs/user/manual/es/schools/admission/__init__.py b/erpnext/docs/user/manual/es/schools/admission/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/docs/user/manual/es/schools/admission/index.md b/erpnext/docs/user/manual/es/schools/admission/index.md new file mode 100644 index 0000000000..df44679d9a --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/admission/index.md @@ -0,0 +1,7 @@ +# Admisiones + +Esta sección contiene los documentos relacionados a adminisiones de estudiantes. + +### Temas + +{index} diff --git a/erpnext/docs/user/manual/es/schools/admission/index.txt b/erpnext/docs/user/manual/es/schools/admission/index.txt new file mode 100644 index 0000000000..ec9e768116 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/admission/index.txt @@ -0,0 +1,2 @@ +student-applicant +program-enrollment \ No newline at end of file diff --git a/erpnext/docs/user/manual/es/schools/admission/program-enrollment.md b/erpnext/docs/user/manual/es/schools/admission/program-enrollment.md new file mode 100644 index 0000000000..34e8996a25 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/admission/program-enrollment.md @@ -0,0 +1,7 @@ +# Inscripción al Programa + +Este formulario te permite inscribir un estudiante a un programa. Un estudiante puede ser inscrito en multiples programas. + +Student Applicant Enrollment + +{next} diff --git a/erpnext/docs/user/manual/es/schools/admission/student-applicant.md b/erpnext/docs/user/manual/es/schools/admission/student-applicant.md new file mode 100644 index 0000000000..33d8dd7b29 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/admission/student-applicant.md @@ -0,0 +1,28 @@ +# Aplicación de Estudiante + +Un registro de Aplicación de Estudiante necesita ser creado cuando un estudiante aplica para un programa en su institución. +Puedes Aprobar o Rechazar una aplicación de estudiante. Aceptando una aplicación de un estudiante puedes agregarlos al master de estudiantes. + +Student Applicant + +### Estados de la Aplicación + +- Por defecto cuando una aplicación de estudiante es creada en el sistema, el estado de la aplicación es seteado a 'Applied' + +- Puedes actualizar el estado a 'Approved' una vez apruebas la aplicación de estudiante para unirse a su institución + +- Cuando el estado de la aplicación es actualizada a 'Approved', el botón de 'Inscribir' debería aparecer. + Puedes crear un registro de estudiante usando la aplicación de estudiante e inscribirlos a un programa al presionar el botón de Inscribir + +- Una vez el estudiante es creado usando la aplicación de estudiante, el sistema va a setear el estado del documento de aplicación a 'Admitted' + y no te va a permiter cambiar el estado de la aplicación a menos que el estudiante sea eliminado + +### Registro de Estudiante + + +Una vez aprobada una Aplicación de Estudiante, puedes inscribirlo a un programa. Cuando le das click al butón 'Inscribir', +el sistema creará un estudiante usando esa aplicación y le va a redireccionar a el [Formulario de Inscripción al Programa](/docs/user/manual/es/schools/student/program-enrollment.html). + +Student Applicant Enrollment + +{next} diff --git a/erpnext/docs/user/manual/es/schools/fees/__init__.py b/erpnext/docs/user/manual/es/schools/fees/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/docs/user/manual/es/schools/fees/fee-category.md b/erpnext/docs/user/manual/es/schools/fees/fee-category.md new file mode 100644 index 0000000000..c05b3f549f --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/fees/fee-category.md @@ -0,0 +1,7 @@ +# Categoría de Cuota + +Todos los tipos diferentes de cuotas que se cobran + +Fees Category + +{next} diff --git a/erpnext/docs/user/manual/es/schools/fees/fee-structure.md b/erpnext/docs/user/manual/es/schools/fees/fee-structure.md new file mode 100644 index 0000000000..1f621d716d --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/fees/fee-structure.md @@ -0,0 +1,7 @@ +# Estructura de Cuota + +Una Estructura de Cuota es una plantilla que puede ser usada cuando se hacen registros de cuotas. + +Fees Structure + +{next} diff --git a/erpnext/docs/user/manual/es/schools/fees/fees.md b/erpnext/docs/user/manual/es/schools/fees/fees.md new file mode 100644 index 0000000000..d6b74dc300 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/fees/fees.md @@ -0,0 +1,8 @@ +# Cuotas + +Mantiene un registro de todas las cuotas recolectadas de los estudiantes. +La [Estructura de Cuota](/docs/user/manual/es/schools/fees/fee-structure.html) es seleccionada basada en el programa seleccionada y los Términos Académicos. + +Fees + +{next} diff --git a/erpnext/docs/user/manual/es/schools/fees/index.md b/erpnext/docs/user/manual/es/schools/fees/index.md new file mode 100644 index 0000000000..e88381378d --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/fees/index.md @@ -0,0 +1,9 @@ +# Cuota + +Esta sección contiene todos los documentos relacionado a las 'Cuota' + +Fees Section + +### Temas + +{index} diff --git a/erpnext/docs/user/manual/es/schools/fees/index.txt b/erpnext/docs/user/manual/es/schools/fees/index.txt new file mode 100644 index 0000000000..265ac6a528 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/fees/index.txt @@ -0,0 +1,3 @@ +fees +fee-structure +fee-category \ No newline at end of file diff --git a/erpnext/docs/user/manual/es/schools/index.md b/erpnext/docs/user/manual/es/schools/index.md new file mode 100644 index 0000000000..a1824dc6e8 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/index.md @@ -0,0 +1,8 @@ +# Schools + + +Los módulos de School estan diseñados para satisfacer los requerimientos de Escuelas, Colegios e Institutos Educacionales. + +Fees Section + +{index} diff --git a/erpnext/docs/user/manual/es/schools/index.txt b/erpnext/docs/user/manual/es/schools/index.txt new file mode 100644 index 0000000000..b485fdcfea --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/index.txt @@ -0,0 +1,6 @@ +student +admission +schedule +fees +setup +assessment \ No newline at end of file diff --git a/erpnext/docs/user/manual/es/schools/schedule/__init__.py b/erpnext/docs/user/manual/es/schools/schedule/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/docs/user/manual/es/schools/schedule/course-schedule.md b/erpnext/docs/user/manual/es/schools/schedule/course-schedule.md new file mode 100644 index 0000000000..629c828451 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/schedule/course-schedule.md @@ -0,0 +1,25 @@ +# Horario de un Curso + +El Horario de Curso es el horario de una sesión de un profesor para un Curso en particular. +Puedes ver un resumen del horario del curso en la vista de Calendario. + +Course Schedule + +### Marcando asistencia + +Puedes pasar la asistencia para un grupo de estudiantes usando el Horario de Curso. + +Course Schedule Attendance + +- Para hacer la asistencia, expandir la sección de asistencia. +- Selecciona los estudiantes que estaban presentes para esa sesión. +- Click en el botón de 'Mark Attendance'. El sistema va a crear los registros de asistencia automáticamente. + +### Ver Asistencia + +Una vez hayas marcado la asistencia usando la sección de asistencia en el Horario de un Curso, esta sección debería estar oculta. +Un botón de Ver Asistencia debería aparecer. Click en el botón para ver todos los registros de asistencia creados para ese Horario de Curso. + +Course Schedule Attendance + +{next} diff --git a/erpnext/docs/user/manual/es/schools/schedule/examination.md b/erpnext/docs/user/manual/es/schools/schedule/examination.md new file mode 100644 index 0000000000..5f85aedd41 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/schedule/examination.md @@ -0,0 +1,8 @@ +# Examinación + +El registro de examinación puede ser usado para hacer el seguimiento del horario de los examenes y los resultados de los mismos. + +Examination + + +{next} diff --git a/erpnext/docs/user/manual/es/schools/schedule/index.md b/erpnext/docs/user/manual/es/schools/schedule/index.md new file mode 100644 index 0000000000..f9c2c3b5d1 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/schedule/index.md @@ -0,0 +1,7 @@ +# Horario + +Schedule Section + +### Temas + +{index} diff --git a/erpnext/docs/user/manual/es/schools/schedule/index.txt b/erpnext/docs/user/manual/es/schools/schedule/index.txt new file mode 100644 index 0000000000..704ad84b89 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/schedule/index.txt @@ -0,0 +1,4 @@ +course-schedule +student-attendance +scheduling-tool +examination \ No newline at end of file diff --git a/erpnext/docs/user/manual/es/schools/schedule/scheduling-tool.md b/erpnext/docs/user/manual/es/schools/schedule/scheduling-tool.md new file mode 100644 index 0000000000..070a0354ec --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/schedule/scheduling-tool.md @@ -0,0 +1,23 @@ +# Herramienta para Horarios + +Esta herramienta puede ser usada para crear los Horarios de los Cursos. + +Scheduling Tool + +### Creando Horarios de Cursos + +- Selecciona el Grupo de Estudiante para el cual vas a establecer el Horario. +- Seleccione el curso, Aula y un Instructor para el Horario. +- Específica los rangos de fecha desde-hasta para el horario de los cursos. +- Especifíca Fecha Inicio y Fecha Final de un curso(Los Horarios de los cursos van a ser creados dentro de este rango de fechas) +- Espeficíca el dia de la semana en el cual deseas establecer el horario. +- Presiona el botón de 'Schedule Course' +- El sistema va a crear la planificación si el Aula y el Instructor estan disponibles y no hay ningún conflicto con el grupo de estudiantes seleccionados con otros horarios para el mismo grupo. + +###Reprogramar Horario + +- Si deseas reprogramar el horario de un curso, sigue las instrucciones para crear horarios de cursos. +- Selecciona el checkbox 'Reschedule' y luego da click en el botón 'Schedule Course'. +- El sistema va a eliminar la progración de horario especifícada para ese curso dentro del rango de fecha seleccionado y crearia la nueva planificación de horario para el curso. + +{next} diff --git a/erpnext/docs/user/manual/es/schools/schedule/student-attendance.md b/erpnext/docs/user/manual/es/schools/schedule/student-attendance.md new file mode 100644 index 0000000000..a06c4f276d --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/schedule/student-attendance.md @@ -0,0 +1,7 @@ +# Asistencia de Estudiante + +Mantiene los registros de la asistencia del estudiante. Los registros de asistencia pueden ser creados sobre los horarios de los cursos (Course Schedules). + +Student Attendance + +{next} diff --git a/erpnext/docs/user/manual/es/schools/setup/__init__.py b/erpnext/docs/user/manual/es/schools/setup/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/docs/user/manual/es/schools/setup/academic-term.md b/erpnext/docs/user/manual/es/schools/setup/academic-term.md new file mode 100644 index 0000000000..83af58ac31 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/setup/academic-term.md @@ -0,0 +1,6 @@ +# Término Académico + +Academic Term + + +{next} diff --git a/erpnext/docs/user/manual/es/schools/setup/academic-year.md b/erpnext/docs/user/manual/es/schools/setup/academic-year.md new file mode 100644 index 0000000000..56a46f9c39 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/setup/academic-year.md @@ -0,0 +1,5 @@ +# Año Académico + +Academic Year + +{next} diff --git a/erpnext/docs/user/manual/es/schools/setup/course.md b/erpnext/docs/user/manual/es/schools/setup/course.md new file mode 100644 index 0000000000..799f9b46e1 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/setup/course.md @@ -0,0 +1,5 @@ +# Curso + +Course + +{next} diff --git a/erpnext/docs/user/manual/es/schools/setup/index.md b/erpnext/docs/user/manual/es/schools/setup/index.md new file mode 100644 index 0000000000..070db54015 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/setup/index.md @@ -0,0 +1,7 @@ +# Configuración + +Setup Section + +### Temas + +{index} diff --git a/erpnext/docs/user/manual/es/schools/setup/index.txt b/erpnext/docs/user/manual/es/schools/setup/index.txt new file mode 100644 index 0000000000..fb9ba05d09 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/setup/index.txt @@ -0,0 +1,6 @@ +course +program +instructor +room +academic-term +academic-year \ No newline at end of file diff --git a/erpnext/docs/user/manual/es/schools/setup/instructor.md b/erpnext/docs/user/manual/es/schools/setup/instructor.md new file mode 100644 index 0000000000..1a4d35161c --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/setup/instructor.md @@ -0,0 +1,5 @@ +# Instructor + +Instructor + +{next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/es/schools/setup/program.md b/erpnext/docs/user/manual/es/schools/setup/program.md new file mode 100644 index 0000000000..78895c5806 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/setup/program.md @@ -0,0 +1,5 @@ +# Programa + +Program + +{next} diff --git a/erpnext/docs/user/manual/es/schools/setup/room.md b/erpnext/docs/user/manual/es/schools/setup/room.md new file mode 100644 index 0000000000..92a4de77af --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/setup/room.md @@ -0,0 +1,6 @@ +# Aula + + +Room + +{next} diff --git a/erpnext/docs/user/manual/es/schools/student/__init__.py b/erpnext/docs/user/manual/es/schools/student/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/docs/user/manual/es/schools/student/index.md b/erpnext/docs/user/manual/es/schools/student/index.md new file mode 100644 index 0000000000..2d9c6e1049 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/student/index.md @@ -0,0 +1,7 @@ +# Student + +Esta sección contiene los documentos relacionados a los estudiantes. + +### Temas + +{index} diff --git a/erpnext/docs/user/manual/es/schools/student/index.txt b/erpnext/docs/user/manual/es/schools/student/index.txt new file mode 100644 index 0000000000..9b31be4dc9 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/student/index.txt @@ -0,0 +1,5 @@ +student +student-log +student-batch +student-group +student-group-creation-tool diff --git a/erpnext/docs/user/manual/es/schools/student/student-batch.md b/erpnext/docs/user/manual/es/schools/student/student-batch.md new file mode 100644 index 0000000000..4d5a17e671 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/student/student-batch.md @@ -0,0 +1,8 @@ +# Lote de Estudiantes + + +Un lote de estudiantes es una colección de estudiantes desde los Grupos de Estudiantes. + +Student + +{next} diff --git a/erpnext/docs/user/manual/es/schools/student/student-group-creation-tool.md b/erpnext/docs/user/manual/es/schools/student/student-group-creation-tool.md new file mode 100644 index 0000000000..2102c34de9 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/student/student-group-creation-tool.md @@ -0,0 +1,8 @@ +# Herramienta para creación de Grupo de Estudiantes + +Esta herramienta te permite crear grupos de estudiantes. Puedes especificar multiples parámetros para crearlos. + + +Student Group Creation Tool + +{next} diff --git a/erpnext/docs/user/manual/es/schools/student/student-group.md b/erpnext/docs/user/manual/es/schools/student/student-group.md new file mode 100644 index 0000000000..f5841cc060 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/student/student-group.md @@ -0,0 +1,8 @@ +# Grupo de Estudiante + +Un Grupo de Estudiante es una colección de estudiantes tomando el mismo curso. Puedes crear calendarios para los cursos y examinaciones para un Grupo de Estudiante. +Un Grupo de Estudiante necesita ser creado para cada curso en un año o término académico en particular. + +Student Group + +{next} diff --git a/erpnext/docs/user/manual/es/schools/student/student-log.md b/erpnext/docs/user/manual/es/schools/student/student-log.md new file mode 100644 index 0000000000..296b867c60 --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/student/student-log.md @@ -0,0 +1,8 @@ +# Bitácora de Estudiante (Log) + +Puedes crear una nota de una actividad de un estudiante usando la bitácora de estudiante (log) +Los registros de bitágora pueden ser categorizadas como 'General', 'Academic', 'Medical' or 'Achievement' + +Student + +{next} diff --git a/erpnext/docs/user/manual/es/schools/student/student.md b/erpnext/docs/user/manual/es/schools/student/student.md new file mode 100644 index 0000000000..fee84c5c4c --- /dev/null +++ b/erpnext/docs/user/manual/es/schools/student/student.md @@ -0,0 +1,10 @@ +# Estudiante + +Un estudiante es una persona que se ha registrado en su institución y has aceptado se solicitud de aplicación. +El doctype de Estudiante mantiene los detalles personales de los estudiantes. + +Puedes ver todo lo relacionado a un estudiante en particular en esta página. Ejemplo: Pagos, Grupo de Estudiante, etc. + +Student + +{next} From f6544e95d41e38416e4a9f5d43ff382704a681d0 Mon Sep 17 00:00:00 2001 From: Shreya Shah Date: Mon, 14 Aug 2017 17:29:09 +0530 Subject: [PATCH 14/52] [UI Tests] Buying Module - Supplier quotations and Purchase orders (#10397) * Get Supplier Quotation with item wise discount * Get purchase orders * Added paths * Codacy fix --- .../tests/test_purchase_order.js | 67 +++++++++++++++++++ .../tests/test_purchase_order_get_items.js | 62 +++++++++++++++++ .../test_purchase_order_with_multi_uom.js | 40 +++++++++++ ...pplier_quotation_for_item_wise_discount.js | 34 ++++++++++ erpnext/tests/ui/tests.txt | 6 +- 5 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js create mode 100644 erpnext/buying/doctype/purchase_order/tests/test_purchase_order_get_items.js create mode 100644 erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_multi_uom.js create mode 100644 erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_item_wise_discount.js diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js new file mode 100644 index 0000000000..4226880159 --- /dev/null +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js @@ -0,0 +1,67 @@ +QUnit.module('Buying'); + +QUnit.test("test: purchase order", function(assert) { + assert.expect(11); + let done = assert.async(); + + frappe.run_serially([ + () => { + return frappe.tests.make('Purchase Order', [ + {supplier: 'Test Supplier'}, + {company: 'Wind Power LLC'}, + {is_subcontracted: 'No'}, + {buying_price_list: 'Test-Buying-USD'}, + {currency: 'USD'}, + {items: [ + [ + {"item_code": 'Test Product 4'}, + {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)}, + {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)}, + {"qty": 5}, + {"uom": 'Unit'}, + {"rate": 100}, + {"warehouse": 'Stores - WP'} + ] + ]}, + + {tc_name: 'Test Term 1'}, + {terms: 'This is a term.'} + ]); + }, + + () => { + // Get supplier details + assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct"); + assert.ok($('div.control-value.like-disabled-input.for-description').text().includes('Contact 3'), "Contact display correct"); + assert.ok(cur_frm.doc.contact_email == 'test@supplier.com', "Contact email correct"); + // Get item details + assert.ok(cur_frm.doc.items[0].item_name == 'Test Product 4', "Item name correct"); + assert.ok(cur_frm.doc.items[0].description == 'Test Product 4', "Description correct"); + assert.ok(cur_frm.doc.items[0].qty == 5, "Quantity correct"); + // Calculate total + assert.ok(cur_frm.doc.total == 500, "Total correct"); + // Get terms + assert.ok(cur_frm.doc.terms == 'This is a term.', "Terms correct"); + }, + + () => cur_frm.print_doc(), + () => frappe.timeout(1), + () => { + assert.ok($('.btn-print-print').is(':visible'), "Print Format Available"); + assert.ok($('div > div:nth-child(5) > div > div > table > tbody > tr > td:nth-child(4) > div').text().includes('Test Product 4'), "Print Preview Works"); + }, + + () => cur_frm.print_doc(), + () => frappe.timeout(1), + + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), + + () => { + assert.ok(cur_frm.doc.status == 'To Receive and Bill', "Submitted successfully"); + }, + + () => done() + ]); +}); \ No newline at end of file diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_get_items.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_get_items.js new file mode 100644 index 0000000000..09fc33d4d8 --- /dev/null +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_get_items.js @@ -0,0 +1,62 @@ +QUnit.module('Buying'); + +QUnit.test("test: purchase order with get items", function(assert) { + assert.expect(4); + let done = assert.async(); + + frappe.run_serially([ + () => { + return frappe.tests.make('Purchase Order', [ + {supplier: 'Test Supplier'}, + {company: 'Wind Power LLC'}, + {is_subcontracted: 'No'}, + {buying_price_list: 'Test-Buying-USD'}, + {currency: 'USD'}, + {items: [ + [ + {"item_code": 'Test Product 4'}, + {"qty": 5}, + {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)}, + {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)}, + {"warehouse": 'Stores - WP'} + ] + ]} + ]); + }, + + () => { + assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct"); + }, + + () => frappe.timeout(0.3), + () => frappe.click_button('Get items from'), + () => frappe.timeout(0.3), + + () => frappe.click_link('Product Bundle'), + () => frappe.timeout(0.5), + + () => cur_dialog.set_value('product_bundle', 'Computer'), + () => frappe.click_button('Get Items'), + () => frappe.timeout(1), + + // Check if items are fetched from Product Bundle + () => { + assert.ok(cur_frm.doc.items[1].item_name == 'CPU', "Product bundle item 1 correct"); + assert.ok(cur_frm.doc.items[2].item_name == 'Screen', "Product bundle item 2 correct"); + assert.ok(cur_frm.doc.items[3].item_name == 'Keyboard', "Product bundle item 3 correct"); + }, + + () => cur_frm.doc.items[1].warehouse = 'Stores - WP', + () => cur_frm.doc.items[2].warehouse = 'Stores - WP', + () => cur_frm.doc.items[3].warehouse = 'Stores - WP', + + () => cur_frm.save(), + () => frappe.timeout(1), + + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), + + () => done() + ]); +}); \ No newline at end of file diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_multi_uom.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_multi_uom.js new file mode 100644 index 0000000000..0f543c5972 --- /dev/null +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_multi_uom.js @@ -0,0 +1,40 @@ +QUnit.module('Buying'); + +QUnit.test("test: purchase order with multi UOM", function(assert) { + assert.expect(3); + let done = assert.async(); + + frappe.run_serially([ + () => { + return frappe.tests.make('Purchase Order', [ + {supplier: 'Test Supplier'}, + {company: 'Wind Power LLC'}, + {is_subcontracted: 'No'}, + {items: [ + [ + {"item_code": 'Test Product 4'}, + {"qty": 5}, + {"uom": 'Unit'}, + {"rate": 100}, + {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)}, + {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)}, + {"warehouse": 'Stores - WP'} + ] + ]} + ]); + }, + + () => { + assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct"); + assert.ok(cur_frm.doc.items[0].item_name == 'Test Product 4', "Item name correct"); + assert.ok(cur_frm.doc.items[0].uom == 'Unit', "Multi UOM correct"); + }, + + () => frappe.timeout(1), + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), + + () => done() + ]); +}); \ No newline at end of file diff --git a/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_item_wise_discount.js b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_item_wise_discount.js new file mode 100644 index 0000000000..bc07b753b3 --- /dev/null +++ b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_item_wise_discount.js @@ -0,0 +1,34 @@ +QUnit.module('Buying'); + +QUnit.test("test: supplier quotation with item wise discount", function(assert){ + assert.expect(2); + let done = assert.async(); + + frappe.run_serially([ + () => { + return frappe.tests.make('Supplier Quotation', [ + {supplier: 'Test Supplier'}, + {company: 'Test Company'}, + {items: [ + [ + {"item_code": 'Test Product 4'}, + {"qty": 5}, + {"uom": 'Unit'}, + {"warehouse": 'All Warehouses - TC'}, + {'discount_percentage': 10}, + ] + ]} + ]); + }, + + () => { + assert.ok(cur_frm.doc.total == 900, "Total correct"); + assert.ok(cur_frm.doc.grand_total == 900, "Grand total correct"); + }, + + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), + () => done() + ]); +}); \ No newline at end of file diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index 68cfad6542..c5d450af6f 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -83,4 +83,8 @@ erpnext/buying/doctype/supplier/test_supplier.js erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.js erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_taxes_and_charges.js -erpnext/accounts/doctype/sales_invoice/test_sales_invoice.js \ No newline at end of file +erpnext/accounts/doctype/sales_invoice/test_sales_invoice.js +erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_item_wise_discount.js +erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js +erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_multi_uom.js +erpnext/buying/doctype/purchase_order/tests/test_purchase_order_get_items.js \ No newline at end of file From 289400d94492c5ff46584996584beee288cd4709 Mon Sep 17 00:00:00 2001 From: Shreya Shah Date: Wed, 16 Aug 2017 11:31:34 +0530 Subject: [PATCH 15/52] [UI Test] Buying module - Multiple tests for Purchase orders (#10414) * Extended timeout to avoid rare failures * Get purchase orders with discount on grand total * Get purchase orders with discount on individual items * Get purchase orders and calculate taxes * Added paths --- .../tests/test_purchase_order.js | 2 +- ...hase_order_with_discount_on_grand_total.js | 48 +++++++++++++++++++ ..._purchase_order_with_item_wise_discount.js | 45 +++++++++++++++++ ...t_purchase_order_with_taxes_and_charges.js | 44 +++++++++++++++++ .../tests/test_supplier_quotation.js | 2 +- erpnext/tests/ui/tests.txt | 5 +- 6 files changed, 143 insertions(+), 3 deletions(-) create mode 100644 erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_discount_on_grand_total.js create mode 100644 erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_item_wise_discount.js create mode 100644 erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js index 4226880159..940f36f1fd 100644 --- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js @@ -45,7 +45,7 @@ QUnit.test("test: purchase order", function(assert) { }, () => cur_frm.print_doc(), - () => frappe.timeout(1), + () => frappe.timeout(2), () => { assert.ok($('.btn-print-print').is(':visible'), "Print Format Available"); assert.ok($('div > div:nth-child(5) > div > div > table > tbody > tr > td:nth-child(4) > div').text().includes('Test Product 4'), "Print Preview Works"); diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_discount_on_grand_total.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_discount_on_grand_total.js new file mode 100644 index 0000000000..54fa777668 --- /dev/null +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_discount_on_grand_total.js @@ -0,0 +1,48 @@ +QUnit.module('Buying'); + +QUnit.test("test: purchase order with discount on grand total", function(assert) { + assert.expect(4); + let done = assert.async(); + + frappe.run_serially([ + () => { + return frappe.tests.make('Purchase Order', [ + {supplier: 'Test Supplier'}, + {company: 'Wind Power LLC'}, + {is_subcontracted: 'No'}, + {buying_price_list: 'Test-Buying-EUR'}, + {currency: 'EUR'}, + {items: [ + [ + {"item_code": 'Test Product 4'}, + {"qty": 5}, + {"uom": 'Unit'}, + {"rate": 500 }, + {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)}, + {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)}, + {"warehouse": 'Stores - WP'} + ] + ]}, + {apply_discount_on: 'Grand Total'}, + {additional_discount_percentage: 10} + ]); + }, + + () => frappe.timeout(1), + + () => { + assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct"); + assert.ok(cur_frm.doc.items[0].rate == 500, "Rate correct"); + // Calculate total + assert.ok(cur_frm.doc.total == 2500, "Total correct"); + // Calculate grand total after discount + assert.ok(cur_frm.doc.grand_total == 2250, "Grand total correct"); + }, + + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), + + () => done() + ]); +}); \ No newline at end of file diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_item_wise_discount.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_item_wise_discount.js new file mode 100644 index 0000000000..4ea8b976fb --- /dev/null +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_item_wise_discount.js @@ -0,0 +1,45 @@ +QUnit.module('Buying'); + +QUnit.test("test: purchase order with item wise discount", function(assert) { + assert.expect(4); + let done = assert.async(); + + frappe.run_serially([ + () => { + return frappe.tests.make('Purchase Order', [ + {supplier: 'Test Supplier'}, + {company: 'Wind Power LLC'}, + {is_subcontracted: 'No'}, + {buying_price_list: 'Test-Buying-EUR'}, + {currency: 'EUR'}, + {items: [ + [ + {"item_code": 'Test Product 4'}, + {"qty": 5}, + {"uom": 'Unit'}, + {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)}, + {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)}, + {"warehouse": 'Stores - WP'}, + {"discount_percentage": 20} + ] + ]} + ]); + }, + + () => frappe.timeout(1), + + () => { + assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct"); + assert.ok(cur_frm.doc.items[0].discount_percentage == 20, "Discount correct"); + // Calculate totals after discount + assert.ok(cur_frm.doc.total == 2000, "Total correct"); + assert.ok(cur_frm.doc.grand_total == 2000, "Grand total correct"); + }, + + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), + + () => done() + ]); +}); \ No newline at end of file diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js new file mode 100644 index 0000000000..b5f59ad339 --- /dev/null +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js @@ -0,0 +1,44 @@ +QUnit.module('Buying'); + +QUnit.test("test: purchase order with taxes and charges", function(assert) { + assert.expect(3); + let done = assert.async(); + + frappe.run_serially([ + () => { + return frappe.tests.make('Purchase Order', [ + {supplier: 'Test Supplier'}, + {company: 'Wind Power LLC'}, + {is_subcontracted: 'No'}, + {buying_price_list: 'Test-Buying-USD'}, + {currency: 'USD'}, + {items: [ + [ + {"item_code": 'Test Product 4'}, + {"qty": 5}, + {"uom": 'Unit'}, + {"rate": 500 }, + {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)}, + {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)}, + {"warehouse": 'Stores - WP'} + ] + ]}, + + {taxes_and_charges: 'TEST In State GST'} + ]); + }, + + () => { + // Check taxes and calculate grand total + assert.ok(cur_frm.doc.taxes[1].account_head=='SGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), "Account Head abbr correct"); + assert.ok(cur_frm.doc.total_taxes_and_charges == 225, "Taxes and charges correct"); + assert.ok(cur_frm.doc.grand_total == 2725, "Grand total correct"); + }, + + () => frappe.timeout(0.3), + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), + () => done() + ]); +}); \ No newline at end of file diff --git a/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js index 81e512ba2c..8404cb5b25 100644 --- a/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js +++ b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js @@ -46,7 +46,7 @@ QUnit.test("test: supplier quotation", function(assert) { }, () => cur_frm.print_doc(), - () => frappe.timeout(1), + () => frappe.timeout(2), () => { assert.ok($('.btn-print-print').is(':visible'), "Print Format Available"); assert.ok($("table > tbody > tr > td:nth-child(3) > div").text().includes("Test Product 4"), "Print Preview Works As Expected"); diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index c5d450af6f..86b6a3a512 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -87,4 +87,7 @@ erpnext/accounts/doctype/sales_invoice/test_sales_invoice.js erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_item_wise_discount.js erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_multi_uom.js -erpnext/buying/doctype/purchase_order/tests/test_purchase_order_get_items.js \ No newline at end of file +erpnext/buying/doctype/purchase_order/tests/test_purchase_order_get_items.js +erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_discount_on_grand_total.js +erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_item_wise_discount.js +erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js \ No newline at end of file From 44b088c6b3b255469bede0745acaf8a733a84b3a Mon Sep 17 00:00:00 2001 From: Utkarsh Goswami Date: Wed, 16 Aug 2017 11:32:04 +0530 Subject: [PATCH 16/52] [UI Test Salary] To test the salary structure and the salary slip (#10407) * Test for salary structure and salary slip * Test for salary structure and salary slip * Test for salary structure and salary slip * Travis CI fixes * Updated * Updated * travis fixes * Travis fixes --- erpnext/hr/doctype/employee/test_employee.js | 63 ++++++++------- .../test_employee_attendance_tool.js | 10 +-- .../test_leave_control_panel.js | 4 +- .../doctype/salary_slip/test_salary_slip.js | 49 +++++++++++ .../salary_structure/test_salary_structure.js | 81 +++++++++++++++++++ erpnext/tests/ui/tests.txt | 2 + 6 files changed, 170 insertions(+), 39 deletions(-) create mode 100644 erpnext/hr/doctype/salary_slip/test_salary_slip.js create mode 100644 erpnext/hr/doctype/salary_structure/test_salary_structure.js diff --git a/erpnext/hr/doctype/employee/test_employee.js b/erpnext/hr/doctype/employee/test_employee.js index 64a6b7a9bf..b7f510506b 100644 --- a/erpnext/hr/doctype/employee/test_employee.js +++ b/erpnext/hr/doctype/employee/test_employee.js @@ -1,39 +1,40 @@ QUnit.module('hr'); QUnit.test("Test: Employee [HR]", function (assert) { - assert.expect(3); + assert.expect(4); let done = assert.async(); - let today_date = frappe.datetime.nowdate(); - - frappe.run_serially([ + // let today_date = frappe.datetime.nowdate(); + let employee_creation = (name,joining_date,birth_date) => { + frappe.run_serially([ // test employee creation - () => frappe.set_route("List", "Employee", "List"), - () => frappe.new_doc("Employee"), - () => frappe.timeout(1), - () => cur_frm.set_value("employee_name", "Test Employee 1"), - () => cur_frm.set_value("salutation", "Ms"), - () => cur_frm.set_value("company", "Test Company"), - () => cur_frm.set_value("date_of_joining", frappe.datetime.add_months(today_date, -2)), // joined 2 month from now - () => cur_frm.set_value("date_of_birth", frappe.datetime.add_months(today_date, -240)), // age is 20 years - () => cur_frm.set_value("employment_type", "Test Employment type"), - () => cur_frm.set_value("holiday_list", "Test Holiday list"), - () => cur_frm.set_value("branch", "Test Branch"), - () => cur_frm.set_value("department", "Test Department"), - () => cur_frm.set_value("designation", "Test Designation"), - () => frappe.click_button('Add Row'), - () => cur_frm.fields_dict.leave_approvers.grid.grid_rows[0].doc.leave_approver="Administrator", - // save data - () => cur_frm.save(), - () => frappe.timeout(1), - // check name of employee - () => assert.equal("Test Employee 1", cur_frm.doc.employee_name, - 'name of employee correctly saved'), - // check auto filled gender according to salutation - () => assert.equal("Female", cur_frm.doc.gender, - 'gender correctly saved as per salutation'), - // check auto filled retirement date [60 years from DOB] - () => assert.equal(frappe.datetime.add_months(today_date, 480), cur_frm.doc.date_of_retirement, // 40 years from now - 'retirement date correctly saved as per date of birth'), + () => { + frappe.tests.make('Employee', [ + { employee_name: name}, + { salutation: 'Mr'}, + { company: 'Test Company'}, + { date_of_joining: joining_date}, + { date_of_birth: birth_date}, + { employment_type: 'Test Employment Type'}, + { holiday_list: 'Test Holiday List'}, + { branch: 'Test Branch'}, + { department: 'Test Department'}, + { designation: 'Test Designation'} + ]); + }, + () => frappe.timeout(2), + () => { + assert.ok(cur_frm.get_field('employee_name').value==name, + 'Name of an Employee is correctly set'); + assert.ok(cur_frm.get_field('gender').value=='Male', + 'Gender of an Employee is correctly set'); + }, + ]); + }; + frappe.run_serially([ + () => employee_creation('Test Employee 1','2017-04-01','1992-02-02'), + () => frappe.timeout(6), + () => employee_creation('Test Employee 3','2017-04-01','1992-02-02'), + () => frappe.timeout(4), () => done() ]); }); \ No newline at end of file diff --git a/erpnext/hr/doctype/employee_attendance_tool/test_employee_attendance_tool.js b/erpnext/hr/doctype/employee_attendance_tool/test_employee_attendance_tool.js index a71ba0f2a2..3ec8ac0a59 100644 --- a/erpnext/hr/doctype/employee_attendance_tool/test_employee_attendance_tool.js +++ b/erpnext/hr/doctype/employee_attendance_tool/test_employee_attendance_tool.js @@ -1,10 +1,10 @@ QUnit.module('hr'); QUnit.test("Test: Employee attendance tool [HR]", function (assert) { - assert.expect(3); + assert.expect(2); let done = assert.async(); let today_date = frappe.datetime.nowdate(); - let date_of_attendance = frappe.datetime.add_days(today_date, -1); // previous day + let date_of_attendance = frappe.datetime.add_days(today_date, -2); // previous day frappe.run_serially([ // create employee @@ -38,11 +38,9 @@ QUnit.test("Test: Employee attendance tool [HR]", function (assert) { () => frappe.set_route("List", "Attendance", "List"), () => frappe.timeout(1), () => { - assert.deepEqual(["Test Employee 2", "Test Employee 1"], [cur_list.data[0].employee_name, cur_list.data[1].employee_name], - "marked attendance correctly saved for both employee"); let marked_attendance = cur_list.data.filter(d => d.attendance_date == date_of_attendance); - assert.equal(marked_attendance.length, 2, - 'both the attendance are marked for correct date'); + assert.equal(marked_attendance.length, 3, + 'all the attendance are marked for correct date'); }, () => done() ]); diff --git a/erpnext/hr/doctype/leave_control_panel/test_leave_control_panel.js b/erpnext/hr/doctype/leave_control_panel/test_leave_control_panel.js index e71ff6e396..5133c0c282 100644 --- a/erpnext/hr/doctype/leave_control_panel/test_leave_control_panel.js +++ b/erpnext/hr/doctype/leave_control_panel/test_leave_control_panel.js @@ -28,8 +28,8 @@ QUnit.test("Test: Leave control panel [HR]", function (assert) { () => frappe.timeout(1), () => { let leave_allocated = cur_list.data.filter(d => d.leave_type == "Test Leave type"); - assert.equal(2, leave_allocated.length, - 'leave allocation successfully done for both the employee'); + assert.equal(3, leave_allocated.length, + 'leave allocation successfully done for all the employees'); }, () => done() ]); diff --git a/erpnext/hr/doctype/salary_slip/test_salary_slip.js b/erpnext/hr/doctype/salary_slip/test_salary_slip.js new file mode 100644 index 0000000000..a49c973d13 --- /dev/null +++ b/erpnext/hr/doctype/salary_slip/test_salary_slip.js @@ -0,0 +1,49 @@ +QUnit.test("test salary slip", function(assert) { + assert.expect(6); + let done = assert.async(); + let employee_name; + + let salary_slip = (ename) => { + frappe.run_serially([ + () => frappe.db.get_value('Employee', {'employee_name': ename}, 'name'), + (r) => { + employee_name = r.message.name; + }, + () => { + // Creating a salary slip for a employee + frappe.tests.make('Salary Slip', [ + { employee: employee_name} + ]); + }, + () => frappe.timeout(1), + () => { + // To check if all the calculations are correctly done + if(ename === 'Test Employee 1') + { + assert.ok(cur_frm.doc.gross_pay==24000, + 'Gross amount for first employee is correctly calculated'); + assert.ok(cur_frm.doc.total_deduction==4800, + 'Deduction amount for first employee is correctly calculated'); + assert.ok(cur_frm.doc.net_pay==19200, + 'Net amount for first employee is correctly calculated'); + } + if(ename === 'Test Employee 3') + { + assert.ok(cur_frm.doc.gross_pay==28800, + 'Gross amount for second employee is correctly calculated'); + assert.ok(cur_frm.doc.total_deduction==5760, + 'Deduction amount for second employee is correctly calculated'); + assert.ok(cur_frm.doc.net_pay==23040, + 'Net amount for second employee is correctly calculated'); + } + }, + ]); + }; + frappe.run_serially([ + () => salary_slip('Test Employee 1'), + () => frappe.timeout(6), + () => salary_slip('Test Employee 3'), + () => frappe.timeout(3), + () => done() + ]); +}); \ No newline at end of file diff --git a/erpnext/hr/doctype/salary_structure/test_salary_structure.js b/erpnext/hr/doctype/salary_structure/test_salary_structure.js new file mode 100644 index 0000000000..074035772c --- /dev/null +++ b/erpnext/hr/doctype/salary_structure/test_salary_structure.js @@ -0,0 +1,81 @@ +QUnit.test("test Salary Structure", function(assert) { + assert.expect(6); + let done = assert.async(); + let employee_name1; + + let salary_structure = (ename1,ename2) => { + frappe.run_serially([ + () => frappe.db.get_value('Employee', {'employee_name': ename1}, 'name'), + (r) => { + employee_name1 = r.message.name; + }, + () => frappe.db.get_value('Employee', {'employee_name': ename2}, 'name'), + (r) => { + // Creating Salary Structure for employees); + frappe.tests.make('Salary Structure', [ + { company: 'Test Company'}, + { payroll_frequency: 'Monthly'}, + { employees: [ + [ + {employee: employee_name1}, + {from_date: '2017-07-01'}, + {base: 25000} + ], + [ + {employee: r.message.name}, + {from_date: '2017-07-01'}, + {base: 30000} + ] + ]}, + { earnings: [ + [ + {salary_component: 'Basic'}, + {formula: 'base * .80'} + ], + [ + {salary_component: 'Leave Encashment'}, + {formula: 'B * .20'} + ] + ]}, + { deductions: [ + [ + {salary_component: 'Income Tax'}, + {formula: '(B+LE) * .20'} + ] + ]}, + { payment_account: 'CASH - TC'}, + ]); + }, + () => frappe.timeout(9), + () => cur_dialog.set_value('value','Test Salary Structure'), + () => frappe.timeout(2), + () => frappe.click_button('Create'), + () => { + // To check if all the fields are correctly set + assert.ok(cur_frm.doc.employees[0].employee_name.includes('Test Employee 1') && + cur_frm.doc.employees[1].employee_name.includes('Test Employee 3'), + 'Employee names are correctly set'); + + assert.ok(cur_frm.doc.employees[0].base==25000, + 'Base value for first employee is correctly set'); + + assert.ok(cur_frm.doc.employees[1].base==30000, + 'Base value for second employee is correctly set'); + + assert.ok(cur_frm.doc.earnings[0].formula.includes('base * .80'), + 'Formula for earnings as Basic is correctly set'); + + assert.ok(cur_frm.doc.earnings[1].formula.includes('B * .20'), + 'Formula for earnings as Leave Encashment is correctly set'); + + assert.ok(cur_frm.doc.deductions[0].formula.includes('(B+LE) * .20'), + 'Formula for deductions as Income Tax is correctly set'); + }, + ]); + }; + frappe.run_serially([ + () => salary_structure('Test Employee 1','Test Employee 3'), + () => frappe.timeout(14), + () => done() + ]); +}); \ No newline at end of file diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index 86b6a3a512..5d60ad1bf1 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -64,6 +64,8 @@ erpnext/schools/doctype/assessment_criteria_group/test_assessment_criteria_group erpnext/schools/doctype/assessment_criteria/test_assessment_criteria.js erpnext/schools/doctype/course/test_course.js erpnext/schools/doctype/program/test_program.js +erpnext/hr/doctype/salary_structure/test_salary_structure.js +erpnext/hr/doctype/salary_slip/test_salary_slip.js erpnext/schools/doctype/guardian/test_guardian.js erpnext/schools/doctype/student_admission/test_student_admission.js erpnext/schools/doctype/student_applicant/tests/test_student_applicant_dummy_data.js From 0371d5a326cd603c18929d654c53726d95afe132 Mon Sep 17 00:00:00 2001 From: Manas Solanki Date: Wed, 16 Aug 2017 11:35:04 +0530 Subject: [PATCH 17/52] new item group filter in the stock ledger report (#10400) --- .../stock/report/stock_ledger/stock_ledger.js | 6 ++++++ .../stock/report/stock_ledger/stock_ledger.py | 19 +++++++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.js b/erpnext/stock/report/stock_ledger/stock_ledger.js index ce357db3f8..e95f5cab57 100644 --- a/erpnext/stock/report/stock_ledger/stock_ledger.js +++ b/erpnext/stock/report/stock_ledger/stock_ledger.js @@ -37,6 +37,12 @@ frappe.query_reports["Stock Ledger"] = { "fieldtype": "Link", "options": "Item" }, + { + "fieldname":"item_group", + "label": __("Item Group"), + "fieldtype": "Link", + "options": "Item Group" + }, { "fieldname":"batch_no", "label": __("Batch No"), diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py index 916adff72d..6820d8fa5b 100644 --- a/erpnext/stock/report/stock_ledger/stock_ledger.py +++ b/erpnext/stock/report/stock_ledger/stock_ledger.py @@ -65,7 +65,7 @@ def get_stock_ledger_entries(filters): def get_item_details(filters): item_details = {} for item in frappe.db.sql("""select name, item_name, description, item_group, - brand, stock_uom from `tabItem` {item_conditions}"""\ + brand, stock_uom from `tabItem` item {item_conditions}"""\ .format(item_conditions=get_item_conditions(filters)), filters, as_dict=1): item_details.setdefault(item.name, item) @@ -74,9 +74,11 @@ def get_item_details(filters): def get_item_conditions(filters): conditions = [] if filters.get("item_code"): - conditions.append("name=%(item_code)s") + conditions.append("item.name=%(item_code)s") if filters.get("brand"): - conditions.append("brand=%(brand)s") + conditions.append("item.brand=%(brand)s") + if filters.get("item_group"): + conditions.append(get_item_group_condition(filters.get("item_group"))) return "where {}".format(" and ".join(conditions)) if conditions else "" @@ -84,7 +86,7 @@ def get_sle_conditions(filters): conditions = [] item_conditions=get_item_conditions(filters) if item_conditions: - conditions.append("""item_code in (select name from tabItem + conditions.append("""sle.item_code in (select item.name from tabItem item {item_conditions})""".format(item_conditions=item_conditions)) if filters.get("warehouse"): conditions.append(get_warehouse_condition(filters.get("warehouse"))) @@ -122,3 +124,12 @@ def get_warehouse_condition(warehouse): warehouse_details.rgt) return '' + +def get_item_group_condition(item_group): + item_group_details = frappe.db.get_value("Item Group", item_group, ["lft", "rgt"], as_dict=1) + if item_group_details: + return "item.item_group in (select ig.name from `tabItem Group` ig \ + where ig.lft >= %s and ig.rgt <= %s and item.item_group = ig.name)"%(item_group_details.lft, + item_group_details.rgt) + + return '' From 5fc5b68a49c197b2e6abc21addc2cac864fea7d8 Mon Sep 17 00:00:00 2001 From: tundebabzy Date: Wed, 16 Aug 2017 07:11:56 +0100 Subject: [PATCH 18/52] update multi currency accounting documentation to remove incorrect info (#10404) --- .../en/accounts/multi-currency-accounting.md | 64 +++---------------- 1 file changed, 9 insertions(+), 55 deletions(-) diff --git a/erpnext/docs/user/manual/en/accounts/multi-currency-accounting.md b/erpnext/docs/user/manual/en/accounts/multi-currency-accounting.md index 598aa0e7f6..060cd17d99 100644 --- a/erpnext/docs/user/manual/en/accounts/multi-currency-accounting.md +++ b/erpnext/docs/user/manual/en/accounts/multi-currency-accounting.md @@ -23,6 +23,15 @@ You can change accounting currency in Party / Account record, until making any t In case of multi-company setup, accounting currency of Party must be same for all the companies. +### Exchange Rates +When dealing with multiple currencies, ERPNext has the Currency Exchange module for managing exchange rates. It allows you to save the exchange rate quotes you require. + +For foreign currency transactions, ERPNext checks Currency Exchange for any matching record. If this fails, ERPNext will attempt to get the exchange rate quote from [fixer.io](http://fixer.io). If this still fails, then the exchange rate will have to be entered manually. + +#### Exchange Rate Selection +ERPNext automatically fetches the latest exchange rate available. + + ## Transactions ### Sales Invoice @@ -50,61 +59,6 @@ In Accounts table, on selection of foreign currency account, system will show Cu Journal Entry in multi currency -#### Example 1: Payment Entry Against Customer With Alternate Currency - -Suppose, default currency of the company is INR and customer's accounting currency is USD. Customer made full payment against an outstanding invoice of USD 100. Exchange Rate (USD -> INR) in Sales Invoice was 60. - -Exchange Rate in the payment entry should always be same as invoice (60), even if exchange rate on the payment date is 62. The bank account will be credited by the amount considering exchange rate as 62. Hence, Exchnage Gain / Loss will be booked based on exchange rate difference. - -Payment Entry - -#### Example 2: Inter-bank Transfer (USD -> INR) - -Suppose the default currency of the company is INR. You have a Paypal account for which Currency is USD. You receive payments in the paypal account and lets say, paypal transfers amount once in a week to your other bank account which is managed in INR. - -Paypal account gets debited on different date with different exchange rate, but on transfer date the exchange rate can be different. Hence, there is generally Exchange Loss / Gain on the transfer entry. -In the bank transfer entry, system sets exchange rate of the credit account (Paypal) based on the average incoming exchange rate. This is to maintain Paypal balance properly in company currency. In case you modify the average exchange rate, you need to adjust the exchange rate manually in the future entries, so that balance in account currency and company currency are in sync. -Then you should calculate and enter Exchange Loss / Gain based on the Paypal exchange rate and the exchange rate on the transfer date. - -Lets say, Paypal account debited by following amounts over the week, which has not been transferred to your other bank account. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
DateAccountDebit (USD)Exchange Rate
2015-09-02Paypal10060
2015-09-02Paypal10061
2015-09-02Paypal10064
- - -Suppose, Exchange Rate on the payment date is 62 and Bank Transfer Entry will be look like below: - -Inter Bank Transfer - - ## Reports ### General Ledger From 9eb8680ec967f3b03e889d1d510ed2c7310eb8c8 Mon Sep 17 00:00:00 2001 From: Zarrar Date: Wed, 16 Aug 2017 13:25:31 +0530 Subject: [PATCH 19/52] travis failing issue fix (#10420) --- .../student_applicant/tests/test_student_applicant_options.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/schools/doctype/student_applicant/tests/test_student_applicant_options.js b/erpnext/schools/doctype/student_applicant/tests/test_student_applicant_options.js index b983afd997..5a6f6df99b 100644 --- a/erpnext/schools/doctype/student_applicant/tests/test_student_applicant_options.js +++ b/erpnext/schools/doctype/student_applicant/tests/test_student_applicant_options.js @@ -86,8 +86,9 @@ QUnit.test('test student applicant', function(assert){ // Enrolling the Student into a Program () => {$('.form-documents .row:nth-child(1) .col-xs-6:nth-child(1) .octicon-plus').click();}, () => frappe.timeout(1), + () => cur_frm.set_value('program', 'Standard Test'), + () => frappe.timeout(1), () => { - cur_frm.set_value('program', 'Standard Test'); cur_frm.set_value('student_category', 'Reservation'); cur_frm.set_value('student_batch_name', 'A'); cur_frm.set_value('academic_year', '2016-17'); From f37eacdee5e2b081d710857ab5c68fc58bb12e2e Mon Sep 17 00:00:00 2001 From: Vishal Dhayagude Date: Thu, 17 Aug 2017 11:01:59 +0530 Subject: [PATCH 20/52] [UI Test] Purchase Invoice (#10422) * [UI Test] Purchase Invoice * [fix] Travis failed --- .../purchase_invoice/test_purchase_invoice.js | 43 +++++++++++++++++++ ...est_purchase_taxes_and_charges_template.js | 26 +++++++++++ ...upplier_quotation_for_taxes_and_charges.js | 29 +------------ erpnext/tests/ui/tests.txt | 2 + 4 files changed, 73 insertions(+), 27 deletions(-) create mode 100644 erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.js create mode 100644 erpnext/accounts/doctype/purchase_taxes_and_charges_template/test_purchase_taxes_and_charges_template.js diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.js new file mode 100644 index 0000000000..6e33e1d7f2 --- /dev/null +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.js @@ -0,0 +1,43 @@ +QUnit.module('Purchaes Invoice'); + +QUnit.test("test purchase invoice", function(assert) { + assert.expect(4); + let done = assert.async(); + frappe.run_serially([ + () => { + return frappe.tests.make('Purchase Invoice', [ + {supplier: 'Test Supplier'}, + {items: [ + [ + {'qty': 5}, + {'item_code': 'Test Product 1'}, + {'rate':100}, + ] + ]}, + {update_stock:1}, + {supplier_address: 'Test1-Billing'}, + {contact_person: 'Contact 3-Test Supplier'}, + {taxes_and_charges: 'TEST In State GST'}, + {tc_name: 'Test Term 1'}, + {terms: 'This is Test'} + ]); + }, + () => cur_frm.save(), + () => { + // get_item_details + assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct"); + // get tax details + assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST', "Tax details correct"); + // get tax account head details + assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct"); + // grand_total Calculated + assert.ok(cur_frm.doc.grand_total==590, "Grad Total correct"); + + }, + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), + () => done() + ]); +}); + diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges_template/test_purchase_taxes_and_charges_template.js b/erpnext/accounts/doctype/purchase_taxes_and_charges_template/test_purchase_taxes_and_charges_template.js new file mode 100644 index 0000000000..5e357ca2ad --- /dev/null +++ b/erpnext/accounts/doctype/purchase_taxes_and_charges_template/test_purchase_taxes_and_charges_template.js @@ -0,0 +1,26 @@ +QUnit.module('Sales Taxes and Charges Template'); + +QUnit.test("test sales taxes and charges template", function(assert) { + assert.expect(1); + let done = assert.async(); + frappe.run_serially([ + () => { + return frappe.tests.make('Purchase Taxes and Charges Template', [ + {title: "TEST In State GST"}, + {taxes:[ + [ + {charge_type:"On Net Total"}, + {account_head:"CGST - "+frappe.get_abbr(frappe.defaults.get_default("Company")) } + ], + [ + {charge_type:"On Net Total"}, + {account_head:"SGST - "+frappe.get_abbr(frappe.defaults.get_default("Company")) } + ] + ]} + ]); + }, + () => {assert.ok(cur_frm.doc.title=='TEST In State GST');}, + () => done() + ]); +}); + diff --git a/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_taxes_and_charges.js b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_taxes_and_charges.js index e1e393b67c..c4b341952c 100644 --- a/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_taxes_and_charges.js +++ b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_taxes_and_charges.js @@ -14,38 +14,13 @@ QUnit.test("test: supplier quotation with taxes and charges", function(assert) { {"item_code": 'Test Product 4'}, {"qty": 5}, {"rate": 100}, - {"warehouse": 'Stores - WP'}, + {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default('Company'))}, ] ]}, + {taxes_and_charges:'TEST In State GST'}, ]); }, () => {supplier_quotation_name = cur_frm.doc.name;}, - () => frappe.set_route('Form', 'Purchase Taxes and Charges Template', 'New Purchase Taxes and Charges Template'), - () => frappe.timeout(1), - () => { - return frappe.tests.set_form_values(cur_frm, [ - {title:'TEST In State GST'}, - {taxes: [ - [ - {"charge_type": 'On Net Total'}, - {"account_head": 'CGST - WP'} - ], - [ - {"charge_type": 'On Net Total'}, - {"account_head": 'SGST - WP'} - ] - ]}, - ]); - }, - () => cur_frm.save(), - () => frappe.set_route('Form', 'Supplier Quotation', supplier_quotation_name), - () => frappe.timeout(1), - () => { - return frappe.tests.set_form_values(cur_frm, [ - {taxes_and_charges:'TEST In State GST'} - ]); - }, - () => { assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct"); assert.ok(cur_frm.doc.total_taxes_and_charges == 45, "Taxes and charges correct"); diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index 5d60ad1bf1..eac65a6947 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -4,6 +4,7 @@ erpnext/accounts/doctype/account/test_account.js erpnext/accounts/doctype/account/test_make_tax_account.js erpnext/accounts/doctype/pricing_rule/test_pricing_rule.js erpnext/accounts/doctype/sales_taxes_and_charges_template/test_sales_taxes_and_charges_template.js +erpnext/accounts/doctype/purchase_taxes_and_charges_template/test_purchase_taxes_and_charges_template.js erpnext/accounts/doctype/shipping_rule/test_shipping_rule.js erpnext/crm/doctype/lead/test_lead.js erpnext/crm/doctype/opportunity/test_opportunity.js @@ -86,6 +87,7 @@ erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.js erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_taxes_and_charges.js erpnext/accounts/doctype/sales_invoice/test_sales_invoice.js +erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.js erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_item_wise_discount.js erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_multi_uom.js From b5ed6823d6d19a17024f49b78cca2b324f75b0bb Mon Sep 17 00:00:00 2001 From: Shreya Shah Date: Thu, 17 Aug 2017 11:03:43 +0530 Subject: [PATCH 21/52] [UI Test] Buying - Create Purchase receipt (#10421) * Create purchase receipt after submitting the purchase order * Checks quantity and rate in stock ledger --- .../tests/test_purchase_order_receipt.js | 77 +++++++++++++++++++ erpnext/tests/ui/tests.txt | 3 +- 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js new file mode 100644 index 0000000000..654586ae57 --- /dev/null +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js @@ -0,0 +1,77 @@ +QUnit.module('Buying'); + +QUnit.test("test: purchase order receipt", function(assert) { + assert.expect(5); + let done = assert.async(); + + frappe.run_serially([ + () => { + return frappe.tests.make('Purchase Order', [ + {supplier: 'Test Supplier'}, + {company: 'Wind Power LLC'}, + {is_subcontracted: 'No'}, + {buying_price_list: 'Test-Buying-USD'}, + {currency: 'USD'}, + {items: [ + [ + {"item_code": 'Test Product 1'}, + {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)}, + {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)}, + {"qty": 5}, + {"uom": 'Unit'}, + {"rate": 100}, + {"warehouse": 'Stores - WP'} + ] + ]}, + ]); + }, + + () => { + + // Check supplier and item details + assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct"); + assert.ok(cur_frm.doc.items[0].item_name == 'Test Product 1', "Item name correct"); + assert.ok(cur_frm.doc.items[0].description == 'Test Product 1', "Description correct"); + assert.ok(cur_frm.doc.items[0].qty == 5, "Quantity correct"); + + }, + + () => frappe.timeout(1), + + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + + () => frappe.timeout(1.5), + () => frappe.click_button('Close'), + () => frappe.timeout(0.3), + + // Make Purchase Receipt + () => frappe.click_button('Make'), + () => frappe.timeout(0.3), + + () => frappe.click_link('Receipt'), + () => frappe.timeout(2), + + () => cur_frm.save(), + + // Save and submit Purchase Receipt + () => frappe.timeout(1), + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(1), + + // View Purchase order in Stock Ledger + () => frappe.click_button('View'), + () => frappe.timeout(0.3), + + () => frappe.click_link('Stock Ledger'), + () => frappe.timeout(2), + () => { + assert.ok($('div.slick-cell.l2.r2 > a').text().includes('Test Product 1') + && $('div.slick-cell.l9.r9 > div').text().includes(5) + && $('div.slick-cell.l12.r12 > div').text().includes(100), "Stock ledger entry correct"); + }, + + () => done() + ]); +}); \ No newline at end of file diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index eac65a6947..2e71285097 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -94,4 +94,5 @@ erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_multi_uom.j erpnext/buying/doctype/purchase_order/tests/test_purchase_order_get_items.js erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_discount_on_grand_total.js erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_item_wise_discount.js -erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js \ No newline at end of file +erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js +erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js \ No newline at end of file From abd3419632df98a533951885ab4f8d63e959fbf6 Mon Sep 17 00:00:00 2001 From: Zarrar Date: Thu, 17 Aug 2017 11:04:16 +0530 Subject: [PATCH 22/52] made test less dependent on python test data (#10424) --- .../test_student_group_creation_tool.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/schools/doctype/student_group_creation_tool/test_student_group_creation_tool.js b/erpnext/schools/doctype/student_group_creation_tool/test_student_group_creation_tool.js index 366822ee91..a8567b3ba0 100644 --- a/erpnext/schools/doctype/student_group_creation_tool/test_student_group_creation_tool.js +++ b/erpnext/schools/doctype/student_group_creation_tool/test_student_group_creation_tool.js @@ -19,9 +19,10 @@ QUnit.test('Test: Student Group Creation Tool', function(assert){ cur_frm.set_value("program", "Standard Test"); frappe.tests.click_button('Get Courses'); }, - () => frappe.timeout(0.5), + () => frappe.timeout(1), () => { - assert.equal(cur_frm.doc.courses.length, 4, 'Successfully created groups using the tool'); + let no_of_courses = $('input.grid-row-check.pull-left').size() - 1; + assert.equal(cur_frm.doc.courses.length, no_of_courses, 'Successfully created groups using the tool'); }, () => { From f7e42211b91a67d09c94346d58a48cd0c63b70f1 Mon Sep 17 00:00:00 2001 From: Ben Cornwell-Mott Date: Wed, 26 Jul 2017 23:09:01 -0700 Subject: [PATCH 23/52] Added Quote Status to RFQ Suppliers with No Quote --- .../request_for_quotation.js | 25 ++++++- .../request_for_quotation.py | 22 +++++++ .../request_for_quotation_supplier.json | 65 ++++++++++++++++++- .../supplier_quotation/supplier_quotation.py | 34 ++++++++++ .../manual/en/buying/request-for-quotation.md | 32 ++++----- 5 files changed, 160 insertions(+), 18 deletions(-) diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js index 558e072cad..6b37edafc7 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js @@ -138,7 +138,6 @@ frappe.ui.form.on("Request for Quotation",{ dialog.show(); }, - make_suppplier_quotation: function(frm) { var doc = frm.doc; var dialog = new frappe.ui.Dialog({ @@ -207,6 +206,30 @@ frappe.ui.form.on("Request for Quotation Supplier",{ if(!w) { frappe.msgprint(__("Please enable pop-ups")); return; } + }, + no_quote: function(frm, cdt, cdn) { + var d = locals[cdt][cdn]; + if (d.no_quote) { + if (d.quote_status != __('Received')) { + frappe.model.set_value(cdt, cdn, 'quote_status', 'No Quote'); + } else { + frappe.msgprint(__("Cannot set a received RFQ to No Quote")); + frappe.model.set_value(cdt, cdn, 'no_quote', 0); + } + } else { + d.quote_status = __('Pending'); + frm.call({ + method:"update_rfq_supplier_status", + doc: frm.doc, + args: { + sup_name: d.supplier + }, + callback: function(r) { + frm.refresh_field("suppliers"); + } + }); + } + } }) diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py index e9603fbcae..a8e897c2dd 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py @@ -54,6 +54,7 @@ class RequestforQuotation(BuyingController): frappe.db.set(self, 'status', 'Submitted') for supplier in self.suppliers: supplier.email_sent = 0 + supplier.quote_status = 'Pending' def on_cancel(self): frappe.db.set(self, 'status', 'Cancelled') @@ -157,6 +158,27 @@ class RequestforQuotation(BuyingController): attachments.append(frappe.attach_print(self.doctype, self.name, doc=self)) return attachments + def update_rfq_supplier_status(self, sup_name=None): + for supplier in self.suppliers: + if sup_name != None and supplier.supplier == sup_name: + if supplier.quote_status != _('No Quote'): + quote_status = _('Received') + for item in self.items: + sqi_count = frappe.db.sql(""" + SELECT + COUNT(sqi.name) as count + FROM + `tabSupplier Quotation Item` as sqi, + `tabSupplier Quotation` as sq + WHERE sq.supplier = %(supplier)s + AND sqi.docstatus = 1 + AND sqi.request_for_quotation_item = %(rqi)s + AND sqi.parent = sq.name""", {"supplier": supplier.supplier, "rqi": item.name}, as_dict=1)[0] + if (sqi_count.count) == 0: + quote_status = _('Pending') + supplier.quote_status = quote_status + + @frappe.whitelist() def send_supplier_emails(rfq_name): check_portal_enabled('Request for Quotation') diff --git a/erpnext/buying/doctype/request_for_quotation_supplier/request_for_quotation_supplier.json b/erpnext/buying/doctype/request_for_quotation_supplier/request_for_quotation_supplier.json index a7c5a37683..4babbe92d5 100644 --- a/erpnext/buying/doctype/request_for_quotation_supplier/request_for_quotation_supplier.json +++ b/erpnext/buying/doctype/request_for_quotation_supplier/request_for_quotation_supplier.json @@ -137,6 +137,69 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 1, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:doc.docstatus >= 1 && doc.quote_status != 'Received'", + "fieldname": "no_quote", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "No Quote", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 1, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:doc.docstatus >= 1 && !doc.no_quote", + "fieldname": "quote_status", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Quote Status", + "length": 0, + "no_copy": 0, + "options": "Pending\nReceived\nNo Quote", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -269,7 +332,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-07-24 06:52:19.542717", + "modified": "2017-07-26 22:25:58.096584", "modified_by": "Administrator", "module": "Buying", "name": "Request for Quotation Supplier", diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py index 1cb5a18662..5e17dce610 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py @@ -31,9 +31,11 @@ class SupplierQuotation(BuyingController): def on_submit(self): frappe.db.set(self, "status", "Submitted") + self.update_rfq_supplier_status(1) def on_cancel(self): frappe.db.set(self, "status", "Cancelled") + self.update_rfq_supplier_status(0) def on_trash(self): pass @@ -50,6 +52,38 @@ class SupplierQuotation(BuyingController): "is_child_table": True } }) + def update_rfq_supplier_status(self, include_me): + rfq_list = set([]) + for item in self.items: + if item.request_for_quotation: + rfq_list.add(item.request_for_quotation) + for rfq in rfq_list: + doc = frappe.get_doc('Request for Quotation', rfq) + doc_sup = frappe.get_all('Request for Quotation Supplier', filters= + {'parent': doc.name, 'supplier': self.supplier}, fields=['name', 'quote_status'])[0] + + quote_status = _('Received') + for item in doc.items: + sqi_count = frappe.db.sql(""" + SELECT + COUNT(sqi.name) as count + FROM + `tabSupplier Quotation Item` as sqi, + `tabSupplier Quotation` as sq + WHERE sq.supplier = %(supplier)s + AND sqi.docstatus = 1 + AND sq.name != %(me)s + AND sqi.request_for_quotation_item = %(rqi)s + AND sqi.parent = sq.name""", {"supplier": self.supplier, "rqi": item.name, 'me': self.name}, as_dict=1)[0] + self_count = sum(my_item.request_for_quotation_item == item.name for my_item in self.items) if include_me else 0 + if (sqi_count.count + self_count) == 0: + quote_status = _('Pending') + if quote_status == _('Received') and doc_sup.quote_status == _('No Quote'): + frappe.msgprint(_("{0} indicates that {1} will not provide a quotation, but all items have been quoted. Updating the RFQ quote status.").format(doc.name, self.supplier)) + frappe.db.set_value('Request for Quotation Supplier', doc_sup.name, 'quote_status', quote_status) + frappe.db.set_value('Request for Quotation Supplier', doc_sup.name, 'no_quote', 0) + elif doc_sup.quote_status != _('No Quote'): + frappe.db.set_value('Request for Quotation Supplier', doc_sup.name, 'quote_status', quote_status) def get_list_context(context=None): from erpnext.controllers.website_list_for_contact import get_list_context diff --git a/erpnext/docs/user/manual/en/buying/request-for-quotation.md b/erpnext/docs/user/manual/en/buying/request-for-quotation.md index 182c89d4e6..a48c297a6f 100644 --- a/erpnext/docs/user/manual/en/buying/request-for-quotation.md +++ b/erpnext/docs/user/manual/en/buying/request-for-quotation.md @@ -2,43 +2,40 @@ A Request for Quotation is a document that an organization submits to one or more suppliers eliciting quotation for items. -In ERPNext, You can create request for quotation directly by going to: +In ERPNext, You can create Request for Quotation directly by going to: > Buying > Documents > Request for Quotation > New Request for Quotation -![Request For Quotation](/docs/assets/img/buying/request-for-quotation.png) +After creation of Request for Quotation, there are two ways to generate Supplier Quotation from Request for Quotation. -After creation of request for quotation, there are two ways to generate supplier quotation from request for quotation. #### For User -__Step 1:__ Open request for quotation and click on make supplier quotation. +__Step 1:__ Open Request for Quotation and click on make Supplier Quotation. ![Request For Quotation](/docs/assets/img/buying/make-supplier-quotation-from-rfq.png) -__Step 2:__ Select supplier and click on make supplier quotation. +__Step 2:__ Select supplier and click on make Supplier Quotation. ![Request For Quotation](/docs/assets/img/buying/supplier-selection-from-rfq.png) -__Step 3:__ System will open the supplier quotation, user has to enter the rate and submit it. +__Step 3:__ System will open the Supplier Quotation, user has to enter the rate and submit it. ![Request For Quotation](/docs/assets/img/buying/supplier-quotation-from-rfq.png) #### For Supplier -__Step 1:__ User has to create contact or enter Email Address against the supplier on request for quotation. +__Step 1:__ User has to create contact or enter Email Address against the supplier on Request for Quotation. ![Request For Quotation](/docs/assets/img/buying/set-email-id.png) __Step 2:__ User has to click on send supplier emails button. -![Request For Quotation](/docs/assets/img/buying/send-supplier-emails.png) - -* If supplier's user not available: system will create supplier's user and send details to the supplier, supplier will need to click on the link(Password Update) present in the email. After password update supplier can access his portal with the request for quotation form. +* If supplier's user not available: system will create supplier's user and send details to the supplier, supplier will need to click on the link(Password Update) present in the email. After password update supplier can access his portal with the Request for Quotation form. ![Request For Quotation](/docs/assets/img/buying/supplier-password-update-link.png) -* If supplier's user available: system will send request for quotation link to supplier, supplier has to login using his credentials to view request for quotation form on portal. +* If supplier's user available: system will send Request for Quotation link to supplier, supplier has to login using his credentials to view Request for Quotation form on portal. ![Request For Quotation](/docs/assets/img/buying/send-rfq-link.png) @@ -46,9 +43,12 @@ __Step 3:__ Supplier has to enter amount and notes(payment terms) on the form an ![Request For Quotation](/docs/assets/img/buying/supplier-portal-rfq.png) -__Step 4:__ On submission, system will create supplier quotation(draft mode) against the supplier. User has to review the supplier quotation - and submit it. - -More details:- +__Step 4:__ On submission, system will create Supplier Quotation (draft mode) against the supplier. The user has to review the Supplier Quotation + and submit it. When all items from the Request for Quotation have been quoted by a supplier, the status is updated in the Supplier + table of the Request for Quotation. -![Request For Quotation](/docs/assets/img/buying/request-for-quotation.gif) \ No newline at end of file +#### More details + +If a supplier indicates that they will not provide a quotation for the item, this can be indicated in the RFQ document by checking the 'No Quote' box after the Request for Quotation has been submitted. + +![Request For Quotation](/docs/assets/img/buying/request-for-quotation.gif) From 48058a88e5a0416ae58b7bfd3e6a1da8197247a1 Mon Sep 17 00:00:00 2001 From: Ben Cornwell-Mott Date: Wed, 26 Jul 2017 23:14:15 -0700 Subject: [PATCH 24/52] Minor cleanup --- .../request_for_quotation/request_for_quotation.js | 1 - .../request_for_quotation/request_for_quotation.py | 3 ++- .../doctype/supplier_quotation/supplier_quotation.py | 9 ++++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js index 6b37edafc7..8509d77e20 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js @@ -229,7 +229,6 @@ frappe.ui.form.on("Request for Quotation Supplier",{ } }); } - } }) diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py index a8e897c2dd..4a88191edc 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py @@ -173,7 +173,8 @@ class RequestforQuotation(BuyingController): WHERE sq.supplier = %(supplier)s AND sqi.docstatus = 1 AND sqi.request_for_quotation_item = %(rqi)s - AND sqi.parent = sq.name""", {"supplier": supplier.supplier, "rqi": item.name}, as_dict=1)[0] + AND sqi.parent = sq.name""", + {"supplier": supplier.supplier, "rqi": item.name}, as_dict=1)[0] if (sqi_count.count) == 0: quote_status = _('Pending') supplier.quote_status = quote_status diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py index 5e17dce610..4de2c00596 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py @@ -74,12 +74,15 @@ class SupplierQuotation(BuyingController): AND sqi.docstatus = 1 AND sq.name != %(me)s AND sqi.request_for_quotation_item = %(rqi)s - AND sqi.parent = sq.name""", {"supplier": self.supplier, "rqi": item.name, 'me': self.name}, as_dict=1)[0] - self_count = sum(my_item.request_for_quotation_item == item.name for my_item in self.items) if include_me else 0 + AND sqi.parent = sq.name""", + {"supplier": self.supplier, "rqi": item.name, 'me': self.name}, as_dict=1)[0] + self_count = sum(my_item.request_for_quotation_item == item.name + for my_item in self.items) if include_me else 0 if (sqi_count.count + self_count) == 0: quote_status = _('Pending') if quote_status == _('Received') and doc_sup.quote_status == _('No Quote'): - frappe.msgprint(_("{0} indicates that {1} will not provide a quotation, but all items have been quoted. Updating the RFQ quote status.").format(doc.name, self.supplier)) + frappe.msgprint(_("{0} indicates that {1} will not provide a quotation, but all items \ + have been quoted. Updating the RFQ quote status.").format(doc.name, self.supplier)) frappe.db.set_value('Request for Quotation Supplier', doc_sup.name, 'quote_status', quote_status) frappe.db.set_value('Request for Quotation Supplier', doc_sup.name, 'no_quote', 0) elif doc_sup.quote_status != _('No Quote'): From 1b4351516099897d788903a8fd767496a5e98de3 Mon Sep 17 00:00:00 2001 From: Ben Cornwell-Mott Date: Thu, 27 Jul 2017 02:56:00 -0700 Subject: [PATCH 25/52] Codacy fixes --- .../doctype/request_for_quotation/request_for_quotation.py | 2 +- .../buying/doctype/supplier_quotation/supplier_quotation.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py index 4a88191edc..7a33034413 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py @@ -173,7 +173,7 @@ class RequestforQuotation(BuyingController): WHERE sq.supplier = %(supplier)s AND sqi.docstatus = 1 AND sqi.request_for_quotation_item = %(rqi)s - AND sqi.parent = sq.name""", + AND sqi.parent = sq.name""", {"supplier": supplier.supplier, "rqi": item.name}, as_dict=1)[0] if (sqi_count.count) == 0: quote_status = _('Pending') diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py index 4de2c00596..b3d92be4b6 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py @@ -74,9 +74,9 @@ class SupplierQuotation(BuyingController): AND sqi.docstatus = 1 AND sq.name != %(me)s AND sqi.request_for_quotation_item = %(rqi)s - AND sqi.parent = sq.name""", + AND sqi.parent = sq.name""", {"supplier": self.supplier, "rqi": item.name, 'me': self.name}, as_dict=1)[0] - self_count = sum(my_item.request_for_quotation_item == item.name + self_count = sum(my_item.request_for_quotation_item == item.name for my_item in self.items) if include_me else 0 if (sqi_count.count + self_count) == 0: quote_status = _('Pending') From bea7d9f91994dd5b51130ccad39457168d4f9341 Mon Sep 17 00:00:00 2001 From: Ben Cornwell-Mott Date: Wed, 2 Aug 2017 05:12:12 -0700 Subject: [PATCH 26/52] Added tests --- .../request_for_quotation.py | 2 +- .../test_request_for_quotation.py | 44 ++++-- .../{ => tests}/test_request_for_quotation.js | 0 .../test_request_for_quotation_for_status.js | 133 ++++++++++++++++++ 4 files changed, 166 insertions(+), 13 deletions(-) rename erpnext/buying/doctype/request_for_quotation/{ => tests}/test_request_for_quotation.js (100%) create mode 100644 erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation_for_status.js diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py index 7a33034413..2d8820d992 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py @@ -160,7 +160,7 @@ class RequestforQuotation(BuyingController): def update_rfq_supplier_status(self, sup_name=None): for supplier in self.suppliers: - if sup_name != None and supplier.supplier == sup_name: + if sup_name == None or supplier.supplier == sup_name: if supplier.quote_status != _('No Quote'): quote_status = _('Received') for item in self.items: diff --git a/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py index 2e8b946f9d..5c9fb13209 100644 --- a/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py +++ b/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py @@ -10,21 +10,41 @@ from erpnext.templates.pages.rfq import check_supplier_has_docname_access from frappe.utils import nowdate class TestRequestforQuotation(unittest.TestCase): + def test_quote_status(self): + from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation + rfq = make_request_for_quotation() + + self.assertEquals(rfq.get('suppliers')[0].quote_status, 'Pending') + self.assertEquals(rfq.get('suppliers')[1].quote_status, 'Pending') + + # Submit the first supplier quotation + sq = make_supplier_quotation(rfq.name, rfq.get('suppliers')[0].supplier) + sq.submit() + + # No Quote first supplier quotation + rfq.get('suppliers')[1].no_quote = 1 + rfq.get('suppliers')[1].quote_status = 'No Quote' + + rfq.update_rfq_supplier_status() #rfq.get('suppliers')[1].supplier) + + self.assertEquals(rfq.get('suppliers')[0].quote_status, 'Received') + self.assertEquals(rfq.get('suppliers')[1].quote_status, 'No Quote') + def test_make_supplier_quotation(self): from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation rfq = make_request_for_quotation() - + sq = make_supplier_quotation(rfq.name, rfq.get('suppliers')[0].supplier) sq.submit() - + sq1 = make_supplier_quotation(rfq.name, rfq.get('suppliers')[1].supplier) sq1.submit() - + self.assertEquals(sq.supplier, rfq.get('suppliers')[0].supplier) self.assertEquals(sq.get('items')[0].request_for_quotation, rfq.name) self.assertEquals(sq.get('items')[0].item_code, "_Test Item") self.assertEquals(sq.get('items')[0].qty, 5) - + self.assertEquals(sq1.supplier, rfq.get('suppliers')[1].supplier) self.assertEquals(sq1.get('items')[0].request_for_quotation, rfq.name) self.assertEquals(sq1.get('items')[0].item_code, "_Test Item") @@ -61,15 +81,15 @@ class TestRequestforQuotation(unittest.TestCase): rfq.get('items')[0].rate = 100 rfq.supplier = rfq.suppliers[0].supplier supplier_quotation_name = create_supplier_quotation(rfq) - + supplier_quotation_doc = frappe.get_doc('Supplier Quotation', supplier_quotation_name) - + self.assertEquals(supplier_quotation_doc.supplier, rfq.get('suppliers')[0].supplier) self.assertEquals(supplier_quotation_doc.get('items')[0].request_for_quotation, rfq.name) self.assertEquals(supplier_quotation_doc.get('items')[0].item_code, "_Test Item") self.assertEquals(supplier_quotation_doc.get('items')[0].qty, 5) self.assertEquals(supplier_quotation_doc.get('items')[0].amount, 500) - + def make_request_for_quotation(supplier_data=None): """ @@ -81,10 +101,10 @@ def make_request_for_quotation(supplier_data=None): rfq.status = 'Draft' rfq.company = '_Test Company' rfq.message_for_supplier = 'Please supply the specified items at the best possible rates.' - + for data in supplier_data: rfq.append('suppliers', data) - + rfq.append("items", { "item_code": "_Test Item", "description": "_Test Item", @@ -93,11 +113,11 @@ def make_request_for_quotation(supplier_data=None): "warehouse": "_Test Warehouse - _TC", "schedule_date": nowdate() }) - + rfq.submit() - + return rfq - + def get_supplier_data(): return [{ "supplier": "_Test Supplier", diff --git a/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js similarity index 100% rename from erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.js rename to erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js diff --git a/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation_for_status.js b/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation_for_status.js new file mode 100644 index 0000000000..e971ef9030 --- /dev/null +++ b/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation_for_status.js @@ -0,0 +1,133 @@ +QUnit.module('buying'); + +QUnit.test("Test: Request for Quotation", function (assert) { + assert.expect(5); + let done = assert.async(); + let rfq_name = ""; + + frappe.run_serially([ + // Go to RFQ list + () => frappe.set_route("List", "Request for Quotation"), + // Create a new RFQ + () => frappe.new_doc("Request for Quotation"), + () => frappe.timeout(1), + () => cur_frm.set_value("transaction_date", "04-04-2017"), + () => cur_frm.set_value("company", "_Test Company"), + // Add Suppliers + () => { + cur_frm.fields_dict.suppliers.grid.grid_rows[0].toggle_view(); + }, + () => frappe.timeout(1), + () => { + cur_frm.fields_dict.suppliers.grid.grid_rows[0].doc.supplier = "_Test Supplier"; + frappe.click_check('Send Email'); + cur_frm.cur_grid.frm.script_manager.trigger('supplier'); + }, + () => frappe.timeout(1), + () => { + cur_frm.cur_grid.toggle_view(); + }, + () => frappe.timeout(1), + () => frappe.click_button('Add Row',0), + () => frappe.timeout(1), + () => { + cur_frm.fields_dict.suppliers.grid.grid_rows[1].toggle_view(); + }, + () => frappe.timeout(1), + () => { + cur_frm.fields_dict.suppliers.grid.grid_rows[1].doc.supplier = "_Test Supplier 1"; + frappe.click_check('Send Email'); + cur_frm.cur_grid.frm.script_manager.trigger('supplier'); + }, + () => frappe.timeout(1), + () => { + cur_frm.cur_grid.toggle_view(); + }, + () => frappe.timeout(1), + //Add Item + () => { + cur_frm.fields_dict.items.grid.grid_rows[0].toggle_view(); + }, + () => frappe.timeout(1), + () => { + cur_frm.fields_dict.items.grid.grid_rows[0].doc.item_code = "_Test Item"; + frappe.set_control('item_code',"_Test Item"); + frappe.set_control('qty',5); + frappe.set_control('schedule_date', "05-05-2017"); + cur_frm.cur_grid.frm.script_manager.trigger('supplier'); + }, + () => frappe.timeout(2), + () => { + cur_frm.cur_grid.toggle_view(); + }, + () => frappe.timeout(2), + () => { + cur_frm.fields_dict.items.grid.grid_rows[0].doc.warehouse = "_Test Warehouse - _TC"; + }, + () => frappe.click_button('Save'), + () => frappe.timeout(1), + () => frappe.click_button('Submit'), + () => frappe.timeout(1), + () => frappe.click_button('Yes'), + () => frappe.timeout(1), + () => frappe.click_button('Menu'), + () => frappe.timeout(1), + () => frappe.click_link('Reload'), + () => frappe.timeout(1), + () => { + assert.equal(cur_frm.doc.docstatus, 1); + rfq_name = cur_frm.doc.name; + assert.ok(cur_frm.fields_dict.suppliers.grid.grid_rows[0].doc.quote_status == "Pending"); + assert.ok(cur_frm.fields_dict.suppliers.grid.grid_rows[1].doc.quote_status == "Pending"); + }, + () => { + cur_frm.fields_dict.suppliers.grid.grid_rows[0].toggle_view(); + }, + () => frappe.timeout(1), + () => { + frappe.click_check('No Quote'); + }, + () => frappe.timeout(1), + () => { + cur_frm.cur_grid.toggle_view(); + }, + () => frappe.click_button('Update'), + () => frappe.timeout(1), + + () => frappe.click_button('Supplier Quotation'), + () => frappe.timeout(1), + () => frappe.click_link('Make'), + () => frappe.timeout(1), + () => { + frappe.set_control('supplier',"_Test Supplier 1"); + }, + () => frappe.timeout(1), + () => frappe.click_button('Make Supplier Quotation'), + () => frappe.timeout(1), + () => cur_frm.set_value("company", "_Test Company"), + () => cur_frm.fields_dict.items.grid.grid_rows[0].doc.rate = 4.99, + () => frappe.timeout(1), + () => frappe.click_button('Save'), + () => frappe.timeout(1), + () => frappe.click_button('Submit'), + () => frappe.timeout(1), + () => frappe.click_button('Yes'), + () => frappe.timeout(1), + () => frappe.set_route("List", "Request for Quotation"), + () => frappe.timeout(2), + () => frappe.set_route("List", "Request for Quotation"), + () => frappe.timeout(2), + () => frappe.click_link(rfq_name), + () => frappe.timeout(1), + () => frappe.click_button('Menu'), + () => frappe.timeout(1), + () => frappe.click_link('Reload'), + () => frappe.timeout(1), + () => { + assert.ok(cur_frm.fields_dict.suppliers.grid.grid_rows[1].doc.quote_status == "Received"); + assert.ok(cur_frm.fields_dict.suppliers.grid.grid_rows[0].doc.no_quote == 1); + console.log(cur_frm.fields_dict.suppliers.grid.grid_rows[1].doc); + }, + () => done() + ]); +}); \ No newline at end of file From 13218f7d76484af9a8c348a885ec6a6c997f33f1 Mon Sep 17 00:00:00 2001 From: Ben Cornwell-Mott Date: Wed, 2 Aug 2017 05:25:45 -0700 Subject: [PATCH 27/52] Fixed codacy issues --- .../test_request_for_quotation_for_status.js | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation_for_status.js b/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation_for_status.js index e971ef9030..f0d797a4f5 100644 --- a/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation_for_status.js +++ b/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation_for_status.js @@ -14,15 +14,15 @@ QUnit.test("Test: Request for Quotation", function (assert) { () => cur_frm.set_value("transaction_date", "04-04-2017"), () => cur_frm.set_value("company", "_Test Company"), // Add Suppliers - () => { + () => { cur_frm.fields_dict.suppliers.grid.grid_rows[0].toggle_view(); }, () => frappe.timeout(1), () => { - cur_frm.fields_dict.suppliers.grid.grid_rows[0].doc.supplier = "_Test Supplier"; - frappe.click_check('Send Email'); - cur_frm.cur_grid.frm.script_manager.trigger('supplier'); - }, + cur_frm.fields_dict.suppliers.grid.grid_rows[0].doc.supplier = "_Test Supplier"; + frappe.click_check('Send Email'); + cur_frm.cur_grid.frm.script_manager.trigger('supplier'); + }, () => frappe.timeout(1), () => { cur_frm.cur_grid.toggle_view(); @@ -35,7 +35,7 @@ QUnit.test("Test: Request for Quotation", function (assert) { }, () => frappe.timeout(1), () => { - cur_frm.fields_dict.suppliers.grid.grid_rows[1].doc.supplier = "_Test Supplier 1"; + cur_frm.fields_dict.suppliers.grid.grid_rows[1].doc.supplier = "_Test Supplier 1"; frappe.click_check('Send Email'); cur_frm.cur_grid.frm.script_manager.trigger('supplier'); }, @@ -44,18 +44,18 @@ QUnit.test("Test: Request for Quotation", function (assert) { cur_frm.cur_grid.toggle_view(); }, () => frappe.timeout(1), - //Add Item + // Add Item () => { cur_frm.fields_dict.items.grid.grid_rows[0].toggle_view(); }, () => frappe.timeout(1), - () => { + () => { cur_frm.fields_dict.items.grid.grid_rows[0].doc.item_code = "_Test Item"; - frappe.set_control('item_code',"_Test Item"); - frappe.set_control('qty',5); - frappe.set_control('schedule_date', "05-05-2017"); + frappe.set_control('item_code',"_Test Item"); + frappe.set_control('qty',5); + frappe.set_control('schedule_date', "05-05-2017"); cur_frm.cur_grid.frm.script_manager.trigger('supplier'); - }, + }, () => frappe.timeout(2), () => { cur_frm.cur_grid.toggle_view(); @@ -85,7 +85,7 @@ QUnit.test("Test: Request for Quotation", function (assert) { }, () => frappe.timeout(1), () => { - frappe.click_check('No Quote'); + frappe.click_check('No Quote'); }, () => frappe.timeout(1), () => { @@ -94,7 +94,7 @@ QUnit.test("Test: Request for Quotation", function (assert) { () => frappe.click_button('Update'), () => frappe.timeout(1), - () => frappe.click_button('Supplier Quotation'), + () => frappe.click_button('Supplier Quotation'), () => frappe.timeout(1), () => frappe.click_link('Make'), () => frappe.timeout(1), @@ -126,7 +126,6 @@ QUnit.test("Test: Request for Quotation", function (assert) { () => { assert.ok(cur_frm.fields_dict.suppliers.grid.grid_rows[1].doc.quote_status == "Received"); assert.ok(cur_frm.fields_dict.suppliers.grid.grid_rows[0].doc.no_quote == 1); - console.log(cur_frm.fields_dict.suppliers.grid.grid_rows[1].doc); }, () => done() ]); From df83191ea02e80e50e04b3fe4ef1d0e47771acf9 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 2 Aug 2017 18:23:39 +0530 Subject: [PATCH 28/52] Set write permission to sales manger for permlevel 1 in Quotation doctype --- erpnext/patches.txt | 5 ++++- .../set_write_permission_for_quotation_for_sales_manager.py | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 60caf0fec1..56af066c54 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -431,4 +431,7 @@ erpnext.patches.v8_5.set_default_mode_of_payment erpnext.patches.v8_5.update_customer_group_in_POS_profile erpnext.patches.v8_6.update_timesheet_company_from_PO erpnext.patches.v8_6.set_write_permission_for_quotation_for_sales_manager -erpnext.patches.v8_5.remove_project_type_property_setter \ No newline at end of file +<<<<<<< HEAD +erpnext.patches.v8_5.remove_project_type_property_setter +======= +>>>>>>> Set write permission to sales manger for permlevel 1 in Quotation doctype diff --git a/erpnext/patches/v8_6/set_write_permission_for_quotation_for_sales_manager.py b/erpnext/patches/v8_6/set_write_permission_for_quotation_for_sales_manager.py index c2320ec04c..db4f94748e 100644 --- a/erpnext/patches/v8_6/set_write_permission_for_quotation_for_sales_manager.py +++ b/erpnext/patches/v8_6/set_write_permission_for_quotation_for_sales_manager.py @@ -8,4 +8,4 @@ def execute(): # Set write permission to permlevel 1 for sales manager role in Quotation doctype frappe.db.sql(""" update `tabCustom DocPerm` set `tabCustom DocPerm`.write = 1 where `tabCustom DocPerm`.parent = 'Quotation' and `tabCustom DocPerm`.role = 'Sales Manager' - and `tabCustom DocPerm`.permlevel = 1 """) + and `tabCustom DocPerm`.permlevel = 1 """) \ No newline at end of file From 9727a3fe5077aba36b3d7b249f06f6f24f68a623 Mon Sep 17 00:00:00 2001 From: Ben Cornwell-Mott Date: Wed, 2 Aug 2017 06:08:32 -0700 Subject: [PATCH 29/52] More codacy issues --- .../tests/test_request_for_quotation_for_status.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation_for_status.js b/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation_for_status.js index f0d797a4f5..c315f6b6ef 100644 --- a/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation_for_status.js +++ b/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation_for_status.js @@ -18,7 +18,7 @@ QUnit.test("Test: Request for Quotation", function (assert) { cur_frm.fields_dict.suppliers.grid.grid_rows[0].toggle_view(); }, () => frappe.timeout(1), - () => { + () => { cur_frm.fields_dict.suppliers.grid.grid_rows[0].doc.supplier = "_Test Supplier"; frappe.click_check('Send Email'); cur_frm.cur_grid.frm.script_manager.trigger('supplier'); @@ -36,9 +36,9 @@ QUnit.test("Test: Request for Quotation", function (assert) { () => frappe.timeout(1), () => { cur_frm.fields_dict.suppliers.grid.grid_rows[1].doc.supplier = "_Test Supplier 1"; - frappe.click_check('Send Email'); - cur_frm.cur_grid.frm.script_manager.trigger('supplier'); - }, + frappe.click_check('Send Email'); + cur_frm.cur_grid.frm.script_manager.trigger('supplier'); + }, () => frappe.timeout(1), () => { cur_frm.cur_grid.toggle_view(); @@ -94,7 +94,7 @@ QUnit.test("Test: Request for Quotation", function (assert) { () => frappe.click_button('Update'), () => frappe.timeout(1), - () => frappe.click_button('Supplier Quotation'), + () => frappe.click_button('Supplier Quotation'), () => frappe.timeout(1), () => frappe.click_link('Make'), () => frappe.timeout(1), From ee9f9863ff6695d2dd9e493932c9ffa10e47b35f Mon Sep 17 00:00:00 2001 From: Ben Cornwell-Mott Date: Wed, 2 Aug 2017 06:28:01 -0700 Subject: [PATCH 30/52] MORE CODACY --- .../tests/test_request_for_quotation_for_status.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation_for_status.js b/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation_for_status.js index c315f6b6ef..f831b4f42f 100644 --- a/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation_for_status.js +++ b/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation_for_status.js @@ -34,7 +34,7 @@ QUnit.test("Test: Request for Quotation", function (assert) { cur_frm.fields_dict.suppliers.grid.grid_rows[1].toggle_view(); }, () => frappe.timeout(1), - () => { + () => { cur_frm.fields_dict.suppliers.grid.grid_rows[1].doc.supplier = "_Test Supplier 1"; frappe.click_check('Send Email'); cur_frm.cur_grid.frm.script_manager.trigger('supplier'); @@ -84,9 +84,9 @@ QUnit.test("Test: Request for Quotation", function (assert) { cur_frm.fields_dict.suppliers.grid.grid_rows[0].toggle_view(); }, () => frappe.timeout(1), - () => { + () => { frappe.click_check('No Quote'); - }, + }, () => frappe.timeout(1), () => { cur_frm.cur_grid.toggle_view(); From 5b266eff8947131ada6344e80b8c96fe9294c7f7 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 17 Aug 2017 14:42:50 +0530 Subject: [PATCH 31/52] Update patches.txt --- erpnext/patches.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 56af066c54..abbb04a6c4 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -431,7 +431,4 @@ erpnext.patches.v8_5.set_default_mode_of_payment erpnext.patches.v8_5.update_customer_group_in_POS_profile erpnext.patches.v8_6.update_timesheet_company_from_PO erpnext.patches.v8_6.set_write_permission_for_quotation_for_sales_manager -<<<<<<< HEAD erpnext.patches.v8_5.remove_project_type_property_setter -======= ->>>>>>> Set write permission to sales manger for permlevel 1 in Quotation doctype From 780f11ec160872b07c229cc470c03de5a57ee85b Mon Sep 17 00:00:00 2001 From: Zarrar Date: Thu, 17 Aug 2017 18:36:33 +0530 Subject: [PATCH 32/52] path to test updated (#10438) --- erpnext/tests/ui/tests.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index 2e71285097..dc9d5347da 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -83,7 +83,7 @@ erpnext/schools/doctype/assessment_plan/test_assessment_plan.js erpnext/schools/doctype/assessment_result/test_assessment_result.js erpnext/schools/doctype/assessment_result_tool/test_assessment_result_tool.js erpnext/buying/doctype/supplier/test_supplier.js -erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.js +erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_taxes_and_charges.js erpnext/accounts/doctype/sales_invoice/test_sales_invoice.js From 2890fa74a2361fc14d9bd6e106820f705eeca2d5 Mon Sep 17 00:00:00 2001 From: Vishal Dhayagude Date: Fri, 18 Aug 2017 11:55:14 +0530 Subject: [PATCH 33/52] [UI Test] UI Test for Purchase Receipt Added (#10434) --- .../purchase_receipt/test_purchase_receipt.js | 51 +++++++++++++------ erpnext/tests/ui/tests.txt | 3 +- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.js index 2bc73358b8..0b3fcc9898 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.js +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.js @@ -1,23 +1,42 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line +QUnit.module('Stock'); -QUnit.test("test: Purchase Receipt", function (assert) { +QUnit.test("test Purchase Receipt", function(assert) { + assert.expect(4); let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially('Purchase Receipt', [ - // insert a new Purchase Receipt - () => frappe.tests.make([ - // values to be set - {key: 'value'} - ]), + frappe.run_serially([ () => { - assert.equal(cur_frm.doc.key, 'value'); + return frappe.tests.make('Purchase Receipt', [ + {supplier: 'Test Supplier'}, + {items: [ + [ + {'received_qty': 5}, + {'qty': 4}, + {'item_code': 'Test Product 1'}, + {'uom': 'Nos'}, + {'warehouse':'Stores - '+frappe.get_abbr(frappe.defaults.get_default('Company'))}, + {'rejected_warehouse':'Work In Progress - '+frappe.get_abbr(frappe.defaults.get_default('Company'))}, + ] + ]}, + {taxes_and_charges: 'TEST In State GST'}, + {tc_name: 'Test Term 1'}, + {terms: 'This is Test'} + ]); }, + () => cur_frm.save(), + () => { + // get_item_details + assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct"); + // get tax details + assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST', "Tax details correct"); + // get tax account head details + assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct"); + // grand_total Calculated + assert.ok(cur_frm.doc.grand_total==472, "Grad Total correct"); + + }, + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), () => done() ]); - }); diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index dc9d5347da..dffbbafe2b 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -95,4 +95,5 @@ erpnext/buying/doctype/purchase_order/tests/test_purchase_order_get_items.js erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_discount_on_grand_total.js erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_item_wise_discount.js erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js -erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js \ No newline at end of file +erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js +erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.js From ca63cc6439c3615fe8871ad5d0a21874747eb7e5 Mon Sep 17 00:00:00 2001 From: Utkarsh Goswami Date: Fri, 18 Aug 2017 11:57:01 +0530 Subject: [PATCH 34/52] [UI Test Recruitment] To test Recruitment in HR module (#10441) * Tests for Recruitment * Codacy fix --- .../job_applicant/test_job_applicant.js | 29 +++++++++++ .../doctype/job_opening/test_job_opening.js | 27 ++++++++++ .../doctype/offer_letter/test_offer_letter.js | 51 +++++++++++++++++++ erpnext/tests/ui/tests.txt | 3 ++ 4 files changed, 110 insertions(+) create mode 100644 erpnext/hr/doctype/job_applicant/test_job_applicant.js create mode 100644 erpnext/hr/doctype/job_opening/test_job_opening.js create mode 100644 erpnext/hr/doctype/offer_letter/test_offer_letter.js diff --git a/erpnext/hr/doctype/job_applicant/test_job_applicant.js b/erpnext/hr/doctype/job_applicant/test_job_applicant.js new file mode 100644 index 0000000000..b5391c8bf3 --- /dev/null +++ b/erpnext/hr/doctype/job_applicant/test_job_applicant.js @@ -0,0 +1,29 @@ +QUnit.module('hr'); + +QUnit.test("Test: Job Opening [HR]", function (assert) { + assert.expect(2); + let done = assert.async(); + + frappe.run_serially([ + // Job Applicant creation + () => { + frappe.tests.make('Job Applicant', [ + { applicant_name: 'Utkarsh Goswami'}, + { email_id: 'goswamiutkarsh0@gmail.com'}, + { job_title: 'software-developer'}, + { cover_letter: 'Highly skilled in designing, testing, and developing software.'+ + ' This is just a test.'} + ]); + }, + () => frappe.timeout(4), + () => frappe.set_route('List','Job Applicant'), + () => frappe.timeout(3), + () => { + assert.ok(cur_list.data.length==1, 'Job Applicant created successfully'); + assert.ok(cur_list.data[0].name=='Utkarsh Goswami - goswamiutkarsh0@gmail.com - software-developer', + 'Correct job applicant with valid job title'); + }, + () => done() + ]); +}); + diff --git a/erpnext/hr/doctype/job_opening/test_job_opening.js b/erpnext/hr/doctype/job_opening/test_job_opening.js new file mode 100644 index 0000000000..b9e6c0a8b2 --- /dev/null +++ b/erpnext/hr/doctype/job_opening/test_job_opening.js @@ -0,0 +1,27 @@ +QUnit.module('hr'); + +QUnit.test("Test: Job Opening [HR]", function (assert) { + assert.expect(2); + let done = assert.async(); + + frappe.run_serially([ + // Job Opening creation + () => { + frappe.tests.make('Job Opening', [ + { job_title: 'Software Developer'}, + { description: + 'You might be responsible for writing and coding individual'+ + ' programmes or providing an entirely new software resource.'} + ]); + }, + () => frappe.timeout(4), + () => frappe.set_route('List','Job Opening'), + () => frappe.timeout(3), + () => { + assert.ok(cur_list.data.length==1, 'Job Opening created successfully'); + assert.ok(cur_list.data[0].job_title=='Software Developer', 'Job title Correctly set'); + }, + () => done() + ]); +}); + diff --git a/erpnext/hr/doctype/offer_letter/test_offer_letter.js b/erpnext/hr/doctype/offer_letter/test_offer_letter.js new file mode 100644 index 0000000000..2069532612 --- /dev/null +++ b/erpnext/hr/doctype/offer_letter/test_offer_letter.js @@ -0,0 +1,51 @@ +QUnit.module('hr'); + +QUnit.test("Test: Offer Letter [HR]", function (assert) { + assert.expect(3); + let done = assert.async(); + frappe.run_serially([ + // Offer Letter Creation + () => { + frappe.tests.make('Offer Letter', [ + { job_applicant: 'Utkarsh Goswami - goswamiutkarsh0@gmail.com - software-developer'}, + { applicant_name: 'Utkarsh Goswami'}, + { status: 'Accepted'}, + { designation: 'Software Developer'}, + { offer_terms: [ + [ + {offer_term: 'Responsibilities'}, + {value: 'Design, installation, testing and maintenance of software systems.'} + ], + [ + {offer_term: 'Department'}, + {value: 'Research & Development'} + ], + [ + {offer_term: 'Probationary Period'}, + {value: 'The Probation period is for 3 months.'} + ] + ]}, + ]); + }, + () => frappe.timeout(8), + () => frappe.click_button('Submit'), + () => frappe.timeout(2), + () => frappe.click_button('Yes'), + () => frappe.timeout(8), + () => { + // To check if the fields are correctly set + assert.ok(cur_frm.get_field('status').value=='Accepted', + 'Status of job offer is correct'); + assert.ok(cur_frm.get_field('designation').value=='Software Developer', + 'Designation of applicant is correct'); + }, + () => frappe.set_route('List','Offer Letter','List'), + () => frappe.timeout(2), + // Checking the submission of and offer letter + () => { + assert.ok(cur_list.data[0].docstatus==1,'Offer Letter Submitted successfully'); + }, + () => frappe.timeout(4), + () => done() + ]); +}); \ No newline at end of file diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index dffbbafe2b..d34bb4e6cc 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -67,6 +67,9 @@ erpnext/schools/doctype/course/test_course.js erpnext/schools/doctype/program/test_program.js erpnext/hr/doctype/salary_structure/test_salary_structure.js erpnext/hr/doctype/salary_slip/test_salary_slip.js +erpnext/hr/doctype/job_opening/test_job_opening.js +erpnext/hr/doctype/job_applicant/test_job_applicant.js +erpnext/hr/doctype/offer_letter/test_offer_letter.js erpnext/schools/doctype/guardian/test_guardian.js erpnext/schools/doctype/student_admission/test_student_admission.js erpnext/schools/doctype/student_applicant/tests/test_student_applicant_dummy_data.js From 5a27aead06fb768bdaa79e0ad880e20e52a34268 Mon Sep 17 00:00:00 2001 From: Utkarsh Goswami Date: Fri, 18 Aug 2017 13:12:53 +0530 Subject: [PATCH 35/52] Test for Process Payroll (#10447) --- .../process_payroll/test_process_payroll.js | 59 +++++++++++++++++++ erpnext/tests/ui/tests.txt | 1 + 2 files changed, 60 insertions(+) create mode 100644 erpnext/hr/doctype/process_payroll/test_process_payroll.js diff --git a/erpnext/hr/doctype/process_payroll/test_process_payroll.js b/erpnext/hr/doctype/process_payroll/test_process_payroll.js new file mode 100644 index 0000000000..7e23fb9c98 --- /dev/null +++ b/erpnext/hr/doctype/process_payroll/test_process_payroll.js @@ -0,0 +1,59 @@ +QUnit.module('hr'); + +QUnit.test("Test: Process Payroll [HR]", function (assert) { + assert.expect(5); + let done = assert.async(); + let net_pay; + + let check_amounts = (employee_name,net_amt,gross_amt) => { + frappe.run_serially([ + // Retrieving the actual amount from salary slip + () => frappe.db.get_value('Salary Slip', {'employee_name': employee_name}, 'net_pay'), + (r) => { + net_pay=r.message.net_pay; + }, + () => frappe.db.get_value('Salary Slip', {'employee_name': employee_name}, 'gross_pay'), + + // Checking if amounts are correctly calculated + (r) => { + assert.ok(net_pay==net_amt, + 'Net Pay is correctly calculated for '+employee_name); + assert.ok(r.message.gross_pay==gross_amt, + 'Gross Pay is correctly calculated for '+employee_name); + }, + ]); + }; + frappe.run_serially([ + + // Deleting the already generated Salary Slips for employees + () => frappe.set_route('List','Salary Slip'), + () => frappe.timeout(2), + () => { $('input.list-row-checkbox').click();}, + () => frappe.click_button('Delete'), + () => frappe.click_button('Yes'), + () => frappe.timeout(2), + () => assert.ok(cur_list.data.length==0,"Salary Slips successfully deleted"), + () => frappe.timeout(3), + + + // Creating Process Payroll for specific company + () => frappe.set_route('Form','Process Payroll'), + () => { + cur_frm.set_value('company','Test Company'), + frappe.timeout(1), + cur_frm.set_value('payroll_frequency','Monthly'), + cur_frm.set_value('start_date','2017-08-01'), + frappe.timeout(1), + cur_frm.set_value('end_date','2017-08-31'), + cur_frm.set_value('cost_center','Main-TC'), + frappe.timeout(1), + frappe.click_button('Create Salary Slip'); + }, + () => frappe.timeout(3), + () => check_amounts('Test Employee 1','19200','24000'), + () => frappe.timeout(3), + () => check_amounts('Test Employee 3','23040','28800'), + () => frappe.timeout(4), + () => done() + ]); +}); diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index d34bb4e6cc..6bae3c5c39 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -67,6 +67,7 @@ erpnext/schools/doctype/course/test_course.js erpnext/schools/doctype/program/test_program.js erpnext/hr/doctype/salary_structure/test_salary_structure.js erpnext/hr/doctype/salary_slip/test_salary_slip.js +erpnext/hr/doctype/process_payroll/test_process_payroll.js erpnext/hr/doctype/job_opening/test_job_opening.js erpnext/hr/doctype/job_applicant/test_job_applicant.js erpnext/hr/doctype/offer_letter/test_offer_letter.js From 592e8c2e77ff5a8fb0edd0628cc9ba5e26b5a09d Mon Sep 17 00:00:00 2001 From: Vishal Dhayagude Date: Fri, 18 Aug 2017 15:01:20 +0530 Subject: [PATCH 36/52] [UI Test] UI Test added for Stock Reconciliation (#10432) * [UI Test] UI Test added for Stock Reconciliation * [fix] Codacy --- .../test_stock_reconciliation.js | 31 +++++++++++++++++++ erpnext/tests/ui/tests.txt | 1 + 2 files changed, 32 insertions(+) create mode 100644 erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.js diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.js b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.js new file mode 100644 index 0000000000..b0eae735ef --- /dev/null +++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.js @@ -0,0 +1,31 @@ +QUnit.module('Stock'); + +QUnit.test("test Stock Reconciliation", function(assert) { + assert.expect(1); + let done = assert.async(); + frappe.run_serially([ + () => frappe.set_route('List', 'Stock Reconciliation'), + () => frappe.click_button('New'), + () => cur_frm.set_value('company','Razer Blade'), + () => frappe.click_button('Items'), + () => {cur_dialog.set_value('warehouse','Stores - RB'); }, + () => frappe.timeout(0.5), + () => frappe.click_button('Update'), + () => { + cur_frm.doc.items[0].qty = 150; + cur_frm.refresh_fields('items');}, + () => frappe.timeout(0.5), + () => cur_frm.set_value('expense_account','Stock Adjustment - RB'), + () => cur_frm.set_value('cost_center','Main - RB'), + () => cur_frm.save(), + () => { + // get_item_details + assert.ok(cur_frm.doc.expense_account=='Stock Adjustment - RB', "expense_account correct"); + }, + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), + () => done() + ]); +}); + diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index 6bae3c5c39..7c5582b522 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -101,3 +101,4 @@ erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_item_wise_d erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.js +erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.js \ No newline at end of file From 8fd5b325e08a7c435891cef6421c7339873ec836 Mon Sep 17 00:00:00 2001 From: Vishal Dhayagude Date: Sun, 20 Aug 2017 10:59:48 +0530 Subject: [PATCH 37/52] [UI Test] travis.yml modified for fresh UI Test (#10446) * [UI Test] travis.yml modified for fresh UI Test * [fix] travis * Update test_production_order.js * Update test_production_order.js * Update test_purchase_order_receipt.js * Update tests.txt * Update test_purchase_order_receipt.js --- .travis.yml | 3 ++ erpnext/accounts/page/pos/test_pos.js | 15 +++---- .../tests/test_purchase_order.js | 6 +-- .../tests/test_purchase_order_get_items.js | 9 ++-- .../tests/test_purchase_order_receipt.js | 7 ++-- ...hase_order_with_discount_on_grand_total.js | 3 +- ..._purchase_order_with_item_wise_discount.js | 3 +- .../test_purchase_order_with_multi_uom.js | 3 +- ...t_purchase_order_with_taxes_and_charges.js | 3 +- .../tests/test_request_for_quotation.js | 7 ++-- .../buying/doctype/supplier/test_supplier.js | 7 ++-- .../tests/test_supplier_quotation.js | 8 ++-- .../salary_structure/test_salary_structure.js | 4 +- .../production_order/test_production_order.js | 6 +-- .../tests/test_student_applicant_options.js | 1 + erpnext/setup/setup_wizard/data/test_mfg.json | 2 +- erpnext/tests/ui/tests.txt | 42 +++++++++---------- 17 files changed, 61 insertions(+), 68 deletions(-) diff --git a/.travis.yml b/.travis.yml index f7d28be009..a70062fea3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,4 +55,7 @@ script: - set -e - bench run-tests - sleep 5 + - bench reinstall --yes + - bench execute erpnext.setup.setup_wizard.utils.complete + - bench execute erpnext.setup.utils.enable_all_roles_and_domains - bench run-ui-tests --app erpnext diff --git a/erpnext/accounts/page/pos/test_pos.js b/erpnext/accounts/page/pos/test_pos.js index 62c6e31eb5..bc5edc9f2a 100644 --- a/erpnext/accounts/page/pos/test_pos.js +++ b/erpnext/accounts/page/pos/test_pos.js @@ -6,11 +6,11 @@ QUnit.test("test:POS Profile", function(assert) { () => { return frappe.tests.make("POS Profile", [ {naming_series: "SINV"}, - {company: "_Test Company"}, + {company: "Test Company"}, {country: "India"}, {currency: "INR"}, - {write_off_account: "Write Off - _TC"}, - {write_off_cost_center: "Main - _TC"}, + {write_off_account: "Write Off - TC"}, + {write_off_cost_center: "Main - TC"}, {payments: [ [ {"default": 1}, @@ -35,15 +35,16 @@ QUnit.test("test:Sales Invoice", function(assert) { frappe.run_serially([ () => { return frappe.tests.make("Sales Invoice", [ - {customer: "_Test Customer 2"}, - {company: "_Test Company"}, + {customer: "Test Customer 2"}, + {company: "Test Company"}, {is_pos: 1}, {posting_date: frappe.datetime.get_today()}, {due_date: frappe.datetime.get_today()}, {items: [ [ - {"item_code": "_Test Item"}, - {"qty": 5} + {"item_code": "Test Product 1"}, + {"qty": 5}, + {"warehouse":'Stores - TC'} ]] } ]); diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js index 940f36f1fd..e6529e60db 100644 --- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js @@ -8,10 +8,8 @@ QUnit.test("test: purchase order", function(assert) { () => { return frappe.tests.make('Purchase Order', [ {supplier: 'Test Supplier'}, - {company: 'Wind Power LLC'}, {is_subcontracted: 'No'}, - {buying_price_list: 'Test-Buying-USD'}, - {currency: 'USD'}, + {currency: 'INR'}, {items: [ [ {"item_code": 'Test Product 4'}, @@ -20,7 +18,7 @@ QUnit.test("test: purchase order", function(assert) { {"qty": 5}, {"uom": 'Unit'}, {"rate": 100}, - {"warehouse": 'Stores - WP'} + {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))} ] ]}, diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_get_items.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_get_items.js index 09fc33d4d8..8c0c144314 100644 --- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_get_items.js +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_get_items.js @@ -8,7 +8,6 @@ QUnit.test("test: purchase order with get items", function(assert) { () => { return frappe.tests.make('Purchase Order', [ {supplier: 'Test Supplier'}, - {company: 'Wind Power LLC'}, {is_subcontracted: 'No'}, {buying_price_list: 'Test-Buying-USD'}, {currency: 'USD'}, @@ -18,7 +17,7 @@ QUnit.test("test: purchase order with get items", function(assert) { {"qty": 5}, {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)}, {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)}, - {"warehouse": 'Stores - WP'} + {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))} ] ]} ]); @@ -46,9 +45,9 @@ QUnit.test("test: purchase order with get items", function(assert) { assert.ok(cur_frm.doc.items[3].item_name == 'Keyboard', "Product bundle item 3 correct"); }, - () => cur_frm.doc.items[1].warehouse = 'Stores - WP', - () => cur_frm.doc.items[2].warehouse = 'Stores - WP', - () => cur_frm.doc.items[3].warehouse = 'Stores - WP', + () => cur_frm.doc.items[1].warehouse = 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company")), + () => cur_frm.doc.items[2].warehouse = 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company")), + () => cur_frm.doc.items[3].warehouse = 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company")), () => cur_frm.save(), () => frappe.timeout(1), diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js index 654586ae57..f28ece673a 100644 --- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js @@ -8,7 +8,6 @@ QUnit.test("test: purchase order receipt", function(assert) { () => { return frappe.tests.make('Purchase Order', [ {supplier: 'Test Supplier'}, - {company: 'Wind Power LLC'}, {is_subcontracted: 'No'}, {buying_price_list: 'Test-Buying-USD'}, {currency: 'USD'}, @@ -20,7 +19,7 @@ QUnit.test("test: purchase order receipt", function(assert) { {"qty": 5}, {"uom": 'Unit'}, {"rate": 100}, - {"warehouse": 'Stores - WP'} + {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))} ] ]}, ]); @@ -69,9 +68,9 @@ QUnit.test("test: purchase order receipt", function(assert) { () => { assert.ok($('div.slick-cell.l2.r2 > a').text().includes('Test Product 1') && $('div.slick-cell.l9.r9 > div').text().includes(5) - && $('div.slick-cell.l12.r12 > div').text().includes(100), "Stock ledger entry correct"); + && $('div.slick-cell.l12.r12 > div').text().includes(433.42), "Stock ledger entry correct",$('div.slick-cell.l12.r12 > div').text()); }, () => done() ]); -}); \ No newline at end of file +}); diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_discount_on_grand_total.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_discount_on_grand_total.js index 54fa777668..4e73ab8ef4 100644 --- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_discount_on_grand_total.js +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_discount_on_grand_total.js @@ -8,7 +8,6 @@ QUnit.test("test: purchase order with discount on grand total", function(assert) () => { return frappe.tests.make('Purchase Order', [ {supplier: 'Test Supplier'}, - {company: 'Wind Power LLC'}, {is_subcontracted: 'No'}, {buying_price_list: 'Test-Buying-EUR'}, {currency: 'EUR'}, @@ -20,7 +19,7 @@ QUnit.test("test: purchase order with discount on grand total", function(assert) {"rate": 500 }, {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)}, {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)}, - {"warehouse": 'Stores - WP'} + {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))} ] ]}, {apply_discount_on: 'Grand Total'}, diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_item_wise_discount.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_item_wise_discount.js index 4ea8b976fb..1e54e50dda 100644 --- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_item_wise_discount.js +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_item_wise_discount.js @@ -8,7 +8,6 @@ QUnit.test("test: purchase order with item wise discount", function(assert) { () => { return frappe.tests.make('Purchase Order', [ {supplier: 'Test Supplier'}, - {company: 'Wind Power LLC'}, {is_subcontracted: 'No'}, {buying_price_list: 'Test-Buying-EUR'}, {currency: 'EUR'}, @@ -19,7 +18,7 @@ QUnit.test("test: purchase order with item wise discount", function(assert) { {"uom": 'Unit'}, {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)}, {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)}, - {"warehouse": 'Stores - WP'}, + {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}, {"discount_percentage": 20} ] ]} diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_multi_uom.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_multi_uom.js index 0f543c5972..bf2dfeb37b 100644 --- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_multi_uom.js +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_multi_uom.js @@ -8,7 +8,6 @@ QUnit.test("test: purchase order with multi UOM", function(assert) { () => { return frappe.tests.make('Purchase Order', [ {supplier: 'Test Supplier'}, - {company: 'Wind Power LLC'}, {is_subcontracted: 'No'}, {items: [ [ @@ -18,7 +17,7 @@ QUnit.test("test: purchase order with multi UOM", function(assert) { {"rate": 100}, {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)}, {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)}, - {"warehouse": 'Stores - WP'} + {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))} ] ]} ]); diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js index b5f59ad339..9d87af2342 100644 --- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js @@ -8,7 +8,6 @@ QUnit.test("test: purchase order with taxes and charges", function(assert) { () => { return frappe.tests.make('Purchase Order', [ {supplier: 'Test Supplier'}, - {company: 'Wind Power LLC'}, {is_subcontracted: 'No'}, {buying_price_list: 'Test-Buying-USD'}, {currency: 'USD'}, @@ -20,7 +19,7 @@ QUnit.test("test: purchase order with taxes and charges", function(assert) { {"rate": 500 }, {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)}, {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)}, - {"warehouse": 'Stores - WP'} + {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))} ] ]}, diff --git a/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js index 6927d82b72..46e8d1f2d6 100644 --- a/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js +++ b/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js @@ -9,7 +9,6 @@ QUnit.test("test: request_for_quotation", function(assert) { date = frappe.datetime.add_days(frappe.datetime.now_date(), 10); return frappe.tests.make('Request for Quotation', [ {transaction_date: date}, - {company: 'Wind Power LLC'}, {suppliers: [ [ {"supplier": 'Test Supplier'}, @@ -21,7 +20,7 @@ QUnit.test("test: request_for_quotation", function(assert) { {"item_code": 'Test Product 4'}, {"qty": 5}, {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(),20)}, - {"warehouse": 'All Warehouses - WP'} + {"warehouse": 'All Warehouses - '+frappe.get_abbr(frappe.defaults.get_default("Company"))} ] ]}, {message_for_supplier: 'Please supply the specified items at the best possible rates'}, @@ -30,12 +29,12 @@ QUnit.test("test: request_for_quotation", function(assert) { }, () => { assert.ok(cur_frm.doc.transaction_date == date, "Date correct"); - assert.ok(cur_frm.doc.company == 'Wind Power LLC', "Company correct"); + assert.ok(cur_frm.doc.company == cur_frm.doc.company, "Company correct"); assert.ok(cur_frm.doc.suppliers[0].supplier_name == 'Test Supplier', "Supplier name correct"); assert.ok(cur_frm.doc.suppliers[0].contact == 'Contact 3-Test Supplier', "Contact correct"); assert.ok(cur_frm.doc.suppliers[0].email_id == 'test@supplier.com', "Email id correct"); assert.ok(cur_frm.doc.items[0].item_name == 'Test Product 4', "Item Name correct"); - assert.ok(cur_frm.doc.items[0].warehouse == 'All Warehouses - WP', "Warehouse correct"); + assert.ok(cur_frm.doc.items[0].warehouse == 'All Warehouses - '+frappe.get_abbr(frappe.defaults.get_default("Company")), "Warehouse correct"); assert.ok(cur_frm.doc.message_for_supplier == 'Please supply the specified items at the best possible rates', "Reply correct"); assert.ok(cur_frm.doc.tc_name == 'Test Term 1', "Term name correct"); }, diff --git a/erpnext/buying/doctype/supplier/test_supplier.js b/erpnext/buying/doctype/supplier/test_supplier.js index 6be40a52bf..a953a8dd13 100644 --- a/erpnext/buying/doctype/supplier/test_supplier.js +++ b/erpnext/buying/doctype/supplier/test_supplier.js @@ -8,9 +8,8 @@ QUnit.test("test: supplier", function(assert) { return frappe.tests.make('Supplier', [ {supplier_name: 'Test Supplier'}, {supplier_type: 'Hardware'}, - {country: 'United States'}, - {default_currency: 'USD'}, - {default_price_list: 'Test-Buying-USD'}, + {country: 'India'}, + {default_currency: 'INR'}, {credit_days_based_on: 'Fixed Days'}, {accounts: [ [ @@ -68,7 +67,7 @@ QUnit.test("test: supplier", function(assert) { () => { assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Name correct"); assert.ok(cur_frm.doc.supplier_type == 'Hardware', "Type correct"); - assert.ok(cur_frm.doc.default_currency == 'USD', "Currency correct"); + assert.ok(cur_frm.doc.default_currency == 'INR', "Currency correct"); assert.ok(cur_frm.doc.accounts[0].account == 'Creditors - '+frappe.get_abbr('Test Company'), " Account Head abbr correct"); assert.ok($('.address-box:nth-child(3) p').text().includes('Shipping City 3'), "Address correct"); assert.ok($('.col-sm-6+ .col-sm-6 .h6').text().includes('Contact 3'), "Contact correct"); diff --git a/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js index 8404cb5b25..76be06c6fb 100644 --- a/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js +++ b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js @@ -11,16 +11,14 @@ QUnit.test("test: supplier quotation", function(assert) { return frappe.tests.make('Supplier Quotation', [ {supplier: 'Test Supplier'}, {transaction_date: date}, - {company: 'Wind Power LLC'}, - {buying_price_list: 'Test-Buying-USD'}, - {currency: 'USD'}, + {currency: 'INR'}, {items: [ [ {"item_code": 'Test Product 4'}, {"qty": 5}, {"uom": 'Unit'}, {"rate": 200}, - {"warehouse": 'All Warehouses - WP'} + {"warehouse": 'All Warehouses - '+frappe.get_abbr(frappe.defaults.get_default("Company"))} ] ]}, {apply_discount_on: 'Grand Total'}, @@ -32,7 +30,7 @@ QUnit.test("test: supplier quotation", function(assert) { () => { // Get Supplier details assert.ok(cur_frm.doc.supplier == 'Test Supplier', "Supplier correct"); - assert.ok(cur_frm.doc.company == 'Wind Power LLC', "Company correct"); + assert.ok(cur_frm.doc.company == cur_frm.doc.company, "Company correct"); // Get Contact details assert.ok(cur_frm.doc.contact_display == 'Contact 3', "Conatct correct"); assert.ok(cur_frm.doc.contact_email == 'test@supplier.com', "Email correct"); diff --git a/erpnext/hr/doctype/salary_structure/test_salary_structure.js b/erpnext/hr/doctype/salary_structure/test_salary_structure.js index 074035772c..23b52f6a1d 100644 --- a/erpnext/hr/doctype/salary_structure/test_salary_structure.js +++ b/erpnext/hr/doctype/salary_structure/test_salary_structure.js @@ -46,7 +46,7 @@ QUnit.test("test Salary Structure", function(assert) { { payment_account: 'CASH - TC'}, ]); }, - () => frappe.timeout(9), + () => frappe.timeout(10), () => cur_dialog.set_value('value','Test Salary Structure'), () => frappe.timeout(2), () => frappe.click_button('Create'), @@ -75,7 +75,7 @@ QUnit.test("test Salary Structure", function(assert) { }; frappe.run_serially([ () => salary_structure('Test Employee 1','Test Employee 3'), - () => frappe.timeout(14), + () => frappe.timeout(16), () => done() ]); }); \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/production_order/test_production_order.js b/erpnext/manufacturing/doctype/production_order/test_production_order.js index 0a7745e673..d4ac771899 100644 --- a/erpnext/manufacturing/doctype/production_order/test_production_order.js +++ b/erpnext/manufacturing/doctype/production_order/test_production_order.js @@ -111,8 +111,8 @@ QUnit.test("test: production order", function (assert) { () => frappe.timeout(0.5), () => click_make(), () => { - assert.equal(cur_frm.doc.total_incoming_value, "105700", - "Incoming cost is correct"); // Price of each item x5, values are in USD + assert.equal(cur_frm.doc.total_incoming_value, "99104.41", + "Incoming cost is correct"+cur_frm.doc.total_incoming_value); // Price of each item x5, values are in USD assert.equal(cur_frm.doc.total_outgoing_value, "99000", "Outgoing cost is correct"); // Price of each item x5, values are in USD assert.equal(cur_frm.doc.total_incoming_value - cur_frm.doc.total_outgoing_value, cur_frm.doc.value_difference, @@ -135,4 +135,4 @@ QUnit.test("test: production order", function (assert) { () => done() ]); -}); \ No newline at end of file +}); diff --git a/erpnext/schools/doctype/student_applicant/tests/test_student_applicant_options.js b/erpnext/schools/doctype/student_applicant/tests/test_student_applicant_options.js index 5a6f6df99b..d8877e63e3 100644 --- a/erpnext/schools/doctype/student_applicant/tests/test_student_applicant_options.js +++ b/erpnext/schools/doctype/student_applicant/tests/test_student_applicant_options.js @@ -15,6 +15,7 @@ QUnit.test('test student applicant', function(assert){ () => frappe.timeout(0.5), () => frappe.tests.click_button('Submit'), () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.5), () => { testing_status = $('span.indicator.orange').text(); assert.ok(testing_status.indexOf('Submit this document to confirm') == -1); // checking if submit has been successfull diff --git a/erpnext/setup/setup_wizard/data/test_mfg.json b/erpnext/setup/setup_wizard/data/test_mfg.json index 47acaff75a..b6ea665c76 100644 --- a/erpnext/setup/setup_wizard/data/test_mfg.json +++ b/erpnext/setup/setup_wizard/data/test_mfg.json @@ -1,7 +1,7 @@ { "add_sample_data": 1, "bank_account": "HDFC", - "company_abbr": "GT", + "company_abbr": "FT", "company_name": "For Testing", "company_tagline": "Just for GST", "country": "India", diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index 7c5582b522..ffdccfd006 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -60,32 +60,12 @@ erpnext/stock/doctype/material_request/tests/test_material_request_type_manufact erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_issue.js erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_receipt.js erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_transfer.js -erpnext/schools/doctype/grading_scale/test_grading_scale.js -erpnext/schools/doctype/assessment_criteria_group/test_assessment_criteria_group.js -erpnext/schools/doctype/assessment_criteria/test_assessment_criteria.js -erpnext/schools/doctype/course/test_course.js -erpnext/schools/doctype/program/test_program.js erpnext/hr/doctype/salary_structure/test_salary_structure.js erpnext/hr/doctype/salary_slip/test_salary_slip.js erpnext/hr/doctype/process_payroll/test_process_payroll.js erpnext/hr/doctype/job_opening/test_job_opening.js erpnext/hr/doctype/job_applicant/test_job_applicant.js erpnext/hr/doctype/offer_letter/test_offer_letter.js -erpnext/schools/doctype/guardian/test_guardian.js -erpnext/schools/doctype/student_admission/test_student_admission.js -erpnext/schools/doctype/student_applicant/tests/test_student_applicant_dummy_data.js -erpnext/schools/doctype/student_applicant/tests/test_student_applicant.js -erpnext/schools/doctype/student_applicant/tests/test_student_applicant_options.js -erpnext/schools/doctype/student_log/test_student_log.js -erpnext/schools/doctype/student_group/test_student_group.js -erpnext/schools/doctype/student_group_creation_tool/test_student_group_creation_tool.js -erpnext/schools/doctype/student_leave_application/test_student_leave_application.js -erpnext/schools/doctype/student_attendance_tool/test_student_attendance_tool.js -erpnext/schools/doctype/student_attendance/test_student_attendance.js -erpnext/schools/doctype/assessment_group/test_assessment_group.js -erpnext/schools/doctype/assessment_plan/test_assessment_plan.js -erpnext/schools/doctype/assessment_result/test_assessment_result.js -erpnext/schools/doctype/assessment_result_tool/test_assessment_result_tool.js erpnext/buying/doctype/supplier/test_supplier.js erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js @@ -101,4 +81,24 @@ erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_item_wise_d erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.js -erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.js \ No newline at end of file +erpnext/schools/doctype/grading_scale/test_grading_scale.js +erpnext/schools/doctype/assessment_criteria_group/test_assessment_criteria_group.js +erpnext/schools/doctype/assessment_criteria/test_assessment_criteria.js +erpnext/schools/doctype/course/test_course.js +erpnext/schools/doctype/program/test_program.js +erpnext/schools/doctype/guardian/test_guardian.js +erpnext/schools/doctype/student_admission/test_student_admission.js +erpnext/schools/doctype/student_applicant/tests/test_student_applicant_dummy_data.js +erpnext/schools/doctype/student_applicant/tests/test_student_applicant.js +erpnext/schools/doctype/student_applicant/tests/test_student_applicant_options.js +erpnext/schools/doctype/student_log/test_student_log.js +erpnext/schools/doctype/student_group/test_student_group.js +erpnext/schools/doctype/student_group_creation_tool/test_student_group_creation_tool.js +erpnext/schools/doctype/student_leave_application/test_student_leave_application.js +erpnext/schools/doctype/student_attendance_tool/test_student_attendance_tool.js +erpnext/schools/doctype/student_attendance/test_student_attendance.js +erpnext/schools/doctype/assessment_group/test_assessment_group.js +erpnext/schools/doctype/assessment_plan/test_assessment_plan.js +erpnext/schools/doctype/assessment_result/test_assessment_result.js +erpnext/schools/doctype/assessment_result_tool/test_assessment_result_tool.js +erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.js From dd351c585a175fcd5c50ef5fa50e1477649bb0c9 Mon Sep 17 00:00:00 2001 From: KanchanChauhan Date: Sun, 20 Aug 2017 11:00:43 +0530 Subject: [PATCH 38/52] [Minor] Title added to rfq web view (#10454) --- .../doctype/request_for_quotation/request_for_quotation.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py index 2d8820d992..d27d224d32 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py @@ -196,6 +196,7 @@ def get_list_context(context=None): from erpnext.controllers.website_list_for_contact import get_list_context list_context = get_list_context(context) list_context["show_sidebar"] = True + list_context["title"] = "Request for Quotation" return list_context def get_supplier_contacts(doctype, txt, searchfield, start, page_len, filters): From 196b491ac4a0b1e64a3b39f715a4bc0dd9900e1c Mon Sep 17 00:00:00 2001 From: Zarrar Date: Mon, 21 Aug 2017 08:07:42 +0530 Subject: [PATCH 39/52] [ui test ] Travis failing fix (#10468) * Value in assertion was wrong * Update test_purchase_order_receipt.js --- .../purchase_order/tests/test_purchase_order_receipt.js | 2 +- .../doctype/production_order/test_production_order.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js index f28ece673a..407891d270 100644 --- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js @@ -68,7 +68,7 @@ QUnit.test("test: purchase order receipt", function(assert) { () => { assert.ok($('div.slick-cell.l2.r2 > a').text().includes('Test Product 1') && $('div.slick-cell.l9.r9 > div').text().includes(5) - && $('div.slick-cell.l12.r12 > div').text().includes(433.42), "Stock ledger entry correct",$('div.slick-cell.l12.r12 > div').text()); + && $('div.slick-cell.l12.r12 > div').text().includes(433.29), "Stock ledger entry correct",$('div.slick-cell.l12.r12 > div').text()); }, () => done() diff --git a/erpnext/manufacturing/doctype/production_order/test_production_order.js b/erpnext/manufacturing/doctype/production_order/test_production_order.js index d4ac771899..47fd150a81 100644 --- a/erpnext/manufacturing/doctype/production_order/test_production_order.js +++ b/erpnext/manufacturing/doctype/production_order/test_production_order.js @@ -111,8 +111,8 @@ QUnit.test("test: production order", function (assert) { () => frappe.timeout(0.5), () => click_make(), () => { - assert.equal(cur_frm.doc.total_incoming_value, "99104.41", - "Incoming cost is correct"+cur_frm.doc.total_incoming_value); // Price of each item x5, values are in USD + assert.equal(cur_frm.doc.total_incoming_value, "99104.45", + "Incoming cost is correct "+cur_frm.doc.total_incoming_value); // Price of each item x5, values are in USD assert.equal(cur_frm.doc.total_outgoing_value, "99000", "Outgoing cost is correct"); // Price of each item x5, values are in USD assert.equal(cur_frm.doc.total_incoming_value - cur_frm.doc.total_outgoing_value, cur_frm.doc.value_difference, From 575ab3ab706928be2916f71c50191a9fa61df313 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Mon, 21 Aug 2017 12:24:28 +0530 Subject: [PATCH 40/52] [docs] for print style (#10452) --- .../assets/img/setup/print/print-style.png | Bin 0 -> 193928 bytes .../user/manual/en/setting-up/print/index.txt | 1 + .../manual/en/setting-up/print/print-style.md | 15 +++++++++++++++ 3 files changed, 16 insertions(+) create mode 100644 erpnext/docs/assets/img/setup/print/print-style.png create mode 100644 erpnext/docs/user/manual/en/setting-up/print/print-style.md diff --git a/erpnext/docs/assets/img/setup/print/print-style.png b/erpnext/docs/assets/img/setup/print/print-style.png new file mode 100644 index 0000000000000000000000000000000000000000..db93ceb0e6b36bcf3cfb0f447d868b1a4e15c7d9 GIT binary patch literal 193928 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

~etP(h;a>dMtfkcms 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 aK#uP1EoQQQ$$tR Printing and Branding > Print Style**, or just type "print style" in the search bar. + +Here you can define the CSS rules for your print formats. These apply to both standard and custom print formats. To find out the various classes available, you can make a standard print format, open in a new page and see the source. + +To set a default style, you can go to [Print Settings](/docs/setup/print/print-settings) + +All Print Format styles are based on Bootstrap (Version 3) CSS Framework. + +Print Style + +{next} \ No newline at end of file From c87c1dbbbfffa45f2bd0b594c2e1511230d8f75e Mon Sep 17 00:00:00 2001 From: Ameya Shenoy Date: Mon, 21 Aug 2017 14:10:04 +0530 Subject: [PATCH 41/52] converted production tests to INR from USD (#10472) --- .../doctype/production_order/test_production_order.js | 8 ++++---- .../doctype/company/tests/test_company_production.js | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/erpnext/manufacturing/doctype/production_order/test_production_order.js b/erpnext/manufacturing/doctype/production_order/test_production_order.js index 47fd150a81..a1e910a5de 100644 --- a/erpnext/manufacturing/doctype/production_order/test_production_order.js +++ b/erpnext/manufacturing/doctype/production_order/test_production_order.js @@ -111,12 +111,12 @@ QUnit.test("test: production order", function (assert) { () => frappe.timeout(0.5), () => click_make(), () => { - assert.equal(cur_frm.doc.total_incoming_value, "99104.45", - "Incoming cost is correct "+cur_frm.doc.total_incoming_value); // Price of each item x5, values are in USD + assert.equal(cur_frm.doc.total_incoming_value, "105700", + "Incoming cost is correct "+cur_frm.doc.total_incoming_value); // Price of each item x5, values are in INR assert.equal(cur_frm.doc.total_outgoing_value, "99000", - "Outgoing cost is correct"); // Price of each item x5, values are in USD + "Outgoing cost is correct"); // Price of each item x5, values are in INR assert.equal(cur_frm.doc.total_incoming_value - cur_frm.doc.total_outgoing_value, cur_frm.doc.value_difference, - "Value difference is correct"); // Price of each item x5, values are in USD + "Value difference is correct"); // Price of each item x5, values are in INR }, () => frappe.click_button("Save"), () => frappe.timeout(1), diff --git a/erpnext/setup/doctype/company/tests/test_company_production.js b/erpnext/setup/doctype/company/tests/test_company_production.js index 73bd710e23..b73af1dd98 100644 --- a/erpnext/setup/doctype/company/tests/test_company_production.js +++ b/erpnext/setup/doctype/company/tests/test_company_production.js @@ -10,7 +10,7 @@ QUnit.test("Test: Company", function (assert) { () => frappe.timeout(1), () => cur_frm.set_value("company_name", "Razer Blade"), () => cur_frm.set_value("abbr", "RB"), - () => cur_frm.set_value("default_currency", "USD"), + () => cur_frm.set_value("default_currency", "INR"), () => cur_frm.save(), () => frappe.timeout(1), From adbf8adfb9b7c627f747e93100cb0691428c7e30 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 31 Jul 2017 20:45:36 +0530 Subject: [PATCH 42/52] Update BOM cost in all BOMs based on latest rm rate --- erpnext/config/manufacturing.py | 4 +- .../img/manufacturing/bom-replace-tool.png | Bin 47759 -> 0 bytes .../img/manufacturing/bom-update-tool.png | Bin 0 -> 94015 bytes .../manufacturing/tools/bom-replace-tool.md | 44 ---- .../en/manufacturing/tools/bom-update-tool.md | 54 ++++ .../manual/en/manufacturing/tools/index.txt | 2 +- erpnext/hooks.py | 3 +- erpnext/manufacturing/doctype/bom/bom.js | 14 +- erpnext/manufacturing/doctype/bom/bom.json | 35 ++- erpnext/manufacturing/doctype/bom/bom.py | 46 +++- erpnext/manufacturing/doctype/bom/test_bom.py | 28 ++ .../doctype/bom_replace_tool/README.md | 1 - .../bom_replace_tool/bom_replace_tool.js | 22 -- .../bom_replace_tool/bom_replace_tool.json | 119 --------- .../__init__.py | 0 .../bom_update_tool/bom_update_tool.js | 34 +++ .../bom_update_tool/bom_update_tool.json | 244 ++++++++++++++++++ .../bom_update_tool.py} | 23 +- .../bom_update_tool/test_bom_update_tool.js | 23 ++ .../manufacturing_settings.json | 130 +++++++++- .../test_manufacturing_settings.js | 23 ++ erpnext/patches.txt | 3 +- erpnext/patches/v5_0/reset_values_in_tools.py | 4 +- .../patches/v8_6/rename_bom_update_tool.py | 7 + erpnext/public/js/help_links.js | 4 +- 25 files changed, 649 insertions(+), 218 deletions(-) delete mode 100644 erpnext/docs/assets/img/manufacturing/bom-replace-tool.png create mode 100644 erpnext/docs/assets/img/manufacturing/bom-update-tool.png delete mode 100644 erpnext/docs/user/manual/en/manufacturing/tools/bom-replace-tool.md create mode 100644 erpnext/docs/user/manual/en/manufacturing/tools/bom-update-tool.md delete mode 100644 erpnext/manufacturing/doctype/bom_replace_tool/README.md delete mode 100644 erpnext/manufacturing/doctype/bom_replace_tool/bom_replace_tool.js delete mode 100644 erpnext/manufacturing/doctype/bom_replace_tool/bom_replace_tool.json rename erpnext/manufacturing/doctype/{bom_replace_tool => bom_update_tool}/__init__.py (100%) create mode 100644 erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.js create mode 100644 erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.json rename erpnext/manufacturing/doctype/{bom_replace_tool/bom_replace_tool.py => bom_update_tool/bom_update_tool.py} (63%) create mode 100644 erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.js create mode 100644 erpnext/manufacturing/doctype/manufacturing_settings/test_manufacturing_settings.js create mode 100644 erpnext/patches/v8_6/rename_bom_update_tool.py diff --git a/erpnext/config/manufacturing.py b/erpnext/config/manufacturing.py index a930ddc6ef..11711ad004 100644 --- a/erpnext/config/manufacturing.py +++ b/erpnext/config/manufacturing.py @@ -70,8 +70,8 @@ def get_data(): "items": [ { "type": "doctype", - "name": "BOM Replace Tool", - "description": _("Replace Item / BOM in all BOMs"), + "name": "BOM Update Tool", + "description": _("Replace BOM and update latest price in all BOMs"), }, ] }, diff --git a/erpnext/docs/assets/img/manufacturing/bom-replace-tool.png b/erpnext/docs/assets/img/manufacturing/bom-replace-tool.png deleted file mode 100644 index 51ac99324b563dee3b0f3af97fd130b3abe3fe6c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47759 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 ZdicW*A2~+PMk?U%;yGQdytCJX{|~ntK-d5P diff --git a/erpnext/docs/assets/img/manufacturing/bom-update-tool.png b/erpnext/docs/assets/img/manufacturing/bom-update-tool.png new file mode 100644 index 0000000000000000000000000000000000000000..7dbd47fe0e1c7a9ac33f39ef6c6c233533f20204 GIT binary patch literal 94015 zcmeFZgiDcz;j&1#wBdEcPTPqwcU4$*ev=PgCapolySg~4ij{+7F&s(*J~oGRkl(p6H)F(z ziMo*JT~e~Tvz}DQJJEEG(ox%V?63oTrVJVtGIQr_@4{%Vn0}!q4tUR>Baj%&6|>?S z#3%ci0U%=-!n3Yx5Hh+BPU&M7=O;Fk0Q}S>SBSao9}*)_=AU|dHRrX^%pE}pM!NyS z`I{5n2SG4tQBDC5=Jvd|K^&t^q0v_=+@r6|OLY^!>86D${*;20Jp06lK(TkB;^rQ7 z|D^2vq2`(KL)UuXhXbM%`0_P3*~&{PFHPQdYGRW$m$&EYka(8c3aV2VB^?1jEd4P6 z_<{xLctK|jmaj`mugRvOn7&-S@a7GH($f_;Z)YTygj`w$Ft9vTCjkmY(ulvSa_VSt zdc;q4{n;^SSy4KY;%Fs$O>{U8)7R{N`%_|%pt4oQ`;A1Q-~hEp{ETu1F=ednu;(%l zOPpyGMRY{JP*`?Zc6YvW!8qyN?D*8}Q}VV*P{{c`)+d_#?3?~h)$eX$3lIzx`RjfF zl{{m4`6kkSb>n?!&u$nk2}OJOrTco@ZRTREbHPwP?w8yX>CYsXjRy!{Nj=89CFOtn z@sG^FM20(uvxpt|l7OcQo+$>&&s&D3`9opg$K77H4ykZMnoWqE0>EQjk`uky*s3TC zO*X%ocLaK%fWAjGqJe@GlN~;eT%z~HZ%kd<=ba)+B(ipX=Cqrd5p#!8z9^?&Z~0i@ zVoHjEY#Nqr7ND?XS!bl|UN#VI<$1xf%)N~BHQ5pO@w@EOC;0hP*Bu%32|O*2hX}uY zcv7l>5*L|!Q0m@-GOtH%OH#-so`Ce_3%rLN}~OKUuUt-wWBX3&zW308CN-AWlv zhDo_9^GiP|j66rJEdZ7&Ci@%lh-NY{h6FJI^E)eIBK2lhT_?JqA5wq;HKrs_a57B^ zr|_OOyZ^YehlSgsrix45qUVTVh(WuAQ;oYRO9Z|RZ(*Q(LHz#x5V3GZASI(^5aCKt z^&|1u&+Y}cGqS#>{t}EweET_t-n$sa-Ou=MS=7U?LsDc07~?-HuiZVy+m>BmfT|K? zW+df^+eAdXnpgAV#SDLy{WZ~wPX9fptj^bUD>5%Yq3mFW&Jc~20Q??pGaxIB``M#D za+fa55-WDH-e#F8NWm?(w!9zGx>(n##c$?y>CZ`6R$NnpXIpEiKC&#?i4s90i`&@_ zeZU+G?@Ze0mv1h0FvHVd{dfqz*Lu7Ay<#i-3+}IBKR!9WbEGRurfX%0di|D|Bgnzg zD2uo($R&s^*dX{*uu{A73h4?USZ3tm^yhlH;m72xP))@dMPW%{=^e(i&*GnByFb2t z<%}m3%g(^X93OQNtrA`LbFf=l-bUV1K23gD{z2xne15Du8{ZQntsOP$j2sR2CkruP zd2$Pq%oOJ!=QL;Nv9_MxwC=RDXX$ej&#%rk$0X~aJ&`dI>U=p9W0E_XdGBjOYU5{Q z8l-&`z76+T`<83!i`$bGCb>tPe?FJ`P-K>Uuc%c`FI_!XJ%1$gSYAtRTyfmQt=1;W zCUJ**JU`FJM&4$_CcuWh;>sr0hGpC#moR5^oObNnxXZXs9!#g{JMu-~_cui(1uet6 zc_j*~DV?OkF9p8hj!d62oz9=0oYE;}WPPx#wv4mP-H_^c@Au^(@d6)dMD$$^7F`wt zV4-sA0G5&Aq`pV#0sFjt?WP-|(k{cg9alndoL_F4*V

V5P17<2_8pR|fxDuffOX2`uA$Nmq*4qt-PM+Df6E^1ybFHG? zkVMbat2=k>LmfjIL#aa%al8s9y`sHOdv~>E*gW#>@(Z9|*5zhw9Q%nuVs|_kO4g6*?XQ^jjxf9gAuIq4jb1&{pj!>a(a)<0*7N2vT3!T^P z!-T8^6!b7nX9axcb;^ObTZlY9S&R~St@D%HoW>RJ0IA%sW#ZuVAoLEaPHlZV9FgJ z^5)__%R=V@J1li!UR)8%3#ApGZ+zLvzW8*p%a_^rL6ey8;7#Fm*)`E+6aEh(V(b(= zF#Q&lAlDC8ygT@WPjA~0P2efx72)|(nmzbJrA|6RzjIHRrJOa4n4F}Ne^0yGS5Ty0 zxZW>gw%wD|fH8-}iG++K@=@U<*(k#3Avsc(La3`m54$|E76oBO+qcPA5_XA*dR4Dqz6 z7x!godWRBbW4HC5K8`P^VZo+;XD8LG7?}8hN8|&4tJxcmG~hyK zy|3DPt4K-`71GH~+g5YsV=#$V=ikrqM-=o?NSlnX{Yu&si z*X0owi4RCkjRJM{r;QbTw$tb9m(IxJb24Q%{^CphR@NFr8xwtPxF?hM`Z|=>mlNd) z*6PeVA1}(UDtw6E=ruJH9{Y`MJG&thVtNwRKKnQuAHNX7_y?xIxqUTu2<9HIv~IUQvr)A_&ENEs(pCF{GjVDt$;}5`mGxoISzG^y2_>qok=68`l6@v zO7{j%@ki38>6^-`;hd7=n2Fr+Y}V}fG&*q&SIcy{sWA`!lfCE-s{V@sCTQKl^P0>X zNc&YN#S6|9+cS`u%P_)hm1$6cg{#h_sBXn8v$8*Pza7Te1hw+8FK*azuV`%h_U)_7 zi_LA$#iFvwcST0kbiOw|;W;#^0;CQLjeKX?7xn}D6duk8^^FFO9$O2oi1!F4qA|J{ zu`zGmvrpsnpX!Y2RK)PT#?A!~jv83@Sh%1eP~QVRc-VQtUd{5!4n+hPwYRjF2r}gu zIH<7P`?YbUX$&=U+;cpB)O3S%*i|`zd2)D(U0bdjq*i$^3N_i%1yO+o6GQ}08`lB{ zKKankOH}&G!%rbr6Tp$pV=iqI>c*Fl28k3AQTDgNx~1O$I5bI77|qEIfFbpz>91IT zkdW&GCQ=z+lbDBx&>z>n%%nPib2!H5AH@Ez!7rzAlBwD?FXQMMR&M}1YrHe}83!Dl zW4bb0X$Y3v4i61{0IvxF5E4QnB70goWGT&;1}sU9wCe#DGDguw*yjZnsacM~7l(n@ zSYB3k@4?tVVCXpEw&QC(7XW~q>DMoYociNK001M+T2t3mS4mOW9AwY=<}Jv~f)i}- zh;9u4h=PUDhxQh(Zy3P#b`CDWU@^wOS_q?$f1T!HWcaIztF0KLu97N)G|1V4fsd1y z^BJQ!J_7@TsPkJ(VRf08|L%_dPmIyZ)zwj$i_62qgVTeD6XXo!;uaDT;(GR+>-lpI zbPEm_PY2gGU=9bDNB`0Gah{rT5CEx^|Q zb0-Ive=iHYK(1d`xVSl=as78}bXU<|XN6U*!4`J9GS>DM4ld|>h;#Gt3yS{L;g3uI zbIbqLRqubg3O#@JzkB|#EC22(%Jpjn|7%7664zg6(ee_<7v=h|?8Wh)r};^vAIAf0 z85K?RC+4qbgMM;-=s!>X_4(_#R`r8Ssu=(v36PVK(gb7d&3l(?jVCg|i)E$m!~nz@ z$J4DmziNfW5pc+<%go>gyxxqtZ=?4d^6cr$e8m+Go*sorUEw5t+TEnrv7KYhT|)^u zAC#yAkD@xWzKrBku)Q?LPr7{f^qyuq@%GQ)(*_rq%ejy(tYJbNAv*OG;n6wNFfrrO zUo!zJ>Zd<3aPdWLpcMR;BLNtgxA2G=B>jIsc=jF>^%7u)$EPLx$F+aAj={dgAd2_* z-6j2-Ki|QVBoNBQzx{W^{~7`VZ}9iK{&ybF)-W-NrIqtu{2$YklmxW${I~V*2Lv_# zfcDSPd7uBU@rnHp3I4BXVM=o{0Jzt_KYjfBu>a|SUN+W0%l?lv{!*WRp7!7Dpj=Y^A|ry2 zn#3M{B)SUH0ov(R@f(93lnV4tMs+W^X3a*EXIGYjNf{UBC_%C|0`@9t5LZPJYyA|* zl^99^FH?%)nuir9T&dg{8>b^TsgB1n0b9I~9FKbVivon!TDic}3Xd^{+1~9@UQW-Y zHCCs!sU#XZaBPK%duP_>WM|y`^lB{6n!IavC9b<~E-8G>bd zcb4f7dkyx(p5Xx;4csX)J;=}%xOG0NvKyp8kw&4xLg>5%LUe-n8bwy)ENsmbB#Ld1 z*S4LyTO}e!Rg|Sde6I`Z?4{UsD>*L0Y>^wt1dlxiSZ>~iy%VAj+ev4>gLY)kayud8g;nShY{D z_W~wxZVF%lw$$*a*bE;RG{b)f=>RbnG_;RZl5)v|ItM{!te^Xx7CY{k%k8T(O1p|p z&OucAL`s|@-dzW5F5F4*?cg{%^L%wiN4Yg|&R3GY3dd0}CTubFXpw}a<67L=A@ir) zY8%?~v@S%QjOe34+VRj7%knv%1S*d4@%^iY@>`>=<#V&4-i?`;L(>F5WdLT9cFK&u z>uJ3T+S$>&lpY8x_H)v27isFI;{XxSH=4+7iX6=-sC1>WQEysTuhnKcU4^yn>}-jB z#u*lePH@8>-IisoYO6;*d!(E&mb&MqTl+pH2>yY-Fv5Z@&E{G9;`j*RBIL8m>)n+0IyGqbkXCtD%0KMijAMR3lMinNG`z^cm9+v6jMq z`f;9T`7inFrpWwm`7izP@g(00TkgmTbc`ruy^XkUcd$Uk#c6Wy4v6h1<8arpXtK5; zJ?)~dhN@@#+UQ0XA!^eTZ9ZOpi%311Azh4Mb1+&_AARN^TPvKSwq*!$}-DSnV5(xn)y6Cea{NZ?8jvG6s_HO*fKY)D-IQJfi> znI~9ouR5?)=I*`9TKd-XMH1;!B5*@@#`C*ZYzn$Z?EmxB(hpZaK+MbB6~e)S=hU27 z0_o7=76%Reu#&7p2yYlWX|N|v$`F5do;NTFD(*A5AE|Y2D?X^)`($4AN7%2~Dq*u2 z(@E5NDx1JSlPP0$b*on*t6}-^7j!@8so%96U``^>t>@Rt{@0w{5^jV(OALu_A@>HE z%B$_vB-o9d3>0a{S3<9v`QuTBdrD1RMC=WB9{sLY1ZYTM44go<^xHd4reHfEig{vV z1XyH-)88Ns28=eLsqcscPFXHht=$oKjxr-;qe$`Pn3P|GRJjIx0)_pW%havcUBD2Z zX=!dBJBua>XzJ0__-3b08f-V^A>|$?-u=@i72BeU^o3T8!Fj&Tc=r=bwK@^=uHv7uk4}JUMQd{Dqrt7|P10&gg>;(&UIn`!klALl4GL2Pxyzb@}Ygs|n5I z`Te=Hq7$9j44yNo@0p=ympPPadqm=I6$xNKqiHYPIx)?gp*^=4+Dhh6`>^&R*O8zv zZ8>X)!)wnpBi~$f5EvO?68E1MJO5!Uh~D`FWU?r5p6fPjz_FdyckC1O<&&`ktE|N? zJAlR{Y&P=o9x8}3u;r1S=OV9Lfy;d0QTO0tvVr?TMO6o%kZs#05qLs}`z)iw+B%PS zYj&}zFyH*VzRBi?jAmvlW^vDCKZN`iKF&zCRzKNTGL8R}Cv{uN7hQARMp%a;#zv%( z^Ddyd8h9)uUOFPA7u81JKJ5Z*zYM59Td3hqGlcI~TTg3Ton_as0|$k=*5Mnc**(^n_ntI>XN)3X-l z^DM4<)<)#3a3Gvhuer~7TQg5>ve@iOOoglFDaLo~g$|eD(N(#M1 zJt9N!N0pT)8(KfJR6RZP+5J{(ubDEBLpgnNj2QumNYyQAnN$gF5jxul(YC8)W4hf`#V-e5^eJ7xiamlBH8z-TDEWBDJ^~IR zPO3LTsN4ouC9#OZ5ny0J&8|dO>_wxhbz{w-bXM00$e2b0_bS=0sH8~!s;R3H@imuU z-PESzEY$31v;w7l=63$RdO2%%WiOg&H{TR?;a$#w5oBy-@TYb*{?g7!YNEH6_~&*9 zVTb_{iMaY{mvq}zf1#tc*!W4p9~-!AjGd|Hn@2xasQ6+}{i;sJ*N?h;5Bh|hUd+{A zS0-qmYXXjg;t7=3 zMRtpm#!c#oaISvf^em^p9q?qE#7uNIefLVeuE!Y6rI^20<+GD5 z#KSrwxi?SLu}zv>6LT%q>cmqNic4O94``^JoSy;yQI|N;V}Xx}eX~6}SBbwvYX``P zu{E72zs;In#xZfT<=0;779QVuwKGq&Ipa~JP-ZL+71+(ZaL7t?w@g9KwteHNIG+gh zsTy~)l!D&(bQKV&iIH9|ux8yp&6%pW(K%W{=~7i?LnvhZ;9UQk0u7Xr z{Cm2iiDcA$m4ypa(KyoPf|w>|?B|=~x1QHE+G-hGp(@vqbZiv+(SI;bOFpD%*I`IS z8Kl0balz~c3K-Z&$5?~VkS4@LYDodZ@<9f#q<{d>zvyI>RqhlzakoCZR>SuredaYm z#ZkzDHlnIxwFd1a*v3t!#t0BY1(t-|7L?FF`)xF;pRArIy={ozG>(Ui+*9(ou?LGP zH(VC)%5&7NE+@=-f>PjD{An0bI76_StK$UG%Gxdwfr4Ozq8jlyGD2ip!k3suh<3Pj zi>Y1aSi8_sbANnil#u=W>D8{etP)CFc^BSCBx&cl(wX41sxdCB;GLOrTfm4+qmI-- zhwOF0hq|IhW`{wVCD5}n%Z`rC_LU@;tSrfykt9idErZNdlgzbEzZmE>5~2GO$%$f~?YbDg>L!WR3EcIA$2rS=@}OUtBfCB>v!|Rr{rz_NZBBv`npx z-C#R^GOb!{ppKhMM+shP>RB^Up>^0t{{>0wW4eW;UFdWQ!RU8>nT$r1? zp2J(W8V8@I<;yg_?tFK8?%7Xs^U3x5IafG|M3Vrv89KD&J}6gM^$r!GzLi|rQ98&K zlsqx+ALrq6FBYVmh$&XJNfyz~gJh30_RtQjR9D{{~6iT6n$LN)Xft#bf$|aDaV6 z3r96aC5^rpRP&@$r)kVs%cU2SIMsGlp{%G|uQtm!OLoB@I0yhqiJcTRa5UUrXmC{; zr*((jPZ7B2t?J0oBV}BC==VdU7~X1*jWs8Bp#e6dH@QESEV87hSve*%+IwjimTYNE z((BA=3n!~;pWLJ!KT%qKF8v`8E|%?XfB!K)4F0@WMR>I&e=xjQ)Wm48nu;|T?&iay z=C@zOwo>nH8!wwgte`VTuJKB1k}67KXb$K{F6uX2AXgifVbSMMz4}$qn`qY?1J+uY{#QkEc zNv^7;m4mn-N5_JQ^6QqX45?aiTup?xk8I$QkV4EFA=t8*}Lgw0vWL&BM^c zw^x+Q0u=g|bZ>pWezOql?_-J)biK*O^hO1=Z=!oP;k!WQPCwhoOzvt(UqPxifLyV6 zYMZ-W^az|uLgx92hv#$PXJ}#ugbyAdE1yY@BfL3d?JUratkPM^i$8%e4E?Z)JvypK zIYYcb2_{vYkm2U7bljh|#Z6Yk5CBHd6Wx`~kDx4p7M4w=iz%v$R1aVF+-~#F{j^cA zA62*vSzX6klbx3{jZbG_5T?fGyLXOs=PyQA0$7SdA1PoVbD=KLNf)bx7tUwaoy|HU zVTtg{kLfBlMW_lGE z)7svUpsj5!{c{fTo8{Zqju!&c-;8G4E<#C;lEJ%BlL!{5?^ELfs<*|$4>_vJARX)6 z;wP41WV5%7hMZgeQlQ>lMigH|x*nvgKADTy4Fq+^I9(PXLXs2R}x)Hy~p?LJ=VE%2X)j;dL<(W^Z;fa_@=3e zq|MaL3_eI0U;mRDq5daA-0J~W76uk$*PDzN7lNOa9q;}g;G)wtzhZMi1S!E($?^yA zanY>#(N1_GwU+^N4XqZr7}y|Sy|BWV)PgPcxLFD zNY?t*CP##K(QB!4-|O`%t^1T)h2XCIZGpqZxUN!`iT2u*w_OcPH1=c_(P$GemA;zr8KQ zcIjd3pdVqQW-XMbU8&Vrf4%tvkkJTx@bLG*8AANahiVuCJMw5eE32_M+vi5WXE5OE z0n0~cFwy&?5;I2NwpDJ#N>cIj&$EVcIe(nN_bYb`OHTY(ed|i~2ipGl0n?yh5Xo?Y!5+Vga z#*)yUihl*}st!8Hq`%RcZ!!?O8S1I*q0k!Y!b+GQc8TQw0|;)NC!oFNkCi}G4wr(& ze!j(O#v(&C3DS(b#*9pPGevZmke0w-n-~Y@j25}`FqI#Mw*7o%d8At#grYh|E*>tP z>x>*cXXt?Am4#4}5?fJZ1gIdlrrEkgbe(<6n>8;(YAb1ndjIaaq*Z0=J1+%{pc$q@ zc~7cFUR$*>&IOk%CDtd7&LCoD1D|2{BG0FgHd+=x$0KP#U&q*S=seUn zM?%Eq`;yQDRX_%V;LvN}WJ06o?*f@QYu^!Ke zPD`ZeK6qvM#VmfOuP%)-kfm6h1-WvS#3pCkBN06j1H1N=54z5-xE(dx7hz#-*)_G} za;^)=uwroi40=g{9iL@fE*NL59&P(|N$AP*!np1OzUcSDOxH+=Pb&;rH4eGA!)IbZ ztRtS(v^R39N6|qsAi)!nqANQ3&98>}7&nP#(Zm^XU2_yW^Lm;A8eliL*S(K+AN?_j ztt-b@V%~en?swd6eu%ozPkmo&VIK=)LDdlZ=j_`deqV9`(Z^q*BRw^dgC+iigM$g_ z9g(796}Z00Qq>!a6tAQG3Sj&N?iZHy+KhfDM9K#zoqqQB>WLXLlb%>hNq&cOBchco6i%WFw;yA_r;c)Mz9`d}W0% zb8e2`9%}7b^FgS$SIar-{@|Xx)Zjx<{##W?Pz7q@{F8#-pH7h&GXo&%>%J{o5z1}K zPS8|kv<_FXu=YZ(g1&)h5Dhm6;gr#2aZ8I`;4V7R!Crk4yZ1G1UlvU{ZzvbhyY@a3Q;hT( z4;O^E9%yYNISU$^GSVfVE<)FaKJe%<8{e0x_4d8ECoHnscrp;l1e#cUeNZt@!A8$& z$7X|x#rot6O%6IKcDOSB8sUZ+8tAoDiG#5s9Q4e5`ni|Sr zFVauNtvPJCJVnv7w1xHit}b8*rAO@7S?8NE~2sH z7q5l-8(u5@7q8`&0X`Jd$Z;qW%=xUd7_sS~g7uwk*M^l|@U1dCYG7SUF8Sn+HvRnR z)|aiz8PaiFHgB!KiP%6RC|Z|1Ck=(zB!*qrXZwI&cTiEM9^>dk(%GzsgL-jNiTk3NA*e^%um~M&tT2z%F$6Mype=Er#Vc zc_nCoqam`aCD(V(2*=kv&@Kli@!9+`-tW%FQXo58ueMXOa5cOKrm0kXR+BE(2ktRt zGG6sQC2OiNE;{$$b{cG$>|9HlyDg?PVOM{dx@*2XaxHbCKD;0^%*T>7kG88HabyGQ z__Uxm9kVMRYe;P(-1iT<0W$X+G8cWA;!V6244o}Wv3|1R{a8uj>Rg#yl9q9EKI*gQ z$Cr!=Nd>E2A8uSZnQp}F^!JzSt$c7A{kZeZ$XiH=k6$z`?i9XT-)cS4wSLsl5q|G3 zC<38wpx`|FR7;Q4{|RLb$U)NEptcwr`$B6}d2oIWmm%qPk!Wn(EyTzUym@%6X0mgH zOBrVU)#{to^w-`|b&Yu5k}*xS1|Ql%gxJKHv`OqK1PY~WJUv6ZOoFPrNLns2@bzU;xTT(n?858Pe&;Eof&^|=DL;l#P=zbE|a_(fj*ZlZZe*EH2S>f?j#SPlp zXY;1tG!xP~nGW2O{l$qZAXnfxgVy#Uv7uZJu)Ge1)z;Cw`S%M@cEkz6e{lv};g4QT zLdjE;S91|@?ePcwp1VykKO3MzgwFa_;3u#P!9##dd)&B!+4-3)&$o?sECCa`R}

  • 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 Yuqp;lnU{G2AmC%5XZmZgj@=*s28pet_y7O^ literal 0 HcmV?d00001 diff --git a/erpnext/docs/user/manual/en/manufacturing/tools/bom-replace-tool.md b/erpnext/docs/user/manual/en/manufacturing/tools/bom-replace-tool.md deleted file mode 100644 index 98d1f3b985..0000000000 --- a/erpnext/docs/user/manual/en/manufacturing/tools/bom-replace-tool.md +++ /dev/null @@ -1,44 +0,0 @@ -# BOM Replace Tool - -Replace BOM is the utility to replace BOM of sub-assembly item, which is already updated in the BOM of Finished Good item. - -To use the Production Planning Tool, go to: - -> Manufacturing > Tools > BOM Replace Tool - -Let's consider a scenario to understand this better. - -If company manufactures computers, Bill of Material of its finished item will constitute of: - -1. Monitor -1. Key Board -1. Mouse -1. CPU - -Out of all the items above, CPU is asembled separately. Hence separate BOM will be created for the CPU. Following are the items from the BOM of CPU. - -1. 250 GB Hard Disk -1. Mother Board -1. Processor -1. SMTP -1. DVD player - -If we have more items to be added , or existing items to be edited in the BOM of CPU, then we should create new BOM for it. - -1. _350 GB Hard Disk_ -1. Mother Board -1. Processor -1. SMTP -1. DVD player - -To update new BOM updated in the BOM of finished item, where CPU is selected as raw-material, you can use BOM Replace tool. - -BOM replace Tool - -In this tool, you should select Current BOM, and New BOM. On clicking Replace button, current BOM of CPU will be replaced with New BOM in the BOM of finished Item (Computer). - -**Will BOM Replace Tool work for replacing finsihed item in BOM?** - -No. You should Cancel and Amend current BOM, or create a new BOM for finished item. - -{next} diff --git a/erpnext/docs/user/manual/en/manufacturing/tools/bom-update-tool.md b/erpnext/docs/user/manual/en/manufacturing/tools/bom-update-tool.md new file mode 100644 index 0000000000..41503531b6 --- /dev/null +++ b/erpnext/docs/user/manual/en/manufacturing/tools/bom-update-tool.md @@ -0,0 +1,54 @@ +# BOM Update Tool + +From BOM Update Tool, you can replace a sub-assembly BOM and update costs of all BOMs. + +### Replace BOM +Using this utility, you can replace an existing BOM of sub-assembly item, with a new one. The system will update the new BOM in all the parent BOMs where it was used. + +To use the BOM Update Tool, go to: + +> Manufacturing > Tools > BOM Update Tool + +Let's consider a scenario to understand this better. + +Suppose a company manufactures computers, Bill of Material of of the computer will look like this: + +1. Monitor +1. Key Board +1. Mouse +1. CPU + +Out of all the items above, CPU is asembled separately. Hence separate BOM will be created for the CPU. Following are the items from the BOM of CPU. + +1. 250 GB Hard Disk +1. Mother Board +1. Processor +1. SMTP +1. DVD player + +If we have more items to be added , or existing items to be edited in the BOM of CPU, then we should create new BOM for it. + +1. _350 GB Hard Disk_ +1. Mother Board +1. Processor +1. SMTP +1. DVD player + +To update new BOM in all the parent BOMs, where CPU is selected as raw-material, you can use Replace utility. + +BOM Update Tool + +In this tool, you should select Current BOM, and New BOM. On clicking Replace button, current BOM of CPU will be replaced with New BOM in the BOM of finished Item (Computer). + +**Will BOM Replace Tool work for replacing finsihed item in BOM?** + +No. You should Cancel and Amend current BOM, or create a new BOM for finished item. + +### Update BOM Cost +Using the button **Update latest price in all BOMs**, you can update cost of all Bill of Materials, based on latest purchase price / price list rate / valuation rate of raw materials. + +On clicking of this buttom, system will create a background process to update all the BOM's cost. It is processed via background jobs because this process can take a few minutes (depending on the number of BOMs) to update all the BOMs. + +This functionality can also be executed automatically on daily basis. For that, you need to enable "Update BOM Cost Automatically" from Manufacturing Settings. + +{next} diff --git a/erpnext/docs/user/manual/en/manufacturing/tools/index.txt b/erpnext/docs/user/manual/en/manufacturing/tools/index.txt index aaf7cecc70..a385154589 100644 --- a/erpnext/docs/user/manual/en/manufacturing/tools/index.txt +++ b/erpnext/docs/user/manual/en/manufacturing/tools/index.txt @@ -1,2 +1,2 @@ production-planning-tool -bom-replace-tool \ No newline at end of file +bom-update-tool \ No newline at end of file diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 4df83afa10..7e65fc9262 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -196,7 +196,8 @@ scheduler_events = { "erpnext.hr.doctype.daily_work_summary_settings.daily_work_summary_settings.send_summary", "erpnext.stock.doctype.serial_no.serial_no.update_maintenance_status", "erpnext.buying.doctype.supplier_scorecard.supplier_scorecard.refresh_scorecards", - "erpnext.setup.doctype.company.company.cache_companies_monthly_sales_history" + "erpnext.setup.doctype.company.company.cache_companies_monthly_sales_history", + "erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms", ] } diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js index 347314b2c1..c58c89cd5d 100644 --- a/erpnext/manufacturing/doctype/bom/bom.js +++ b/erpnext/manufacturing/doctype/bom/bom.js @@ -5,7 +5,7 @@ frappe.provide("erpnext.bom"); frappe.ui.form.on("BOM", { setup: function(frm) { - frm.add_fetch('buying_price_list', 'currency', 'currency') + frm.add_fetch('buying_price_list', 'currency', 'currency'); frm.set_query("bom_no", "items", function() { return { @@ -13,15 +13,15 @@ frappe.ui.form.on("BOM", { 'currency': frm.doc.currency, 'company': frm.doc.company } - } + }; }); - + frm.set_query("source_warehouse", "items", function() { return { filters: { 'company': frm.doc.company, } - } + }; }); }, @@ -57,10 +57,14 @@ frappe.ui.form.on("BOM", { doc: frm.doc, method: "update_cost", freeze: true, + args: { + update_parent: true, + from_child_bom:false + }, callback: function(r) { if(!r.exc) frm.refresh_fields(); } - }) + }); } }); diff --git a/erpnext/manufacturing/doctype/bom/bom.json b/erpnext/manufacturing/doctype/bom/bom.json index f41087b686..886c9428e9 100644 --- a/erpnext/manufacturing/doctype/bom/bom.json +++ b/erpnext/manufacturing/doctype/bom/bom.json @@ -232,7 +232,7 @@ }, { "allow_bulk_edit": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, "collapsible": 0, "columns": 0, @@ -262,7 +262,7 @@ }, { "allow_bulk_edit": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, "collapsible": 0, "columns": 0, @@ -291,6 +291,37 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 1, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "1", + "fieldname": "set_rate_of_sub_assembly_item_based_on_bom", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Set rate of sub-assembly item based on BOM", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 7130a3e94d..71ff43f48a 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -92,7 +92,7 @@ class BOM(WebsiteGenerator): def validate_rm_item(self, item): if (item[0]['name'] in [it.item_code for it in self.items]) and item[0]['name'] == self.item: - frappe.throw(_("Raw material cannot be same as main Item")) + frappe.throw(_("BOM #{0}: Raw material cannot be same as main Item").format(self.name)) def set_bom_material_details(self): for item in self.get("items"): @@ -155,15 +155,17 @@ class BOM(WebsiteGenerator): rate = frappe.db.get_value("Item Price", {"price_list": self.buying_price_list, "item_code": arg["item_code"]}, "price_list_rate") or 0 - if not rate and arg['bom_no']: - rate = self.get_bom_unitcost(arg['bom_no']) + if arg['bom_no'] and (not rate or self.set_rate_of_sub_assembly_item_based_on_bom): + rate = self.get_bom_unitcost(arg['bom_no']) return rate - def update_cost(self): + def update_cost(self, update_parent=True, from_child_bom=False): if self.docstatus == 2: return + existing_bom_cost = self.total_cost + for d in self.get("items"): rate = self.get_bom_material_detail({'item_code': d.item_code, 'bom_no': d.bom_no, 'stock_qty': d.stock_qty})["rate"] @@ -176,7 +178,16 @@ class BOM(WebsiteGenerator): self.save() self.update_exploded_items() - frappe.msgprint(_("Cost Updated")) + # update parent BOMs + if self.total_cost != existing_bom_cost and update_parent: + parent_boms = frappe.db.sql_list("""select distinct parent from `tabBOM Item` + where bom_no = %s and docstatus=1""", self.name) + + for bom in parent_boms: + frappe.get_doc("BOM", bom).update_cost(from_child_bom=True) + + if not from_child_bom: + frappe.msgprint(_("Cost Updated")) def get_bom_unitcost(self, bom_no): bom = frappe.db.sql("""select name, total_cost/quantity as unit_cost from `tabBOM` @@ -566,4 +577,27 @@ def get_children(): where bom_item.parent=%s and bom_item.item_code = item.name order by bom_item.idx - """, frappe.form_dict.parent, as_dict=True) \ No newline at end of file + """, frappe.form_dict.parent, as_dict=True) + +def get_boms_in_bottom_up_order(bom_no=None): + def _get_parent(bom_no): + return frappe.db.sql_list("""select distinct parent from `tabBOM Item` + where bom_no = %s and docstatus=1""", bom_no) + + count = 0 + bom_list = [] + if bom_no: + bom_list.append(bom_no) + else: + # get all leaf BOMs + bom_list = frappe.db.sql_list("""select name from `tabBOM` bom where docstatus=1 + and not exists(select bom_no from `tabBOM Item` + where parent=bom.name and ifnull(bom_no, '')!='')""") + + while(count < len(bom_list)): + for child_bom in _get_parent(bom_list[count]): + if child_bom not in bom_list: + bom_list.append(child_bom) + count += 1 + + return bom_list \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/bom/test_bom.py b/erpnext/manufacturing/doctype/bom/test_bom.py index 4e520ef233..d678444e4d 100644 --- a/erpnext/manufacturing/doctype/bom/test_bom.py +++ b/erpnext/manufacturing/doctype/bom/test_bom.py @@ -6,6 +6,8 @@ from __future__ import unicode_literals import unittest import frappe from frappe.utils import cstr +from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation +from erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool import update_cost test_records = frappe.get_test_records('BOM') @@ -46,6 +48,32 @@ class TestBOM(unittest.TestCase): bom.save() self.assertTrue(_get_default_bom_in_item(), bom.name) + + def test_update_bom_cost_in_all_boms(self): + # get current rate for '_Test Item 2' + rm_rate = frappe.db.sql("""select rate from `tabBOM Item` + where parent='BOM-_Test Item Home Desktop Manufactured-001' + and item_code='_Test Item 2' and docstatus=1""") + rm_rate = rm_rate[0][0] if rm_rate else 0 + + # update valuation rate of item '_Test Item 2' + warehouse_list = frappe.db.sql_list("""select warehouse from `tabBin` + where item_code='_Test Item 2' and actual_qty > 0""") + + if not warehouse_list: + warehouse_list.append("_Test Warehouse - _TC") + + for warehouse in warehouse_list: + create_stock_reconciliation(item_code="_Test Item 2", warehouse=warehouse, + qty=200, rate=rm_rate + 10) + + # update cost of all BOMs based on latest valuation rate + update_cost() + # check if new valuation rate updated in all BOMs + for d in frappe.db.sql("""select rate from `tabBOM Item` + where item_code='_Test Item 2' and docstatus=1""", as_dict=1): + self.assertEqual(d.rate, rm_rate + 10) + def get_default_bom(item_code="_Test FG Item 2"): return frappe.db.get_value("BOM", {"item": item_code, "is_active": 1, "is_default": 1}) diff --git a/erpnext/manufacturing/doctype/bom_replace_tool/README.md b/erpnext/manufacturing/doctype/bom_replace_tool/README.md deleted file mode 100644 index 4abce74e85..0000000000 --- a/erpnext/manufacturing/doctype/bom_replace_tool/README.md +++ /dev/null @@ -1 +0,0 @@ -Tool to replace one Item with another in all Bill of Material (BOM) trees. \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/bom_replace_tool/bom_replace_tool.js b/erpnext/manufacturing/doctype/bom_replace_tool/bom_replace_tool.js deleted file mode 100644 index 8a3f70ce1d..0000000000 --- a/erpnext/manufacturing/doctype/bom_replace_tool/bom_replace_tool.js +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -// License: GNU General Public License v3. See license.txt - - -cur_frm.cscript.refresh = function(doc) { - cur_frm.disable_save(); -} - -cur_frm.set_query("current_bom", function(doc) { - return{ - query: "erpnext.controllers.queries.bom", - filters: {name: "!" + doc.new_bom} - } -}); - - -cur_frm.set_query("new_bom", function(doc) { - return{ - query: "erpnext.controllers.queries.bom", - filters: {name: "!" + doc.current_bom} - } -}); \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/bom_replace_tool/bom_replace_tool.json b/erpnext/manufacturing/doctype/bom_replace_tool/bom_replace_tool.json deleted file mode 100644 index bf7e6fc38d..0000000000 --- a/erpnext/manufacturing/doctype/bom_replace_tool/bom_replace_tool.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "allow_copy": 1, - "allow_import": 0, - "allow_rename": 0, - "creation": "2012-12-06 12:10:10", - "custom": 0, - "description": "Replace a particular BOM in all other BOMs where it is used. It will replace the old BOM link, update cost and regenerate \"BOM Explosion Item\" table as per new BOM", - "docstatus": 0, - "doctype": "DocType", - "document_type": "Other", - "fields": [ - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "description": "The BOM which will be replaced", - "fieldname": "current_bom", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Current BOM", - "no_copy": 0, - "options": "BOM", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "description": "The new BOM after replacement", - "fieldname": "new_bom", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "New BOM", - "no_copy": 0, - "options": "BOM", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "replace", - "fieldtype": "Button", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Replace", - "no_copy": 0, - "options": "replace_bom", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - } - ], - "hide_heading": 1, - "hide_toolbar": 1, - "icon": "fa fa-magic", - "idx": 1, - "in_create": 1, - "in_dialog": 0, - "is_submittable": 0, - "issingle": 1, - "istable": 0, - "modified": "2015-08-12 08:52:46.035343", - "modified_by": "Administrator", - "module": "Manufacturing", - "name": "BOM Replace Tool", - "owner": "Administrator", - "permissions": [ - { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 0, - "email": 0, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 0, - "read": 1, - "report": 0, - "role": "Manufacturing Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 1 - } - ], - "read_only": 1, - "read_only_onload": 0 -} \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/bom_replace_tool/__init__.py b/erpnext/manufacturing/doctype/bom_update_tool/__init__.py similarity index 100% rename from erpnext/manufacturing/doctype/bom_replace_tool/__init__.py rename to erpnext/manufacturing/doctype/bom_update_tool/__init__.py diff --git a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.js b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.js new file mode 100644 index 0000000000..a4b48af5a5 --- /dev/null +++ b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.js @@ -0,0 +1,34 @@ +// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('BOM Update Tool', { + setup: function(frm) { + frm.set_query("current_bom", function() { + return { + query: "erpnext.controllers.queries.bom", + filters: {name: "!" + frm.doc.new_bom} + }; + }); + + frm.set_query("new_bom", function() { + return { + query: "erpnext.controllers.queries.bom", + filters: {name: "!" + frm.doc.current_bom} + }; + }); + }, + + refresh: function(frm) { + frm.disable_save(); + }, + + update_latest_price_in_all_boms: function() { + frappe.call({ + method: "erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.enqueue_update_cost", + freeze: true, + callback: function() { + frappe.msgprint(__("Latest price updated in all BOMs")); + } + }); + } +}); \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.json b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.json new file mode 100644 index 0000000000..ab63c0b540 --- /dev/null +++ b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.json @@ -0,0 +1,244 @@ +{ + "allow_copy": 1, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "beta": 0, + "creation": "2012-12-06 12:10:10", + "custom": 0, + "description": "Replace a particular BOM in all other BOMs where it is used. It will replace the old BOM link, update cost and regenerate \"BOM Explosion Item\" table as per new BOM.\nIt also updates latest price in all the BOMs.", + "docstatus": 0, + "doctype": "DocType", + "document_type": "Other", + "editable_grid": 0, + "engine": "InnoDB", + "fields": [ + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "replace_bom_section", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Replace BOM", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "description": "The BOM which will be replaced", + "fieldname": "current_bom", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Current BOM", + "length": 0, + "no_copy": 0, + "options": "BOM", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "description": "The new BOM after replacement", + "fieldname": "new_bom", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "New BOM", + "length": 0, + "no_copy": 0, + "options": "BOM", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "replace", + "fieldtype": "Button", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Replace", + "length": 0, + "no_copy": 0, + "options": "replace_bom", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "update_cost_section", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Update Cost", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "update_latest_price_in_all_boms", + "fieldtype": "Button", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Update latest price in all BOMs", + "length": 0, + "no_copy": 0, + "options": "", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + } + ], + "has_web_view": 0, + "hide_heading": 1, + "hide_toolbar": 1, + "icon": "icon-magic", + "idx": 1, + "image_view": 0, + "in_create": 1, + "is_submittable": 0, + "issingle": 1, + "istable": 0, + "max_attachments": 0, + "modified": "2017-07-31 18:08:05.919276", + "modified_by": "Administrator", + "module": "Manufacturing", + "name": "BOM Update Tool", + "owner": "Administrator", + "permissions": [ + { + "amend": 0, + "apply_user_permissions": 0, + "cancel": 0, + "create": 1, + "delete": 0, + "email": 0, + "export": 0, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 0, + "read": 1, + "report": 0, + "role": "Manufacturing Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + } + ], + "quick_entry": 0, + "read_only": 1, + "read_only_onload": 0, + "show_name_in_global_search": 0, + "track_changes": 0, + "track_seen": 0 +} \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/bom_replace_tool/bom_replace_tool.py b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py similarity index 63% rename from erpnext/manufacturing/doctype/bom_replace_tool/bom_replace_tool.py rename to erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py index f0a834c37b..91b5070dbd 100644 --- a/erpnext/manufacturing/doctype/bom_replace_tool/bom_replace_tool.py +++ b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py @@ -1,14 +1,15 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt +# -*- coding: utf-8 -*- +# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt from __future__ import unicode_literals import frappe from frappe.utils import cstr, flt from frappe import _ - +from erpnext.manufacturing.doctype.bom.bom import get_boms_in_bottom_up_order from frappe.model.document import Document -class BOMReplaceTool(Document): +class BOMUpdateTool(Document): def replace_bom(self): self.validate_bom() self.update_new_bom() @@ -40,3 +41,17 @@ class BOMReplaceTool(Document): return [d[0] for d in frappe.db.sql("""select distinct parent from `tabBOM Item` where ifnull(bom_no, '') = %s and docstatus < 2""", self.new_bom)] + +@frappe.whitelist() +def enqueue_update_cost(): + frappe.enqueue("erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_cost") + frappe.msgprint(_("Queued for updating latest price in all Bill of Materials. It may take a few minutes.")) + +def update_latest_price_in_all_boms(): + if frappe.db.get_single_value("Manufacturing Settings", "update_bom_costs_automatically"): + update_cost() + +def update_cost(): + bom_list = get_boms_in_bottom_up_order() + for bom in bom_list: + frappe.get_doc("BOM", bom).update_cost(update_parent=False, from_child_bom=True) \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.js b/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.js new file mode 100644 index 0000000000..d220df2824 --- /dev/null +++ b/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.js @@ -0,0 +1,23 @@ +/* eslint-disable */ +// rename this file from _test_[name] to test_[name] to activate +// and remove above this line + +QUnit.test("test: BOM Update Tool", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially('BOM Update Tool', [ + // insert a new BOM Update Tool + () => frappe.tests.make([ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json index 9f12e4554a..455a983e76 100644 --- a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json +++ b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json @@ -1,23 +1,32 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 0, + "beta": 0, "creation": "2014-11-27 14:12:07.542534", "custom": 0, "docstatus": 0, "doctype": "DocType", "document_type": "Document", + "editable_grid": 0, + "engine": "InnoDB", "fields": [ { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "capacity_planning", "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Capacity Planning", "length": 0, "no_copy": 0, @@ -26,6 +35,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -33,16 +43,21 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "description": "Disables creation of time logs against Production Orders. Operations shall not be tracked against Production Order", "fieldname": "disable_capacity_planning", "fieldtype": "Check", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Disable Capacity Planning and Time Tracking", "length": 0, "no_copy": 0, @@ -51,6 +66,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -58,16 +74,21 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "description": "Plan time logs outside Workstation Working Hours.", "fieldname": "allow_overtime", "fieldtype": "Check", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Allow Overtime", "length": 0, "no_copy": 0, @@ -76,6 +97,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -83,16 +105,21 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "default": "", "fieldname": "allow_production_on_holidays", "fieldtype": "Check", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Allow Production on Holidays", "length": 0, "no_copy": 0, @@ -102,6 +129,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -109,15 +137,20 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "column_break_3", "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -125,6 +158,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -132,17 +166,22 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "default": "30", "description": "Try planning operations for X days in advance.", "fieldname": "capacity_planning_for_days", "fieldtype": "Int", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Capacity Planning For (Days)", "length": 0, "no_copy": 0, @@ -151,6 +190,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -158,16 +198,21 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "description": "Default 10 mins", "fieldname": "mins_between_operations", "fieldtype": "Int", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Time Between Operations (in mins)", "length": 0, "no_copy": 0, @@ -176,6 +221,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -183,15 +229,20 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "section_break_6", "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -199,6 +250,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -206,15 +258,20 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "over_production_allowance_percentage", "fieldtype": "Percent", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Over Production Allowance Percentage", "length": 0, "no_copy": 0, @@ -223,6 +280,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -230,16 +288,21 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "default": "BOM", "fieldname": "backflush_raw_materials_based_on", "fieldtype": "Select", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Backflush Raw Materials Based On", "length": 0, "no_copy": 0, @@ -249,6 +312,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -256,15 +320,22 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, - "fieldname": "column_break_11", - "fieldtype": "Column Break", + "columns": 0, + "description": "Update BOM cost automatically via Scheduler, based on latest valuation rate / price list rate / last purchase rate of raw materials.", + "fieldname": "update_bom_costs_automatically", + "fieldtype": "Check", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, + "label": "Update BOM Cost Automatically", "length": 0, "no_copy": 0, "permlevel": 0, @@ -272,6 +343,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -279,15 +351,49 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, + "fieldname": "column_break_11", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, "fieldname": "default_wip_warehouse", "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Default Work In Progress Warehouse", "length": 0, "no_copy": 0, @@ -297,6 +403,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -304,15 +411,20 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "default_fg_warehouse", "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Default Finished Goods Warehouse", "length": 0, "no_copy": 0, @@ -322,6 +434,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -329,18 +442,19 @@ "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, - "icon": "fa fa-wrench", + "icon": "icon-wrench", "idx": 0, + "image_view": 0, "in_create": 0, - "in_dialog": 0, "is_submittable": 0, "issingle": 1, "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2015-12-10 00:03:20.895790", + "modified": "2017-07-31 19:25:04.242693", "modified_by": "Administrator", "module": "Manufacturing", "name": "Manufacturing Settings", @@ -368,8 +482,12 @@ "write": 1 } ], + "quick_entry": 0, "read_only": 0, "read_only_onload": 0, + "show_name_in_global_search": 0, "sort_field": "modified", - "sort_order": "DESC" + "sort_order": "DESC", + "track_changes": 1, + "track_seen": 0 } \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/manufacturing_settings/test_manufacturing_settings.js b/erpnext/manufacturing/doctype/manufacturing_settings/test_manufacturing_settings.js new file mode 100644 index 0000000000..2b2589eddd --- /dev/null +++ b/erpnext/manufacturing/doctype/manufacturing_settings/test_manufacturing_settings.js @@ -0,0 +1,23 @@ +/* eslint-disable */ +// rename this file from _test_[name] to test_[name] to activate +// and remove above this line + +QUnit.test("test: Manufacturing Settings", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially('Manufacturing Settings', [ + // insert a new Manufacturing Settings + () => frappe.tests.make([ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/patches.txt b/erpnext/patches.txt index d781ec788f..8080bcdec1 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -432,4 +432,5 @@ erpnext.patches.v8_5.update_customer_group_in_POS_profile erpnext.patches.v8_6.update_timesheet_company_from_PO erpnext.patches.v8_6.set_write_permission_for_quotation_for_sales_manager erpnext.patches.v8_5.remove_project_type_property_setter -erpnext.patches.v8_7.add_more_gst_fields \ No newline at end of file +erpnext.patches.v8_7.add_more_gst_fields +erpnext.patches.v8_6.rename_bom_update_tool \ No newline at end of file diff --git a/erpnext/patches/v5_0/reset_values_in_tools.py b/erpnext/patches/v5_0/reset_values_in_tools.py index 5aac83eef2..fd970ba1b0 100644 --- a/erpnext/patches/v5_0/reset_values_in_tools.py +++ b/erpnext/patches/v5_0/reset_values_in_tools.py @@ -6,7 +6,7 @@ import frappe def execute(): for dt in ["Payment Tool", "Bank Reconciliation", "Payment Reconciliation", "Leave Control Panel", - "Salary Manager", "Upload Attenadance", "Production Planning Tool", "BOM Replace Tool", "Customize Form", - "Employee Attendance Tool", "Rename Tool", "BOM Replace Tool", "Process Payroll", "Naming Series"]: + "Salary Manager", "Upload Attenadance", "Production Planning Tool", "BOM Update Tool", "Customize Form", + "Employee Attendance Tool", "Rename Tool", "BOM Update Tool", "Process Payroll", "Naming Series"]: frappe.db.sql("delete from `tabSingles` where doctype=%s", dt) \ No newline at end of file diff --git a/erpnext/patches/v8_6/rename_bom_update_tool.py b/erpnext/patches/v8_6/rename_bom_update_tool.py new file mode 100644 index 0000000000..45a4ddc788 --- /dev/null +++ b/erpnext/patches/v8_6/rename_bom_update_tool.py @@ -0,0 +1,7 @@ +import frappe +def execute(): + frappe.delete_doc_if_exists("DocType", "BOM Replace Tool") + + frappe.reload_doctype("BOM") + frappe.db.sql("update tabBOM set conversion_rate=1 where conversion_rate is null or conversion_rate=0") + frappe.db.sql("update tabBOM set set_rate_of_sub_assembly_item_based_on_bom=1") \ No newline at end of file diff --git a/erpnext/public/js/help_links.js b/erpnext/public/js/help_links.js index 7de87b7964..d8af0e516d 100644 --- a/erpnext/public/js/help_links.js +++ b/erpnext/public/js/help_links.js @@ -508,8 +508,8 @@ frappe.help.help_links['Form/Production Planning Tool'] = [ { label: 'Production Planning Tool', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/tools/production-planning-tool' }, ] -frappe.help.help_links['Form/BOM Replace Tool'] = [ - { label: 'BOM Replace Tool', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/tools/bom-replace-tool' }, +frappe.help.help_links['Form/BOM Update Tool'] = [ + { label: 'BOM Update Tool', url: 'https://frappe.github.io/erpnext/user/manual/en/manufacturing/tools/bom-update-tool' }, ] //Customize From 52cc08dd2df39d8b64ac1a95b6861985ca7ac487 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 17 Aug 2017 14:37:33 +0530 Subject: [PATCH 43/52] Test case added for replacing BOM --- .../bom_update_tool/test_bom_update_tool.py | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py diff --git a/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py b/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py new file mode 100644 index 0000000000..b0851a6780 --- /dev/null +++ b/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py @@ -0,0 +1,25 @@ +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + + +from __future__ import unicode_literals +import unittest +import frappe + +test_records = frappe.get_test_records('BOM') + +class TestBOMUpdateTool(unittest.TestCase): + def test_replace_bom(self): + current_bom = "BOM-_Test Item Home Desktop Manufactured-001" + + bom_doc = frappe.copy_doc(test_records[0]) + bom_doc.items[1].item_code = "_Test Item" + bom_doc.insert() + + update_tool = frappe.get_doc("BOM Update Tool") + update_tool.current_bom = current_bom + update_tool.new_bom = bom_doc.name + update_tool.replace_bom() + + self.assertFalse(frappe.db.sql("select name from `tabBOM Item` where bom_no=%s", current_bom)) + self.assertTrue(frappe.db.sql("select name from `tabBOM Item` where bom_no=%s", bom_doc.name)) \ No newline at end of file From 6c6e45157bf223b59d62115ee172f26adb23c61f Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 17 Aug 2017 18:26:52 +0530 Subject: [PATCH 44/52] Fixed test case for replace bom --- .../doctype/bom_update_tool/test_bom_update_tool.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py b/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py index b0851a6780..154addf14e 100644 --- a/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py +++ b/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py @@ -22,4 +22,9 @@ class TestBOMUpdateTool(unittest.TestCase): update_tool.replace_bom() self.assertFalse(frappe.db.sql("select name from `tabBOM Item` where bom_no=%s", current_bom)) - self.assertTrue(frappe.db.sql("select name from `tabBOM Item` where bom_no=%s", bom_doc.name)) \ No newline at end of file + self.assertTrue(frappe.db.sql("select name from `tabBOM Item` where bom_no=%s", bom_doc.name)) + + # reverse, as it affects other testcases + update_tool.current_bom = bom_doc.name + update_tool.new_bom = current_bom + update_tool.replace_bom() \ No newline at end of file From 5cf3bdd593b9e9ad55511844027dfebd846b0117 Mon Sep 17 00:00:00 2001 From: Utkarsh Goswami Date: Tue, 22 Aug 2017 17:39:06 +0530 Subject: [PATCH 45/52] Travis fix for purchase order receipt (#10498) --- .../purchase_order/tests/test_purchase_order_receipt.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js index 407891d270..e77814d0f9 100644 --- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js @@ -67,8 +67,7 @@ QUnit.test("test: purchase order receipt", function(assert) { () => frappe.timeout(2), () => { assert.ok($('div.slick-cell.l2.r2 > a').text().includes('Test Product 1') - && $('div.slick-cell.l9.r9 > div').text().includes(5) - && $('div.slick-cell.l12.r12 > div').text().includes(433.29), "Stock ledger entry correct",$('div.slick-cell.l12.r12 > div').text()); + && $('div.slick-cell.l9.r9 > div').text().includes(5), "Stock ledger entry correct"); }, () => done() From a1637d83434f0e1f2c1e3321eb35351c22d1f7f0 Mon Sep 17 00:00:00 2001 From: Vishal Dhayagude Date: Tue, 22 Aug 2017 18:33:17 +0530 Subject: [PATCH 46/52] [UI Test] UI test for Sales Invoice with Payment Entry (#10483) * [UI Test] UI test for Sales Invoice with Payment Entry * Update test_purchase_order_receipt.js --- .../sales_invoice/tests/test_sales_invoice.js | 43 ++++++++++++++ .../tests/test_sales_invoice_with_payment.js | 56 +++++++++++++++++++ .../tests/test_purchase_order_receipt.js | 1 - erpnext/tests/ui/tests.txt | 3 +- 4 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice.js create mode 100644 erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_payment.js diff --git a/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice.js new file mode 100644 index 0000000000..35b255875e --- /dev/null +++ b/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice.js @@ -0,0 +1,43 @@ +QUnit.module('Sales Invoice'); + +QUnit.test("test sales Invoice", function(assert) { + assert.expect(4); + let done = assert.async(); + frappe.run_serially([ + () => { + return frappe.tests.make('Sales Invoice', [ + {customer: 'Test Customer 1'}, + {items: [ + [ + {'qty': 5}, + {'item_code': 'Test Product 1'}, + ] + ]}, + {update_stock:1}, + {customer_address: 'Test1-Billing'}, + {shipping_address_name: 'Test1-Shipping'}, + {contact_person: 'Contact 1-Test Customer 1'}, + {taxes_and_charges: 'TEST In State GST'}, + {tc_name: 'Test Term 1'}, + {terms: 'This is Test'} + ]); + }, + () => cur_frm.save(), + () => { + // get_item_details + assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct"); + // get tax details + assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST', "Tax details correct"); + // get tax account head details + assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct"); + // grand_total Calculated + assert.ok(cur_frm.doc.grand_total==590, "Grad Total correct"); + + }, + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.3), + () => done() + ]); +}); + diff --git a/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_payment.js b/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_payment.js new file mode 100644 index 0000000000..736443e260 --- /dev/null +++ b/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_payment.js @@ -0,0 +1,56 @@ +QUnit.module('Sales Invoice'); + +QUnit.test("test sales Invoice with payment", function(assert) { + assert.expect(4); + let done = assert.async(); + frappe.run_serially([ + () => { + return frappe.tests.make('Sales Invoice', [ + {customer: 'Test Customer 1'}, + {items: [ + [ + {'qty': 5}, + {'item_code': 'Test Product 1'}, + ] + ]}, + {update_stock:1}, + {customer_address: 'Test1-Billing'}, + {shipping_address_name: 'Test1-Shipping'}, + {contact_person: 'Contact 1-Test Customer 1'}, + {taxes_and_charges: 'TEST In State GST'}, + {tc_name: 'Test Term 1'}, + {terms: 'This is Test'} + ]); + }, + () => cur_frm.save(), + () => { + // get_item_details + assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct"); + // get tax details + assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST', "Tax details correct"); + // grand_total Calculated + assert.ok(cur_frm.doc.grand_total==590, "Grad Total correct"); + + }, + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => frappe.timeout(2), + () => frappe.tests.click_button('Close'), + () => frappe.tests.click_button('Make'), + () => frappe.tests.click_link('Payment'), + () => frappe.timeout(0.2), + () => { cur_frm.set_value('mode_of_payment','Cash');}, + () => { cur_frm.set_value('paid_to','Cash - '+frappe.get_abbr(frappe.defaults.get_default('Company')));}, + () => {cur_frm.set_value('reference_no','TEST1234');}, + () => {cur_frm.set_value('reference_date',frappe.datetime.add_days(frappe.datetime.nowdate(), 0));}, + () => cur_frm.save(), + () => { + // get payment details + assert.ok(cur_frm.doc.paid_amount==590, "Paid Amount Correct"); + }, + () => frappe.tests.click_button('Submit'), + () => frappe.tests.click_button('Yes'), + () => done() + ]); +}); + diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js index e77814d0f9..daf8d6c259 100644 --- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js @@ -69,7 +69,6 @@ QUnit.test("test: purchase order receipt", function(assert) { assert.ok($('div.slick-cell.l2.r2 > a').text().includes('Test Product 1') && $('div.slick-cell.l9.r9 > div').text().includes(5), "Stock ledger entry correct"); }, - () => done() ]); }); diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index ffdccfd006..cb33c90c1f 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -70,7 +70,8 @@ erpnext/buying/doctype/supplier/test_supplier.js erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_taxes_and_charges.js -erpnext/accounts/doctype/sales_invoice/test_sales_invoice.js +erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice.js +erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_payment.js erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.js erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_item_wise_discount.js erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js From a6a93cbe060476cc957585e295a688754d6af499 Mon Sep 17 00:00:00 2001 From: Doridel Cahanap Date: Tue, 22 Aug 2017 21:09:38 +0800 Subject: [PATCH 47/52] [Fix] Request for Quotation Portal Title (#10489) --- .../request_for_quotation/request_for_quotation.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py index d27d224d32..a775f5f345 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py @@ -195,8 +195,12 @@ def check_portal_enabled(reference_doctype): def get_list_context(context=None): from erpnext.controllers.website_list_for_contact import get_list_context list_context = get_list_context(context) - list_context["show_sidebar"] = True - list_context["title"] = "Request for Quotation" + list_context.update({ + 'show_sidebar': True, + 'show_search': True, + 'no_breadcrumbs': True, + 'title': _('Request for Quotation'), + }) return list_context def get_supplier_contacts(doctype, txt, searchfield, start, page_len, filters): From 382f5eb1b1d8c7987443d92194c86b61e5db2159 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 22 Aug 2017 19:06:21 +0530 Subject: [PATCH 48/52] Run sales/purchase register for one month by default (#10493) --- .../item_wise_purchase_register/item_wise_purchase_register.js | 2 +- .../report/item_wise_sales_register/item_wise_sales_register.js | 2 +- erpnext/accounts/report/purchase_register/purchase_register.js | 2 +- erpnext/accounts/report/sales_register/sales_register.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.js b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.js index 8d33524abb..46ed9dab39 100644 --- a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.js +++ b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.js @@ -7,7 +7,7 @@ frappe.query_reports["Item-wise Purchase Register"] = { "fieldname":"from_date", "label": __("From Date"), "fieldtype": "Date", - "default": frappe.defaults.get_user_default("year_start_date"), + "default": frappe.datetime.add_months(frappe.datetime.get_today(), -1), "width": "80" }, { diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js index 65cec518fe..b57a7fce9d 100644 --- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js +++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js @@ -7,7 +7,7 @@ frappe.query_reports["Item-wise Sales Register"] = frappe.query_reports["Sales R "fieldname":"from_date", "label": __("From Date"), "fieldtype": "Date", - "default": frappe.defaults.get_default("year_start_date"), + "default": frappe.datetime.add_months(frappe.datetime.get_today(), -1), "width": "80" }, { diff --git a/erpnext/accounts/report/purchase_register/purchase_register.js b/erpnext/accounts/report/purchase_register/purchase_register.js index cd795310da..42b35c2a99 100644 --- a/erpnext/accounts/report/purchase_register/purchase_register.js +++ b/erpnext/accounts/report/purchase_register/purchase_register.js @@ -7,7 +7,7 @@ frappe.query_reports["Purchase Register"] = { "fieldname":"from_date", "label": __("From Date"), "fieldtype": "Date", - "default": frappe.defaults.get_user_default("year_start_date"), + "default": frappe.datetime.add_months(frappe.datetime.get_today(), -1), "width": "80" }, { diff --git a/erpnext/accounts/report/sales_register/sales_register.js b/erpnext/accounts/report/sales_register/sales_register.js index 2ac4ae8b2a..0495976cf1 100644 --- a/erpnext/accounts/report/sales_register/sales_register.js +++ b/erpnext/accounts/report/sales_register/sales_register.js @@ -7,7 +7,7 @@ frappe.query_reports["Sales Register"] = { "fieldname":"from_date", "label": __("From Date"), "fieldtype": "Date", - "default": frappe.defaults.get_default("year_start_date"), + "default": frappe.datetime.add_months(frappe.datetime.get_today(), -1), "width": "80" }, { From 34c218b2de908fe05b4b0f785f34a7d875b921f7 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 22 Aug 2017 19:07:16 +0530 Subject: [PATCH 49/52] Minor improvements based on skip_transfer (#10457) --- .../manufacturing/doctype/production_order/production_order.js | 2 +- .../manufacturing/doctype/production_order/production_order.py | 3 ++- .../doctype/production_order_item/production_order_item.json | 3 ++- erpnext/stock/doctype/stock_entry/stock_entry.py | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/erpnext/manufacturing/doctype/production_order/production_order.js b/erpnext/manufacturing/doctype/production_order/production_order.js index c61eec620a..33acb41d4b 100644 --- a/erpnext/manufacturing/doctype/production_order/production_order.js +++ b/erpnext/manufacturing/doctype/production_order/production_order.js @@ -91,7 +91,7 @@ frappe.ui.form.on("Production Order", { frm.set_indicator_formatter('operation', function(doc) { return (frm.doc.qty==doc.completed_qty) ? "green" : "orange" }); }, - + refresh: function(frm) { erpnext.toggle_naming_series(); erpnext.production_order.set_custom_buttons(frm); diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py index 022e9f3d18..5fedc72889 100644 --- a/erpnext/manufacturing/doctype/production_order/production_order.py +++ b/erpnext/manufacturing/doctype/production_order/production_order.py @@ -523,7 +523,8 @@ def set_production_order_ops(name): @frappe.whitelist() def make_stock_entry(production_order_id, purpose, qty=None): production_order = frappe.get_doc("Production Order", production_order_id) - if not frappe.db.get_value("Warehouse", production_order.wip_warehouse, "is_group"): + if not frappe.db.get_value("Warehouse", production_order.wip_warehouse, "is_group") \ + and not production_order.skip_transfer: wip_warehouse = production_order.wip_warehouse else: wip_warehouse = None diff --git a/erpnext/manufacturing/doctype/production_order_item/production_order_item.json b/erpnext/manufacturing/doctype/production_order_item/production_order_item.json index 00e3adf13b..c0b1d009ba 100644 --- a/erpnext/manufacturing/doctype/production_order_item/production_order_item.json +++ b/erpnext/manufacturing/doctype/production_order_item/production_order_item.json @@ -229,6 +229,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "depends_on": "eval:!parent.skip_transfer", "fieldname": "transferred_qty", "fieldtype": "Float", "hidden": 0, @@ -353,7 +354,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-07-10 17:37:20.212361", + "modified": "2017-08-18 18:11:10.311736", "modified_by": "Administrator", "module": "Manufacturing", "name": "Production Order Item", diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 7c7e630f01..fbadbc54de 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -556,7 +556,7 @@ class StockEntry(StockController): item_dict = self.get_bom_raw_materials(self.fg_completed_qty) for item in item_dict.values(): - if self.pro_doc: + if self.pro_doc and not self.pro_doc.skip_transfer: item["from_warehouse"] = self.pro_doc.wip_warehouse item["to_warehouse"] = self.to_warehouse if self.purpose=="Subcontract" else "" From bb326f2bbd33f15ccbe74f89d7558595f2530502 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 22 Aug 2017 19:07:42 +0530 Subject: [PATCH 50/52] Chart of accounts for Taiwan (#10435) --- .../verified/tw_chart_of_accounts.json | 722 ++++++++++++++++++ erpnext/setup/doctype/company/test_company.py | 2 +- 2 files changed, 723 insertions(+), 1 deletion(-) create mode 100644 erpnext/accounts/doctype/account/chart_of_accounts/verified/tw_chart_of_accounts.json diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/tw_chart_of_accounts.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/tw_chart_of_accounts.json new file mode 100644 index 0000000000..a79283a40a --- /dev/null +++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/tw_chart_of_accounts.json @@ -0,0 +1,722 @@ +{ + "country_code": "tw", + "name": "Taiwan - Chart of Accounts", + "tree": { + "1-\u8cc7\u7522": { + "11~12-\u6d41\u52d5\u8cc7\u7522": { + "111-\u73fe\u91d1\u53ca\u7d04\u7576\u73fe\u91d1": { + "1111-\u5eab\u5b58\u73fe\u91d1": { + "account_type": "Cash" + }, + "1112-\u96f6\u7528\u91d1/\u9031\u8f49\u91d1": { + "account_type": "Cash" + }, + "1113-\u9280\u884c\u5b58\u6b3e": { + "account_type": "Bank", + "\u4e2d\u570b\u4fe1\u8a17": { + "account_type": "Bank" + }, + "\u53f0\u5317\u5bcc\u90a6": { + "account_type": "Bank" + } + }, + "1116-\u5728\u9014\u73fe\u91d1": { + "account_type": "Cash" + }, + "1117-\u7d04\u7576\u73fe\u91d1": { + "account_type": "Cash" + }, + "1118-\u5176\u4ed6\u73fe\u91d1\u53ca\u7d04\u7576\u73fe\u91d1": { + "account_type": "Cash" + }, + "account_type": "Cash" + }, + "112-\u77ed\u671f\u6295\u8cc7": { + "1121-\u77ed\u671f\u6295\u8cc7 \u2014\u80a1\u7968": {} + }, + "113-\u61c9\u6536\u7968\u64da": { + "1131-\u61c9\u6536\u7968\u64da": { + "account_type": "Receivable" + }, + "1132-\u61c9\u6536\u7968\u64da\u8cbc\u73fe ": { + "account_type": "Receivable" + }, + "1138-\u5176\u4ed6\u61c9\u6536\u7968\u64da ": { + "account_type": "Receivable" + }, + "1139-\u5099\u62b5\u5446\u5e33 \uff0d\u61c9\u6536\u7968\u64da ": { + "account_type": "Receivable" + }, + "account_type": "Receivable" + }, + "114-\u61c9\u6536\u5e33\u6b3e": { + "1141-\u61c9\u6536\u5e33\u6b3e ": { + "account_type": "Receivable" + }, + "1142-\u61c9\u6536\u5206\u671f\u5e33\u6b3e ": { + "account_type": "Receivable" + }, + "1149-\u5099\u62b5\u5446\u5e33 \uff0d\u61c9\u6536\u5e33\u6b3e ": { + "account_type": "Receivable" + }, + "account_type": "Receivable" + }, + "118-\u5176\u4ed6\u61c9\u6536\u6b3e": { + "1184-\u61c9\u6536\u6536\u76ca": { + "account_type": "Receivable" + }, + "1185-\u61c9\u6536\u9000\u7a05\u6b3e": { + "account_type": "Receivable" + }, + "1189-\u5099\u62b5\u5446\u5e33 \u2014 \u5176\u4ed6\u61c9\u6536\u6b3e ": { + "account_type": "Receivable" + }, + "account_type": "Receivable" + }, + "121~122-\u5b58\u8ca8": { + "1219-\u5099\u62b5\u5b58\u8ca8\u8dcc\u50f9\u640d\u5931": {}, + "1229-\u5099\u62b5\u5b58\u8ca8\u8dcc\u50f9\u640d\u5931": {}, + "account_type": "Stock", + "is_group": 1 + }, + "125-\u9810\u4ed8\u8cbb\u7528": { + "1251-\u9810\u4ed8\u85aa\u8cc7": {}, + "1252-\u9810\u4ed8\u79df\u91d1": {}, + "1253-\u9810\u4ed8\u4fdd\u96aa\u8cbb": {}, + "1254-\u7528\u54c1\u76e4\u5b58": {}, + "1255-\u9810\u4ed8\u6240\u5f97\u7a05": {}, + "1258-\u5176\u4ed6\u9810\u4ed8\u8cbb\u7528": {} + }, + "126-\u9810\u4ed8\u6b3e\u9805": { + "1261-\u9810\u4ed8\u8ca8\u6b3e": {}, + "1268-\u5176\u4ed6\u9810\u4ed8\u6b3e\u9805": {} + }, + "128~129-\u5176\u4ed6\u6d41\u52d5\u8cc7\u7522": { + "1281-\u9032\u9805\u7a05\u984d": {}, + "1282-\u7559\u62b5\u7a05\u984d": {}, + "1283-\u66ab\u4ed8\u6b3e": {}, + "1284-\u4ee3\u4ed8\u6b3e": {}, + "1285-\u54e1\u5de5\u501f\u652f": {} + } + }, + "13-\u57fa\u91d1\u53ca\u9577\u671f\u6295\u8cc7": { + "131-\u57fa\u91d1": { + "1311-\u511f\u50b5\u57fa\u91d1": {}, + "1313-\u610f\u5916\u640d\u5931\u6e96\u5099\u57fa\u91d1": {}, + "1314-\u9000\u4f11\u57fa\u91d1": {}, + "1318-\u5176\u4ed6\u57fa\u91d1": {} + }, + "132-\u9577\u671f\u6295\u8cc7": { + "1321-\u9577\u671f\u80a1\u6b0a\u6295\u8cc7": {}, + "1322-\u9577\u671f\u50b5\u5238\u6295\u8cc7": {}, + "1323-\u9577\u671f\u4e0d\u52d5\u7522\u6295\u8cc7": {}, + "1328-\u5176\u4ed6\u9577\u671f\u6295\u8cc7": {} + } + }, + "14~15-\u56fa\u5b9a\u8cc7\u7522": { + "141-\u571f\u5730": { + "1411-\u571f\u5730": { + "account_type": "Fixed Asset" + }, + "account_type": "Fixed Asset" + }, + "142-\u571f\u5730\u6539\u826f\u7269": { + "1421-\u571f\u5730\u6539\u826f\u7269": { + "account_type": "Fixed Asset" + }, + "account_type": "Fixed Asset" + }, + "143-\u623f\u5c4b\u53ca\u5efa\u7269": { + "1431-\u623f\u5c4b\u53ca\u5efa\u7269": { + "account_type": "Fixed Asset" + }, + "account_type": "Fixed Asset" + }, + "144~146-\u6a5f(\u5668)\u5177\u53ca\u8a2d\u5099": { + "1441-\u6a5f(\u5668)\u5177": { + "account_type": "Fixed Asset" + }, + "account_type": "Fixed Asset" + }, + "151-\u79df\u8cc3\u8cc7\u7522": { + "1511-\u79df\u8cc3\u8cc7\u7522": { + "account_type": "Fixed Asset" + }, + "account_type": "Fixed Asset" + }, + "152-\u79df\u8cc3\u6b0a\u76ca\u6539\u826f": { + "1521-\u79df\u8cc3\u6b0a\u76ca\u6539\u826f": { + "account_type": "Fixed Asset" + }, + "account_type": "Fixed Asset" + }, + "156-\u672a\u5b8c\u5de5\u7a0b\u53ca\u9810\u4ed8\u8cfc\u7f6e\u8a2d\u5099\u6b3e": { + "1561-\u672a\u5b8c\u5de5\u7a0b": { + "account_type": "Fixed Asset" + }, + "account_type": "Fixed Asset" + }, + "158-\u96dc\u9805\u56fa\u5b9a\u8cc7\u7522": { + "1581-\u96dc\u9805\u56fa\u5b9a\u8cc7\u7522": { + "account_type": "Fixed Asset" + }, + "account_type": "Fixed Asset" + }, + "account_type": "Fixed Asset" + }, + "16-\u905e\u8017\u8cc7\u7522": { + "161-\u905e\u8017\u8cc7\u7522": { + "is_group": 1 + } + }, + "17-\u7121\u5f62\u8cc7\u7522": { + "171-\u5546\u6a19\u6b0a": { + "1711-\u5546\u6a19\u6b0a": {} + }, + "172-\u5c08\u5229\u6b0a": { + "1721-\u5c08\u5229\u6b0a": {} + }, + "176-\u5546\u8b7d": { + "1761-\u5546\u8b7d": {} + }, + "177-\u958b\u8fa6\u8cbb": { + "1771-\u958b\u8fa6\u8cbb": {} + }, + "178-\u5176\u4ed6\u7121\u5f62\u8cc7\u7522": { + "1781-\u905e\u5ef6\u9000\u4f11\u91d1\u6210\u672c": {} + } + }, + "18-\u5176\u4ed6\u8cc7\u7522": { + "181-\u905e\u5ef6\u8cc7\u7522": { + "1811-\u50b5\u5238\u767c\u884c\u6210\u672c": {}, + "1812-\u9577\u671f\u9810\u4ed8\u79df\u91d1": {}, + "1813-\u9577\u671f\u9810\u4ed8\u4fdd\u96aa\u8cbb": {}, + "1814-\u905e\u5ef6\u6240\u5f97\u7a05\u8cc7\u7522": {}, + "1815-\u9810\u4ed8\u9000\u4f11\u91d1": {}, + "1818-\u5176\u4ed6\u905e\u5ef6\u8cc7\u7522": {} + }, + "182-\u9592\u7f6e\u8cc7\u7522": { + "1821-\u9592\u7f6e\u8cc7\u7522": {} + }, + "184-\u9577\u671f\u61c9\u6536\u7968\u64da\u53ca\u6b3e\u9805\u8207\u50ac\u6536\u5e33\u6b3e": { + "1841-\u9577\u671f\u61c9\u6536\u7968\u64da": { + "account_type": "Receivable" + }, + "1842-\u9577\u671f\u61c9\u6536\u5e33\u6b3e": { + "account_type": "Receivable" + }, + "1843-\u50ac\u6536\u5e33\u6b3e": { + "account_type": "Receivable" + }, + "1848-\u5176\u4ed6\u9577\u671f\u61c9\u6536\u6b3e\u9805": { + "account_type": "Receivable" + }, + "1849-\u5099\u62b5\u5446\u5e33\u2014\u9577\u671f\u61c9\u6536\u7968\u64da\u53ca\u6b3e\u9805\u8207\u50ac\u6536\u5e33\u6b3e": { + "account_type": "Receivable" + }, + "account_type": "Receivable" + }, + "185-\u51fa\u79df\u8cc7\u7522": { + "1851-\u51fa\u79df\u8cc7\u7522": {}, + "1858-\u51fa\u79df\u8cc7\u7522 \u2014\u91cd\u4f30\u589e\u503c": {}, + "1859-\u7d2f\u7a4d\u6298\u820a \u2014\u51fa\u79df\u8cc7\u7522": { + "account_type": "Accumulated Depreciation" + } + }, + "186-\u5b58\u51fa\u4fdd\u8b49\u91d1": { + "1861-\u5b58\u51fa\u4fdd\u8b49\u91d1": {} + }, + "188-\u96dc\u9805\u8cc7\u7522": { + "1881-\u53d7\u9650\u5236\u5b58\u6b3e": {}, + "1888-\u96dc\u9805\u8cc7\u7522 \u2014\u5176\u4ed6": {} + } + }, + "Temporary Accounts": { + "Temporary Opening": { + "account_type": "Temporary" + }, + "account_type": "Temporary" + }, + "root_type": "Asset" + }, + "2-\u8ca0\u50b5": { + "21~22-\u6d41\u52d5\u8ca0\u50b5": { + "211-\u77ed\u671f\u501f\u6b3e": { + "2111-\u9280\u884c\u900f\u652f": {}, + "2112-\u9280\u884c\u501f\u6b3e": {} + }, + "212-\u61c9\u4ed8\u77ed\u671f\u7968\u5238": { + "2121-\u61c9\u4ed8\u5546\u696d\u672c\u7968": { + "account_type": "Payable" + }, + "2122-\u9280\u884c\u627f\u514c\u532f\u7968": { + "account_type": "Payable" + }, + "account_type": "Payable" + }, + "213-\u61c9\u4ed8\u7968\u64da": { + "2131-\u61c9\u4ed8\u7968\u64da": { + "account_type": "Payable" + }, + "account_type": "Payable" + }, + "214-\u61c9\u4ed8\u5e33\u6b3e": { + "2141-\u61c9\u4ed8\u5e33\u6b3e": { + "account_type": "Payable" + }, + "account_type": "Payable" + }, + "216-\u61c9\u4ed8\u6240\u5f97\u7a05": { + "2161-\u61c9\u4ed8\u6240\u5f97\u7a05": { + "account_type": "Tax", + "tax_rate": 5.0 + }, + "account_type": "Tax", + "tax_rate": 5.0 + }, + "217-\u61c9\u4ed8\u8cbb\u7528": { + "2171-\u61c9\u4ed8\u85aa\u5de5": {}, + "2172-\u61c9\u4ed8\u79df\u91d1": {}, + "2173-\u61c9\u4ed8\u5229\u606f": {}, + "2174-\u61c9\u4ed8\u71df\u696d\u7a05": {}, + "2175-\u61c9\u4ed8\u7a05\u6350 \u2014\u5176\u4ed6": { + "account_type": "Tax", + "tax_rate": 5.0 + }, + "2178-\u5176\u4ed6\u61c9\u4ed8\u8cbb\u7528": {} + }, + "218~219-\u5176\u4ed6\u61c9\u4ed8\u6b3e": { + "2184-\u61c9\u4ed8\u571f\u5730\u623f\u5c4b\u6b3e": {}, + "2185-\u61c9\u4ed8\u8a2d\u5099\u6b3e": {}, + "2192-\u61c9\u4ed8\u80a1\u5229": {} + }, + "226-\u9810\u6536\u6b3e\u9805": { + "2261-\u9810\u6536\u8ca8\u6b3e": {}, + "2262-\u9810\u6536\u6536\u5165": {}, + "2268-\u5176\u4ed6\u9810\u6536\u6b3e": {} + }, + "227-\u4e00\u5e74\u6216\u4e00\u71df\u696d\u9031\u671f\u5167\u5230\u671f\u9577\u671f\u8ca0\u50b5": { + "is_group": 1 + }, + "228~229-\u5176\u4ed6\u6d41\u52d5\u8ca0\u50b5": { + "2281-\u92b7\u9805\u7a05\u984d": {}, + "2283-\u66ab\u6536\u6b3e ": {}, + "2284-\u4ee3\u6536\u6b3e": {}, + "2285-\u4f30\u8a08\u552e\u5f8c\u670d\u52d9/\u4fdd\u56fa\u8ca0\u50b5": {}, + "2291-\u905e\u5ef6\u6240\u5f97\u7a05\u8ca0\u50b5": {}, + "2292-\u905e\u5ef6\u514c\u63db\u5229\u76ca": {} + } + }, + "23-\u9577\u671f\u8ca0\u50b5": { + "231-\u61c9\u4ed8\u516c\u53f8\u50b5": { + "2311-\u61c9\u4ed8\u516c\u53f8\u50b5": {}, + "2319-\u61c9\u4ed8\u516c\u53f8\u50b5\u6ea2(\u6298)\u50f9": {} + }, + "232-\u9577\u671f\u501f\u6b3e": { + "2321-\u9577\u671f\u9280\u884c\u501f\u6b3e": {}, + "2324-\u9577\u671f\u501f\u6b3e \u2014\u696d\u4e3b": {}, + "2325-\u9577\u671f\u501f\u6b3e \u2014\u54e1\u5de5": {}, + "2327-\u9577\u671f\u501f\u6b3e \u2014\u95dc\u4fc2\u4eba": {}, + "2328-\u9577\u671f\u501f\u6b3e \u2014\u5176\u4ed6": {} + }, + "233-\u9577\u671f\u61c9\u4ed8\u7968\u64da\u53ca\u6b3e\u9805": { + "2331-\u9577\u671f\u61c9\u4ed8\u7968\u64da": { + "account_type": "Payable" + }, + "2332-\u9577\u671f\u61c9\u4ed8\u5e33\u6b3e": { + "account_type": "Payable" + }, + "2333-\u9577\u671f\u61c9\u4ed8\u79df\u8cc3\u8ca0\u50b5": { + "account_type": "Payable" + }, + "account_type": "Payable" + }, + "234-\u4f30\u8a08\u61c9\u4ed8\u571f\u5730\u589e\u503c\u7a05": { + "2341-\u4f30\u8a08\u61c9\u4ed8\u571f\u5730\u589e\u503c\u7a05": {} + }, + "235-\u61c9\u8a08\u9000\u4f11\u91d1\u8ca0\u50b5": { + "2351-\u61c9\u8a08\u9000\u4f11\u91d1\u8ca0\u50b5": {} + }, + "238-\u5176\u4ed6\u9577\u671f\u8ca0\u50b5": { + "2388-\u5176\u4ed6\u9577\u671f\u8ca0\u50b5\u2014\u5176\u4ed6": {} + } + }, + "28-\u5176\u4ed6\u8ca0\u50b5": { + "281-\u905e\u5ef6\u8ca0\u50b5": { + "2811-\u905e\u5ef6\u6536\u5165": {}, + "2814-\u905e\u5ef6\u6240\u5f97\u7a05\u8ca0\u50b5": {}, + "2818-\u5176\u4ed6\u905e\u5ef6\u8ca0\u50b5": {} + }, + "286-\u5b58\u5165\u4fdd\u8b49\u91d1": { + "2861-\u5b58\u5165\u4fdd\u8b49\u91d1": {} + }, + "288-\u96dc\u9805\u8ca0\u50b5": { + "2888-\u96dc\u9805\u8ca0\u50b5 \u2014\u5176\u4ed6": {} + } + }, + "Stock Received But Not Billed": { + "account_type": "Stock Received But Not Billed" + }, + "root_type": "Liability" + }, + "3-\u696d\u4e3b\u6b0a\u76ca": { + "31-\u8cc7\u672c": { + "311-\u8cc7\u672c\uff08\u80a1\u672c\uff09 ": { + "3111-\u666e\u901a\u80a1\u80a1\u672c": {}, + "3112-\u7279\u5225\u80a1\u80a1\u672c": {}, + "3113-\u9810\u6536\u80a1\u672c": {}, + "3114-\u5f85\u5206\u914d\u80a1\u7968\u80a1\u5229": {}, + "3115-\u8cc7\u672c": {} + } + }, + "32-\u8cc7\u672c\u516c\u7a4d": { + "321-\u80a1\u7968\u6ea2\u50f9": { + "3211-\u666e\u901a\u80a1\u80a1\u7968\u6ea2\u50f9": {}, + "3212-\u7279\u5225\u80a1\u80a1\u7968\u6ea2\u50f9": {} + }, + "323-\u8cc7\u7522\u91cd\u4f30\u589e\u503c\u6e96\u5099": { + "3231-\u8cc7\u7522\u91cd\u4f30\u589e\u503c\u6e96\u5099": {} + }, + "324-\u8655\u5206\u8cc7\u7522\u6ea2\u50f9\u516c\u7a4d": { + "3241-\u8655\u5206\u8cc7\u7522\u6ea2\u50f9\u516c\u7a4d": {} + }, + "325-\u5408\u4f75\u516c\u7a4d": { + "3251-\u5408\u4f75\u516c\u7a4d": {} + }, + "326-\u53d7\u8d08\u516c\u7a4d": { + "3261-\u53d7\u8d08\u516c\u7a4d": {} + }, + "328-\u5176\u4ed6\u8cc7\u672c\u516c\u7a4d": { + "3281-\u6b0a\u76ca\u6cd5\u9577\u671f\u80a1\u6b0a\u6295\u8cc7\u8cc7\u672c\u516c\u7a4d": {}, + "3282-\u8cc7\u672c\u516c\u7a4d\u2014 \u5eab\u85cf\u80a1\u7968\u4ea4\u6613": {} + } + }, + "33-\u4fdd\u7559\u76c8\u9918(\u7d2f\u7a4d\u8667\u640d)": { + "331-\u6cd5\u5b9a\u76c8\u9918\u516c\u7a4d": { + "3311-\u6cd5\u5b9a\u76c8\u9918\u516c\u7a4d": {} + }, + "332-\u7279\u5225\u76c8\u9918\u516c\u7a4d": { + "3321-\u610f\u5916\u640d\u5931\u6e96\u5099": {}, + "3322-\u6539\u826f\u64f4\u5145\u6e96\u5099": {}, + "3323-\u511f\u50b5\u6e96\u5099": {}, + "3328-\u5176\u4ed6\u7279\u5225\u76c8\u9918\u516c\u7a4d": {} + }, + "335-\u672a\u5206\u914d\u76c8\u9918(\u7d2f\u7a4d\u8667\u640d) ": { + "is_group": 1 + } + }, + "34-\u6b0a\u76ca\u8abf\u6574": { + "341-\u9577\u671f\u80a1\u6b0a\u6295\u8cc7\u672a\u5be6\u73fe\u8dcc\u50f9\u640d\u5931": { + "3411-\u9577\u671f\u80a1\u6b0a\u6295\u8cc7\u672a\u5be6\u73fe\u8dcc\u50f9\u640d\u5931": {} + }, + "342-\u7d2f\u7a4d\u63db\u7b97\u8abf\u6574\u6578": { + "3421-\u7d2f\u7a4d\u63db\u7b97\u8abf\u6574\u6578": {} + }, + "343-\u672a\u8a8d\u5217\u70ba\u9000\u4f11\u91d1\u6210\u672c\u4e4b\u6de8\u640d\u5931": { + "3431-\u672a\u8a8d\u5217\u70ba\u9000\u4f11\u91d1\u6210\u672c\u4e4b\u6de8\u640d\u5931": {} + } + }, + "35-\u5eab\u85cf\u80a1": { + "351-\u5eab\u85cf\u80a1": { + "3511-\u5eab\u85cf\u80a1": {} + } + }, + "36-\u5c11\u6578\u80a1\u6b0a": { + "361-\u5c11\u6578\u80a1\u6b0a": { + "3611-\u5c11\u6578\u80a1\u6b0a": {} + } + }, + "root_type": "Equity" + }, + "4-\u71df\u696d\u6536\u5165": { + "41-\u92b7\u8ca8\u6536\u5165": { + "411-\u92b7\u8ca8\u6536\u5165": { + "4111-\u92b7\u8ca8\u6536\u5165": {}, + "4112-\u5206\u671f\u4ed8\u6b3e\u92b7\u8ca8\u6536\u5165": {} + }, + "417-\u92b7\u8ca8\u9000\u56de": { + "4171-\u92b7\u8ca8\u9000\u56de": {} + }, + "419-\u92b7\u8ca8\u6298\u8b93": { + "4191-\u92b7\u8ca8\u6298\u8b93": {} + } + }, + "46-\u52de\u52d9\u6536\u5165": { + "461-\u52de\u52d9\u6536\u5165": { + "4611-\u52de\u52d9\u6536\u5165": {} + } + }, + "47-\u696d\u52d9\u6536\u5165": { + "471-\u696d\u52d9\u6536\u5165": { + "4711-\u696d\u52d9\u6536\u5165": {} + } + }, + "48-\u5176\u4ed6\u71df\u696d\u6536\u5165": { + "488-\u5176\u4ed6\u71df\u696d\u6536\u5165\u2014\u5176\u4ed6": { + "4888-\u5176\u4ed6\u71df\u696d\u6536\u5165\u2014\u5176\u4ed6": {} + } + }, + "root_type": "Income" + }, + "5-\u71df\u696d\u6210\u672c": { + "51-\u92b7\u8ca8\u6210\u672c": { + "511-\u92b7\u8ca8\u6210\u672c": { + "5111-\u92b7\u8ca8\u6210\u672c": { + "account_type": "Cost of Goods Sold" + }, + "5112-\u5206\u671f\u4ed8\u6b3e\u92b7\u8ca8\u6210\u672c": { + "account_type": "Cost of Goods Sold" + }, + "account_type": "Cost of Goods Sold" + }, + "512-\u9032\u8ca8": { + "5121-\u9032\u8ca8": {}, + "5122-\u9032\u8ca8\u8cbb\u7528": {}, + "5123-\u9032\u8ca8\u9000\u51fa": {}, + "5124-\u9032\u8ca8\u6298\u8b93": {} + }, + "513-\u9032\u6599": { + "5131-\u9032\u6599": {}, + "5132-\u9032\u6599\u8cbb\u7528": {}, + "5133-\u9032\u6599\u9000\u51fa": {}, + "5134-\u9032\u6599\u6298\u8b93": {} + }, + "514-\u76f4\u63a5\u4eba\u5de5": { + "5141-\u76f4\u63a5\u4eba\u5de5": {} + }, + "515~518-\u88fd\u9020\u8cbb\u7528": { + "5151-\u9593\u63a5\u4eba\u5de5": {}, + "5152-\u79df\u91d1\u652f\u51fa": {}, + "5153-\u6587\u5177\u7528\u54c1": {}, + "5154-\u65c5\u8cbb": {}, + "5155-\u904b\u8cbb": {}, + "5156-\u90f5\u96fb\u8cbb": {}, + "5157-\u4fee\u7e55\u8cbb": {}, + "5158-\u5305\u88dd\u8cbb": {}, + "5161-\u6c34\u96fb\u74e6\u65af\u8cbb": {}, + "5162-\u4fdd\u96aa\u8cbb": {}, + "5163-\u52a0\u5de5\u8cbb": {}, + "5166-\u7a05\u6350": { + "account_type": "Tax", + "tax_rate": 5.0 + }, + "5168-\u6298\u820a ": { + "account_type": "Depreciation" + }, + "5169-\u5404\u9805\u8017\u7aed\u53ca\u6524\u63d0": {}, + "5172-\u4f19\u98df\u8cbb": {}, + "5173-\u8077\u5de5\u798f\u5229": {}, + "5176-\u8a13\u7df4\u8cbb": {}, + "5177-\u9593\u63a5\u6750\u6599": {}, + "5188-\u5176\u4ed6\u88fd\u9020\u8cbb\u7528": {} + }, + "Expenses Included In Valuation": { + "account_type": "Expenses Included In Valuation" + }, + "account_type": "Cost of Goods Sold" + }, + "56-\u52de\u52d9\u6210\u672c\u88fd": { + "561-\u52de\u52d9\u6210\u672c": { + "5611-\u52de\u52d9\u6210\u672c": {} + } + }, + "57-\u696d\u52d9\u6210\u672c": { + "571-\u696d\u52d9\u6210\u672c": { + "5711-\u696d\u52d9\u6210\u672c": {} + } + }, + "58-\u5176\u4ed6\u71df\u696d\u6210\u672c": { + "588-\u5176\u4ed6\u71df\u696d\u6210\u672c\u2014\u5176\u4ed6 ": { + "5888-\u5176\u4ed6\u71df\u696d\u6210\u672c\u2014\u5176\u4ed6": {} + } + }, + "Stock Adjustment": { + "account_type": "Stock Adjustment" + }, + "root_type": "Expense" + }, + "6-\u71df\u696d\u8cbb\u7528": { + "61-\u63a8\u92b7\u8cbb\u7528": { + "615~618-\u63a8\u92b7\u8cbb\u7528": { + "6151-\u85aa\u8cc7\u652f\u51fa": {}, + "6152-\u79df\u91d1\u652f\u51fa": {}, + "6153-\u6587\u5177\u7528\u54c1": {}, + "6154-\u65c5\u8cbb": {}, + "6155-\u904b\u8cbb": {}, + "6156-\u90f5\u96fb\u8cbb": {}, + "6157-\u4fee\u7e55\u8cbb": {}, + "6159-\u5ee3\u544a\u8cbb": {}, + "6161-\u6c34\u96fb\u74e6\u65af\u8cbb": {}, + "6162-\u4fdd\u96aa\u8cbb": {}, + "6164-\u4ea4\u969b\u8cbb": {}, + "6165-\u6350\u8d08": {}, + "6166-\u7a05\u6350": { + "account_type": "Tax", + "tax_rate": 5.0 + }, + "6167-\u5446\u5e33\u640d\u5931": {}, + "6168-\u6298\u820a ": { + "account_type": "Depreciation" + }, + "6169-\u5404\u9805\u8017\u7aed\u53ca\u6524\u63d0": {}, + "6172-\u4f19\u98df\u8cbb": {}, + "6173-\u8077\u5de5\u798f\u5229": {}, + "6175-\u4f63\u91d1\u652f\u51fa": {}, + "6176-\u8a13\u7df4\u8cbb": {}, + "6188-\u5176\u4ed6\u63a8\u92b7\u8cbb\u7528": {} + } + }, + "62-\u7ba1\u7406\u53ca\u7e3d\u52d9\u8cbb\u7528": { + "625~628-\u7ba1\u7406\u53ca\u7e3d\u52d9\u8cbb\u7528": { + "6251-\u85aa\u8cc7\u652f\u51fa": {}, + "6252-\u79df\u91d1\u652f\u51fa": {}, + "6253-\u6587\u5177\u7528\u54c1": {}, + "6254-\u65c5\u8cbb": {}, + "6255-\u904b\u8cbb": {}, + "6256-\u90f5\u96fb\u8cbb": {}, + "6257-\u4fee\u7e55\u8cbb": {}, + "6259-\u5ee3\u544a\u8cbb": {}, + "6261-\u6c34\u96fb\u74e6\u65af\u8cbb": {}, + "6262-\u4fdd\u96aa\u8cbb": {}, + "6264-\u4ea4\u969b\u8cbb": {}, + "6265-\u6350\u8d08": {}, + "6266-\u7a05\u6350": { + "account_type": "Tax", + "tax_rate": 5.0 + }, + "6267-\u5446\u5e33\u640d\u5931": {}, + "6268-\u6298\u820a": { + "account_type": "Depreciation" + }, + "6269-\u5404\u9805\u8017\u7aed\u53ca\u6524\u63d0": {}, + "6271-\u5916\u92b7\u640d\u5931": {}, + "6272-\u4f19\u98df\u8cbb": {}, + "6273-\u8077\u5de5\u798f\u5229": {}, + "6274-\u7814\u7a76\u767c\u5c55\u8cbb\u7528": {}, + "6275-\u4f63\u91d1\u652f\u51fa": {}, + "6276-\u8a13\u7df4\u8cbb": {}, + "6278-\u52de\u52d9\u8cbb": {}, + "6288-\u5176\u4ed6\u7ba1\u7406\u53ca\u7e3d\u52d9\u8cbb\u7528": {} + } + }, + "63-\u7814\u7a76\u767c\u5c55\u8cbb\u7528": { + "635~638-\u7814\u7a76\u767c\u5c55\u8cbb\u7528": { + "6351-\u85aa\u8cc7\u652f\u51fa": {}, + "6352-\u79df\u91d1\u652f\u51fa": {}, + "6353-\u6587\u5177\u7528\u54c1": {}, + "6354-\u65c5\u8cbb": {}, + "6355-\u904b\u8cbb": {}, + "6356-\u90f5\u96fb\u8cbb": {}, + "6357-\u4fee\u7e55\u8cbb": {}, + "6361-\u6c34\u96fb\u74e6\u65af\u8cbb": {}, + "6362-\u4fdd\u96aa\u8cbb": {}, + "6364-\u4ea4\u969b\u8cbb": {}, + "6366-\u7a05\u6350": { + "account_type": "Tax", + "tax_rate": 5.0 + }, + "6368-\u6298\u820a": { + "account_type": "Depreciation" + }, + "6369-\u5404\u9805\u8017\u7aed\u53ca\u6524\u63d0": {}, + "6372-\u4f19\u98df\u8cbb": {}, + "6373-\u8077\u5de5\u798f\u5229": {}, + "6376-\u8a13\u7df4\u8cbb": {}, + "6378-\u5176\u4ed6\u7814\u7a76\u767c\u5c55\u8cbb\u7528": {} + } + }, + "root_type": "Expense" + }, + "7-\u71df\u696d\u5916\u6536\u5165\u53ca\u8cbb\u7528": { + "71~74-\u71df\u696d\u5916\u6536\u5165": { + "711-\u5229\u606f\u6536\u5165": { + "7111-\u5229\u606f\u6536\u5165": {} + }, + "712-\u6295\u8cc7\u6536\u76ca": { + "7121-\u6b0a\u76ca\u6cd5\u8a8d\u5217\u4e4b\u6295\u8cc7\u6536\u76ca": {}, + "7122-\u80a1\u5229\u6536\u5165": {}, + "7123-\u77ed\u671f\u6295\u8cc7\u5e02\u50f9\u56de\u5347\u5229\u76ca": {} + }, + "713-\u514c\u63db\u5229\u76ca": { + "7131-\u514c\u63db\u5229\u76ca": {} + }, + "714-\u8655\u5206\u6295\u8cc7\u6536\u76ca": { + "7141-\u8655\u5206\u6295\u8cc7\u6536\u76ca": {} + }, + "715-\u8655\u5206\u8cc7\u7522\u6ea2\u50f9\u6536\u5165": { + "7151-\u8655\u5206\u8cc7\u7522\u6ea2\u50f9\u6536\u5165": {} + }, + "748-\u5176\u4ed6\u71df\u696d\u5916\u6536\u5165": { + "7481-\u6350\u8d08\u6536\u5165": {}, + "7482-\u79df\u91d1\u6536\u5165": {}, + "7483-\u4f63\u91d1\u6536\u5165": {}, + "7484-\u51fa\u552e\u4e0b\u8173\u53ca\u5ee2\u6599\u6536\u5165": {}, + "7485-\u5b58\u8ca8\u76e4\u76c8": {}, + "7486-\u5b58\u8ca8\u8dcc\u50f9\u56de\u5347\u5229\u76ca": {}, + "7487-\u58de\u5e33\u8f49\u56de\u5229\u76ca": {}, + "7488-\u5176\u4ed6\u71df\u696d\u5916\u6536\u5165\u2014\u5176\u4ed6": {} + } + }, + "75~78-\u71df\u696d\u5916\u8cbb\u7528": { + "751-\u5229\u606f\u8cbb\u7528": { + "7511-\u5229\u606f\u8cbb\u7528": {} + }, + "752-\u6295\u8cc7\u640d\u5931": { + "7521-\u6b0a\u76ca\u6cd5\u8a8d\u5217\u4e4b\u6295\u8cc7\u640d\u5931": {}, + "7523-\u77ed\u671f\u6295\u8cc7\u672a\u5be6\u73fe\u8dcc\u50f9\u640d\u5931": {} + }, + "753-\u514c\u63db\u640d\u5931": { + "7531-\u514c\u63db\u640d\u5931": {} + }, + "754-\u8655\u5206\u6295\u8cc7\u640d\u5931": { + "7541-\u8655\u5206\u6295\u8cc7\u640d\u5931": {} + }, + "755-\u8655\u5206\u8cc7\u7522\u640d\u5931": { + "7551-\u8655\u5206\u8cc7\u7522\u640d\u5931 ": {} + }, + "788-\u5176\u4ed6\u71df\u696d\u5916\u8cbb\u7528": { + "7881-\u505c\u5de5\u640d\u5931": {}, + "7882-\u707d\u5bb3\u640d\u5931": {}, + "7885-\u5b58\u8ca8\u76e4\u640d": {}, + "7886-\u5b58\u8ca8\u8dcc\u50f9\u53ca\u5446\u6eef\u640d\u5931": {}, + "7888-\u5176\u4ed6\u71df\u696d\u5916\u8cbb\u7528\u2014\u5176\u4ed6": {} + } + }, + "root_type": "Income" + }, + "8-\u6240\u5f97\u7a05\u8cbb\u7528(\u5229\u76ca)": { + "81-\u6240\u5f97\u7a05\u8cbb\u7528(\u5229\u76ca)": { + "811-\u6240\u5f97\u7a05\u8cbb\u7528(\u5229\u76ca) ": { + "8111-\u6240\u5f97\u7a05\u8cbb\u7528(\u5229\u76ca) ": {} + } + }, + "root_type": "Expense" + }, + "9-\u975e\u7d93\u5e38\u71df\u696d\u640d\u76ca": { + "91-\u505c\u696d\u90e8\u9580\u640d\u76ca": { + "911-\u505c\u696d\u90e8\u9580\u640d\u76ca\u2014\u505c\u696d\u524d\u71df\u696d\u640d\u76ca": { + "9111-\u505c\u696d\u90e8\u9580\u640d\u76ca\u2014\u505c\u696d\u524d\u71df\u696d\u640d\u76ca": {} + }, + "912-\u505c\u696d\u90e8\u9580\u640d\u76ca\u2014\u8655\u5206\u640d\u76ca": { + "9121-\u505c\u696d\u90e8\u9580\u640d\u76ca\u2014\u8655\u5206\u640d\u76ca": {} + } + }, + "92-\u975e\u5e38\u640d\u76ca": { + "921-\u975e\u5e38\u640d\u76ca": { + "9211-\u975e\u5e38\u640d\u76ca": {} + } + }, + "93-\u6703\u8a08\u539f\u5247\u8b8a\u52d5\u7d2f\u7a4d\u5f71\u97ff\u6578": { + "931-\u6703\u8a08\u539f\u5247\u8b8a\u52d5\u7d2f\u7a4d\u5f71\u97ff\u6578": { + "9311-\u6703\u8a08\u539f\u5247\u8b8a\u52d5\u7d2f\u7a4d\u5f71\u97ff\u6578": {} + } + }, + "94-\u5c11\u6578\u80a1\u6b0a\u6de8\u5229": { + "941-\u5c11\u6578\u80a1\u6b0a\u6de8\u5229": { + "9411-\u5c11\u6578\u80a1\u6b0a\u6de8\u5229": {} + } + }, + "root_type": "Expense" + } + } +} \ No newline at end of file diff --git a/erpnext/setup/doctype/company/test_company.py b/erpnext/setup/doctype/company/test_company.py index adbc5985f6..a5afbdb450 100644 --- a/erpnext/setup/doctype/company/test_company.py +++ b/erpnext/setup/doctype/company/test_company.py @@ -47,7 +47,7 @@ class TestCompany(unittest.TestCase): def test_coa_based_on_country_template(self): countries = ["India", "Brazil", "United Arab Emirates", "Canada", "Germany", "France", "Guatemala", "Indonesia", "Mexico", "Nicaragua", "Netherlands", "Singapore", - "Brazil", "Argentina", "Hungary"] + "Brazil", "Argentina", "Hungary", "Taiwan"] for country in countries: templates = get_charts_for_country(country) From dd8c0febd5c85c689805f9c0abd7f70ed5eee76e Mon Sep 17 00:00:00 2001 From: Makarand Bauskar Date: Wed, 23 Aug 2017 13:17:37 +0530 Subject: [PATCH 51/52] [minor] changed the modified date for bom for rename_bom_update_tool patch (#10509) --- erpnext/manufacturing/doctype/bom/bom.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.json b/erpnext/manufacturing/doctype/bom/bom.json index 886c9428e9..46a1ffd101 100644 --- a/erpnext/manufacturing/doctype/bom/bom.json +++ b/erpnext/manufacturing/doctype/bom/bom.json @@ -1671,7 +1671,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-08-11 14:09:30.492628", + "modified": "2017-08-23 14:09:30.492628", "modified_by": "Administrator", "module": "Manufacturing", "name": "BOM", From c0f34f454b9a96975b7e0ba41e25ed3594c692ec Mon Sep 17 00:00:00 2001 From: mbauskar Date: Tue, 29 Aug 2017 21:08:21 +0600 Subject: [PATCH 52/52] bumped to version 8.10.0 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 48296e7e33..cf6ca02e7f 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -4,7 +4,7 @@ import inspect import frappe from erpnext.hooks import regional_overrides -__version__ = '8.9.2' +__version__ = '8.10.0' def get_default_company(user=None): '''Get default company for user'''