def ready(self): Invoice = self.get_model('Invoice') signals.post_save.connect( handlers.log_invoice_save, sender=Invoice, dispatch_uid='nodeconductor_killbill.handlers.log_invoice_save', ) signals.post_delete.connect( handlers.log_invoice_delete, sender=Invoice, dispatch_uid='nodeconductor_killbill.handlers.log_invoice_delete', ) for index, resource in enumerate( structure_models.PaidResource.get_all_models()): post_transition.connect( handlers.subscribe, sender=resource, dispatch_uid='nodeconductor_killbill.handlers.subscribe_{}_{}'. format(resource.__name__, index), ) signals.post_delete.connect( handlers.unsubscribe, sender=resource, dispatch_uid='nodeconductor_killbill.handlers.unsubscribe_{}_{}' .format(resource.__name__, index), ) signals.pre_save.connect( preserve_fields_before_update, sender=resource, dispatch_uid= 'nodeconductor_killbill.handlers.preserve_fields_before_update_{}_{}' .format(resource.__name__, index), ) signals.post_save.connect( handlers.update_resource_name, sender=resource, dispatch_uid= 'nodeconductor_killbill.handlers.update_resource_name_{}_{}'. format(resource.__name__, index), ) signals.post_save.connect( handlers.update_project_name, sender=structure_models.Project, dispatch_uid='nodeconductor_killbill.handlers.update_project_name', ) signals.post_save.connect( handlers.update_project_group_name, sender=structure_models.ProjectGroup, dispatch_uid= 'nodeconductor_killbill.handlers.update_project_group_name', )
def ready(self): backend = import_by_path(settings.DJANGO_FSM_LOG_STORAGE_METHOD) StateLog = self.get_model('StateLog') backend.setup_model(StateLog) pre_transition.connect(backend.pre_transition_callback) post_transition.connect(backend.post_transition_callback)
def ready(self): from django_fsm.signals import post_transition from shop.models.fields import JSONField from rest_framework.serializers import ModelSerializer from shop.rest.fields import JSONSerializerField from shop.models.notification import order_event_notification post_transition.connect(order_event_notification) # add JSONField to the map of customized serializers ModelSerializer.serializer_field_mapping[JSONField] = JSONSerializerField # perform some sanity checks ForeignKeyBuilder.check_for_pending_mappings()
def ready(self): from django_fsm.signals import post_transition from shop.models.fields import JSONField from rest_framework.serializers import ModelSerializer from shop.deferred import ForeignKeyBuilder from shop.rest.fields import JSONSerializerField from shop.models.notification import order_event_notification post_transition.connect(order_event_notification) # add JSONField to the map of customized serializers ModelSerializer.serializer_field_mapping[JSONField] = JSONSerializerField # perform some sanity checks ForeignKeyBuilder.check_for_pending_mappings()
def test_invoice_workflow(self): post_transition.disconnect(generate_invoice_pdf, sender=Invoice, dispatch_uid="generate_invoice_pdf") self.invoice_test1.state_open() post_transition.connect(generate_invoice_pdf, sender=Invoice, dispatch_uid="generate_invoice_pdf") # Workflow self.assertEqual(self.invoice_test1.state,InvoiceStatus.OPEN) self.invoice_test1.state_approved() self.assertEqual(self.invoice_test1.state,InvoiceStatus.APPROVED) self.invoice_test1.state_sent() self.assertEqual(self.invoice_test1.state,InvoiceStatus.SENT) self.invoice_test1.state_paid() self.assertEqual(self.invoice_test1.state,InvoiceStatus.PAID) self.invoice_test2.state_rejected() self.assertEqual(self.invoice_test2.state,InvoiceStatus.REJECTED)
def ready(self): from django_fsm.signals import post_transition from jsonfield.fields import JSONField from rest_framework.serializers import ModelSerializer from shop.rest.serializers import JSONSerializerField from shop.models.notification import order_event_notification post_transition.connect(order_event_notification) # Monkey patches for Django-1.7 if get_version() < (1, 8): from django.utils import numberformat from shop.patches import numberformat as patched_numberformat numberformat.format = patched_numberformat.format # add JSONField to the map of customized serializers ModelSerializer.serializer_field_mapping[JSONField] = JSONSerializerField
def ready(self): from django_fsm.signals import post_transition from jsonfield.fields import JSONField from rest_framework.serializers import ModelSerializer from shop.rest.serializers import JSONSerializerField from shop.models.notification import order_event_notification post_transition.connect(order_event_notification) # Monkey patches for Django-1.8 if get_tuple_version()[:2] < (1, 9): from django.utils import numberformat from shop.patches import numberformat as patched_numberformat numberformat.format = patched_numberformat.format # add JSONField to the map of customized serializers ModelSerializer.serializer_field_mapping[JSONField] = JSONSerializerField
def ready(self): from django_fsm.signals import post_transition from jsonfield.fields import JSONField from rest_framework.serializers import ModelSerializer from shop.rest.fields import JSONSerializerField from shop.models.notification import order_event_notification post_transition.connect(order_event_notification) # Monkey patches for Django-1.8 if get_tuple_version()[:2] < (1, 9): from django.utils import numberformat from shop.patches import numberformat as patched_numberformat numberformat.format = patched_numberformat.format # add JSONField to the map of customized serializers ModelSerializer.serializer_field_mapping[JSONField] = JSONSerializerField # perform some sanity checks ForeignKeyBuilder.check_for_pending_mappings()
html_template="email/admin/student_registered.html", context={'new_profile': student, 'user': student}, ) action.send(student, verb='has registered') def student_missing_information_mail(sender, instance, name, source, target, **kwargs): if target == StudentProfileState.MISSING_INFORMATION and not is_duplicate_transition(name, instance): with translation.override(instance.get_preferred_language()): send_templated_mail( subject=_("Your profile at Motius is incomplete"), html_template='email/student/student_missing_information.html', recipient_list=[instance.user.email], context={'profile': instance, 'user': instance.user} ) post_transition.connect(student_missing_information_mail, sender=StudentProfile, dispatch_uid="student_missing_information_mail") def student_accepted_mail(sender, instance, name, source, target, **kwargs): if target == StudentProfileState.ACCEPTED and not is_duplicate_transition(name, instance): with translation.override(instance.get_preferred_language()): mail = send_templated_mail( subject=_("We've accepted you for Motius"), html_template='email/student/student_accepted.html', recipient_list=[instance.user.email], context={'profile': instance, 'user': instance.user}, skip_sending=True, ) # Attach student guide to email student_guide = finders.find('pdf/student_guide_%s.pdf' % instance.get_preferred_language())
signal_counter = models.IntegerField(default=0) state = FSMField(default="SUBMITTED_BY_USER") @transition(field=state, source="SUBMITTED_BY_USER", target="REVIEW_USER") @transition(field=state, source="SUBMITTED_BY_ADMIN", target="REVIEW_ADMIN") @transition(field=state, source="SUBMITTED_BY_ANONYMOUS", target="REVIEW_ANONYMOUS") def review(self): self.counter += 1 class Meta: app_label = 'testapp' def count_calls(sender, instance, name, source, target, **kwargs): instance.signal_counter += 1 post_transition.connect(count_calls, sender=TestModel) class TestStateProxy(TestCase): def test_transition_method_called_once(self): model = TestModel() model.review() self.assertEqual(1, model.counter) # BUG self.assertEqual(1, model.signal_counter)
def ready(self): PriceEstimate = self.get_model('PriceEstimate') DefaultPriceListItem = self.get_model('DefaultPriceListItem') signals.post_save.connect( handlers. make_autocalculate_price_estimate_invisible_on_manual_estimate_creation, sender=PriceEstimate, dispatch_uid= ('nodeconductor.cost_tracking.handlers.' 'make_autocalculate_price_estimate_invisible_on_manual_estimate_creation' )) signals.post_delete.connect( handlers. make_autocalculated_price_estimate_visible_on_manual_estimate_deletion, sender=PriceEstimate, dispatch_uid= ('nodeconductor.cost_tracking.handlers.' 'make_autocalculated_price_estimate_visible_on_manual_estimate_deletion' )) signals.pre_save.connect( handlers. make_autocalculate_price_estimate_invisible_if_manually_created_estimate_exists, sender=PriceEstimate, dispatch_uid= ('nodeconductor.cost_tracking.handlers.' 'make_autocalculate_price_estimate_invisible_if_manually_created_estimate_exists' )) for index, service in enumerate( structure_models.Service.get_all_models()): signals.post_save.connect( handlers.create_price_list_items_for_service, sender=service, dispatch_uid= ('nodeconductor.cost_tracking.handlers.create_price_list_items_for_service_{}_{}' .format(service.__name__, index))) for index, resource in enumerate( structure_models.Resource.get_all_models()): post_transition.connect( handlers.estimate_costs, sender=resource, dispatch_uid= 'nodeconductor.cost_tracking.handlers.estimate_costs_{}_{}'. format(resource.__name__, index), ) signals.post_save.connect( handlers.change_price_list_items_if_default_was_changed, sender=DefaultPriceListItem, dispatch_uid= 'nodeconductor.cost_tracking.handlers.change_price_list_items_if_default_was_changed' ) signals.post_delete.connect( handlers.delete_price_list_items_if_default_was_deleted, sender=DefaultPriceListItem, dispatch_uid= 'nodeconductor.cost_tracking.handlers.delete_price_list_items_if_default_was_deleted' ) for index, model in enumerate(PriceEstimate.get_estimated_models()): signals.pre_delete.connect( handlers.delete_price_estimate_on_scope_deletion, sender=model, dispatch_uid= ('nodeconductor.cost_tracking.handlers.delete_price_estimate_on_scope_deletion_{}_{}' .format(model.__name__, index)))
class TestModel(models.Model): counter = models.IntegerField(default=0) signal_counter = models.IntegerField(default=0) state = FSMField(default="SUBMITTED_BY_USER") @transition(field=state, source="SUBMITTED_BY_USER", target="REVIEW_USER") @transition(field=state, source="SUBMITTED_BY_ADMIN", target="REVIEW_ADMIN") @transition(field=state, source="SUBMITTED_BY_ANONYMOUS", target="REVIEW_ANONYMOUS") def review(self): self.counter += 1 class Meta: app_label = 'testapp' def count_calls(sender, instance, name, source, target, **kwargs): instance.signal_counter += 1 post_transition.connect(count_calls, sender=TestModel) class TestStateProxy(TestCase): def test_transition_method_called_once(self): model = TestModel() model.review() self.assertEqual(1, model.counter) # BUG self.assertEqual(1, model.signal_counter)
from django_fsm.signals import pre_transition, post_transition from .managers import StateLogManager from .utils import import_class_by_path class StateLog(models.Model): timestamp = models.DateTimeField(default=now) by = models.ForeignKey(getattr(settings, 'AUTH_USER_MODEL', 'auth.User'), blank=True, null=True) state = models.CharField(max_length=255, db_index=True) transition = models.CharField(max_length=255) content_type = models.ForeignKey(ContentType) object_id = models.PositiveIntegerField(db_index=True) content_object = GenericForeignKey('content_type', 'object_id') objects = StateLogManager() def __unicode__(self): return '{} - {} - {}'.format( self.timestamp, self.content_object, self.transition ) backend = import_class_by_path(settings.DJANGO_FSM_LOG_STORAGE_METHOD) backend.setup_model(StateLog) pre_transition.connect(backend.pre_transition_callback) post_transition.connect(backend.post_transition_callback)
_etcd_client.delete('/deis/domains/{}'.format(app)) # Log significant app-related events post_save.connect(_log_build_created, sender=Build, dispatch_uid='api.models.log') post_save.connect(_log_release_created, sender=Release, dispatch_uid='api.models.log') post_save.connect(_log_config_updated, sender=Config, dispatch_uid='api.models.log') post_save.connect(_log_domain_added, sender=Domain, dispatch_uid='api.models.log') post_delete.connect(_log_domain_removed, sender=Domain, dispatch_uid='api.models.log') # save FSM transitions as they happen def _save_transition(**kwargs): kwargs['instance'].save() post_transition.connect(_save_transition) # wire up etcd publishing if we can connect try: _etcd_client = etcd.Client(host=settings.ETCD_HOST, port=int(settings.ETCD_PORT)) _etcd_client.get('/deis') except etcd.EtcdException: logger.log(logging.WARNING, 'Cannot synchronize with etcd cluster') _etcd_client = None if _etcd_client: post_save.connect(_etcd_publish_key, sender=Key, dispatch_uid='api.models') post_delete.connect(_etcd_purge_key, sender=Key, dispatch_uid='api.models') post_delete.connect(_etcd_purge_user, sender=User, dispatch_uid='api.models') post_save.connect(_etcd_publish_domains, sender=Domain, dispatch_uid='api.models') post_delete.connect(_etcd_publish_domains, sender=Domain, dispatch_uid='api.models')
# -*- coding: utf-8 -*- from __future__ import unicode_literals from django_fsm.signals import post_transition from edw.tasks import send_notification def transition_event_notification(sender, instance, name, source, target, **kwargs): if hasattr(instance, 'send_notification'): send_notification.apply_async( kwargs={ 'model_name': instance.__class__.__name__, 'instance_id': instance.id, 'source': source, 'target': target, } ) return post_transition.connect(transition_event_notification)
def setUp(self): self.pre_transition_called = False self.post_transition_called = False pre_transition.connect(self.on_pre_transition, sender=MultiResultTest) post_transition.connect(self.on_post_transition, sender=MultiResultTest)
def setUp(self): self.model = ExceptionalBlogPost() post_transition.connect(self.on_post_transition, sender=ExceptionalBlogPost) self.post_transition_data = None
def setUp(self): self.model = ExceptionalBlogPost() post_transition.connect(self.on_post_transition, sender=ExceptionalBlogPost) self.post_transition_data = None
@classmethod def remove(cls, callback): scheduler = cls.get_scheduler() if scheduler.get_job(callback.__name__) is not None: scheduler.remove_job(callback.__name__) @classmethod def get_list(cls): job_list = [] scheduler = cls.get_scheduler() for job in scheduler.get_jobs(): if hasattr(job, 'next_run_time'): status = job.next_run_time else: status = 'pending' job_list.append((job.name, job.func.__doc__, job.trigger, status)) return job_list PrintFieldsPlugIn.add_plugin(GeneralPrintPlugin) def post_after_transition(sender, **kwargs): if 'exception' not in kwargs: instance = kwargs['instance'] instance.save() post_transition.connect(post_after_transition)
def ready(self): from django_fsm.signals import post_transition post_transition.connect(order_event_notification)
def setUp(self): self.model = BlogPost() self.pre_transition_called = False self.post_transition_called = False pre_transition.connect(self.on_pre_transition, sender=BlogPost) post_transition.connect(self.on_post_transition, sender=BlogPost)
object_id = models.PositiveIntegerField(db_index=True) content_object = GenericForeignKey('content_type', 'object_id') objects = StateLogManager() class Meta: get_latest_by = 'timestamp' def __str__(self): return '{} - {} - {}'.format( self.timestamp, self.content_object, self.transition ) def get_state_display(self): fsm_obj = self.content_object for field in fsm_obj._meta.fields: if isinstance(field, FSMFieldMixin): state_display = dict(field.flatchoices).get(self.state, self.state) return force_text(state_display, strings_only=True) try: import django.apps except: # django < 1.7 backend = import_by_path(settings.DJANGO_FSM_LOG_STORAGE_METHOD) backend.setup_model(StateLog) pre_transition.connect(backend.pre_transition_callback) post_transition.connect(backend.post_transition_callback)
post_save.connect(_log_build_created, sender=Build, dispatch_uid='api.models.log') post_save.connect(_log_release_created, sender=Release, dispatch_uid='api.models.log') post_save.connect(_log_config_updated, sender=Config, dispatch_uid='api.models.log') post_save.connect(_log_domain_added, sender=Domain, dispatch_uid='api.models.log') post_delete.connect(_log_domain_removed, sender=Domain, dispatch_uid='api.models.log') # save FSM transitions as they happen def _save_transition(**kwargs): kwargs['instance'].save() # close database connections after transition # to avoid leaking connections inside threads from django.db import connection connection.close() post_transition.connect(_save_transition) # wire up etcd publishing if we can connect try: _etcd_client = etcd.Client(host=settings.ETCD_HOST, port=int(settings.ETCD_PORT)) _etcd_client.get('/deis') except etcd.EtcdException: logger.log(logging.WARNING, 'Cannot synchronize with etcd cluster') _etcd_client = None if _etcd_client: post_save.connect(_etcd_publish_key, sender=Key, dispatch_uid='api.models') post_delete.connect(_etcd_purge_key, sender=Key, dispatch_uid='api.models') post_delete.connect(_etcd_purge_user, sender=User, dispatch_uid='api.models') post_save.connect(_etcd_publish_domains, sender=Domain, dispatch_uid='api.models') post_delete.connect(_etcd_purge_domains, sender=Domain, dispatch_uid='api.models')
def create_standard_obm(sender, instance, created, **kwargs): if created and instance.client.outstanding_balance != 0: try: mod = OutstandingBalanceModifierTag.objects.get(name='Standard') except OutstandingBalanceModifierTag.DoesNotExist: pass else: OutstandingBalanceModifier.objects.create( invoice=instance, memo='Outstanding Balance', amount=mod.amount, percentage=mod.percentage, charge_type=mod ) post_save.connect(create_standard_obm, sender=ClientInvoice) post_transition.connect(create_pdf, sender=ClientInvoice) class TutorInvoice(Invoice): tutor = models.ForeignKey('Tutor.Tutor') def close_invoice(self): self.save() memo = unicode(self.tutor) + ' ' + unicode(self.start_date) + \ ' through ' + unicode(self.end_date) Transaction.objects.create(memo=memo, date=timezone.now(), payment=self.amount, payee_object=self.tutor) def open_invoice(self): self.save()
def setUp(self): self.model = BlogPost() self.pre_transition_called = False self.post_transition_called = False pre_transition.connect(self.on_pre_transition, sender=BlogPost) post_transition.connect(self.on_post_transition, sender=BlogPost)
from motius_user.models import StudentProfile from .enums import InvoiceStatus from .models import Invoice, IbanBankAccount def generate_invoice_pdf(sender, instance, name, source, target, **kwargs): if target == InvoiceStatus.OPEN and not is_duplicate_transition(name, instance): with tempfile.NamedTemporaryFile() as fh: motius_pdf.from_url( settings.SITE_URL + reverse('payment_invoice_html', args=[instance.pk]), fh.name, ) instance.pdf = File(fh) instance.save() action.send(instance, verb='new invoice generated for', target=instance.recipient) post_transition.connect(generate_invoice_pdf, sender=Invoice, dispatch_uid="generate_invoice_pdf") def update_default_iban(sender, instance, created, raw, **kwargs): """ Unsets any other defaults if the saved instance is default """ if instance.default: instance.student.bank_accounts\ .filter(default=True)\ .exclude(pk=instance.pk)\ .update(default=False) post_save.connect(update_default_iban, sender=IbanBankAccount, dispatch_uid="update_default_iban") def delete_default_iban(sender, instance, using, **kwargs):