Пример #1
0
 def current_outing(self):
     if Outing.objects.filter(route=self,
                              fiscal_year_id=fiscal_year(sap_style=True)):
         return Outing.objects.get(
             route=self, fiscal_year_id=fiscal_year(sap_style=True))
     else:
         return None
Пример #2
0
    def clean_start_date(self):
        start_date = self.cleaned_data['start_date']
        fy = shared_models.FiscalYear.objects.get(
            pk=fiscal_year(start_date, sap_style=True))

        # is there already a fiscal year? There is a special case when there will be a fiscal year, but we are cloning
        if not self.initial.get("cloning") and self.instance.fiscal_year:
            # there if we remove this instance, there should not be another projectyear with the same fiscal year as fy
            project = self.instance.project
            other_years = project.years.filter(~Q(id=self.instance.id))
            if other_years.filter(fiscal_year=fy).exists():
                raise forms.ValidationError(
                    gettext(
                        f"Sorry, there is already a {fy} year in this project."
                    ))
            pass
        else:
            if self.initial.get("cloning"):
                project = self.instance.project
            else:
                project = self.initial["project"]
            if project.years.filter(fiscal_year=fy).exists():
                raise forms.ValidationError(
                    gettext(
                        f"Sorry, there is already a {fy} year in this project."
                    ))
        return start_date
Пример #3
0
 def get_filterset_kwargs(self, filterset_class):
     kwargs = super().get_filterset_kwargs(filterset_class)
     if kwargs["data"] is None:
         kwargs["data"] = {
             "fiscal_year": fiscal_year(),
         }
     return kwargs
Пример #4
0
 def save(self, *args, **kwargs):
     qs = self.samples.all()
     if qs.filter(datetime__isnull=False).exists():
         self.start_date = qs.order_by("datetime").first().datetime
         self.end_date = qs.order_by("datetime").last().datetime
         self.fiscal_year_id = fiscal_year(self.end_date, sap_style=True)
     super().save(*args, **kwargs)
Пример #5
0
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['google_api_key'] = settings.GOOGLE_API_KEY
        context["current_fy"] = fiscal_year()
        context["field_list"] = [
            'id',
            'path_number',
            'program_reference_number',
            'organization',
            'title',
            'program',
            'language',
            'status',
            'regions',
            'start_year',
            'project_length',
            'activities',
            'watersheds',
            'spp',
            'date_completed',
            'summary',
        ]

        site_list = [[
            "{} ({})".format(obj.name, obj.site_type), obj.lat, obj.long
        ] for obj in self.object.sites.all() if obj.lat and obj.long]
        context['site_list'] = site_list

        return context
Пример #6
0
 def get_initial(self):
     return {
         'fiscal_year': fiscal_year(sap_style=True),
         'created_by': self.request.user,
         'transaction_type': 3,
         'in_mrs': False,
         'do_another': 1,
     }
Пример #7
0
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        my_user = self.request.user
        rc_list = shared_models.ResponsibilityCenter.objects.filter(manager=my_user)
        context["rc_list"] = rc_list
        context["fy"] = fiscal_year(sap_style=True)

        return context
Пример #8
0
 def setUp(self):
     super().setUp()
     self.test_urls = [
         reverse_lazy('travel:export_trip_list',
                      kwargs={
                          "fy": fiscal_year(sap_style=True),
                          "region": "None",
                          "adm": "None",
                          "from_date": "None",
                          "to_date": "None",
                      }),
         reverse_lazy('travel:export_trip_list',
                      kwargs={
                          "fy": "None",
                          "region": RegionFactory().id,
                          "adm": "None",
                          "from_date": "None",
                          "to_date": "None",
                      }),
         reverse_lazy('travel:export_trip_list',
                      kwargs={
                          "fy": "None",
                          "region": "None",
                          "adm": faker.pybool(),
                          "from_date": "None",
                          "to_date": "None",
                      }),
         reverse_lazy('travel:export_trip_list',
                      kwargs={
                          "fy":
                          "None",
                          "region":
                          "None",
                          "adm":
                          "None",
                          "from_date":
                          faker.date_time_this_year().strftime("%Y-%m-%d"),
                          "to_date":
                          "None",
                      }),
         reverse_lazy('travel:export_trip_list',
                      kwargs={
                          "fy":
                          "None",
                          "region":
                          "None",
                          "adm":
                          "None",
                          "from_date":
                          "None",
                          "to_date":
                          faker.date_time_this_year().strftime("%Y-%m-%d"),
                      }),
     ]
     self.view = views.export_trip_list
