django.utils.timezone.localdate

Here are the examples of the python api django.utils.timezone.localdate taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

70 Examples 7

3 Source : dates.py
with GNU General Public License v3.0
from Aghoreshwar

def timezone_today():
    """Return the current date in the current time zone."""
    if settings.USE_TZ:
        return timezone.localdate()
    else:
        return datetime.date.today()

3 Source : tasks.py
with MIT License
from ArionMiles

def check_reminders_job():
    # Mark reminders with at least one theater found AND date lt today as complete
    Reminder.objects.filter(theaterlink__found=True, date__lt=timezone.localdate(), completed=False, dropped=False).update(completed=True)
    # Drop reminders with date lt today (these have no theaters found)
    Reminder.objects.filter(completed=False, dropped=False, date__lt=timezone.localdate()).update(dropped=True)
    # Search for all movies which have movie date set to today or sometime in the future.
    pending_reminders = Reminder.objects.filter(completed=False, dropped=False, date__gte=timezone.localdate())

    # Segregating reminders into regions
    reminders_by_region = defaultdict(list)
    for reminder in pending_reminders:
        reminders_by_region[reminder.user.profile.region].append(reminder)

    logger.info("Running job for {} movies.".format(len(pending_reminders)))
    for region, reminders in reminders_by_region.items():
        bms = BMS(region.code, region.name)
        for reminder in reminders:
            check_reminders(bms, reminder)

3 Source : views.py
with MIT License
from ArionMiles

    def get(self, request):
        user_region = self.request.user.profile.region
        bms = BMS(user_region.code, user_region.name)
        data = bms.get_movie_list()
        data += bms.get_coming_soon(settings.BMS_TOKEN, 20, timezone.localdate())
        return JsonResponse({'movies': data, 'status':'ok'})

class TrendingView(LoginRequiredMixin, RegionExistsMixin, TemplateView):

3 Source : mixins.py
with GNU General Public License v3.0
from arrobalytics

    def due_in_days(self):
        td = self.due_date - localdate()
        if td.days   <   0:
            return 0
        return td.days

    def is_past_due(self):

3 Source : purchase_order.py
with GNU General Public License v3.0
from arrobalytics

    def clean(self):
        if self.fulfilled and self.po_status != PurchaseOrderModel.PO_STATUS_APPROVED:
            raise ValidationError('Can only fulfill POs thjat have been approved.')

        if not self.po_number:
            self.po_number = generate_po_number()

        if self.fulfillment_date:
            self.fulfilled = True
        if self.fulfilled:
            self.po_amount_received = self.po_amount
        if self.fulfilled and not self.fulfillment_date:
            self.fulfillment_date = localdate()

    def get_po_item_data(self, queryset: QuerySet = None) -> Tuple:

3 Source : utils.py
with GNU General Public License v3.0
from arrobalytics

def get_end_date_from_session(entity_slug: str, request) -> date:
    session_end_date_filter = get_end_date_session_key(entity_slug)
    end_date = request.session.get(session_end_date_filter)
    end_date = parse_date(end_date) if end_date else localdate()
    return end_date


def prepare_context_by_unit(context: dict):

3 Source : account.py
with GNU General Public License v3.0
from arrobalytics

    def get_redirect_url(self, *args, **kwargs):
        loc_date = localdate()
        return reverse('django_ledger:account-detail-month',
                       kwargs={
                           'entity_slug': self.kwargs['entity_slug'],
                           'account_pk': self.kwargs['account_pk'],
                           'year': loc_date.year,
                           'month': loc_date.month,
                       })


