Esempio n. 1
0
def process_workflow_actions(doc, state):
    workflow = get_workflow_name(doc.get('doctype'))
    if not workflow: return

    if state == "on_trash":
        clear_workflow_actions(doc.get('doctype'), doc.get('name'))
        return

    if is_workflow_action_already_created(doc): return

    clear_old_workflow_actions(doc)
    update_completed_workflow_actions(doc)
    clear_doctype_notifications('Workflow Action')

    next_possible_transitions = get_next_possible_transitions(
        workflow, get_doc_workflow_state(doc))

    if not next_possible_transitions: return

    user_data_map = get_users_next_action_data(next_possible_transitions, doc)

    if not user_data_map: return

    create_workflow_actions_for_users(user_data_map.keys(), doc)

    if send_email_alert(workflow):
        enqueue(send_workflow_action_email,
                queue='short',
                users_data=list(user_data_map.values()),
                doc=doc)
Esempio n. 2
0
 def send_email(self):
     """send email with payment link"""
     email_args = {
         "recipients":
         self.email_to,
         "sender":
         None,
         "subject":
         self.subject,
         "message":
         self.get_message(),
         "now":
         True,
         "attachments": [
             dataent.attach_print(self.reference_doctype,
                                  self.reference_name,
                                  file_name=self.reference_name,
                                  print_format=self.print_format)
         ]
     }
     enqueue(method=dataent.sendmail,
             queue='short',
             timeout=300,
             is_async=True,
             **email_args)
Esempio n. 3
0
def import_data(data_import):
    dataent.db.set_value("Data Import",
                         data_import,
                         "import_status",
                         "In Progress",
                         update_modified=False)
    dataent.publish_realtime("data_import_progress", {
        "progress": "0",
        "data_import": data_import,
        "reload": True
    },
                             user=dataent.session.user)

    from dataent.core.page.background_jobs.background_jobs import get_info
    enqueued_jobs = [d.get("job_name") for d in get_info()]

    if data_import not in enqueued_jobs:
        enqueue(upload,
                queue='default',
                timeout=6000,
                event='data_import',
                job_name=data_import,
                data_import_doc=data_import,
                from_data_import="Yes",
                user=dataent.session.user)
Esempio n. 4
0
    def email_salary_slip(self):
        receiver = dataent.db.get_value("Employee", self.employee,
                                        "prefered_email")

        if receiver:
            email_args = {
                "recipients": [receiver],
                "message":
                _("Please see attachment"),
                "subject":
                'Salary Slip - from {0} to {1}'.format(self.start_date,
                                                       self.end_date),
                "attachments": [
                    dataent.attach_print(self.doctype,
                                         self.name,
                                         file_name=self.name)
                ],
                "reference_doctype":
                self.doctype,
                "reference_name":
                self.name
            }
            if not dataent.flags.in_test:
                enqueue(method=dataent.sendmail,
                        queue='short',
                        timeout=300,
                        is_async=True,
                        **email_args)
            else:
                dataent.sendmail(**email_args)
        else:
            msgprint(
                _("{0}: Employee email not found, hence email not sent").
                format(self.employee_name))
def execute():
    comm_records_count = dataent.db.count("Communication",
                                          {"comment_type": "Updated"})
    if comm_records_count > 100000:
        enqueue(method=move_data_from_communication_to_activity_log,
                queue='short',
                now=True)
    else:
        move_data_from_communication_to_activity_log()
Esempio n. 6
0
def notify(doc,
           print_html=None,
           print_format=None,
           attachments=None,
           recipients=None,
           cc=None,
           bcc=None,
           fetched_from_email_account=False):
    """Calls a delayed task 'sendmail' that enqueus email in Email Queue queue

	:param print_html: Send given value as HTML attachment
	:param print_format: Attach print format of parent document
	:param attachments: A list of filenames that should be attached when sending this email
	:param recipients: Email recipients
	:param cc: Send email as CC to
	:param bcc: Send email as BCC to
	:param fetched_from_email_account: True when pulling email, the notification shouldn't go to the main recipient

	"""
    recipients, cc, bcc = get_recipients_cc_and_bcc(
        doc,
        recipients,
        cc,
        bcc,
        fetched_from_email_account=fetched_from_email_account)

    if not recipients and not cc:
        return

    doc.emails_not_sent_to = set(doc.all_email_addresses) - set(
        doc.sent_email_addresses)

    if dataent.flags.in_test:
        # for test cases, run synchronously
        doc._notify(print_html=print_html,
                    print_format=print_format,
                    attachments=attachments,
                    recipients=recipients,
                    cc=cc,
                    bcc=None)
    else:
        check_email_limit(list(set(doc.sent_email_addresses)))
        enqueue(sendmail,
                queue="default",
                timeout=300,
                event="sendmail",
                communication_name=doc.name,
                print_html=print_html,
                print_format=print_format,
                attachments=attachments,
                recipients=recipients,
                cc=cc,
                bcc=bcc,
                lang=dataent.local.lang,
                session=dataent.local.session,
                print_letterhead=dataent.flags.print_letterhead)
Esempio n. 7
0
def send_workflow_action_email(users_data, doc):
    common_args = get_common_email_args(doc)
    message = common_args.pop('message', None)
    for d in users_data:
        email_args = {
            'recipients': [d.get('email')],
            'args': {
                'actions': d.get('possible_actions'),
                'message': message
            },
            'reference_name': doc.name,
            'reference_doctype': doc.doctype
        }
        email_args.update(common_args)
        enqueue(method=dataent.sendmail, queue='short', **email_args)
Esempio n. 8
0
def schedule_files_backup(user_email):
    from dataent.utils.background_jobs import enqueue, get_jobs
    queued_jobs = get_jobs(site=dataent.local.site, queue="long")
    method = 'dataent.desk.page.backups.backups.backup_files_and_notify_user'

    if method not in queued_jobs[dataent.local.site]:
        enqueue(
            "dataent.desk.page.backups.backups.backup_files_and_notify_user",
            queue='long',
            user_email=user_email)
        dataent.msgprint(
            _("Queued for backup. You will receive an email with the download link"
              ))
    else:
        dataent.msgprint(
            _("Backup job is already queued. You will receive an email with the download link"
              ))
Esempio n. 9
0
def trigger(site, event, last=None, queued_jobs=(), now=False):
    """Trigger method in hooks.scheduler_events."""

    queue = 'long' if event.endswith('_long') else 'short'
    timeout = queue_timeout[queue]
    if not queued_jobs and not now:
        queued_jobs = get_jobs(site=site, queue=queue)

    if dataent.flags.in_test:
        dataent.flags.ran_schedulers.append(event)

    events_from_hooks = get_scheduler_events(event)
    if not events_from_hooks:
        return

    events = events_from_hooks
    if not now:
        events = []
        if event == "cron":
            for e in events_from_hooks:
                e = cron_map.get(e, e)
                if croniter.is_valid(e):
                    if croniter(e, last).get_next(
                            datetime) <= dataent.utils.now_datetime():
                        events.extend(events_from_hooks[e])
                else:
                    dataent.log_error("Cron string " + e + " is not valid",
                                      "Error triggering cron job")
                    dataent.logger(__name__).error(
                        'Exception in Trigger Events for Site {0}, Cron String {1}'
                        .format(site, e))

        else:
            if croniter(
                    cron_map[event],
                    last).get_next(datetime) <= dataent.utils.now_datetime():
                events.extend(events_from_hooks)

    for handler in events:
        if not now:
            if handler not in queued_jobs:
                enqueue(handler, queue, timeout, event)
        else:
            scheduler_task(site=site, event=event, handler=handler, now=True)