Пример #9
0
    def clean(self):
        cleaned_data = super().clean()

        # we have to make sure
        # 1) the end date is after the start date and
        # 2)the start and end dates are within the same fiscal year
        end_date = cleaned_data.get("end_date")
        if end_date:
            start_date = cleaned_data.get("start_date")
            if end_date and start_date and end_date < start_date:
                self.add_error(
                    'end_date',
                    gettext("The end date must be after the start date!"))

            if end_date and start_date and fiscal_year(
                    start_date) != fiscal_year(end_date):
                self.add_error(
                    'end_date',
                    gettext(
                        "The start and end dates must be within the same fiscal year!"
                    ))
Пример #10
0
    def get_initial(self):
        # default the year to the year of the latest samples
        my_dict = {
            "fiscal_year": fiscal_year(sap_style=True),
        }

        try:
            self.kwargs["report_number"]
        except KeyError:
            print("no report")
        else:
            my_dict["report"] = self.kwargs["report_number"]

        return my_dict
Пример #11
0
        def setUp(self):
            super().setUp()

            date = datetime(year=faker.pyint(2000, 2030),
                            month=4,
                            day=1,
                            tzinfo=timezone.get_current_timezone())
            year = fiscal_year(date, sap_style=True)

            # At a minimum a year is required
            self.test_url = reverse_lazy(
                'whalesdb:report_deployment_summary') + f'?year={year}'

            self.user = self.get_and_login_user()
Пример #12
0
    def save(self, *args, **kwargs):
        if self.notes:
            self.notes_html = markdown.markdown(self.notes)

        self.date_modified = timezone.now()

        # if status is resolved or canceled, add a date closed timestamp
        if self.status_id == 1 or self.status == 4:
            self.date_closed = timezone.now()
        else:
            self.date_closed = None

        self.fiscal_year_id = fiscal_year(self.date_opened, sap_style=True)
        super().save(*args, **kwargs)
Пример #13
0
 def setUp(self):
     super().setUp()
     self.test_urls = [
         reverse_lazy('travel:export_cfts_list',
                      kwargs={
                          "fy": "None",
                          "region": "None",
                          "trip": "None",
                          "user": "******",
                          "from_date": "None",
                          "to_date": "None",
                      }),
         reverse_lazy('travel:export_cfts_list',
                      kwargs={
                          "fy": fiscal_year(sap_style=True),
                          "region": "None",
                          "trip": "None",
                          "user": "******",
                          "from_date": "None",
                          "to_date": "None",
                      }),
         reverse_lazy('travel:export_cfts_list',
                      kwargs={
                          "fy": "None",
                          "region": RegionFactory().id,
                          "trip": "None",
                          "user": "******",
                          "from_date": "None",
                          "to_date": "None",
                      }),
         reverse_lazy('travel:export_cfts_list',
                      kwargs={
                          "fy": "None",
                          "region": "None",
                          "trip": TripFactory().id,
                          "user": "******",
                          "from_date": "None",
                          "to_date": "None",
                      }),
         reverse_lazy('travel:export_cfts_list',
                      kwargs={
                          "fy": "None",
                          "region": "None",
                          "trip": "None",
                          "user": UserFactory().id,
                          "from_date": "None",
                          "to_date": "None",
                      }),
     ]
     self.view = views.export_cfts_list
Пример #14
0
    def save(self, *args, **kwargs):
        if self.uuid is None:
            self.uuid = uuid.uuid1()

        if self.fgp_publication_date:
            # if there is a revision date, use this, otherwise use fgp pub date
            pub_date = self.last_revision_date if self.last_revision_date else self.fgp_publication_date
            fy = shared_models.FiscalYear.objects.get(
                pk=fiscal_year(date=pub_date, sap_style=True))
            self.publication_fy = fy

        # will handle this through the resource form. If not, each time the record is verified, this field will be updated
        # self.date_last_modified = timezone.now()
        super().save(*args, **kwargs)