class AccountModelYearDetailView(LoginRequiredMixIn,

3 Source : bill.py
with GNU General Public License v3.0
from arrobalytics

    def get_initial(self):
        return {
            'date': localdate()
        }

    def get_form(self, form_class=None):

3 Source : journal_entry.py
with GNU General Public License v3.0
from arrobalytics

    def get_initial(self):
        return {
            'date': localdate(),
            'ledger': LedgerModel.objects.for_entity(
                entity_slug=self.kwargs['entity_slug'],
                user_model=self.request.user
            ).get(uuid__exact=self.kwargs['ledger_pk'])
        }

    def get_success_url(self):

3 Source : purchase_order.py
with GNU General Public License v3.0
from arrobalytics

    def get_initial(self):
        return {
            'for_inventory': False,
            'po_date': localdate()
        }

    def get_form(self, form_class=None):

3 Source : tests_process.py
with GNU Affero General Public License v3.0
from betagouv

    def test_cannot_cancel(self, *args, **kwargs):
        job_application = JobApplicationWithApprovalFactory(
            state=JobApplicationWorkflow.STATE_ACCEPTED,
            hiring_start_at=timezone.localdate() + relativedelta(days=1),
        )
        siae_user = job_application.to_siae.members.first()
        # Add a blocking employee record
        EmployeeRecordFactory(job_application=job_application, status=EmployeeRecord.Status.PROCESSED)

        self.client.login(username=siae_user.email, password=DEFAULT_PASSWORD)
        url = reverse("apply:cancel", kwargs={"job_application_id": job_application.pk})
        response = self.client.get(url)
        next_url = reverse("apply:details_for_siae", kwargs={"job_application_id": job_application.pk})
        self.assertRedirects(response, next_url)

        job_application.refresh_from_db()
        self.assertFalse(job_application.state.is_cancelled)

    def test_accept_after_cancel(self, *args, **kwargs):

3 Source : dates.py
with MIT License
from chunky2808

def timezone_today():
    """
    Return the current date in the current time zone.
    """
    if settings.USE_TZ:
        return timezone.localdate()
    else:
        return datetime.date.today()

3 Source : model_complaint.py
with MIT License
from fga-eps-mds

    def clean(self, *args, **kwargs):
        if self.complaint_day:
            if timezone.localdate().isoformat()   <   str(self.complaint_day):
                raise ValidationError(
                    {'complaint_day':
                        _("The complaint cannot be in the future!")}
                )

        return super(Complaint, self).clean()

    def __str__(self):

3 Source : test_model_user.py
with MIT License
from fga-eps-mds

    def test_invalid_birthday(self):
        today = timezone.localdate()
        tomorrow = today + relativedelta(days=1)
        past = date(1800, 1, 1)

        with self.assertRaises(ValidationError):
            self.user.birthday = tomorrow
            self.user.save()
            self.user.clean()

        with self.assertRaises(ValidationError):
            self.user.birthday = past
            self.user.save()
            self.user.clean()


class TestField(TestCase):

3 Source : export.py
with MIT License
from g0v

    def is_end_of_sth(self):
        today = timezone.localdate()
        tomorrow = today + timedelta(days=1)

        is_end_of_month = today.month != tomorrow.month
        is_end_of_quarter = False
        is_end_of_year = False

        if is_end_of_month:
            is_end_of_quarter = today.month % 3 == 0
            is_end_of_year = today.month == 12

        return {
            'month': is_end_of_month,
            'quarter': is_end_of_quarter,
            'year': is_end_of_year
        }

    def zip_everything(self, tmp_dir, prefix, type='raw'):

3 Source : test_timezone.py
with Apache License 2.0
from gethue

    def test_localdate(self):
        naive = datetime.datetime(2015, 1, 1, 0, 0, 1)
        with self.assertRaisesMessage(ValueError, 'localtime() cannot be applied to a naive datetime'):
            timezone.localdate(naive)
        with self.assertRaisesMessage(ValueError, 'localtime() cannot be applied to a naive datetime'):
            timezone.localdate(naive, timezone=EAT)

        aware = datetime.datetime(2015, 1, 1, 0, 0, 1, tzinfo=ICT)
        self.assertEqual(timezone.localdate(aware, timezone=EAT), datetime.date(2014, 12, 31))
        with timezone.override(EAT):
            self.assertEqual(timezone.localdate(aware), datetime.date(2014, 12, 31))

        with mock.patch('django.utils.timezone.now', return_value=aware):
            self.assertEqual(timezone.localdate(timezone=EAT), datetime.date(2014, 12, 31))
            with timezone.override(EAT):
                self.assertEqual(timezone.localdate(), datetime.date(2014, 12, 31))

    def test_override(self):

3 Source : models.py
with GNU General Public License v3.0
from jonaswinkler

    def __str__(self):
        if is_aware(self.created):
            created = timezone.localdate(self.created).isoformat()
        else:
            created = datetime.date.isoformat(self.created)
        if self.correspondent and self.title:
            return f"{created} {self.correspondent} {self.title}"
        else:
            return f"{created} {self.title}"

    @property

3 Source : calendar.py
with BSD 3-Clause "New" or "Revised" License
from linuxsoftware

    def _getCommonContext(self, request):
        cxt = self.get_context(request)
        cxt.update({'version':  __version__,
                    'themeCSS': getattr(settings, "JOYOUS_THEME_CSS", ""),
                    'today':    timezone.localdate(),

                    # Init these variables to prevent template DEBUG messages
                    'listLink':     None,
                    'weeklyLink':   None,
                    'monthlyLink':  None,
                   })
        return cxt

    def _getExtraContext(self, route):

3 Source : recurring_events.py
with BSD 3-Clause "New" or "Revised" License
from linuxsoftware

    def _getFromTime(self, atDate=None):
        """
        What was the time of this event?  Due to time zones that depends what
        day we are talking about.  If no day is given, assume today.

        :param atDate: day in local timezone for which we want the time_from
        :rtype: time_from in local timezone
        """
        if atDate is None:
            atDate = timezone.localdate()
        return getLocalTimeAtDate(atDate, self.time_from, self.tz)

    def _futureExceptions(self, request):

3 Source : test_getevents.py
with BSD 3-Clause "New" or "Revised" License
from linuxsoftware

    def testGetAllCurrentEvents(self):
        today = timezone.localdate()
        futureEvent = MultidayEventPage(owner = self.user,
                                        slug  = "yesterday",
                                        title = "Yesterday's Event",
                                        date_from = today - dt.timedelta(days=1),
                                        date_to   = today + dt.timedelta(days=3),
                                        time_from = dt.time(17),
                                        time_to   = dt.time(10,30))
        self.calendar.add_child(instance=futureEvent)
        events = getAllUpcomingEvents(self.request, home=self.home)
        self.assertEqual(len(events), 1)
        title, event, url = events[0]
        self.assertEqual(title, "Yesterday's Event")
        self.assertEqual(event.slug, "yesterday")
        events0 = getAllUpcomingEvents(self.request)
        self.assertEqual(len(events0), 1)

    def testGetAllPastEvents(self):

3 Source : widgets.py
with BSD 3-Clause "New" or "Revised" License
from linuxsoftware

    def valid_dates(self):
        valid_dates = None # null in JS
        if self.overrides_repeat:
            today = timezone.localdate()
            past = (today - dt.timedelta(days=200)).replace(day=1)
            future = (today + dt.timedelta(days=600)).replace(day=1)
            valid_dates = ["{:%Y%m%d}".format(occurence) for occurence in
                           self.overrides_repeat.between(past, future, inc=True)]
        return valid_dates

    @property

3 Source : views.py
with MIT License
from silviogutierrez

def storyboard(request: HttpRequest) -> HttpResponse:
    form = forms.StoryboardForm(
        request.POST or None,
        initial={
            "char_field": "Ok",
            "integer_field": 7,
            "date_field": timezone.localdate(),
            "date_time_field": timezone.now(),
            "enum_field": models.Opera.Style.VERISMO,
            "boolean_field": True,
        },
    )
    return templates.Storyboard(
        form=form,
    ).render(request)

3 Source : utils.py
with Apache License 2.0
from UniversitaDellaCalabria

def _successivo_ad_oggi(data_da_valutare):
    """
    Ci dice se una data è successiva alla data di oggi
    """
    oggi = timezone.localdate()
    if data_da_valutare:
        return data_da_valutare > oggi


# Unused formset method
def get_formset_dict(data, clean=False):

0 Source : io_mixin.py
with GNU General Public License v3.0
from arrobalytics

def validate_io_date(dt: str or date or datetime, no_parse_locadate: bool = True):
    if isinstance(dt, date):
        return dt
    elif isinstance(dt, datetime):
        if is_naive(dt):
            return make_aware(dt).date
        return dt.date
    elif isinstance(dt, str):
        # try to parse a date object from string...
        fdt = parse_date(dt)
        if not fdt:
            # try to parse a datetime object from string...
            fdt = parse_datetime(dt)
            if not fdt:
                raise InvalidDateInputException(
                    message=f'Could not parse date from {dt}'
                )
            elif is_naive(fdt):
                return make_aware(fdt).date
            return fdt.date
        return fdt
    if no_parse_locadate:
        return localdate()
    return


def validate_dates(

0 Source : mixins.py
with GNU General Public License v3.0
from arrobalytics

    def mark_as_paid(self,
                     user_model,
                     entity_slug: str,
                     paid_date: date = None,
                     itemthrough_queryset=None,
                     commit: bool = False):

        self.paid = True
        self.progress = Decimal.from_float(1.0)
        self.amount_paid = self.amount_due
        paid_dt = localdate() if not paid_date else paid_date

        if not self.paid_date:
            self.paid_date = paid_dt
        if self.paid_date > paid_dt:
            raise ValidationError(f'Cannot pay {self.__class__.__name__} in the future.')
        if self.paid_date   <   self.date:
            raise ValidationError(f'Cannot pay {self.__class__.__name__} before {self.__class__.__name__}'
                                  f' date {self.date}.')
        self.update_state()
        self.clean()
        if commit:
            self.migrate_state(
                user_model=user_model,
                entity_slug=entity_slug,
                itemthrough_queryset=itemthrough_queryset
            )
            ledger_model = self.ledger
            ledger_model.locked = True
            # pylint: disable=no-member
            ledger_model.save(update_fields=['locked', 'updated'])
            self.save()

    def migrate_state(self,

0 Source : mixins.py
with GNU General Public License v3.0
from arrobalytics

    def migrate_state(self,
                      user_model,
                      entity_slug: str,
                      itemthrough_queryset: QuerySet = None,
                      force_migrate: bool = False,
                      commit: bool = True,
                      void: bool = False,
                      je_date: date = None):

        if not self.migrate_allowed() and not force_migrate:
            raise ValidationError(f'{self.REL_NAME_PREFIX.upper()} state migration not allowed')

        # getting current ledger state
        # pylint: disable=no-member
        txs_qs, txs_digest = self.ledger.digest(
            user_model=user_model,
            process_groups=True,
            process_roles=False,
            process_ratios=False,
            signs=False,
            by_unit=True
        )

        digest_data = txs_digest['tx_digest']['accounts']

        # Index (account_uuid, unit_uuid, balance_type, role)
        current_ledger_state = {
            (a['account_uuid'], a['unit_uuid'], a['balance_type']): a['balance'] for a in digest_data
            # (a['account_uuid'], a['unit_uuid'], a['balance_type'], a['role']): a['balance'] for a in digest_data
        }

        item_data = list(self.get_item_data(entity_slug=entity_slug, queryset=itemthrough_queryset))
        cogs_adjustment = defaultdict(lambda: Decimal('0.00'))
        inventory_adjustment = defaultdict(lambda: Decimal('0.00'))
        progress = self.get_progress()

        if isinstance(self, lazy_loader.get_bill_model()):

            for item in item_data:
                account_uuid_expense = item.get('item_model__expense_account__uuid')
                account_uuid_inventory = item.get('item_model__inventory_account__uuid')
                if account_uuid_expense:
                    item['account_uuid'] = account_uuid_expense
                    item['account_balance_type'] = item.get('item_model__expense_account__balance_type')
                elif account_uuid_inventory:
                    item['account_uuid'] = account_uuid_inventory
                    item['account_balance_type'] = item.get('item_model__inventory_account__balance_type')

        elif isinstance(self, lazy_loader.get_invoice_model()):

            for item in item_data:

                account_uuid_earnings = item.get('item_model__earnings_account__uuid')
                account_uuid_cogs = item.get('item_model__cogs_account__uuid')
                account_uuid_inventory = item.get('item_model__inventory_account__uuid')

                if account_uuid_earnings:
                    item['account_uuid'] = account_uuid_earnings
                    item['account_balance_type'] = item.get('item_model__earnings_account__balance_type')

                if account_uuid_cogs and account_uuid_inventory:

                    try:
                        irq = item.get('item_model__inventory_received')
                        irv = item.get('item_model__inventory_received_value')
                        tot_amt = 0
                        if irq is not None and irv is not None and irq != 0:
                            qty = item.get('quantity', Decimal('0.00'))
                            if not isinstance(qty, Decimal):
                                qty = Decimal.from_float(qty)
                            cogs_unit_cost = irv / irq
                            tot_amt = round(cogs_unit_cost * qty, 2)
                    except ZeroDivisionError:
                        tot_amt = 0

                    if tot_amt != 0:
                        # keeps track of necessary transactions to increase COGS account...
                        cogs_adjustment[(
                            account_uuid_cogs,
                            item.get('entity_unit__uuid'),
                            item.get('item_model__cogs_account__balance_type')
                        )] += tot_amt * progress

                        # keeps track of necessary transactions to reduce inventory account...
                        inventory_adjustment[(
                            account_uuid_inventory,
                            item.get('entity_unit__uuid'),
                            item.get('item_model__inventory_account__balance_type')
                        )] -= tot_amt * progress

        item_data_gb = groupby(item_data,
                               key=lambda a: (a['account_uuid'],
                                              a['entity_unit__uuid'],
                                              a['account_balance_type']))

        # scaling down item amount based on progress...
        progress_item_idx = {
            idx: round(sum(a['account_unit_total'] for a in ad) * progress, 2) for idx, ad in item_data_gb
        }

        # tuple ( unit_uuid, total_amount ) sorted by uuid...
        # sorting before group by...
        ua_gen = list((k[1], v) for k, v in progress_item_idx.items())
        ua_gen.sort(key=lambda a: str(a[0]) if a[0] else '')

        unit_amounts = {
            u: sum(a[1] for a in l) for u, l in groupby(ua_gen, key=lambda x: x[0])
        }
        total_amount = sum(unit_amounts.values())

        # { unit_uuid: float (percent) }
        unit_percents = {
            k: (v / total_amount) if progress and total_amount else Decimal('0.00') for k, v in unit_amounts.items()
        }

        if not void:
            new_state = self.new_state(commit=commit)
        else:
            new_state = self.void_state(commit=commit)

        amount_paid_split = self.split_amount(
            amount=new_state['amount_paid'],
            unit_split=unit_percents,
            account_uuid=self.cash_account_id,
            account_balance_type='debit'
        )
        amount_prepaid_split = self.split_amount(
            amount=new_state['amount_receivable'],
            unit_split=unit_percents,
            account_uuid=self.prepaid_account_id,
            account_balance_type='debit'
        )
        amount_unearned_split = self.split_amount(
            amount=new_state['amount_unearned'],
            unit_split=unit_percents,
            account_uuid=self.unearned_account_id,
            account_balance_type='credit'
        )

        new_ledger_state = dict()
        new_ledger_state.update(amount_paid_split)
        new_ledger_state.update(amount_prepaid_split)
        new_ledger_state.update(amount_unearned_split)

        if inventory_adjustment and cogs_adjustment:
            new_ledger_state.update(cogs_adjustment)
            new_ledger_state.update(inventory_adjustment)

        new_ledger_state.update(progress_item_idx)

        # list of all keys involved
        idx_keys = set(list(current_ledger_state) + list(new_ledger_state))

        # difference between new vs current
        diff_idx = {
            k: new_ledger_state.get(k, Decimal('0.00')) - current_ledger_state.get(k, Decimal('0.00')) for k in
            idx_keys if new_ledger_state.get(k, Decimal('0.00')) != Decimal('0.00')
        }

        if commit:
            JournalEntryModel = lazy_loader.get_journal_entry_model()
            TransactionModel = lazy_loader.get_transaction_model()

            unit_uuids = list(set(k[1] for k in idx_keys))
            now_date = localdate() if not je_date else je_date
            je_list = {
                u: JournalEntryModel(
                    entity_unit_id=u,
                    date=now_date,
                    description=self.get_migrate_state_desc(),
                    activity='op',
                    origin='migration',
                    locked=True,
                    posted=True,
                    ledger_id=self.ledger_id
                ) for u in unit_uuids
            }

            for u, je in je_list.items():
                je.clean(verify_txs=False)

            JournalEntryModel.objects.bulk_create(
                je for _, je in je_list.items()
            )

            txs_list = [
                (unit_uuid, TransactionModel(
                    journal_entry=je_list.get(unit_uuid),
                    amount=abs(round(amt, 2)),
                    tx_type=self.get_tx_type(acc_bal_type=bal_type, adjustment_amount=amt),
                    account_id=acc_uuid,
                    description=self.get_migrate_state_desc()
                )) for (acc_uuid, unit_uuid, bal_type), amt in diff_idx.items() if amt
            ]

            for unit_uuid, tx in txs_list:
                tx.clean()

            for uid in unit_uuids:
                # validates each unit txs independently...
                balance_tx_data(tx_data=[tx for ui, tx in txs_list if uid == ui], perform_correction=True)

            # validates all txs as a whole (for safety)...
            txs = [tx for ui, tx in txs_list]
            balance_tx_data(tx_data=txs, perform_correction=True)
            TransactionModel.objects.bulk_create(txs)
        return item_data, digest_data

    def void_state(self, commit: bool = False):

0 Source : mixins.py
with GNU General Public License v3.0
from arrobalytics

    def is_past_due(self):
        return not self.paid if self.paid else self.due_date   <   localdate()

    def net_due_group(self):

0 Source : mixins.py
with GNU General Public License v3.0
from arrobalytics

    def clean(self):

        if not self.amount_due:
            self.amount_due = 0

        if not self.date:
            self.date = localdate()

        if self.cash_account_id is None:
            raise ValidationError('Must provide a cash account.')

        if self.accrue:
            if not self.prepaid_account_id:
                raise ValidationError(f'Accrued {self.__class__.__name__} must define a Prepaid Expense account.')
            if not self.unearned_account_id:
                raise ValidationError(f'Accrued {self.__class__.__name__} must define an Unearned Income account.')

        if any([
            self.cash_account_id is not None,
            self.prepaid_account_id is not None,
            self.unearned_account_id is not None
        ]):
            if not all([
                self.cash_account_id is not None,
                self.prepaid_account_id is not None,
                self.unearned_account_id is not None
            ]):
                raise ValidationError('Must provide all accounts Cash, Prepaid, UnEarned.')
            # pylint: disable=no-member
            if self.cash_account.role != ASSET_CA_CASH:
                raise ValidationError(f'Cash account must be of role {ASSET_CA_CASH}.')
            # pylint: disable=no-member
            if self.prepaid_account.role != ASSET_CA_PREPAID:
                raise ValidationError(f'Prepaid account must be of role {ASSET_CA_PREPAID}.')
            # pylint: disable=no-member
            if self.unearned_account.role != LIABILITY_CL_DEFERRED_REVENUE:
                raise ValidationError(f'Unearned account must be of role {LIABILITY_CL_DEFERRED_REVENUE}.')

        if self.accrue and self.progress is None:
            self.progress = 0

        if self.terms != self.TERMS_ON_RECEIPT:
            # pylint: disable=no-member
            self.due_date = self.date + timedelta(days=int(self.terms.split('_')[-1]))
        else:
            self.due_date = self.date

        if self.amount_due and self.amount_paid == self.amount_due:
            self.paid = True
        elif self.amount_paid > self.amount_due:
            raise ValidationError(f'Amount paid {self.amount_paid} cannot exceed amount due {self.amount_due}')

        if self.paid:
            self.progress = Decimal(1.0)
            self.amount_paid = self.amount_due
            today = localdate()

            if not self.paid_date:
                self.paid_date = today
            if self.paid_date > today:
                raise ValidationError(f'Cannot pay {self.__class__.__name__} in the future.')
            if self.paid_date   <   self.date:
                raise ValidationError(f'Cannot pay {self.__class__.__name__} before {self.__class__.__name__}'
                                      f' date {self.date}.')
        else:
            self.paid_date = None

        if self.void and not all([
            self.amount_paid == 0,
            self.amount_earned == 0,
            self.amount_unearned == 0,
            self.amount_due == 0
        ]):
            raise ValidationError('Voided element cannot have any balance.')

        if self.migrate_allowed():
            self.update_state()


class MarkdownNotesMixIn(models.Model):

0 Source : purchase_order.py
with GNU General Public License v3.0
from arrobalytics

    def mark_as_fulfilled(self,
                          date: datetime.date = None,
                          po_items: Union[QuerySet, List[ItemThroughModel]] = None,
                          commit=False):
        self.clean()

        if not date and not self.po_date:
            date = localdate()

        elif date and self.po_date:
            if date   <   self.po_date:
                raise ValidationError(f'Cannot fulfill PO with date earlier than PO date {self.po_date}')

        if not po_items:
            po_items, agg = self.get_po_item_data()

        bill_models = [i.bill_model for i in po_items]

        all_items_billed = all(bill_models)
        if not all_items_billed:
            raise ValidationError('All items must be billed before PO can be fulfilled.')

        all_bills_paid = all(b.paid for b in bill_models)
        if not all_bills_paid:
            raise ValidationError('All Bills must be paid before PO can be fulfilled.')

        self.fulfillment_date = date
        self.fulfilled = True

        self.clean()

        if commit:
            update_fields = [
                'fulfilled',
                'fulfillment_date',
                'updated'
            ]
            self.save(update_fields=update_fields)


class PurchaseOrderModel(PurchaseOrderModelAbstract):

0 Source : django_ledger.py
with GNU General Public License v3.0
from arrobalytics

def period_navigation(context, base_url: str):
    KWARGS = dict()
    entity_slug = context['view'].kwargs['entity_slug']
    KWARGS['entity_slug'] = entity_slug

    if context['view'].kwargs.get('ledger_pk'):
        KWARGS['ledger_pk'] = context['view'].kwargs.get('ledger_pk')

    if context['view'].kwargs.get('account_pk'):
        KWARGS['account_pk'] = context['view'].kwargs.get('account_pk')

    if context['view'].kwargs.get('unit_slug'):
        KWARGS['unit_slug'] = context['view'].kwargs.get('unit_slug')

    ctx = dict()
    ctx['year'] = context['year']
    ctx['has_year'] = context.get('has_year')
    ctx['has_quarter'] = context.get('has_quarter')
    ctx['has_month'] = context.get('has_month')
    ctx['has_date'] = context.get('has_date')
    ctx['previous_year'] = context['previous_year']

    KWARGS['year'] = context['previous_year']
    ctx['previous_year_url'] = reverse(f'django_ledger:{base_url}-year', kwargs=KWARGS)
    ctx['next_year'] = context['next_year']

    KWARGS['year'] = context['next_year']
    ctx['next_year_url'] = reverse(f'django_ledger:{base_url}-year', kwargs=KWARGS)

    KWARGS['year'] = context['year']
    ctx['current_year_url'] = reverse(f'django_ledger:{base_url}-year', kwargs=KWARGS)

    dt = localdate()
    KWARGS_CURRENT_MONTH = {
        'entity_slug': context['view'].kwargs['entity_slug'],
        'year': dt.year,
        'month': dt.month
    }
    if 'unit_slug' in KWARGS:
        KWARGS_CURRENT_MONTH['unit_slug'] = KWARGS['unit_slug']
    if 'account_pk' in KWARGS:
        KWARGS_CURRENT_MONTH['account_pk'] = KWARGS['account_pk']
    if 'ledger_pk' in KWARGS:
        KWARGS_CURRENT_MONTH['ledger_pk'] = KWARGS['ledger_pk']

    ctx['current_month_url'] = reverse(f'django_ledger:{base_url}-month',
                                       kwargs=KWARGS_CURRENT_MONTH)

    quarter_urls = list()
    ctx['quarter'] = context.get('quarter')
    for Q in range(1, 5):
        KWARGS['quarter'] = Q
        quarter_urls.append({
            'url': reverse(f'django_ledger:{base_url}-quarter', kwargs=KWARGS),
            'quarter': Q,
            'quarter_name': f'Q{Q}'
        })
    del KWARGS['quarter']
    ctx['quarter_urls'] = quarter_urls

    month_urls = list()
    ctx['month'] = context.get('month')
    for M in range(1, 13):
        KWARGS['month'] = M
        month_urls.append({
            'url': reverse(f'django_ledger:{base_url}-month', kwargs=KWARGS),
            'month': M,
            'month_abbr': month_abbr[M]
        })
    ctx['month_urls'] = month_urls
    ctx['from_date'] = context['from_date']
    ctx['to_date'] = context['to_date']
    ctx.update(KWARGS)

    ctx['date_navigation_url'] = context.get('date_navigation_url')

    return ctx


@register.inclusion_tag('django_ledger/tags/menu.html', takes_context=True)

0 Source : test_bill.py
with GNU General Public License v3.0
from arrobalytics

    def test_bill_create(self):

        self.login_client()
        entity_model: EntityModel = choice(self.ENTITY_MODEL_QUERYSET)

        bill_create_url = reverse('django_ledger:bill-create',
                                  kwargs={
                                      'entity_slug': entity_model.slug
                                  })

        response = self.CLIENT.get(bill_create_url)

        # bill create form is rendered
        self.assertContains(response,
                            'id="djl-bill-create-form-id"',
                            msg_prefix='Bill create form is not rendered.')

        # user can select a vendor
        self.assertContains(response,
                            'id="djl-bill-create-vendor-select-input"',
                            msg_prefix='Vendor Select input not rendered.')

        # user can select bill terms...
        self.assertContains(response,
                            'id="djl-bill-create-terms-select-input"',
                            msg_prefix='Bill terms input not rendered.')

        # user can select bill terms...
        self.assertContains(response,
                            'id="djl-bill-xref-input"',
                            msg_prefix='Bill XREF input not rendered.')

        # user can select date...
        self.assertContains(response,
                            'id="djl-bill-date-input"',
                            msg_prefix='Bill XREF input not rendered.')

        # user can select cash account...
        self.assertContains(response,
                            'id="djl-bill-cash-account-input"',
                            msg_prefix='Bill cash account input not rendered.')

        # user can select prepaid account...
        self.assertContains(response,
                            'id="djl-bill-prepaid-account-input"',
                            msg_prefix='Bill prepaid account input not rendered.')

        # user can select unearned account...
        self.assertContains(response,
                            'id="djl-bill-unearned-account-input"',
                            msg_prefix='Bill unearned account input not rendered.')

        # user can select unearned account...
        self.assertContains(response,
                            'id="djl-bill-create-button"',
                            msg_prefix='Bill create button not rendered.')

        # user cannot input amount due...
        self.assertNotContains(response,
                               'id="djl-bill-amount-due-input"',
                               msg_prefix='Bill amount due input not rendered.')

        # user can navigate to bill list
        bill_list_url = reverse('django_ledger:bill-list',
                                kwargs={
                                    'entity_slug': entity_model.slug
                                })
        self.assertContains(response, bill_list_url)

        account_qs = entity_model.get_accounts(
            user_model=self.user_model
        )

        # account_queryset = entity_model.
        a_vendor_model = VendorModel.objects.for_entity(
            entity_slug=entity_model.slug,
            user_model=self.user_model
        ).first()

        bill_data = {
            'vendor': a_vendor_model.uuid,
            'date': localdate(),
            'terms': BillModel.TERMS_ON_RECEIPT
        }

        create_response = self.CLIENT.post(bill_create_url, data=bill_data, follow=True)
        self.assertFormError(create_response, form='form', field=None,
                             errors=['Must provide a cash account.'])

        bill_data['cash_account'] = account_qs.with_roles(roles=ASSET_CA_CASH).first().uuid
        create_response = self.CLIENT.post(bill_create_url, data=bill_data, follow=True)
        self.assertFormError(create_response, form='form', field=None,
                             errors=['Must provide all accounts Cash, Prepaid, UnEarned.'])

        cash_account = account_qs.with_roles(roles=ASSET_CA_PREPAID).first()
        bill_data['prepaid_account'] = cash_account.uuid
        create_response = self.CLIENT.post(bill_create_url, data=bill_data, follow=True)
        self.assertFormError(create_response, form='form', field=None,
                             errors=['Must provide all accounts Cash, Prepaid, UnEarned.'])

        del bill_data['prepaid_account']
        unearned_account = account_qs.with_roles(roles=LIABILITY_CL_DEFERRED_REVENUE).first()
        bill_data['unearned_account'] = unearned_account.uuid
        create_response = self.CLIENT.post(bill_create_url, data=bill_data, follow=True)
        self.assertFormError(create_response, form='form', field=None,
                             errors=['Must provide all accounts Cash, Prepaid, UnEarned.'])

        bill_data['prepaid_account'] = cash_account.uuid
        create_response = self.CLIENT.post(bill_create_url, data=bill_data, follow=True)
        self.assertTrue(create_response.resolver_match.view_name, 'django_ledger:bill-detail')

    def test_bill_detail(self):

0 Source : test_bill.py
with GNU General Public License v3.0
from arrobalytics

    def test_bill_detail(self):
        self.login_client()
        today = localdate()

        for i in range(5):
            entity_model, bill_model = self.create_bill(amount=Decimal('0.00'), date=today)
            vendor_model: VendorModel = bill_model.vendor
            bill_detail_url = reverse('django_ledger:bill-detail',
                                      kwargs={
                                          'entity_slug': entity_model.slug,
                                          'bill_pk': bill_model.uuid
                                      })

            with self.assertNumQueries(8):
                bill_detail_response = self.CLIENT.get(bill_detail_url)
            self.assertTrue(bill_detail_response.status_code, 200)

            self.assertTrue(bill_model.is_draft())
            # 'Not Approved' is displayed to the user...
            self.assertFalse(bill_model.is_approved())

            # bill card is displayed to the user...
            self.assertContains(bill_detail_response, 'id="djl-bill-card-widget"')

            # vendor card is displayed to the user...
            self.assertContains(bill_detail_response, 'id="djl-vendor-card-widget"')

            # if bill is not approved or draft...
            # user can update bill
            self.assertContains(bill_detail_response, 'id="djl-bill-detail-update-button"')
            # user cannot mark as paid
            self.assertNotContains(bill_detail_response, 'id="djl-bill-detail-mark-paid-button"')
            # user can delete..
            self.assertContains(bill_detail_response, 'id="djl-bill-detail-delete-button"')
            # user cannot void...
            self.assertNotContains(bill_detail_response, 'id="djl-bill-detail-void-button"')

            # user can navigate to bill-list...
            self.assertContains(bill_detail_response,
                                reverse('django_ledger:bill-list',
                                        kwargs={
                                            'entity_slug': entity_model.slug
                                        }))

            # vendor name ia shown
            self.assertContains(bill_detail_response, vendor_model.vendor_name)

            # can edit vendor link
            self.assertContains(bill_detail_response,
                                reverse('django_ledger:vendor-update',
                                        kwargs={
                                            'entity_slug': entity_model.slug,
                                            'vendor_pk': vendor_model.uuid
                                        }))

            # link to cash account detail
            self.assertContains(bill_detail_response,
                                reverse('django_ledger:account-detail',
                                        kwargs={
                                            'entity_slug': entity_model.slug,
                                            'account_pk': bill_model.cash_account.uuid
                                        }))

            # amount paid is shown
            self.assertContains(bill_detail_response, 'id="djl-bill-detail-amount-paid"')

            # amount owed is shown
            self.assertContains(bill_detail_response, 'id="djl-bill-detail-amount-owed"')

            if not bill_model.accrue:
                # amount prepaid is not shown
                self.assertNotContains(bill_detail_response, ' id="djl-bill-detail-amount-prepaid"')
                # amount unearned is not shown
                self.assertNotContains(bill_detail_response, ' id="djl-bill-detail-amount-unearned"')

            else:
                # amount prepaid is shown
                self.assertContains(bill_detail_response, ' id="djl-bill-detail-amount-prepaid"')
                # amount unearned is shown
                self.assertContains(bill_detail_response, ' id="djl-bill-detail-amount-unearned"')

            # amounts are zero...
            self.assertEqual(bill_model.get_amount_cash(), Decimal('0.00'))
            self.assertEqual(bill_model.get_amount_earned(), Decimal('0.00'))
            self.assertEqual(bill_model.get_amount_open(), Decimal('0.00'))
            self.assertEqual(bill_model.get_amount_prepaid(), Decimal('0.00'))
            self.assertEqual(bill_model.get_amount_unearned(), Decimal('0.00'))

0 Source : test_entity.py
with GNU General Public License v3.0
from arrobalytics

    def test_entity_detail(self):

        self.login_client()
        entity_model: EntityModel = choice(self.ENTITY_MODEL_QUERYSET)

        # ENTITY-DETAIL VIEW...
        with self.assertNumQueries(2):
            # this will redirect to entity-detail-month...
            entity_detail_url = reverse('django_ledger:entity-dashboard',
                                        kwargs={
                                            'entity_slug': entity_model.slug
                                        })
            response = self.CLIENT.get(entity_detail_url)

        with self.assertNumQueries(10):
            local_dt = localdate()
            entity_month_detail_url = reverse('django_ledger:entity-dashboard-month',
                                              kwargs={
                                                  'entity_slug': entity_model.slug,
                                                  'year': local_dt.year,
                                                  'month': local_dt.month
                                              })
            self.assertRedirects(response, entity_month_detail_url)

        with self.assertNumQueries(7):
            # same as before, but this time the session must not be update because user has not suited entities...
            response = self.CLIENT.get(entity_month_detail_url)
            self.assertContains(response, text=entity_model.name)
            self.assertContains(response, text='Dashboard')
            self.assertTrue(response.context['bills'].count() >= 0)
            self.assertTrue(response.context['invoices'].count() >= 0)

    def test_delete_entity(self):

0 Source : bill.py
with GNU General Public License v3.0
from arrobalytics

    def delete(self, request, *args, **kwargs):
        bill_model: BillModel = self.get_object()
        success_url = self.get_success_url()

        self.object = bill_model

        bill_items_qs = bill_model.itemthroughmodel_set.for_entity(
            entity_slug=self.kwargs['entity_slug'],
            user_model=self.request.user,
        )

        # forcing QS evaluation
        len(bill_items_qs)
        if self.void:

            if bill_model.void:
                messages.add_message(
                    self.request,
                    message=f'Bill {bill_model.bill_number} already voided...',
                    level=messages.ERROR,
                    extra_tags='is-danger')
                url_redirect = reverse('django_ledger:bill-detail',
                                       kwargs={
                                           'entity_slug': self.kwargs['entity_slug'],
                                           'bill_pk': bill_model.uuid
                                       })
                return HttpResponseRedirect(redirect_to=url_redirect)

            bill_model.void = True
            ld = localdate()
            bill_model.void_date = ld
            bill_model.save(update_fields=[
                'void',
                'void_date',
                'updated'
            ])

            bill_model.migrate_state(
                user_model=self.request.user,
                commit=True,
                void=True,
                itemthrough_queryset=bill_items_qs,
                je_date=ld,
                entity_slug=self.kwargs['entity_slug']
            )
            return HttpResponseRedirect(success_url)

        has_POs = bill_items_qs.filter(po_model__isnull=False).count() > 0
        if has_POs:
            messages.add_message(self.request,
                                 level=messages.ERROR,
                                 message='Cannot delete bill that has a PO. Void bill instead.',
                                 extra_tags='is-danger')
            return self.render_to_response(context=self.get_context_data())

        bill_model.itemthroughmodel_set.update(bill_model=None)
        self.object.delete()
        return HttpResponseRedirect(success_url)

0 Source : entity.py
with GNU General Public License v3.0
from arrobalytics

    def get_redirect_url(self, *args, **kwargs):
        loc_date = localdate()
        unit_slug = self.get_unit_slug()
        if unit_slug:
            return reverse('django_ledger:unit-dashboard-month',
                           kwargs={
                               'entity_slug': self.kwargs['entity_slug'],
                               'unit_slug': unit_slug,
                               'year': loc_date.year,
                               'month': loc_date.month,
                           })
        return reverse('django_ledger:entity-dashboard-month',
                       kwargs={
                           'entity_slug': self.kwargs['entity_slug'],
                           'year': loc_date.year,
                           'month': loc_date.month,
                       })


class FiscalYearEntityModelDashboardView(LoginRequiredMixIn,

0 Source : purchase_order.py
with GNU General Public License v3.0
from arrobalytics

    def post(self, request, entity_slug, *args, **kwargs):
        self.object = self.get_object()
        po_model: PurchaseOrderModel = self.object
        if self.update_items:
            PurchaseOrderItemFormset = get_po_item_formset(po_model)
            po_item_formset: PurchaseOrderItemFormset = PurchaseOrderItemFormset(request.POST,
                                                                                 user_model=self.request.user,
                                                                                 po_model=po_model,
                                                                                 entity_slug=entity_slug)

            context = self.get_context_data(item_formset=po_item_formset)

            if po_item_formset.is_valid():
                if po_item_formset.has_changed():
                    po_items = po_item_formset.save(commit=False)
                    all_received = all([
                        i['po_item_status'] == ItemThroughModel.STATUS_RECEIVED
                        for i in po_item_formset.cleaned_data if i
                    ])

                    for f in po_item_formset.forms:
                        i: ItemThroughModel = f.instance
                        if i:
                            if all([
                                i.po_item_status in [
                                    ItemThroughModel.STATUS_RECEIVED,
                                    ItemThroughModel.STATUS_IN_TRANSIT
                                ],
                                i.bill_model is None
                            ]):
                                messages.add_message(
                                    request=self.request,
                                    level=messages.ERROR,
                                    message=f'Item {i.item_model.__str__()} must be billed'
                                            f' before {i.get_po_item_status_display()}...',
                                    extra_tags='is-danger')
                                return self.render_to_response(context)

                    if all_received and po_model.fulfillment_date:

                        all_bills_paid = all([
                            f.instance.bill_model.paid_date for f in po_item_formset.forms
                        ])

                        if not all_bills_paid:
                            messages.add_message(
                                request=self.request,
                                level=messages.ERROR,
                                message=f'All Bills must be paid before PO being fulfilled..',
                                extra_tags='is-danger')
                            return self.render_to_response(context)

                    elif all_received and not po_model.fulfillment_date:
                        po_model.fulfillment_date = localdate()
                        po_model.fulfilled = True
                        po_model.clean()
                        po_model.save(update_fields=[
                            'fulfillment_date',
                            'fulfilled',
                            'updated'
                        ])

                    create_bill_uuids = [
                        str(i['uuid'].uuid) for i in po_item_formset.cleaned_data if i and i['create_bill'] is True
                    ]

                    if create_bill_uuids:
                        item_uuids = ','.join(create_bill_uuids)
                        redirect_url = reverse(
                            'django_ledger:bill-create-po',
                            kwargs={
                                'entity_slug': self.kwargs['entity_slug'],
                                'po_pk': po_model.uuid,
                            }
                        )
                        redirect_url += f'?item_uuids={item_uuids}'
                        return HttpResponseRedirect(redirect_url)

                    for item in po_items:
                        if not item.po_model:
                            item.po_model = po_model
                    po_item_formset.save()
                    po_model.update_po_state()
                    po_model.clean()
                    po_model.save(update_fields=['po_amount',
                                                 'po_amount_received',
                                                 'updated'])

            else:
                return self.render_to_response(context)
        elif self.mark_as_fulfilled:
            po_model.mark_as_fulfilled(commit=True, date=localdate())
        # fixme: the super call needs to be executed first...?
        return super().post(request, *args, **kwargs)

    def get_form(self, form_class=None):

0 Source : tests.py
with GNU Affero General Public License v3.0
from betagouv

    def test_send_invitation(self):
        invitation = SentSiaeStaffInvitationFactory.build()
        email = invitation.email_invitation

        # Subject
        self.assertIn(invitation.sender.get_full_name().title(), email.subject)

        # Body
        self.assertIn(capfirst(invitation.first_name), email.body)
        self.assertIn(capfirst(invitation.last_name), email.body)
        self.assertIn(invitation.acceptance_link, email.body)

        self.assertIn(str(timezone.localdate(invitation.expiration_date).day), email.body)

        # To
        self.assertIn(invitation.email, email.to)


################################################################
###################### PrescribersWithOrg ######################
################################################################


class TestPrescriberWithOrgInvitation(TestCase):

0 Source : tests_list.py
with GNU Affero General Public License v3.0
from betagouv

    def test_list_for_siae_view__filtered_by_dates(self):
        """
        Eddie wants to see job applications sent at a specific date.
        """
        self.client.login(username=self.eddie_hit_pit.email, password=DEFAULT_PASSWORD)
        date_format = DuetDatePickerWidget.INPUT_DATE_FORMAT
        job_applications = self.hit_pit.job_applications_received.not_archived().order_by("created_at")
        jobs_in_range = job_applications[3:]
        start_date = jobs_in_range[0].created_at

        # Negative indexing is not allowed in querysets
        end_date = jobs_in_range[len(jobs_in_range) - 1].created_at
        query = urlencode(
            {
                "start_date": timezone.localdate(start_date).strftime(date_format),
                "end_date": timezone.localdate(end_date).strftime(date_format),
            }
        )
        url = f"{self.siae_base_url}?{query}"
        response = self.client.get(url)
        applications = response.context["job_applications_page"].object_list

        self.assertGreater(len(applications), 0)

        for application in applications:
            self.assertGreaterEqual(application.created_at, start_date)
            self.assertLessEqual(application.created_at, end_date)

    def test_list_for_siae_view__empty_dates_in_params(self):

0 Source : tests_process.py
with GNU Affero General Public License v3.0
from betagouv

    def test_accept(self, *args, **kwargs):
        """Test the `accept` transition."""
        create_test_cities(["54", "57"], num_per_department=2)
        city = City.objects.first()
        today = timezone.localdate()

        job_seeker = JobSeekerWithAddressFactory(city=city.name)
        address = {
            "address_line_1": job_seeker.address_line_1,
            "post_code": job_seeker.post_code,
            "city": city.name,
            "city_slug": city.slug,
        }
        siae = SiaeWithMembershipFactory()
        siae_user = siae.members.first()

        hiring_end_dates = [
            Approval.get_default_end_date(today),
            None,
        ]
        cases = list(product(hiring_end_dates, JobApplicationWorkflow.CAN_BE_ACCEPTED_STATES))

        for hiring_end_at, state in cases:
            with self.subTest(hiring_end_at=hiring_end_at, state=state):

                job_application = JobApplicationSentByJobSeekerFactory(
                    state=state, job_seeker=job_seeker, to_siae=siae
                )
                self.client.login(username=siae_user.email, password=DEFAULT_PASSWORD)

                url = reverse("apply:accept", kwargs={"job_application_id": job_application.pk})
                response = self.client.get(url)
                self.assertEqual(response.status_code, 200)

                # Good duration.
                hiring_start_at = today
                post_data = {
                    # Data for `JobSeekerPoleEmploiStatusForm`.
                    "pole_emploi_id": job_application.job_seeker.pole_emploi_id,
                    # Data for `AcceptForm`.
                    "hiring_start_at": hiring_start_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
                    "answer": "",
                    **address,
                }
                if hiring_end_at:
                    post_data["hiring_end_at"] = hiring_end_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT)

                response = self.client.post(url, data=post_data)
                next_url = reverse("apply:details_for_siae", kwargs={"job_application_id": job_application.pk})
                self.assertRedirects(response, next_url)

                job_application = JobApplication.objects.get(pk=job_application.pk)
                self.assertEqual(job_application.hiring_start_at, hiring_start_at)
                self.assertEqual(job_application.hiring_end_at, hiring_end_at)
                self.assertTrue(job_application.state.is_accepted)

                # test how hiring_end_date is displayed
                response = self.client.get(next_url)
                self.assertEqual(response.status_code, 200)
                # test case hiring_end_at
                if hiring_end_at:
                    self.assertContains(response, f"Fin : {hiring_end_at.strftime('%d')}")
                else:
                    self.assertContains(response, "Fin : Non renseigné")

        ##############
        # Exceptions #
        ##############
        job_application = JobApplicationSentByJobSeekerFactory(state=state, job_seeker=job_seeker, to_siae=siae)
        url = reverse("apply:accept", kwargs={"job_application_id": job_application.pk})

        # Wrong dates.
        hiring_start_at = today
        hiring_end_at = Approval.get_default_end_date(hiring_start_at)
        # Force `hiring_start_at` in past.
        hiring_start_at = hiring_start_at - relativedelta(days=1)
        post_data = {
            "hiring_start_at": hiring_start_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "hiring_end_at": hiring_end_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "answer": "",
            **address,
        }
        response = self.client.post(url, data=post_data)
        self.assertFormError(response, "form_accept", "hiring_start_at", JobApplication.ERROR_START_IN_PAST)

        # Wrong dates: end   <   start.
        hiring_start_at = today
        hiring_end_at = hiring_start_at - relativedelta(days=1)
        post_data = {
            "hiring_start_at": hiring_start_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "hiring_end_at": hiring_end_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "answer": "",
            **address,
        }
        response = self.client.post(url, data=post_data)
        self.assertFormError(response, "form_accept", None, JobApplication.ERROR_END_IS_BEFORE_START)

        # No address provided.
        job_application = JobApplicationSentByJobSeekerFactory(
            state=JobApplicationWorkflow.STATE_PROCESSING, to_siae=siae
        )
        url = reverse("apply:accept", kwargs={"job_application_id": job_application.pk})

        hiring_start_at = today
        hiring_end_at = Approval.get_default_end_date(hiring_start_at)
        post_data = {
            # Data for `JobSeekerPoleEmploiStatusForm`.
            "pole_emploi_id": job_application.job_seeker.pole_emploi_id,
            # Data for `AcceptForm`.
            "hiring_start_at": hiring_start_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "hiring_end_at": hiring_end_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "answer": "",
        }
        response = self.client.post(url, data=post_data)
        self.assertFormError(response, "form_user_address", "address_line_1", "Ce champ est obligatoire.")
        self.assertFormError(response, "form_user_address", "city", "Ce champ est obligatoire.")
        self.assertFormError(response, "form_user_address", "post_code", "Ce champ est obligatoire.")

    def test_accept_with_active_suspension(self, *args, **kwargs):

0 Source : tests_process.py
with GNU Affero General Public License v3.0
from betagouv

    def test_accept_with_active_suspension(self, *args, **kwargs):
        """Test the `accept` transition with active suspension for active user"""
        create_test_cities(["54", "57"], num_per_department=2)
        city = City.objects.first()
        today = timezone.localdate()
        # the old job of job seeker
        job_seeker_user = JobSeekerWithAddressFactory()
        old_job_application = JobApplicationWithApprovalFactory(
            state=JobApplicationWorkflow.STATE_ACCEPTED,
            job_seeker=job_seeker_user,
            # Ensure that the old_job_application cannot be canceled.
            hiring_start_at=today - relativedelta(days=100),
        )
        # create suspension for the job seeker
        approval_job_seeker = old_job_application.approval
        siae_user = old_job_application.to_siae.members.first()
        susension_start_at = today
        suspension_end_at = today + relativedelta(days=50)

        SuspensionFactory(
            approval=approval_job_seeker,
            start_at=susension_start_at,
            end_at=suspension_end_at,
            created_by=siae_user,
            reason=Suspension.Reason.BROKEN_CONTRACT.value,
        )

        # Now, another Siae wants to hire the job seeker
        other_siae = SiaeWithMembershipFactory()
        job_application = JobApplicationSentByJobSeekerFactory(
            approval=approval_job_seeker,
            state=JobApplicationWorkflow.STATE_PROCESSING,
            job_seeker=job_seeker_user,
            to_siae=other_siae,
        )
        other_siae_user = job_application.to_siae.members.first()

        # login with other siae
        self.client.login(username=other_siae_user.email, password=DEFAULT_PASSWORD)
        url = reverse("apply:accept", kwargs={"job_application_id": job_application.pk})

        hiring_start_at = today + relativedelta(days=20)
        hiring_end_at = Approval.get_default_end_date(hiring_start_at)

        post_data = {
            # Data for `JobSeekerPoleEmploiStatusForm`.
            "pole_emploi_id": job_application.job_seeker.pole_emploi_id,
            # Data for `AcceptForm`.
            "hiring_start_at": hiring_start_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "hiring_end_at": hiring_end_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "answer": "",
            "address_line_1": job_seeker_user.address_line_1,
            "post_code": job_seeker_user.post_code,
            "city": city.name,
            "city_slug": city.slug,
        }
        response = self.client.post(url, data=post_data)
        self.assertEqual(response.status_code, 302)
        get_job_application = JobApplication.objects.get(pk=job_application.pk)
        g_suspension = get_job_application.approval.suspension_set.in_progress().last()

        # The end date of suspension is set to d-1 of hiring start day
        self.assertEqual(g_suspension.end_at, get_job_application.hiring_start_at - relativedelta(days=1))
        # Check if the duration of approval was updated correctly
        self.assertEqual(
            get_job_application.approval.end_at,
            approval_job_seeker.end_at + relativedelta(days=(g_suspension.end_at - g_suspension.start_at).days),
        )

    def test_accept_with_manual_approval_delivery(self, *args, **kwargs):

0 Source : tests_process.py
with GNU Affero General Public License v3.0
from betagouv

    def test_accept_with_manual_approval_delivery(self, *args, **kwargs):
        """
        Test the "manual approval delivery mode" path of the view.
        """
        create_test_cities(["57"], num_per_department=1)
        city = City.objects.first()

        job_application = JobApplicationSentByJobSeekerFactory(
            state=JobApplicationWorkflow.STATE_PROCESSING,
            # The state of the 2 `pole_emploi_*` fields will trigger a manual delivery.
            job_seeker__pole_emploi_id="",
            job_seeker__lack_of_pole_emploi_id_reason=User.REASON_FORGOTTEN,
        )

        siae_user = job_application.to_siae.members.first()
        self.client.login(username=siae_user.email, password=DEFAULT_PASSWORD)

        url = reverse("apply:accept", kwargs={"job_application_id": job_application.pk})
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)

        post_data = {
            # Data for `JobSeekerPoleEmploiStatusForm`.
            "pole_emploi_id": job_application.job_seeker.pole_emploi_id,
            "lack_of_pole_emploi_id_reason": job_application.job_seeker.lack_of_pole_emploi_id_reason,
            # Data for `UserAddressForm`.
            "address_line_1": "11 rue des Lilas",
            "post_code": "57000",
            "city": city.name,
            "city_slug": city.slug,
            # Data for `AcceptForm`.
            "hiring_start_at": timezone.localdate().strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "hiring_end_at": (timezone.localdate() + relativedelta(days=360)).strftime(
                DuetDatePickerWidget.INPUT_DATE_FORMAT
            ),
            "answer": "",
        }
        response = self.client.post(url, data=post_data)
        next_url = reverse("apply:details_for_siae", kwargs={"job_application_id": job_application.pk})
        self.assertRedirects(response, next_url)

        job_application.refresh_from_db()
        self.assertEqual(job_application.approval_delivery_mode, job_application.APPROVAL_DELIVERY_MODE_MANUAL)

    def test_accept_and_update_hiring_start_date_of_two_job_applications(self, *args, **kwargs):

0 Source : tests_process.py
with GNU Affero General Public License v3.0
from betagouv

    def test_accept_and_update_hiring_start_date_of_two_job_applications(self, *args, **kwargs):
        create_test_cities(["54", "57"], num_per_department=2)
        city = City.objects.first()
        job_seeker = JobSeekerWithAddressFactory()
        base_for_post_data = {
            "address_line_1": job_seeker.address_line_1,
            "post_code": job_seeker.post_code,
            "city": city.name,
            "city_slug": city.slug,
            "pole_emploi_id": job_seeker.pole_emploi_id,
            "answer": "",
        }
        hiring_start_at = timezone.localdate() + relativedelta(months=2)
        hiring_end_at = hiring_start_at + relativedelta(months=2)
        approval_default_ending = Approval.get_default_end_date(start_at=hiring_start_at)

        # Send 3 job applications to 3 different structures
        job_application = JobApplicationSentByJobSeekerFactory(
            job_seeker=job_seeker, state=JobApplicationWorkflow.STATE_PROCESSING
        )
        job_app_starting_earlier = JobApplicationSentByJobSeekerFactory(
            job_seeker=job_seeker, state=JobApplicationWorkflow.STATE_PROCESSING
        )
        job_app_starting_later = JobApplicationSentByJobSeekerFactory(
            job_seeker=job_seeker, state=JobApplicationWorkflow.STATE_PROCESSING
        )

        # SIAE 1 logs in and accepts the first job application.
        # The delivered approval should start at the same time as the contract.
        user = job_application.to_siae.members.first()
        self.client.login(username=user.email, password=DEFAULT_PASSWORD)
        url_accept = reverse("apply:accept", kwargs={"job_application_id": job_application.pk})
        post_data = {
            "hiring_start_at": hiring_start_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "hiring_end_at": hiring_end_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            **base_for_post_data,
        }
        response = self.client.post(url_accept, data=post_data)
        self.assertEqual(response.status_code, 302)

        # First job application has been accepted.
        # All other job applications are obsolete.
        job_application.refresh_from_db()
        self.assertTrue(job_application.state.is_accepted)
        self.assertEqual(job_application.approval.start_at, job_application.hiring_start_at)
        self.assertEqual(job_application.approval.end_at, approval_default_ending)
        self.client.logout()

        # SIAE 2 accepts the second job application
        # but its contract starts earlier than the approval delivered the first time.
        # Approval's starting date should be brought forward.
        user = job_app_starting_earlier.to_siae.members.first()
        hiring_start_at = hiring_start_at - relativedelta(months=1)
        hiring_end_at = hiring_start_at + relativedelta(months=2)
        approval_default_ending = Approval.get_default_end_date(start_at=hiring_start_at)
        job_app_starting_earlier.refresh_from_db()
        self.assertTrue(job_app_starting_earlier.state.is_obsolete)

        self.client.login(username=user.email, password=DEFAULT_PASSWORD)
        url_accept = reverse("apply:accept", kwargs={"job_application_id": job_app_starting_earlier.pk})
        post_data = {
            "hiring_start_at": hiring_start_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "hiring_end_at": hiring_end_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            **base_for_post_data,
        }
        response = self.client.post(url_accept, data=post_data)
        job_app_starting_earlier.refresh_from_db()

        # Second job application has been accepted.
        # The job seeker has now two part-time jobs at the same time.
        self.assertEqual(response.status_code, 302)
        self.assertTrue(job_app_starting_earlier.state.is_accepted)
        self.assertEqual(job_app_starting_earlier.approval.start_at, job_app_starting_earlier.hiring_start_at)
        self.assertEqual(job_app_starting_earlier.approval.end_at, approval_default_ending)
        self.client.logout()

        # SIAE 3 accepts the third job application.
        # Its contract starts later than the corresponding approval.
        # Approval's starting date should not be updated.
        user = job_app_starting_later.to_siae.members.first()
        hiring_start_at = hiring_start_at + relativedelta(months=6)
        hiring_end_at = hiring_start_at + relativedelta(months=2)
        job_app_starting_later.refresh_from_db()
        self.assertTrue(job_app_starting_later.state.is_obsolete)

        self.client.login(username=user.email, password=DEFAULT_PASSWORD)
        url_accept = reverse("apply:accept", kwargs={"job_application_id": job_app_starting_later.pk})
        post_data = {
            "hiring_start_at": hiring_start_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "hiring_end_at": hiring_end_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            **base_for_post_data,
        }
        response = self.client.post(url_accept, data=post_data)
        job_app_starting_later.refresh_from_db()

        # Third job application has been accepted.
        # The job seeker has now three part-time jobs at the same time.
        self.assertEqual(response.status_code, 302)
        self.assertTrue(job_app_starting_later.state.is_accepted)
        self.assertEqual(job_app_starting_later.approval.start_at, job_app_starting_earlier.hiring_start_at)

    def test_eligibility(self, *args, **kwargs):

0 Source : tests_process.py
with GNU Affero General Public License v3.0
from betagouv

    def test_accept_after_cancel(self, *args, **kwargs):
        # A canceled job application is not linked to an approval
        # unless the job seeker has an accepted job application.
        create_test_cities(["54", "57"], num_per_department=2)
        city = City.objects.first()
        job_seeker = JobSeekerWithAddressFactory(city=city.name)
        job_application = JobApplicationSentByJobSeekerFactory(
            state=JobApplicationWorkflow.STATE_CANCELLED, job_seeker=job_seeker
        )
        siae_user = job_application.to_siae.members.first()
        self.client.login(username=siae_user.email, password=DEFAULT_PASSWORD)

        url_accept = reverse("apply:accept", kwargs={"job_application_id": job_application.pk})
        hiring_start_at = timezone.localdate()
        hiring_end_at = Approval.get_default_end_date(hiring_start_at)
        post_data = {
            "hiring_start_at": hiring_start_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "hiring_end_at": hiring_end_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "pole_emploi_id": job_application.job_seeker.pole_emploi_id,
            "answer": "",
            "address_line_1": job_seeker.address_line_1,
            "post_code": job_seeker.post_code,
            "city": city.name,
            "city_slug": city.slug,
        }
        response = self.client.post(url_accept, data=post_data)

        next_url = reverse("apply:details_for_siae", kwargs={"job_application_id": job_application.pk})
        self.assertRedirects(response, next_url)

        job_application.refresh_from_db()
        self.assertEqual(job_seeker.approvals.count(), 1)
        approval = job_seeker.approvals.first()
        self.assertEqual(approval.start_at, job_application.hiring_start_at)
        self.assertTrue(job_application.state.is_accepted)

    def test_archive(self, *args, **kwargs):

0 Source : test_edit.py
with GNU Affero General Public License v3.0
from betagouv

    def test_max_postpone_contract_date(self):
        """
        The contract start date can only be postponed of 30 days
        """

        self.client.login(username=self.user1.username, password=DEFAULT_PASSWORD)

        url = reverse("apply:edit_contract_start_date", kwargs={"job_application_id": self.job_application_1.id})
        response = self.client.get(url)

        self.assertEqual(response.status_code, 200)

        future_start_date = timezone.localdate() + relativedelta(days=JobApplication.MAX_CONTRACT_POSTPONE_IN_DAYS + 1)

        post_data = {
            "hiring_start_at": future_start_date.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "hiring_end_at": self.job_application_1.hiring_end_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
        }

        response = self.client.post(url, data=post_data)
        self.assertEqual(response.status_code, 200)

    def test_postpone_approval(self):

0 Source : test_suspend.py
with GNU Affero General Public License v3.0
from betagouv

    def test_suspend_approval(self):
        """
        Test the creation of a suspension.
        """

        today = timezone.localdate()

        job_application = JobApplicationWithApprovalFactory(
            state=JobApplicationWorkflow.STATE_ACCEPTED,
            hiring_start_at=today - relativedelta(days=1),
        )

        # Ensure that the job_application cannot be canceled.
        EmployeeRecordFactory(job_application=job_application, status=EmployeeRecord.Status.PROCESSED)

        approval = job_application.approval
        self.assertEqual(0, approval.suspension_set.count())

        siae_user = job_application.to_siae.members.first()
        self.client.login(username=siae_user.email, password=DEFAULT_PASSWORD)

        back_url = "/"
        params = urlencode({"back_url": back_url})
        url = reverse("approvals:suspend", kwargs={"approval_id": approval.pk})
        url = f"{url}?{params}"

        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.context["preview"], False)

        start_at = today
        end_at = today + relativedelta(days=10)

        post_data = {
            "start_at": start_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "end_at": end_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "reason": Suspension.Reason.SUSPENDED_CONTRACT,
            "reason_explanation": "",
            # Preview.
            "preview": "1",
        }

        # Go to preview.
        response = self.client.post(url, data=post_data)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.context["preview"], True)

        # Save to DB.
        del post_data["preview"]
        post_data["save"] = 1

        response = self.client.post(url, data=post_data)
        self.assertEqual(response.status_code, 302)
        self.assertRedirects(response, back_url)

        self.assertEqual(1, approval.suspension_set.count())
        suspension = approval.suspension_set.first()
        self.assertEqual(suspension.created_by, siae_user)

    def test_create_suspension_without_end_date(self):

0 Source : test_suspend.py
with GNU Affero General Public License v3.0
from betagouv

    def test_create_suspension_without_end_date(self):
        # Only test form validation (faster)

        today = timezone.localdate()

        job_application = JobApplicationWithApprovalFactory(
            state=JobApplicationWorkflow.STATE_ACCEPTED,
            hiring_start_at=today - relativedelta(days=1),
        )

        # Ensure that the job_application cannot be canceled.
        EmployeeRecordFactory(job_application=job_application, status=EmployeeRecord.Status.PROCESSED)

        # Fill all form data:
        # do not forget to fill `end_at` field with None (or model init will override with a default value)
        post_data = {
            "start_at": today.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "end_at": None,
            "set_default_end_date": False,
            "reason": Suspension.Reason.SUSPENDED_CONTRACT,
            "reason_explanation": "",
            "preview": "1",
        }

        form = SuspensionForm(approval=job_application.approval, siae=job_application.to_siae, data=post_data)

        self.assertFalse(form.is_valid())
        self.assertIsNotNone(form.errors["end_at"][0])

        # Check 'set_default_end_date' and expect a default end date to be set
        post_data["set_default_end_date"] = True
        form = SuspensionForm(approval=job_application.approval, siae=job_application.to_siae, data=post_data)

        self.assertTrue(form.is_valid())
        self.assertEqual(form.cleaned_data["end_at"], Suspension.get_max_end_at(today))

    def test_clean_form(self):

