Пример #1
0
    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)
Пример #2
0
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}'
Пример #3
0
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')
Пример #4
0
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
Пример #5
0
 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)
Пример #6
0
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")
Пример #7
0
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")
Пример #8
0
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}'
Пример #9
0
    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
Пример #10
0
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")
            }
        )
    )
Пример #11
0
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')
Пример #12
0
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'
        ]
Пример #13
0
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',
    )
Пример #14
0
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
Пример #15
0
class OtpForm(forms.Form):
    code = forms.CharField(
        widget=forms.TextInput(
            attrs={
                'placeholder': _('Code')
            }
        )
    )
Пример #16
0
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'}
Пример #17
0
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')
Пример #18
0
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')
Пример #19
0
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')
Пример #20
0
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')
Пример #21
0
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')
Пример #22
0
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']
Пример #23
0
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')
Пример #24
0
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')
Пример #25
0
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')
Пример #26
0
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)
Пример #27
0
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")
Пример #28
0
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()
Пример #29
0
class Settings(BaseModel):
    standard_delivery_fee = models.PositiveIntegerField(
        verbose_name=_('Standard Delivery Fee'),
        help_text=_('Delivery feed for Alger, Boumerdes and Blida'),
        default=500)
Пример #30
0
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)