def post(self, request): if request.user.is_authenticated: if request.user.is_staff: return redirect('ecommerce:dashboard') return redirect('ecommerce:index') login_form = LoginForm(request.POST) if login_form.is_valid(): user = authenticate( request, username=login_form.cleaned_data.get('username'), password=login_form.cleaned_data.get('password')) if user: login(request, user) if request.GET.get('next', None): return redirect(request.GET.get('next')) if request.user.is_superuser: return redirect('ecommerce:dashboard') if request.user.is_staff: return redirect('ecommerce:dashboard-products') return redirect('ecommerce:index') else: user = User.objects.filter( username=login_form.cleaned_data.get('username')) if user.exists(): user = user.first() if not user.is_active: login_form.add_error( None, _("Your account isn't activated, an admin will activate it soon." )) else: login_form.add_error(None, _('Invalid username/password')) context = dict(login_form=login_form) return render(request, self.template_name, context)
class Rate(DeletableModel): stars = models.DecimalField(max_digits=2, decimal_places=1, verbose_name=_('Stars')) comment = models.CharField(max_length=255, null=True, verbose_name=_('Comment')) profile = models.ForeignKey('accounts.Profile', related_name='ratings', on_delete=do_nothing) product = models.ForeignKey('Product', related_name='ratings', on_delete=do_nothing) class Meta: verbose_name = _('Rating') verbose_name_plural = _('Ratings') @property def checked_stars_range(self): return range(0, int(self.stars)) @property def un_checked_stars_range(self): return range(0, 5 - int(self.stars)) def __str__(self): return f'{self.comment}'
class SearchOrderStatusChangeHistory(forms.Form): FROM_STATUS_CHOICES = (('O', _('Old Status')), ) + Order.status_choices TO_STATUS_CHOICES = (('N', _('New Status')), ) + Order.status_choices date = forms.DateField(required=False, input_formats=['%d/%m/%Y'], widget=BootstrapDatePickerInput()) time = forms.TimeField(required=False, input_formats=['%H:%M'], widget=BootstrapTimePickerInput()) user = forms.ModelChoiceField(queryset=User.objects.exclude(user_type='C'), required=False, empty_label=_('User')) order = forms.ModelChoiceField(queryset=Order.objects.all(), required=False, empty_label=_('Order')) from_status = forms.ChoiceField(choices=FROM_STATUS_CHOICES, required=False) to_status = forms.ChoiceField(choices=TO_STATUS_CHOICES, required=False) def clean_from_status(self): if self.cleaned_data.get('from_status') == 'O': return None return self.cleaned_data.get('from_status') def clean_to_status(self): if self.cleaned_data.get('to_status') == 'N': return None return self.cleaned_data.get('to_status')
class OrderLine(BaseModel): product = models.ForeignKey('Product', related_name='orders_lines', on_delete=do_nothing) order = models.ForeignKey('Order', related_name='lines', on_delete=do_nothing) quantity = models.DecimalField(max_digits=10, decimal_places=2, verbose_name=_('Quantity')) on_discount = models.BooleanField(default=False, verbose_name=_('On Discount')) def __str__(self): return '{} {}'.format(self.quantity, self.product) @property def total(self): return (self.product.price * self.quantity).quantize( decimal.Decimal("0.01")) class Meta: verbose_name = _('Order Line') verbose_name_plural = _('Order Lines') def delete(self, using=None, keep_parents=False): data = super(OrderLine, self).delete(using, keep_parents) from ecommerce.signals import order_line_deleted order_line_deleted.send(sender=self.__class__, instance=self) return data
def __init__(self, is_caller=False, *args, **kwargs): super(CreateOrderForm, self).__init__(*args, **kwargs) if is_caller: self.status_choices = ( ('P', _('Pending')), ('RC', _('RECALL')), ('CO', _('Confirmed')), ('CA', _('Canceled')), ) self.fields['status'] = forms.ChoiceField( choices=self.status_choices)
class Region(BaseModel): name = models.CharField(max_length=255, verbose_name=_('Name')) name_ar = models.CharField(max_length=255, verbose_name=_('Arabic Name')) name_fr = models.CharField(max_length=255, verbose_name=_('English Name')) def __str__(self): return "{0}".format(self.name) class Meta: verbose_name = _('Region') verbose_name_plural = _("Regions")
class City(BaseModel): name = models.CharField(max_length=255, verbose_name=_('Name')) name_ar = models.CharField(max_length=255, verbose_name=_('Arabic Name')) name_en = models.CharField(max_length=255, verbose_name=_('English Name')) code_postal = models.IntegerField(verbose_name=_('Postal Code')) state = models.ForeignKey('State', on_delete=models.DO_NOTHING, related_name='cities', verbose_name=_('State')) def __str__(self): return f"{self.state} {self.name}" class Meta: verbose_name = _('City') verbose_name_plural = _("Cities")
class Partner(DeletableModel): name = models.CharField(max_length=30, null=True, blank=True, verbose_name=_("Name")) url = models.URLField(null=True, blank=True, verbose_name=_("URL")) class Meta: verbose_name = _('Partner') verbose_name_plural = _('Partners') def __str__(self): return f'{self.name}'
def render_as_printable(self) -> list: columns = (_('Product'), _('Price'), _('Quantity'), _('Total')) data = [columns] for line in self.get_lines: line_data = [ line.product.name, line.product.price, line.quantity, line.total ] data.append(line_data) bottom_row = [" ", " ", " ", self.total_sum] data.append(bottom_row) return data
class LoginForm(forms.Form): username = forms.CharField( widget=forms.TextInput( attrs={ 'placeholder': str(_("Username")) + "/" + str(_("Phone")) + "/" + str(_("Email")) } ) ) password = forms.CharField( widget=forms.PasswordInput( attrs={ 'placeholder': _("Password") } ) )
class CartLine(BaseModel): product = models.ForeignKey('Product', related_name='cart_lines', on_delete=do_nothing) cart = models.ForeignKey('Cart', related_name='lines', on_delete=do_nothing) quantity = models.DecimalField(max_digits=10, decimal_places=2, verbose_name=_('Quantity')) def _total_sum(self): return self.product.price * self.quantity @property def total_sum(self): return self._total_sum().quantize(decimal.Decimal("0.01")) @property def total(self): return self.total_sum def to_order_line(self, order): return OrderLine.objects.create(product=self.product, quantity=self.quantity, order=order) class Meta: verbose_name = _('Cart Line') verbose_name_plural = _('Cart Lines')
class CreateOrderForm(forms.ModelForm): number = forms.IntegerField(widget=forms.NumberInput( attrs={ 'placeholder': _('Number'), 'readonly': True })) assigned_to = forms.ModelChoiceField( queryset=User.objects.filter(user_type='CA'), required=False) def __init__(self, is_caller=False, *args, **kwargs): super(CreateOrderForm, self).__init__(*args, **kwargs) if is_caller: self.status_choices = ( ('P', _('Pending')), ('RC', _('RECALL')), ('CO', _('Confirmed')), ('CA', _('Canceled')), ) self.fields['status'] = forms.ChoiceField( choices=self.status_choices) class Meta: global status_choices model = Order fields = [ 'profile', 'number', 'status', 'shipping_fee', 'free_delivery', 'note', 'delivery_date' ]
class OrderStatusChange(BaseModel): order = models.ForeignKey('Order', on_delete=do_nothing, related_name='status_changes', verbose_name=_('Order')) previous_status = models.CharField(max_length=2, choices=Order.status_choices, verbose_name=_('Previous Status')) new_status = models.CharField(max_length=2, choices=Order.status_choices, verbose_name=_('New Status')) user = models.ForeignKey( 'accounts.User', on_delete=do_nothing, related_name='status_changes', )
class User(AbstractUser): USER_TYPES = (('C', _('Client')), ('S', _('Staff')), ('A', _('Admin')), ('CA', _('Caller'))) notification_token = models.CharField(max_length=255, unique=True, blank=True, null=True) phones = ArrayField(base_field=models.CharField( _("Phone Number"), max_length=50, validators=[phone_validator], unique=True, )) is_active = models.BooleanField( _('Active'), default=False, help_text=_( 'Designates whether this user should be treated as active. ' 'Unselect this instead of deleting accounts.' ), ) user_type = models.CharField( _("Type"), max_length=2, choices=USER_TYPES, help_text=_("The user's type can be one of the available choices, " "Client, Staff or Admin."), ) visible = models.BooleanField(default=True) USERNAME_FIELD = "username" REQUIRED_FIELDS = ["first_name", "last_name", 'user_type', 'phones', 'email'] @property def full_name(self): return super().get_full_name() @property def confirmed_phone(self) -> bool: return False @property def confirmed_email(self) -> bool: return False def delete(self, using=None, keep_parents=False): self.visible = False self.is_active = False self.profile.visible = False self.save() def __str__(self): return self.full_name
class OtpForm(forms.Form): code = forms.CharField( widget=forms.TextInput( attrs={ 'placeholder': _('Code') } ) )
class CreateUser(BSModalCreateView): model = User context_object_name = 'user' success_url = reverse_lazy("accounts:users-list") template_name = "dashboard/create_user.html" success_message = _('User Created Success') form_class = CreateStaffForm initial = {'user_type': 'S'}
class Profile(DeletableModel): GENDERS = (('M', 'Male'), ('F', 'Female')) user = models.OneToOneField('User', on_delete=do_nothing, related_name='profile') photo = models.ImageField( _('Profile Picture'), upload_to='profile/', help_text=_( "the user's profile picture." ), blank=True, null=True ) address = models.CharField(_("Address"), max_length=255, null=True) city = models.ForeignKey('City', on_delete=do_nothing, null=True, blank=True, related_name='profiles', verbose_name=_('City')) birth_date = models.DateField(_('Birth Date'), blank=True, null=True) gender = models.CharField(choices=GENDERS, max_length=1, default='M', verbose_name=_('Gender'), null=True) @property def get_age(self) -> int: if not self.birth_date: return 0 today = date.today() dob = self.birth_date before_dob = (today.month, today.day) < (dob.month, dob.day) return today.year - self.birth_date.year - before_dob @property def get_photo(self): try: return self.photo.url except ValueError: return None @property def orders_count(self): return self.orders.filter(visible=True).count() or 0 def __str__(self): return self.user.full_name class Meta: verbose_name = _('Profile') verbose_name_plural = _('Profiles')
class SeasonalDiscount(DeletableModel): name = models.CharField(max_length=50, unique=True, verbose_name=_('Name')) name_ar = models.CharField(max_length=50, unique=True, verbose_name=_('Arabic Name')) name_en = models.CharField(max_length=50, unique=True, verbose_name=_('English Name')) period = DateRangeField(verbose_name=_('Period')) global_discount = models.DecimalField(max_digits=5, decimal_places=2, null=True, verbose_name=_('Discount')) products = models.ManyToManyField('Product', through='ProductOnSeasonalDiscount') class Meta: verbose_name = _('Seasonal Discount') verbose_name_plural = _('Seasonal Discounts')
class Category(DeletableModel): name = models.CharField(max_length=50, unique=True, verbose_name=_('Name')) name_ar = models.CharField(max_length=50, unique=True, verbose_name=_('Arabic Name'), null=True, blank=True) name_en = models.CharField(max_length=50, unique=True, verbose_name=_('English Name'), null=True, blank=True) objects = CustomCategoryManager() def __str__(self): return self.name class Meta: verbose_name = _('Category') verbose_name_plural = _('Categories')
class Deliveries(DeletableModel): order = models.ForeignKey('Order', on_delete=cascade, verbose_name=_('Order'), related_name="deliveries") delivery_guys = models.ForeignKey('DeliveryGuy', on_delete=cascade, verbose_name=_('Delivery Guy'), related_name="deliveries") delivery_date = models.DateField(_("Delivery Date"), null=True, blank=True) @property def fee(self) -> int: return 0 def __str__(self) -> str: return f'{self.delivery_guys.name} is delivering {self.order.number}' class Meta: verbose_name = _('Delivery') verbose_name_plural = _('Deliveries')
class DeliveryCompany(DeletableModel): company_name = models.CharField(unique=True, verbose_name=_('Company Name'), max_length=255) weight_threshold = models.PositiveIntegerField( verbose_name=_('Weight Threshold'), default=0, blank=True) base_fee = models.PositiveIntegerField(verbose_name=_('Base Fee'), default=0, blank=True) default = models.BooleanField(default=False, verbose_name=_('Default')) @property def delivery_guys_count(self) -> int: return self.delivery_guys.count() def __str__(self): return self.company_name class Meta: verbose_name = _('Delivery Company') verbose_name_plural = _('Delivery Companies')
class ProfileForm(forms.ModelForm): user = forms.ModelChoiceField(User.objects.all(), empty_label=_('Choose a user')) photo = forms.ImageField(allow_empty_file=True) address = forms.CharField( widget=forms.TextInput( attrs={ 'placeholder': _('Address') } ) ) city = forms.ModelChoiceField(City.objects.all(), empty_label=_('Select a city'), required=False) birth_date = forms.DateField( widget=forms.DateInput( attrs={ 'placeholder': _('Birth Date') } ) ) class Meta: model = Profile fields = ['user', 'photo', 'address', 'city', 'birth_date', 'gender']
class SubCategory(DeletableModel): name = models.CharField(max_length=50, verbose_name=_('Name')) name_ar = models.CharField(max_length=50, verbose_name=_('Arabic Name'), null=True, blank=True) name_en = models.CharField(max_length=50, verbose_name=_('English Name'), null=True, blank=True) category = models.ForeignKey('Category', related_name='sub_categories', verbose_name=_('Category'), on_delete=do_nothing) def __str__(self): return self.name class Meta: unique_together = (('name', 'category'), ) verbose_name = _('Sub-Category') verbose_name_plural = _('Sub-Categories')
class DeliveryGuy(DeletableModel): name = models.CharField(unique=True, max_length=50, verbose_name=_('Name')) company = models.ForeignKey('DeliveryCompany', on_delete=cascade, null=True, blank=True, related_name="delivery_guys") def __str__(self): return "{} {}".format(self.name, self.company) class Meta: verbose_name = _('Delivery Guy') verbose_name_plural = _('Delivery Guys')
class ProductOnSeasonalDiscount(DeletableModel): product = models.ForeignKey('Product', related_name='seasonal_discounts', on_delete=do_nothing) seasonal_discount = models.ForeignKey('SeasonalDiscount', on_delete=do_nothing) discount = models.DecimalField(max_digits=5, decimal_places=2, null=True, verbose_name=_('Discount')) class Meta: verbose_name = _('Product On Seasonal Discount') verbose_name_plural = _('Products On Seasonal Discount')
class OrderFilter(forms.Form): FROM_STATUS_CHOICES = Order.status_choices order = forms.ModelChoiceField(queryset=Order.objects.all(), required=False, empty_label=_('Numero')) user = forms.ModelChoiceField(queryset=User.objects.filter(user_type='C'), required=False, empty_label=_('Client')) delivery_man = forms.ModelChoiceField(queryset=DeliveryGuy.objects.all(), required=False, empty_label=_('Delivery Man')) caller = forms.ModelChoiceField( queryset=User.objects.exclude(user_type='C'), required=False, empty_label=_('Caller')) start_date = forms.DateField(required=False, input_formats=['%d/%m/%Y'], widget=BootstrapDatePickerInput()) end_date = forms.DateField(required=False, input_formats=['%d/%m/%Y'], widget=BootstrapDatePickerInput()) status = forms.MultipleChoiceField(choices=FROM_STATUS_CHOICES, required=False)
class State(BaseModel): name = models.CharField(max_length=255, verbose_name=_('Name')) name_ar = models.CharField(max_length=255, verbose_name=_('Arabic Name')) name_fr = models.CharField(max_length=255, verbose_name=_('English Name')) matricule = models.IntegerField(verbose_name=_('Matricule')) code_postal = models.IntegerField(verbose_name=_('Postal Code')) region = models.ForeignKey('Region', verbose_name=_('Region'), on_delete=do_nothing, null=True, blank=True) def __str__(self): return self.name class Meta: verbose_name = _('State') verbose_name_plural = _("States")
class CheckoutForm(forms.Form): first_name = forms.CharField(required=False) last_name = forms.CharField(required=False) phone_number = forms.CharField(required=False) email_address = forms.EmailField(required=False) city = forms.ModelChoiceField(queryset=City.objects.all(), required=False) address = forms.CharField(widget=forms.Textarea(), required=False) note = forms.CharField( widget=forms.Textarea(attrs={"placeholder": _("Note")}), required=False) def save(self, user: User): cd = self.cleaned_data user.first_name = cd.get('first_name', user.first_name) user.last_name = cd.get('last_name', user.last_name) user.phones.append(cd.get('phone_number')) user.profile.city = cd.get('city', user.profile.city) user.profile.address = cd.get('address', user.profile.address) user.profile.save() user.save()
class Settings(BaseModel): standard_delivery_fee = models.PositiveIntegerField( verbose_name=_('Standard Delivery Fee'), help_text=_('Delivery feed for Alger, Boumerdes and Blida'), default=500)
class Complaint(DeletableModel): COMPLAINTS = ( ('DP', _('Delivery Problem')), ('PP', _('Product Problem')), ('SP', _('Service Problem')), ('O', _('Other')), ) client = models.ForeignKey('accounts.User', related_name="complaints", verbose_name=_('Client'), on_delete=do_nothing) complaint = models.CharField(choices=COMPLAINTS, max_length=2, verbose_name=_("Complaint")) against = models.ForeignKey('DeliveryGuy', related_name="complaints", verbose_name=_('Against'), on_delete=do_nothing, null=True, blank=True) comment = models.TextField(verbose_name=_('Comment'), max_length=500, null=True, blank=True) treated = models.BooleanField(default=False, verbose_name=_('Treated'), blank=True) order = models.ForeignKey('Order', related_name=_('complaints'), verbose_name=_('Order'), on_delete=do_nothing, null=True, blank=True)