0 Source : test_suspend.py
with GNU Affero General Public License v3.0
from betagouv

    def test_clean_form(self):
        # Ensure `clean()` is running OK in case of `start_at` error (Sentry issue):
        today = timezone.localdate()
        start_at = today + relativedelta(days=1)

        job_application = JobApplicationWithApprovalFactory(
            state=JobApplicationWorkflow.STATE_ACCEPTED,
            hiring_start_at=today - relativedelta(days=Suspension.MAX_RETROACTIVITY_DURATION_DAYS + 1),
        )

        post_data = {
            "start_at": start_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "end_at": None,
            "set_default_end_date": False,
            "reason": Suspension.Reason.SUSPENDED_CONTRACT,
            "reason_explanation": "",
            "preview": "1",
        }
        form = SuspensionForm(approval=job_application.approval, siae=job_application.to_siae, data=post_data)
        self.assertFalse(form.is_valid())

    def test_update_suspension(self):

0 Source : test_suspend.py
with GNU Affero General Public License v3.0
from betagouv

    def test_update_suspension(self):
        """
        Test the update of a suspension.
        """

        today = timezone.localdate()

        job_application = JobApplicationWithApprovalFactory(
            state=JobApplicationWorkflow.STATE_ACCEPTED,
            # Ensure that the job_application cannot be canceled.
            hiring_start_at=today - relativedelta(days=1),
        )

        approval = job_application.approval
        siae_user = job_application.to_siae.members.first()
        start_at = today
        end_at = today + relativedelta(days=10)

        suspension = SuspensionFactory(approval=approval, start_at=start_at, end_at=end_at, created_by=siae_user)

        self.client.login(username=siae_user.email, password=DEFAULT_PASSWORD)

        back_url = "/"
        params = urlencode({"back_url": back_url})
        url = reverse("approvals:suspension_update", kwargs={"suspension_id": suspension.pk})
        url = f"{url}?{params}"

        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)

        new_end_at = end_at + relativedelta(days=30)

        post_data = {
            "start_at": suspension.start_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "end_at": new_end_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "reason": suspension.reason,
            "reason_explanation": suspension.reason_explanation,
        }

        response = self.client.post(url, data=post_data)
        self.assertEqual(response.status_code, 302)
        self.assertRedirects(response, back_url)

        self.assertEqual(1, approval.suspension_set.count())
        suspension = approval.suspension_set.first()
        self.assertEqual(suspension.updated_by, siae_user)
        self.assertEqual(suspension.end_at, new_end_at)

    def test_delete_suspension(self):

0 Source : test_suspend.py
with GNU Affero General Public License v3.0
from betagouv

    def test_delete_suspension(self):
        """
        Test the deletion of a suspension.
        """

        today = timezone.localdate()

        job_application = JobApplicationWithApprovalFactory(
            state=JobApplicationWorkflow.STATE_ACCEPTED,
            # Ensure that the job_application cannot be canceled.
            hiring_start_at=today - relativedelta(days=1),
        )

        approval = job_application.approval
        siae_user = job_application.to_siae.members.first()
        start_at = today
        end_at = today + relativedelta(days=10)

        suspension = SuspensionFactory(approval=approval, start_at=start_at, end_at=end_at, created_by=siae_user)

        self.client.login(username=siae_user.email, password=DEFAULT_PASSWORD)

        back_url = "/"
        params = urlencode({"back_url": back_url})
        url = reverse("approvals:suspension_delete", kwargs={"suspension_id": suspension.pk})
        url = f"{url}?{params}"

        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)

        post_data = {"confirm": "true"}

        response = self.client.post(url, data=post_data)
        self.assertEqual(response.status_code, 302)
        self.assertRedirects(response, back_url)

        self.assertEqual(0, approval.suspension_set.count())

0 Source : test_model_user.py
with MIT License
from fga-eps-mds

    def test_age(self):
        """
        Test to get age of user
        """

        test_ages = [
            5, 10, 4, 66, 12
        ]

        today = timezone.localdate()

        for test_age in test_ages:
            self.user.birthday = timezone.datetime(
                year=(today.year - test_age),
                month=today.month,
                day=today.day
            )

            self.user.save()
            self.user.refresh_from_db()

            self.assertEquals(
                self.user.age(),
                test_age
            )

        edge_cases_months = [
            -1,
            0,
            1,
            5,
            6,
            7,
            8,
            10,
            11,
            12,
            13
        ]

        for months in edge_cases_months:
            self.user.birthday = today + relativedelta(months=-months)

            self.user.save()
            self.user.refresh_from_db()

            if 6   <  = months  <  12:
                self.assertEquals(
                    self.user.age(),
                    0.5
                )
            elif months  <  6:
                if months is 6:
                    self.assertEquals(
                        self.user.age(),
                        0
                    )
            elif months >= 12:
                if months is 6:
                    self.assertGreaterEqual(
                        self.user.age(),
                        1
                    )

    def test_invalid_birthday(self):

See More Examples