class AbstractReportSliceSerializer(ModelSerializer): """Abstract serializer for the ReportSlice models.""" report_platform_id = UUIDField(format='hex_verbose', required=False) report_slice_id = UUIDField(format='hex_verbose', required=False) account = CharField(max_length=50, required=False) report_json = JSONField(allow_null=False) git_commit = CharField(max_length=50, required=False) source = CharField(max_length=15, required=True) source_metadata = JSONField(allow_null=True, required=False) state = ChoiceField(choices=ReportSlice.STATE_CHOICES) retry_type = ChoiceField(choices=ReportSlice.RETRY_CHOICES, default=ReportSlice.TIME) state_info = JSONField(allow_null=False) retry_count = IntegerField(default=0) hosts_count = IntegerField(min_value=1, max_value=MAX_HOSTS_PER_REP) last_update_time = DateTimeField(allow_null=False) failed_hosts = JSONField(allow_null=True) candidate_hosts = JSONField(allow_null=True) ready_to_archive = BooleanField(default=False) creation_time = DateTimeField(allow_null=False) processing_start_time = DateTimeField(allow_null=True, required=False) processing_end_time = DateTimeField(allow_null=True, required=False) class Meta: """Meta class for AbstractReportSliceSerializer.""" abstract = True fields = '__all__'
class HttpConfigSerializer(ModelSerializer): header = JSONField() url_encoded_params = JSONField() class Meta: model = HttpConfig fields = ["url_encoded_params", "header"] @classmethod def build_from_metaclass(cls): properties = cls.build_properties() return type("MetaHttpConfigSerializer", (ModelSerializer, ), properties) @classmethod def build_properties(cls): properties = { "Meta": cls.build_nested_meta_class(), "header": JSONField(), "url_encoded_params": JSONField() } return properties @classmethod def build_nested_meta_class(cls): properties = { "model": HttpConfig, "fields": ["header", "url_encoded_params"] } return type("Meta", (), properties) def create(self, validated_data): return self.Meta.model.objects.create(**validated_data)
class AbstractReportSerializer(ModelSerializer): """Abstract serializer for the Report models.""" report_platform_id = UUIDField(format='hex_verbose', required=False) host_inventory_api_version = CharField(max_length=10, required=False) source = CharField(max_length=15, required=False) source_metadata = JSONField(allow_null=True, required=False) account = CharField(max_length=50, required=False) request_id = CharField(max_length=50, required=False) upload_ack_status = CharField(max_length=10, required=False) upload_srv_kafka_msg = JSONField(required=True) git_commit = CharField(max_length=50, required=False) state = ChoiceField(choices=Report.STATE_CHOICES) retry_type = ChoiceField(choices=Report.RETRY_CHOICES, default=Report.TIME) state_info = JSONField(allow_null=True) retry_count = IntegerField(default=0) last_update_time = DateTimeField(allow_null=True) ready_to_archive = BooleanField(default=False) arrival_time = DateTimeField(allow_null=False) processing_start_time = DateTimeField(allow_null=True, required=False) processing_end_time = DateTimeField(allow_null=True, required=False) class Meta: """Meta class for ReportSerializer.""" abstract = True fields = '__all__'
def build_properties(cls): properties = { "Meta": cls.build_nested_meta_class(), "header": JSONField(), "url_encoded_params": JSONField() } return properties
class CustomerContactSerializer(ModelSerializer): customer_id = UUIDField(read_only=True) customer_name_kanji = JSONField(read_only=True) cc_attrs = JSONField(read_only=True) is_basic = BooleanField(read_only=True) forests_count = IntegerField(read_only=True) business_id = CharField(read_only=True) class Meta: model = Contact exclude = ["contact_info", "deleted"]
class CampaignSerializer(ModelSerializer): location = JSONField() publicity_configuration = JSONField() products = JSONField() budget = DecimalField(max_digits=12, decimal_places=3) gender_range = ChoiceField(choices=['M', 'F', 'M-F']) class Meta: model = Campaign exclude = ('clients', )
class Payload(Serializer): user = User() response_url = CharField() actions = Action(many=True) trigger_id = CharField() submission = JSONField() callback_id = CharField()
class LessonProgressSerializer(ModelSerializer): """ Annotates a Lesson with progress information based on logs generated by the requesting User """ progress = SerializerMethodField() resources = JSONField(default='[]') class Meta: model = Lesson fields = ( 'description', 'id', 'is_active', 'title', 'progress', 'resources', ) def get_progress(self, instance): content_ids = [resource['content_id'] for resource in instance.resources] num_completed_logs = ContentSummaryLog.objects \ .exclude(completion_timestamp__isnull=True) \ .filter( user=self.context['user'], content_id__in=content_ids ) \ .count() return { 'resources_completed': num_completed_logs, 'total_resources': len(instance.resources), }
class OutpostSerializer(ModelSerializer): """Outpost Serializer""" config = JSONField(validators=[is_dict], source="_config") providers_obj = ProviderSerializer(source="providers", many=True, read_only=True) def validate_config(self, config) -> dict: """Check that the config has all required fields""" try: from_dict(OutpostConfig, config) except DaciteError as exc: raise ValidationError( f"Failed to validate config: {str(exc)}") from exc return config class Meta: model = Outpost fields = [ "pk", "name", "type", "providers", "providers_obj", "service_connection", "token_identifier", "config", ]
class DataFrameRecordsSerializer(Serializer): """ A Serializer implementation that uses :func:`pandas.DataFrame.from_dict <pandas.DataFrame.from_records>` and :func:`pandas.DataFrame.to_dict <pandas.DataFrame.to_records>` to convert data to internal value and to external representation. """ columns = ListField(child=CharField()) data = ListField(child=JSONField()) def to_internal_value(self, data): validated_data = super().to_internal_value(data) try: data_frame = pd.DataFrame.from_records( validated_data['data'], index='index', columns=validated_data['columns']) return data_frame except ValueError as e: raise ValidationError( {api_settings.NON_FIELD_ERRORS_KEY: [str(e)]}) def to_representation(self, instance): recarray = instance.to_records(index=True) return OrderedDict([('columns', recarray.dtype.names), ('data', recarray.tolist())])
class LessonProgressSerializer(ModelSerializer): """ Annotates a Lesson with progress information based on logs generated by the requesting User """ progress = SerializerMethodField() resources = JSONField(default="[]") class Meta: model = Lesson fields = ("description", "id", "is_active", "title", "progress", "resources") def get_progress(self, instance): content_ids = [resource["content_id"] for resource in instance.resources] resource_progress = ( ContentSummaryLog.objects.filter( user=self.context["user"], content_id__in=content_ids ) .aggregate(Sum("progress")) .get("progress__sum") ) return { "resource_progress": resource_progress, "total_resources": len(instance.resources), }
class ArtifactStatsSerializer(Serializer): # Fields metadata = MetadataSerializer() timestamp = UnixEpochDateTimeField() metrics = JSONField(encoder=DjangoJSONEncoder) def create(self, validated_data): return ArtifactStatsRest(**validated_data)
class ProblemPostSerializer(ModelSerializer): inputs = JSONField() sample_inputs = JSONField() solution_code = CharField() solution_lang = CharField() checker_type = CharField() checker_code = CharField(allow_blank=True) class Meta: model = Problem fields = ('title', 'description', 'time_limit', 'memory_limit', 'note', 'sample_inputs', 'checker_type', 'inputs', 'checker_code', 'solution_code', 'solution_lang') def create(self, validated_data): validated_data['checker_type'] = getattr( CheckerType, validated_data['checker_type']).value if not validated_data['sample_inputs']: validated_data['sample_inputs'] = validated_data['inputs'][:2] else: validated_data['inputs'] = validated_data[ 'sample_inputs'] + validated_data['inputs'] inputs = validated_data.pop('inputs') solution_code = validated_data.pop('solution_code') solution_lang = validated_data.pop('solution_lang') problem = Problem(**validated_data) problem.save() test_case = TestCase(problem=problem, inputs=inputs, expected_outputs="") solution = Solution(problem=problem, code=solution_code, lang=getattr(LanguageEnum, solution_lang).value, is_model_solution=True) test_case.save() solution.save() save_input_files(problem.id, inputs) return problem def to_representation(self, problem): # used in serializer.data return {'problem_id': problem.id}
class ProposalSerializer(HyperlinkedModelSerializer): data = JSONField() proposer = StringRelatedField() class Meta: model = PopularProposal fields = ('id', 'title', 'slug', 'get_absolute_url', 'data', 'proposer', 'created', 'clasification', 'is_local_meeting', 'nro_supports')
class ListCancelledOrderSerializer(serializers.ModelSerializer): payload = JSONField() class Meta: model = CancelledOrder fields = ( 'order_id', 'payload', 'created', )
class ProblemPutSerializer(ModelSerializer): inputs = JSONField() sample_inputs = JSONField() solution_code = CharField() solution_lang = CharField() checker_type = CharField() checker_code = CharField(allow_blank=True) class Meta: model = Problem fields = ('id', 'title', 'description', 'time_limit', 'memory_limit', 'note', 'sample_inputs', 'checker_type', 'inputs', 'checker_code', 'solution_code', 'solution_lang') def update(self, problem, validated_data): validated_data['checker_type'] = getattr( CheckerType, validated_data['checker_type']).value if not validated_data['sample_inputs']: validated_data['sample_inputs'] = validated_data['inputs'][:2] else: validated_data['inputs'] = validated_data[ 'sample_inputs'] + validated_data['inputs'] inputs = validated_data.pop('inputs') solution_code = validated_data.pop('solution_code') solution_lang = validated_data.pop('solution_lang') for k, v in validated_data.items(): setattr(problem, k, v) problem.save() Solution.objects.filter(problem=problem, is_model_solution=True).update( code=solution_code, lang=getattr(LanguageEnum, solution_lang).value) save_input_files(problem.id, inputs) return problem def to_representation(self, problem): # used in serializer.data return {'problem_id': problem.id}
class ContextModelSerializer(serializers.ModelSerializer): context = JSONField( encoder=None, required=False, allow_null=True, write_only=True, help_text= "Provide extra context for dynamic jexl transforms and events", ) def validate(self, data): self.context_data = data.pop("context", None) return super().validate(data)
class CategoryCreateSerializer(ModelSerializer): children = JSONField(required=False) class Meta: model = Category fields = ('name', 'children') def create(self, validated_data): name = self.get_name(validated_data) parent = Category.objects.create(name=name) children = self.get_children(validated_data) if len(children) > 0: self.process_kids(parent, children) return parent @staticmethod def get_name(validated_data): try: return validated_data.pop('name') except KeyError: raise ValidationError({'name': '"name" field is required.'}) @staticmethod def get_children(validated_data): try: return validated_data.pop('children') except KeyError: return [] @staticmethod def process_kids(parent, children): kids = [] for child in children: kids.append(CategoryCreateSerializer.retreive_kid(child)) parent.kids.add(*kids) CategoryCreateSerializer.set_siblings(kids) @staticmethod def retreive_kid(child): serializer = CategoryCreateSerializer(data=child) serializer.is_valid(raise_exception=True) return serializer.create(serializer.validated_data) @staticmethod def set_siblings(kids): if len(kids) > 0: for i, kid in enumerate(kids): kid.siblings.add(*kids[i + 1:])
class BankAccountSerializer(UuidModelSerializer): """ Bank Account serializer. """ bank = BankSerializer() identification = JSONField() class Meta(UuidModelSerializer.Meta): model = models.BankAccount fields = UuidModelSerializer.Meta.fields + ( 'bank', 'type', 'identification', 'transferwise_recipient_id', )
class ContactSerializer(ModelSerializer): forest_internal_id = CharField(read_only=True) forest_id = UUIDField(read_only=True) forestcustomer_id = UUIDField(read_only=True) customer_id = UUIDField(read_only=True) owner_customer_id = UUIDField(read_only=True) cc_attrs = JSONField(read_only=True) # forest customer contact default default = BooleanField(read_only=True) is_basic = BooleanField(read_only=True) forests_count = IntegerField(read_only=True) business_id = CharField(read_only=True) class Meta: model = Contact exclude = ["contact_info", "deleted"]
class ReceiveMessageSerializer(serializers.ModelSerializer): uuid = serializers.CharField() payload = JSONField() class Meta: model = Inbox fields = ( 'origin_create_time', 'uuid', 'message_source', 'message_type', 'payload' ) def create(self, validated_data): return get_inbox_service().handle_message( validated_data['uuid'], validated_data['origin_create_time'], validated_data['message_source'], validated_data['message_type'], validated_data['payload'], )
class ClientSerializer(ModelSerializer): location = JSONField(required=False) email = EmailField() salary = DecimalField(max_digits=9, decimal_places=2, required=False, source='earnings') gender = ChoiceField(choices=['M', 'F'], required=False) total_campaigns = IntegerField(required=False) birth_date = DateField(required=False) name = CharField(max_length=256, source='full_name') class Meta: model = Client fields = ('location', 'email', 'salary', 'gender', 'total_campaigns', 'birth_date', 'name', 'dni', 'id')
class UserFilterSerializer(HyperlinkedModelSerializer): user = PrimaryKeyRelatedField(read_only=True) filter = JSONField() def to_representation(self, instance): ret = super(UserFilterSerializer, self).to_representation(instance) filter = ret['filter'] ret['filter'] = json.loads(filter) return ret class Meta: model = UserFilter fields = ('url', 'id', 'user', 'name', 'filter', 'date')
class OutpostSerializer(ModelSerializer): """Outpost Serializer""" _config = JSONField(validators=[is_dict]) providers_obj = ProviderSerializer(source="providers", many=True, read_only=True) class Meta: model = Outpost fields = [ "pk", "name", "providers", "providers_obj", "service_connection", "token_identifier", "_config", ]
class StripeCustomerSerializer(ModelSerializer): stripe_js_response = JSONField() def create(self, validated_data): instance = None if validated_data.get("stripe_js_response"): # Create a Customer try: user = self.context['request'].user stripe_js_response = validated_data.pop("stripe_js_response") instance = StripeCustomer.objects.create( user=user, stripe_js_response=stripe_js_response) instance.create_at_stripe() except stripe.StripeError as e: raise ValidationError({"stripe_js_response": e}) return instance class Meta: model = StripeCustomer fields = ["stripe_js_response"]
class TestSerializer(Serializer): # pylint: disable=abstract-method boolean_field = BooleanField() char_field = CharField() choice_field = ChoiceField([]) date_field = DateField() date_time_field = DateTimeField() decimal_field = DecimalField(1, 1) dict_field = DictField() duration_field = DurationField() email_field = EmailField() file_field = FileField() file_path_field = FilePathField('') float_field = FloatField() image_field = ImageField() integer_field = IntegerField() ip_address_field = IPAddressField() json_field = JSONField() string_list_field = ListField(child=CharField()) int_list_field = ListField(child=IntegerField()) int_list_list_field = ListField( child=ListField( child=IntegerField(), ), ) multiple_choice_field = MultipleChoiceField([]) null_boolean_field = NullBooleanField() regex_field = RegexField('') slug_field = SlugField() time_field = TimeField() url_field = URLField() uuid_field = UUIDField() nullable_char_field = CharField(allow_null=True) nullable_char_listfield = ListField( child=CharField(allow_null=True), ) write_only_field = CharField(write_only=True)
class StripeCustomerSerializer(ModelSerializer): stripe_js_response = JSONField() def create(self, validated_data): instance = None if validated_data.get("stripe_js_response"): # Create a Customer try: user = self.context['request'].user stripe_js_response = validated_data.pop("stripe_js_response") instance = StripeCustomer.objects.create( user=user, stripe_js_response=stripe_js_response) instance.create_at_stripe() except stripe.error.StripeError as e: logging.error( "[AA-Stripe] creating customer failed for user {user.id}: {error}".format(user=user, error=e) ) raise ValidationError({"stripe_error": e._message}) return instance class Meta: model = StripeCustomer fields = ["stripe_js_response"]
class CreateSaleSerializer(serializers.ModelSerializer): solditems = ItemSerializer(many=True) payment_data = JSONField() class Meta: model = Sales fields = ('id', 'user', 'invoice_number', 'table', 'sale_point', 'total_net', 'sub_total', 'balance', 'terminal', 'amount_paid', 'payment_data', 'status', 'total_tax', 'discount_amount', 'solditems') def validate_total_net(self, value): data = self.get_initial() try: Decimal(data.get('total_net')) except Exception as e: raise ValidationError('Total Net should be a decimal/integer') return value def validate_total_tax(self, value): data = self.get_initial() try: total_net = Decimal(data.get('total_net')) total_tax = Decimal(data.get('total_tax')) if total_tax >= total_net: raise ValidationError( 'Total tax cannot be more than total net') except Exception as e: raise ValidationError('Total Net should be a decimal/integer') return value def validate_discount_amount(self, value): data = self.get_initial() try: discount = Decimal(data.get('discount_amount')) except Exception as e: raise ValidationError('Discount should be a decimal/integer *' + str(discount) + '*') return value def validate_status(self, value): data = self.get_initial() status = str(data.get('status')) if status == 'fully-paid' or status == 'payment-pending': return value else: raise ValidationError( 'Enter correct Status. Expecting either fully-paid/payment-pending' ) def validate_terminal(self, value): data = self.get_initial() terminal_id = int(data.get('terminal')) try: Terminal.objects.get(pk=terminal_id) except Exception as e: raise ValidationError('Terminal specified does not exist') return value def create(self, validated_data): # add sold amount to drawer try: total_net = Decimal(validated_data.get('total_net')) except Exception as e: total_net = Decimal(0) try: total_tax = Decimal(validated_data.get('total_tax')) except Exception as e: total_tax = Decimal(0) terminal = validated_data.get('terminal') terminal.amount += Decimal(total_net) terminal.save() sale = Sales() try: sold_items_data = validated_data.pop('solditems') except Exception as e: raise ValidationError('Ordered items field should not be empty') status = validated_data.get('status') # make a sale sale.user = validated_data.get('user') sale.invoice_number = validated_data.get('invoice_number') sale.total_net = validated_data.get('total_net') sale.debt = validated_data.get('total_net') sale.sub_total = validated_data.get('sub_total') sale.balance = validated_data.get('balance') sale.terminal = validated_data.get('terminal') #sale.table = validated_data.get('table') sale.sale_point = validated_data.get('sale_point') sale.amount_paid = validated_data.get('amount_paid') sale.status = status sale.payment_data = validated_data.get('payment_data') sale.total_tax = total_tax sale.mobile = validated_data.get('mobile') sale.discount_amount = validated_data.get('discount_amount') sale.save() # add payment options for sold_item_data in sold_items_data: SoldItem.objects.create(sales=sale, **sold_item_data) try: item = Item.objects.get(stock__sku=sold_item_data['sku']) if item: Item.objects.decrease_stock(item, sold_item_data['quantity']) else: print('stock not found') except Exception as e: print('Error reducing stock!') return sale
class SystemFingerprintSerializer(NotEmptySerializer): """Serializer for the Fingerprint model.""" # Common facts system_platform_id = UUIDField(format='hex_verbose', read_only=True) name = CharField(required=False, max_length=256) os_name = CharField(required=False, max_length=64) os_release = CharField(required=False, max_length=128) os_version = CharField(required=False, max_length=64) infrastructure_type = ChoiceField( required=False, choices=SystemFingerprint.INFRASTRUCTURE_TYPE) mac_addresses = CustomJSONField(required=False) ip_addresses = CustomJSONField(required=False) cpu_count = IntegerField(required=False, min_value=0) architecture = CharField(required=False, max_length=64) # Network scan facts bios_uuid = CharField(required=False, max_length=36) subscription_manager_id = CharField(required=False, max_length=36) cpu_socket_count = IntegerField(required=False, min_value=0) cpu_core_count = FloatField(required=False, min_value=0) cpu_core_per_socket = IntegerField(required=False, min_value=0) system_creation_date = DateField(required=False) system_last_checkin_date = DateField(required=False) system_role = CharField(required=False, max_length=128) system_addons = JSONField(required=False) system_service_level_agreement = CharField(required=False, max_length=128) system_usage_type = CharField(required=False, max_length=128) insights_client_id = CharField(required=False, max_length=128) virtualized_type = CharField(required=False, max_length=64) # VCenter scan facts vm_state = CharField(required=False, max_length=24) vm_uuid = CharField(required=False, max_length=36) vm_dns_name = CharField(required=False, max_length=256) vm_host = CharField(required=False, max_length=128) vm_host_socket_count = IntegerField(required=False, min_value=0) vm_host_core_count = IntegerField(required=False, min_value=0) vm_cluster = CharField(required=False, max_length=128) vm_datacenter = CharField(required=False, max_length=128) products = ProductSerializer(many=True, allow_null=True, required=False) entitlements = EntitlementSerializer(many=True, allow_null=True, required=False) # Red Hat facts is_redhat = NullBooleanField(required=False) redhat_certs = CharField(required=False) # pylint: disable=invalid-name redhat_package_count = IntegerField(required=False, min_value=0) metadata = CustomJSONField(required=True) sources = CustomJSONField(required=True) etc_machine_id = CharField(required=False, max_length=48) class Meta: """Meta class for SystemFingerprintSerializer.""" model = SystemFingerprint fields = '__all__' def create(self, validated_data): """Create a system fingerprint.""" products_data = validated_data.pop('products', []) entitlements_data = validated_data.pop('entitlements', []) fingerprint = SystemFingerprint.objects.create(**validated_data) for product_data in products_data: Product.objects.create(fingerprint=fingerprint, **product_data) for entitlement_data in entitlements_data: Entitlement.objects.create(fingerprint=fingerprint, **entitlement_data) return fingerprint
class OrderUpdateSerializer(serializers.ModelSerializer): ordered_items = ItemSerializer(many=True) payment_data = JSONField() mpesaIds = JSONField(required=False, write_only=True) visaIds = JSONField(required=False, write_only=True) create_credit = serializers.BooleanField(write_only=True) update_credit = serializers.BooleanField(write_only=True) due_date = serializers.CharField(required=False, write_only=True) class Meta: model = Orders fields = ('id', 'invoice_number', 'total_net', 'sub_total', 'balance', 'terminal', 'table', 'room', 'amount_paid', 'status', 'total_tax', 'discount_amount', 'debt', 'ordered_items', 'payment_data', 'mpesaIds', 'visaIds', 'customer', 'customer_name', 'create_credit', 'update_credit', 'due_date') def validate_status(self, value): data = self.get_initial() status = str(data.get('status')) if status == 'fully-paid' or status == 'payment-pending': status = status amount_paid = Decimal(data.get('amount_paid')) sale = Orders.objects.get( invoice_number=str(data.get('invoice_number'))) if status == 'fully-paid' and sale.balance > amount_paid: raise ValidationError( "Status error. Amount paid is less than balance.") else: return value elif status == "cancelled" or status == "credited": pass return value else: raise ValidationError( 'Enter correct Status. Expecting either fully-paid/payment-pending or cancelled' ) def validate_payment_data(self, value): data = self.get_initial() dictionary_value = dict(data.get('payment_data')) return value def validate_total_net(self, value): data = self.get_initial() try: Decimal(data.get('total_net')) return value except Exception as e: raise ValidationError('Total Net should be a decimal/integer') def validate_debt(self, value): data = self.get_initial() try: Decimal(data.get('debt')) except Exception as e: raise ValidationError('Debt should be a decimal/integer') return value def validate_amount_paid(self, value): data = self.get_initial() try: Decimal(data.get('amount_paid')) except Exception as e: raise ValidationError('Amount paid should be a decimal/integer') return value def validate_terminal(self, value): data = self.get_initial() terminal = Terminal.objects.filter(pk=int(data.get('terminal'))) if terminal.exists(): return value else: raise ValidationError('Terminal specified does not exist') def validate_customer(self, value): data = self.get_initial() customer_id = int(data.get('customer')) customer_name = data.get('customer_name') user = None try: user = Customer.objects.get(pk=customer_id) except Exception as e: if customer_name: user = Customer.objects.create(name=customer_name, creditable=True) return user def send_to_credit(self, order): credit = Credit() credit.user = order.user credit.invoice_number = order.invoice_number credit.total_net = order.total_net credit.sub_total = order.sub_total credit.balance = order.balance credit.terminal = order.terminal credit.amount_paid = order.amount_paid credit.status = order.status credit.status = 'payment-pending' credit.payment_data = order.payment_data credit.customer = order.customer credit.customer_name = order.customer_name try: if order.due_date: from datetime import datetime due_date = datetime.strptime(order.due_date, '%Y-%m-%d').date() credit.due_date = due_date except Exception as e: logger.error(e) try: credit.table = order.table credit.room = order.room credit.carry = 'Sitting' except Exception as e: credit.carry = 'Take Away' logger.error(e) credit.total_tax = order.total_tax credit.save() # add credit history try: history = CreditHistoryEntry() history.credit = credit history.balance = credit.total_net history.amount = credit.amount_paid history.save() except Exception as e: logger.error(e) for option in order.payment_data: try: pay_opt = PaymentOption.objects.get( pk=int(option['payment_id'])) credit.payment_options.add(pay_opt) except Exception as e: logger.error("error adding options " + str(e)) for item in order.items(): try: new_item = CreditedItem.objects.create( credit=credit, sku=item.sku, quantity=item.quantity, product_name=item.product_name, total_cost=item.total_cost, unit_cost=item.unit_cost, product_category=item.product_category) new_item.counter = item.counter new_item.transfer_id = item.transfer_id new_item.order = item.id new_item.attributes = item.attributes new_item.unit_purchase = item.unit_purchase new_item.total_purchase = item.total_purchase if item.discount_id: new_item.discount_id = item.discount_id.pk new_item.discount_quantity = item.discount_quantity new_item.discount_total = item.discount_total new_item.discount_set_status = item.discount_set_status new_item.cold = item.cold new_item.cold_quantity = item.cold_quantity if item.counter: try: stock = Stock.objects.filter(sku=item.sku).first() new_item.minimum_price = stock.minimum_price new_item.wholesale_override = stock.wholesale_override new_item.low_stock_threshold = stock.low_stock_threshold new_item.unit_purchase = stock.cost_price except Exception as e: pass elif item.kitchen: new_item.is_stock = False else: pass new_item.kitchen = item.kitchen new_item.save() except Exception as e: logger.error(e.message, exception=e) def diff(self, list1, list2): s = set(list2) d = [x for x in list1 if x not in s] return list(d) def same(self, list1, list2): s = set(list1) & set(list2) return list(s) def update(self, instance, validated_data): terminal = validated_data.get('terminal', instance.terminal.id) terminal.amount += Decimal( validated_data.get('amount_paid', instance.amount_paid)) terminal.save() instance.table = validated_data.get('table', instance.table) instance.room = validated_data.get('room', instance.room) instance.total_net = validated_data.get('total_net', instance.total_net) instance.debt = instance.debt - validated_data.get( 'amount_paid', instance.amount_paid) instance.amount_paid = instance.amount_paid + validated_data.get( 'amount_paid', instance.amount_paid) instance.balance = validated_data.get('balance', instance.balance) instance.customer = validated_data.get('customer', instance.customer) instance.customer_name = validated_data.get('customer_name', instance.customer_name) if validated_data.get('customer_name'): try: customer = Customer.objects.get(name=instance.customer_name) except: customer = Customer.objects.create(name=instance.customer_name, creditable=True) instance.customer = customer if instance.amount_paid >= instance.total_net: instance.status = 'fully-paid' instance.payment_data = validated_data.get('payment_data') if validated_data.get('mpesaIds'): change_mpesa_id_status(validated_data.get('mpesaIds')) if validated_data.get('visaIds'): change_visa_id_status(validated_data.get('visaIds')) else: instance.status = validated_data.get('status', instance.status) if validated_data.get('status') == "credited": instance.status = "credited" instance.last_status_change = now() instance.save() try: ordered_items_data = validated_data.pop('ordered_items') except Exception as e: raise ValidationError('Ordered items field should not be empty') # return order sold item to transfer stock then delete them # Item = CounterTransferItems items = instance.ordered_items.all() client_ids = [int(i['transfer_id']) for i in ordered_items_data] server_ids = [int(i.transfer_id) for i in items] # get the ids in client not in server client_ids_to_add = self.diff(client_ids, server_ids) # get ids that are both in the client and the server to update their quantities common_ids = self.same(server_ids, client_ids) # add client_ids to the new payload new_payload = [ i for i in ordered_items_data if int(i['transfer_id']) in client_ids_to_add ] # loop through the ordered_items_data and get those that have changed in quantities for item_data in ordered_items_data: # check if the transfer_id exists in the common_ids to match the item if item_data['transfer_id'] in common_ids: try: ordered_item_match = items.get( product_name=item_data['product_name'], sku=item_data['sku'], transfer_id=int(item_data['transfer_id'])) # check if item from counter if ordered_item_match.counter and ordered_item_match.counter == item_data[ 'counter']: try: transferred_item = Item.objects.get( pk=ordered_item_match.transfer_id) # check if stock returned to store and the current stock quantity exceeds the ordered # quantity if (ordered_item_match.quantity + transferred_item.qty) >= int( item_data['quantity']): Item.objects.increase_stock( transferred_item, int(ordered_item_match.quantity)) new_payload.append(item_data) else: # should remain the same item_data[ 'quantity'] = ordered_item_match.quantity item_data[ 'unit_cost'] = ordered_item_match.unit_cost item_data[ 'total_cost'] = ordered_item_match.total_cost item_data[ 'unit_purchase'] = ordered_item_match.unit_purchase item_data[ 'discount_id'] = ordered_item_match.discount_id item_data[ 'discount_quantity'] = ordered_item_match.discount_quantity item_data[ 'discount_total'] = ordered_item_match.discount_total item_data[ 'discount_set_status'] = ordered_item_match.discount_set_status new_payload.append(item_data) except Exception as e: logger.error(e.message, exception=e) # check if item from kitchen elif ordered_item_match.kitchen and ordered_item_match.kitchen == item_data[ 'kitchen']: try: transferred_item = MenuItem.objects.get( pk=ordered_item_match.transfer_id) # check if stock returned to store and the current stock quantity exceeds the ordered # quantity if (ordered_item_match.quantity + transferred_item.qty) >= int( item_data['quantity']): MenuItem.objects.increase_stock( transferred_item, int(ordered_item_match.quantity)) new_payload.append(item_data) else: # should remain the same item_data[ 'quantity'] = ordered_item_match.quantity item_data[ 'unit_cost'] = ordered_item_match.unit_cost item_data[ 'total_cost'] = ordered_item_match.total_cost item_data[ 'unit_purchase'] = ordered_item_match.unit_purchase item_data[ 'discount_id'] = ordered_item_match.discount_id item_data[ 'discount_quantity'] = ordered_item_match.discount_quantity item_data[ 'discount_total'] = ordered_item_match.discount_total item_data[ 'discount_set_status'] = ordered_item_match.discount_set_status new_payload.append(item_data) except Exception as e: logger.error(e.message, exception=e) except Exception as e: logger.error(e.message, exception=e) # delete all order items items.delete() """ recreate orders """ for ordered_item_data in new_payload: OrderedItem.objects.create(orders=instance, **ordered_item_data) if ordered_item_data.get('counter'): try: item = Item.objects.get( pk=int(ordered_item_data['transfer_id'])) if item: Item.objects.decrease_stock( item, ordered_item_data['quantity']) else: logger.info('stock not found') except Exception as e: logger.error('Error reducing counter stock!', exception=e) elif ordered_item_data.get('kitchen'): try: item = MenuItem.objects.get( pk=int(ordered_item_data['transfer_id'])) if item: MenuItem.objects.decrease_stock( item, ordered_item_data['quantity']) else: logger.info('stock not found') except Exception as e: logger.error('Error reducing kitchen stock!', exception=e) else: logger.info('Kitchen or counter were not provided') if validated_data.get('create_credit'): if validated_data.get('due_date'): instance.due_date = validated_data.get('due_date') self.send_to_credit(instance) return instance