Пример #15
0
def sign_up_or_remove_user_from_route(request, route):
    my_route = models.Route.objects.get(pk=route)
    # get or create the outing from this fiscal
    my_outing, created = models.Outing.objects.get_or_create(
        fiscal_year_id=fiscal_year(sap_style=True),
        route=my_route,
    )
    # if the user is already in the list of users, remove them
    if request.user in my_outing.users.all():
        my_outing.users.remove(request.user)
    else:
        my_outing.users.add(request.user)

    return HttpResponseRedirect(
        reverse("spring_cleanup:route_detail", kwargs={"pk": my_route.id}))
Пример #16
0
    def save(self, *args, **kwargs):
        self.fiscal_year_id = fiscal_year(self.application_end_date,
                                          sap_style=True)

        # look at the review to help determine the status
        self.status = 10  # draft
        if self.submission_date:
            self.status = 20  # submitted
        elif self.submission_date and hasattr(
                self, "recommendation") and self.recommendation.id:
            self.status = 30  # submitted
            if self.recommendation.manager_signed:
                self.status = 40  #
            if self.recommendation.applicant_signed:
                self.status = 50  #
        super().save(*args, **kwargs)
Пример #17
0
 def get_context_data(self, **kwargs):
     context = super().get_context_data(**kwargs)
     context["current_fy"] = fiscal_year()
     # send in the name of the project's first fiscal year
     context["first_year"] = context["object"].project.years.first(
     ).fiscal_year.full
     # currently field are being called manually into a table. This can be improved when time permits
     context["field_list"] = [
         'annual_funding',
     ]
     context["my_payment"] = models.Payment.objects.first()
     context["payment_field_list"] = [
         # 'project_year',
         'claim_number',
         'disbursement|Total amount',
         'from_period',
         'to_period',
         'final_payment',
         'materials_submitted',
         'nhq_notified',
         'payment_confirmed',
         'notes',
     ]
     return context
