diff --git a/.travis.yml b/.travis.yml index 03e75b6897d..b74289f70c3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,6 @@ language: python dist: trusty -addons: - apt: - sources: - - google-chrome - packages: - - google-chrome-stable - python: - "2.7" @@ -31,15 +24,6 @@ install: - cp -r $TRAVIS_BUILD_DIR/test_sites/test_site ~/frappe-bench/sites/ before_script: - - wget http://chromedriver.storage.googleapis.com/2.33/chromedriver_linux64.zip - - unzip chromedriver_linux64.zip - - sudo apt-get install libnss3 - - sudo apt-get --only-upgrade install google-chrome-stable - - sudo cp chromedriver /usr/local/bin/. - - sudo chmod +x /usr/local/bin/chromedriver - - export DISPLAY=:99.0 - - sh -e /etc/init.d/xvfb start - - sleep 3 - mysql -u root -ptravis -e 'create database test_frappe' - echo "USE mysql;\nCREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe';\nFLUSH PRIVILEGES;\n" | mysql -u root -ptravis - echo "USE mysql;\nGRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost';\n" | mysql -u root -ptravis @@ -60,24 +44,6 @@ jobs: - set -e - bench run-tests env: Server Side Test - - # stage - script: - - bench --verbose run-setup-wizard-ui-test - - bench execute erpnext.setup.utils.enable_all_roles_and_domains - - bench run-ui-tests --app erpnext - env: Client Side Test - - # stage - script: - - bench --verbose run-setup-wizard-ui-test - - bench execute erpnext.setup.utils.enable_all_roles_and_domains - - bench run-ui-tests --app erpnext --test-list erpnext/tests/ui/tests2.txt - env: Client Side Test - 2 - - # stage - script: - - bench --verbose run-setup-wizard-ui-test - - bench execute erpnext.setup.utils.enable_all_roles_and_domains - - bench run-ui-tests --app erpnext --test-list erpnext/tests/ui/agriculture.txt - env: Agriculture Client Side Test - # stage script: - wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 1b88bdc5b9b..96ad60f866f 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '10.0.17' +__version__ = '10.0.18' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 266e3e13fb7..2a0c553a366 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -224,12 +224,17 @@ class SalesInvoice(SellingController): from erpnext.selling.doctype.customer.customer import check_credit_limit validate_against_credit_limit = False + bypass_credit_limit_check_at_sales_order = cint(frappe.db.get_value("Customer", self.customer, + "bypass_credit_limit_check_at_sales_order")) + if bypass_credit_limit_check_at_sales_order: + validate_against_credit_limit = True + for d in self.get("items"): if not (d.sales_order or d.delivery_note): validate_against_credit_limit = True break if validate_against_credit_limit: - check_credit_limit(self.customer, self.company) + check_credit_limit(self.customer, self.company, bypass_credit_limit_check_at_sales_order) def set_missing_values(self, for_validate=False): pos = self.set_pos_fields(for_validate) @@ -242,7 +247,10 @@ class SalesInvoice(SellingController): super(SalesInvoice, self).set_missing_values(for_validate) if pos: - return {"print_format": pos.get("print_format_for_online") } + return { + "print_format": pos.get("print_format_for_online"), + "allow_edit_rate": pos.get("allow_user_to_edit_rate") + } def update_time_sheet(self, sales_invoice): for d in self.timesheets: diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.py b/erpnext/accounts/doctype/tax_rule/tax_rule.py index 9c091e8c9d6..2e92e054586 100644 --- a/erpnext/accounts/doctype/tax_rule/tax_rule.py +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.py @@ -130,8 +130,8 @@ def get_party_details(party, party_type, args=None): def get_tax_template(posting_date, args): """Get matching tax rule""" args = frappe._dict(args) - conditions = ["""(from_date is null or from_date = '' or from_date <= '{0}') - and (to_date is null or to_date = '' or to_date >= '{0}')""".format(posting_date)] + conditions = ["""(from_date is null or from_date <= '{0}') + and (to_date is null or to_date >= '{0}')""".format(posting_date)] for key, value in args.iteritems(): if key=="use_for_shopping_cart": diff --git a/erpnext/buying/doctype/supplier/test_records.json b/erpnext/buying/doctype/supplier/test_records.json index 370ce8dad16..2536721326b 100644 --- a/erpnext/buying/doctype/supplier/test_records.json +++ b/erpnext/buying/doctype/supplier/test_records.json @@ -8,7 +8,7 @@ { "doctype": "Supplier", "supplier_name": "_Test Supplier P", - "supplier_type": "_Test Supplier Type", + "supplier_type": "_Test Supplier Type" }, { "doctype": "Supplier", diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index 158aac0c1bc..fd7bdc7bc42 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -257,7 +257,7 @@ def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len, def get_batch_no(doctype, txt, searchfield, start, page_len, filters): cond = "" if filters.get("posting_date"): - cond = "and (ifnull(batch.expiry_date, '')='' or batch.expiry_date >= %(posting_date)s)" + cond = "and (batch.expiry_date is null or batch.expiry_date >= %(posting_date)s)" batch_nos = None args = { diff --git a/erpnext/docs/assets/img/education/student/student group.gif b/erpnext/docs/assets/img/education/student/student-group.gif similarity index 100% rename from erpnext/docs/assets/img/education/student/student group.gif rename to erpnext/docs/assets/img/education/student/student-group.gif diff --git a/erpnext/docs/user/manual/en/education/Assessment/assessment_criteria.md b/erpnext/docs/user/manual/en/education/Assessment/assessment_criteria.md index b97cfb12596..64183ad8beb 100644 --- a/erpnext/docs/user/manual/en/education/Assessment/assessment_criteria.md +++ b/erpnext/docs/user/manual/en/education/Assessment/assessment_criteria.md @@ -10,4 +10,17 @@ Assessment Criteria is be used when scheduling Assessment Plan for Student Group Assessment Plan Criteria +#### Video Tutorial on Assessment Criteria + + + +
+ +
+ +
+
+ {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/education/Assessment/assessment_criteria_group.md b/erpnext/docs/user/manual/en/education/Assessment/assessment_criteria_group.md deleted file mode 100644 index 4287ca86179..00000000000 --- a/erpnext/docs/user/manual/en/education/Assessment/assessment_criteria_group.md +++ /dev/null @@ -1 +0,0 @@ -# \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/education/Assessment/assessment_group.md b/erpnext/docs/user/manual/en/education/Assessment/assessment_group.md index ed02a5366dd..35e00ad3d58 100644 --- a/erpnext/docs/user/manual/en/education/Assessment/assessment_group.md +++ b/erpnext/docs/user/manual/en/education/Assessment/assessment_group.md @@ -10,4 +10,17 @@ On the same lines, you can also define multiple Assessment Group bases on assess Assessment Group Term +#### Video Tutorial on Assessment Group + + + +
+ +
+ +
+
+ {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/education/Assessment/assessment_plan.md b/erpnext/docs/user/manual/en/education/Assessment/assessment_plan.md index 7272279c9b5..8e085355143 100644 --- a/erpnext/docs/user/manual/en/education/Assessment/assessment_plan.md +++ b/erpnext/docs/user/manual/en/education/Assessment/assessment_plan.md @@ -16,4 +16,17 @@ To schedule an assessment/examination for a Student Group, for specific Course, Assessment Plan Criteria +#### Video Tutorial on Assessment Plan + + + +
+ +
+ +
+
+ {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/education/Assessment/assessment_result.md b/erpnext/docs/user/manual/en/education/Assessment/assessment_result.md index ed3e5fb3344..5547f2247b3 100644 --- a/erpnext/docs/user/manual/en/education/Assessment/assessment_result.md +++ b/erpnext/docs/user/manual/en/education/Assessment/assessment_result.md @@ -4,4 +4,16 @@ Assessment Result is a log of marks/grades earned by the student for specific As Assessment Result +#### Video Tutorial on Assessment Result + + +
+ +
+ +
+
+ {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/education/Assessment/assessment_result_tool.md b/erpnext/docs/user/manual/en/education/Assessment/assessment_result_tool.md index 88b7a7a078e..1cd0762faab 100644 --- a/erpnext/docs/user/manual/en/education/Assessment/assessment_result_tool.md +++ b/erpnext/docs/user/manual/en/education/Assessment/assessment_result_tool.md @@ -6,4 +6,17 @@ Assessment Result Tool help you entering marks earned by the Students for specif As you go on entering marks for a Student, and switch to next student, in the backend, Student Result record will be auto-created for that Student. +#### Video Tutorial on Assessment Result Tool + + + +
+ +
+ +
+
+ {next} diff --git a/erpnext/docs/user/manual/en/education/Assessment/grading_scale.md b/erpnext/docs/user/manual/en/education/Assessment/grading_scale.md index 0ad610b6331..c3d8b2127ae 100644 --- a/erpnext/docs/user/manual/en/education/Assessment/grading_scale.md +++ b/erpnext/docs/user/manual/en/education/Assessment/grading_scale.md @@ -4,4 +4,17 @@ In the Grading Scale, you can define various grades and threshold for them. Base Grading Scale +#### Video Tutorial on Grading Scale + + + +
+ +
+ +
+
+ {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/education/Attendance/index.txt b/erpnext/docs/user/manual/en/education/Attendance/index.txt index 8cd02627a20..14ecda38148 100644 --- a/erpnext/docs/user/manual/en/education/Attendance/index.txt +++ b/erpnext/docs/user/manual/en/education/Attendance/index.txt @@ -1,3 +1,3 @@ student-attendance -student-leave-application -student-attendance-tool \ No newline at end of file +student-attendance-tool +student-leave-application \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/education/Attendance/student-attendance-tool.md b/erpnext/docs/user/manual/en/education/Attendance/student-attendance-tool.md index fac9d6e69d8..c68f473db06 100644 --- a/erpnext/docs/user/manual/en/education/Attendance/student-attendance-tool.md +++ b/erpnext/docs/user/manual/en/education/Attendance/student-attendance-tool.md @@ -12,4 +12,17 @@ Student detials will be autofetched and you can mark the attendance of the given Student Attendance +#### Tutorial Video for Student Attendance Tool + + + +
+ +
+ +
+
+ {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/education/Attendance/student-attendance.md b/erpnext/docs/user/manual/en/education/Attendance/student-attendance.md index 4be2831f309..b93114607e9 100644 --- a/erpnext/docs/user/manual/en/education/Attendance/student-attendance.md +++ b/erpnext/docs/user/manual/en/education/Attendance/student-attendance.md @@ -12,4 +12,17 @@ Select the **Student, Course Schedule and Student Group** for which attendance i **Student Attendance tool** can be used for bulk updation of the attendance based on **Batch, Course or Activity**. +#### Tutorial Video on Student Attendance + + + +
+ +
+ +
+
+ {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/education/Attendance/student-leave-application.md b/erpnext/docs/user/manual/en/education/Attendance/student-leave-application.md index e22c6e9d688..011d07c94cc 100644 --- a/erpnext/docs/user/manual/en/education/Attendance/student-leave-application.md +++ b/erpnext/docs/user/manual/en/education/Attendance/student-leave-application.md @@ -10,4 +10,17 @@ Incase the student is not attending the institute in order to participate or rep Once a Leave Application is recorded for a student it will not be recorded in the absent student report as he has applied for a leave. +#### Tutorial Video for Student Leave Application + + + +
+ +
+ +
+
+ {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/education/admission/program-enrollment-tool.md b/erpnext/docs/user/manual/en/education/admission/program-enrollment-tool.md index 97a26c73ceb..5727bc230b8 100644 --- a/erpnext/docs/user/manual/en/education/admission/program-enrollment-tool.md +++ b/erpnext/docs/user/manual/en/education/admission/program-enrollment-tool.md @@ -18,4 +18,16 @@ You can create the Program Enrollment for : For promoting the students, the new academic year, academic term and program can also be selected for the enrollment of the fetched students list. +#### Video Tutorial for Program Enrollment Tool + + +
+ +
+ +
+
+ {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/education/admission/program-enrollment.md b/erpnext/docs/user/manual/en/education/admission/program-enrollment.md index 6fe9692a893..36af3f263eb 100644 --- a/erpnext/docs/user/manual/en/education/admission/program-enrollment.md +++ b/erpnext/docs/user/manual/en/education/admission/program-enrollment.md @@ -17,5 +17,15 @@ Student Batch: To categorize student into different sections/batches, you can as Student Category: For the Institutions having multiple Fees Structure, this field can be used to differentiate the student enrollment in a given fee category. +#### Video Tutorial For Program Enrollment -{next} \ No newline at end of file + +
+ +
+ +
+
+ +{next} diff --git a/erpnext/docs/user/manual/en/education/admission/student-applicant.md b/erpnext/docs/user/manual/en/education/admission/student-applicant.md index 121844cf9a5..fa1b4c2c75b 100644 --- a/erpnext/docs/user/manual/en/education/admission/student-applicant.md +++ b/erpnext/docs/user/manual/en/education/admission/student-applicant.md @@ -27,4 +27,16 @@ the system shall create a student against that applicant and redirect you to the Student Applicant Enrollment +#### Video Tutorial for Student Application + + + +
+ +
+ +
+
+ {next} diff --git a/erpnext/docs/user/manual/en/education/fees/fee-structure.md b/erpnext/docs/user/manual/en/education/fees/fee-structure.md index 2131c4afed9..76d43a47830 100644 --- a/erpnext/docs/user/manual/en/education/fees/fee-structure.md +++ b/erpnext/docs/user/manual/en/education/fees/fee-structure.md @@ -20,4 +20,16 @@ You can set the "Income Account" and "Receivable Account" in the Accounts sectio If you are going to use this in the Fee Schedule, you must select the Accounts carefully as Fee Schedule updates the respected Accounts in bulk. +#### Video Tutorial for Fee Structure + + +
+ +
+ +
+
+ {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/education/schedule/course-schedule.md b/erpnext/docs/user/manual/en/education/schedule/course-schedule.md index f5134d59fff..8b8a36eb151 100644 --- a/erpnext/docs/user/manual/en/education/schedule/course-schedule.md +++ b/erpnext/docs/user/manual/en/education/schedule/course-schedule.md @@ -5,6 +5,18 @@ You can see the overall course schedule in the Calendar view. Course Schedule +#### Video Tutorial on Course Scheduling + + +
+ +
+ +
+
+ ### Marking Attendance You can mark attendance for a Student Group against a Course Schedule. diff --git a/erpnext/docs/user/manual/en/education/schedule/scheduling-tool.md b/erpnext/docs/user/manual/en/education/schedule/scheduling-tool.md index 08a7fa9ec0c..087c933fe3b 100644 --- a/erpnext/docs/user/manual/en/education/schedule/scheduling-tool.md +++ b/erpnext/docs/user/manual/en/education/schedule/scheduling-tool.md @@ -20,4 +20,14 @@ This tool can be used to create 'Course Schedules'. - Check the 'Reschedule' checkbox and then click 'Schedule Course' button. - System will delete existing Course Schedules for specified Course within the mentioned Course Start Date and Course End Date and crate new Course Schedules. +#### Video Tutorial on Scheduling Tool + +
+ +
+ +
+
+ {next} diff --git a/erpnext/docs/user/manual/en/education/setup/course.md b/erpnext/docs/user/manual/en/education/setup/course.md index 0d6e5ac5eb7..ec7d813056d 100644 --- a/erpnext/docs/user/manual/en/education/setup/course.md +++ b/erpnext/docs/user/manual/en/education/setup/course.md @@ -12,4 +12,18 @@ Once a **Course** is created, a course schedule can defined for the same. The Course form is further linked to **Program, Student Group and Assessment Plan** doctypes. The links allow to view/create the related documents for a **Course**. +#### Video Tutorial for Course + + + +
+ +
+ +
+
+ + {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/education/setup/instructor.md b/erpnext/docs/user/manual/en/education/setup/instructor.md index 219413d275e..5af4cc098e0 100644 --- a/erpnext/docs/user/manual/en/education/setup/instructor.md +++ b/erpnext/docs/user/manual/en/education/setup/instructor.md @@ -16,5 +16,16 @@ While creating the **Assessment Plan** for a Student Group, **Instructor** can b Further, the log for the Instructor can be entered in the Instructor Log table which can be used for keeping the records of subjects taught by that Instructor. +#### Video Tutorial for Instructor + + +
+ +
+ +
+
{next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/education/setup/program.md b/erpnext/docs/user/manual/en/education/setup/program.md index 25e390eb87b..0d2a4d2994c 100644 --- a/erpnext/docs/user/manual/en/education/setup/program.md +++ b/erpnext/docs/user/manual/en/education/setup/program.md @@ -4,7 +4,7 @@ An educational program is a program written by the institutions which determines To create a Program go to : -###education >> Setup >> Program >> New Program +> Education > Setup > Program > New Program Enter a unique code for every **Program**. You can also link the **Program** to the department under which it is conducted. @@ -16,4 +16,16 @@ Add the relevant Course and the Fee details for a program. The Program Doctype is further linked to the **Student applicant**, **Program enrollment, Student group, Fee structre and Fee**. The links allow to view or create the related document for a Program. +#### Video Tutorial on Program and Courses + + +
+ +
+ +
+
+ {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/education/setup/school-settings.md b/erpnext/docs/user/manual/en/education/setup/school-settings.md index 44f9c44ed11..74e5ed561fc 100644 --- a/erpnext/docs/user/manual/en/education/setup/school-settings.md +++ b/erpnext/docs/user/manual/en/education/setup/school-settings.md @@ -2,7 +2,7 @@ The Education Settings page allow you to setup basic settings like **Academic Year and Term** for the educational setup. -Student +Student The checkbox to Validate Batch for Students in Student Group enables the Student Batch validation for every Student from the Program Enrollment for the **Batch** based on **Student Group** diff --git a/erpnext/docs/user/manual/en/education/student/student-group-creation-tool.md b/erpnext/docs/user/manual/en/education/student/student-group-creation-tool.md index aeedd97a2e5..d27f4f74f64 100644 --- a/erpnext/docs/user/manual/en/education/student/student-group-creation-tool.md +++ b/erpnext/docs/user/manual/en/education/student/student-group-creation-tool.md @@ -4,7 +4,7 @@ The Student group creation tool allows you to create student groups in bulk. To create Student group using this tool go to -##education >>Student >> Student Group creation tool +> Education > Student > Student Group creation tool Select the **Academic Term** and the **Program** for which a student group is to be created. @@ -14,4 +14,16 @@ By default the student group is created based on the **Course** only. The check You can leave it unchecked if you don't want to consider batch while making course based groups. +#### Tutorial Video on Student Group Creation Tool + + +
+ +
+ +
+
+ {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/education/student/student-group.md b/erpnext/docs/user/manual/en/education/student/student-group.md index 467fb3e84e6..be68df1e731 100644 --- a/erpnext/docs/user/manual/en/education/student/student-group.md +++ b/erpnext/docs/user/manual/en/education/student/student-group.md @@ -6,9 +6,9 @@ A Student Group needs to be created for every course for **Academic Term** and * To create a Student Group go to: -education >> Student >> New Student Group +> Education > Student > New Student Group -Student Group +Student Group To create a Student group based on **Batch**, select the **Progam** and **Batch**, where as to create a Student group based on **Course**, you will only have to select the Course Code. Creating a student group based on activity allows you to group of student for events and activities happening in the institute. @@ -18,5 +18,18 @@ Once a student group is created you can mark attendance for the group. You can also update the **Email Group** for the Student Group. Click on Update Email Group to add all the email ids of the gaurdians in the respective email group and **Newsletter** can be created and sent to the Email group. +#### Tutorial Video on Student Groups + + + +
+ +
+ +
+
{next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/education/student/student.md b/erpnext/docs/user/manual/en/education/student/student.md index fce5d7ba8a8..9799e80a690 100644 --- a/erpnext/docs/user/manual/en/education/student/student.md +++ b/erpnext/docs/user/manual/en/education/student/student.md @@ -4,9 +4,21 @@ A Student is a person who has enrolled at your institute and you have accepted t The Student doctype maintains detials like personal information, date of birth, address etc. It also records the **Guardian** and sibling details. Student + The student is enrolled in a **Program** when the application is approved. Once the enrollement is done the **Student Applicant** status is update to Admitted. You can view every doctype created for a particular student. Eg : Fees, Student Group, etc +#### Video Tutorial on Student Management + + +
+ +
+ +
+
{next} \ No newline at end of file diff --git a/erpnext/education/doctype/guardian/guardian.py b/erpnext/education/doctype/guardian/guardian.py index 3741a06a908..e82cc546af4 100644 --- a/erpnext/education/doctype/guardian/guardian.py +++ b/erpnext/education/doctype/guardian/guardian.py @@ -37,7 +37,6 @@ def invite_guardian(guardian): frappe.throw(_("Please set Email Address")) else: guardian_as_user = frappe.get_value('User', dict(email=guardian_doc.email_address)) - print guardian_as_user if guardian_as_user: frappe.msgprint(_("User {0} already exists").format(getlink("User", guardian_as_user))) return guardian_as_user diff --git a/erpnext/healthcare/doctype/healthcare_settings/healthcare_settings.py b/erpnext/healthcare/doctype/healthcare_settings/healthcare_settings.py index 7206e4b58c3..0d3d6e76508 100644 --- a/erpnext/healthcare/doctype/healthcare_settings/healthcare_settings.py +++ b/erpnext/healthcare/doctype/healthcare_settings/healthcare_settings.py @@ -9,60 +9,60 @@ from frappe.core.doctype.sms_settings.sms_settings import send_sms import json class HealthcareSettings(Document): - def validate(self): - for key in ["collect_registration_fee","manage_customer","patient_master_name", - "require_test_result_approval","require_sample_collection", "default_medical_code_standard"]: - frappe.db.set_default(key, self.get(key, "")) - if(self.collect_registration_fee): - if self.registration_fee <= 0 : - frappe.throw("Registration fee can not be Zero") + def validate(self): + for key in ["collect_registration_fee","manage_customer","patient_master_name", + "require_test_result_approval","require_sample_collection", "default_medical_code_standard"]: + frappe.db.set_default(key, self.get(key, "")) + if(self.collect_registration_fee): + if self.registration_fee <= 0 : + frappe.throw("Registration fee can not be Zero") @frappe.whitelist() def get_sms_text(doc): - sms_text = {} - doc = frappe.get_doc("Lab Test",doc) - #doc = json.loads(doc) - context = {"doc": doc, "alert": doc, "comments": None} - emailed = frappe.db.get_value("Healthcare Settings", None, "sms_emailed") - sms_text['emailed'] = frappe.render_template(emailed, context) - printed = frappe.db.get_value("Healthcare Settings", None, "sms_printed") - sms_text['printed'] = frappe.render_template(printed, context) - return sms_text + sms_text = {} + doc = frappe.get_doc("Lab Test",doc) + #doc = json.loads(doc) + context = {"doc": doc, "alert": doc, "comments": None} + emailed = frappe.db.get_value("Healthcare Settings", None, "sms_emailed") + sms_text['emailed'] = frappe.render_template(emailed, context) + printed = frappe.db.get_value("Healthcare Settings", None, "sms_printed") + sms_text['printed'] = frappe.render_template(printed, context) + return sms_text def send_registration_sms(doc): - if (frappe.db.get_value("Healthcare Settings", None, "reg_sms")=='1'): - if doc.mobile: - context = {"doc": doc, "alert": doc, "comments": None} - if doc.get("_comments"): - context["comments"] = json.loads(doc.get("_comments")) - messages = frappe.db.get_value("Healthcare Settings", None, "reg_msg") - messages = frappe.render_template(messages, context) - number = [doc.mobile] - send_sms(number,messages) - else: - frappe.msgprint(doc.name + " Has no mobile number to send registration SMS", alert=True) + if (frappe.db.get_value("Healthcare Settings", None, "reg_sms")=='1'): + if doc.mobile: + context = {"doc": doc, "alert": doc, "comments": None} + if doc.get("_comments"): + context["comments"] = json.loads(doc.get("_comments")) + messages = frappe.db.get_value("Healthcare Settings", None, "reg_msg") + messages = frappe.render_template(messages, context) + number = [doc.mobile] + send_sms(number,messages) + else: + frappe.msgprint(doc.name + " Has no mobile number to send registration SMS", alert=True) def get_receivable_account(company): - receivable_account = get_account(None, "receivable_account", "Healthcare Settings", company) - if receivable_account: - return receivable_account - return frappe.db.get_value("Company", company, "default_receivable_account") + receivable_account = get_account(None, "receivable_account", "Healthcare Settings", company) + if receivable_account: + return receivable_account + return frappe.db.get_value("Company", company, "default_receivable_account") def get_income_account(physician, company): - if(physician): - income_account = get_account("Physician", None, physician, company) - if income_account: - return income_account - income_account = get_account(None, "income_account", "Healthcare Settings", company) - if income_account: - return income_account - return frappe.db.get_value("Company", company, "default_income_account") + if(physician): + income_account = get_account("Physician", None, physician, company) + if income_account: + return income_account + income_account = get_account(None, "income_account", "Healthcare Settings", company) + if income_account: + return income_account + return frappe.db.get_value("Company", company, "default_income_account") def get_account(parent_type, parent_field, parent, company): - if(parent_type): - return frappe.db.get_value("Party Account", - {"parenttype": parent_type, "parent": parent, "company": company}, "account") - if(parent_field): - return frappe.db.get_value("Party Account", - {"parentfield": parent_field, "parent": parent, "company": company}, "account") + if(parent_type): + return frappe.db.get_value("Party Account", + {"parenttype": parent_type, "parent": parent, "company": company}, "account") + if(parent_field): + return frappe.db.get_value("Party Account", + {"parentfield": parent_field, "parent": parent, "company": company}, "account") diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index a06645ad9fa..fb52d5260cc 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -592,7 +592,7 @@ def validate_bom_no(item, bom_no): @frappe.whitelist() def get_children(doctype, parent=None, is_root=False, **filters): - if not parent: + if not parent or parent=="BOM": frappe.msgprint(_('Please select a BOM')) return diff --git a/erpnext/manufacturing/doctype/bom/bom_tree.js b/erpnext/manufacturing/doctype/bom/bom_tree.js index 854f6334d73..6cbd7a2ab16 100644 --- a/erpnext/manufacturing/doctype/bom/bom_tree.js +++ b/erpnext/manufacturing/doctype/bom/bom_tree.js @@ -11,7 +11,8 @@ frappe.treeview_settings["BOM"] = { title: "BOM", breadcrumb: "Manufacturing", disable_add_node: true, - root_label: "All Bill of Materials", //fieldname from filters + root_label: "BOM", //fieldname from filters + get_tree_root: false, get_label: function(node) { if(node.data.qty) { return node.data.qty + " x " + node.data.item_code; @@ -19,6 +20,23 @@ frappe.treeview_settings["BOM"] = { return node.data.item_code || node.data.value; } }, + onload: function(me) { + var label = frappe.get_route()[0] + "/" + frappe.get_route()[1]; + if(frappe.pages[label]) { + delete frappe.pages[label]; + } + + var filter = me.opts.filters[0]; + if(frappe.route_options && frappe.route_options[filter.fieldname]) { + var val = frappe.route_options[filter.fieldname]; + delete frappe.route_options[filter.fieldname]; + filter.default = ""; + me.args[filter.fieldname] = val; + me.root_label = val; + me.page.set_title(val); + } + me.make_tree(); + }, toolbar: [ { toggle_btn: true }, { diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py index 7cfbab002a7..d3b7c5a4980 100644 --- a/erpnext/manufacturing/doctype/production_order/production_order.py +++ b/erpnext/manufacturing/doctype/production_order/production_order.py @@ -490,7 +490,7 @@ class ProductionOrder(Document): and detail.parent = entry.name and detail.item_code = %s''', (self.name, d.item_code))[0][0] - d.db_set('transferred_qty', transferred_qty, update_modified = False) + d.db_set('transferred_qty', flt(transferred_qty), update_modified = False) @frappe.whitelist() diff --git a/erpnext/patches.txt b/erpnext/patches.txt index d300285c676..f5953e2c492 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -345,7 +345,7 @@ erpnext.patches.v7_0.repost_bin_qty_and_item_projected_qty erpnext.patches.v7_1.set_prefered_contact_email execute:frappe.reload_doc('accounts', 'doctype', 'accounts_settings') execute:frappe.db.set_value("Accounts Settings", "Accounts Settings", "unlink_payment_on_cancellation_of_invoice", 0) -execute:frappe.db.sql("update `tabStock Entry` set total_amount = null where purpose in('Repack', 'Manufacture')") +execute:frappe.db.sql("update `tabStock Entry` set total_amount = 0 where purpose in('Repack', 'Manufacture')") erpnext.patches.v7_1.save_stock_settings erpnext.patches.v7_0.repost_gle_for_pi_with_update_stock #2016-11-01 erpnext.patches.v7_1.add_account_user_role_for_timesheet diff --git a/erpnext/patches/v7_0/update_status_of_po_so.py b/erpnext/patches/v7_0/update_status_of_po_so.py index c0b6f59eaf5..d630e8f0f2d 100644 --- a/erpnext/patches/v7_0/update_status_of_po_so.py +++ b/erpnext/patches/v7_0/update_status_of_po_so.py @@ -20,7 +20,10 @@ def update_po_per_received_per_billed(): where parent = `tabPurchase Order`.name), 2), `tabPurchase Order`.per_billed = ifnull(round((select sum( if(amount > ifnull(billed_amt, 0), ifnull(billed_amt, 0), amount)) / sum(amount) *100 from `tabPurchase Order Item` - where parent = `tabPurchase Order`.name), 2), 0)""") + where parent = `tabPurchase Order`.name), 2), 0) + where + net_total > 0 + """) def update_so_per_delivered_per_billed(): frappe.db.sql(""" @@ -32,7 +35,10 @@ def update_so_per_delivered_per_billed(): where parent = `tabSales Order`.name), 2), `tabSales Order`.per_billed = ifnull(round((select sum( if(amount > ifnull(billed_amt, 0), ifnull(billed_amt, 0), amount)) / sum(amount) *100 from `tabSales Order Item` - where parent = `tabSales Order`.name), 2), 0)""") + where parent = `tabSales Order`.name), 2), 0) + where + net_total > 0 + """) def update_status(): frappe.db.sql(""" diff --git a/erpnext/patches/v7_1/set_currency_exchange_date.py b/erpnext/patches/v7_1/set_currency_exchange_date.py index 7d8e4f0415d..630b7d42293 100644 --- a/erpnext/patches/v7_1/set_currency_exchange_date.py +++ b/erpnext/patches/v7_1/set_currency_exchange_date.py @@ -5,5 +5,5 @@ def execute(): frappe.db.sql(""" update `tabCurrency Exchange` set `date` = '2010-01-01' - where date is null or date = '' or date = '0000-00-00' + where date is null or date = '0000-00-00' """) \ No newline at end of file diff --git a/erpnext/patches/v7_2/rename_att_date_attendance.py b/erpnext/patches/v7_2/rename_att_date_attendance.py index f7caf706db5..b2658ba7f12 100644 --- a/erpnext/patches/v7_2/rename_att_date_attendance.py +++ b/erpnext/patches/v7_2/rename_att_date_attendance.py @@ -7,7 +7,7 @@ def execute(): frappe.reload_doc("hr", "doctype", "attendance") frappe.db.sql("""update `tabAttendance` set attendance_date = att_date - where attendance_date is null or attendance_date = '' or attendance_date = '0000-00-00'""") + where attendance_date is null or attendance_date = '0000-00-00'""") update_reports("Attendance", "att_date", "attendance_date") update_users_report_view_settings("Attendance", "att_date", "attendance_date") diff --git a/erpnext/patches/v7_2/update_salary_slips.py b/erpnext/patches/v7_2/update_salary_slips.py index 22bb1d82dc9..c6bca8e7b9b 100644 --- a/erpnext/patches/v7_2/update_salary_slips.py +++ b/erpnext/patches/v7_2/update_salary_slips.py @@ -9,8 +9,7 @@ def execute(): salary_slips = frappe.db.sql("""select month, name, fiscal_year from `tabSalary Slip` where (month is not null and month != '') and - (start_date is null or start_date = '') and - (end_date is null or end_date = '') and docstatus != 2""", as_dict=True) + start_date is null and end_date is null and docstatus != 2""", as_dict=True) for salary_slip in salary_slips: if not cint(salary_slip.month): diff --git a/erpnext/patches/v8_1/set_delivery_date_in_so_item.py b/erpnext/patches/v8_1/set_delivery_date_in_so_item.py index aa5cbc50bcc..2e815710722 100644 --- a/erpnext/patches/v8_1/set_delivery_date_in_so_item.py +++ b/erpnext/patches/v8_1/set_delivery_date_in_so_item.py @@ -8,7 +8,7 @@ def execute(): frappe.db.sql(""" update `tabSales Order` set delivery_date = final_delivery_date - where (delivery_date is null or delivery_date = '' or delivery_date = '0000-00-00') + where (delivery_date is null or delivery_date = '0000-00-00') and order_type = 'Sales'""") frappe.db.sql(""" @@ -16,8 +16,6 @@ def execute(): set so_item.delivery_date = so.delivery_date where so.name = so_item.parent and so.order_type = 'Sales' - and (so_item.delivery_date is null or so_item.delivery_date = '' - or so_item.delivery_date = '0000-00-00') - and (so.delivery_date is not null and so.delivery_date != '' - and so.delivery_date != '0000-00-00') - """) + and (so_item.delivery_date is null or so_item.delivery_date = '0000-00-00') + and (so.delivery_date is not null and so.delivery_date != '0000-00-00') + """) \ No newline at end of file diff --git a/erpnext/selling/doctype/customer/customer.json b/erpnext/selling/doctype/customer/customer.json index ecc14624e54..8a57f6d64d4 100644 --- a/erpnext/selling/doctype/customer/customer.json +++ b/erpnext/selling/doctype/customer/customer.json @@ -1066,9 +1066,9 @@ "bold": 0, "collapsible": 0, "columns": 0, - "depends_on": "", - "fieldname": "payment_terms", - "fieldtype": "Link", + "default": "0", + "fieldname": "bypass_credit_limit_check_at_sales_order", + "fieldtype": "Check", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -1076,10 +1076,9 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Default Payment Terms Template", + "label": "Bypass credit limit check at Sales Order", "length": 0, "no_copy": 0, - "options": "Payment Terms Template", "permlevel": 0, "precision": "", "print_hide": 0, @@ -1098,9 +1097,8 @@ "bold": 0, "collapsible": 0, "columns": 0, - "default": "0", - "fieldname": "bypass_credit_limit_check_at_sales_order", - "fieldtype": "Check", + "fieldname": "column_break_34", + "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -1108,7 +1106,6 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Bypass credit limit check at Sales Order", "length": 0, "no_copy": 0, "permlevel": 0, @@ -1123,6 +1120,38 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "", + "fieldname": "payment_terms", + "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 Payment Terms Template", + "length": 0, + "no_copy": 0, + "options": "Payment Terms Template", + "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/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index f19173eaa9b..d0db648ba6c 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -70,12 +70,12 @@ class Customer(TransactionBase): def fetch_primary_address_and_contact_detail(self): if(self.customer_primary_contact): primary_contact_doc = frappe.get_doc("Contact",self.customer_primary_contact) - self.db_set('mobile_no', primary_contact_doc.mobile_no) - self.db_set('email_id', primary_contact_doc.email_id) + self.mobile_no = primary_contact_doc.mobile_no + self.email_id = primary_contact_doc.email_id if(self.customer_primary_address): primary_address_doc = frappe.get_doc("Address",self.customer_primary_address) - self.db_set('primary_address', "
" + primary_address_doc.get_display()) + self.primary_address = "
" + primary_address_doc.get_display() def create_primary_contact(self): if not self.customer_primary_contact and not self.lead_name: @@ -197,12 +197,14 @@ def get_customer_list(doctype, txt, searchfield, start, page_len, filters): ("%%%s%%" % txt, "%%%s%%" % txt, "%%%s%%" % txt, "%%%s%%" % txt, start, page_len)) -def check_credit_limit(customer, company): - customer_outstanding = get_customer_outstanding(customer, company) +def check_credit_limit(customer, company, ignore_outstanding_sales_order=False, extra_amount=0): + customer_outstanding = get_customer_outstanding(customer, company, ignore_outstanding_sales_order) + if extra_amount > 0: + customer_outstanding += flt(extra_amount) credit_limit = get_credit_limit(customer, company) if credit_limit > 0 and flt(customer_outstanding) > credit_limit: - msgprint(_("Credit limit has been crossed for customer {0} {1}/{2}") + msgprint(_("Credit limit has been crossed for customer {0} ({1}/{2})") .format(customer, customer_outstanding, credit_limit)) # If not authorized person raise exception @@ -243,7 +245,8 @@ def get_customer_outstanding(customer, company, ignore_outstanding_sales_order=F and dn.customer=%s and dn.company=%s and dn.docstatus = 1 and dn.status not in ('Closed', 'Stopped') and ifnull(dn_item.against_sales_order, '') = '' - and ifnull(dn_item.against_sales_invoice, '') = ''""", (customer, company), as_dict=True) + and ifnull(dn_item.against_sales_invoice, '') = '' + """, (customer, company), as_dict=True) outstanding_based_on_dn = 0.0 diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 5bacf28bb82..60046c819fb 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -484,11 +484,6 @@ def make_delivery_note(source_name, target_doc=None): else: target.po_no = source.po_no - # Since the credit limit check is bypassed at sales order level, - # we need to check it at delivery note - if cint(frappe.db.get_value("Customer", source.customer, "bypass_credit_limit_check_at_sales_order")): - check_credit_limit(source.customer, source.company) - target.ignore_pricing_rule = 1 target.run_method("set_missing_values") target.run_method("calculate_taxes_and_totals") @@ -553,10 +548,6 @@ def make_sales_invoice(source_name, target_doc=None, ignore_permissions=False): target.run_method("set_missing_values") target.run_method("calculate_taxes_and_totals") - # Since the credit limit check is bypassed at sales order level, we need to check it at sales invoice - if cint(frappe.db.get_value("Customer", source.customer, "bypass_credit_limit_check_at_sales_order")): - check_credit_limit(source.customer, source.company) - # set company address target.update(get_company_address(target.company)) if target.company_address: diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.js b/erpnext/selling/page/point_of_sale/point_of_sale.js index 29238ea8058..2da5431e980 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.js +++ b/erpnext/selling/page/point_of_sale/point_of_sale.js @@ -468,6 +468,7 @@ erpnext.pos.PointOfSale = class PointOfSale { if (r.message) { this.frm.meta.default_print_format = r.message.print_format || 'POS Invoice'; + this.frm.allow_edit_rate = r.message.allow_edit_rate; } } @@ -739,6 +740,7 @@ class POSCart { disable_highlight: ['Qty', 'Disc', 'Rate', 'Pay'], reset_btns: ['Qty', 'Disc', 'Rate', 'Pay'], del_btn: 'Del', + disable_btns: !this.frm.allow_edit_rate ? ['Rate']: [], wrapper: this.wrapper.find('.number-pad-container'), onclick: (btn_value) => { // on click @@ -1269,7 +1271,7 @@ class NumberPad { constructor({ wrapper, onclick, button_array, add_class={}, disable_highlight=[], - reset_btns=[], del_btn='', + reset_btns=[], del_btn='', disable_btns }) { this.wrapper = wrapper; this.onclick = onclick; @@ -1278,6 +1280,7 @@ class NumberPad { this.disable_highlight = disable_highlight; this.reset_btns = reset_btns; this.del_btn = del_btn; + this.disable_btns = disable_btns; this.make_dom(); this.bind_events(); this.value = ''; @@ -1308,6 +1311,14 @@ class NumberPad { } this.set_class(); + + this.disable_btns.forEach((btn) => { + const $btn = this.get_btn(btn); + $btn.prop("disabled", true) + $btn.hover(() => { + $btn.css('cursor','not-allowed'); + }) + }) } set_class() { diff --git a/erpnext/setup/setup_wizard/setup_wizard.py b/erpnext/setup/setup_wizard/setup_wizard.py index 2c5f7e84563..d6491a8659c 100644 --- a/erpnext/setup/setup_wizard/setup_wizard.py +++ b/erpnext/setup/setup_wizard/setup_wizard.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe from frappe import _ -from operations import install_fixtures, taxes_setup, defaults_setup, company_setup, sample_data +from .operations import install_fixtures, taxes_setup, defaults_setup, company_setup, sample_data def get_setup_stages(args=None): if frappe.db.sql("select name from tabCompany"): diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py index bcbc35ee7ec..1673a96ef6b 100644 --- a/erpnext/stock/doctype/batch/batch.py +++ b/erpnext/stock/doctype/batch/batch.py @@ -203,7 +203,7 @@ def set_batch_nos(doc, warehouse_field, throw=False): else: batch_qty = get_batch_qty(batch_no=d.batch_no, warehouse=warehouse) if flt(batch_qty, d.precision("qty")) < flt(qty, d.precision("qty")): - frappe.throw(_("Row #{0}: The batch {1} has only {2} qty. Please select another batch which has {3} qty available or split the row into multiple rows, to deliver/issue from multiple batches").format(d.idx, d.batch_no, batch_qty, d.stock_qty)) + frappe.throw(_("Row #{0}: The batch {1} has only {2} qty. Please select another batch which has {3} qty available or split the row into multiple rows, to deliver/issue from multiple batches").format(d.idx, d.batch_no, batch_qty, qty)) @frappe.whitelist() diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index dd00398695b..65f384f6d90 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -235,13 +235,22 @@ class DeliveryNote(SellingController): def check_credit_limit(self): from erpnext.selling.doctype.customer.customer import check_credit_limit + extra_amount = 0 validate_against_credit_limit = False - for d in self.get("items"): - if not (d.against_sales_order or d.against_sales_invoice): - validate_against_credit_limit = True - break + bypass_credit_limit_check_at_sales_order = cint(frappe.db.get_value("Customer", self.customer, + "bypass_credit_limit_check_at_sales_order")) + if bypass_credit_limit_check_at_sales_order: + validate_against_credit_limit = True + extra_amount = self.base_grand_total + else: + for d in self.get("items"): + if not (d.against_sales_order or d.against_sales_invoice): + validate_against_credit_limit = True + break + if validate_against_credit_limit: - check_credit_limit(self.customer, self.company) + check_credit_limit(self.customer, self.company, + bypass_credit_limit_check_at_sales_order, extra_amount) def validate_packed_qty(self): """ diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js index c7719e4b8cd..104eeb82ac1 100644 --- a/erpnext/stock/doctype/item/item.js +++ b/erpnext/stock/doctype/item/item.js @@ -317,11 +317,6 @@ $.extend(erpnext.item, { show_multiple_variants_dialog: function(frm) { var me = this; - if(me.multiple_variant_dialog) { - me.multiple_variant_dialog.show(); - return; - } - let promises = []; let attr_val_fields = {}; diff --git a/erpnext/templates/generators/item.html b/erpnext/templates/generators/item.html index de544930cc3..6fec94e99cd 100644 --- a/erpnext/templates/generators/item.html +++ b/erpnext/templates/generators/item.html @@ -57,6 +57,21 @@
+
+ +
+ + + + + + + +
+
+
diff --git a/erpnext/templates/includes/product_page.js b/erpnext/templates/includes/product_page.js index 9f9d6ac412a..722283e6cb1 100644 --- a/erpnext/templates/includes/product_page.js +++ b/erpnext/templates/includes/product_page.js @@ -15,7 +15,7 @@ frappe.ready(function() { $(".item-cart").toggleClass("hide", (!!!r.message.price || !!!r.message.in_stock)); if(r.message && r.message.price) { $(".item-price") - .html(r.message.price.formatted_price + " {{ _("per") }} " + r.message.uom); + .html(r.message.price.formatted_price + " / " + r.message.uom); if(r.message.in_stock==0) { $(".item-stock").html("
{{ _("Not in stock") }}
"); @@ -44,7 +44,7 @@ frappe.ready(function() { erpnext.shopping_cart.update_cart({ item_code: get_item_code(), - qty: 1, + qty: $("#item-spinner .cart-qty").val(), callback: function(r) { if(!r.exc) { toggle_update_cart(1); @@ -55,6 +55,25 @@ frappe.ready(function() { }); }); + $("#item-spinner").on('click', '.number-spinner button', function () { + var btn = $(this), + input = btn.closest('.number-spinner').find('input'), + oldValue = input.val().trim(), + newVal = 0; + + if (btn.attr('data-dir') == 'up') { + newVal = parseInt(oldValue) + 1; + } else if (btn.attr('data-dir') == 'dwn') { + if (parseInt(oldValue) > 1) { + newVal = parseInt(oldValue) - 1; + } + else { + newVal = parseInt(oldValue); + } + } + input.val(newVal); + }); + $("[itemscope] .item-view-attribute .form-control").on("change", function() { try { var item_code = encodeURIComponent(get_item_code()); @@ -86,6 +105,7 @@ var toggle_update_cart = function(qty) { $("#item-update-cart") .toggle(qty ? true : false) .find("input").val(qty); + $("#item-spinner").toggle(qty ? false : true); } function get_item_code() {