main
Lowlights 2024-02-19 11:43:38 +06:00
parent 7878c16e19
commit 22e474971f
145 changed files with 3611 additions and 0 deletions

3
.env Normal file
View File

@ -0,0 +1,3 @@
TWILIO_ACCOUNT_SID='ACf013a59a14734432fd12dd9b12aaf8b4'
TWILIO_AUTH_TOKEN='c680a1e5bee0a19e4e83c32fcb24e983'
TWILIO_WHATSAPP_NUMBER='whatsapp:+77053360730'

8
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

30
.idea/djangoProject1.iml Normal file
View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="FacetManager">
<facet type="django" name="Django">
<configuration>
<option name="rootFolder" value="$MODULE_DIR$" />
<option name="settingsModule" value="djangoProject1/settings.py" />
<option name="manageScript" value="$MODULE_DIR$/manage.py" />
<option name="environment" value="&lt;map/&gt;" />
<option name="doNotUseTestRunner" value="false" />
<option name="trackFilePattern" value="migrations" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/venv" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="TemplatesService">
<option name="TEMPLATE_CONFIGURATION" value="Django" />
<option name="TEMPLATE_FOLDERS">
<list>
<option value="$USER_HOME$/djangoProject1\templates" />
</list>
</option>
</component>
</module>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

7
.idea/misc.xml Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.11 (djangoProject1) (2)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11 (djangoProject1) (2)" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/djangoProject1.iml" filepath="$PROJECT_DIR$/.idea/djangoProject1.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

0
cart/__init__.py Normal file
View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

3
cart/admin.py Normal file
View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

6
cart/apps.py Normal file
View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class CartConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'cart'

73
cart/cart.py Normal file
View File

@ -0,0 +1,73 @@
from decimal import Decimal
from django.conf import settings
from main.models import Product
class Cart:
def __init__(self, request):
"""
Initialize the cart.
"""
self.session = request.session
cart = self.session.get(settings.CART_SESSION_ID)
if not cart:
# save an empty cart in the session
cart = self.session[settings.CART_SESSION_ID] = {}
self.cart = cart
def __iter__(self):
"""
Iterate over the items in the cart and get the products
from the database.
"""
product_ids = self.cart.keys()
# get the product objects and add them to the cart
products = Product.objects.filter(id__in=product_ids)
cart = self.cart.copy()
for product in products:
cart[str(product.id)]['product'] = product
for item in cart.values():
item['price'] = Decimal(item['price'])
item['total_price'] = item['price'] * item['quantity']
yield item
def __len__(self):
"""
Count all items in the cart.
"""
return sum(item['quantity'] for item in self.cart.values())
def add(self, product, quantity=1, override_quantity=False):
"""
Add a product to the cart or update its quantity.
"""
product_id = str(product.id)
if product_id not in self.cart:
self.cart[product_id] = {'quantity': 0,
'price': str(product.price)}
if override_quantity:
self.cart[product_id]['quantity'] = quantity
else:
self.cart[product_id]['quantity'] += quantity
self.save()
def save(self):
# mark the session as "modified" to make sure it gets saved
self.session.modified = True
def remove(self, product):
"""
Remove a product from the cart.
"""
product_id = str(product.id)
if product_id in self.cart:
del self.cart[product_id]
self.save()
def clear(self):
# remove cart from session
del self.session[settings.CART_SESSION_ID]
self.save()
def get_total_price(self):
return sum(Decimal(item['price']) * item['quantity'] for item in self.cart.values())

View File

@ -0,0 +1,3 @@
from .cart import Cart
def cart(request):
return {'cart': Cart(request)}

9
cart/forms.py Normal file
View File

@ -0,0 +1,9 @@
from django import forms
PRODUCT_QUANTITY_CHOICES = [(i, str(i)) for i in range(1, 21)]
class CartAddProductForm(forms.Form):
quantity = forms.TypedChoiceField(
choices=PRODUCT_QUANTITY_CHOICES,
coerce=int)
override = forms.BooleanField(required=False,
initial=False,
widget=forms.HiddenInput)

View File

Binary file not shown.

3
cart/models.py Normal file
View File

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

View File

@ -0,0 +1,80 @@
body, html {
height: 100%;
margin: 0;
font-family: 'Papyrus', fantasy;
background: url('path_to_your_cosmic_background.jpg') no-repeat center center fixed;
background-size: cover;
}
.checkout-container {
background-color: rgba(0, 0, 0, 0.5);
color: #E0FFFF; /* Цвет текста, напоминающий свет луны */
border-radius: 15px;
padding: 30px;
box-shadow: 0 0 15px 5px rgba(0, 255, 255, 0.2);
backdrop-filter: blur(10px);
}
.checkout-title {
font-size: 28px;
color: #FFD700;
text-align: center;
text-shadow: 0 0 15px rgba(255, 215, 0, 0.7);
}
.order-list li {
background-color: rgba(105, 105, 105, 0.1);
padding: 10px;
border-radius: 5px;
margin-bottom: 10px;
border-left: 5px solid #FFD700; /* Золотая линия для элементов списка */
box-shadow: inset 0 0 10px rgba(255, 255, 255, 0.3);
}
.item-price {
font-weight: bold;
}
.total-price {
font-size: 20px;
text-align: right;
border-top: 1px dashed #FFD700;
padding-top: 10px;
}
.place-order-btn {
background-color: transparent;
border: 2px solid #FFD700;
color: #FFD700;
font-size: 16px;
padding: 10px 30px;
display: block;
margin: 20px auto 0;
transition: all 0.3s ease-in-out;
}
.place-order-btn:hover {
background-color: #FFD700;
color: #000;
box-shadow: 0 0 20px #FFD700;
}
/* Добавьте анимации и трансформации для интерактивных элементов */
@keyframes pulse {
0% {
transform: scale(1);
box-shadow: 0 0 0 0 rgba(255, 215, 0, 0.7);
}
70% {
transform: scale(1.05);
box-shadow: 0 0 10px 10px rgba(255, 215, 0, 0);
}
100% {
transform: scale(1);
box-shadow: 0 0 0 0 rgba(255, 215, 0, 0);
}
}
.place-order-btn:focus:not(:hover) {
animation: pulse 2s infinite;
}

View File

@ -0,0 +1,65 @@
{% extends "main/base.html" %}
{% load static %}
{% block title %}Your shopping cart{% endblock %}
{% block content %}
<link rel="stylesheet" href="{% static "/deps/css/cart.css" %}">
<div class="cart-container">
<h1>Корзина</h1>
<table class="cart-table">
<thead>
<tr>
<th>Изображение</th>
<th>Продукт</th>
<th>Количество</th>
<th>Удалить</th>
<th>Цена за единицу</th>
<th>Общая цена</th>
</tr>
</thead>
<tbody>
{% for item in cart %}
{% with product=item.product %}
<tr>
<td>
<a href="{{ product.get_absolute_url }}">
<img src="{% if product.image %}{{ product.image.url }}{% else %}{% static 'img/no_image.jpg' %}{% endif %}" alt="{{ product.name }}">
</a>
</td>
<td>{{ product.name }}</td>
<td>
<form action="{% url 'cart:cart_add' product.id %}" method="post">
{% csrf_token %}
{{ item.update_quantity_form.quantity }}
{{ item.update_quantity_form.override }}
<input type="submit" value="Update" class="btn-update">
</form>
</td>
<td>
<form action="{% url 'cart:cart_remove' product.id %}" method="post">
{% csrf_token %}
<input type="submit" value="Remove" class="btn-remove">
</form>
</td>
<td class="num">₸{{ item.price }}</td>
<td class="num">₸{{ item.total_price }}</td>
</tr>
{% endwith %}
{% endfor %}
<tr class="total">
<td>Итого</td>
<td colspan="4"></td>
<td class="num">₸{{ cart.get_total_price }}</td>
</tr>
</tbody>
</table>
<div class="cart-action-buttons">
<a href="{% url 'main:product_list' %}" class="button light">Продолжить покупки</a>
<!-- Обновите 'your_checkout_url' на реальный URL оформления заказа -->
<a href="{% url "orders:order_create"%}" class="button checkout">Оформить заказ</a>
</div>
</div>
{% endblock %}