Пример #18
0
class Project(models.Model):
    # choices for is_national
    is_national_choices = (
        (None, _("Unknown")),
        (1, _("National")),
        (0, _("Regional")),
    )

    year = models.ForeignKey(shared_models.FiscalYear,
                             on_delete=models.DO_NOTHING,
                             blank=True,
                             null=True,
                             related_name="projects",
                             verbose_name=_("fiscal year"),
                             default=fiscal_year(next=True, sap_style=True))
    # basic
    section = models.ForeignKey(shared_models.Section,
                                on_delete=models.DO_NOTHING,
                                null=True,
                                related_name="projects",
                                verbose_name=_("section"))
    project_title = custom_widgets.OracleTextField(
        verbose_name=_("Project title"))
    activity_type = models.ForeignKey(ActivityType,
                                      on_delete=models.DO_NOTHING,
                                      blank=False,
                                      null=True,
                                      verbose_name=_("activity type"))
    functional_group = models.ForeignKey(FunctionalGroup,
                                         on_delete=models.DO_NOTHING,
                                         blank=True,
                                         null=True,
                                         related_name="projects",
                                         verbose_name=_("Functional group"))
    default_funding_source = models.ForeignKey(
        FundingSource,
        on_delete=models.DO_NOTHING,
        blank=False,
        null=True,
        related_name="projects",
        verbose_name=_("primary funding source"))
    tags = models.ManyToManyField(
        Tag,
        blank=True,
        verbose_name=_("Tags / keywords (used for searching)"),
        related_name="projects")

    # details
    is_national = models.IntegerField(blank=True,
                                      null=True,
                                      default=False,
                                      verbose_name=_("National or regional?"),
                                      choices=is_national_choices)
    status = models.ForeignKey(Status,
                               on_delete=models.DO_NOTHING,
                               blank=True,
                               null=True,
                               verbose_name=_("project status"),
                               limit_choices_to={"used_for": 1})

    # DELETE ME!!!! ############################################
    is_competitive = models.IntegerField(
        blank=True,
        null=True,
        choices=NULL_YES_NO_CHOICES,
        default=0,
        verbose_name=_("Is the funding competitive?"))
    # DELETE ME!!!! ############################################
    is_approved = models.IntegerField(
        blank=True,
        null=True,
        choices=NULL_YES_NO_CHOICES,
        verbose_name=_("Has this project already been approved"))

    start_date = models.DateTimeField(blank=True,
                                      null=True,
                                      verbose_name=_("Start date of project"))
    end_date = models.DateTimeField(blank=True,
                                    null=True,
                                    verbose_name=_("End date of project"))

    # HTML field
    description = models.TextField(
        blank=True,
        null=True,
        verbose_name=_("Project objective & description"))
    # description_html = models.TextField(blank=True, null=True, verbose_name=_("Project objective & description"))

    # HTML field
    priorities = models.TextField(
        blank=True, null=True, verbose_name=_("Project-specific priorities"))
    # HTML field
    deliverables = models.TextField(
        blank=True,
        null=True,
        verbose_name=_("Project deliverables / activities"))

    # SPECIALIZED EQUIPMENT
    ########################
    requires_specialized_equipment = models.BooleanField(
        default=False,
        verbose_name=
        _("Will the project require the purchase, design or fabrication of specialized laboratory or field equipment?"
          ))
    technical_service_needs = models.TextField(
        blank=True,
        null=True,
        verbose_name=_("What technical services are being requested?"))
    mobilization_needs = models.TextField(
        blank=True,
        null=True,
        verbose_name=
        _("Do you anticipate needing assistance with mobilization/demobilization of this equipment?"
          ))

    # TRAVEL
    ########
    has_travel = models.BooleanField(
        default=False,
        verbose_name=_("Does this project involved a field component?"))
    vehicle_needs = models.TextField(
        blank=True,
        null=True,
        verbose_name=
        _("Describe need for vehicle (type of vehicle, number of weeks, time-frame)"
          ))
    ship_needs = models.TextField(
        blank=True,
        null=True,
        verbose_name=_("Ship (Coast Guard, charter vessel) Requirements"))
    coip_reference_id = models.CharField(
        max_length=100,
        blank=True,
        null=True,
        verbose_name=
        _("If this project links to a ship time request in COIP, please include the COIP application number here."
          ))
    instrumentation = models.TextField(
        blank=True,
        null=True,
        verbose_name=_(
            "What field instrumentation will be deployed during this project?")
    )
    owner_of_instrumentation = models.CharField(
        max_length=500,
        blank=True,
        null=True,
        verbose_name=_(
            "Who is the owner/curator of this instrumentation, if known?"))
    # -- > Field staff
    requires_field_staff = models.BooleanField(
        default=False, verbose_name=_("Do you require field support staff?"))
    field_staff_needs = models.TextField(
        blank=True,
        null=True,
        verbose_name=
        _("If so, please include some additional detail, e.g., how many people are likely to be required and when"
          ))

    # DATA
    #######
    has_new_data = models.BooleanField(
        default=False,
        verbose_name=_("Will new data be collected or generated?"))
    data_collection = models.TextField(
        blank=True,
        null=True,
        verbose_name=_("What type of data will be collected"))
    data_products = models.TextField(
        blank=True,
        null=True,
        verbose_name=_(
            "What data products will be generated (e.g. models, indices)?"))
    open_data_eligible = models.BooleanField(
        default=True,
        verbose_name=
        _("Are these data / data products eligible to be placed on the Open Data Platform?"
          ))
    data_storage = models.TextField(
        blank=True, null=True, verbose_name=_("Data storage / archiving Plan"))
    regional_dm_needs = models.TextField(
        blank=True,
        null=True,
        verbose_name=_(
            "Describe what data management support is required, if any."))

    # LAB WORK
    ##########
    has_lab_work = models.BooleanField(
        default=False,
        verbose_name=_("Does this project involve laboratory work?"))
    # maritimes only
    abl_services_required = models.BooleanField(
        default=False,
        verbose_name=
        _("Does this project require the services of Aquatic Biotechnology Lab (ABL)?"
          ))
    lab_space_required = models.BooleanField(
        default=False, verbose_name=_("Is laboratory space required?"))
    requires_other_lab_support = models.BooleanField(
        default=False,
        verbose_name=
        _("Does this project require other specialized laboratory support or services (provide details below)?"
          ))
    other_lab_support_needs = models.TextField(
        blank=True,
        null=True,
        verbose_name=
        _("Describe other laboratory requirements relevant for project planning purposes."
          ))

    it_needs = models.TextField(
        blank=True,
        null=True,
        verbose_name=_(
            "Special IT requirements (software, licenses, hardware)"))
    notes = models.TextField(blank=True,
                             null=True,
                             verbose_name=_("additional notes"))

    # coding
    responsibility_center = models.ForeignKey(
        shared_models.ResponsibilityCenter,
        on_delete=models.DO_NOTHING,
        blank=True,
        null=True,
        related_name='projects_projects',
        verbose_name=_("responsibility center (if known)"))
    allotment_code = models.ForeignKey(
        shared_models.AllotmentCode,
        on_delete=models.DO_NOTHING,
        blank=True,
        null=True,
        related_name='projects_projects',
        verbose_name=_("allotment code (if known)"))
    existing_project_codes = models.ManyToManyField(
        shared_models.Project,
        blank=True,
        verbose_name=_("existing project codes (if known)"))

    # admin
    submitted = models.BooleanField(
        default=False, verbose_name=_("Submit project for review"))
    # approved = models.BooleanField(default=False, verbose_name=_("approved"))
    recommended_for_funding = models.BooleanField(
        default=False, verbose_name=_("recommended"))
    approved = models.IntegerField(blank=True,
                                   null=True,
                                   choices=NULL_YES_NO_CHOICES,
                                   verbose_name=_("approved"))
    allocated_budget = models.FloatField(blank=True,
                                         null=True,
                                         verbose_name=_("Allocated budget"))
    notification_email_sent = models.DateTimeField(
        blank=True,
        null=True,
        verbose_name=_("Notification Email Sent"),
        editable=False)
    meeting_notes = models.TextField(blank=True,
                                     null=True,
                                     verbose_name=_("administrative notes"))

    is_hidden = models.IntegerField(
        blank=True,
        null=True,
        choices=NULL_YES_NO_CHOICES,
        default=False,
        verbose_name=_("Should the project be hidden from other users?"))

    date_last_modified = models.DateTimeField(
        blank=True,
        null=True,
        default=timezone.now,
        verbose_name=_("date last modified"))
    last_modified_by = models.ForeignKey(User,
                                         on_delete=models.DO_NOTHING,
                                         blank=True,
                                         null=True,
                                         verbose_name=_("last modified by"))

    class Meta:
        ordering = ['id']

    def __str__(self):
        return "{}".format(self.project_title)

    def send_approval_email(self, request):
        if self.approved is not None and not self.notification_email_sent:
            email = emails.ProjectApprovalEmail(self, request)
            # send the email object
            custom_send_mail(subject=email.subject,
                             html_message=email.message,
                             from_email=email.from_email,
                             recipient_list=email.to_list)
            self.notification_email_sent = timezone.now()
            self.save()

    def save(self, *args, **kwargs):
        self.date_last_modified = timezone.now()

        super().save(*args, **kwargs)

    @property
    def status_report_count(self):
        return self.reports.count()

    @property
    def unapproved(self):
        return self.submitted and not self.approved

    @property
    def coding(self):
        if self.responsibility_center:
            rc = self.responsibility_center.code
        else:
            rc = "xxxxx"
        if self.allotment_code:
            ac = self.allotment_code.code
        else:
            ac = "xxx"

        if self.existing_project_codes.count() >= 1:
            pc = listrify([
                project_code.code
                for project_code in self.existing_project_codes.all()
            ])
            if self.existing_project_codes.count() > 1:
                pc = "[" + pc + "]"
        else:
            pc = "xxxxx"
        return "{}-{}-{}".format(rc, ac, pc)

    def get_funding_sources(self):
        # look through all expenses and compile a unique list of funding sources
        my_list = []
        for item in self.staff_members.all():
            if item.funding_source and item.cost and item.cost > 0:
                my_list.append(item.funding_source)

        for item in self.om_costs.all():
            if item.funding_source and item.budget_requested and item.budget_requested > 0:
                my_list.append(item.funding_source)

        for item in self.capital_costs.all():
            if item.funding_source and item.budget_requested and item.budget_requested > 0:
                my_list.append(item.funding_source)

        return set(my_list)

    @property
    def funding_sources(self):
        return listrify(self.get_funding_sources())

    @property
    def project_leads(self):
        return listrify(
            [staff for staff in self.staff_members.all() if staff.lead])

    @property
    def project_leads_as_users(self):
        return [
            staff.user for staff in self.staff_members.all()
            if staff.lead and staff.user
        ]

    @property
    def total_fte(self):
        return sum([
            nz(staff.duration_weeks, 0) for staff in self.staff_members.all()
        ])

    @property
    def total_ot(self):
        return sum([
            nz(staff.overtime_hours, 0) for staff in self.staff_members.all()
        ])

    @property
    def total_salary(self):
        return nz(
            self.staff_members.filter(employee_type__cost_type=1).aggregate(
                dsum=Sum("cost"))['dsum'], 0)

    @property
    def total_om(self):
        return nz(self.staff_members.filter(employee_type__cost_type=2).aggregate(dsum=Sum("cost"))['dsum'], 0) + \
               nz(self.om_costs.aggregate(dsum=Sum("budget_requested"))['dsum'], 0)

    @property
    def total_capital(self):
        return nz(
            self.capital_costs.aggregate(dsum=Sum("budget_requested"))['dsum'],
            0)

    @property
    def total_cost(self):
        return nz(self.staff_members.all().aggregate(dsum=Sum("cost"))['dsum'], 0) + \
               nz(self.om_costs.aggregate(dsum=Sum("budget_requested"))['dsum'], 0) + \
               nz(self.capital_costs.aggregate(dsum=Sum("budget_requested"))['dsum'], 0)
