Rushabh Mehta | dc8067e | 2016-06-29 18:38:32 +0530 | [diff] [blame] | 1 | from __future__ import unicode_literals |
Kanchan Chauhan | 1c1e2e9 | 2016-10-20 14:53:10 +0530 | [diff] [blame] | 2 | import frappe, erpnext |
Rohit Waghchaure | 8002d47 | 2016-07-13 16:03:05 +0530 | [diff] [blame] | 3 | import random |
Rushabh Mehta | e9d9b8e | 2016-12-15 11:27:35 +0530 | [diff] [blame] | 4 | import datetime |
| 5 | from frappe.utils import random_string, add_days, get_last_day, getdate |
Rohit Waghchaure | 8002d47 | 2016-07-13 16:03:05 +0530 | [diff] [blame] | 6 | from erpnext.projects.doctype.timesheet.test_timesheet import make_timesheet |
| 7 | from erpnext.projects.doctype.timesheet.timesheet import make_salary_slip, make_sales_invoice |
Neil Trini Lasrado | 0672459 | 2016-08-22 12:57:09 +0530 | [diff] [blame] | 8 | from frappe.utils.make_random import get_random |
rohitwaghchaure | ea092a7 | 2017-02-01 12:02:08 +0530 | [diff] [blame] | 9 | from erpnext.hr.doctype.expense_claim.test_expense_claim import get_payable_account |
Shreya Shah | 093e7e6 | 2018-02-16 14:49:39 +0530 | [diff] [blame] | 10 | from erpnext.hr.doctype.expense_claim.expense_claim import make_bank_entry |
Rushabh Mehta | e9d9b8e | 2016-12-15 11:27:35 +0530 | [diff] [blame] | 11 | from erpnext.hr.doctype.leave_application.leave_application import (get_leave_balance_on, |
| 12 | OverlapError, AttendanceAlreadyMarkedError) |
Rushabh Mehta | dc8067e | 2016-06-29 18:38:32 +0530 | [diff] [blame] | 13 | |
| 14 | def work(): |
| 15 | frappe.set_user(frappe.db.get_global('demo_hr_user')) |
Rushabh Mehta | dc8067e | 2016-06-29 18:38:32 +0530 | [diff] [blame] | 16 | year, month = frappe.flags.current_date.strftime("%Y-%m").split("-") |
Zlash65 | c24d2fd | 2018-09-27 18:49:00 +0530 | [diff] [blame] | 17 | setup_department_approvers() |
Kanchan Chauhan | db0e57c | 2016-07-29 15:59:39 +0530 | [diff] [blame] | 18 | mark_attendance() |
| 19 | make_leave_application() |
Rushabh Mehta | dc8067e | 2016-06-29 18:38:32 +0530 | [diff] [blame] | 20 | |
Shreya | f8e7bc7 | 2017-12-01 10:42:12 +0530 | [diff] [blame] | 21 | # payroll entry |
Rushabh Mehta | e9d9b8e | 2016-12-15 11:27:35 +0530 | [diff] [blame] | 22 | if not frappe.db.sql('select name from `tabSalary Slip` where month(adddate(start_date, interval 1 month))=month(curdate())'): |
Rushabh Mehta | e9d9b8e | 2016-12-15 11:27:35 +0530 | [diff] [blame] | 23 | # based on frequency |
Zlash65 | 796bffb | 2018-09-26 12:27:09 +0530 | [diff] [blame] | 24 | payroll_entry = get_payroll_entry() |
Shreya | f8e7bc7 | 2017-12-01 10:42:12 +0530 | [diff] [blame] | 25 | payroll_entry.salary_slip_based_on_timesheet = 0 |
Zlash65 | 796bffb | 2018-09-26 12:27:09 +0530 | [diff] [blame] | 26 | payroll_entry.save() |
Shreya | f8e7bc7 | 2017-12-01 10:42:12 +0530 | [diff] [blame] | 27 | payroll_entry.create_salary_slips() |
| 28 | payroll_entry.submit_salary_slips() |
Shreya | 9240eaa | 2018-03-30 12:19:11 +0530 | [diff] [blame] | 29 | payroll_entry.make_accrual_jv_entry() |
Zlash65 | 796bffb | 2018-09-26 12:27:09 +0530 | [diff] [blame] | 30 | payroll_entry.submit() |
Shreya | f8e7bc7 | 2017-12-01 10:42:12 +0530 | [diff] [blame] | 31 | # payroll_entry.make_journal_entry(reference_date=frappe.flags.current_date, |
Rushabh Mehta | cc8b2b2 | 2017-03-31 12:44:29 +0530 | [diff] [blame] | 32 | # reference_number=random_string(10)) |
Rushabh Mehta | e9d9b8e | 2016-12-15 11:27:35 +0530 | [diff] [blame] | 33 | |
Zlash65 | 796bffb | 2018-09-26 12:27:09 +0530 | [diff] [blame] | 34 | # based on timesheet |
| 35 | payroll_entry = get_payroll_entry() |
Shreya | f8e7bc7 | 2017-12-01 10:42:12 +0530 | [diff] [blame] | 36 | payroll_entry.salary_slip_based_on_timesheet = 1 |
Zlash65 | 796bffb | 2018-09-26 12:27:09 +0530 | [diff] [blame] | 37 | payroll_entry.save() |
Shreya | f8e7bc7 | 2017-12-01 10:42:12 +0530 | [diff] [blame] | 38 | payroll_entry.create_salary_slips() |
| 39 | payroll_entry.submit_salary_slips() |
Shreya | 9240eaa | 2018-03-30 12:19:11 +0530 | [diff] [blame] | 40 | payroll_entry.make_accrual_jv_entry() |
Zlash65 | 796bffb | 2018-09-26 12:27:09 +0530 | [diff] [blame] | 41 | payroll_entry.submit() |
Shreya | f8e7bc7 | 2017-12-01 10:42:12 +0530 | [diff] [blame] | 42 | # payroll_entry.make_journal_entry(reference_date=frappe.flags.current_date, |
Rushabh Mehta | cc8b2b2 | 2017-03-31 12:44:29 +0530 | [diff] [blame] | 43 | # reference_number=random_string(10)) |
Rushabh Mehta | e9d9b8e | 2016-12-15 11:27:35 +0530 | [diff] [blame] | 44 | |
Rohit Waghchaure | 8002d47 | 2016-07-13 16:03:05 +0530 | [diff] [blame] | 45 | if frappe.db.get_global('demo_hr_user'): |
| 46 | make_timesheet_records() |
Rushabh Mehta | e9d9b8e | 2016-12-15 11:27:35 +0530 | [diff] [blame] | 47 | |
Saurabh | f589c82 | 2016-07-15 18:28:05 +0530 | [diff] [blame] | 48 | #expense claim |
| 49 | expense_claim = frappe.new_doc("Expense Claim") |
| 50 | expense_claim.extend('expenses', get_expenses()) |
| 51 | expense_claim.employee = get_random("Employee") |
| 52 | expense_claim.company = frappe.flags.company |
rohitwaghchaure | ea092a7 | 2017-02-01 12:02:08 +0530 | [diff] [blame] | 53 | expense_claim.payable_account = get_payable_account(expense_claim.company) |
Saurabh | f589c82 | 2016-07-15 18:28:05 +0530 | [diff] [blame] | 54 | expense_claim.posting_date = frappe.flags.current_date |
Zlash65 | c24d2fd | 2018-09-27 18:49:00 +0530 | [diff] [blame] | 55 | expense_claim.expense_approver = frappe.db.get_global('demo_hr_user') |
| 56 | expense_claim.save() |
Saurabh | f589c82 | 2016-07-15 18:28:05 +0530 | [diff] [blame] | 57 | |
| 58 | rand = random.random() |
| 59 | |
Saurabh | 9cba6e1 | 2016-07-18 16:22:51 +0530 | [diff] [blame] | 60 | if rand < 0.4: |
Saurabh | f589c82 | 2016-07-15 18:28:05 +0530 | [diff] [blame] | 61 | update_sanctioned_amount(expense_claim) |
Zlash65 | c24d2fd | 2018-09-27 18:49:00 +0530 | [diff] [blame] | 62 | expense_claim.approval_status = 'Approved' |
Saurabh | f589c82 | 2016-07-15 18:28:05 +0530 | [diff] [blame] | 63 | expense_claim.submit() |
| 64 | |
| 65 | if random.randint(0, 1): |
| 66 | #make journal entry against expense claim |
Nabin Hait | 9641d5b | 2017-08-01 17:33:08 +0530 | [diff] [blame] | 67 | je = frappe.get_doc(make_bank_entry("Expense Claim", expense_claim.name)) |
Saurabh | f589c82 | 2016-07-15 18:28:05 +0530 | [diff] [blame] | 68 | je.posting_date = frappe.flags.current_date |
| 69 | je.cheque_no = random_string(10) |
| 70 | je.cheque_date = frappe.flags.current_date |
| 71 | je.flags.ignore_permissions = 1 |
| 72 | je.submit() |
| 73 | |
Zlash65 | 796bffb | 2018-09-26 12:27:09 +0530 | [diff] [blame] | 74 | def get_payroll_entry(): |
| 75 | # process payroll for previous month |
| 76 | payroll_entry = frappe.new_doc("Payroll Entry") |
| 77 | payroll_entry.company = frappe.flags.company |
| 78 | payroll_entry.payroll_frequency = 'Monthly' |
| 79 | |
| 80 | # select a posting date from the previous month |
| 81 | payroll_entry.posting_date = get_last_day(getdate(frappe.flags.current_date) - datetime.timedelta(days=10)) |
| 82 | payroll_entry.payment_account = frappe.get_value('Account', {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name") |
| 83 | |
| 84 | payroll_entry.set_start_end_dates() |
| 85 | return payroll_entry |
| 86 | |
Saurabh | f589c82 | 2016-07-15 18:28:05 +0530 | [diff] [blame] | 87 | def get_expenses(): |
| 88 | expenses = [] |
Saurabh | 718d835 | 2016-07-18 15:20:47 +0530 | [diff] [blame] | 89 | expese_types = frappe.db.sql("""select ect.name, eca.default_account from `tabExpense Claim Type` ect, |
| 90 | `tabExpense Claim Account` eca where eca.parent=ect.name |
| 91 | and eca.company=%s """, frappe.flags.company,as_dict=1) |
Saurabh | f589c82 | 2016-07-15 18:28:05 +0530 | [diff] [blame] | 92 | |
| 93 | for expense_type in expese_types[:random.randint(1,4)]: |
| 94 | claim_amount = random.randint(1,20)*10 |
| 95 | |
| 96 | expenses.append({ |
| 97 | "expense_date": frappe.flags.current_date, |
| 98 | "expense_type": expense_type.name, |
| 99 | "default_account": expense_type.default_account or "Miscellaneous Expenses - WPL", |
Mangesh-Khairnar | 444313b | 2019-06-12 12:52:02 +0530 | [diff] [blame] | 100 | "amount": claim_amount, |
Saurabh | f589c82 | 2016-07-15 18:28:05 +0530 | [diff] [blame] | 101 | "sanctioned_amount": claim_amount |
| 102 | }) |
| 103 | |
| 104 | return expenses |
| 105 | |
| 106 | def update_sanctioned_amount(expense_claim): |
| 107 | for expense in expense_claim.expenses: |
| 108 | sanctioned_amount = random.randint(1,20)*10 |
| 109 | |
Mangesh-Khairnar | 444313b | 2019-06-12 12:52:02 +0530 | [diff] [blame] | 110 | if sanctioned_amount < expense.amount: |
Saurabh | f589c82 | 2016-07-15 18:28:05 +0530 | [diff] [blame] | 111 | expense.sanctioned_amount = sanctioned_amount |
Rohit Waghchaure | 8002d47 | 2016-07-13 16:03:05 +0530 | [diff] [blame] | 112 | |
| 113 | def get_timesheet_based_salary_slip_employee(): |
Kanchan Chauhan | db197d5 | 2016-08-20 00:30:59 +0530 | [diff] [blame] | 114 | sal_struct = frappe.db.sql(""" |
| 115 | select name from `tabSalary Structure` |
| 116 | where salary_slip_based_on_timesheet = 1 |
| 117 | and docstatus != 2""") |
| 118 | if sal_struct: |
| 119 | employees = frappe.db.sql(""" |
Nabin Hait | 2f82bce | 2018-04-26 16:32:17 +0530 | [diff] [blame] | 120 | select employee from `tabSalary Structure Assignment` |
| 121 | where salary_structure IN %(sal_struct)s""", {"sal_struct": sal_struct}, as_dict=True) |
Kanchan Chauhan | db197d5 | 2016-08-20 00:30:59 +0530 | [diff] [blame] | 122 | return employees |
Rushabh Mehta | e9d9b8e | 2016-12-15 11:27:35 +0530 | [diff] [blame] | 123 | else: |
| 124 | return [] |
| 125 | |
Rohit Waghchaure | 8002d47 | 2016-07-13 16:03:05 +0530 | [diff] [blame] | 126 | def make_timesheet_records(): |
| 127 | employees = get_timesheet_based_salary_slip_employee() |
Kanchan Chauhan | db197d5 | 2016-08-20 00:30:59 +0530 | [diff] [blame] | 128 | for e in employees: |
Zlash65 | 796bffb | 2018-09-26 12:27:09 +0530 | [diff] [blame] | 129 | ts = make_timesheet(e.employee, simulate = True, billable = 1, activity_type=get_random("Activity Type"), company=frappe.flags.company) |
Rushabh Mehta | 397e508 | 2017-01-21 16:57:24 +0530 | [diff] [blame] | 130 | frappe.db.commit() |
Rohit Waghchaure | 8002d47 | 2016-07-13 16:03:05 +0530 | [diff] [blame] | 131 | |
| 132 | rand = random.random() |
| 133 | if rand >= 0.3: |
| 134 | make_salary_slip_for_timesheet(ts.name) |
| 135 | |
| 136 | rand = random.random() |
| 137 | if rand >= 0.2: |
| 138 | make_sales_invoice_for_timesheet(ts.name) |
| 139 | |
| 140 | def make_salary_slip_for_timesheet(name): |
| 141 | salary_slip = make_salary_slip(name) |
| 142 | salary_slip.insert() |
| 143 | salary_slip.submit() |
Rohit Waghchaure | 7d439ec | 2016-07-21 14:50:59 +0530 | [diff] [blame] | 144 | frappe.db.commit() |
Rohit Waghchaure | 8002d47 | 2016-07-13 16:03:05 +0530 | [diff] [blame] | 145 | |
| 146 | def make_sales_invoice_for_timesheet(name): |
| 147 | sales_invoice = make_sales_invoice(name) |
| 148 | sales_invoice.customer = get_random("Customer") |
| 149 | sales_invoice.append('items', { |
Rushabh Mehta | 397e508 | 2017-01-21 16:57:24 +0530 | [diff] [blame] | 150 | 'item_code': get_random("Item", {"has_variants": 0, "is_stock_item": 0, |
| 151 | "is_fixed_asset": 0}), |
Rohit Waghchaure | 8002d47 | 2016-07-13 16:03:05 +0530 | [diff] [blame] | 152 | 'qty': 1, |
| 153 | 'rate': 1000 |
| 154 | }) |
Rohit Waghchaure | 7d439ec | 2016-07-21 14:50:59 +0530 | [diff] [blame] | 155 | sales_invoice.flags.ignore_permissions = 1 |
Rohit Waghchaure | 8002d47 | 2016-07-13 16:03:05 +0530 | [diff] [blame] | 156 | sales_invoice.set_missing_values() |
| 157 | sales_invoice.calculate_taxes_and_totals() |
| 158 | sales_invoice.insert() |
Rohit Waghchaure | 7d439ec | 2016-07-21 14:50:59 +0530 | [diff] [blame] | 159 | sales_invoice.submit() |
Kanchan Chauhan | db0e57c | 2016-07-29 15:59:39 +0530 | [diff] [blame] | 160 | frappe.db.commit() |
Rushabh Mehta | e9d9b8e | 2016-12-15 11:27:35 +0530 | [diff] [blame] | 161 | |
Kanchan Chauhan | db0e57c | 2016-07-29 15:59:39 +0530 | [diff] [blame] | 162 | def make_leave_application(): |
| 163 | allocated_leaves = frappe.get_all("Leave Allocation", fields=['employee', 'leave_type']) |
Rushabh Mehta | e9d9b8e | 2016-12-15 11:27:35 +0530 | [diff] [blame] | 164 | |
Kanchan Chauhan | db0e57c | 2016-07-29 15:59:39 +0530 | [diff] [blame] | 165 | for allocated_leave in allocated_leaves: |
| 166 | leave_balance = get_leave_balance_on(allocated_leave.employee, allocated_leave.leave_type, frappe.flags.current_date, |
| 167 | consider_all_leaves_in_the_allocation_period=True) |
| 168 | if leave_balance != 0: |
| 169 | if leave_balance == 1: |
| 170 | to_date = frappe.flags.current_date |
| 171 | else: |
| 172 | to_date = add_days(frappe.flags.current_date, random.randint(0, leave_balance-1)) |
Rushabh Mehta | e9d9b8e | 2016-12-15 11:27:35 +0530 | [diff] [blame] | 173 | |
Kanchan Chauhan | db0e57c | 2016-07-29 15:59:39 +0530 | [diff] [blame] | 174 | leave_application = frappe.get_doc({ |
| 175 | "doctype": "Leave Application", |
| 176 | "employee": allocated_leave.employee, |
| 177 | "from_date": frappe.flags.current_date, |
| 178 | "to_date": to_date, |
| 179 | "leave_type": allocated_leave.leave_type, |
Kanchan Chauhan | db0e57c | 2016-07-29 15:59:39 +0530 | [diff] [blame] | 180 | }) |
| 181 | try: |
| 182 | leave_application.insert() |
| 183 | leave_application.submit() |
| 184 | frappe.db.commit() |
Rushabh Mehta | e9d9b8e | 2016-12-15 11:27:35 +0530 | [diff] [blame] | 185 | except (OverlapError, AttendanceAlreadyMarkedError): |
Kanchan Chauhan | db0e57c | 2016-07-29 15:59:39 +0530 | [diff] [blame] | 186 | frappe.db.rollback() |
Rushabh Mehta | e9d9b8e | 2016-12-15 11:27:35 +0530 | [diff] [blame] | 187 | |
Kanchan Chauhan | db0e57c | 2016-07-29 15:59:39 +0530 | [diff] [blame] | 188 | def mark_attendance(): |
Kanchan Chauhan | 7933eb6 | 2017-01-12 17:24:53 +0530 | [diff] [blame] | 189 | attendance_date = frappe.flags.current_date |
Kanchan Chauhan | db0e57c | 2016-07-29 15:59:39 +0530 | [diff] [blame] | 190 | for employee in frappe.get_all('Employee', fields=['name'], filters = {'status': 'Active'}): |
Rushabh Mehta | e9d9b8e | 2016-12-15 11:27:35 +0530 | [diff] [blame] | 191 | |
Kanchan Chauhan | 7933eb6 | 2017-01-12 17:24:53 +0530 | [diff] [blame] | 192 | if not frappe.db.get_value("Attendance", {"employee": employee.name, "attendance_date": attendance_date}): |
Kanchan Chauhan | db0e57c | 2016-07-29 15:59:39 +0530 | [diff] [blame] | 193 | attendance = frappe.get_doc({ |
| 194 | "doctype": "Attendance", |
| 195 | "employee": employee.name, |
Kanchan Chauhan | 7933eb6 | 2017-01-12 17:24:53 +0530 | [diff] [blame] | 196 | "attendance_date": attendance_date |
Kanchan Chauhan | db0e57c | 2016-07-29 15:59:39 +0530 | [diff] [blame] | 197 | }) |
Shreya Shah | d9a585b | 2018-02-12 16:02:57 +0530 | [diff] [blame] | 198 | |
Kanchan Chauhan | db0e57c | 2016-07-29 15:59:39 +0530 | [diff] [blame] | 199 | leave = frappe.db.sql("""select name from `tabLeave Application` |
Shreya Shah | d9a585b | 2018-02-12 16:02:57 +0530 | [diff] [blame] | 200 | where employee = %s and %s between from_date and to_date |
Kanchan Chauhan | 7933eb6 | 2017-01-12 17:24:53 +0530 | [diff] [blame] | 201 | and docstatus = 1""", (employee.name, attendance_date)) |
Rushabh Mehta | e9d9b8e | 2016-12-15 11:27:35 +0530 | [diff] [blame] | 202 | |
Kanchan Chauhan | db0e57c | 2016-07-29 15:59:39 +0530 | [diff] [blame] | 203 | if leave: |
| 204 | attendance.status = "Absent" |
| 205 | else: |
Neil Trini Lasrado | 0672459 | 2016-08-22 12:57:09 +0530 | [diff] [blame] | 206 | attendance.status = "Present" |
Kanchan Chauhan | db0e57c | 2016-07-29 15:59:39 +0530 | [diff] [blame] | 207 | attendance.save() |
Rushabh Mehta | e9d9b8e | 2016-12-15 11:27:35 +0530 | [diff] [blame] | 208 | attendance.submit() |
Neil Trini Lasrado | 0672459 | 2016-08-22 12:57:09 +0530 | [diff] [blame] | 209 | frappe.db.commit() |
Zlash65 | c24d2fd | 2018-09-27 18:49:00 +0530 | [diff] [blame] | 210 | |
| 211 | def setup_department_approvers(): |
| 212 | for d in frappe.get_all('Department', filters={'department_name': ['!=', 'All Departments']}): |
| 213 | doc = frappe.get_doc('Department', d.name) |
| 214 | doc.append("leave_approvers", {'approver': frappe.session.user}) |
| 215 | doc.append("expense_approvers", {'approver': frappe.session.user}) |
| 216 | doc.flags.ignore_mandatory = True |
| 217 | doc.save() |