Update app.py
Browse files
app.py
CHANGED
|
@@ -186,6 +186,8 @@ def load_data():
|
|
| 186 |
'system_mode': 'both',
|
| 187 |
'hide_stock_online': False,
|
| 188 |
'closed_catalog_enabled': False,
|
|
|
|
|
|
|
| 189 |
'theme': 'light',
|
| 190 |
'customer_fields': {
|
| 191 |
'name': True, 'phone': True, 'city': True, 'address': False, 'zip': False
|
|
@@ -226,6 +228,8 @@ def load_data():
|
|
| 226 |
if 'system_mode' not in settings: settings['system_mode'] = 'both'; changed = True
|
| 227 |
if 'hide_stock_online' not in settings: settings['hide_stock_online'] = False; changed = True
|
| 228 |
if 'closed_catalog_enabled' not in settings: settings['closed_catalog_enabled'] = False; changed = True
|
|
|
|
|
|
|
| 229 |
if 'theme' not in settings: settings['theme'] = 'light'; changed = True
|
| 230 |
if 'customer_fields' not in settings:
|
| 231 |
settings['customer_fields'] = {'name': True, 'phone': True, 'city': True, 'address': False, 'zip': False}
|
|
@@ -263,6 +267,7 @@ def load_data():
|
|
| 263 |
if 'staff_name' not in order: order['staff_name'] = ''; changed = True
|
| 264 |
if 'assembled' not in order: order['assembled'] = {}; changed = True
|
| 265 |
if 'global_discount' not in order: order['global_discount'] = 0; changed = True
|
|
|
|
| 266 |
for item in order.get('cart', []):
|
| 267 |
if 'discount' not in item: item['discount'] = 0; changed = True
|
| 268 |
if 'category' not in item: item['category'] = 'Без категории'; changed = True
|
|
@@ -317,6 +322,8 @@ def get_env_data(env_id):
|
|
| 317 |
'system_mode': 'both',
|
| 318 |
'hide_stock_online': False,
|
| 319 |
'closed_catalog_enabled': False,
|
|
|
|
|
|
|
| 320 |
'theme': 'light',
|
| 321 |
'customer_fields': {'name': True, 'phone': True, 'city': True, 'address': False, 'zip': False},
|
| 322 |
'socials': {
|
|
@@ -334,7 +341,10 @@ def save_env_data(env_id, env_data):
|
|
| 334 |
all_data[env_id] = env_data
|
| 335 |
save_data(all_data)
|
| 336 |
|
| 337 |
-
def update_order_totals(order,
|
|
|
|
|
|
|
|
|
|
| 338 |
total = 0
|
| 339 |
global_discount = float(order.get('global_discount', 0))
|
| 340 |
for i in order['cart']:
|
|
@@ -363,6 +373,14 @@ def update_order_totals(order, business_type):
|
|
| 363 |
total += item_total
|
| 364 |
|
| 365 |
total = max(0, total - global_discount)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 366 |
order['total_price'] = round(total, 2)
|
| 367 |
|
| 368 |
def is_order_fully_assembled(order):
|
|
@@ -967,6 +985,8 @@ CATALOG_TEMPLATE = '''
|
|
| 967 |
const hideStockOnline = {{ 'true' if settings.hide_stock_online else 'false' }};
|
| 968 |
const businessType = '{{ settings.business_type }}';
|
| 969 |
const cFields = {{ settings.customer_fields|tojson }};
|
|
|
|
|
|
|
| 970 |
|
| 971 |
let cart = {};
|
| 972 |
let currentGalleryPhotos =[];
|
|
@@ -1374,6 +1394,10 @@ CATALOG_TEMPLATE = '''
|
|
| 1374 |
|
| 1375 |
total = total - globalDisc;
|
| 1376 |
if(total < 0) total = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1377 |
|
| 1378 |
const cartBar = document.getElementById('cartBar');
|
| 1379 |
if (total > 0 || Object.keys(cart).length > 0) {
|
|
@@ -1427,6 +1451,10 @@ CATALOG_TEMPLATE = '''
|
|
| 1427 |
</div>
|
| 1428 |
`;
|
| 1429 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1430 |
}
|
| 1431 |
|
| 1432 |
function openCartModal() {
|
|
@@ -1927,6 +1955,9 @@ ORDER_TEMPLATE = '''
|
|
| 1927 |
{% if order.global_discount > 0 %}
|
| 1928 |
<div style="color:#e17055; font-size:0.9rem; margin-bottom:5px;">Применена общая скидка: -{{ order.global_discount }} {{ currency_code }}</div>
|
| 1929 |
{% endif %}
|
|
|
|
|
|
|
|
|
|
| 1930 |
Итого:
|
| 1931 |
</td>
|
| 1932 |
<td>{{ order.total_price }} {{ currency_code }}</td>
|
|
@@ -2702,6 +2733,12 @@ ADMIN_TEMPLATE = '''
|
|
| 2702 |
<label><input type="checkbox" name="closed_catalog_enabled" {% if settings.closed_catalog_enabled %}checked{% endif %}> Включить закрытый каталог (доступ только по паролю из раздела пользователей)</label>
|
| 2703 |
{% endif %}
|
| 2704 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2705 |
<div style="font-weight: 600; margin-bottom: 5px; border-top: 1px solid var(--border); padding-top: 15px; margin-top: 10px;">Безопасность (Админ-панель):</div>
|
| 2706 |
<div class="social-item" style="margin-bottom: 10px;">
|
| 2707 |
<label style="width: auto; margin-right: 15px;"><input type="checkbox" name="admin_password_enabled" {% if settings.admin_password_enabled %}checked{% endif %}> Пароль на вход</label>
|
|
@@ -3538,7 +3575,7 @@ REPORTS_TEMPLATE = '''
|
|
| 3538 |
.tabs { display: flex; gap: 10px; margin-bottom: 20px; border-bottom: 2px solid var(--border); padding-bottom: 10px; flex-wrap: wrap; }
|
| 3539 |
.tab { padding: 10px 20px; cursor: pointer; font-weight: 600; color: #636e72; border-radius: 8px; transition: background 0.2s; }
|
| 3540 |
.tab:hover { background: #e9ecef; }
|
| 3541 |
-
.tab.active {
|
| 3542 |
|
| 3543 |
.tab-content { display: none; }
|
| 3544 |
.tab-content.active { display: block; }
|
|
@@ -3615,6 +3652,15 @@ REPORTS_TEMPLATE = '''
|
|
| 3615 |
<i class="fas fa-undo icon"></i>
|
| 3616 |
</div>
|
| 3617 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3618 |
</div>
|
| 3619 |
|
| 3620 |
<div class="table-container">
|
|
@@ -3723,6 +3769,7 @@ REPORTS_TEMPLATE = '''
|
|
| 3723 |
let totalRet = 0;
|
| 3724 |
let totalItems = 0;
|
| 3725 |
let ordersCount = 0;
|
|
|
|
| 3726 |
|
| 3727 |
let staffSales = {};
|
| 3728 |
let productSales = {};
|
|
@@ -3735,6 +3782,10 @@ REPORTS_TEMPLATE = '''
|
|
| 3735 |
} else {
|
| 3736 |
totalRev += o.total_price;
|
| 3737 |
ordersCount++;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3738 |
|
| 3739 |
const staff = o.staff_name || 'Онлайн (Без сотрудника)';
|
| 3740 |
if(!staffSales[staff]) staffSales[staff] = { orders: 0, sum: 0 };
|
|
@@ -3772,6 +3823,11 @@ REPORTS_TEMPLATE = '''
|
|
| 3772 |
document.getElementById('totalReturns').innerText = totalRet.toLocaleString() + ' {{ currency_code }}';
|
| 3773 |
document.getElementById('totalItemsSold').innerText = totalItems.toLocaleString();
|
| 3774 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3775 |
let aov = ordersCount > 0 ? (totalRev / ordersCount) : 0;
|
| 3776 |
document.getElementById('avgOrderValue').innerText = Math.round(aov).toLocaleString() + ' {{ currency_code }}';
|
| 3777 |
|
|
@@ -4147,6 +4203,8 @@ def create_environment():
|
|
| 4147 |
"system_mode": "both",
|
| 4148 |
"hide_stock_online": False,
|
| 4149 |
"closed_catalog_enabled": False,
|
|
|
|
|
|
|
| 4150 |
"theme": "light",
|
| 4151 |
"customer_fields": {'name': True, 'phone': True, 'city': True, 'address': False, 'zip': False},
|
| 4152 |
"socials": {
|
|
@@ -4338,7 +4396,7 @@ def finish_assembly(env_id, order_id):
|
|
| 4338 |
new_cart.append(item)
|
| 4339 |
|
| 4340 |
order['cart'] = new_cart
|
| 4341 |
-
update_order_totals(order, data['settings']
|
| 4342 |
save_env_data(env_id, data)
|
| 4343 |
|
| 4344 |
return jsonify({"success": True})
|
|
@@ -4369,7 +4427,7 @@ def process_return(env_id, order_id):
|
|
| 4369 |
restore_stock(c_key, item.get('product_id'), item.get('variant_idx', -1), ret_qty, data['products'])
|
| 4370 |
break
|
| 4371 |
|
| 4372 |
-
update_order_totals(order, data['settings']
|
| 4373 |
if order['total_price'] <= 0:
|
| 4374 |
order['status'] = 'returned'
|
| 4375 |
|
|
@@ -4446,10 +4504,11 @@ def create_order(env_id):
|
|
| 4446 |
"customer_zip": customer_zip,
|
| 4447 |
"customer_whatsapp": customer_whatsapp,
|
| 4448 |
"global_discount": global_discount,
|
| 4449 |
-
"assembled": {}
|
|
|
|
| 4450 |
}
|
| 4451 |
|
| 4452 |
-
update_order_totals(new_order, data['settings']
|
| 4453 |
|
| 4454 |
if order_status == 'pos' and data['settings'].get('track_inventory', False) and data['settings'].get('system_mode', 'both') not in ['external', 'light_external']:
|
| 4455 |
deduct_stock(processed_cart, data['products'])
|
|
@@ -4525,7 +4584,7 @@ def edit_order(env_id, order_id):
|
|
| 4525 |
order['cart'].remove(item)
|
| 4526 |
break
|
| 4527 |
|
| 4528 |
-
update_order_totals(order, data['settings']
|
| 4529 |
save_env_data(env_id, data)
|
| 4530 |
|
| 4531 |
return jsonify({"success": True, "total_price": order['total_price']})
|
|
@@ -4554,7 +4613,7 @@ def apply_discount(env_id, order_id):
|
|
| 4554 |
except ValueError:
|
| 4555 |
item['discount'] = 0
|
| 4556 |
|
| 4557 |
-
update_order_totals(order, data['settings']
|
| 4558 |
save_env_data(env_id, data)
|
| 4559 |
flash('Скидка успешно применена.', 'success')
|
| 4560 |
return redirect(url_for('admin', env_id=env_id))
|
|
@@ -4642,6 +4701,7 @@ def reports(env_id):
|
|
| 4642 |
return render_template_string(
|
| 4643 |
REPORTS_TEMPLATE,
|
| 4644 |
env_id=env_id,
|
|
|
|
| 4645 |
currency_code=settings.get('currency', 'T'),
|
| 4646 |
orders_json=json.dumps(orders_list)
|
| 4647 |
)
|
|
@@ -4778,6 +4838,12 @@ def admin(env_id):
|
|
| 4778 |
settings['admin_password_enabled'] = 'admin_password_enabled' in request.form
|
| 4779 |
settings['admin_password'] = request.form.get('admin_password', '').strip()
|
| 4780 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4781 |
settings['customer_fields'] = {
|
| 4782 |
'name': 'cf_name' in request.form,
|
| 4783 |
'phone': 'cf_phone' in request.form,
|
|
|
|
| 186 |
'system_mode': 'both',
|
| 187 |
'hide_stock_online': False,
|
| 188 |
'closed_catalog_enabled': False,
|
| 189 |
+
'commission_enabled': False,
|
| 190 |
+
'commission_percent': 0.0,
|
| 191 |
'theme': 'light',
|
| 192 |
'customer_fields': {
|
| 193 |
'name': True, 'phone': True, 'city': True, 'address': False, 'zip': False
|
|
|
|
| 228 |
if 'system_mode' not in settings: settings['system_mode'] = 'both'; changed = True
|
| 229 |
if 'hide_stock_online' not in settings: settings['hide_stock_online'] = False; changed = True
|
| 230 |
if 'closed_catalog_enabled' not in settings: settings['closed_catalog_enabled'] = False; changed = True
|
| 231 |
+
if 'commission_enabled' not in settings: settings['commission_enabled'] = False; changed = True
|
| 232 |
+
if 'commission_percent' not in settings: settings['commission_percent'] = 0.0; changed = True
|
| 233 |
if 'theme' not in settings: settings['theme'] = 'light'; changed = True
|
| 234 |
if 'customer_fields' not in settings:
|
| 235 |
settings['customer_fields'] = {'name': True, 'phone': True, 'city': True, 'address': False, 'zip': False}
|
|
|
|
| 267 |
if 'staff_name' not in order: order['staff_name'] = ''; changed = True
|
| 268 |
if 'assembled' not in order: order['assembled'] = {}; changed = True
|
| 269 |
if 'global_discount' not in order: order['global_discount'] = 0; changed = True
|
| 270 |
+
if 'commission_amount' not in order: order['commission_amount'] = 0; changed = True
|
| 271 |
for item in order.get('cart', []):
|
| 272 |
if 'discount' not in item: item['discount'] = 0; changed = True
|
| 273 |
if 'category' not in item: item['category'] = 'Без категории'; changed = True
|
|
|
|
| 322 |
'system_mode': 'both',
|
| 323 |
'hide_stock_online': False,
|
| 324 |
'closed_catalog_enabled': False,
|
| 325 |
+
'commission_enabled': False,
|
| 326 |
+
'commission_percent': 0.0,
|
| 327 |
'theme': 'light',
|
| 328 |
'customer_fields': {'name': True, 'phone': True, 'city': True, 'address': False, 'zip': False},
|
| 329 |
'socials': {
|
|
|
|
| 341 |
all_data[env_id] = env_data
|
| 342 |
save_data(all_data)
|
| 343 |
|
| 344 |
+
def update_order_totals(order, settings):
|
| 345 |
+
business_type = settings.get('business_type', 'mixed')
|
| 346 |
+
commission_enabled = settings.get('commission_enabled', False)
|
| 347 |
+
commission_percent = float(settings.get('commission_percent', 0.0))
|
| 348 |
total = 0
|
| 349 |
global_discount = float(order.get('global_discount', 0))
|
| 350 |
for i in order['cart']:
|
|
|
|
| 373 |
total += item_total
|
| 374 |
|
| 375 |
total = max(0, total - global_discount)
|
| 376 |
+
|
| 377 |
+
if commission_enabled and commission_percent > 0:
|
| 378 |
+
commission_amount = total * (commission_percent / 100.0)
|
| 379 |
+
order['commission_amount'] = round(commission_amount, 2)
|
| 380 |
+
total += commission_amount
|
| 381 |
+
else:
|
| 382 |
+
order['commission_amount'] = 0
|
| 383 |
+
|
| 384 |
order['total_price'] = round(total, 2)
|
| 385 |
|
| 386 |
def is_order_fully_assembled(order):
|
|
|
|
| 985 |
const hideStockOnline = {{ 'true' if settings.hide_stock_online else 'false' }};
|
| 986 |
const businessType = '{{ settings.business_type }}';
|
| 987 |
const cFields = {{ settings.customer_fields|tojson }};
|
| 988 |
+
const commissionEnabled = {{ 'true' if settings.commission_enabled else 'false' }};
|
| 989 |
+
const commissionPercent = {{ settings.commission_percent | default(0) }};
|
| 990 |
|
| 991 |
let cart = {};
|
| 992 |
let currentGalleryPhotos =[];
|
|
|
|
| 1394 |
|
| 1395 |
total = total - globalDisc;
|
| 1396 |
if(total < 0) total = 0;
|
| 1397 |
+
|
| 1398 |
+
if (commissionEnabled && commissionPercent > 0) {
|
| 1399 |
+
total += total * (commissionPercent / 100.0);
|
| 1400 |
+
}
|
| 1401 |
|
| 1402 |
const cartBar = document.getElementById('cartBar');
|
| 1403 |
if (total > 0 || Object.keys(cart).length > 0) {
|
|
|
|
| 1451 |
</div>
|
| 1452 |
`;
|
| 1453 |
}
|
| 1454 |
+
|
| 1455 |
+
if (commissionEnabled && commissionPercent > 0) {
|
| 1456 |
+
list.innerHTML += `<div style="text-align: right; font-size: 0.85rem; color: #0984e3; margin-top: 10px; font-weight: 600;">Включая комиссию ${commissionPercent}%</div>`;
|
| 1457 |
+
}
|
| 1458 |
}
|
| 1459 |
|
| 1460 |
function openCartModal() {
|
|
|
|
| 1955 |
{% if order.global_discount > 0 %}
|
| 1956 |
<div style="color:#e17055; font-size:0.9rem; margin-bottom:5px;">Применена общая скидка: -{{ order.global_discount }} {{ currency_code }}</div>
|
| 1957 |
{% endif %}
|
| 1958 |
+
{% if settings.commission_enabled and order.commission_amount and order.commission_amount > 0 %}
|
| 1959 |
+
<div style="color:#0984e3; font-size:0.9rem; margin-bottom:5px;">Комиссия ({{ settings.commission_percent }}%): +{{ order.commission_amount }} {{ currency_code }}</div>
|
| 1960 |
+
{% endif %}
|
| 1961 |
Итого:
|
| 1962 |
</td>
|
| 1963 |
<td>{{ order.total_price }} {{ currency_code }}</td>
|
|
|
|
| 2733 |
<label><input type="checkbox" name="closed_catalog_enabled" {% if settings.closed_catalog_enabled %}checked{% endif %}> Включить закрытый каталог (доступ только по паролю из раздела пользователей)</label>
|
| 2734 |
{% endif %}
|
| 2735 |
|
| 2736 |
+
<div style="font-weight: 600; margin-bottom: 5px; border-top: 1px solid var(--border); padding-top: 15px; margin-top: 10px;">Комиссия на заказы:</div>
|
| 2737 |
+
<div class="social-item" style="margin-bottom: 10px;">
|
| 2738 |
+
<label style="width: auto; margin-right: 15px;"><input type="checkbox" name="commission_enabled" {% if settings.commission_enabled %}checked{% endif %}> Добавить комиссию</label>
|
| 2739 |
+
<input type="number" step="0.01" name="commission_percent" value="{{ settings.commission_percent }}" placeholder="Процент (например, 0.95)" style="flex: 1; min-width: 150px;">
|
| 2740 |
+
</div>
|
| 2741 |
+
|
| 2742 |
<div style="font-weight: 600; margin-bottom: 5px; border-top: 1px solid var(--border); padding-top: 15px; margin-top: 10px;">Безопасность (Админ-панель):</div>
|
| 2743 |
<div class="social-item" style="margin-bottom: 10px;">
|
| 2744 |
<label style="width: auto; margin-right: 15px;"><input type="checkbox" name="admin_password_enabled" {% if settings.admin_password_enabled %}checked{% endif %}> Пароль на вход</label>
|
|
|
|
| 3575 |
.tabs { display: flex; gap: 10px; margin-bottom: 20px; border-bottom: 2px solid var(--border); padding-bottom: 10px; flex-wrap: wrap; }
|
| 3576 |
.tab { padding: 10px 20px; cursor: pointer; font-weight: 600; color: #636e72; border-radius: 8px; transition: background 0.2s; }
|
| 3577 |
.tab:hover { background: #e9ecef; }
|
| 3578 |
+
.tab.active {background: var(--primary); color: #fff; }
|
| 3579 |
|
| 3580 |
.tab-content { display: none; }
|
| 3581 |
.tab-content.active { display: block; }
|
|
|
|
| 3652 |
<i class="fas fa-undo icon"></i>
|
| 3653 |
</div>
|
| 3654 |
</div>
|
| 3655 |
+
{% if settings.commission_enabled %}
|
| 3656 |
+
<div class="stat-card">
|
| 3657 |
+
<div class="stat-card-inner">
|
| 3658 |
+
<div class="title">Сумма комиссий ({{ settings.commission_percent }}%)</div>
|
| 3659 |
+
<div class="value" id="totalCommissions" style="color:var(--info);">0</div>
|
| 3660 |
+
<i class="fas fa-percentage icon"></i>
|
| 3661 |
+
</div>
|
| 3662 |
+
</div>
|
| 3663 |
+
{% endif %}
|
| 3664 |
</div>
|
| 3665 |
|
| 3666 |
<div class="table-container">
|
|
|
|
| 3769 |
let totalRet = 0;
|
| 3770 |
let totalItems = 0;
|
| 3771 |
let ordersCount = 0;
|
| 3772 |
+
let totalCommissions = 0;
|
| 3773 |
|
| 3774 |
let staffSales = {};
|
| 3775 |
let productSales = {};
|
|
|
|
| 3782 |
} else {
|
| 3783 |
totalRev += o.total_price;
|
| 3784 |
ordersCount++;
|
| 3785 |
+
|
| 3786 |
+
if (o.commission_amount) {
|
| 3787 |
+
totalCommissions += o.commission_amount;
|
| 3788 |
+
}
|
| 3789 |
|
| 3790 |
const staff = o.staff_name || 'Онлайн (Без сотрудника)';
|
| 3791 |
if(!staffSales[staff]) staffSales[staff] = { orders: 0, sum: 0 };
|
|
|
|
| 3823 |
document.getElementById('totalReturns').innerText = totalRet.toLocaleString() + ' {{ currency_code }}';
|
| 3824 |
document.getElementById('totalItemsSold').innerText = totalItems.toLocaleString();
|
| 3825 |
|
| 3826 |
+
let tcEl = document.getElementById('totalCommissions');
|
| 3827 |
+
if (tcEl) {
|
| 3828 |
+
tcEl.innerText = totalCommissions.toLocaleString() + ' {{ currency_code }}';
|
| 3829 |
+
}
|
| 3830 |
+
|
| 3831 |
let aov = ordersCount > 0 ? (totalRev / ordersCount) : 0;
|
| 3832 |
document.getElementById('avgOrderValue').innerText = Math.round(aov).toLocaleString() + ' {{ currency_code }}';
|
| 3833 |
|
|
|
|
| 4203 |
"system_mode": "both",
|
| 4204 |
"hide_stock_online": False,
|
| 4205 |
"closed_catalog_enabled": False,
|
| 4206 |
+
"commission_enabled": False,
|
| 4207 |
+
"commission_percent": 0.0,
|
| 4208 |
"theme": "light",
|
| 4209 |
"customer_fields": {'name': True, 'phone': True, 'city': True, 'address': False, 'zip': False},
|
| 4210 |
"socials": {
|
|
|
|
| 4396 |
new_cart.append(item)
|
| 4397 |
|
| 4398 |
order['cart'] = new_cart
|
| 4399 |
+
update_order_totals(order, data['settings'])
|
| 4400 |
save_env_data(env_id, data)
|
| 4401 |
|
| 4402 |
return jsonify({"success": True})
|
|
|
|
| 4427 |
restore_stock(c_key, item.get('product_id'), item.get('variant_idx', -1), ret_qty, data['products'])
|
| 4428 |
break
|
| 4429 |
|
| 4430 |
+
update_order_totals(order, data['settings'])
|
| 4431 |
if order['total_price'] <= 0:
|
| 4432 |
order['status'] = 'returned'
|
| 4433 |
|
|
|
|
| 4504 |
"customer_zip": customer_zip,
|
| 4505 |
"customer_whatsapp": customer_whatsapp,
|
| 4506 |
"global_discount": global_discount,
|
| 4507 |
+
"assembled": {},
|
| 4508 |
+
"commission_amount": 0
|
| 4509 |
}
|
| 4510 |
|
| 4511 |
+
update_order_totals(new_order, data['settings'])
|
| 4512 |
|
| 4513 |
if order_status == 'pos' and data['settings'].get('track_inventory', False) and data['settings'].get('system_mode', 'both') not in ['external', 'light_external']:
|
| 4514 |
deduct_stock(processed_cart, data['products'])
|
|
|
|
| 4584 |
order['cart'].remove(item)
|
| 4585 |
break
|
| 4586 |
|
| 4587 |
+
update_order_totals(order, data['settings'])
|
| 4588 |
save_env_data(env_id, data)
|
| 4589 |
|
| 4590 |
return jsonify({"success": True, "total_price": order['total_price']})
|
|
|
|
| 4613 |
except ValueError:
|
| 4614 |
item['discount'] = 0
|
| 4615 |
|
| 4616 |
+
update_order_totals(order, data['settings'])
|
| 4617 |
save_env_data(env_id, data)
|
| 4618 |
flash('Скидка успешно применена.', 'success')
|
| 4619 |
return redirect(url_for('admin', env_id=env_id))
|
|
|
|
| 4701 |
return render_template_string(
|
| 4702 |
REPORTS_TEMPLATE,
|
| 4703 |
env_id=env_id,
|
| 4704 |
+
settings=settings,
|
| 4705 |
currency_code=settings.get('currency', 'T'),
|
| 4706 |
orders_json=json.dumps(orders_list)
|
| 4707 |
)
|
|
|
|
| 4838 |
settings['admin_password_enabled'] = 'admin_password_enabled' in request.form
|
| 4839 |
settings['admin_password'] = request.form.get('admin_password', '').strip()
|
| 4840 |
|
| 4841 |
+
settings['commission_enabled'] = 'commission_enabled' in request.form
|
| 4842 |
+
try:
|
| 4843 |
+
settings['commission_percent'] = float(request.form.get('commission_percent', 0.0))
|
| 4844 |
+
except ValueError:
|
| 4845 |
+
settings['commission_percent'] = 0.0
|
| 4846 |
+
|
| 4847 |
settings['customer_fields'] = {
|
| 4848 |
'name': 'cf_name' in request.form,
|
| 4849 |
'phone': 'cf_phone' in request.form,
|