Esempio n. 10
0
    def test_job_timeout(self):
        job = enqueue(test_timeout, timeout=10)
        count = 5
        while count > 0:
            count -= 1
            time.sleep(5)
            if job.get_status() == 'failed':
                break

        self.assertTrue(job.is_failed)
Esempio n. 11
0
def pull(now=False):
	"""Will be called via scheduler, pull emails from all enabled Email accounts."""
	if dataent.cache().get_value("workers:no-internet") == True:
		if test_internet():
			dataent.cache().set_value("workers:no-internet", False)
		else:
			return
	queued_jobs = get_jobs(site=dataent.local.site, key='job_name')[dataent.local.site]
	for email_account in dataent.get_list("Email Account",
		filters={"enable_incoming": 1, "awaiting_password": 0}):
		if now:
			pull_from_email_account(email_account.name)

		else:
			# job_name is used to prevent duplicates in queue
			job_name = 'pull_from_email_account|{0}'.format(email_account.name)

			if job_name not in queued_jobs:
				enqueue(pull_from_email_account, 'short', event='all', job_name=job_name,
					email_account=email_account.name)
Esempio n. 12
0
    def queue_action(self, action, **kwargs):
        '''Run an action in background. If the action has an inner function,
		like _submit for submit, it will call that instead'''
        # call _submit instead of submit, so you can override submit to call
        # run_delayed based on some action
        # See: Stock Reconciliation
        if hasattr(self, '_' + action):
            action = '_' + action

        if file_lock.lock_exists(self.get_signature()):
            dataent.throw(_(
                'This document is currently queued for execution. Please try again'
            ),
                          title=_('Document Queued'))

        self.lock()
        enqueue('dataent.model.document.execute_action',
                doctype=self.doctype,
                name=self.name,
                action=action,
                **kwargs)
Esempio n. 13
0
	def send_emails(self):
		"""send emails to leads and customers"""
		if self.email_sent:
			throw(_("Newsletter has already been sent"))

		self.recipients = self.get_recipients()

		if getattr(dataent.local, "is_ajax", False):
			self.validate_send()

			# using default queue with a longer timeout as this isn't a scheduled task
			enqueue(send_newsletter, queue='default', timeout=6000, event='send_newsletter',
				newsletter=self.name)

		else:
			self.queue_all()

		dataent.msgprint(_("Scheduled to send to {0} recipients").format(len(self.recipients)))

		dataent.db.set(self, "email_sent", 1)
		dataent.db.set(self, 'scheduled_to_send', len(self.recipients))
Esempio n. 14
0
def take_backup_to_dropbox(retry_count=0, upload_db_backup=True):
	did_not_upload, error_log = [], []
	try:
		if cint(dataent.db.get_value("Dropbox Settings", None, "enabled")):
			did_not_upload, error_log = backup_to_dropbox(upload_db_backup)
			if did_not_upload: raise Exception

			send_email(True, "Dropbox")
	except JobTimeoutException:
		if retry_count < 2:
			args = {
				"retry_count": retry_count + 1,
				"upload_db_backup": False #considering till worker timeout db backup is uploaded
			}
			enqueue("dataent.integrations.doctype.dropbox_settings.dropbox_settings.take_backup_to_dropbox",
				queue='long', timeout=1500, **args)
	except Exception:
		file_and_error = [" - ".join(f) for f in zip(did_not_upload, error_log)]
		error_message = ("\n".join(file_and_error) + "\n" + dataent.get_traceback())
		dataent.errprint(error_message)
		send_email(False, "Dropbox", error_message)
Esempio n. 15
0
    def create_fees(self):
        self.db_set("fee_creation_status", "In Process")
        dataent.publish_realtime("fee_schedule_progress", {
            "progress": "0",
            "reload": 1
        },
                                 user=dataent.session.user)

        total_records = sum(
            [int(d.total_students) for d in self.student_groups])
        if total_records > 10:
            dataent.msgprint(
                _('''Fee records will be created in the background.
				In case of any error the error message will be updated in the Schedule.''')
            )
            enqueue(generate_fee,
                    queue='default',
                    timeout=6000,
                    event='generate_fee',
                    fee_schedule=self.name)
        else:
            generate_fee(self.name)
