Compare commits

..

34 Commits

Author SHA1 Message Date
Saurabh
1b18bba04a Merge branch 'hotfix' 2018-05-15 12:58:15 +05:30
Saurabh
f8c26bb778 bumped to version 10.1.32 2018-05-15 13:28:15 +06:00
Saurabh
ccd0617e19 Merge pull request #14017 from netchampfaris/apply-price-list-hotfix
[fix] apply price list
2018-05-15 11:25:08 +05:30
Saurabh
bf10d0f98b Merge pull request #14031 from shreyashah115/leave-balance
[Bug] Clear leave balance in Leave Application
2018-05-15 11:11:49 +05:30
Shreya
dbb67fb4fd Clear leave balance on changing leave type 2018-05-14 23:02:09 +05:30
Faris Ansari
404f39d373 [fix] apply price list
in_apply_price_list flag remains true if server exception occurs
2018-05-14 15:46:45 +05:30
Shreya Shah
bbee9b6cc4 [Enhancement] Monthly Attendance Report (#13970)
* Update Attendance on Approval of Leave

* Separate out leaves on the basis of its type

* Remove commented code

* Make attendance records if not found

* Fix Codacy

* Replace bad code in attendance.py
2018-05-14 14:30:58 +05:30
Faris Ansari
69b0535e10 [fix] Incorrect currency conversion in Itemised Tax Breakup (#14006) 2018-05-14 14:19:31 +05:30
rohitwaghchaure
7f63c1ad7c Merge pull request #14014 from rohitwaghchaure/hotfix_production_order_name_issue
[Fix] 'ProductionOrder' object has no attribute 'set_work_order_operations'
2018-05-14 14:04:09 +05:30
Rohit Waghchaure
ebe1ebead2 [Fix] 'ProductionOrder' object has no attribute 'set_work_order_operations' 2018-05-14 13:21:45 +05:30
Faris Ansari
f2b3307136 Remove escaped customer string (#13986)
- no need to escape strings that are passed to the values parameter of the sql method
- this query was failing for inputs like "D'Arby" which have quotes
2018-05-11 21:07:27 +05:30
Nabin Hait
9d215c2d9b Set operations on production order while making from Material Request 2018-05-09 18:32:54 +05:30
Vishal Dhayagude
3cf0d51e65 [fix] Compounding error in task weight (#13958)
* [fix] Compounding error in task weight

* [minor] minor changes

* [fix] Requested Changes added
2018-05-09 10:42:39 +05:30
Nabin Hait
9fc5ddc26e Merge branch 'hotfix' 2018-05-08 16:31:38 +05:30
Nabin Hait
0ff31f0ebf bumped to version 10.1.31 2018-05-08 17:01:38 +06:00
Saurabh
40349f4b00 [fix] add stock entry link on Material Request Dashboard (#13950) 2018-05-08 15:23:51 +05:30
Saurabh
b36517158b [fix] cheque print template coordinates (#13959) 2018-05-08 15:23:29 +05:30
Manas Solanki
3b9720f0be Merge pull request #13952 from manassolanki/minor-report-fix
[minor] fix for the student report card
2018-05-08 12:43:43 +05:30
Manas Solanki
cf26b2ca1c [minor] fix for the student report card 2018-05-08 12:39:02 +05:30
Nabin Hait
02a40e9d7b Merge branch 'hotfix' 2018-05-05 14:33:33 +05:30
Nabin Hait
ea199f9cd9 bumped to version 10.1.30 2018-05-05 15:03:33 +06:00
Nabin Hait
161f35a687 Update sales_invoice.py 2018-05-05 14:32:31 +05:30
Nabin Hait
fcb984b294 Merge branch 'hotfix' 2018-05-05 12:13:29 +05:30
Nabin Hait
723fe8fb1b bumped to version 10.1.29 2018-05-05 12:43:29 +06:00
Ameya Shenoy
47c0c8ba49 removed bad code and made compatible with pip 10 (#13805) 2018-05-04 19:20:20 +05:30
Rohit Waghchaure
3e0a937cb8 [Fix] Tax not changes when user change the POS profile in the sales invoice 2018-05-04 19:20:20 +05:30
Jamsheer
bd63f0056a Patient medical record updation and deletion fixes (#13891) 2018-05-04 18:13:28 +05:30
Shreya Shah
55daa9cd24 fix taxable amount for same items (#13927) 2018-05-04 18:01:23 +05:30
Shreya Shah
764b9bfeba cint for Item field has_variants (#13916)
* convert none type value to int

* Fix typo
2018-05-04 17:58:36 +05:30
Nabin Hait
62b985d405 [fix] Update show_in_website in template 2018-05-04 12:21:15 +05:30
Saurabh
ed393d1025 [fix] consider user permissions in leave application calendar view (#13902)
* [fix] consider user permissions in leave application calendar view

* add hr settings to control leave calendar view

* add patch
2018-05-03 18:52:25 +05:30
Nabin Hait
ed376cacc8 Set Qty in transactions based on serial no via Stock Settings (#13897) 2018-05-03 16:24:52 +05:30
Saurabh
7461806b1c Merge pull request #13892 from codingCoffee/travis
dark magic to revive travis
2018-05-02 23:23:07 +05:30
Ameya Shenoy
bb7c5ac0f8 dark magic to revive travis
It seems that some process inside travis is using port no 9000. Hence
adding this line in the travis.yml to change common_site_config.json and
use port no 9001 for socket_io
2018-05-02 17:32:39 +05:30
32 changed files with 326 additions and 66 deletions

View File

@@ -33,6 +33,7 @@ before_script:
- bench reinstall --yes
- bench build
- bench scheduler disable
- sed -i 's/9000/9001/g' sites/common_site_config.json
- bench start &
- sleep 10

View File

@@ -5,7 +5,7 @@ import frappe
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
__version__ = '10.1.28'
__version__ = '10.1.32'
def get_default_company(user=None):
'''Get default company for user'''

View File

@@ -27,10 +27,20 @@ def create_or_update_cheque_print_format(template_name):
doc = frappe.get_doc("Cheque Print Template", template_name)
cheque_print.html = """
<style>
.print-format {
padding: 0px;
}
@media screen {
.print-format {
padding: 0in;
}
}
</style>
<div style="position: relative; top:%(starting_position_from_top_edge)scm">
<div style="width:%(cheque_width)scm;height:%(cheque_height)scm;">
<span style="top:%(acc_pay_dist_from_top_edge)scm; left:%(acc_pay_dist_from_left_edge)scm;
border-bottom: solid 1px;border-top:solid 1px; position: absolute;">
border-bottom: solid 1px;border-top:solid 1px; width:2cm;text-align: center; position: absolute;">
%(message_to_show)s
</span>
<span style="top:%(date_dist_from_top_edge)scm; left:%(date_dist_from_left_edge)scm;
@@ -38,11 +48,11 @@ def create_or_update_cheque_print_format(template_name):
{{ frappe.utils.formatdate(doc.reference_date) or '' }}
</span>
<span style="top:%(acc_no_dist_from_top_edge)scm;left:%(acc_no_dist_from_left_edge)scm;
position: absolute;">
position: absolute; min-width: 6cm;">
{{ doc.account_no or '' }}
</span>
<span style="top:%(payer_name_from_top_edge)scm;left: %(payer_name_from_left_edge)scm;
position: absolute;">
position: absolute; min-width: 6cm;">
{{doc.party_name}}
</span>
<span style="top:%(amt_in_words_from_top_edge)scm; left:%(amt_in_words_from_left_edge)scm;
@@ -51,11 +61,11 @@ def create_or_update_cheque_print_format(template_name):
{{frappe.utils.money_in_words(doc.base_paid_amount or doc.base_received_amount)}}
</span>
<span style="top:%(amt_in_figures_from_top_edge)scm;left: %(amt_in_figures_from_left_edge)scm;
position: absolute;">
position: absolute; min-width: 4cm;">
{{doc.get_formatted("base_paid_amount") or doc.get_formatted("base_received_amount")}}
</span>
<span style="top:%(signatory_from_top_edge)scm;left: %(signatory_from_left_edge)scm;
position: absolute;">
position: absolute; min-width: 6cm;">
{{doc.company}}
</span>
</div>

View File

@@ -558,7 +558,8 @@ def get_itemised_tax_breakup_html(doc):
itemised_tax=itemised_tax,
itemised_taxable_amount=itemised_taxable_amount,
tax_accounts=tax_accounts,
company_currency=erpnext.get_company_currency(doc.company)
conversion_rate=doc.conversion_rate,
currency=doc.currency
)
)

View File

@@ -24,7 +24,7 @@ frappe.ui.form.on('Student Report Generation Tool', {
frm.page.clear_indicator();
frm.page.set_primary_action(__('Print Report Card'), () => {
let url = "/api/method/erpnext.education.doctype.student_report_generation_tool.student_report_generation_tool.preview_report_card";
open_url_post(url, frm.doc, true);
open_url_post(url, {"doc": frm.doc}, true);
});
},

View File

@@ -3,7 +3,7 @@
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
import frappe, json
from frappe.model.document import Document
from erpnext.education.api import get_grade
from frappe.utils.pdf import get_pdf
@@ -16,8 +16,8 @@ class StudentReportGenerationTool(Document):
@frappe.whitelist()
def preview_report_card(**kwargs):
doc = frappe._dict(**kwargs)
def preview_report_card(doc):
doc = frappe._dict(json.loads(doc))
doc.students = [doc.student]
if not (doc.student_name and doc.student_batch):
program_enrollment = frappe.get_all("Program Enrollment", fields=["student_batch_name", "student_name"],
@@ -33,7 +33,7 @@ def preview_report_card(**kwargs):
course_criteria = get_courses_criteria(courses)
# get the assessment group as per the user selection
if int(doc.include_all_assessment):
if doc.include_all_assessment:
assessment_groups = get_child_assessment_groups(doc.assessment_group)
else:
assessment_groups = [doc.assessment_group]
@@ -55,7 +55,7 @@ def preview_report_card(**kwargs):
"assessment_groups": assessment_groups,
"course_criteria": course_criteria,
"letterhead": letterhead.content,
"add_letterhead": int(doc.add_letterhead) if int(doc.add_letterhead) else 0
"add_letterhead": doc.add_letterhead if doc.add_letterhead else 0
})
final_template = frappe.render_template(base_template_path, {"body": html, "title": "Report Card"})

View File

@@ -113,9 +113,11 @@ def insert_consultation_to_medical_record(doc):
def update_consultation_to_medical_record(consultation):
medical_record_id = frappe.db.sql("select name from `tabPatient Medical Record` where reference_name=%s", (consultation.name))
if(medical_record_id[0][0]):
if medical_record_id and medical_record_id[0][0]:
subject = set_subject_field(consultation)
frappe.db.set_value("Patient Medical Record", medical_record_id[0][0], "subject", subject)
else:
insert_consultation_to_medical_record(consultation)
def delete_medical_record(consultation):
frappe.db.sql("""delete from `tabPatient Medical Record` where reference_name = %s""", (consultation.name))

View File

@@ -244,7 +244,7 @@ def insert_lab_test_to_medical_record(doc):
def delete_lab_test_from_medical_record(self):
medical_record_id = frappe.db.sql("select name from `tabPatient Medical Record` where reference_name=%s",(self.name))
if(medical_record_id[0][0]):
if medical_record_id and medical_record_id[0][0]:
frappe.delete_doc("Patient Medical Record", medical_record_id[0][0])
def create_item_line(test_code, sales_invoice):

View File

@@ -27,7 +27,7 @@ def insert_vital_signs_to_medical_record(doc):
def delete_vital_signs_from_medical_record(doc):
medical_record_id = frappe.db.sql("select name from `tabPatient Medical Record` where reference_name=%s",(doc.name))
if(medical_record_id[0][0]):
if medical_record_id and medical_record_id[0][0]:
frappe.delete_doc("Patient Medical Record", medical_record_id[0][0])
def set_subject_field(doc):

View File

@@ -20,17 +20,19 @@ class Attendance(Document):
set_employee_name(self)
def check_leave_record(self):
leave_record = frappe.db.sql("""select leave_type, half_day from `tabLeave Application`
leave_record = frappe.db.sql("""select leave_type, half_day, half_day_date from `tabLeave Application`
where employee = %s and %s between from_date and to_date and status = 'Approved'
and docstatus = 1""", (self.employee, self.attendance_date), as_dict=True)
if leave_record:
if leave_record[0].half_day:
self.status = 'Half Day'
frappe.msgprint(_("Employee {0} on Half day on {1}").format(self.employee, self.attendance_date))
else:
self.status = 'On Leave'
self.leave_type = leave_record[0].leave_type
frappe.msgprint(_("Employee {0} on Leave on {1}").format(self.employee, self.attendance_date))
for d in leave_record:
if d.half_day_date == getdate(self.attendance_date):
self.status = 'Half Day'
frappe.msgprint(_("Employee {0} on Half day on {1}").format(self.employee, self.attendance_date))
else:
self.status = 'On Leave'
self.leave_type = d.leave_type
frappe.msgprint(_("Employee {0} on Leave on {1}").format(self.employee, self.attendance_date))
if self.status == "On Leave" and not leave_record:
frappe.throw(_("No leave record found for employee {0} for {1}").format(self.employee, self.attendance_date))

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
@@ -11,6 +12,7 @@
"editable_grid": 1,
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -21,6 +23,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Employee Settings",
@@ -38,6 +41,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -50,6 +54,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Retirement Age",
@@ -68,6 +73,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -80,6 +86,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Employee Records to be created by",
@@ -98,6 +105,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -108,6 +116,7 @@
"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,
@@ -125,6 +134,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -136,6 +146,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Stop Birthday Reminders",
@@ -153,6 +164,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -163,6 +175,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Maintain Billing Hours and Working Hours Same on Timesheet",
@@ -181,6 +194,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -191,6 +205,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Payroll Settings",
@@ -208,6 +223,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -219,6 +235,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Include holidays in Total no. of Working Days",
@@ -236,6 +253,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -248,6 +266,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Email Salary Slip to Employee",
@@ -266,6 +285,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -276,6 +296,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Max working hours against Timesheet",
@@ -292,21 +313,81 @@
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "leave_settings",
"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": "Leave Settings",
"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": "show_leaves_of_all_department_members_in_calendar",
"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": "Show Leaves Of All Department Members In Calendar",
"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
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "fa fa-cog",
"idx": 1,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2017-01-16 14:01:31.183485",
"modified_by": "anastasiadis.st00@gmail.com",
"modified": "2018-05-03 15:35:13.015466",
"modified_by": "Administrator",
"module": "HR",
"name": "HR Settings",
"owner": "Administrator",
@@ -321,7 +402,6 @@
"export": 0,
"if_owner": 0,
"import": 0,
"is_custom": 0,
"permlevel": 0,
"print": 1,
"read": 1,
@@ -336,6 +416,7 @@
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_order": "ASC",
"track_changes": 0,
"track_seen": 0

View File

@@ -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: HR Settings", function (assert) {
let done = assert.async();
// number of asserts
assert.expect(1);
frappe.run_serially([
// insert a new HR Settings
() => frappe.tests.make('HR Settings', [
// values to be set
{key: 'value'}
]),
() => {
assert.equal(cur_frm.doc.key, 'value');
},
() => done()
]);
});

View File

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals
import frappe
import unittest
class TestHRSettings(unittest.TestCase):
pass

View File

@@ -95,6 +95,9 @@ frappe.ui.form.on("Leave Application", {
if (!r.exc && r.message) {
frm.set_value('leave_balance', r.message);
}
else {
frm.set_value('leave_balance', "0");
}
}
});
}

View File

@@ -5,12 +5,12 @@ from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import cint, cstr, date_diff, flt, formatdate, getdate, get_link_to_form, \
comma_or, get_fullname
comma_or, get_fullname, nowdate
from erpnext.hr.utils import set_employee_name
from erpnext.hr.doctype.leave_block_list.leave_block_list import get_applicable_block_dates
from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee
from erpnext.hr.doctype.employee_leave_approver.employee_leave_approver import get_approver_list
from erpnext.buying.doctype.supplier_scorecard.supplier_scorecard import daterange
class LeaveDayBlockedError(frappe.ValidationError): pass
class OverlapError(frappe.ValidationError): pass
@@ -52,6 +52,7 @@ class LeaveApplication(Document):
frappe.throw(_("Only Leave Applications with status 'Approved' and 'Rejected' can be submitted"))
self.validate_back_dated_application()
self.update_attendance()
# notify leave applier about approval
self.notify_employee(self.status)
@@ -100,6 +101,41 @@ class LeaveApplication(Document):
frappe.throw(_("Leave cannot be applied/cancelled before {0}, as leave balance has already been carry-forwarded in the future leave allocation record {1}")
.format(formatdate(future_allocation[0].from_date), future_allocation[0].name))
def update_attendance(self):
if self.status == "Approved":
attendance = frappe.db.sql("""select name from `tabAttendance` where employee = %s\
and (attendance_date between %s and %s) and docstatus < 2""",(self.employee, self.from_date, self.to_date), as_dict=1)
if attendance:
for d in attendance:
doc = frappe.get_doc("Attendance", d.name)
if getdate(self.half_day_date) == doc.attendance_date:
status = "Half Day"
else:
status = "On Leave"
frappe.db.sql("""update `tabAttendance` set status = %s, leave_type = %s\
where name = %s""",(status, self.leave_type, d.name))
elif self.from_date <= nowdate():
for dt in daterange(getdate(self.from_date), getdate(self.to_date)):
date = dt.strftime("%Y-%m-%d")
if not date == self.half_day_date:
doc = frappe.new_doc("Attendance")
doc.employee = self.employee
doc.attendance_date = date
doc.company = self.company
doc.status = "On Leave"
doc.leave_type = self.leave_type
doc.submit()
else:
doc = frappe.new_doc("Attendance")
doc.employee = self.employee
doc.attendance_date = date
doc.company = self.company
doc.status = "Half Day"
doc.leave_type = self.leave_type
doc.submit()
def validate_salary_processed_days(self):
if not frappe.db.get_value("Leave Type", self.leave_type, "is_lwp"):
return

View File

@@ -22,6 +22,10 @@ def execute(filters=None):
holiday_map = get_holiday(holiday_list, filters["month"])
data = []
leave_types = frappe.db.sql("""select name from `tabLeave Type`""", as_list=True)
leave_list = [d[0] for d in leave_types]
columns.extend(leave_list)
for emp in sorted(att_map):
emp_det = emp_map.get(emp)
if not emp_det:
@@ -49,10 +53,35 @@ def execute(filters=None):
elif status == "Half Day":
total_p += 0.5
total_a += 0.5
total_l += 0.5
row += [total_p, total_l, total_a]
data.append(row)
if not filters.get("employee"):
filters.update({"employee": emp})
conditions += " and employee = %(employee)s"
elif not filters.get("employee") == emp:
filters.update({"employee": emp})
leave_details = frappe.db.sql("""select leave_type, status, count(*) as count from `tabAttendance`\
where leave_type is not NULL %s group by leave_type, status""" % conditions, filters, as_dict=1)
leaves = {}
for d in leave_details:
if d.status == "Half Day":
d.count = d.count * 0.5
if d.leave_type in leaves:
leaves[d.leave_type] += d.count
else:
leaves[d.leave_type] = d.count
for d in leave_list:
if d in leaves:
row.append(leaves[d])
else:
row.append("0.0")
data.append(row)
return columns, data
def get_columns(filters):

View File

@@ -499,4 +499,6 @@ erpnext.patches.v10_0.update_hub_connector_domain
erpnext.patches.v10_0.set_student_party_type
erpnext.patches.v10_0.update_project_in_sle
erpnext.patches.v10_0.fix_reserved_qty_for_sub_contract
erpnext.patches.v10_0.taxes_issue_with_pos
erpnext.patches.v10_0.taxes_issue_with_pos
erpnext.patches.v10_0.set_qty_in_transactions_based_on_serial_no_input
erpnext.patches.v10_0.show_leaves_of_all_department_members_in_calendar

View File

@@ -0,0 +1,12 @@
# Copyright (c) 2017, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
frappe.reload_doc("stock", "doctype", "stock_settings")
ss = frappe.get_doc("Stock Settings")
ss.set_qty_in_transactions_based_on_serial_no_input = 1
ss.save()

View File

@@ -0,0 +1,5 @@
import frappe
def execute():
frappe.reload_doc("hr", "doctype", "hr_settings")
frappe.db.set_value("HR Settings", None, "show_leaves_of_all_department_members_in_calendar", 1)

View File

@@ -75,7 +75,7 @@ class Project(Document):
sum = 0
for task in self.tasks:
if task.task_weight > 0:
sum = sum + task.task_weight
sum = flt(sum + task.task_weight, task.precision('task_weight'))
if sum > 0 and sum != 1:
frappe.throw(_("Total of all task weights should be 1. Please adjust weights of all Project tasks accordingly"))

View File

@@ -106,7 +106,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
if(
this.frm.docstatus < 2
this.frm.docstatus < 2
&& this.frm.fields_dict["payment_terms_template"]
&& this.frm.fields_dict["payment_schedule"]
&& this.frm.doc.payment_terms_template
@@ -401,7 +401,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
item.serial_no = valid_serial_nos.join('\n');
refresh_field("serial_no", item.name, item.parentfield);
if(!doc.is_return) {
if(!doc.is_return && cint(user_defaults.set_qty_in_transactions_based_on_serial_no_input)) {
frappe.model.set_value(item.doctype, item.name,
"qty", valid_serial_nos.length / item.conversion_factor);
frappe.model.set_value(item.doctype, item.name, "stock_qty", valid_serial_nos.length);
@@ -1094,6 +1094,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
me.in_apply_price_list = false;
}
}
}).always(() => {
me.in_apply_price_list = false;
});
},

View File

@@ -144,7 +144,17 @@ class Gstr1Report(object):
""" % (self.doctype, ', '.join(['%s']*len(self.invoices))), tuple(self.invoices), as_dict=1)
for d in items:
self.invoice_items.setdefault(d.parent, {}).setdefault(d.item_code, d.base_net_amount)
item_details = {}
item_details[d.item_code] = d.base_net_amount
if d.parent in self.invoice_items:
parent_dict = self.invoice_items[d.parent]
if d.item_code in parent_dict:
item_details[d.item_code] += parent_dict[d.item_code]
else:
item_details.update(parent_dict)
self.invoice_items[d.parent] = item_details
def get_items_based_on_tax_rate(self):
self.tax_details = frappe.db.sql("""

View File

@@ -316,7 +316,7 @@ def make_address(args, is_primary_address=1):
return address
def get_customer_primary_contact(doctype, txt, searchfield, start, page_len, filters):
customer = frappe.db.escape(filters.get('customer'))
customer = filters.get('customer')
return frappe.db.sql("""
select `tabContact`.name from `tabContact`, `tabDynamic Link`
where `tabContact`.name = `tabDynamic Link`.parent and `tabDynamic Link`.link_name = %(customer)s

View File

@@ -37,6 +37,7 @@ def set_default_settings(args):
stock_settings.auto_indent = 1
stock_settings.auto_insert_price_list_rate_if_missing = 1
stock_settings.automatically_set_serial_nos_based_on_fifo = 1
stock_settings.set_qty_in_transactions_based_on_serial_no_input = 1
stock_settings.save()
selling_settings = frappe.get_doc("Selling Settings")

View File

@@ -604,19 +604,20 @@ class Item(WebsiteGenerator):
def update_template_item(self):
"""Set Show in Website for Template Item if True for its Variant"""
if self.variant_of and self.show_in_website:
self.show_variant_in_website = 1
self.show_in_website = 0
if self.variant_of:
if self.show_in_website:
self.show_variant_in_website = 1
self.show_in_website = 0
if self.show_variant_in_website:
# show template
template_item = frappe.get_doc("Item", self.variant_of)
if self.show_variant_in_website:
# show template
template_item = frappe.get_doc("Item", self.variant_of)
if not template_item.show_in_website:
template_item.show_in_website = 1
template_item.flags.dont_update_variants = True
template_item.flags.ignore_permissions = True
template_item.save()
if not template_item.show_in_website:
template_item.show_in_website = 1
template_item.flags.dont_update_variants = True
template_item.flags.ignore_permissions = True
template_item.save()
def update_variants(self):
if self.flags.dont_update_variants or \
@@ -640,9 +641,9 @@ class Item(WebsiteGenerator):
def validate_stock_exists_for_template_item(self):
if self.stock_ledger_created() and self._doc_before_save:
if (self._doc_before_save.has_variants != self.has_variants
if (cint(self._doc_before_save.has_variants) != cint(self.has_variants)
or self._doc_before_save.variant_of != self.variant_of):
frappe.throw(_("Cannot change Variant properties after stock transction. You will have to make a new Item to do this.").format(self.name),
frappe.throw(_("Cannot change Variant properties after stock transaction. You will have to make a new Item to do this.").format(self.name),
StockExistsForTemplate)
if self.has_variants or self.variant_of:

View File

@@ -417,6 +417,7 @@ def raise_production_orders(material_request):
prod_order.material_request_item = d.name
prod_order.planned_start_date = mr.transaction_date
prod_order.company = mr.company
prod_order.set_production_order_operations()
prod_order.save()
production_orders.append(prod_order.name)
else:

View File

@@ -7,7 +7,7 @@ def get_data():
'transactions': [
{
'label': _('Related'),
'items': ['Request for Quotation', 'Supplier Quotation', 'Purchase Order']
'items': ['Request for Quotation', 'Supplier Quotation', 'Purchase Order', "Stock Entry"]
},
{
'label': _('Manufacturing'),

View File

@@ -198,7 +198,7 @@ def validate_serial_no(sle, item_det):
frappe.throw(_("Serial No {0} quantity {1} cannot be a fraction").format(sle.item_code, sle.actual_qty))
if len(serial_nos) and len(serial_nos) != abs(cint(sle.actual_qty)):
frappe.throw(_("{0} Serial Numbers required for Item {1}. You have provided {2}.").format(sle.actual_qty, sle.item_code, len(serial_nos)),
frappe.throw(_("{0} Serial Numbers required for Item {1}. You have provided {2}.").format(abs(sle.actual_qty), sle.item_code, len(serial_nos)),
SerialNoQtyError)
if len(serial_nos) != len(set(serial_nos)):

View File

@@ -463,6 +463,37 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "1",
"fieldname": "set_qty_in_transactions_based_on_serial_no_input",
"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 Qty in Transactions based on Serial No Input",
"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,
@@ -679,7 +710,7 @@
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2017-11-17 01:35:49.562613",
"modified": "2018-05-03 12:37:12.905394",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Settings",

View File

@@ -11,8 +11,9 @@ from frappe.utils.html_utils import clean_html
class StockSettings(Document):
def validate(self):
for key in ["item_naming_by", "item_group", "stock_uom", "allow_negative_stock", "default_warehouse"]:
frappe.db.set_default(key, self.get(key, ""))
for key in ["item_naming_by", "item_group", "stock_uom",
"allow_negative_stock", "default_warehouse", "set_qty_in_transactions_based_on_serial_no_input"]:
frappe.db.set_default(key, self.get(key, ""))
from erpnext.setup.doctype.naming_series.naming_series import set_by_naming_series
set_by_naming_series("Item", "item_code",

View File

@@ -16,16 +16,16 @@
<tr>
<td>{{ item }}</td>
<td class='text-right'>
{{ frappe.utils.fmt_money(itemised_taxable_amount.get(item), None, company_currency) }}
{{ frappe.utils.fmt_money(itemised_taxable_amount.get(item), None, currency) }}
</td>
{% for tax_account in tax_accounts %}
{% set tax_details = taxes.get(tax_account) %}
{% if tax_details %}
<td class='text-right'>
{% if tax_details.tax_rate or not tax_details.tax_amount %}
({{ tax_details.tax_rate }}%)
({{ tax_details.tax_rate }}%)
{% endif %}
{{ frappe.utils.fmt_money(tax_details.tax_amount, None, company_currency) }}
{{ frappe.utils.fmt_money(tax_details.tax_amount / conversion_rate, None, currency) }}
</td>
{% else %}
<td></td>

View File

@@ -1,20 +1,17 @@
# -*- coding: utf-8 -*-
from setuptools import setup, find_packages
try: # for pip >= 10
from pip._internal.req import parse_requirements
except ImportError: # for pip <= 9.0.3
from pip.req import parse_requirements
import re, ast
# get version from __version__ variable in erpnext/__init__.py
_version_re = re.compile(r'__version__\s+=\s+(.*)')
with open('requirements.txt') as f:
install_requires = f.read().strip().split('\n')
with open('erpnext/__init__.py', 'rb') as f:
version = str(ast.literal_eval(_version_re.search(
f.read().decode('utf-8')).group(1)))
requirements = parse_requirements("requirements.txt", session="")
setup(
name='erpnext',
version=version,
@@ -24,6 +21,5 @@ setup(
packages=find_packages(),
zip_safe=False,
include_package_data=True,
install_requires=[str(ir.req) for ir in requirements],
dependency_links=[str(ir._link) for ir in requirements if ir._link]
install_requires=install_requires
)