3
cart/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

10
cart/urls.py Normal file
View File

@ -0,0 +1,10 @@
from django.urls import path
from . import views
app_name = 'cart'
urlpatterns = [
path('', views.cart_detail, name='cart_detail'),
path('add/<int:product_id>/', views.cart_add, name='cart_add'),
path('remove/<int:product_id>/', views.cart_remove,
name='cart_remove'),
]

32
cart/views.py Normal file
View File

@ -0,0 +1,32 @@
from django.shortcuts import render, redirect, get_object_or_404
from django.views.decorators.http import require_POST
from main.models import Product
from .cart import Cart
from .forms import CartAddProductForm
@require_POST
def cart_add(request, product_id):
cart = Cart(request)
product = get_object_or_404(Product, id=product_id)
form = CartAddProductForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
cart.add(product=product,quantity=cd['quantity'],
override_quantity=cd['override'])
return redirect('cart:cart_detail')
@require_POST
def cart_remove(request, product_id):
cart = Cart(request)
product = get_object_or_404(Product, id=product_id)
cart.remove(product)
return redirect('cart:cart_detail')
def cart_detail(request):
cart = Cart(request)
for item in cart:
item['update_quantity_form'] = CartAddProductForm(initial={
'quantity': item['quantity'],
'override': True})
return render(request, 'cart/detail.html', {'cart': cart})

BIN
db.sqlite3 Normal file

Binary file not shown.

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

16
djangoProject1/asgi.py Normal file
View File

@ -0,0 +1,16 @@
"""
ASGI config for djangoProject1 project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/
"""
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoProject1.settings')
application = get_asgi_application()

145
djangoProject1/settings.py Normal file
View File

@ -0,0 +1,145 @@
"""
Django settings for djangoProject1 project.
Generated by 'django-admin startproject' using Django 5.0.2.
For more information on this file, see
https://docs.djangoproject.com/en/5.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.0/ref/settings/
"""
import os
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-)p-ed99i+^)@_t33f65!y8eqn23!&kt)zc(ht$8h7e8#1k(o$f'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
CART_SESSION_ID = 'cart'
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'main.apps.MainConfig',
'cart.apps.CartConfig',
'orders.apps.OrdersConfig',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'djangoProject1.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates']
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'djangoProject1.wsgi.application'
# Database
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Password validation
# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/5.0/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.0/howto/static-files/
STATIC_URL = 'static/'
# Default primary key field type
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# В settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
import environ
env =environ.Env()
environ.Env.read_env(env_file="C:/Users/fhjj3/djangoProject1/.env")
environ.Env.read_env(env_file=str(BASE_DIR / '.env'))
TWILIO_ACCOUNT_SID = env('TWILIO_ACCOUNT_SID')
TWILIO_AUTH_TOKEN = env('TWILIO_AUTH_TOKEN')
TWILIO_WHATSAPP_NUMBER = env('TWILIO_WHATSAPP_NUMBER')
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' # Используйте SMTP бэкенд для отправки писем
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'fhjj3590@gmail.com'
EMAIL_HOST_PASSWORD = 'uzmd nmit yxwc sgox' # Предполагается, что это сгенерированный пароль для приложений
EMAIL_PORT = 587
EMAIL_USE_TLS = True

32
djangoProject1/urls.py Normal file
View File

@ -0,0 +1,32 @@
"""
URL configuration for Harmony project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/5.0/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path,include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('cart/', include('cart.urls', namespace='cart')),
path('orders/', include('orders.urls', namespace='orders')),
path('', include('main.urls', namespace='main')),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)

16
djangoProject1/wsgi.py Normal file
View File

@ -0,0 +1,16 @@
"""
WSGI config for djangoProject1 project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoProject1.settings')
application = get_wsgi_application()

68
invoice_1.pdf Normal file
View File

@ -0,0 +1,68 @@
%PDF-1.3
%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com
1 0 obj
<<
/F1 2 0 R
>>
endobj
2 0 obj
<<
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
>>
endobj
3 0 obj
<<
/Contents 7 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 6 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
4 0 obj
<<
/PageMode /UseNone /Pages 6 0 R /Type /Catalog
>>
endobj
5 0 obj
<<
/Author (anonymous) /CreationDate (D:20240218225917-06'00') /Creator (ReportLab PDF Library - www.reportlab.com) /Keywords () /ModDate (D:20240218225917-06'00') /Producer (ReportLab PDF Library - www.reportlab.com)
/Subject (unspecified) /Title (untitled) /Trapped /False
>>
endobj
6 0 obj
<<
/Count 1 /Kids [ 3 0 R ] /Type /Pages
>>
endobj
7 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 102
>>
stream
GapQh0E=F,0U\H3T\pNYT^QKk?tc>IP,;W#U1^23ihPEM_?CW4KISi90MntRifICK%KE/ee05&l(FoYV9neZ[Kb,ht@Ke@a%%S##~>endstream
endobj
xref
0 8
0000000000 65535 f
0000000073 00000 n
0000000104 00000 n
0000000211 00000 n
0000000414 00000 n
0000000482 00000 n
0000000778 00000 n
0000000837 00000 n
trailer
<<
/ID
[<dfa685a70af9cd44f8a81cfb0b67bc98><dfa685a70af9cd44f8a81cfb0b67bc98>]
% ReportLab generated PDF document -- digest (http://www.reportlab.com)
/Info 5 0 R
/Root 4 0 R
/Size 8
>>
startxref
1029
%%EOF

68
invoice_2.pdf Normal file
View File

@ -0,0 +1,68 @@
%PDF-1.3
%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com
1 0 obj
<<
/F1 2 0 R
>>
endobj
2 0 obj
<<
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
>>
endobj
3 0 obj
<<
/Contents 7 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 6 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
4 0 obj
<<
/PageMode /UseNone /Pages 6 0 R /Type /Catalog
>>
endobj
5 0 obj
<<
/Author (anonymous) /CreationDate (D:20240218230410-06'00') /Creator (ReportLab PDF Library - www.reportlab.com) /Keywords () /ModDate (D:20240218230410-06'00') /Producer (ReportLab PDF Library - www.reportlab.com)
/Subject (unspecified) /Title (untitled) /Trapped /False
>>
endobj
6 0 obj
<<
/Count 1 /Kids [ 3 0 R ] /Type /Pages
>>
endobj
7 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 102
>>
stream
GapQh0E=F,0U\H3T\pNYT^QKk?tc>IP,;W#U1^23ihPEM_?CW4KISi90MntRifICK%KE/ee05&l(FoY69neZ[Kb,ht@Ke@a%'("2~>endstream
endobj
xref
0 8
0000000000 65535 f
0000000073 00000 n
0000000104 00000 n
0000000211 00000 n
0000000414 00000 n
0000000482 00000 n
0000000778 00000 n
0000000837 00000 n
trailer
<<
/ID
[<ec49df0e43ea243c0ea148f44a3a082b><ec49df0e43ea243c0ea148f44a3a082b>]
% ReportLab generated PDF document -- digest (http://www.reportlab.com)
/Info 5 0 R
/Root 4 0 R
/Size 8
>>
startxref
1029
%%EOF

68
invoice_3.pdf Normal file
View File

@ -0,0 +1,68 @@
%PDF-1.3
%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com
1 0 obj
<<
/F1 2 0 R
>>
endobj
2 0 obj
<<
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
>>
endobj
3 0 obj
<<
/Contents 7 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 6 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
4 0 obj
<<
/PageMode /UseNone /Pages 6 0 R /Type /Catalog
>>
endobj
5 0 obj
<<
/Author (anonymous) /CreationDate (D:20240218230455-06'00') /Creator (ReportLab PDF Library - www.reportlab.com) /Keywords () /ModDate (D:20240218230455-06'00') /Producer (ReportLab PDF Library - www.reportlab.com)
/Subject (unspecified) /Title (untitled) /Trapped /False
>>
endobj
6 0 obj
<<
/Count 1 /Kids [ 3 0 R ] /Type /Pages
>>
endobj
7 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 102
>>
stream
GapQh0E=F,0U\H3T\pNYT^QKk?tc>IP,;W#U1^23ihPEM_?CW4KISi90MntRifICK%KE/ee05&l(FoZ!9neZ[Kb,ht@Ke@a%(R!A~>endstream
endobj
xref
0 8
0000000000 65535 f
0000000073 00000 n
0000000104 00000 n
0000000211 00000 n
0000000414 00000 n
0000000482 00000 n
0000000778 00000 n
0000000837 00000 n
trailer
<<
/ID
[<58e49d6780c80c154396c8a9030fddee><58e49d6780c80c154396c8a9030fddee>]
% ReportLab generated PDF document -- digest (http://www.reportlab.com)
/Info 5 0 R
/Root 4 0 R
/Size 8
>>
startxref
1029
%%EOF

BIN
invoice_image.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

0
main/__init__.py Normal file
View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

17
main/admin.py Normal file
View File

@ -0,0 +1,17 @@
from django.contrib import admin
from .models import Category,Product
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
list_display = ['name','slug']
prepopulated_fields = {'slug':('name',)}
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
list_display = ['name','slug','price','available','created','updated']
list_filter = ['available','created','updated']
list_editable = ['price','available']
prepopulated_fields = {'slug':('name',)}

6
main/apps.py Normal file
View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class MainConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'main'

View File

@ -0,0 +1,47 @@
# Generated by Django 5.0.2 on 2024-02-18 16:21
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Category',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=200)),
('slug', models.SlugField(max_length=200, unique=True)),
],
options={
'verbose_name': 'category',
'verbose_name_plural': 'categories',
'ordering': ['name'],
'indexes': [models.Index(fields=['name'], name='main_catego_name_5111b9_idx')],
},
),
migrations.CreateModel(
name='Product',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=200)),
('slug', models.SlugField(max_length=200)),
('image', models.ImageField(blank=True, upload_to='products/%Y/%m/%d')),
('description', models.TextField(blank=True)),
('price', models.DecimalField(decimal_places=2, max_digits=10)),
('available', models.BooleanField(default=True)),
('created', models.DateTimeField(auto_now_add=True)),
('updated', models.DateTimeField(auto_now=True)),
('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='products', to='main.category')),
],
options={
'ordering': ['name'],
},
),
]

View File

Binary file not shown.

51
main/models.py Normal file
View File

@ -0,0 +1,51 @@
from django.db import models
from django.urls import reverse
class Category(models.Model):
name = models.CharField(max_length=200)
slug = models.SlugField(max_length=200,unique=True)
class Meta:
ordering = ['name']
indexes = [
models.Index(fields=['name']),
]
verbose_name = 'category'
verbose_name_plural = 'categories'
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('main:product_list_by_category',args=[self.slug])
class Product(models.Model):
category = models.ForeignKey(Category,
related_name='products',
on_delete=models.CASCADE)
name = models.CharField(max_length=200)
slug = models.SlugField(max_length=200)
image = models.ImageField(upload_to='products/%Y/%m/%d',
blank=True)
description = models.TextField(blank=True)
price = models.DecimalField(max_digits=10,
decimal_places=2)
available = models.BooleanField(default=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['name']
indexes = [
models.Index(fields=['id', 'slug']),
models.Index(fields=['name']),
models.Index(fields=['-created']),
]
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('main:product_detail',args=[self.id,self.slug])

View File

@ -0,0 +1,47 @@
/* Стили для страницы about */
body {
background-image: url("../images/walp.png");
background-repeat: no-repeat;
background-attachment: fixed;
background-position: center center;
background-size: cover;
height: 100%;
margin: 0;
padding: 0;
font-family: 'Arial', sans-serif;
}
.about-container {
background-color: rgba(107, 91, 149, 0.8);
color: #ffffff;
padding: 20px;
border-radius: 10px;
box-shadow: 5px 5px 25px 19px #380069;
margin: 50px auto;
max-width: 600px;
}
h2 {
color: #ffa07a;
}
p {
font-size: 16px;
line-height: 1.6;
}
a.telegram-button {
display: inline-block;
background-color: #4CAF50; /* Зеленый цвет */
color: #ffffff;
padding: 15px 30px;
text-decoration: none;
border-radius: 8px;
margin-top: 20px;
transition: background-color 0.3s;
font-size: 18px;
}
a.telegram-button:hover {
background-color: #45a049; /* Темно-зеленый цвет при наведении */
}

View File

@ -0,0 +1,330 @@
@import url(//fonts.googleapis.com/css?family=Ubuntu);
body {
margin:0;
padding:0;
font-family:helvetica, sans-serif;
}
h1, h2, h3, h4, h5 , h6 {
font-family: 'Ubuntu', sans-serif; font-weight:normal;
}
a {
text-decoration:none;
color:#5993bb;
}
a:hover {
color:#77b6e2;
}
a.button, input[type="submit"] {
color:#fff;
background:#5993bb;
border-radius:4px;
padding:10px 20px;
font-size:14px;
border:0;
}
a.button.light {
color:#666;
background:#ededed;
}
.text-left {
text-align:left;
}
.text-right {
text-align:right;
}
table {
width:100%;
border-spacing:0;
border-collapse: collapse;
}
table th, table td {
text-align:left;
font-size:14px;
padding:10px;
margin:0;
}
tbody tr:nth-child(odd) {
background:#efefef;
}
tbody tr.subtotal {
background:#ccc;
}
thead th, tbody tr.total {
background:#5993bb;
color:#fff;
font-weight:bold;
}
table.cart {
margin-bottom:40px;
}
table.cart img {
width:180px;
}
tbody td.num {
text-align:right;
}
td input[type="submit"] {
font-size:12px;
padding:4px 10px;
}
form p label, form p input {
float:left;
clear:both;
}
form p label {
font-size:14px;
padding-bottom:4px;
}
form p input {
width:300px;
font-size:13px;
margin-bottom:10px;
padding:10px 12px;
border:0;
background:#efefef;
color:#666;
border-radius:4px;
}
ul.errorlist {
float:left;
color:#ff0000;
clear:both;
font-size:13px;
margin:0 0 0 10px;
padding:10px 0;
}
#header {
padding:10px 100px;
font-size:18px;
overflow:auto;
}
#subheader {
background:#ececec;
color:#444;
padding:15px 100px;
overflow:auto;
}
#header .logo {
font-family: 'Ubuntu', sans-serif;
float:left;
color:#333;
font-size:22px;
margin-right:10%;
}
#subheader .cart {
float:right;
padding-top:4px;
}
#content {
padding:0 100px;
overflow:hidden;
}
#sidebar {
width:220px;
padding:30px 20px 0 0;
float:left;
}
#sidebar ul{
margin:0;
padding:0;
}
#sidebar ul li {
margin:0;
list-style:none;
padding:10px 14px;
}
#sidebar ul li a {
display:block;
}
#sidebar ul li.selected {
background:#5993bb;
border-radius:4px;
}
#sidebar ul li.selected a {
color:#fff;
}
#main {
float:left;
width: 96%;
margin-right:-220px;
overflow:hidden;
}
.product-list .item {
width:25%;
padding:10px 20px 10px 0;
float:left;
text-align:center;
line-height:1.2;
}
.product-list .item img {
width:100%;
margin-bottom:8px;
}
.product-detail {
text-align:justify;
}
.product-detail .price {
color:#333;
font-size:28px;
font-weight:bold;
}
.product-detail img {
width:40%;
float:left;
padding:0 20px 20px 0;
}
.product-detail h1 {
margin-bottom:0;
}
.product-detail h2 {
margin-top:10px;
}
.order-form {
float:left;
}
.order-info {
float:right;
width:300px;
background:#efefef;
padding:10px 20px;
color:#333;
border-bottom:4px solid #5993bb;
}
.order-info h3 {
color:#5993bb;
}
.order-info ul li {
margin:0;
padding:0;
font-size:14px;
}
.order-info p {
font-weight:bold;
float:right;
}
.order-info span {
float:right;
}
.neg {
color:#dc1616;
}
.languages {
float:right;
padding-top:4px;
font-size:14px;
}
.languages ul {
list-style:none;
margin:0;
padding:0;
float:left;
}
.languages ul li {
float:left;
margin:0 0 0 10px;
font-size:14px;
}
.languages p {
float:left;
margin:0;
}
.recommendations {
clear:both;
}
.recommendations div {
float:left;
}
.recommendations img {
width:200px
}
.recommendations p {
clear:both;
}
.recommendations.cart {
width:60%;
float:left;
overflow:auto;
}
.recommendations.cart h3 {
margin-top:0;
}
.recommendations.cart .item {
margin-right:10px;
}
.recommendations.cart img {
width:120px;
}
/* braintree hosted fields */
form div.field {
font-size:13px;
color:#666;
width:300px;
height:22px;
margin-bottom:10px;
padding:6px 12px;
border:0;
background:#efefef;
color:#666;
border-radius:4px;
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,120 @@
/* Основные стили страницы корзины с улучшенной видимостью картинок */
.cart-page {
background: linear-gradient(135deg, #483D8B 0%, #6A5ACD 100%); /* Эзотерический градиент фона */
color: #FFFFFF;
padding: 20px;
border-radius: 12px;
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.6);
margin-top: 30px;
overflow: hidden; /* Убедимся, что все внутри округлённых границ */
}
/* Улучшенная стилизация таблицы */
.cart-table {
width: 100%;
border-collapse: separate;
border-spacing: 0 15px; /* Добавим пространство между строками */
margin-bottom: 1rem;
}
.cart-table th, .cart-table td {
padding: 15px;
border-bottom: 2px solid #7B68EE;
text-align: left;
color: #FFFFFF;
}
.cart-table th {
font-size: 1.1rem;
letter-spacing: 1px;
background-color: rgba(255, 255, 255, 0.2); /* Слегка прозрачный фон для заголовков */
backdrop-filter: blur(4px); /* Размытие под заголовками */
}
/* Увеличенные изображения продуктов */
.cart-table img {
height: 100px; /* Увеличим размер изображений */
width: auto;
border-radius: 8px; /* Скруглённые углы для изображений */
}
/* Стилизация кнопок с учетом эзотерического дизайна */
.btn-update, .btn-remove, .button.light, .button.checkout {
font-size: 1rem;
padding: 8px 16px;
border-radius: 25px;
border: 2px solid #FFFFFF;
background: transparent;
color: #00ffc4;
letter-spacing: 0.5px;
font-weight: bold;
text-transform: uppercase; /* Буквы в верхнем регистре для акцента */
}
/* Визуальные эффекты для кнопок при наведении */
.btn-remove, .btn-update, .button.light, .button.checkout {
transition: all 0.3s ease-in-out;
}
.btn-remove:hover {
background-color: #FF6347; /* Терракот при наведении */
}
.btn-update:hover {
background-color: #00bb85; /* Лайм при наведении */
}
.button.light:hover, .button.checkout:hover {
opacity: 0.85;
background-color: #FFFFFF;
color: #235e73;
}
.cart-container{
background-color: rgba(0, 82, 74, 0.72); /* Прозрачный серый фон */
padding: 30px; /* Отступ для создания пространства вокруг .cart-page */
border-radius: 15px; /* Скруглённые углы для согласованности с .cart-page */
box-shadow: 0 6px 12px rgba(0, 107, 85, 0.47); /* Небольшое тень для дополнительной глубины */
margin: 20px auto; /* Автоматические отступы для центрирования и добавления пространства сверху и снизу */
max-width: calc(100% - 40px); /* Ограничение максимальной ширины с учетом отступов */
}
/* Улучшенное оформление строки "Итого" */
.total {
font-weight: bold;
color: #FFF;
background: linear-gradient(145deg, #5acdae, #1ba99c);
font-size: 1.2rem;
text-shadow: 0px 1px 2px rgba(0, 0, 0, 0.5);
}
.total td {
padding: 15px;
border-top: 3px solid rgba(36, 239, 146, 0.41); /* Добавляем золотую границу для акцента */
}
/* Дополнительный стиль для общей цены, чтобы выделить её ещё сильнее */
.total .num {
background-color: rgba(255, 215, 0, 0.2); /* Слегка прозрачный золотой фон */
border-radius: 5px;
padding: 5px 10px;
margin-right: 5px;
box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.2);
}
/* Стиль для кнопок действий с использованием эзотерических цветов и эффектов */
.button.light, .button.checkout {
background: linear-gradient(145deg, #2ac296, #00ffb2);
color: white;
padding: 10px 20px;
border-radius: 30px;
border: none;
cursor: pointer;
font-weight: bold;
text-transform: uppercase;
box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.2);
transition: transform 0.2s ease-in-out, box-shadow 0.2s ease;
}
.button.light:hover, .button.checkout:hover {
transform: scale(1.05);
box-shadow: 0px 6px 8px rgba(0, 0, 0, 0.3);
}

View File

@ -0,0 +1,37 @@
.card:hover {
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
background-color: rgba(0, 94, 74, 0.73); /* Цвет фона при наведении */
}
/* Стили для текста и заголовков в карточке */
.card-title {
font-size: 1.2rem;
margin-bottom: 0.5rem;
}
.card-text {
color: #38ff00; /* Цвет текста */
}
/* Стили для цены */
.card strong {
color: #e38900; /* Цвет цены */
}
/* Стили для ссылок */
.card a {
text-decoration: none;
color: #ffffff; /* Цвет ссылок */
transition: color 0.3s;
}
.card a:hover {
color: #306e00; /* Цвет ссылок при наведении */
}
.card {
background-color: rgba(0, 0, 0, 0.62); /* Цвет фона карточки */
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
transition: box-shadow 0.3s, background-color 0.3s;
border: none;
}

View File

@ -0,0 +1,75 @@
@keyframes glow {
from {
text-shadow: 0 0 10px #64ffca, 0 0 20px #a1faea, 0 0 30px #E6E6FA, 0 0 40px #E6E6FA, 0 0 50px #E6E6FA, 0 0 60px #E6E6FA, 0 0 70px #E6E6FA;
}
to {
text-shadow: 0 0 20px #10dcc4, 0 0 30px #00ffce, 0 0 40px #90fff5, 0 0 50px #00ffb6, 0 0 60px #FF4500, 0 0 70px #FF4500, 0 0 80px #FF4500;
}
}
.navbar-brand {
animation: glow 1.5s ease-in-out infinite alternate;
display: inline-block;
}
.navbar-brand:hover .magic-star {
animation: sparkle 0.5s forwards;
}
.magic-star {
display: inline-block;
transform: scale(0);
transition: transform 0.3s ease;
}
@keyframes sparkle {
100% {
transform: scale(1.5);
opacity: 0;
}
}
.h1:hover .magic-star {
animation: sparkle 0.5s forwards;
}
/* Стили для основного контента и боковой панели категорий */
.main-content {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.categories-sidebar {
width: 15%; /* Уменьшаем ширину боковой панели */
margin-left: auto; /* Выравнивание по правому краю */
padding: 20px;
background: rgba(0, 0, 0, 0.5); /* Полупрозрачный фон для панели */
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.product-list {
flex-grow: 1;
max-width: 80%; /* Увеличиваем максимальную ширину списка продуктов для баланса */
}
.btn-group .btn {
margin-bottom: 10px; /* Отступ между кнопками */
border: none;
background: linear-gradient(145deg, #37d7ff, #53fae1); /* Градиент для кнопок */
color: white;
transition: transform 0.2s ease;
}
.btn-group .btn:hover {
transform: scale(1.05); /* Небольшое увеличение при наведении */
background: linear-gradient(145deg, #00a490, #30ffe8);
}
.btn-group .active {
font-weight: bold;
background: #d7c900; /* Выделение активной категории */
color: black;
}

View File

@ -0,0 +1,100 @@
body {
background-image: url("../img/det.png");
background-repeat: no-repeat;
background-attachment: fixed;
background-position: center center;
background-size: cover;
height: 100%;
}
.dropdown-toggle::after {
content: none;
}
.custom-shadow {
box-shadow: 5px 5px 25px 19px #380069;
}
.product_id {
color: #000000;
font-size: 15px;
}
.badge.bg-warning.text-dark {
position: absolute;
top: 10px;
right: 5px;
z-index: 1;
padding: 5px 10px;
border-radius: 3px;
font-size: 1rem;
box-shadow: 2px 2px 15px 9px #000000;
}
.badge-banner {
top: 80%;
border-radius: 15px;
font-size: 0.7rem;
}
/* Ваши стили для футера */
footer {
padding-top: 20px; /* Расстояние от верха футера */
background-color: #343a40; /* Цвет фона футера */
color: #ffffff; /* Цвет текста внутри футера */
}
.footer-content {
display: flex;
justify-content: space-between;
align-items: center;
}
.footer-ad {
flex-grow: 1; /* Растянуть колонку на всю доступную ширину */
}
.ad-text {
text-align: center;
}
.ad-block {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
margin-top: 10px;
}
.ad-heading {
color: #ffffff;
font-size: 18px;
}
.ad-description {
color: #ffffff;
font-size: 14px;
margin-bottom: 10px;
}
.ad-button {
background-color: #ffc107; /* Цвет кнопки */
color: #343a40; /* Цвет текста на кнопке */
border: none;
padding: 10px 20px;
border-radius: 5px;
text-decoration: none;
transition: background-color 0.3s;
}
.ad-button:hover {
background-color: #ffca2c; /* Цвет кнопки при наведении */
}
.footer-text {
font-size: 18px; /* Размер шрифта */
font-weight: bold; /* Жирное начертание */
margin-top: 10px; /* Верхний отступ */
}
.footer-text span {
color: #ff6b6b; /* Цвет для части текста */
}

View File

@ -0,0 +1,84 @@
body, html {
height: 100%;
margin: 0;
font-family: 'Papyrus', fantasy;
background-image: url("../images/bg-image.png");
background-size: cover;
}
.checkout-container {
background-color: rgba(0, 0, 0, 0.5);
color: #E0FFFF; /* Цвет текста, напоминающий свет луны */
border-radius: 15px;
padding: 30px;
box-shadow: 0 0 15px 5px rgba(0, 255, 255, 0.2);
backdrop-filter: blur(10px);
}
.checkout-title {
font-size: 28px;
color: #FFD700;
text-align: center;
text-shadow: 0 0 15px rgba(255, 215, 0, 0.7);
}
.order-list li {
background-color: rgba(105, 105, 105, 0.1);
padding: 10px;
border-radius: 5px;
margin-bottom: 10px;
border-left: 5px solid #FFD700; /* Золотая линия для элементов списка */
box-shadow: inset 0 0 10px rgba(255, 255, 255, 0.3);
}
.item-price {
font-weight: bold;
}
.total-price {
font-size: 20px;
text-align: right;
border-top: 1px dashed #FFD700;
padding-top: 10px;
}
.place-order-btn {
background-color: transparent;
border: 2px solid #FFD700;
color: #FFD700;
font-size: 16px;
padding: 10px 30px;
display: block;
margin: 20px auto 0;
transition: all 0.3s ease-in-out;
}
.place-order-btn:hover {
background-color: #FFD700;
color: #000;
box-shadow: 0 0 20px #FFD700;
}
/* Добавьте анимации и трансформации для интерактивных элементов */
@keyframes pulse {
0% {
transform: scale(1);
box-shadow: 0 0 0 0 rgba(255, 215, 0, 0.7);
}
70% {
transform: scale(1.05);
box-shadow: 0 0 10px 10px rgba(255, 215, 0, 0);
}
100% {
transform: scale(1);
box-shadow: 0 0 0 0 rgba(255, 215, 0, 0);
}
}
.place-order-btn:focus:not(:hover) {
animation: pulse 2s infinite;
}

View File

@ -0,0 +1,108 @@
@keyframes moveBackground {
0% { background-position: 0 0; }
100% { background-position: -10000px 5000px; }
}
.mystical-background {
position: relative;
background-image: url('main/static/deps/img/mg.png'); /* Укажите правильный путь к файлу */
background-size: cover;
animation: moveBackground 300s linear infinite;
color: #fff;
}
.product-detail {
/* Ваши стили для деталей товара */
padding: 20px;
background-color: rgba(0, 0, 0, 0.7); /* Темный полупрозрачный фон */
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.5);
}
/* Добавьте стили для текста, кнопок и других элементов сюда */
/* Стили для заголовков и описания */
.product-detail h1 {
font-size: 2.5rem;
color: #24ffc5; /* Золотой цвет для заголовков */
text-shadow: 0px 0px 10px rgba(255, 255, 255, 0.7); /* Свечение вокруг текста */
}
.product-detail h2 {
font-size: 1.8rem;
color: #7FFFD4; /* Аквамариновый цвет для подзаголовков */
margin-bottom: 20px;
}
.product-detail .price {
font-size: 2rem;
color: #00FA9A; /* Мягкий зеленый цвет для цены */
font-weight: bold;
margin-bottom: 20px;
}
.product-detail .description {
font-size: 1.2rem;
color: #E6E6FA; /* Лавандовый цвет для описания */
line-height: 1.6;
margin-bottom: 20px;
}
/* Стили для кнопок */
.btn {
padding: 10px 20px;
border-radius: 30px;
font-weight: bold;
text-transform: uppercase;
text-shadow: 0px 0px 5px rgba(0, 0, 0, 0.5);
transition: all 0.3s ease;
border: 2px solid #FFF; /* Белая обводка для контраста */
background: transparent;
color: #FFF;
cursor: pointer;
}
.btn-primary {
background-color: #483D8B; /* Темно-синий цвет */
}
.btn-secondary {
background-color: #4dd0a9; /* Сине-фиолетовый цвет */
}
.btn-primary:hover, .btn-secondary:hover {
background-color: #FFF;
color: #483D8B;
border-color: #483D8B;
}
/* Стиль для анимации кнопок при наведении */
.btn:hover {
transform: scale(1.05);
box-shadow: 0px 0px 15px #FFF;
}
.product-image-container {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
border-radius: 15px; /* Скругляем углы контейнера */
box-shadow: 0px 10px 20px rgba(35, 182, 138, 0.2); /* Добавляем тень для эффекта "глубины" */
margin-right: 20px; /* Отступ справа */
background: rgba(255, 255, 255, 0.1); /* Немного прозрачности для контейнера */
backdrop-filter: blur(5px); /* Размытие фона за контейнером */
width: 500px; /* Увеличенная ширина контейнера */
height: 500px; /* Увеличенная высота контейнера */
}
.product-image {
width: 100%; /* Ширина изображения равна ширине контейнера */
height: 100%; /* Высота изображения равна высоте контейнера */
object-fit: contain; /* Изображение масштабируется с сохранением пропорций */
}
.product-image-container:hover .product-image {
transform: scale(1.1); /* Немного большее увеличение размера изображения при наведении */
transition: transform 0.3s ease-in-out; /* Плавное увеличение */
}

View File

@ -0,0 +1,60 @@
body {
font-family:Helvetica, sans-serif;
color:#222;
line-height:1.5;
}
table {
width:100%;
border-spacing:0;
border-collapse: collapse;
margin:20px 0;
}
table th, table td {
text-align:left;
font-size:14px;
padding:10px;
margin:0;
}
tbody tr:nth-child(odd) {
background:#efefef;
}
thead th, tbody tr.total {
background:#5993bb;
color:#fff;
font-weight:bold;
}
h1 {
margin:0;
}
.secondary {
color:#bbb;
margin-bottom:20px;
}
.num {
text-align:right;
}
.paid, .pending {
color:#1bae37;
border:4px solid #1bae37;
text-transform:uppercase;
font-weight:bold;
font-size:22px;
padding:4px 12px 0px;
float:right;
transform: rotate(-15deg);
margin-right:40px;
}
.pending {
color:#a82d2d;
border:4px solid #a82d2d;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 880 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1 @@
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}

View File

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-box-arrow-in-left" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M10 3.5a.5.5 0 0 0-.5-.5h-8a.5.5 0 0 0-.5.5v9a.5.5 0 0 0 .5.5h8a.5.5 0 0 0 .5-.5v-2a.5.5 0 0 1 1 0v2A1.5 1.5 0 0 1 9.5 14h-8A1.5 1.5 0 0 1 0 12.5v-9A1.5 1.5 0 0 1 1.5 2h8A1.5 1.5 0 0 1 11 3.5v2a.5.5 0 0 1-1 0v-2z"/>
<path fill-rule="evenodd" d="M4.146 8.354a.5.5 0 0 1 0-.708l3-3a.5.5 0 1 1 .708.708L5.707 7.5H14.5a.5.5 0 0 1 0 1H5.707l2.147 2.146a.5.5 0 0 1-.708.708l-3-3z"/>
</svg>

After

Width:  |  Height:  |  Size: 552 B

View File

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-box-arrow-in-right" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M6 3.5a.5.5 0 0 1 .5-.5h8a.5.5 0 0 1 .5.5v9a.5.5 0 0 1-.5.5h-8a.5.5 0 0 1-.5-.5v-2a.5.5 0 0 0-1 0v2A1.5 1.5 0 0 0 6.5 14h8a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2h-8A1.5 1.5 0 0 0 5 3.5v2a.5.5 0 0 0 1 0v-2z"/>
<path fill-rule="evenodd" d="M11.854 8.354a.5.5 0 0 0 0-.708l-3-3a.5.5 0 1 0-.708.708L10.293 7.5H1.5a.5.5 0 0 0 0 1h8.793l-2.147 2.146a.5.5 0 0 0 .708.708l3-3z"/>
</svg>

After

Width:  |  Height:  |  Size: 555 B

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="white" class="bi bi-github" viewBox="0 0 16 16">
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"/>
</svg>

After

Width:  |  Height:  |  Size: 709 B

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="white" class="bi bi-grid-fill" viewBox="0 0 16 16">
<path d="M1 2.5A1.5 1.5 0 0 1 2.5 1h3A1.5 1.5 0 0 1 7 2.5v3A1.5 1.5 0 0 1 5.5 7h-3A1.5 1.5 0 0 1 1 5.5v-3zm8 0A1.5 1.5 0 0 1 10.5 1h3A1.5 1.5 0 0 1 15 2.5v3A1.5 1.5 0 0 1 13.5 7h-3A1.5 1.5 0 0 1 9 5.5v-3zm-8 8A1.5 1.5 0 0 1 2.5 9h3A1.5 1.5 0 0 1 7 10.5v3A1.5 1.5 0 0 1 5.5 15h-3A1.5 1.5 0 0 1 1 13.5v-3zm8 0A1.5 1.5 0 0 1 10.5 9h3a1.5 1.5 0 0 1 1.5 1.5v3a1.5 1.5 0 0 1-1.5 1.5h-3A1.5 1.5 0 0 1 9 13.5v-3z"/>
</svg>

After

Width:  |  Height:  |  Size: 537 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

View File

@ -0,0 +1,3 @@
[LocalizedFileNames]
Снимок экрана 2024-02-08 161455.png=@Снимок экрана 2024-02-08 161455,0
Снимок экрана 2024-02-08 161541.png=@Снимок экрана 2024-02-08 161541,0

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

BIN
main/static/deps/img/mg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

File diff suppressed because one or more lines are too long

181
main/static/deps/js/jquery-ajax.js vendored Normal file
View File

@ -0,0 +1,181 @@
// Когда html документ готов (прорисован)
$(document).ready(function () {
// берем в переменную элемент разметки с id jq-notification для оповещений от ajax
var successMessage = $("#jq-notification");
// // Ловим собыитие клика по кнопке добавить в корзину
// $(document).on("click", ".add-to-cart", function (e) {
// // Блокируем его базовое действие
// e.preventDefault();
// // Берем элемент счетчика в значке корзины и берем оттуда значение
// var goodsInCartCount = $("#goods-in-cart-count");
// var cartCount = parseInt(goodsInCartCount.text() || 0);
// // Получаем id товара из атрибута data-product-id
// var product_id = $(this).data("product-id");
// // Из атрибута href берем ссылку на контроллер django
// var add_to_cart_url = $(this).attr("href");
// // делаем post запрос через ajax не перезагружая страницу
// $.ajax({
// type: "POST",
// url: add_to_cart_url,
// data: {
// product_id: product_id,
// csrfmiddlewaretoken: $("[name=csrfmiddlewaretoken]").val(),
// },
// success: function (data) {
// // Сообщение
// successMessage.html(data.message);
// successMessage.fadeIn(400);
// // Через 7сек убираем сообщение
// setTimeout(function () {
// successMessage.fadeOut(400);
// }, 7000);
// // Увеличиваем количество товаров в корзине (отрисовка в шаблоне)
// cartCount++;
// goodsInCartCount.text(cartCount);
// // Меняем содержимое корзины на ответ от django (новый отрисованный фрагмент разметки корзины)
// var cartItemsContainer = $("#cart-items-container");
// cartItemsContainer.html(data.cart_items_html);
// },
// error: function (data) {
// console.log("Ошибка при добавлении товара в корзину");
// },
// });
// });
// // Ловим собыитие клика по кнопке удалить товар из корзины
// $(document).on("click", ".remove-from-cart", function (e) {
// // Блокируем его базовое действие
// e.preventDefault();
// // Берем элемент счетчика в значке корзины и берем оттуда значение
// var goodsInCartCount = $("#goods-in-cart-count");
// var cartCount = parseInt(goodsInCartCount.text() || 0);
// // Получаем id корзины из атрибута data-cart-id
// var cart_id = $(this).data("cart-id");
// // Из атрибута href берем ссылку на контроллер django
// var remove_from_cart = $(this).attr("href");
// // делаем post запрос через ajax не перезагружая страницу
// $.ajax({
// type: "POST",
// url: remove_from_cart,
// data: {
// cart_id: cart_id,
// csrfmiddlewaretoken: $("[name=csrfmiddlewaretoken]").val(),
// },
// success: function (data) {
// // Сообщение
// successMessage.html(data.message);
// successMessage.fadeIn(400);
// // Через 7сек убираем сообщение
// setTimeout(function () {
// successMessage.fadeOut(400);
// }, 7000);
// // Уменьшаем количество товаров в корзине (отрисовка)
// cartCount -= data.quantity_deleted;
// goodsInCartCount.text(cartCount);
// // Меняем содержимое корзины на ответ от django (новый отрисованный фрагмент разметки корзины)
// var cartItemsContainer = $("#cart-items-container");
// cartItemsContainer.html(data.cart_items_html);
// },
// error: function (data) {
// console.log("Ошибка при добавлении товара в корзину");
// },
// });
// });
// // Теперь + - количества товара
// // Обработчик события для уменьшения значения
// $(document).on("click", ".decrement", function () {
// // Берем ссылку на контроллер django из атрибута data-cart-change-url
// var url = $(this).data("cart-change-url");
// // Берем id корзины из атрибута data-cart-id
// var cartID = $(this).data("cart-id");
// // Ищем ближайшеий input с количеством
// var $input = $(this).closest('.input-group').find('.number');
// // Берем значение количества товара
// var currentValue = parseInt($input.val());
// // Если количества больше одного, то только тогда делаем -1
// if (currentValue > 1) {
// $input.val(currentValue - 1);
// // Запускаем функцию определенную ниже
// // с аргументами (id карты, новое количество, количество уменьшилось или прибавилось, url)
// updateCart(cartID, currentValue - 1, -1, url);
// }
// });
// // Обработчик события для увеличения значения
// $(document).on("click", ".increment", function () {
// // Берем ссылку на контроллер django из атрибута data-cart-change-url
// var url = $(this).data("cart-change-url");
// // Берем id корзины из атрибута data-cart-id
// var cartID = $(this).data("cart-id");
// // Ищем ближайшеий input с количеством
// var $input = $(this).closest('.input-group').find('.number');
// // Берем значение количества товара
// var currentValue = parseInt($input.val());
// $input.val(currentValue + 1);
// // Запускаем функцию определенную ниже
// // с аргументами (id карты, новое количество, количество уменьшилось или прибавилось, url)
// updateCart(cartID, currentValue + 1, 1, url);
// });
// function updateCart(cartID, quantity, change, url) {
// $.ajax({
// type: "POST",
// url: url,
// data: {
// cart_id: cartID,
// quantity: quantity,
// csrfmiddlewaretoken: $("[name=csrfmiddlewaretoken]").val(),
// },
// success: function (data) {
// // Сообщение
// successMessage.html(data.message);
// successMessage.fadeIn(400);
// // Через 7сек убираем сообщение
// setTimeout(function () {
// successMessage.fadeOut(400);
// }, 7000);
// // Изменяем количество товаров в корзине
// var goodsInCartCount = $("#goods-in-cart-count");
// var cartCount = parseInt(goodsInCartCount.text() || 0);
// cartCount += change;
// goodsInCartCount.text(cartCount);
// // Меняем содержимое корзины
// var cartItemsContainer = $("#cart-items-container");
// cartItemsContainer.html(data.cart_items_html);
// },
// error: function (data) {
// console.log("Ошибка при добавлении товара в корзину");
// },
// });
// }
});

35
main/static/deps/js/jquery-events.js vendored Normal file
View File

@ -0,0 +1,35 @@
// Когда html документ готов (прорисован)
$(document).ready(function () {
// Берем из разметки элемент по id - оповещения от django
var notification = $('#notification');
// И через 7 сек. убираем
if (notification.length > 0) {
setTimeout(function () {
notification.alert('close');
}, 7000);
}
// При клике по значку корзины открываем всплывающее(модальное) окно
$('#modalButton').click(function () {
$('#exampleModal').appendTo('body');
$('#exampleModal').modal('show');
});
// Собыите клик по кнопке закрыть окна корзины
$('#exampleModal .btn-close').click(function () {
$('#exampleModal').modal('hide');
});
// Обработчик события радиокнопки выбора способа доставки
$("input[name='requires_delivery']").change(function() {
var selectedValue = $(this).val();
// Скрываем или отображаем input ввода адреса доставки
if (selectedValue === "1") {
$("#deliveryAddressField").show();
} else {
$("#deliveryAddressField").hide();
}
});
});

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,126 @@
{% load static %}
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="{% static "/deps/css/bootstrap/bootstrap.min.css"%}">
<link rel="stylesheet" href="{% static "/deps/css/my_css.css"%}">
<!-- Стиль footer-a для главной страницы -->
<link rel="stylesheet" href="{% static "/deps/css/my_footer_css.css"%}">
<link rel="stylesheet" href="{% static "/deps/css/catal.css"%}">
<!-- Favicons for different platforms -->
<link rel="apple-touch-icon" sizes="180x180" href="{% static "/deps/favicon/apple-touch-icon.png"%}">
<link rel="icon" type="image/png" sizes="32x32" href="{% static "/deps/favicon/favicon-32x32.png"%}">
<link rel="icon" type="image/png" sizes="16x16" href="{% static "/deps/favicon/favicon-16x16.png"%}">
<link rel="manifest" href="{% static "/deps/favicon/site.webmanifest"%}">
<title>Главная</title>
</head>
<body>
<header>
<nav class="navbar navbar-expand-lg bg-dark" data-bs-theme="dark">
<div class="container">
<a class="navbar-brand" href="{% url "main:product_list"%}">Harmony of Esotericism</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item dropdown ">
<a class="nav-link dropdown-toggle text-white" href="#" role="button"
data-bs-toggle="dropdown" aria-expanded="false">
Информация
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item text-white" href="#">Контактная информация</a></li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link text-white" href="{% url 'cart:cart_detail' %}">Корзина</a>
</li>
{# <li class="nav-item dropdown ">#}
{# <a class="nav-link dropdown-toggle text-white" href="#" role="button"#}
{# data-bs-toggle="dropdown" aria-expanded="false">#}
{# Мой профиль#}
{# </a>#}
{# <ul class="dropdown-menu">#}
{# #}
{# <li><a class="dropdown-item text-white" href="#">Личный кабинет</a>#}
{# </li>#}
{##}
{# <li>#}
{# <hr class="dropdown-divider">#}
{# </li>#}
{##}
{# </ul>#}
{# </li>#}
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<div class="row mt-1">
<div class="col-lg-2">
<!-- Пустой блок на Ваше усмотрение -->
</div>
<div id="header">
<h1 style="color: white; text-align: center; position: relative;">
<a class="navbar-brand" href="{% url 'main:product_list' %}" style="text-decoration: none; color: white; font-family: 'Papyrus', fantasy;">
<!-- Добавляем иконку или символ перед названием магазина -->
Гармония Эзотерики
</a>
</h1>
</div>
</div>
<!-- Добавление кнопок категорий и формы для фильтрации -->
{% block content %}
<div class="row mb-3">
<div class="col-12">
<form method="get" action="{% url 'main:product_list' %}">
<button type="submit" class="btn btn-primary">Искать по Категориям</button>
</form>
</div>
</div>
{% endblock %}
</div>
{# <footer class="py-2 bg-dark">#}
{# <div class="container">#}
{# <div class="row">#}
{# <div class="col-lg-14">#}
{# <p class="m-0 text-center text-white footer-text" style="font-size: 18px;">Harmony of Esotericism 2024</p>#}
{# </div>#}
{# <div class="col-lg-14">#}
{# <div class="text-center mt-3">#}
{# <h5 class="text-white" style="font-size: 14px;">Посетите нашего телеграм бота!</h5>#}
{##}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# </footer>#}
<script src="{% static "/deps/js/jquery/jquery-3.7.0.min.js"%}"></script>
<script src="{% static "/deps/js/jquery-events.js"%}"></script>
<script src="{% static "/deps/js/jquery-ajax.js"%}"></script>
<script src="{% static "/deps/js/bootstrap/bootstrap.bundle.min.js"%}"></script>
</body>
</html>

View File

@ -0,0 +1,26 @@
{% extends "main/base.html" %}
{% load static %}
{% block title %}{{ product.name }}{% endblock %}
{% block content %}
<div class="product-detail-page">
<div class="product-image-container">
<img src="{% if product.image %}{{ product.image.url }}{% else %}{% static 'img/no_image.png' %}{% endif %}" alt="{{ product.name }}" class="product-image">
</div>
<div class="product-info-container">
<div class="product-detail mystical-background">
<h1>{{ product.name }}</h1>
<p class="product-price">{{ product.price }}₸</p>
<p class="product-description">{{ product.description|linebreaks }}</p>
<div class="product-actions">
<form action="{% url 'cart:cart_add' product.id %}" method="post">
{% csrf_token %}
<input type="submit" value="Добавить в корзину" class="btn btn-primary">
</form>
<a href="{% url 'main:product_list' %}" class="btn btn-secondary">Продолжить покупки</a>
<a href="{% url "orders:order_create"%}" class="btn btn-secondary">Оформить заказ</a>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,61 @@
{% extends "main/base.html" %}
{% load static %}
{% block content %}
<link rel="stylesheet" href="{% static 'deps/css/my_css.css' %}">
<link rel="stylesheet" href="{% static 'deps/css/exo.css' %}">
<div class="main-content">
<div id="main" class="product-list">
<div class="row">
{% for product in products %}
{% if not category or product.category == category %}
<div class="col-12 col-md-6 col-lg-4 p-4">
<div class="card border-primary rounded custom-shadow">
{% if product.image %}
<a href="{{ product.get_absolute_url }}">
<div class="aspect-ratio overflow-hidden" style="position: relative; padding-top: 100%;">
<img src="{{ product.image.url }}" class="w-100 h-100 position-absolute" style="object-fit: cover; top: 0; left: 0;" alt="{{ product.name }}">
</div>
</a>
{% else %}
<div class="aspect-ratio overflow-hidden" style="position: relative; padding-top: 100%;">
<img src="{% static 'deps/img/no_image.jpg' %}" class="w-100 h-100 position-absolute" style="object-fit: cover; top: 0; left: 0;" alt="{{ product.name }}">
</div>
{% endif %}
<div class="card-body">
<a href="{{ product.get_absolute_url }}">
<p class="card-title">{{ product.name }}</p>
</a>
<p class="card-text text-truncate" style="color: #9fffd3">{{ product.description }}</p>
<div class="d-flex justify-content-between">
<p><strong style="color: white">{{ product.price }}₸</strong></p>
<form action="{% url 'cart:cart_add' product.id %}" method="post">
{% csrf_token %}
<input type="hidden" name="quantity" value="1">
<input type="hidden" name="override" value="False">
<button style="color: #00ffb6" type="submit" class="btn btn-primary btn-sm">Добавить</button>
</form>
</div>
</div>
</div>
</div>
{% endif %}
{% endfor %}
</div>
</div>
<div id="sidebar" class="categories-sidebar">
<div class="btn-group flex-wrap overflow-hidden rounded-8" role="group" aria-label="Категории">
<a href="{% url 'main:product_list' %}" class="btn btn-secondary rounded-0 {% if not category %}active{% endif %}">
Все
</a>
{% for c in categories %}
<a href="{{ c.get_absolute_url }}" class="btn btn-secondary rounded-0 {% if category.slug == c.slug %}active{% endif %}">
{{ c.name }}
</a>
{% endfor %}
</div>
</div>
</div>
{% endblock %}

3
main/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

15
main/urls.py Normal file
View File

@ -0,0 +1,15 @@
from django.urls import path
from . import views
app_name = 'main'
urlpatterns = [
path('', views.product_list, name='product_list'),
path('products/', views.product_list, name='product_list'),
path('<slug:category_slug>/', views.product_list,
name='product_list_by_category'),
path('<int:id>/<slug:slug>/', views.product_detail,
name='product_detail'),
]

33
main/views.py Normal file
View File

@ -0,0 +1,33 @@
from django.shortcuts import render,get_object_or_404
from django.http import HttpResponse
from .models import Category, Product
from cart.forms import CartAddProductForm
def home(request):
# Ваш код для отображения главной страницы
return render(request, 'main/base.html')
def product_list(request, category_slug=None):
category = None
categories = Category.objects.all()
products = Product.objects.filter(available=True)
if category_slug:
category = get_object_or_404(Category,
slug=category_slug)
products = products.filter(category=category)
return render(request,'main/product/list.html',
{'category': category,
'categories': categories,
'products': products})
def product_detail(request, id, slug):
product = get_object_or_404(Product,
id=id,
slug=slug,
available=True)
cart_product_form = CartAddProductForm()
return render(request,
'main/product/detail.html',
{'product': product,
'cart_product_form': cart_product_form})

22
manage.py Normal file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoProject1.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()

BIN
media/invoice_10.pdf Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

68
media/invoice_11.pdf Normal file
View File

@ -0,0 +1,68 @@
%PDF-1.3
%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com
1 0 obj
<<
/F1 2 0 R
>>
endobj
2 0 obj
<<
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
>>
endobj
3 0 obj
<<
/Contents 7 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 6 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
4 0 obj
<<
/PageMode /UseNone /Pages 6 0 R /Type /Catalog
>>
endobj
5 0 obj
<<
/Author (anonymous) /CreationDate (D:20240219080150-06'00') /Creator (ReportLab PDF Library - www.reportlab.com) /Keywords () /ModDate (D:20240219080150-06'00') /Producer (ReportLab PDF Library - www.reportlab.com)
/Subject (unspecified) /Title (untitled) /Trapped /False
>>
endobj
6 0 obj
<<
/Count 1 /Kids [ 3 0 R ] /Type /Pages
>>
endobj
7 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 104
>>
stream
GapQh0E=F,0U\H3T\pNYT^QKk?tc>IP,;W#U1^23ihPEM_?CW4KISi90MntRifICK%KE/ee05&l(FoYV6VW8r/;4WeOD4qO!$;.QG5~>endstream
endobj
xref
0 8
0000000000 65535 f
0000000073 00000 n
0000000104 00000 n
0000000211 00000 n
0000000414 00000 n
0000000482 00000 n
0000000778 00000 n
0000000837 00000 n
trailer
<<
/ID
[<46974cbc22aca82055745e0be532c429><46974cbc22aca82055745e0be532c429>]
% ReportLab generated PDF document -- digest (http://www.reportlab.com)
/Info 5 0 R
/Root 4 0 R
/Size 8
>>
startxref
1031
%%EOF

68
media/invoice_12.pdf Normal file
View File

@ -0,0 +1,68 @@
%PDF-1.3
%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com
1 0 obj
<<
/F1 2 0 R
>>
endobj
2 0 obj
<<
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
>>
endobj
3 0 obj
<<
/Contents 7 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 6 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
4 0 obj
<<
/PageMode /UseNone /Pages 6 0 R /Type /Catalog
>>
endobj
5 0 obj
<<
/Author (anonymous) /CreationDate (D:20240219080214-06'00') /Creator (ReportLab PDF Library - www.reportlab.com) /Keywords () /ModDate (D:20240219080214-06'00') /Producer (ReportLab PDF Library - www.reportlab.com)
/Subject (unspecified) /Title (untitled) /Trapped /False
>>
endobj
6 0 obj
<<
/Count 1 /Kids [ 3 0 R ] /Type /Pages
>>
endobj
7 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 102
>>
stream
GapQh0E=F,0U\H3T\pNYT^QKk?tc>IP,;W#U1^23ihPEM_?CW4KISi90MntRifICK%KE/ee05&l(Fu-g9neZ[Kb,htC'?3i*t8j-~>endstream
endobj
xref
0 8
0000000000 65535 f
0000000073 00000 n
0000000104 00000 n
0000000211 00000 n
0000000414 00000 n
0000000482 00000 n
0000000778 00000 n
0000000837 00000 n
trailer
<<
/ID
[<57330d4d54db8c8cd0df3ab596c800db><57330d4d54db8c8cd0df3ab596c800db>]
% ReportLab generated PDF document -- digest (http://www.reportlab.com)
/Info 5 0 R
/Root 4 0 R
/Size 8
>>
startxref
1029
%%EOF

68
media/invoice_4.pdf Normal file
View File

@ -0,0 +1,68 @@
%PDF-1.3
%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com
1 0 obj
<<
/F1 2 0 R
>>
endobj
2 0 obj
<<
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
>>
endobj
3 0 obj
<<
/Contents 7 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 6 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
4 0 obj
<<
/PageMode /UseNone /Pages 6 0 R /Type /Catalog
>>
endobj
5 0 obj
<<
/Author (anonymous) /CreationDate (D:20240218233355-06'00') /Creator (ReportLab PDF Library - www.reportlab.com) /Keywords () /ModDate (D:20240218233355-06'00') /Producer (ReportLab PDF Library - www.reportlab.com)
/Subject (unspecified) /Title (untitled) /Trapped /False
>>
endobj
6 0 obj
<<
/Count 1 /Kids [ 3 0 R ] /Type /Pages
>>
endobj
7 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 102
>>
stream
GapQh0E=F,0U\H3T\pNYT^QKk?tc>IP,;W#U1^23ihPEM_?CW4KISi90MntRifICK%KE/ee05&l(FoY&9neZ[Kb,ht@Ke@a%*&uP~>endstream
endobj
xref
0 8
0000000000 65535 f
0000000073 00000 n
0000000104 00000 n
0000000211 00000 n
0000000414 00000 n
0000000482 00000 n
0000000778 00000 n
0000000837 00000 n
trailer
<<
/ID
[<7ff900bd69895d6fd30b340931449cb9><7ff900bd69895d6fd30b340931449cb9>]
% ReportLab generated PDF document -- digest (http://www.reportlab.com)
/Info 5 0 R
/Root 4 0 R
/Size 8
>>
startxref
1029
%%EOF

Some files were not shown because too many files have changed in this diff Show More