Esempio n. 16
0
def send_token_via_sms(otpsecret, token=None, phone_no=None):
    '''Send token as sms to user.'''
    try:
        from dataent.core.doctype.sms_settings.sms_settings import send_request
    except:
        return False

    if not phone_no:
        return False

    ss = dataent.get_doc('SMS Settings', 'SMS Settings')
    if not ss.sms_gateway_url:
        return False

    hotp = pyotp.HOTP(otpsecret)
    args = {
        ss.message_parameter:
        'Your verification code is {}'.format(hotp.at(int(token)))
    }

    for d in ss.get("parameters"):
        args[d.parameter] = d.value

    args[ss.receiver_parameter] = phone_no

    sms_args = {
        'params': args,
        'gateway_url': ss.sms_gateway_url,
        'use_post': ss.use_post
    }
    enqueue(method=send_request,
            queue='short',
            timeout=300,
            event=None,
            is_async=True,
            job_name=None,
            now=False,
            **sms_args)
    return True
Esempio n. 17
0
def send_token_via_email(user,
                         token,
                         otp_secret,
                         otp_issuer,
                         subject=None,
                         message=None):
    '''Send token to user as email.'''
    user_email = dataent.db.get_value('User', user, 'email')
    if not user_email:
        return False
    hotp = pyotp.HOTP(otp_secret)
    otp = hotp.at(int(token))
    template_args = {'otp': otp, 'otp_issuer': otp_issuer}
    if not subject:
        subject = get_email_subject_for_2fa(template_args)
    if not message:
        message = get_email_body_for_2fa(template_args)

    email_args = {
        'recipients': user_email,
        'sender': None,
        'subject': subject,
        'message': message,
        'header': [_('Verfication Code'), 'blue'],
        'delayed': False,
        'retry': 3
    }

    enqueue(method=dataent.sendmail,
            queue='short',
            timeout=300,
            event=None,
            is_async=True,
            job_name=None,
            now=False,
            **email_args)
    return True
Esempio n. 18
0
def reset_otp_secret(user):
    otp_issuer = dataent.db.get_value('System Settings', 'System Settings',
                                      'otp_issuer_name')
    user_email = dataent.db.get_value('User', user, 'email')
    if dataent.session.user in ["Administrator", user]:
        dataent.defaults.clear_default(user + '_otplogin')
        dataent.defaults.clear_default(user + '_otpsecret')
        email_args = {
            'recipients':
            user_email,
            'sender':
            None,
            'subject':
            'OTP Secret Reset - {}'.format(otp_issuer or "Dataent Framework"),
            'message':
            '<p>Your OTP secret on {} has been reset. If you did not perform this reset and did not request it, please contact your System Administrator immediately.</p>'
            .format(otp_issuer or "Dataent Framework"),
            'delayed':
            False,
            'retry':
            3
        }
        enqueue(method=dataent.sendmail,
                queue='short',
                timeout=300,
                event=None,
                is_async=True,
                job_name=None,
                now=False,
                **email_args)
        return dataent.msgprint(
            _("OTP Secret has been reset. Re-registration will be required on next login."
              ))
    else:
        return dataent.throw(
            _("OTP secret can only be reset by the Administrator."))
Esempio n. 19
0
def take_backup():
	"Enqueue longjob for taking backup to dropbox"
	enqueue("dataent.integrations.doctype.dropbox_settings.dropbox_settings.take_backup_to_dropbox", queue='long', timeout=1500)
	dataent.msgprint(_("Queued for backup. It may take a few minutes to an hour."))
Esempio n. 20
0
 def enqueue_report(self):
     enqueue(run_background, prepared_report=self.name, timeout=6000)