Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
AE UTBM
Sith
Commits
dbf0653b
Commit
dbf0653b
authored
Aug 20, 2016
by
Skia
🤘
Browse files
Add support for product buying groups + many cosmetics and form pimping
parent
00f05c71
Pipeline
#130
failed with stage
in 2 minutes and 9 seconds
Changes
19
Pipelines
1
Expand all
Hide whitespace changes
Inline
Side-by-side
core/lookups.py
View file @
dbf0653b
from
ajax_select
import
register
,
LookupChannel
from
core.views.site
import
search_user
from
core.models
import
User
from
core.models
import
User
,
Group
from
club.models
import
Club
from
counter.models
import
Product
,
Counter
@
register
(
'users'
)
...
...
@@ -17,6 +18,32 @@ class UsersLookup(LookupChannel):
def
format_item_display
(
self
,
item
):
return
item
.
get_display_name
()
@
register
(
'groups'
)
class
GroupsLookup
(
LookupChannel
):
model
=
Group
def
get_query
(
self
,
q
,
request
):
return
self
.
model
.
objects
.
filter
(
name__icontains
=
q
)[:
50
]
def
format_match
(
self
,
obj
):
return
obj
.
name
def
format_item_display
(
self
,
item
):
return
item
.
name
@
register
(
'clubs'
)
class
ClubLookup
(
LookupChannel
):
model
=
Club
def
get_query
(
self
,
q
,
request
):
return
self
.
model
.
objects
.
filter
(
name__icontains
=
q
)[:
50
]
def
format_match
(
self
,
obj
):
return
obj
.
name
def
format_item_display
(
self
,
item
):
return
item
.
name
@
register
(
'counters'
)
class
CountersLookup
(
LookupChannel
):
model
=
Counter
...
...
core/models.py
View file @
dbf0653b
...
...
@@ -368,7 +368,7 @@ class User(AbstractBaseUser):
<em>%s</em>
</a>
"""
%
(
self
.
profile_pict
.
get_download_url
()
if
self
.
profile_pict
else
staticfiles_storage
.
url
(
"core/img/
na.gif
"
),
self
.
profile_pict
.
get_download_url
()
if
self
.
profile_pict
else
staticfiles_storage
.
url
(
"core/img/
unknown.jpg
"
),
_
(
"Profile"
),
escape
(
self
.
get_display_name
()),
)
...
...
core/static/core/img/unknown.jpg
0 → 100644
View file @
dbf0653b
48.8 KB
core/static/core/img/yug.jpg
0 → 100644
View file @
dbf0653b
53.6 KB
core/static/core/style.css
View file @
dbf0653b
...
...
@@ -183,10 +183,10 @@ tbody>tr:hover {
}
#user_profile
h4
{
border-bottom
:
1px
solid
grey
;
max-width
:
60%
;
}
#user_profile
#left_column
{
max-
width
:
59%
;
width
:
59%
;
}
#user_profile
#right_column
{
max-
width
:
40%
;
width
:
40%
;
float
:
right
;
font-style
:
italic
;
}
...
...
core/templates/core/base.jinja
View file @
dbf0653b
...
...
@@ -25,7 +25,7 @@
<a
href=
"
{{
url
(
'core:user_tools'
)
}}
"
>
{%
trans
%}
Tools
{%
endtrans
%}
</a>
|
<a
href=
"
{{
url
(
'core:logout'
)
}}
"
>
{%
trans
%}
Logout
{%
endtrans
%}
</a>
<form
action=
"
{{
url
(
'core:search'
)
}}
"
method=
"GET"
>
<input
type=
"text"
placeholder=
"
{%
trans
%}
Search
{%
endtrans
%}
"
name=
"query"
/>
<input
type=
"text"
placeholder=
"
{%
trans
%}
Search
{%
endtrans
%}
"
name=
"query"
id=
"search"
/>
<input
type=
"submit"
value=
"
{%
trans
%}
Search
{%
endtrans
%}
"
style=
"display: none;"
/>
</form>
{%
endif
%}
...
...
@@ -94,6 +94,13 @@ $('.select_date').datepicker({
monthNamesShort
:
$
.
datepicker
.
regional
[
"
{{
request.LANGUAGE_CODE
}}
"
].
monthNamesShort
,
monthNames
:
$
.
datepicker
.
regional
[
"
{{
request.LANGUAGE_CODE
}}
"
].
monthNames
,
}).
datepicker
(
$
.
datepicker
.
regional
[
"
{{
request.LANGUAGE_CODE
}}
"
]
);
$
(
document
).
keydown
(
function
(
e
)
{
if
(
$
(
e
.
target
).
is
(
'
input
'
))
{
return
}
if
(
e
.
keyCode
==
83
)
{
$
(
"
#search
"
).
focus
();
return
false
;
}
});
</script>
{%
endblock
%}
</body>
...
...
core/templates/core/user_detail.jinja
View file @
dbf0653b
...
...
@@ -11,7 +11,9 @@
<div
id=
"right_column"
>
<div
id=
"pictures"
>
{%
if
profile.profile_pict
%}
<img
src=
"
{{
profile.profile_pict.get_download_url
()
}}
"
alt=
"
{%
trans
%}
Profile
{%
endtrans
%}
"
/>
<img
src=
"
{{
profile.profile_pict.get_download_url
()
}}
"
alt=
"
{%
trans
%}
Profile
{%
endtrans
%}
"
id=
"picture"
/>
{%
else
%}
<img
src=
"
{{
static
(
'core/img/unknown.jpg'
)
}}
"
alt=
"
{%
trans
%}
Profile
{%
endtrans
%}
"
id=
"picture"
/>
{%
endif
%}
</div>
<p
id=
"quote"
><em>
{{
profile.quote
}}
</em></p>
...
...
@@ -53,4 +55,23 @@
{%
endblock
%}
{%
block
script
%}
{{
super
()
}}
<script>
$
(
function
()
{
var
keys
=
[];
var
pattern
=
"
71,85,89,71,85,89
"
;
$
(
document
).
keydown
(
function
(
e
)
{
keys
.
push
(
e
.
keyCode
);
if
(
keys
.
toString
()
==
pattern
)
{
keys
=
[];
$
(
"
#right_column img
"
).
attr
(
"
src
"
,
"
{{
static
(
'core/img/yug.jpg'
)
}}
"
);
}
if
(
keys
.
length
==
6
)
{
keys
.
shift
();
}
});
}
);
</script>
{%
endblock
%}
core/templates/core/user_stats.jinja
View file @
dbf0653b
...
...
@@ -7,7 +7,7 @@
{%
block
infos
%}
{%
if
profile.permanencies
%}
<div>
<h3>
Permanencies
</h3>
<h3>
{%
trans
%}
Permanencies
{%
endtrans
%}
</h3>
<p>
Total:
{{
total_perm_time
}}
</p>
<p>
Foyer:
{{
total_foyer_time
}}
</p>
<p>
MDE:
{{
total_mde_time
}}
</p>
...
...
counter/migrations/0016_auto_20160820_1923.py
0 → 100644
View file @
dbf0653b
# -*- coding: utf-8 -*-
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
import
django.db.models.deletion
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'core'
,
'0007_auto_20160813_0522'
),
(
'counter'
,
'0015_auto_20160820_0158'
),
]
operations
=
[
migrations
.
AddField
(
model_name
=
'product'
,
name
=
'buying_group'
,
field
=
models
.
ForeignKey
(
blank
=
True
,
on_delete
=
django
.
db
.
models
.
deletion
.
SET_NULL
,
verbose_name
=
'buying group'
,
related_name
=
'products'
,
to
=
'core.Group'
,
null
=
True
),
),
migrations
.
AlterField
(
model_name
=
'product'
,
name
=
'club'
,
field
=
models
.
ForeignKey
(
verbose_name
=
'club'
,
to
=
'club.Club'
,
related_name
=
'products'
),
),
migrations
.
AlterField
(
model_name
=
'product'
,
name
=
'icon'
,
field
=
models
.
ImageField
(
blank
=
True
,
null
=
True
,
upload_to
=
'products'
,
verbose_name
=
'icon'
),
),
migrations
.
AlterField
(
model_name
=
'product'
,
name
=
'product_type'
,
field
=
models
.
ForeignKey
(
blank
=
True
,
on_delete
=
django
.
db
.
models
.
deletion
.
SET_NULL
,
verbose_name
=
'parent product'
,
related_name
=
'children_products'
,
to
=
'counter.Product'
,
null
=
True
),
),
]
counter/migrations/0017_auto_20160820_2047.py
0 → 100644
View file @
dbf0653b
# -*- coding: utf-8 -*-
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
import
django.db.models.deletion
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'counter'
,
'0016_auto_20160820_1923'
),
]
operations
=
[
migrations
.
AddField
(
model_name
=
'product'
,
name
=
'parent_product'
,
field
=
models
.
ForeignKey
(
to
=
'counter.Product'
,
null
=
True
,
related_name
=
'children_products'
,
on_delete
=
django
.
db
.
models
.
deletion
.
SET_NULL
,
verbose_name
=
'parent product'
,
blank
=
True
),
),
migrations
.
AlterField
(
model_name
=
'product'
,
name
=
'product_type'
,
field
=
models
.
ForeignKey
(
to
=
'counter.ProductType'
,
null
=
True
,
related_name
=
'products'
,
on_delete
=
django
.
db
.
models
.
deletion
.
SET_NULL
,
verbose_name
=
'product type'
,
blank
=
True
),
),
]
counter/migrations/0018_auto_20160820_2051.py
0 → 100644
View file @
dbf0653b
# -*- coding: utf-8 -*-
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'core'
,
'0007_auto_20160813_0522'
),
(
'counter'
,
'0017_auto_20160820_2047'
),
]
operations
=
[
migrations
.
RemoveField
(
model_name
=
'product'
,
name
=
'buying_group'
,
),
migrations
.
AddField
(
model_name
=
'product'
,
name
=
'buying_group'
,
field
=
models
.
ManyToManyField
(
related_name
=
'products'
,
to
=
'core.Group'
,
verbose_name
=
'buying group'
),
),
]
counter/migrations/0019_auto_20160820_2053.py
0 → 100644
View file @
dbf0653b
# -*- coding: utf-8 -*-
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'counter'
,
'0018_auto_20160820_2051'
),
]
operations
=
[
migrations
.
RenameField
(
model_name
=
'product'
,
old_name
=
'buying_group'
,
new_name
=
'buying_groups'
,
),
]
counter/models.py
View file @
dbf0653b
...
...
@@ -76,15 +76,19 @@ class Product(models.Model):
"""
name
=
models
.
CharField
(
_
(
'name'
),
max_length
=
64
)
description
=
models
.
TextField
(
_
(
'description'
),
blank
=
True
)
product_type
=
models
.
ForeignKey
(
ProductType
,
related_name
=
'products'
,
null
=
True
,
blank
=
True
)
product_type
=
models
.
ForeignKey
(
ProductType
,
related_name
=
'products'
,
verbose_name
=
_
(
"product type"
),
null
=
True
,
blank
=
True
,
on_delete
=
models
.
SET_NULL
)
code
=
models
.
CharField
(
_
(
'code'
),
max_length
=
16
,
blank
=
True
)
purchase_price
=
CurrencyField
(
_
(
'purchase price'
))
selling_price
=
CurrencyField
(
_
(
'selling price'
))
special_selling_price
=
CurrencyField
(
_
(
'special selling price'
))
icon
=
models
.
ImageField
(
upload_to
=
'products'
,
null
=
True
,
blank
=
True
)
club
=
models
.
ForeignKey
(
Club
,
related_name
=
"products"
)
icon
=
models
.
ImageField
(
upload_to
=
'products'
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
"icon"
)
)
club
=
models
.
ForeignKey
(
Club
,
related_name
=
"products"
,
verbose_name
=
_
(
"club"
)
)
limit_age
=
models
.
IntegerField
(
_
(
'limit age'
),
default
=
0
)
tray
=
models
.
BooleanField
(
_
(
'tray price'
),
default
=
False
)
parent_product
=
models
.
ForeignKey
(
'self'
,
related_name
=
'children_products'
,
verbose_name
=
_
(
"parent product"
),
null
=
True
,
blank
=
True
,
on_delete
=
models
.
SET_NULL
)
buying_groups
=
models
.
ManyToManyField
(
Group
,
related_name
=
'products'
,
verbose_name
=
_
(
"buying groups"
))
class
Meta
:
verbose_name
=
_
(
'product'
)
...
...
counter/templates/counter/counter_click.jinja
View file @
dbf0653b
...
...
@@ -46,6 +46,9 @@
{%
if
request.session
[
'too_young'
]
%}
<p><strong>
{%
trans
%}
Too young for that product
{%
endtrans
%}
</strong></p>
{%
endif
%}
{%
if
request.session
[
'not_allowed'
]
%}
<p><strong>
{%
trans
%}
Not allowed for that product
{%
endtrans
%}
</strong></p>
{%
endif
%}
{%
if
request.session
[
'not_enough'
]
%}
<p><strong>
{%
trans
%}
Not enough money
{%
endtrans
%}
</strong></p>
{%
endif
%}
...
...
@@ -79,11 +82,16 @@
<input
type=
"hidden"
name=
"action"
value=
"cancel"
>
<input
type=
"submit"
value=
"
{%
trans
%}
Cancel
{%
endtrans
%}
"
/>
</form>
<p><strong>
{%
trans
%}
Products:
{%
endtrans
%}
</strong>
{%
for
p
in
counter.products.all
()
%}
{{
add_product
(
p.id
,
p.name
)
}}
<div><strong>
{%
trans
%}
Products:
{%
endtrans
%}
</strong>
{%
for
t
in
categories
%}
{%
if
counter.products.
filter
(
product_type
=
t
)
.
exists
()
%}
<h5>
{{
t
}}
</h5>
{%
for
p
in
counter.products.
filter
(
product_type
=
t
)
.
all
()
%}
{{
add_product
(
p.id
,
p.name
)
}}
{%
endfor
%}
{%
endif
%}
{%
endfor
%}
</
p
>
</
div
>
</div>
{%
endblock
%}
...
...
counter/views.py
View file @
dbf0653b
...
...
@@ -123,6 +123,7 @@ class CounterClick(DetailView):
request
.
session
[
'basket_total'
]
=
0
request
.
session
[
'not_enough'
]
=
False
request
.
session
[
'too_young'
]
=
False
request
.
session
[
'not_allowed'
]
=
False
self
.
refill_form
=
None
ret
=
super
(
CounterClick
,
self
).
get
(
request
,
*
args
,
**
kwargs
)
if
((
self
.
object
.
type
!=
"BAR"
and
not
request
.
user
.
is_authenticated
())
or
...
...
@@ -145,6 +146,7 @@ class CounterClick(DetailView):
request
.
session
[
'basket_total'
]
=
0
request
.
session
[
'not_enough'
]
=
False
request
.
session
[
'too_young'
]
=
False
request
.
session
[
'not_allowed'
]
=
False
if
self
.
object
.
type
!=
"BAR"
:
self
.
operator
=
request
.
user
elif
self
.
is_barman_price
():
...
...
@@ -208,6 +210,13 @@ class CounterClick(DetailView):
price
=
self
.
get_price
(
pid
)
total
=
self
.
sum_basket
(
request
)
product
=
self
.
get_product
(
pid
)
can_buy
=
False
for
g
in
product
.
buying_groups
.
all
():
if
request
.
user
.
is_in_group
(
g
.
name
):
can_buy
=
True
if
not
can_buy
:
request
.
session
[
'not_allowed'
]
=
True
return
False
bq
=
0
# Bonus quantity, for trays
if
product
.
tray
:
# Handle the tray to adjust the quantity q to add and the bonus quantity bq
total_qty_mod_6
=
self
.
get_total_quantity_for_pid
(
request
,
pid
)
%
6
...
...
@@ -224,8 +233,6 @@ class CounterClick(DetailView):
request
.
session
[
'basket'
][
pid
][
'bonus_qty'
]
+=
bq
else
:
# or create if not
request
.
session
[
'basket'
][
pid
]
=
{
'qty'
:
q
,
'price'
:
int
(
price
*
100
),
'bonus_qty'
:
bq
}
request
.
session
[
'not_enough'
]
=
False
# Reset not_enough to save the session
request
.
session
[
'too_young'
]
=
False
request
.
session
.
modified
=
True
return
True
...
...
@@ -321,6 +328,7 @@ class CounterClick(DetailView):
kwargs
[
'customer'
]
=
self
.
customer
kwargs
[
'basket_total'
]
=
self
.
sum_basket
(
self
.
request
)
kwargs
[
'refill_form'
]
=
self
.
refill_form
or
RefillForm
()
kwargs
[
'categories'
]
=
ProductType
.
objects
.
all
()
return
kwargs
class
CounterLogin
(
RedirectView
):
...
...
@@ -451,23 +459,42 @@ class ProductListView(CanEditPropMixin, ListView):
model
=
Product
template_name
=
'counter/product_list.jinja'
class
ProductEditForm
(
forms
.
ModelForm
):
class
Meta
:
model
=
Product
fields
=
[
'name'
,
'description'
,
'product_type'
,
'code'
,
'parent_product'
,
'buying_groups'
,
'purchase_price'
,
'selling_price'
,
'special_selling_price'
,
'icon'
,
'club'
,
'limit_age'
,
'tray'
]
parent_product
=
AutoCompleteSelectField
(
'products'
,
show_help_text
=
False
,
label
=
_
(
"Parent product"
),
required
=
False
)
buying_groups
=
AutoCompleteSelectMultipleField
(
'groups'
,
show_help_text
=
False
,
help_text
=
""
,
label
=
_
(
"Buying groups"
))
club
=
AutoCompleteSelectField
(
'clubs'
,
show_help_text
=
False
)
counters
=
AutoCompleteSelectMultipleField
(
'counters'
,
show_help_text
=
False
,
help_text
=
""
,
label
=
_
(
"Counters"
),
required
=
False
)
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
ProductEditForm
,
self
).
__init__
(
*
args
,
**
kwargs
)
if
self
.
instance
.
id
:
self
.
fields
[
'counters'
].
initial
=
[
str
(
c
.
id
)
for
c
in
self
.
instance
.
counters
.
all
()]
def
save
(
self
,
*
args
,
**
kwargs
):
ret
=
super
(
ProductEditForm
,
self
).
save
(
*
args
,
**
kwargs
)
if
self
.
fields
[
'counters'
].
initial
:
for
cid
in
self
.
fields
[
'counters'
].
initial
:
c
=
Counter
.
objects
.
filter
(
id
=
int
(
cid
)).
first
()
c
.
products
.
remove
(
self
.
instance
)
c
.
save
()
for
cid
in
self
.
cleaned_data
[
'counters'
]:
c
=
Counter
.
objects
.
filter
(
id
=
int
(
cid
)).
first
()
c
.
products
.
add
(
self
.
instance
)
c
.
save
()
return
ret
class
ProductCreateView
(
CanCreateMixin
,
CreateView
):
"""
A create view for the admins
"""
model
=
Product
fields
=
[
'name'
,
'description'
,
'product_type'
,
'code'
,
'purchase_price'
,
'selling_price'
,
'special_selling_price'
,
'icon'
,
'club'
]
form_class
=
ProductEditForm
template_name
=
'core/create.jinja'
class
ProductEditForm
(
forms
.
ModelForm
):
class
Meta
:
model
=
Product
fields
=
[
'name'
,
'description'
,
'product_type'
,
'code'
,
'purchase_price'
,
'selling_price'
,
'special_selling_price'
,
'icon'
,
'club'
,
'limit_age'
,
'tray'
]
counters
=
make_ajax_field
(
Product
,
'counters'
,
'counters'
,
show_help_text
=
False
,
label
=
'Counters'
,
help_text
=
"Guy"
,
required
=
False
)
# TODO FIXME
class
ProductEditView
(
CanEditPropMixin
,
UpdateView
):
"""
An edit view for the admins
...
...
@@ -476,8 +503,6 @@ class ProductEditView(CanEditPropMixin, UpdateView):
form_class
=
ProductEditForm
pk_url_kwarg
=
"product_id"
template_name
=
'core/edit.jinja'
# TODO: add management of the 'counters' ForeignKey
class
RefillingDeleteView
(
CanEditPropMixin
,
DeleteView
):
"""
...
...
eboutic/views.py
View file @
dbf0653b
...
...
@@ -55,9 +55,12 @@ class EbouticMain(TemplateView):
""" Add a product to the basket """
try
:
p
=
Product
.
objects
.
filter
(
id
=
int
(
request
.
POST
[
'product_id'
])).
first
()
self
.
basket
.
add_product
(
p
)
except
:
pass
for
g
in
p
.
buying_groups
.
all
():
if
request
.
user
.
is_in_group
(
g
.
name
):
self
.
basket
.
add_product
(
p
)
break
except
Exception
as
e
:
print
(
repr
(
e
))
def
del_product
(
self
,
request
):
""" Delete a product from the basket """
...
...
locale/fr/LC_MESSAGES/django.mo
View file @
dbf0653b
No preview for this file type
locale/fr/LC_MESSAGES/django.po
View file @
dbf0653b
This diff is collapsed.
Click to expand it.
migrate.py
View file @
dbf0653b
...
...
@@ -83,7 +83,6 @@ def migrate_users():
}
def
get_random_free_email
():
id
=
random
.
randrange
(
4000
)
email
=
"no_email_%s@git.an"
%
random
.
randrange
(
4000
,
40000
)
while
User
.
objects
.
filter
(
email
=
email
).
exists
():
email
=
"no_email_%s@git.an"
%
random
.
randrange
(
4000
,
40000
)
...
...
@@ -602,10 +601,10 @@ def main():
migrate_products
()
migrate_products_to_counter
()
# reset_customer_amount()
migrate_invoices
()
migrate_refillings
()
migrate_invoices
()
migrate_sellings
()
#
reset_index('core', 'c
ounter
', 'subscription')
reset_index
(
'core'
,
'c
lub
'
,
'subscription'
,
'accounting'
,
'eboutic'
,
'launderette'
,
'counter'
)
if
__name__
==
"__main__"
:
main
()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment