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
3
Source : dates.py
with GNU General Public License v3.0
from Aghoreshwar
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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