first upload to git

parents
Pipeline #1247 failed with stages
from django.contrib import admin
# Register your models here.
from django.apps import AppConfig
class DashboardConfig(AppConfig):
name = 'dashboard'
from django.db import models
# Create your models here.
{% extends 'pos_base.html' %}
{% block tailhead %}
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.css" />
{% endblock tailhead %}
{% block content %}
{% include 'navbar.html' %}
<div class="container">
<div class='row'>
<div class="col-8 ">
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
ยอดรวมวันนี้
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton" id='areaDropdown'>
<a class="dropdown-item" id='week' href="#" onclick='setshow(this)'>1สัปดาห์(7วันก่อนหน้า)</a>
<a class="dropdown-item" id='month' href="#" onclick='setshow(this)'>1เดือน(30วันก่อนหน้า)</a>
{% comment %}
no onclick send param by postMethod ,no recive postMethod to make something in views.py
<a class="dropdown-item" href="#" onclick='showOption(this)'>เลือกช่วงเวลา</a> {% endcomment %}
</div>
</div>
</div>
<div class="col-4 ">
<a class="nav-link" href="{% url 'download' today_filename%}" id='download'>download</a>
</div>
</div>
</div>
<div class="container">
<div class='d-none' id="reportrange" style="background: #fff; cursor: pointer; padding: 5px 10px; border: 1px solid #ccc; max-width: 250px">
<i class="fa fa-calendar"></i>&nbsp;
<span></span>
<i class="fa fa-caret-down"></i>
</div>
</div>
<div class="px-5 mx-5">
<div class="px-5 mx-5 d-none" id='divChart'>
<div>
<canvas id="myChart"></canvas>
</div>
</div>
<table class="table" id='todayTable'>
<thead>
<tr>
<th onclick="sortTodayTable(0)" class='w-20'>รหัสสินค้า
{% comment %} <i class="bi bi-chevron-down"></i> {% endcomment %}
{% comment %} <i class="bi bi-chevron-up"></i> {% endcomment %}
</th>
<th onclick="sortTodayTable(1)" class='w-20'>ชื่อสินค้า</th>
<th onclick="sortTodayTable(2)" class='w-20'>ราคาขาย</th>
<th onclick="sortTodayTable(3)" class='w-20'>จำนวนการขาย</th>
<th onclick="sortTodayTable(4)" class='w-20'>มูลค่า</th>
</tr>
</thead>
<tbody>
{% for key,value in today.items %}
<tr>
<td> {{ value.id }} </td>
<td> {{ value.name }} </td>
<td> {{ value.price }} </td>
<td> {{ value.sold }} </td>
<td> {{ value.value }} </td>
</tr>
{% endfor %}
</tbody>
</table>
<table class="table d-none" id='weekTable'>
<thead>
<tr>
<th onclick="sortWeekTable(0)" class='w-20 p-0'>รหัสสินค้า</th>
<th onclick="sortWeekTable(1)" class='w-20 p-0'>ชื่อสินค้า</th>
<th onclick="sortWeekTable(2)" class='w-10 p-0'>ราคาขาย</th>
<th onclick="sortWeekTable(3)" class='w-10 p-0'>จำนวนการขาย</th>
<th onclick="sortWeekTable(4)" class='w-10 p-0'>มูลค่า</th>
<th onclick="sortWeekTable(5)" class='w-20 p-0'>จำนวนการขายเฉลี่ยต่อวัน</th>
<th onclick="sortWeekTable(6)" class='w-10 p-0'>มูลค่าเฉลี่ยต่อวัน</th>
</tr>
</thead>
<tbody>
{% for key,value in week.dataProduct.items %}
<tr>
<td> {{ value.id }} </td>
<td> {{ value.name }} </td>
<td> {{ value.price }} </td>
<td> {{ value.sold }} </td>
<td> {{ value.value }} </td>
<td> {{ value.soldperday}} </td>
<td> {{ value.valueperday }} </td>
</tr>
{% endfor %}
</tbody>
</table>
<table class="table d-none" id='monthTable'>
<thead>
<tr>
<th onclick="sortMonthTable(0)" class='w-20 p-0'>รหัสสินค้า
{% comment %} <i class="bi bi-chevron-down"></i> {% endcomment %}
{% comment %} <i class="bi bi-chevron-up"></i> {% endcomment %}
</th>
<th onclick="sortMonthTable(1)" class='w-20 p-0'>ชื่อสินค้า</th>
<th onclick="sortMonthTable(2)" class='w-10 p-0'>ราคาขาย</th>
<th onclick="sortMonthTable(3)" class='w-10 p-0'>จำนวนการขาย</th>
<th onclick="sortMonthTable(4)" class='w-10 p-0'>มูลค่า</th>
<th onclick="sortMonthTable(5)" class='w-20 p-0'>จำนวนการขายเฉลี่ยต่อวัน</th>
<th onclick="sortMonthTable(6)" class='w-10 p-0'>มูลค่าเฉลี่ยต่อวัน</th>
</tr>
</thead>
<tbody>
{% for key,value in month.dataProduct.items %}
<tr>
<td> {{ value.id }} </td>
<td> {{ value.name }} </td>
<td> {{ value.price }} </td>
<td> {{ value.sold }} </td>
<td> {{ value.value }} </td>
<td> {{ value.soldperday}} </td>
<td> {{ value.valueperday }} </td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.min.js"></script>
<script>
var atoday = $('<a class="dropdown-item" href="' + {% url 'dashboard' %} + '">ยอดรวมวันนี้</a>');
var tmpa = ''
var start = moment().subtract(1, 'months');
var end = moment();
function cb(start, end) {
$('#reportrange span').html(start.format('MMMM D, YYYY') + ' - ' + end.format('MMMM D, YYYY'));
}
$('#reportrange').daterangepicker({
startDate: start,
endDate: end,
}, cb);
cb(start, end);
function managebtnDropdown(element){
if (tmpa == ''){
$('#areaDropdown').append(atoday)
tmpa = element.cloneNode(true)
}else{
$('#areaDropdown').append(tmpa)
tmpa = element.cloneNode(true)
}
$('#dropdownMenuButton').text(element.innerHTML)
element.remove()
}
function setshow(element){
// data and hide table 4 column show table by id
console.log(element.id)
managebtnDropdown(element)
$('#todayTable').addClass('d-none')
$('table').each( function(){
var t = $(this);
var idChart = '#'+t.attr('id').replace('Table','Chart');
//console.log(idChart)
if(t.attr('id') == element.id+'Table'){
t.removeClass('d-none');
//$(idChart).removeClass('d-none');
if(element.id=='week'){
showChart(w_labels,w_data,w_avg)
$('#download').attr('href',"{% url 'download' last_week_filename%}")
}
if(element.id=='month'){
showChart(m_labels,m_data,m_avg)
$('#download').attr('href',"{% url 'download' last_month_filename%}")
}
}else{
t.addClass('d-none')
//$(idChart).addClass('d-none')
}
})
$('#'+element.id+'table').removeClass('d-none')
$("#reportrange").addClass('d-none')
}
function showOption(element){
managebtnDropdown(element)
$("#reportrange").removeClass('d-none')
}
function sortTodayTable(n){
sortTable('todayTable',n)
}
function sortWeekTable(n){
sortTable('weekTable',n)
}
function sortMonthTable(n){
sortTable('monthTable',n)
}
function sortTable(idTable,n) {
var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
table = document.getElementById(idTable);
switching = true;
$('.bi-chevron-down').remove();
$('.bi-chevron-up').remove();
//Set the sorting direction to ascending:
dir = "asc";
/*Make a loop that will continue until
no switching has been done:*/
while (switching) {
//start by saying: no switching is done:
switching = false;
rows = table.rows;
/*Loop through all table rows (except the
first, which contains table headers):*/
for (i = 1; i < (rows.length - 1); i++) {
//start by saying there should be no switching:
shouldSwitch = false;
/*Get the two elements you want to compare,
one from current row and one from the next:*/
x = rows[i].getElementsByTagName("TD")[n];
y = rows[i + 1].getElementsByTagName("TD")[n];
/*check if the two rows should switch place,
based on the direction, asc or desc:*/
if (dir == "asc") {
if (Number(x.innerHTML)) {
if (Number(x.innerHTML) > Number(y.innerHTML)) {
shouldSwitch = true;
break;
}
}else{
if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) {
//if so, mark as a switch and break the loop:
shouldSwitch = true;
break;
}
}
} else if (dir == "desc") {
if (Number(x.innerHTML)) {
if (Number(x.innerHTML) < Number(y.innerHTML)) {
shouldSwitch = true;
break;
}
}else{
if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) {
//if so, mark as a switch and break the loop:
shouldSwitch = true;
break;
}
}
}
}
if (shouldSwitch) {
/*If a switch has been marked, make the switch
and mark that a switch has been done:*/
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
switching = true;
//Each time a switch is done, increase this count by 1:
switchcount ++;
} else {
/*If no switching has been done AND the direction is "asc",
set the direction to "desc" and run the while loop again.*/
if (switchcount == 0 && dir == "asc") {
dir = "desc";
switching = true;
}else{
if (dir=='desc'){
rows[0].getElementsByTagName('th')[n].innerHTML += '<i class="bi bi-chevron-down"></i>'
}else{
rows[0].getElementsByTagName('th')[n].innerHTML += '<i class="bi bi-chevron-up"></i>'
}
}
}
}
}
var myChart = null;
function showChart(l,d,a){
const labels = l
const data = {
labels: labels,
datasets: [{
label: 'มูลค่าการขาย',
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)',
pointBackgroundColor:'rgb(0,0,255)',
data: d,
},{
label: 'มูลค่าการขายเฉลี่ย',
backgroundColor: 'rgb(204, 204, 204)',
//borderColor: 'rgb(0, 0, 255)',
pointBackgroundColor:'rgb(51,51,51)',
borderColor: 'rgb(51,51,51)',
fill: true,
data: a,
borderDashOffset:5,
borderDash:[10]
},]
};
const config = {
type: 'line',
data,
options: {}
};
try {
myChart = new Chart(
document.getElementById('myChart'),
config
);
}
catch(err) {
myChart.destroy();
myChart = new Chart(
document.getElementById('myChart'),
config
);
}
$('#divChart').removeClass('d-none')
}
const w_labels = {{week.labels|safe}};
const w_data = {{week.data}};
const w_avg = {{week.avgSoldValue}};
const m_labels = {{month.labels|safe}};
const m_data = {{month.data}};
const m_avg = {{month.avgSoldValue}};
</script>
{% endblock content %}
\ No newline at end of file
from django.test import TestCase
# Create your tests here.
from re import X
from xlsxwriter import workbook
import management
from time import sleep
from django.shortcuts import redirect, render
from datetime import date, datetime, timedelta
from pos.models import *
from management.models import Product
from django.contrib.auth.decorators import login_required
from management.permission_page import pos_manager_only
import xlsxwriter
import glob
from icecream import ic
# Create your views here.
# https://linuxhint.com/download-the-file-in-django/
import mimetypes
# import os module
import os
# Import HttpResponse module
from django.http.response import HttpResponse
def download_file(request, filename=''):
if filename == '':
filename = 'constFile/example_for_add_product.xlsx'
path = open(filename, 'rb')
# Set the mime type
mime_type, _ = mimetypes.guess_type(filename)
# Set the return value of the HttpResponse
response = HttpResponse(path, content_type=mime_type)
# Set the HTTP header for sending to browser
response['Content-Disposition'] = "attachment; filename=%s" % filename
# Return the response value
return response
@login_required
@pos_manager_only
def dashborad(req):
context=dict()
userlabel = str(req.user.id)+'_'+str(req.user)
print('------------------------------------xlsx file --------------------------------------------------')
for name in glob.glob('*.xlsx'):
print(name)
try:
if userlabel in name:
os.remove(name)
except:
print("can't delete filename:",name)
if req.method == 'POST':
#pick time range
print(req.POST)
context['mode'] = 'post'
else :
strnowtime = datetime.now().strftime("%Y%m%d%H%M%S")
labelfilexlsx = userlabel+'_'+strnowtime
today_filename = 'today_of_'+labelfilexlsx+'.xlsx'
last_week_filename = 'last_week_of_'+labelfilexlsx+'.xlsx'
last_month_filename = 'last_month_of_'+labelfilexlsx+'.xlsx'
context['today_filename'] = today_filename
context['last_week_filename'] = last_week_filename
context['last_month_filename'] = last_month_filename
context['today'] = billlistsNdays(filename=today_filename)
context['week'] = billlistinrange(date.today() - timedelta(days=7),date.today(),last_week_filename)
context['month'] = billlistinrange(date.today() - timedelta(days=30),date.today(),last_month_filename)
return render(req,'dashboard.html',context)
def billlistinrange(start,end,filename=''):
bills = Bill.objects.filter(created__gte=start).filter(created__lt=end)
data = dict()
soldValueInDay = dict()
dataset = dict()
nday = (end-start).days
sumSoldValue = 0
for i in bills:
listsInBill = BillList.objects.filter(bill=i)
datekey = i.created.strftime('%d/%m/%Y')
if soldValueInDay.get(datekey) == None : soldValueInDay[datekey] = 0
for j in listsInBill:
v = j.product.price * j.quantity
soldValueInDay[datekey] += v
sumSoldValue += v
if dataset.get(j.product.id) != None:
# print(dataset.get(j.product.id))
dataset[j.product.id]['sold']+=int(j.quantity)
else :
# id : autoincrement field in db
dataset[j.product.id] = {
'id':j.product.product_id,
'name':j.product.name,
'price':j.product.price,
'sold':j.quantity
}
if filename!='':
workbook = xlsxwriter.Workbook(filename)
sheet_by_day = workbook.add_worksheet('days')
sheet_by_product = workbook.add_worksheet('products')
columns_by_p = [
{'header':'id'},
{'header':'name'},
{'header':'price'},
{'header':'sold'},
{'header':'value'},
{'header':'sold/day'},
{'header':'value/day'},
]
columns_by_d = [
{'header':'day'},
{'header':'value'},
]
product_tableArea = 'A1:G'+str(len(dataset.keys())+1)
sheet_by_product.add_table(product_tableArea,{'columns':columns_by_p,'style':None})
row_counter = 2
for key in dataset.keys():
tmp = dataset[key]
val = tmp['price'] * tmp['sold']
tmp['value'] = val
tmp['soldperday'] = round(tmp['sold']/nday,2)
tmp['valueperday'] = round(val/nday,2)
dataset[key] = tmp
if filename!='':
cellstr = 'A'+str(row_counter)
sheet_by_product.write_row(cellstr,list(tmp.values()))
row_counter+=1
if filename!='':
keysol = list(soldValueInDay.keys())
day_tableArea = 'A1:B'+str(len(keysol)+1)
sheet_by_day.add_table(day_tableArea,{'columns':columns_by_d, 'style':None})
for i in range(len(keysol)) :
cellstr = 'A'+str(i+2)
sheet_by_day.write_row(cellstr,[keysol[i],soldValueInDay.get(keysol[i])])
workbook.close()
data['dataProduct'] = dataset
data['soldValueInDay'] = soldValueInDay
x_axis = []
y_axis = []
for i in range(nday):
k = (start+timedelta(days=i)).strftime('%d/%m/%Y')
x_axis.append(k)
y_axis.append(0) if soldValueInDay.get(k) == None else y_axis.append(float(soldValueInDay.get(k)))
data['avgSoldValue'] = [round(float(sumSoldValue)/nday,2)]*nday
data['labels'] = x_axis
data['data'] = y_axis
return data
def billlistsNdays(n=0,filename=''):
start_date = date.today() - timedelta(days=n)
bills = Bill.objects.filter(created__gte=start_date)
dataset = {}
for i in bills:
listsInBill = BillList.objects.filter(bill=i)
for j in listsInBill:
if dataset.get(j.product.id) != None:
# print(dataset.get(j.product.id))
dataset[j.product.id]['sold']+=int(j.quantity)
else :
# id : autoincrement field in db
dataset[j.product.id] = {
'id':j.product.product_id,
'name':j.product.name,
'price':j.product.price,
'sold':j.quantity
}
if filename!='':
workbook = xlsxwriter.Workbook(filename)
sheet = workbook.add_worksheet('products')
columns_table = [
{'header':'id'},
{'header':'name'},
{'header':'price'},
{'header':'sold'},
{'header':'value'}
]
tableArea = 'A1:E'+str(len(dataset.keys())+1)
sheet.add_table(tableArea,{'style':None,'columns':columns_table})
row_counter=2
for key in dataset.keys():
dataset[key]['value'] = dataset[key]['price'] * dataset[key]['sold']
if filename != '' :
cellstr = 'A'+str(row_counter)
sheet.write_row(cellstr,dataset[key].values())
if filename!='':
workbook.close()
return dataset
\ No newline at end of file
#!/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', 'webproject.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()
from django.contrib import admin
from .models import *
# Register your models here.
admin.site.register(Product)
admin.site.register(EmployeeUser)
admin.site.register(FileForSave)
admin.site.register(POSManager)
from django.apps import AppConfig
class ManagementConfig(AppConfig):
name = 'management'
from django import forms
from django.db.models import fields
from .models import Product #,EmployeeUser
from django.utils.translation import ugettext, ugettext_lazy as _
from pos.models import Bill
class FileForm(forms.Form):
docfile = forms.FileField(label='Select a file')
class ProductForm(forms.ModelForm):
class Meta:
model = Product
exclude = ['manager']
class BillForm(forms.ModelForm):
class Meta:
model = Bill
exclude = ['manager']
class EmployeeForm(forms.Form):
username = forms.CharField(label=_('username '), required=True)
password = forms.CharField(label=_('password '), required=True)
note = forms.CharField(label=_('note '), required=False)
class SendProductID(forms.Form):
pid = forms.CharField(required=False)
# Generated by Django 3.1.4 on 2021-04-16 01:10
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='FileForSave',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('docfile', models.FileField(upload_to='')),
],
),
migrations.CreateModel(
name='Manager',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('test', models.CharField(max_length=50)),
],
),
migrations.CreateModel(
name='Product',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('product_id', models.CharField(max_length=50)),
('name', models.CharField(max_length=50)),
('description', models.CharField(max_length=50)),
('price', models.DecimalField(decimal_places=2, max_digits=7)),
('quantity', models.IntegerField()),
('category', models.CharField(max_length=50)),
],
),
migrations.CreateModel(
name='SubUser',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('test', models.CharField(max_length=50)),
],
),
]
# Generated by Django 3.2 on 2021-04-16 07:14
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('management', '0001_initial'),
]
operations = [
migrations.DeleteModel(
name='Manager',
),
migrations.DeleteModel(
name='SubUser',
),
]
# Generated by Django 3.2 on 2021-04-17 07:59
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('management', '0002_auto_20210416_1414'),
]
operations = [
migrations.AddField(
model_name='product',
name='manager_username',
field=models.CharField(default=2, max_length=50),
preserve_default=False,
),
]
# Generated by Django 3.2 on 2021-04-21 13:33
import django.contrib.auth.models
import django.contrib.auth.validators
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
('management', '0003_product_manager_username'),
]
operations = [
migrations.CreateModel(
name='EmployeeUser',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('username', models.CharField(max_length=50)),
('password', models.CharField(max_length=15)),
('manager_username', models.CharField(max_length=50)),
],
),
migrations.CreateModel(
name='Manager',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
('email', models.EmailField(max_length=254, unique=True, verbose_name='email address')),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
],
options={
'verbose_name': 'user',
'verbose_name_plural': 'users',
'abstract': False,
},
managers=[
('objects', django.contrib.auth.models.UserManager()),
],
),
]
# Generated by Django 3.2 on 2021-04-21 13:51
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('management', '0004_employeeuser_manager'),
]
operations = [
migrations.DeleteModel(
name='Manager',
),
]
# Generated by Django 3.2 on 2021-04-24 04:49
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('management', '0005_delete_manager'),
]
operations = [
migrations.DeleteModel(
name='EmployeeUser',
),
migrations.AlterField(
model_name='product',
name='product_id',
field=models.CharField(max_length=50, unique=True),
),
]
# Generated by Django 3.2 on 2021-04-24 06:42
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('management', '0006_auto_20210424_1149'),
]
operations = [
migrations.CreateModel(
name='EmployeeUser',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('note', models.CharField(max_length=15)),
('manager_username', models.CharField(max_length=150)),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]
# Generated by Django 3.2 on 2021-04-24 07:36
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('management', '0007_employeeuser'),
]
operations = [
migrations.RenameField(
model_name='employeeuser',
old_name='manager_username',
new_name='create_by',
),
]
# Generated by Django 3.2 on 2021-04-24 07:39
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('management', '0008_rename_manager_username_employeeuser_create_by'),
]
operations = [
migrations.AlterField(
model_name='employeeuser',
name='id',
field=models.AutoField(primary_key=True, serialize=False),
),
]
# Generated by Django 3.2 on 2021-04-24 07:42
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('management', '0009_alter_employeeuser_id'),
]
operations = [
migrations.AlterField(
model_name='employeeuser',
name='id',
field=models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
]
# Generated by Django 3.2 on 2021-04-25 03:51
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('management', '0010_alter_employeeuser_id'),
]
operations = [
migrations.AlterField(
model_name='employeeuser',
name='create_by',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='Manager', to=settings.AUTH_USER_MODEL),
),
]
# Generated by Django 3.2 on 2021-04-25 03:54
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('management', '0011_alter_employeeuser_create_by'),
]
operations = [
migrations.AlterField(
model_name='employeeuser',
name='create_by',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to=settings.AUTH_USER_MODEL),
),
]
# Generated by Django 3.2 on 2021-04-25 03:58
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('management', '0012_alter_employeeuser_create_by'),
]
operations = [
migrations.AlterField(
model_name='employeeuser',
name='create_by',
field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to=settings.AUTH_USER_MODEL),
),
]
# Generated by Django 3.2 on 2021-04-25 04:11
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('management', '0013_alter_employeeuser_create_by'),
]
operations = [
migrations.AlterField(
model_name='employeeuser',
name='create_by',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='auth.user'),
),
]
# Generated by Django 3.2 on 2021-04-26 03:19
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('management', '0014_alter_employeeuser_create_by'),
]
operations = [
migrations.RemoveField(
model_name='product',
name='manager_username',
),
migrations.AddField(
model_name='product',
name='manager',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
]
# Generated by Django 3.2 on 2021-04-26 03:35
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('management', '0015_auto_20210426_1019'),
]
operations = [
migrations.AlterField(
model_name='employeeuser',
name='note',
field=models.CharField(max_length=50),
),
migrations.AlterField(
model_name='product',
name='manager',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.user'),
),
migrations.CreateModel(
name='Man',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('note', models.CharField(max_length=150)),
('create_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to=settings.AUTH_USER_MODEL)),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]
# Generated by Django 3.2 on 2021-05-03 06:26
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('management', '0016_auto_20210426_1035'),
]
operations = [
migrations.AlterField(
model_name='product',
name='product_id',
field=models.CharField(max_length=50),
),
migrations.AlterUniqueTogether(
name='product',
unique_together={('product_id', 'manager')},
),
migrations.DeleteModel(
name='Man',
),
]
# Generated by Django 3.2 on 2021-05-20 11:35
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('management', '0017_auto_20210503_1326'),
]
operations = [
migrations.CreateModel(
name='POSManager',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('shop', models.CharField(max_length=150)),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.urls import reverse
from django.contrib.auth.models import User,Group
from django.dispatch import receiver
from django.db.models.signals import post_save, pre_save,pre_delete
class FileForSave(models.Model):
docfile = models.FileField(upload_to='')
class EmployeeUser(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
note = models.CharField(max_length=50)
create_by = models.ForeignKey(User, on_delete=models.CASCADE,related_name='+')
def delete(self, *args, **kwargs):
self.user.delete()
return super(self.__class__, self).delete(*args, **kwargs)
def __str__(self):
return str(self.user)+' create_by '+str(self.create_by)
class POSManager(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
shop = models.CharField(max_length=150)
def delete(self, *args, **kwargs):
self.user.delete()
return super(self.__class__, self).delete(*args, **kwargs)
def __str__(self):
return str(self.user)+' manage '+str(self.shop)
class Product(models.Model):
product_id = models.CharField(max_length=50)
name = models.CharField(max_length=50)
description = models.CharField(max_length=50)
category = models.CharField(max_length=50)
price = models.DecimalField(max_digits=7,decimal_places=2)
quantity = models.IntegerField()
manager = models.ForeignKey(User, on_delete=models.CASCADE)
class Meta:
unique_together = (("product_id","manager"),)
def __str__(self):
return str(self.manager)+' create ' +str(self.product_id)+' '+self.name+' '+str(self.price)
def get_absolute_url(self):
return reverse("show_product")
@receiver(pre_save, sender=User)
def update_username_from_email(sender, instance, **kwargs):
if instance.username.lower()==instance.first_name.lower() and instance.email!=None and instance.email!='' :
user_email = instance.email
username = user_email[:30]
n = 1
while User.objects.exclude(pk=instance.pk).filter(username=username).exists():
n += 1
username = user_email[:(29 - len(str(n)))] + '-' + str(n)
instance.username = username
@receiver(post_save,sender=User)
def addGroupsManager(sender, instance, **kwargs):
if instance.groups.exists() == False:
group_manager = Group.objects.get(name='manager')
instance.groups.add(group_manager)
@receiver(post_save,sender=EmployeeUser)
def setGroupEmployeeDeleteGroupManager(sender,instance, **kwargs):
group_employee = Group.objects.get(name='employee')
instance.user.groups.add(group_employee)
group_manager = Group.objects.get(name='manager')
instance.user.groups.remove(group_manager)
# edit เมื่อทำหน้าสมัครเอง
if POSManager.objects.filter(user=instance.create_by).count()==0:
POSManager(user=instance.create_by).save()
\ No newline at end of file
from django.shortcuts import redirect,render
def pos_manager_only(view_func):
def wrapper_function(request, *args, **kwargs):
group = None
if request.user.groups.exists():
group = request.user.groups.all()[0].name
if group == 'manager':
print('managerrrrrrrrrrrrrrrrrrrrrrrr')
return view_func(request,*args, **kwargs)
else :
return redirect('GaMaiMeeSit')
return wrapper_function
# def allow_by_role(roles=[]):
# def decorator(view_f):
# def wrapper(request, *args, **kwargs):
# group = None
# if request.user.groups.exists():
# group = request.user.groups.all()[0].name
# if group in roles:
# print('group in role')
# return view_f(request,*args, **kwargs)
# else :
# return redirect('GaMaiMeeSit')
# return wrapper
# return decorator
def gamaimeesit(request):
return render(request,'gamaimeesit.html')
\ No newline at end of file
{% extends 'pos_base.html' %}
{% block content %}
{% include 'navbar.html' %}
<!-- check message -->
{% if message != '' %}
<div class="modal fade" id="show_message" tabindex="-1" role="dialog" aria-labelledby="exampleModalLongTitle" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-body">
{{message}}
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
</div>
</div>
</div>
{% endif %}
<!-- Modal product -->
<div class="modal fade" id="product_Modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">กรุณายืนยัน</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% comment %} <div class="modal-body">
...
</div> {% endcomment %}
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">ปิด</button>
<button type="button" class="btn btn-primary" onclick='document.getElementById("product_form").submit();'>เพิ่มสินค้า</button>
</div>
</div>
</div>
</div>
<!-- Modal upload file -->
<div class="modal fade" id="upload_file_Modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">กรุณายืนยัน</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% comment %} <div class="modal-body">
<p>
นอนยันการอัพโหลด
</p>
</div> {% endcomment %}
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">ปิด</button>
<button type="button" class="btn btn-primary" onclick='document.getElementById("upload_form").submit();'>อัพโหลด</button>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-lg-6 p-0">
<ul class="list-group">
<li class="list-group-item list-group-item-light ">
<h2>เพิ่มสินค้า 1 รายการ</h2>
</li>
<li class="list-group-item">
<form id='product_form' name='product_form' action="{% url "add_product" %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ product_form.as_p }}
</form>
<button class="btn btn-outline-success" data-toggle="modal" data-target="#product_Modal" >เพิ่มสินค้า</button>
</li>
</ul>
</div>
<div class="col-lg-6">
<ul class="list-group">
<li class="list-group-item list-group-item-info">
<h2>เพิ่มสินค้าโดยใช้ไฟล์ xlsx</h2>
</li>
<li class="list-group-item">
<a class="nav-link" href="{% url 'download' 'exampleAddProduct.xlsx'%}" id='download'>ตัวอย่างไฟล์</a>
<form id='upload_form' name='upload_form' action="{% url "add_product" %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<p>{{ upload_form.non_field_errors }}</p>
<p>{{ upload_form.docfile.label_tag }} {{ upload_form.docfile.help_text }}</p>
<p>
{{ upload_form.docfile.errors }}
<input class='btn p-0' type="file" name="docfile" required="" id="id_docfile">
</p>
</form>
<button name='summit_upload_form' class="btn btn-outline-success" data-toggle="modal" data-target="#upload_file_Modal">อัพโหลด</button>
</li>
</ul>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
<script type="text/javascript">
$(window).on('load', function() {
$('#show_message').modal('show');
});
</script>
{% endblock content %}
{% extends 'pos_base.html' %}
{% block content %}
<div class="container py-5">
<form align='center' action='.' method='POST'>{% csrf_token %}
<h5 class='text-primary'>ยืนยันการลบ</h5>
<p>
<b>รายการขาย สร้างเมื่อ</b> {{ object.created }} <b>บุคคลที่สร้าง</b> {{object.user}}
</p>
<button type="submit" class="btn btn-outline-danger mx-5" >ยืนยัน</button>
<a href='{% url "bills" %}'><button type="button" class="btn btn-outline-info mx-5" >ปิด</button></a>
</form>
</div>
{% endblock %}
\ No newline at end of file
{% extends 'pos_base.html' %}
{% block content %}
<div class="container py-5">
<form align='center' action='.' method='POST'>{% csrf_token %}
<h5 class='text-primary'>ยืนยันการลบ</h5>
<p>
<b>username</b> {{ object.user }} <b>note</b> {{object.note}}
</p>
<button type="submit" class="btn btn-outline-danger mx-5" >ยืนยัน</button>
<a href='{% url "show_product" %}'><button type="button" class="btn btn-outline-info mx-5" >ปิด</button></a>
</form>
</div>
{% endblock %}
\ No newline at end of file
{% extends 'pos_base.html' %}
{% block content %}
<div class="container py-5">
<form align='center' action='.' method='POST'>{% csrf_token %}
<h5 class='text-primary'>ยืนยันการลบ</h5>
<p>
สินค้ารหัส {{object.product_id}} ชื่อสินค้า {{object.name}}
</p>
<button type="submit" class="btn btn-outline-danger mx-5" >ยืนยัน</button>
<a href='{% url "show_product" %}'><button type="button" class="btn btn-outline-info mx-5" >ปิด</button></a>
</form>
</div>
{% endblock %}
\ No newline at end of file
{% extends 'pos_base.html' %}
{% block content %}
{% include 'navbar.html' %}
<div class="modal fade" id="product_Modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">กรุณายืนยัน</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">ปิด</button>
<button type="button" class="btn btn-primary" onclick='document.getElementById("product_form").submit();'>บันทึก</button>
</div>
</div>
</div>
</div>
<div class="container">
<form id='product_form'action='.' method='POST'>{% csrf_token %}
{{ form.as_p }}
</form>
<button class="btn btn-outline-success" data-toggle="modal" data-target="#product_Modal" >บันทึก</button>
</div>
{% endblock %}
\ No newline at end of file
{% extends 'pos_base.html' %}
{% block content %}
<h1>ไม่มีสิทธิ์เข้าถึงหน้านี้</h1>
<script>
window.onload = fiveSecondGoHomePage()
function fiveSecondGoHomePage(){
setTimeout(function(){
window.location.href = '{% url "home" %}'
}, 5000);
}
</script>
{% endblock content %}
\ No newline at end of file
{% extends 'pos_base.html' %}
{% block content %}
{% include 'navbar.html'%}
{% comment %} {{emps}} {% endcomment %}
<div class="container">
<form action="{% url "manage_employee" %}" method="post" class='text-center' >
{% csrf_token %}
{% comment %} &nbsp;&nbsp;&nbsp; {% endcomment %}
{{ sign_up_form }}
<button type='submit' >เพิ่ม</button>
</form>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th scope="col">username</th>
<th scope="col">Note</th>
<th scope='col' class='text-center'>ลบผู้ใช้</th>
</tr>
</thead>
<tbody>
{% for emp in emps %}
<tr>
<td >{{emp.username}} </td>
<td >{{emp.note}} </td>
<td scope='rowgroup' class='text-center'>
<a href='{% url "deleteemployee" emp.id %}'>
<button type="button" class="btn btn-small btn-outline-secondary" >
<i class="bi-trash"></i>
</button>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock content %}
{% extends 'pos_base.html' %}
{% block content %}
{% include 'navbar.html' %}
<div class="container">
<table class="table">
<thead>
<tr>
<th>เวลาที่สร้าง</th>
<th>สร้างโดย</th>
<th></th>
</tr>
</thead>
<tbody>
{% for i in bills%}
<tr>
<td scope="row">{{i.created}}</td>
<td>{{i.user}}</td>
<td><a href='{% url "deletebill" i.id %}'> <button type="button" class="btn btn-small btn-outline-secondary" ><i class="bi-trash"></i></button> </a></td>
</tr>
{% endfor %}
<tr>
<td scope="row"></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</div>
{% endblock content %}
\ No newline at end of file
{% extends 'pos_base.html' %}
{% block content %}
{% include 'navbar.html' %}
<div class="container d-lg-none">
<h1>
ขนาดของจอเล็กเกินไป
</h1>
</div>
<div class='container d-none d-lg-block mt-5'>
<a name="" id="" class="btn btn-lg btn-primary align-content-center" href="{% url 'add_product' %}" role="button">เพิ่มสินค้า</a>
{% comment %} <button class='btn btn-outline-info'> </button> {% endcomment %}
{% comment %} unable to sort data in table have to fix it? {% endcomment %}
<ul class="list-group list-group-flush">
<li class="list-group-item m-0 p-1 list-group-item-primary">
<div class="row">
<div class='col-lg-2 '>product id</div>
<div class='col-lg-2 '>name</div>
<div class='col-xl-2 d-lg-none d-xl-block '>description</div>
<div class='col-lg-2 col-xl-1 text-center'>price</div>
<div class='col-lg-2 col-xl-1 text-center'>quantity</div>
<div class='col-lg-2 text-center'>category</div>
<div class='col-lg-2 '>management</div>
</div>
</li>
{% for product in products %}
<li class="list-group-item m-0 p-1">
<div class="row">
<div class='col-lg-2 '>{{product.product_id}}</div>
<div class='col-lg-2 text-truncate'>{{product.name}}</div>
<div class='col-lg-2 d-lg-none d-xl-block'><p class='m-0'>{{product.description}}
{% comment %} ครับ สำหรับท่านที่เดินผ่านไปผ่านมานะครับ วันนี้ เฉาก๊วยชากังราวของเรานะครับ
ก็ได้มาบริการท่านพ่อแม่พี่น้องกันอีกแล้วครับ อากาศร้อนๆ อย่างนี้นะครับ
สำหรับท่านที่เดินผ่านไปผ่านมา ลองมาแวะชิมเฉาก๊วยแท้ๆ กันก่อนนะครับ
เฉาก๊วยชากังราวของเราเป็นที่รู้จักไปทั่ว {% endcomment %}
</p></div>
<div class='col-lg-2 col-xl-1 text-center'>{{product.price}}</div>
<div class='col-lg-2 col-xl-1 text-center'>{{product.quantity}}</div>
<div class='col-lg-2 text-center'>{{product.category}}</div>
<div class='col-lg-2 '>
{% comment %} <a href='{% url "edit_product" %}'> {% endcomment %}
<button type="button" class="btn btn-small btn-outline-secondary" onclick='to_edit_page({{product.id}})'><i class="bi-list"></i></button>
{% comment %} </a> {% endcomment %}
<button type="button" class="btn btn-small" disabled></button>
{% comment %} <button type="button" class="btn btn-small btn-outline-secondary" data-toggle="modal" data-target="#confirm_delete" onclick='savePIDforDELETE({{product.id}})'><i class="bi-trash"></i></button> {% endcomment %}
<a href='{% url "deleteproduct" product.id %}'> <button type="button" class="btn btn-small btn-outline-secondary" ><i class="bi-trash"></i></button> </a>
</div>
</div>
</li>
{% endfor %}
</ul>
</div>
<script>
console.log('hi');
function to_edit_page(pid){
window.location.href = '{% url "home" %}'+'management/editproduct/'+pid;
}
</script>
{% endblock %}
\ No newline at end of file
from django.test import TestCase
# Create your tests here.
from django import urls
from django.shortcuts import redirect, render,get_object_or_404
import os
from django.urls import reverse
from .models import FileForSave, POSManager,Product,EmployeeUser
from .forms import FileForm,EmployeeForm,ProductForm,SendProductID
import pandas as pd
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.views.generic.edit import UpdateView,DeleteView
from django.http import HttpResponseRedirect
from django.contrib.auth.decorators import login_required
from .permission_page import pos_manager_only
from pos.models import Bill,BillList
@login_required
@pos_manager_only
def show_bills(req):
context = dict()
manager = POSManager.objects.get(user=req.user)
context['bills'] = Bill.objects.filter(manager=manager).order_by('-created')
return render(req,'show_bills.html',context)
@login_required
@pos_manager_only
def show_products(request):
context = {}
context['products'] = Product.objects.filter(manager=request.user).order_by('quantity')
context['keepPID'] = SendProductID()
return render(request,'show_product.html',context)
class BillDeleteView(DeleteView):
template_name = 'delete_bill.html'
def get_object(self):
id_ = self.kwargs.get("id")
return get_object_or_404(Bill, id=id_)
def delete(self, request, *args, **kwargs):
self.object = self.get_object()
success_url = self.get_success_url()
print(success_url)
self.object.delete()
success_url = self.get_success_url()
return HttpResponseRedirect(success_url)
def get_success_url(self):
return reverse('bills',kwargs=None)
@login_required
@pos_manager_only
def add_product(request):
message = ''
file_form = FileForm()
product_form = ProductForm()
if request.method == 'POST':
file_form = FileForm(request.POST, request.FILES)
product_form = ProductForm(request.POST)
if file_form.is_valid():
newdoc = FileForSave(docfile=request.FILES['docfile'])
newdoc.save()
try:
df = pd.read_excel (newdoc.docfile)
for i in df.values:
i = i.tolist()
for j in i:
print(type(j),end=' ')
print()
try:
product = Product.objects.get(manager=request.user,product_id=i[0])
product.quantity+=i[4]
product.save()
except:
try:
instance_product = Product(
product_id=str(i[0],),
name=i[1],
description=i[2],
price=i[3],
quantity=i[4],
category=i[5],
manager=request.user)
instance_product.save()
print(post_save(sender=Product,instance=instance_product))
except:
print('*--try level 3 error--* new_instance_product error')
print('*--try level 2 error--* no this product')
except:
print('*--try level 1 error--*')
message = 'เกิดข้อผิดพลาด'
allFile = FileForSave.objects.all()
for i in allFile:
f_path = i.docfile.path
try:
os.remove(f_path)
print(f_path+' deleted')
i.delete()
except:
print("can't delete "+f_path)
return redirect('show_product')
elif product_form.is_valid():
rp = request.POST
instance_product = Product(
product_id=rp.get('product_id'),
name=rp.get('name'),
description=rp.get('description'),
price=rp.get('price'),
quantity=rp.get('quantity'),
category=rp.get('category'),
manager=request.user)
instance_product.save()
return redirect('show_product')
else:
message = 'กรุณากรอกข้อมูลกรอกข้อมูล'
context = {'upload_form': file_form, 'message': message}
context['product_form']=product_form
return render(request, 'add_product.html', context)
@login_required
@pos_manager_only
def manage_employee(request):
sign_up_form = EmployeeForm()
if request.method == 'POST':
form = EmployeeForm(request.POST, request.FILES)
if form.is_valid():
user = User.objects.create(username=request.POST['username'])
user.set_password(raw_password=request.POST['password'])
user.save()
employee = EmployeeUser(user=user,create_by=request.user,note=request.POST['note'])
employee.save()
return redirect('manage_employee')
employees = EmployeeUser.objects.filter(create_by=request.user).values()
employees2 = []
for i in employees:
employees2.append({
'username':User.objects.get(id=i['user_id']).username,
'note':i['note'],
'id':i['id']
})
return render(request,'manage_employee.html',{'sign_up_form':sign_up_form,'emps':employees2,'emp1':employees})
@login_required
@pos_manager_only
def edit_product(request):
print('in function edit product ')
if request.method == 'POST':
print(request.POST)
context = {}
return render(request, 'edit_product.html' ,context)
else :
return redirect('show_product')
class ProductUpdateView(UpdateView):
model = Product
form_class = ProductForm
template_name = 'edit_product.html'
def get_object(self):
id_ = self.kwargs.get("id")
return get_object_or_404(Product, id=id_)
def form_valid(self, form):
return super().form_valid(form)
class ProductDeleteView(DeleteView):
template_name = "delete_product.html"
def get_object(self):
id_ = self.kwargs.get("id")
print(get_object_or_404(Product, id=id_))
return get_object_or_404(Product, id=id_)
def delete(self, request, *args, **kwargs):
self.object = self.get_object()
manager = User.objects.get(id = self.object.manager_id)
success_url = self.get_success_url()
if request.user == manager:
success_url = self.get_success_url()
print('delete ok')
self.object.delete()
else:
print("you don't have permission")
return HttpResponseRedirect(success_url)
def get_success_url(self):
return reverse('show_product',kwargs=None)
class EmployeeDeleteView(DeleteView):
template_name = "delete_employee.html"
def get_object(self):
id_ = self.kwargs.get("id")
return get_object_or_404(EmployeeUser, id=id_ )
def delete(self, request, *args, **kwargs):
self.object = self.get_object()
self.object.delete()
success_url = self.get_success_url()
return HttpResponseRedirect(success_url)
def get_success_url(self):
return reverse('manage_employee',kwargs=None)
from django.contrib import admin
from .models import *
# Register your models here.
admin.site.register(BillList)
admin.site.register(Bill)
admin.site.register(FeaturePic)
\ No newline at end of file
from django.apps import AppConfig
class PosConfig(AppConfig):
name = 'pos'
# Generated by Django 3.2 on 2021-04-26 03:19
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('management', '0015_auto_20210426_1019'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Transaction',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('quantity', models.IntegerField()),
('created', models.DateTimeField(auto_now_add=True)),
('product', models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, to='management.product')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, to=settings.AUTH_USER_MODEL)),
],
),
]
# Generated by Django 3.2 on 2021-05-20 11:35
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('management', '0018_posmanager'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('pos', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='transaction',
name='created',
),
migrations.RemoveField(
model_name='transaction',
name='user',
),
migrations.CreateModel(
name='Order',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True)),
('manager', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='management.posmanager')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, to=settings.AUTH_USER_MODEL)),
],
options={
'unique_together': {('created', 'user')},
},
),
]
# Generated by Django 3.2 on 2021-05-20 11:37
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('pos', '0002_auto_20210520_1835'),
]
operations = [
migrations.AddField(
model_name='transaction',
name='order',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='pos.order'),
),
]
# Generated by Django 3.2 on 2021-05-20 11:38
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('pos', '0003_transaction_order'),
]
operations = [
migrations.AlterField(
model_name='transaction',
name='order',
field=models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, to='pos.order'),
),
]
# Generated by Django 3.2 on 2021-06-11 04:00
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('management', '0018_posmanager'),
('pos', '0004_alter_transaction_order'),
]
operations = [
migrations.CreateModel(
name='BillList',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('quantity', models.IntegerField()),
],
),
migrations.RenameModel(
old_name='Order',
new_name='Bill',
),
migrations.DeleteModel(
name='Transaction',
),
migrations.AddField(
model_name='billlist',
name='bill',
field=models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, to='pos.bill'),
),
migrations.AddField(
model_name='billlist',
name='product',
field=models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, to='management.product'),
),
]
# Generated by Django 3.2 on 2021-09-01 06:12
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pos', '0005_auto_20210611_1100'),
]
operations = [
migrations.CreateModel(
name='FeaturePic',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('urlPic', models.TextField()),
],
),
migrations.AlterField(
model_name='bill',
name='created',
field=models.DateTimeField(),
),
]
from django.db import models
from django.db.models.constraints import UniqueConstraint
from management.models import Product,POSManager
from django.contrib.auth.models import User
from django.dispatch import receiver
from django.db.models.signals import post_save, pre_save,pre_delete
import pytz
class Bill(models.Model):
created = models.DateTimeField(editable=True)
user = models.ForeignKey(User,on_delete=models.RESTRICT)
manager = models.ForeignKey(POSManager,on_delete=models.CASCADE)
class Meta:
unique_together = (("created","user"),)
def __str__(self):
return str(self.user.username)+' : '+str(self.created.astimezone(pytz.timezone('Asia/Bangkok')))
class BillList(models.Model):
product = models.ForeignKey(Product,on_delete=models.RESTRICT)
quantity = models.IntegerField()
bill = models.ForeignKey(Bill,on_delete=models.CASCADE,blank=True)
def __str__(self):
return str(self.product.name)+' '+str(self.quantity)
class FeaturePic(models.Model):
urlPic = models.TextField()
@receiver(pre_delete,sender=BillList)
def role_back_product_from_billlist(sender, instance ,**kwargs):
iproduct = Product.objects.get(id=instance.product.id)
iproduct.quantity += int(instance.quantity)
iproduct.save()
\ No newline at end of file
{% extends 'pos_base.html' %}
{% block tailhead %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<style>
/* Make the image fully responsive */
.carousel-inner img {
width: 100%;
height: 100%;
}
.carousel .carousel-indicators li.active {background-color: blue;}
</style>
{% endblock tailhead %}
{% block content %}
{% include 'navbar.html' %}
{% comment %} <h1>home page</h1> {% endcomment %}
<div class="container">
<h1>Feature</h1>
<div id="demo" class="carousel slide" data-ride="carousel">
<!-- Indicators -->
<ul class="carousel-indicators">
{% for i in featurePic %}
{% if forloop.counter == 1 %}
<li data-target="#demo" data-slide-to="{{forloop.counter}}"
class="active"
></li>
{% else %}
<li data-target="#demo" data-slide-to="{{forloop.counter}}"
></li>
{% endif %}
{% endfor %}
</ul>
<!-- The slideshow -->
<div class="carousel-inner">
{% for pic in featurePic %}
{% if forloop.counter == 1 %}
<div class="carousel-item active" data-interval='5000'>
<img src="{{pic.0}}" >
</div>
{% else %}
<div class="carousel-item">
<img src="{{pic.0}}" >
</div>
{% endif %}
{% endfor %}
</div>
<!-- Left and right controls -->
<a class="carousel-control-prev" href="#demo" data-slide="prev">
<span class="carousel-control-prev-icon"></span>
</a>
<a class="carousel-control-next" href="#demo" data-slide="next">
<span class="carousel-control-next-icon"></span>
</a>
</div>
</div>
{% endblock content %}
{% load socialaccount %}
<html>
<head>
<title>Google Registration</title>
</head>
<body>
{% if user.is_authenticated %}
<p>Welcome, {{ user.get_full_name }} !</p>
{% else %}
<h1>My Google Login Project</h1>
<a href="{% provider_login_url 'google' %}">Login with Google</a>
{% endif %}
</body>
</html>
\ No newline at end of file
<nav class="navbar navbar-expand-lg navbar-light bg-light">
{% if user.is_authenticated %}
{% else %}
<a class="navbar-brand" href="{% url 'home' %}">Home </a>
{% endif %}
<button class="navbar-toggler" type="button" data-toggle="collapse" data-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 mr-auto">
<li class="nav-item " id='pos_a'>
<a class="nav-link" href="{% url 'pos' %}">POS
{% comment %} <span class="sr-only">(current)</span> {% endcomment %}
</a>
</li>
<li class="nav-item" id='product_a'>
<a class="nav-link" href="{% url 'show_product' %}">Product</a>
</li>
<li class="nav-item " id='pos_a'>
<a class="nav-link" href="{% url 'dashboard' %}">Dashboard
</a>
</li>
<li class="nav-item " id='pos_a'>
<a class="nav-link" href="{% url 'bills' %}">Bills
</a>
</li>
<li class="nav-item " id='pos_a'>
<a class="nav-link" href="{% url 'manage_employee' %}">Employee
</a>
</li>
</ul>
{% if user.is_authenticated %}
<a>Welcome, {{ user.get_full_name }} ! </a>
&nbsp;
<a href='/accounts/logout/' ><button class="btn my-2 my-sm-0 btn-outline-secondary" >logout</button></a>
{% else %}
<a href='/accounts/login/' ><button class="btn my-2 my-sm-0 btn-success" >login</button></a>
{% endif %}
</div>
</nav>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css"
integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.4.1/font/bootstrap-icons.css">
<title>{% block title %}{% endblock title %}</title>
{% block css %}{% endblock css %}
{% block tailhead %}{% endblock tailhead %}
</head>
<body>
{% comment %} {% include 'navbar.html' %} {% endcomment %}
{% block content %}
{% endblock %}
<script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk="
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"
integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.min.js"
integrity="sha384-+YQ4JLhjyBLPDQt//I+STsc9iw4uQqACwlvpslubQzn4u2UU2UFM80nGisd026JF" crossorigin="anonymous"></script>
</body>
</html>
\ No newline at end of file
{% extends 'pos_base.html' %}
{% block css %}
<style>
.collapsing {
-webkit-transition: none;
transition: none;
display: none;
}
</style>
{% endblock css %}
ิิิ{%block content%}
{% include 'navbar.html' %}
<div class='row mx-2'>
<div class="col-md-8">
<div class="list-group-item list-group-item-action active d-flex flex-row" aria-current="true" disabled>
<div>
<a class='text-dark' role="button" onclick='removeShowProduct()' id='headerProductCate' >
ประเภทสินค้า
</a>
</div>
<div class='ml-1 p-0 collapse multi-collapse text-dark col-6' id='headerProduct'>
> สินค้า
</div>
</div>
<div class="d-flex flex-wrap overflow-auto" id='productCate'>
{% for i in productCate %}
<div class="w-33 btn align-content-center bd-highlight col-md-4 col-sm-6 col-6">
<button type="button" class="btn btn-outline-info btn-lg btn-block text-truncate" onclick='showProduct({{forloop.counter0}})'
data-toggle="collapse"
data-target=".multi-collapse"
aria-expanded="false" aria-controls="headerProduct selectProduct"
>
{{i}}
</button>
</div>
{% endfor %}
</div>
<div class="collapse multi-collapse overflow-auto" id='selectProduct'>
</div>
</div>
<div class='col-md-4 '>
<div type="button" class="list-group-item list-group-item-action active " aria-current="true" >
สรุปรายการ
<a href='{% url "pos" %}' class='btn btn-primary py-0 my-0 px-1 float-right' style='border-radius: 13px; '>
<i class="bi bi-bootstrap-reboot"></i>
</a>
</div>
<ul class='list-group ' id='list_selected_products'>
</ul>
</div>
</div>
<footer>
<div class=" pt-4 border-bottom " >
<div class="col-md-12 bg-secondary" id='footerBar' style='position: absolute;bottom: 0;width: 100%;'>
<div class="py-1 d-flex justify-content-end align-items-right " >
<span class='pr-3'><h1 id='priceShow'></h1></span>
<button type="submit" id='saveOrderBtn' name='saveOrderBtn' class="btn btn-outline-secondary btn-lg" onclick='saveOrder()' disabled>Submit</button>
</div>
</div>
</div>
</footer>
<div class="container d-none">
<form id='sendOrder_form' name='sendOrder_form' action="{% url "pos" %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
</form>
</div>
<script>
var productsById = {{ productsById|safe }};
var products = {{ productDict|safe }};
var categories = {{ productCate|safe }} ;
var indexCategory = ''
var productInCate = {}
var selectedProducts= {} // { productId : quantity}
var sortSelectedProduct = [] // [productId]
console.log(products,categories);
function showProduct(indexCate){
productInCate = {}
var selectProduct = document.getElementById("selectProduct");
selectProduct.innerHTML = ''
indexCategory = indexCate;
for(let i of products[categories[indexCate]]){
productInCate[i.id]=i
var divProduct = document.createElement('div');
divProduct.setAttribute('class',"w-33 btn align-content-center bd-highlight col-md-4 col-sm-6 col-6");
var buttonProduct = document.createElement('button');
buttonProduct.setAttribute('class',"btn btn-outline-info btn-lg btn-block text-truncate ");
buttonProduct.setAttribute('type','button');
buttonProduct.setAttribute('onclick','addProduct('+ i.id +')');
buttonProduct.innerHTML=i.name+'<br>'+i.price+'<br>'+i.quantity;
if(i.quantity<=0){
console.log('quantity == 0',i)
buttonProduct.setAttribute('class',"btn btn-outline-secondary btn-lg btn-block text-truncate ");
buttonProduct.disabled = true;
}
divProduct.appendChild(buttonProduct);
selectProduct.appendChild(divProduct);
}
products[categories[indexCate]]
console.log(products[categories[indexCate]],categories[indexCate])
$('#productCate').addClass("disabled").hide();
$('#productCate').removeClass("d-flex flex-wrap");
$('#selectProduct').addClass("d-flex flex-wrap");
$('#headerProductCate').removeClass('text-dark');
$('#headerProductCate').addClass('text-white');
}
function removeShowProduct(){
$('#headerProductCate').removeClass('text-white');
$('#headerProductCate').addClass('text-dark');
$('#selectProduct').collapse('hide')
$('#headerProduct').collapse('hide')
$('#selectProduct').removeClass("d-flex flex-wrap");
$('#productCate').addClass("d-flex flex-wrap");
}
function createDivSelectedBtn(productID){
var divProductName = $('<div class="d-inline-flex p-2 align-self-center">'+productsById[productID].name+'</div>');
var divGroupButton = $('<div class=" btn-group float-right" role="group" aria-label="Basic example"></div>');
var btnPlus = $('<button type="button" class="btn btn-small btn-light" onclick=addProduct('+ productID.toString() +')><i class="bi-plus-circle" ></i></button>');
var btnDash = $('<button type="button" class="btn btn-small btn-light" onclick=decreaseProduct('+ productID.toString() +')><i class="bi-dash-circle" ></i></button>');
var btnTrash = $('<button type="button" class="btn btn-small btn-light" onclick=removeSelected('+ productID.toString() +') ><i class="bi-trash" ></i></button>');
if(selectedProducts[productID]==1){
console.log('== 1')
btnDash = $('<button type="button" class="btn btn-small btn-light" disabled><i class="bi-dash-circle"></i></button>');
}
if(selectedProducts[productID]>=productsById[productID].quantity){
console.log('max')
btnPlus = $('<button type="button" class="btn btn-small btn-light" disabled><i class="bi-plus-circle"></i></button>');
}
var btnProductQuantity = $('<button type="button" class="btn btn-small btn-light" disabled>'+selectedProducts[productID]+'</button>');
var liProduct = $('<li class="list-group-item"></li>')
divGroupButton.append(btnPlus,btnProductQuantity,btnDash,btnTrash);
liProduct.append(divProductName,divGroupButton);
return liProduct
}
function onChangeSelectedProducts(){
if(sortSelectedProduct.length > 0){
var submitBtn = document.getElementById('saveOrderBtn');
submitBtn.setAttribute('class',"btn-lg btn btn-outline-light");
submitBtn.disabled = false;
document.getElementById('footerBar').setAttribute('class'," pt-1 border-bottom bg-primary")
}else{
var submitBtn = document.getElementById('saveOrderBtn');
submitBtn.setAttribute('class',"btn-lg btn btn-outline-secondary");
submitBtn.disabled = true;
document.getElementById('footerBar').setAttribute('class'," pt-1 border-bottom bg-secondary")
}
var sumPrice = 0;
$('#list_selected_products').empty();
sortSelectedProduct.forEach(productID => {
sumPrice+= productsById[productID].price * selectedProducts[productID];
createDivSelectedBtn(productID).appendTo('#list_selected_products');
})
if(sumPrice > 0){
$('#priceShow').text(sumPrice);
}else{
document.getElementById('priceShow').innerHTML='';
}
}
function decreaseProduct(productID){
selectedProducts[productID] -= 1
onChangeSelectedProducts()
}
function removeSelected(productID){
delete selectedProducts[productID];
const index = sortSelectedProduct.indexOf(productID);
if (index > -1) {
sortSelectedProduct.splice(index, 1);
}
onChangeSelectedProducts();
}
function addProduct(productID){
if(selectedProducts[productID]){
if(selectedProducts[productID]<productsById[productID].quantity){
selectedProducts[productID] += 1
onChangeSelectedProducts()
}else if(selectedProducts[productID]=productsById[productID].quantity){
alert('สินค้ามีเพียงเท่านี้')
}
console.log(selectedProducts)
}else{
sortSelectedProduct.push(productID)
selectedProducts[productID] = 1
onChangeSelectedProducts()
}
}
function saveOrder(){
for(const i in selectedProducts){
$('<input type="hidden" name="list_productID" value="'+i+'" />').appendTo('#sendOrder_form');
$('<input type="hidden" name="list_productQuantity" value="'+ selectedProducts[i] +'" />').appendTo('#sendOrder_form');
}
return $('#sendOrder_form').submit();
}
</script>
{%endblock%}
from django.test import TestCase
# Create your tests here.
import django
from django.db.models.manager import Manager
from pos.models import Bill, BillList, FeaturePic
from django import dispatch
from django.shortcuts import redirect, render
from management.models import EmployeeUser, POSManager, Product
import json
from allauth.account.forms import LoginForm
from django.views.decorators.csrf import csrf_protect
from django.contrib.auth import authenticate,login,logout
from django.contrib.auth.decorators import login_required
from datetime import *
import pytz
# from management.permission_page import allow_by_role
django.utils.timezone.activate(pytz.timezone('Asia/Bangkok'))
# https://stackoverflow.com/questions/21925671/convert-django-model-object-to-dict-with-all-of-the-fields-intact
from itertools import chain
def to_dict(instance):
opts = instance._meta
data = {}
for f in chain(opts.concrete_fields, opts.private_fields):
if f.name == 'price' :
data[f.name] = str(f.value_from_object(instance))
else:
data[f.name] = f.value_from_object(instance)
for f in opts.many_to_many:
data[f.name] = [i.id for i in f.value_from_object(instance)]
return data
# Create your views here.
@login_required
# @allow_by_role(roles=['manager','employee'])
def pos_page(req):
mgr_user = None
if req.user.groups.filter(name = 'manager').exists():
mgr_user = POSManager.objects.get(user=req.user)
else :
emp_user = EmployeeUser.objects.get(user=req.user)
mgr_user = POSManager.objects.get(emp_user.create_by)
if req.method == 'POST':
list_productId = req.POST.getlist('list_productID')
list_productQuantity = req.POST.getlist('list_productQuantity')
bill = Bill(
created=datetime.now(),
user=req.user,
manager=mgr_user)
bill.save()
for i in range(len(list_productId)):
iproduct = Product.objects.get(id=list_productId[i])
iproduct.quantity -= int(list_productQuantity[i])
iproduct.save()
BillList(
product=Product.objects.get(id=list_productId[i]),
quantity=list_productQuantity[i],
bill=bill
).save()
return redirect('pos')
productCategory = Product.objects.filter(manager=mgr_user.user).values_list('category').distinct()
productsById = dict()
productCategory = [i[0] for i in productCategory]
productDict = {}
for i in productCategory :
k = Product.objects.filter(category=i,manager=req.user)
kl = []
for j in list(k):
kl.append(to_dict(j))
productsById[j.id] = to_dict(j)
productDict[i]=kl
return render(req,'pos_page.html',{'productCate':productCategory,'productDict':productDict,'productsById':productsById})
@csrf_protect
def home(req):
login_form = LoginForm()
mgr_user = None
if req.user.groups.filter(name = 'manager').exists():
try:
mgr_user = POSManager.objects.get(user=req.user)
except:
POSManager(user=req.user).save()
# if req.user.is_authenticated:
# # Do something for authenticated users.
# print('logining')
# else:
# if req.method == 'POST':
# form = LoginForm(req.POST, req.FILES)
# if form.is_valid():
# print(req.POST)
# print(req.POST['login'],req.POST['password'])
# user = authenticate(username=req.POST['login'], password=req.POST['password'])
# if user is not None:
# login(req,user)
# print('login have user')
# # user.lo
# # A backend authenticated the credentials
# else:
# print('nope')
# # No backend authenticated the credentials
# # username = req.FILES['']
# # password =
# # newdoc.save()
# # print(request.FILES['docfile'])
# # print(newdoc.docfile)
# # Redirect to the document list after POST
# # return redirect('test')
# else:
# message = 'The form is not valid. Fix the following error:'
# print(message)
# else:
# print('ไม่มีpost')
# # Do something for anonymous users.
featurePic = FeaturePic.objects.all().values_list('urlPic')
return render(req,'home.html',{'login_form':login_form,'featurePic':featurePic})
Django==3.2
django_allauth==0.44.0
icecream==2.1.1
pandas==1.2.4
pytz==2021.1
XlsxWriter==1.4.3
"""
ASGI config for webproject 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/3.1/howto/deployment/asgi/
"""
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'webproject.settings')
application = get_asgi_application()
"""
Django settings for webproject project.
Generated by 'django-admin startproject' using Django 3.1.4.
For more information on this file, see
https://docs.djangoproject.com/en/3.1/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.1/ref/settings/
"""
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/3.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '4yqfy+!(tt&!@ock$38c=aj1fe)$#kz&k29ef+kx%&@z&(5mvs'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'pos','dashboard','management',
'django.contrib.sites',
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.google',
'django_extensions',
]
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 = 'webproject.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': ['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 = 'webproject.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Password validation
# https://docs.djangoproject.com/en/3.1/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/3.1/topics/i18n/
LANGUAGE_CODE = 'en-us'
# TIME_ZONE = 'UTC'
TIME_ZONE = 'Asia/Bangkok'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/
STATIC_URL = '/static/'
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
# AUTH_USER_MODEL = 'management.Manager'
SITE_ID = 1
# ACCOUNT_USER_MODEL_USERNAME_FIELD = 'email'
# ACCOUNT_EMAIL_REQUIRED = True
# ACCOUNT_USERNAME_REQUIRED = False
# ACCOUNT_SIGNUP_PASSWORD_ENTER_TWICE = False
# ACCOUNT_SESSION_REMEMBER = True
# ACCOUNT_AUTHENTICATION_METHOD = 'email'
# ACCOUNT_UNIQUE_EMAIL = True
LOGIN_REDIRECT_URL = '/'
ACCOUNT_LOGOUT_REDIRECT_URL ="/"
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'allauth.account.auth_backends.AuthenticationBackend',
)
SOCIALACCOUNT_PROVIDERS = {
'google': {
'SCOPE': [
'profile',
'email',
],
'AUTH_PARAMS': {
'access_type': 'online',
}
}
}
"""webproject URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/3.1/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 pos import views as pos_views
from management import views as management_views
from management import permission_page as pp
from dashboard import views as dashboard_views
urlpatterns = [
path('admin/', admin.site.urls,name='admin'),
path('pos/',pos_views.pos_page,name='pos'),
path('', pos_views.home,name='home'),
path('accounts/', include('allauth.urls')),
path('management/employee/',management_views.manage_employee,name='manage_employee'),
path('management/addproduct/',management_views.add_product,name='add_product'),
path('management/product/',management_views.show_products,name='show_product'),
path('management/editproduct/<int:id>/', management_views.ProductUpdateView.as_view(), name='editproduct'),
path('management/deleteproduct/<int:id>/', management_views.ProductDeleteView.as_view(), name='deleteproduct'),
path('management/deleteemployee/<int:id>/', management_views.EmployeeDeleteView.as_view(), name='deleteemployee'),
path('gamaimeesit/',pp.gamaimeesit,name='GaMaiMeeSit'),
path('dashboard/',dashboard_views.dashborad,name='dashboard'),
path('download/<str:filename>/',dashboard_views.download_file,name='download'),
path('management/bills/',management_views.show_bills,name='bills'),
path('management/deletebill/<int:id>/',management_views.BillDeleteView.as_view(),name='deletebill'),
]
"""
WSGI config for webproject 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/3.1/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'webproject.settings')
application = get_wsgi_application()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment