Ejemplo n.º 1
0
 def test_parameter(self):
     self.assertRaises(Exception, get_parameter, "foo")
     p = Parameter(key="testT", value="valueT", type="TEXT", desc="test")
     p.save()
     self.assertEquals(get_parameter(p.key), p.value)
     p = Parameter(key="testF", value=0.666, type="FLOAT", desc="test")
     p.save()
     self.assertEquals(get_parameter(p.key), p.value)
     p.value = 0.777
     p.save()
     self.assertEquals(get_parameter(p.key), p.value)
Ejemplo n.º 2
0
 def test_parameter(self):
     self.assertRaises(Exception, get_parameter, "foo")
     p = Parameter(key="testT", value="valueT", type="TEXT", desc="test")
     p.save()
     self.assertEqual(get_parameter(p.key), p.value)
     p = Parameter(key="testF", value=0.666, type="FLOAT", desc="test")
     p.save()
     self.assertEqual(get_parameter(p.key), p.value)
     p.value=0.777
     p.save()
     self.assertEqual(get_parameter(p.key), p.value)
Ejemplo n.º 3
0
def alert_consultant(context):
    """Randomly alert consultant about important stuff to do"""
    close_old_connections()
    if outside_business_hours():
        return

    consultants = Consultant.objects.exclude(telegram_id=None).filter(active=True)
    if not consultants:
        logger.warning("No consultant have telegram id defined. Alerting won't be possible. Bye")
        return
    consultant = random.choice(consultants)
    if consultant.is_in_holidays():
        # don't bother people during holidays
        return
    cache_key = "BOT_ALERT_CONSULTANT_LAST_24H_%s" % consultant.trigramme
    if cache.get(cache_key):
        # don't persecute people :-)
        return
    cache.set(cache_key, 1, 3600*24)  # Keep track 24 hours that this user has been alerted

    tasks = compute_consultant_tasks(consultant)
    if tasks:
        task_name, task_count, task_link, task_priority = random.choice(tasks)
        url = get_parameter("HOST") + task_link
        msg = _("Hey, what about thinking about that: %(task_name)s (x%(task_count)s)\n%(link)s") % {"task_name": task_name,
                                                                                                     "task_count": task_count,
                                                                                                     "link": url}
        context.bot.send_message(chat_id=consultant.telegram_id, text=msg)
Ejemplo n.º 4
0
def leads_pivotable(request, year=None):
    """Pivot table for all leads of given year"""
    data = []
    leads = Lead.objects.passive()
    derivedAttributes = """{'%s': $.pivotUtilities.derivers.bin('%s', 20),}""" % (
        _("sales (interval)"), _("sales"))
    month = int(get_parameter("FISCAL_YEAR_MONTH"))

    if not leads:
        return HttpResponse()

    years = get_fiscal_years(leads, "creation_date")

    if year is None and years:
        year = years[-1]
    if year != "all":
        year = int(year)
        start = date(year, month, 1)
        end = date(year + 1, month, 1)
        leads = leads.filter(creation_date__gte=start, creation_date__lt=end)
    leads = leads.select_related("responsible", "client__contact",
                                 "client__organisation__company", "subsidiary",
                                 "business_broker__company",
                                 "business_broker__contact")
    for lead in leads:
        data.append({
            _("deal id"):
            lead.deal_id,
            _("name"):
            lead.name,
            _("client organisation"):
            unicode(lead.client.organisation),
            _("client company"):
            unicode(lead.client.organisation.company),
            _(u"sales (k€)"):
            int(lead.sales or 0),
            _("date"):
            lead.creation_date.strftime("%Y-%m"),
            _("responsible"):
            unicode(lead.responsible),
            _("broker"):
            unicode(lead.business_broker),
            _("state"):
            lead.get_state_display(),
            _(u"billed (€)"):
            int(
                lead.clientbill_set.filter(state__in=(
                    "1_SENT", "2_PAID")).aggregate(Sum("amount")).values()[0]
                or 0),
            _("subsidiary"):
            unicode(lead.subsidiary)
        })
    return render(
        request, "leads/leads_pivotable.html", {
            "data": json.dumps(data),
            "derivedAttributes": derivedAttributes,
            "years": years,
            "selected_year": year
        })
Ejemplo n.º 5
0
def main():
    token = os.environ.get("TELEGRAM_TOKEN", settings.TELEGRAM_TOKEN)
    updater = Updater(token, use_context=True)
    dispatcher = updater.dispatcher

    conv_handler = ConversationHandler(
        entry_points=[CommandHandler('time', declare_time),
                      CommandHandler("hello", hello),
                      CommandHandler("start", hello),
                      CommandHandler("help", help)],
        states={  # used for timesheet session only
            MISSION_SELECT: [
                CallbackQueryHandler(select_mission, pattern="NONPROD"),
                CallbackQueryHandler(end_timesheet, pattern="END"),
                CallbackQueryHandler(mission_timesheet),
            ],
            MISSION_TIMESHEET: [
                CallbackQueryHandler(select_mission),
            ],
        },
        fallbacks=[CommandHandler('help', help)],
    )

    # Add ConversationHandler to dispatcher
    dispatcher.add_handler(conv_handler)

    # Add alert job
    updater.job_queue.run_repeating(alert_consultant, get_parameter("BOT_ALERT_INTERVAL"))

    # Add call for timesheet alert
    try:
        timesheet_time = time(*[int(i) for i in get_parameter("BOT_CALL_TIME_FOR_TIMESHEET").split(":")],
                              tzinfo=pytz.timezone(settings.TIME_ZONE))
    except (TypeError, ValueError):
        logger.error("Cannot parse timesheet time. Defaulting to 19:00")
        timesheet_time = time(19, tzinfo=pytz.timezone(settings.TIME_ZONE))
    updater.job_queue.run_daily(call_for_timesheet, timesheet_time)

    # Start the Bot
    updater.start_polling()

    # Run the bot until Ctrl-C or SIGINT,SIGTERM or SIGABRT.
    updater.idle()
Ejemplo n.º 6
0
def mail_lead(request, lead_id=0):
    try:
        lead = Lead.objects.get(id=lead_id)
    except Lead.DoesNotExist:
        raise Http404
    try:
        send_lead_mail(lead)
        return HttpResponse(_("Lead %(id)s was sent to %(mail)s !") % {"id": lead_id,
                                                                       "mail": get_parameter("LEAD_MAIL_TO")})
    except Exception as e:
        return HttpResponse(_("Failed to send mail: %s") % e)
Ejemplo n.º 7
0
def mail_lead(request, lead_id=0):
    try:
        lead = Lead.objects.get(id=lead_id)
    except Lead.DoesNotExist:
        raise Http404
    try:
        send_lead_mail(lead)
        return HttpResponse(_("Lead %(id)s was sent to %(mail)s !") % {"id": lead_id,
                                                                       "mail": get_parameter("LEAD_MAIL_TO")})
    except Exception as e:
        return HttpResponse(_("Failed to send mail: %s") % e)
Ejemplo n.º 8
0
def graph_yearly_billing(request):
    """Fiscal year billing per subsidiary"""
    bills = ClientBill.objects.filter(state__in=("1_SENT", "2_PAID"))
    years = get_fiscal_years_from_qs(bills, "creation_date")
    month = int(get_parameter("FISCAL_YEAR_MONTH"))
    data = {}
    graph_data = []
    labels = []
    growth = []
    subsidiaries = Subsidiary.objects.all()
    for subsidiary in subsidiaries:
        data[subsidiary.name] = []

    for year in years:
        turnover = {}
        for subsidiary_name, amount in bills.filter(creation_date__gte=date(year, month, 1), creation_date__lt=date(year + 1, month, 1)).values_list("lead__subsidiary__name").annotate(Sum("amount")):
            turnover[subsidiary_name] = float(amount)
        for subsidiary in subsidiaries:
            data[subsidiary.name].append(turnover.get(subsidiary.name, 0))

    last_turnover = 0
    for current_turnover in [sum(i) for i in zip(*list(data.values()))]:  # Total per year
        if last_turnover > 0:
            growth.append(round(100 * (current_turnover - last_turnover) / last_turnover, 1))
        else:
            growth.append(None)
        last_turnover = current_turnover

    if years[-1] == date.today().year:
        growth.pop()  # Don't compute for on-going year.

    graph_data.append(["x"] + years)  # X (years) axis

    # Add turnover per subsidiary
    for key, value in list(data.items()):
        if sum(value) == 0:
            continue
        value.insert(0, key)
        graph_data.append(value)
        labels.append(key)

    # Add growth
    graph_data.append([_("growth")] + growth)
    labels.append(_("growth"))

    return render(request, "billing/graph_yearly_billing.html",
                  {"graph_data": json.dumps(graph_data),
                   "years": years,
                   "subsidiaries" : json.dumps(labels),
                   "series_colors": COLORS,
                   "user": request.user})
Ejemplo n.º 9
0
def leads_pivotable(request, year=None):
    """Pivot table for all leads of given year"""
    data = []
    leads = Lead.objects.passive()
    derivedAttributes = """{'%s': $.pivotUtilities.derivers.bin('%s', 20),}""" % (_("sales (interval)"), _("sales (k€)"))
    month = int(get_parameter("FISCAL_YEAR_MONTH"))

    if not leads:
        return HttpResponse()

    years = get_fiscal_years(leads, "creation_date")

    if year is None and years:
        year = years[-1]
    if year != "all":
        year = int(year)
        start = date(year, month, 1)
        end = date(year + 1, month, 1)
        leads = leads.filter(creation_date__gte=start, creation_date__lt=end)
    leads = leads.select_related("responsible", "client__contact", "client__organisation__company", "subsidiary",
                         "business_broker__company", "business_broker__contact")
    for lead in leads:
        data.append({_("deal id"): lead.deal_id,
                     _("name"): lead.name,
                     _("client organisation"): str(lead.client.organisation),
                     _("client company"): str(lead.client.organisation.company),
                     _("sales (k€)"): int(lead.sales or 0),
                     _("date"): lead.creation_date.strftime("%Y-%m"),
                     _("responsible"): str(lead.responsible),
                     _("broker"): str(lead.business_broker),
                     _("state"): lead.get_state_display(),
                     _("billed (€)"): int(list(lead.clientbill_set.filter(state__in=("1_SENT", "2_PAID")).aggregate(Sum("amount")).values())[0] or 0),
                     _("Over budget margin (k€)"): lead.margin(),
                     _("subsidiary"): str(lead.subsidiary)})
    return render(request, "leads/leads_pivotable.html", { "data": json.dumps(data),
                                                    "derivedAttributes": derivedAttributes,
                                                    "years": years,
                                                    "selected_year": year})
Ejemplo n.º 10
0
from people.urls import people_urls
from staffing.urls import staffing_urls
from billing.urls import billing_urls
from actionset.urls import actionset_urls
from expense.urls import expense_urls
from leads.urls import leads_urls
from core.urls import core_urls

# Overide internal server error view
handler500 = "core.views.internal_error"

pydici_patterns = [url(r'^admin/', admin.site.urls),]

# Help page
try:
    help_page_url = get_parameter("HELP_PAGE")
except:
    # Corner case, during initial migration Parameter table does not exist yet
    help_page_url = ""

if settings.DEBUG:
    import debug_toolbar
    pydici_patterns.append(url(r'^__debug__/', include(debug_toolbar.urls)))

pydici_patterns.extend([
    # Direct to template and direct pages
    url(r'^help', RedirectView.as_view(url=help_page_url, permanent=True), name='help'),

    # Media
    url(r'^media/(?P<path>.*)$', django.views.static.serve,
            {'document_root': os.path.join(settings.PYDICI_ROOTDIR, 'media')}),
Ejemplo n.º 11
0
def postSaveLead(request, lead, updated_fields, created=False, state_changed=False, sync=False):
    mail = False
    if lead.send_email:
        mail = True
        lead.send_email = False

    lead.save()

    # Log it
    LogEntry.objects.log_action(
        user_id         = request.user.pk,
        content_type_id = ContentType.objects.get_for_model(lead).pk,
        object_id       = lead.pk,
        object_repr     = force_text(lead),
        action_flag     = ADDITION,
        change_message  = ", ".join(updated_fields),
    )

    if mail:
        try:
            fromAddr = request.user.email or "*****@*****.**"
            send_lead_mail(lead, request, fromAddr=fromAddr,
                           fromName="%s %s" % (request.user.first_name, request.user.last_name))
            messages.add_message(request, messages.INFO, ugettext("Lead sent to business mailing list"))
        except Exception as e:
            messages.add_message(request, messages.ERROR, ugettext("Failed to send mail: %s") % e)

    if settings.TELEGRAM_IS_ENABLED:
        try:
            bot = telegram.bot.Bot(token=settings.TELEGRAM_TOKEN)
            sticker = None
            url = get_parameter("HOST") + reverse("leads:detail", args=[lead.id, ])
            if created:
                msg = ugettext("New Lead !\n%(lead)s\n%(url)s") % {"lead": lead, "url":url }
                sticker = settings.TELEGRAM_STICKERS.get("happy")
                chat_group = "new_leads"
            elif state_changed:
                # Only notify when lead state changed to avoid useless spam
                try:
                    change = "%s (%s)" % (lead.get_change_history()[0].change_message, lead.get_change_history()[0].user)
                except:
                    change = ""
                msg = ugettext("Lead %(lead)s has been updated\n%(url)s\n%(change)s") % {"lead": lead, "url": url, "change": change}
                if lead.state == "WON":
                    sticker = settings.TELEGRAM_STICKERS.get("happy")
                elif lead.state in ("LOST", "FORGIVEN"):
                    sticker = settings.TELEGRAM_STICKERS.get("sad")
                chat_group = "leads_update"
            else:
                # No notification
                chat_group = ""

            for chat_id in settings.TELEGRAM_CHAT.get(chat_group, []):
                bot.sendMessage(chat_id=chat_id, text=msg, disable_web_page_preview=True)
                if sticker:
                    bot.sendSticker(chat_id=chat_id, sticker=sticker)
        except Exception as e:
            messages.add_message(request, messages.ERROR, ugettext("Failed to send telegram notification: %s") % e)

    # Compute leads probability
    if sync:
        compute = compute_leads_state.now  # Select synchronous flavor of computation function
    else:
        compute = compute_leads_state

    if lead.state in ("WON", "LOST", "SLEEPING", "FORGIVEN"):
        # Remove leads proba, no more needed
        lead.stateproba_set.all().delete()
        # Learn again. This new lead will now be used to training
        compute(relearn=True)
    else:
        # Just update proba for this lead with its new features
        compute(relearn=False, leads_id=[lead.id,])

    # Update lead tags
    compute_leads_tags()

    # update lead similarity model
    compute_lead_similarity()

    # Create or update mission  if needed
    if lead.mission_set.count() == 0:
        if lead.state in ("OFFER_SENT", "NEGOTIATION", "WON"):
            create_default_mission(lead)
            messages.add_message(request, messages.INFO, ugettext("A mission has been initialized for this lead."))

    for mission in lead.mission_set.all():
        if mission.subsidiary != lead.subsidiary:
            mission.subsidiary = lead.subsidiary
            mission.save()
        if lead.state == "WON":
            mission.probability = 100
            mission.active = True
            mission.save()
            messages.add_message(request, messages.INFO, ugettext("Mission's probability has been set to 100%"))
        elif lead.state in ("LOST", "FORGIVEN", "SLEEPING"):
            mission.probability = 0
            mission.active = False
            mission.save()
            messages.add_message(request, messages.INFO, ugettext("According mission has been archived"))
Ejemplo n.º 12
0
def warnForImcompleteTimesheet(warnSurbooking=False, days=None, month=None):
    """Warn users and admin for incomplete timesheet after due date
    @param warnSurbooking: Warn for surbooking days (default is false)
    @param day: only check n first days. If none, check all month"""
    emailTemplate = get_template("batch/timesheet_warning_email.txt")
    if month == "current":
        nextMonth = (date.today().replace(day=1) + timedelta(days=40)).replace(day=1)
        currentMonth = date.today().replace(day=1)
    else:
        # Checking past month
        nextMonth = date.today().replace(day=1)
        currentMonth = (nextMonth - timedelta(days=5)).replace(day=1)

    mails = []  # List of mail to be sent
    for consultant in Consultant.objects.filter(active=True, subcontractor=False):
        recipients = []
        if not [m for m in consultant.forecasted_missions(currentMonth) if m.nature == "PROD"]:
            # No productive mission forecasted on current month
            # Consultant may have just started
            # No check needed. Skip it
            continue
        missions = consultant.timesheet_missions(month=currentMonth)
        timesheetData, timesheetTotal, warning = gatherTimesheetData(consultant, missions, currentMonth)
        url = get_parameter("HOST") + urlresolvers.reverse("people:consultant_home", args=[consultant.trigramme])
        url += "?year=%s;month=%s" % (currentMonth.year, currentMonth.month)
        url += "#tab-timesheet"

        # Truncate if day parameter was given
        if days:
            warning = warning[:days]
        warning = [i for i in warning if i]  # Remove None
        if sum(warning) > 0:
            surbookingDays = warning.count(1)
            incompleteDays = warning.count(2)
            if not warnSurbooking and not incompleteDays:
                continue  # Don't cry if user only have surbooking issue

            user = consultant.getUser()
            if user and user.email:
                recipients.append(user.email)
            if consultant.manager:
                managerUser = consultant.manager.getUser()
                if managerUser and managerUser.email:
                    recipients.append(managerUser.email)

            if recipients:
                msgText = emailTemplate.render(context={"month": currentMonth,
                                                        "surbooking_days": surbookingDays,
                                                        "incomplete_days": incompleteDays,
                                                        "consultant": consultant,
                                                        "days": days,
                                                        "url": url})
                mails.append(((_("[pydici] Your timesheet is not correct"), msgText,
                          get_parameter("MAIL_FROM"), recipients)))
            else:
                mails.append(((_("[pydici] User has no email"),
                               _("User %s has an incomplete timesheet but cannot be warned because he has no email." % consultant),
                               get_parameter("MAIL_FROM"), [get_parameter("MAIL_FROM"), ])))

    # Send all emails in one time
    send_mass_mail(mails, fail_silently=False)
Ejemplo n.º 13
0
def postSaveLead(request,
                 lead,
                 updated_fields,
                 created=False,
                 state_changed=False,
                 sync=False):
    mail = False
    if lead.send_email:
        mail = True
        lead.send_email = False

    lead.save()

    # Log it
    LogEntry.objects.log_action(
        user_id=request.user.pk,
        content_type_id=ContentType.objects.get_for_model(lead).pk,
        object_id=lead.pk,
        object_repr=force_text(lead),
        action_flag=ADDITION,
        change_message=", ".join(updated_fields),
    )

    if mail:
        try:
            fromAddr = request.user.email or "*****@*****.**"
            send_lead_mail(lead,
                           request,
                           fromAddr=fromAddr,
                           fromName="%s %s" %
                           (request.user.first_name, request.user.last_name))
            messages.add_message(
                request, messages.INFO,
                ugettext("Lead sent to business mailing list"))
        except Exception as e:
            messages.add_message(request, messages.ERROR,
                                 ugettext("Failed to send mail: %s") % e)

    if settings.TELEGRAM_IS_ENABLED:
        try:
            bot = telegram.bot.Bot(token=settings.TELEGRAM_TOKEN)
            sticker = None
            url = get_parameter("HOST") + reverse("leads:detail",
                                                  args=[
                                                      lead.id,
                                                  ])
            if created:
                msg = ugettext("New Lead !\n%(lead)s\n%(url)s") % {
                    "lead": lead,
                    "url": url
                }
                sticker = settings.TELEGRAM_STICKERS.get("happy")
                chat_group = "new_leads"
            elif state_changed:
                # Only notify when lead state changed to avoid useless spam
                try:
                    change = "%s (%s)" % (
                        lead.get_change_history()[0].change_message,
                        lead.get_change_history()[0].user)
                except:
                    change = ""
                msg = ugettext(
                    "Lead %(lead)s has been updated\n%(url)s\n%(change)s") % {
                        "lead": lead,
                        "url": url,
                        "change": change
                    }
                if lead.state == "WON":
                    sticker = settings.TELEGRAM_STICKERS.get("happy")
                elif lead.state in ("LOST", "FORGIVEN"):
                    sticker = settings.TELEGRAM_STICKERS.get("sad")
                chat_group = "leads_update"
            else:
                # No notification
                chat_group = ""

            for chat_id in settings.TELEGRAM_CHAT.get(chat_group, []):
                bot.sendMessage(chat_id=chat_id,
                                text=msg,
                                disable_web_page_preview=True)
                if sticker:
                    bot.sendSticker(chat_id=chat_id, sticker=sticker)
        except Exception as e:
            messages.add_message(
                request, messages.ERROR,
                ugettext("Failed to send telegram notification: %s") % e)

    # Compute leads probability
    if sync:
        compute = compute_leads_state.now  # Select synchronous flavor of computation function
    else:
        compute = compute_leads_state

    if lead.state in ("WON", "LOST", "SLEEPING", "FORGIVEN"):
        # Remove leads proba, no more needed
        lead.stateproba_set.all().delete()
        # Learn again. This new lead will now be used to training
        compute(relearn=True)
    else:
        # Just update proba for this lead with its new features
        compute(relearn=False, leads_id=[
            lead.id,
        ])

    # Update lead tags
    compute_leads_tags()

    # update lead similarity model
    compute_lead_similarity()

    # Create or update mission  if needed
    if lead.mission_set.count() == 0:
        if lead.state in ("OFFER_SENT", "NEGOTIATION", "WON"):
            create_default_mission(lead)
            messages.add_message(
                request, messages.INFO,
                ugettext("A mission has been initialized for this lead."))

    for mission in lead.mission_set.all():
        if mission.subsidiary != lead.subsidiary:
            mission.subsidiary = lead.subsidiary
            mission.save()
        if lead.state == "WON":
            mission.probability = 100
            mission.active = True
            mission.save()
            messages.add_message(
                request, messages.INFO,
                ugettext("Mission's probability has been set to 100%"))
        elif lead.state in ("LOST", "FORGIVEN", "SLEEPING"):
            mission.probability = 0
            mission.active = False
            mission.save()
            messages.add_message(
                request, messages.INFO,
                ugettext("According mission has been archived"))
Ejemplo n.º 14
0
                           request,
                           fromAddr=fromAddr,
                           fromName="%s %s" %
                           (request.user.first_name, request.user.last_name))
            messages.add_message(
                request, messages.INFO,
                ugettext("Lead sent to business mailing list"))
        except Exception, e:
            messages.add_message(request, messages.ERROR,
                                 ugettext("Failed to send mail: %s") % e)

    if TELEGRAM_IS_ENABLED:
        try:
            bot = telegram.bot.Bot(token=TELEGRAM_TOKEN)
            sticker = None
            url = get_parameter("HOST") + urlresolvers.reverse(
                "leads.views.detail", args=[
                    lead.id,
                ])
            if created:
                msg = ugettext(u"New Lead !\n%(lead)s\n%(url)s") % {
                    "lead": lead,
                    "url": url
                }
                sticker = TELEGRAM_STICKERS.get("happy")
                chat_group = "new_leads"
            elif state_changed:
                # Only notify when lead state changed to avoid useless spam
                try:
                    change = u"%s (%s)" % (
                        lead.get_change_history()[0].change_message,
Ejemplo n.º 15
0
handler500 = "core.views.internal_error"

pydici_patterns = patterns('', (r'^admin/', include(admin.site.urls)))

if pydici.settings.DEBUG:
    import debug_toolbar
    pydici_patterns += patterns(
        '',
        url(r'^__debug__/', include(debug_toolbar.urls)),
    )

pydici_patterns += patterns(
    '',
    # Direct to template and direct pages
    url(r'^help',
        RedirectView.as_view(url=get_parameter("HELP_PAGE"), permanent=True),
        name='help'),

    # Media
    (r'^media/(?P<path>.*)$', 'django.views.static.serve', {
        'document_root': os.path.join(pydici.settings.PYDICI_ROOTDIR, 'media')
    }),

    # Feeds
    url(r'^feeds/latest/?$', LatestLeads(), name='latest'),
    url(r'^feeds/new/?$', NewLeads(), name='new'),
    url(r'^feeds/won/?$', WonLeads(), name='won'),
    url(r'^feeds/mine/?$', MyLatestLeads(), name='mine'),
    url(r'^feeds/latestStaffing/?$', LatestStaffing(), name='latestStaffing'),
    url(r'^feeds/myLatestStaffing/?$',
        MyLatestStaffing(),
Ejemplo n.º 16
0
def warnForImcompleteTimesheet(warnSurbooking=False, days=None, month=None):
    """Warn users and admin for incomplete timesheet after due date
    @param warnSurbooking: Warn for surbooking days (default is false)
    @param day: only check n first days. If none, check all month"""
    emailTemplate = get_template("batch/timesheet_warning_email.txt")
    if month == "current":
        nextMonth = (date.today().replace(day=1) +
                     timedelta(days=40)).replace(day=1)
        currentMonth = date.today().replace(day=1)
    else:
        # Checking past month
        nextMonth = date.today().replace(day=1)
        currentMonth = (nextMonth - timedelta(days=5)).replace(day=1)

    mails = []  # List of mail to be sent
    for consultant in Consultant.objects.filter(active=True,
                                                subcontractor=False):
        recipients = []
        if not [
                m for m in consultant.forecasted_missions(currentMonth)
                if m.nature == "PROD"
        ]:
            # No productive mission forecasted on current month
            # Consultant may have just started
            # No check needed. Skip it
            continue
        missions = consultant.timesheet_missions(month=currentMonth)
        timesheetData, timesheetTotal, warning = gatherTimesheetData(
            consultant, missions, currentMonth)
        url = get_parameter("HOST") + urlresolvers.reverse(
            "people:consultant_home", args=[consultant.trigramme])
        url += "?year=%s;month=%s" % (currentMonth.year, currentMonth.month)
        url += "#tab-timesheet"

        # Truncate if day parameter was given
        if days:
            warning = warning[:days]
        warning = [i for i in warning if i]  # Remove None
        if sum(warning) > 0:
            surbookingDays = warning.count(1)
            incompleteDays = warning.count(2)
            if not warnSurbooking and not incompleteDays:
                continue  # Don't cry if user only have surbooking issue

            user = consultant.getUser()
            if user and user.email:
                recipients.append(user.email)
            if consultant.manager:
                managerUser = consultant.manager.getUser()
                if managerUser and managerUser.email:
                    recipients.append(managerUser.email)

            if recipients:
                msgText = emailTemplate.render(
                    context={
                        "month": currentMonth,
                        "surbooking_days": surbookingDays,
                        "incomplete_days": incompleteDays,
                        "consultant": consultant,
                        "days": days,
                        "url": url
                    })
                mails.append(
                    ((_("[pydici] Your timesheet is not correct"), msgText,
                      get_parameter("MAIL_FROM"), recipients)))
            else:
                mails.append(((
                    _("[pydici] User has no email"),
                    _("User %s has an incomplete timesheet but cannot be warned because he has no email."
                      % consultant), get_parameter("MAIL_FROM"), [
                          get_parameter("MAIL_FROM"),
                      ])))

    # Send all emails in one time
    send_mass_mail(mails, fail_silently=False)
Ejemplo n.º 17
0
from expense.urls import expense_urls
from leads.urls import leads_urls
from core.urls import core_urls

from core.views import PydiciSelect2View, PydiciSelect2SubcontractorView

# Overide internal server error view
handler500 = "core.views.internal_error"

pydici_patterns = [
    url(r'^admin/', admin.site.urls),
]

# Help page
try:
    help_page_url = get_parameter("HELP_PAGE")
except:
    # Corner case, during initial migration Parameter table does not exist yet
    help_page_url = ""

if settings.DEBUG:
    import debug_toolbar
    pydici_patterns.append(url(r'^__debug__/', include(debug_toolbar.urls)))

pydici_patterns.extend([
    # Direct to template and direct pages
    url(r'^help',
        RedirectView.as_view(url=help_page_url, permanent=True),
        name='help'),

    # Media