Пример #19
0
class Project(models.Model):
    # choices for is_national
    is_national_choices = (
        (None, _("Unknown")),
        (True, _("National")),
        (False, _("Regional")),
    )

    year = models.ForeignKey(shared_models.FiscalYear,
                             on_delete=models.DO_NOTHING,
                             blank=True,
                             null=True,
                             related_name="projects",
                             verbose_name=_("fiscal year"),
                             default=fiscal_year(next=True, sap_style=True))
    # basic
    section = models.ForeignKey(shared_models.Section,
                                on_delete=models.DO_NOTHING,
                                null=True,
                                related_name="projects",
                                verbose_name=_("section"))
    project_title = custom_widgets.OracleTextField(
        verbose_name=_("Project title"))
    activity_type = models.ForeignKey(ActivityType,
                                      on_delete=models.DO_NOTHING,
                                      blank=False,
                                      null=True,
                                      verbose_name=_("activity type"))
    functional_group = models.ForeignKey(FunctionalGroup,
                                         on_delete=models.DO_NOTHING,
                                         blank=True,
                                         null=True,
                                         related_name="projects",
                                         verbose_name=_("Functional group"))
    default_funding_source = models.ForeignKey(
        FundingSource,
        on_delete=models.DO_NOTHING,
        blank=False,
        null=True,
        related_name="projects",
        verbose_name=_("primary funding source"))
    programs = models.ManyToManyField(
        Program,
        blank=True,
        verbose_name=_("Science regional program name(s)"),
        related_name="projects")
    tags = models.ManyToManyField(
        Tag,
        blank=True,
        verbose_name=_("Tags / keywords (used for searching)"),
        related_name="projects")

    # details
    is_national = models.NullBooleanField(
        default=False,
        verbose_name=_("National or regional?"),
        choices=is_national_choices)
    status = models.ForeignKey(Status,
                               on_delete=models.DO_NOTHING,
                               blank=True,
                               null=True,
                               verbose_name=_("project status"),
                               limit_choices_to={"used_for": 1})

    # DELETE FOLLOWING TWO FIELDS
    is_competitive = models.NullBooleanField(
        default=False, verbose_name=_("Is the funding competitive?"))
    is_approved = models.NullBooleanField(
        verbose_name=_("Has this project already been approved"))

    start_date = models.DateTimeField(blank=True,
                                      null=True,
                                      verbose_name=_("Start date of project"))
    end_date = models.DateTimeField(blank=True,
                                    null=True,
                                    verbose_name=_("End date of project"))

    # HTML field
    description = models.TextField(
        blank=True,
        null=True,
        verbose_name=_("Project objective & description"))
    # description_html = models.TextField(blank=True, null=True, verbose_name=_("Project objective & description"))

    # HTML field
    priorities = models.TextField(
        blank=True, null=True, verbose_name=_("Project-specific priorities"))
    # HTML field
    deliverables = models.TextField(
        blank=True,
        null=True,
        verbose_name=_("Project deliverables / activities"))

    # data
    #######
    # HTML field
    data_collection = models.TextField(
        blank=True,
        null=True,
        verbose_name=_("What type of data will be collected"))
    # HTML field
    data_sharing = models.TextField(
        blank=True,
        null=True,
        verbose_name=
        _("Which of these data / data products will be placed on the Open Data Platform this year?"
          ))
    # HTML field
    data_storage = models.TextField(
        blank=True, null=True, verbose_name=_("Data storage / archiving Plan"))
    metadata_url = models.CharField(
        max_length=1000,
        blank=True,
        null=True,
        verbose_name=_(
            "Provide link to existing metadata record, if available"))

    # needs
    ########

    # DELETE ME!! #
    regional_dm_needs = models.TextField(
        blank=True,
        null=True,
        verbose_name=
        _("Describe assistance required from the branch data manager, if applicable"
          ))
    # DELETE ME!! #
    sectional_dm_needs = models.TextField(
        blank=True,
        null=True,
        verbose_name=
        _("Describe assistance required from the section data manager, if applicable"
          ))

    # HTML field
    vehicle_needs = models.TextField(
        blank=True,
        null=True,
        verbose_name=
        _("Describe need for vehicle (type of vehicle, number of weeks, time-frame)"
          ))
    # HTML field
    it_needs = models.TextField(
        blank=True,
        null=True,
        verbose_name=_(
            "Special IT requirements (software, licenses, hardware)"))
    # HTML field
    chemical_needs = models.TextField(
        blank=True,
        null=True,
        verbose_name=
        _("Please provide details regarding chemical needs and the plan for storage and disposal."
          ))
    # HTML field
    ship_needs = models.TextField(
        blank=True,
        null=True,
        verbose_name=_("Ship (Coast Guard, charter vessel) Requirements"))

    # HTML field
    notes = models.TextField(blank=True,
                             null=True,
                             verbose_name=_("additional notes"))

    # coding
    responsibility_center = models.ForeignKey(
        shared_models.ResponsibilityCenter,
        on_delete=models.DO_NOTHING,
        blank=True,
        null=True,
        related_name='projects_projects',
        verbose_name=_("responsibility center (if known)"))
    allotment_code = models.ForeignKey(
        shared_models.AllotmentCode,
        on_delete=models.DO_NOTHING,
        blank=True,
        null=True,
        related_name='projects_projects',
        verbose_name=_("allotment code (if known)"))
    existing_project_codes = models.ManyToManyField(
        shared_models.Project,
        blank=True,
        verbose_name=_("existing project codes (if known)"))

    feedback = models.TextField(
        blank=True,
        null=True,
        verbose_name=
        _("Do you have any feedback you would like to submit about this process"
          ))

    # admin
    submitted = models.BooleanField(
        default=False, verbose_name=_("Submit project for review"))
    # approved = models.BooleanField(default=False, verbose_name=_("approved"))
    recommended_for_funding = models.BooleanField(
        default=False, verbose_name=_("recommended"))
    approved = models.NullBooleanField(verbose_name=_("approved"))
    allocated_budget = models.FloatField(blank=True,
                                         null=True,
                                         verbose_name=_("Allocated budget"))
    notification_email_sent = models.DateTimeField(
        blank=True, null=True, verbose_name=_("Notification Email Sent"))
    # section_head_feedback = models.TextField(blank=True, null=True, verbose_name=_("section head feedback"))

    # manager_approved = models.BooleanField(default=False, verbose_name=_("division manager approved"))
    # manager_feedback = models.TextField(blank=True, null=True, verbose_name=_("division manager feedback"))

    # rds_approved = models.BooleanField(default=False, verbose_name=_("RDS approved"))
    # rds_feedback = models.TextField(blank=True, null=True, verbose_name=_("RDS feedback"))

    meeting_notes = models.TextField(blank=True,
                                     null=True,
                                     verbose_name=_("administrative notes"))

    is_hidden = models.NullBooleanField(
        default=False,
        verbose_name=_("Should the project be hidden from other users?"))

    date_last_modified = models.DateTimeField(
        blank=True,
        null=True,
        default=timezone.now,
        verbose_name=_("date last modified"))
    last_modified_by = models.ForeignKey(User,
                                         on_delete=models.DO_NOTHING,
                                         blank=True,
                                         null=True,
                                         verbose_name=_("last modified by"))

    class Meta:
        ordering = ['id']

    def __str__(self):
        return "{}".format(self.project_title)

    def send_approval_email(self, request):
        if self.approved is not None and not self.notification_email_sent:
            email = emails.ProjectApprovalEmail(self, request)
            # send the email object
            custom_send_mail(subject=email.subject,
                             html_message=email.message,
                             from_email=email.from_email,
                             recipient_list=email.to_list)
            self.notification_email_sent = timezone.now()
            self.save()

    def save(self, *args, **kwargs):
        self.date_last_modified = timezone.now()

        super().save(*args, **kwargs)

    @property
    def status_report_count(self):
        return self.reports.count()

    @property
    def unapproved(self):
        return self.submitted and not self.approved

    @property
    def coding(self):
        if self.responsibility_center:
            rc = self.responsibility_center.code
        else:
            rc = "xxxxx"
        if self.allotment_code:
            ac = self.allotment_code.code
        else:
            ac = "xxx"

        if self.existing_project_codes.count() >= 1:
            pc = listrify([
                project_code.code
                for project_code in self.existing_project_codes.all()
            ])
            if self.existing_project_codes.count() > 1:
                pc = "[" + pc + "]"
        else:
            pc = "xxxxx"
        return "{}-{}-{}".format(rc, ac, pc)

    def get_funding_sources(self):
        # look through all expenses and compile a unique list of funding sources
        my_list = []
        for item in self.staff_members.all():
            if item.funding_source and item.cost and item.cost > 0:
                my_list.append(item.funding_source)

        for item in self.om_costs.all():
            if item.funding_source and item.budget_requested and item.budget_requested > 0:
                my_list.append(item.funding_source)

        for item in self.capital_costs.all():
            if item.funding_source and item.budget_requested and item.budget_requested > 0:
                my_list.append(item.funding_source)

        return set(my_list)

    @property
    def funding_sources(self):
        return listrify(self.get_funding_sources())

    @property
    def project_leads(self):
        return listrify(
            [staff for staff in self.staff_members.all() if staff.lead])

    @property
    def project_leads_as_users(self):
        return [
            staff.user for staff in self.staff_members.all()
            if staff.lead and staff.user
        ]

    @property
    def core_status(self):
        return "/".join(
            list(
                set(([
                    program.get_is_core_display()
                    for program in self.programs.all()
                ]))))

    @property
    def total_fte(self):
        return sum([
            nz(staff.duration_weeks, 0) for staff in self.staff_members.all()
        ])

    @property
    def total_ot(self):
        return sum([
            nz(staff.overtime_hours, 0) for staff in self.staff_members.all()
        ])

    @property
    def total_salary(self):
        return nz(
            self.staff_members.filter(employee_type__cost_type=1).aggregate(
                dsum=Sum("cost"))['dsum'], 0)

    @property
    def total_om(self):
        return nz(self.staff_members.filter(employee_type__cost_type=2).aggregate(dsum=Sum("cost"))['dsum'], 0) + \
               nz(self.om_costs.aggregate(dsum=Sum("budget_requested"))['dsum'], 0)

    @property
    def total_capital(self):
        return nz(
            self.capital_costs.aggregate(dsum=Sum("budget_requested"))['dsum'],
            0)

    @property
    def total_cost(self):
        return nz(self.staff_members.all().aggregate(dsum=Sum("cost"))['dsum'], 0) + \
               nz(self.om_costs.aggregate(dsum=Sum("budget_requested"))['dsum'], 0) + \
               nz(self.capital_costs.aggregate(dsum=Sum("budget_requested"))['dsum'], 0)
Пример #20
0
 def get_initial(self):
     return {
         'fiscal_year': fiscal_year(sap_style=True),
         'created_by': self.request.user,
         'do_another': 1,
     }