class ApplicationSchema(ma.SQLAlchemyAutoSchema): class Meta: model = Application load_instance = True ordered = True include_relationships = True status = EnumField(ApplicationStatus) applicant = ma.Nested('AccountSchema', only=('full_name', 'email')) feedback = ma.Nested('FeedbackSchema', exclude=('time', )) reports = ma.Nested('VolunteeringReportSchema', many=True) telegram_username = ma.Str(data_key='telegram')
class NotificationSchema(ma.SQLAlchemyAutoSchema): class Meta: model = Notification load_instance = True include_relationships = True type = EnumField(NotificationType) payload = ma.Nested(PayloadSchema)
class StockChangeSchema(ma.SQLAlchemyAutoSchema): class Meta: model = StockChange load_instance = True ordered = True include_fk = True include_relationships = True status = EnumField(StockChangeStatus) variety = ma.Nested(VarietySchema, exclude=('stock_changes', )) account = ma.Nested('AccountSchema', only=('email', 'full_name')) product = ma.Nested('ProductSchema', only=('id', 'name', 'type')) @pre_dump def get_product(self, stock_change, **_kwargs): stock_change.product = Product.query.get( stock_change.variety.product_id) return stock_change
class ApplicationActivitySchema(ma.SQLAlchemyAutoSchema): '''An intermediate schema for VolunteeringReportSchema to get the activity name.''' class Meta: model = Application load_instance = True fields = ('activity', ) include_relationships = True activity = ma.Nested('ActivityProjectSchema')
class ActivityProjectSchema(ma.SQLAlchemyAutoSchema): '''An intermediate schema for VolunteeringReportSchema to get the project name.''' class Meta: model = Application load_instance = True fields = ('project', 'name') include_relationships = True project = ma.Nested('ProjectSchema', only=('name', 'id'))
class VolunteeringReportSchema(ma.SQLAlchemyAutoSchema): class Meta: model = VolunteeringReport load_instance = True ordered = True include_fk = True include_relationships = True reporter_email = ma.Str(dump_only=True) application_id = ma.Int(dump_only=True) application = ma.Nested('ApplicationActivitySchema', data_key='application_on') rating = ma.Int(validate=validate.Range(min=1, max=5))
class ProjectSchema(ma.SQLAlchemyAutoSchema): class Meta: model = Project load_instance = True ordered = True include_relationships = True name = ma.Str(allow_none=True, validate=validate.Length(max=128), error_messages={ 'validator_failed': 'The name must be below 128 characters.' }) creator = ma.Nested('AccountSchema', only=('full_name', 'email')) image_id = ma.Int(allow_none=True) review_status = EnumField(ReviewStatus) lifetime_stage = EnumField(LifetimeStage) activities = ma.Nested('ActivitySchema', many=True) moderators = ma.Nested('AccountSchema', only=('full_name', 'email'), many=True) start_date = ma.DateTime() end_date = ma.DateTime()
class ProductSchema(ma.SQLAlchemyAutoSchema): class Meta: model = Product load_instance = True ordered = True include_relationships = True varieties = ma.Nested('VarietySchema', many=True, validate=validate.Length(min=1)) name = ma.Str(validate=validate.Length(min=1, max=128)) type = ma.Str(validate=validate.Length(min=1, max=128), allow_none=True) description = ma.Str(validate=validate.Length(max=1024)) price = ma.Int(validate=validate.Range(min=1))
class PayloadSchema(ma.Schema): project = ma.Nested('ProjectSchema', only=('id', 'name', 'review_status', 'lifetime_stage', 'image_id')) activity = ma.Nested('ActivitySchema', only=('id', 'name', 'internal', 'reward_rate')) product = ma.Nested('ProductSchema', only=('id', 'name', 'type', 'price')) variety = ma.Nested('VarietySchema', only=('id', 'size', 'color', 'images')) account = ma.Nested('AccountSchema', only=('email', 'full_name')) application = ma.Nested('ApplicationSchema', only=('id', 'status', 'actual_hours')) stock_change = ma.Nested('StockChangeSchema', only=('id', 'amount', 'status')) transaction = ma.Nested('TransactionSchema', only=('id', 'change')) message = ma.Str() @pre_dump def fill_data(self, data, **_kwargs): if 'project_id' in data: data['project'] = Project.query.get(data.pop('project_id')) if 'activity_id' in data: data['activity'] = Activity.query.get(data.pop('activity_id')) if 'product_id' in data: data['product'] = Product.query.get(data.pop('product_id')) if 'variety_id' in data: data['variety'] = Variety.query.get(data.pop('variety_id')) if 'account_email' in data: data['account'] = Account.query.get(data.pop('account_email')) if 'application_id' in data: data['application'] = Application.query.get( data.pop('application_id')) if 'stock_change_id' in data: data['stock_change'] = StockChange.query.get( data.pop('stock_change_id')) if 'transaction_id' in data: data['transaction'] = Transaction.query.get( data.pop('transaction_id')) return data
class VarietySchema(ma.SQLAlchemyAutoSchema): class Meta: model = Variety load_instance = True ordered = True include_fk = True include_relationships = True @pre_load def create_stock_change(self, data, **_kwargs): """Convert the integer `amount` property into a stock change.""" if 'stock_changes' in data: raise ValidationError( 'The stock changes are not to be specified explicitly.') if self.context.get('update', False): return data if 'amount' not in data: raise ValidationError('The amount for a variety is not specified.') amount = data.pop('amount') data['stock_changes'] = [{ 'amount': amount, 'account_email': self.context['user'].email, 'status': 'carried_out', }] return data @pre_load def normalize_color(self, data, **_kwargs): """Normalize the color value.""" if 'color' not in data: if self.context.get('update', False): return data raise ValidationError('The color must be specified.') if data['color'] is None: return data if data['color'].startswith('#'): data['color'] = data['color'][1:].upper() if len(data['color']) != 6: raise ValidationError( f'The color value is {len(data["color"])} characters long, 6 expected.' ) return data @pre_load def enumerate_images(self, data, **_kwargs): """Convert the array of URL strings to an array of image objects with order.""" if self.context.get('update', False): if 'images' in data: data['images'] = [{ 'order': idx, 'image_id': id } for (idx, id) in enumerate(data['images'], start=1)] else: try: data['images'] = [{ 'order': idx, 'image_id': id } for (idx, id) in enumerate(data['images'], start=1)] except KeyError: raise ValidationError('Images must be specified.') return data @post_dump def format_color(self, data, **_kwargs): """Add a '#' to the color value.""" if data['color'] is not None: data['color'] = '#' + data['color'] return data @post_dump def flatten_images(self, data, **_kwargs): """Convert an array of image objects with order into a flat array of URL strings.""" if 'images' not in data: return data data['images'] = [ image["image_id"] for image in sorted(data['images'], key=lambda x: x['order']) ] return data images = ma.Nested('ProductImageSchema', many=True) stock_changes = ma.Nested('StockChangeSchema', many=True) amount = ma.Int(dump_only=True) purchases = ma.Int(dump_only=True)