Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
R
repanier
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
chris
repanier
Commits
6f4929c2
Commit
6f4929c2
authored
Dec 03, 2016
by
Patrick
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Django 1.9.11, CMS 3.4.1
parent
c36d88d9
Changes
27
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
4576 additions
and
191 deletions
+4576
-191
repanier/fields/RepanierMoneyField.py
repanier/fields/RepanierMoneyField.py
+313
-0
repanier/fields/__init__.py
repanier/fields/__init__.py
+0
-0
repanier/management/commands/back_to_send.py
repanier/management/commands/back_to_send.py
+3
-1
repanier/management/commands/move_pictures.py
repanier/management/commands/move_pictures.py
+1
-1
repanier/models/__init__.py
repanier/models/__init__.py
+22
-0
repanier/models/bankaccount.py
repanier/models/bankaccount.py
+137
-0
repanier/models/box.py
repanier/models/box.py
+122
-0
repanier/models/configuration.py
repanier/models/configuration.py
+413
-0
repanier/models/customer.py
repanier/models/customer.py
+328
-0
repanier/models/deliveryboard.py
repanier/models/deliveryboard.py
+104
-0
repanier/models/invoice.py
repanier/models/invoice.py
+451
-0
repanier/models/lut.py
repanier/models/lut.py
+167
-0
repanier/models/offeritem.py
repanier/models/offeritem.py
+532
-0
repanier/models/permanence.py
repanier/models/permanence.py
+483
-0
repanier/models/permanenceboard.py
repanier/models/permanenceboard.py
+44
-0
repanier/models/producer.py
repanier/models/producer.py
+328
-0
repanier/models/product.py
repanier/models/product.py
+320
-0
repanier/models/purchase.py
repanier/models/purchase.py
+407
-0
repanier/models/staff.py
repanier/models/staff.py
+117
-0
repanier/rest/__init__.py
repanier/rest/__init__.py
+0
-0
repanier/rest/lut.py
repanier/rest/lut.py
+42
-0
repanier/rest/permanence.py
repanier/rest/permanence.py
+83
-0
repanier/rest/producer.py
repanier/rest/producer.py
+55
-0
repanier/rest/product.py
repanier/rest/product.py
+75
-0
repanier/rest/version.py
repanier/rest/version.py
+11
-0
repanier/rest/view.py
repanier/rest/view.py
+18
-0
repanier/static/bootstrap/css/bootswatch.less
repanier/static/bootstrap/css/bootswatch.less
+0
-189
No files found.
repanier/fields/RepanierMoneyField.py
0 → 100644
View file @
6f4929c2
# -*- coding: utf-8
from
__future__
import
unicode_literals
import
sys
from
decimal
import
*
from
django.conf
import
settings
from
django.core.exceptions
import
ValidationError
from
django.db
import
models
from
django.db.models.expressions
import
BaseExpression
,
Expression
from
django.forms
import
DecimalField
,
NumberInput
from
django.forms.utils
import
flatatt
from
django.utils.encoding
import
force_text
,
python_2_unicode_compatible
from
django.utils.html
import
format_html
import
repanier.apps
DECIMAL_ZERO
=
Decimal
(
'0'
)
PYTHON2
=
sys
.
version_info
[
0
]
==
2
# class RepanierMoneyComparisonError(TypeError):
# # This exception was needed often enough to merit its own
# # Exception class.
#
# def __init__(self, other):
# assert not isinstance(other, RepanierMoney)
# self.other = other
#
# def __str__(self):
# # Note: at least w/ Python 2.x, use __str__, not __unicode__.
# return "Cannot compare instances of RepanierMoney and %s" \
# % self.other.__class__.__name__
@
python_2_unicode_compatible
class
RepanierMoney
(
object
):
def
__init__
(
self
,
amount
=
DECIMAL_ZERO
,
decimal_places
=
2
):
if
not
isinstance
(
amount
,
Decimal
):
amount
=
Decimal
(
str
(
amount
))
self
.
decimal_places
=
decimal_places
self
.
rounding
=
Decimal
(
'10'
)
**
-
self
.
decimal_places
# 2 places --> '0.01'
self
.
amount
=
amount
.
quantize
(
self
.
rounding
,
ROUND_HALF_UP
)
def
__float__
(
self
):
return
float
(
self
.
amount
)
def
__repr__
(
self
):
return
"%s %d"
%
(
self
.
amount
,
self
.
decimal_places
)
def
__pos__
(
self
):
return
RepanierMoney
(
amount
=
self
.
amount
,
decimal_places
=
self
.
decimal_places
)
def
__neg__
(
self
):
return
RepanierMoney
(
amount
=-
self
.
amount
,
decimal_places
=
self
.
decimal_places
)
def
__add__
(
self
,
other
):
if
isinstance
(
other
,
RepanierMoney
):
return
RepanierMoney
(
amount
=
self
.
amount
+
other
.
amount
,
decimal_places
=
self
.
decimal_places
)
else
:
return
RepanierMoney
(
amount
=
self
.
amount
+
other
,
decimal_places
=
self
.
decimal_places
)
def
__sub__
(
self
,
other
):
return
self
.
__add__
(
-
other
)
def
__mul__
(
self
,
other
):
if
isinstance
(
other
,
RepanierMoney
):
return
RepanierMoney
(
amount
=
self
.
amount
*
other
.
amount
,
decimal_places
=
self
.
decimal_places
)
else
:
return
RepanierMoney
(
amount
=
self
.
amount
*
other
,
decimal_places
=
self
.
decimal_places
)
def
__truediv__
(
self
,
other
):
if
isinstance
(
other
,
RepanierMoney
):
return
RepanierMoney
(
amount
=
self
.
amount
/
other
.
amount
,
decimal_places
=
self
.
decimal_places
)
else
:
return
RepanierMoney
(
amount
=
self
.
amount
/
other
,
decimal_places
=
self
.
decimal_places
)
def
__abs__
(
self
):
return
RepanierMoney
(
amount
=
abs
(
self
.
amount
),
decimal_places
=
self
.
decimal_places
)
# def __bool__(self):
# return bool(self.amount)
#
# if PYTHON2:
# __nonzero__ = __bool__
def
__rmod__
(
self
,
other
):
"""
Calculate percentage of an amount. The left-hand side of the
operator must be a numeric value.
Example:
>>> money = RepanierMoney(200)
>>> 5 % money
USD 10.00
"""
if
isinstance
(
other
,
RepanierMoney
):
raise
TypeError
(
'Invalid __rmod__ operation'
)
else
:
return
RepanierMoney
(
amount
=
Decimal
(
self
.
amount
*
(
other
/
100
)),
decimal_places
=
self
.
decimal_places
)
__radd__
=
__add__
def
__rsub__
(
self
,
other
):
if
isinstance
(
other
,
RepanierMoney
):
return
RepanierMoney
(
amount
=
other
.
amount
-
self
.
amount
,
decimal_places
=
self
.
decimal_places
)
else
:
return
RepanierMoney
(
amount
=
other
-
self
.
amount
,
decimal_places
=
self
.
decimal_places
)
__rmul__
=
__mul__
__rtruediv__
=
__truediv__
# _______________________________________
# Override comparison operators
def
__eq__
(
self
,
other
):
return
(
isinstance
(
other
,
RepanierMoney
)
and
(
self
.
amount
==
other
.
amount
))
or
self
.
amount
==
other
def
__ne__
(
self
,
other
):
result
=
self
.
__eq__
(
other
)
return
not
result
def
__lt__
(
self
,
other
):
return
(
isinstance
(
other
,
RepanierMoney
)
and
(
self
.
amount
<
other
.
amount
))
or
self
.
amount
<
other
def
__gt__
(
self
,
other
):
return
(
isinstance
(
other
,
RepanierMoney
)
and
(
self
.
amount
>
other
.
amount
))
or
self
.
amount
>
other
def
__le__
(
self
,
other
):
return
self
<
other
or
self
==
other
def
__ge__
(
self
,
other
):
return
self
.
amount
>
other
or
self
==
other
def
__str__
(
self
):
negative
,
digits
,
e
=
self
.
amount
.
as_tuple
()
result
=
[]
digits
=
list
(
map
(
str
,
digits
))
build
,
next
=
result
.
append
,
digits
.
pop
# Suffix currency
if
repanier
.
apps
.
REPANIER_SETTINGS_AFTER_AMOUNT
:
build
(
" %s"
%
repanier
.
apps
.
REPANIER_SETTINGS_CURRENCY_DISPLAY
)
# Decimals
for
i
in
range
(
self
.
decimal_places
):
build
(
next
()
if
digits
else
'0'
)
# Decimal points
if
self
.
decimal_places
:
build
(
settings
.
DECIMAL_SEPARATOR
)
# Grouped number
if
not
digits
:
build
(
'0'
)
else
:
i
=
0
while
digits
:
build
(
next
())
i
+=
1
if
i
==
settings
.
NUMBER_GROUPING
and
digits
:
i
=
0
build
(
settings
.
THOUSAND_SEPARATOR
)
# Prefix sign
if
negative
:
build
(
"- "
)
# Prefix currency
if
not
repanier
.
apps
.
REPANIER_SETTINGS_AFTER_AMOUNT
:
build
(
"%s "
%
repanier
.
apps
.
REPANIER_SETTINGS_CURRENCY_DISPLAY
)
return
u
''
.
join
(
reversed
(
result
))
def
as_tuple
(
self
):
"""Represents the number as a triple tuple.
To show the internals exactly as they are.
"""
return
self
.
amount
.
as_tuple
()
class
MoneyFieldProxy
(
object
):
def
__init__
(
self
,
field
):
self
.
field
=
field
def
_money_from_obj
(
self
,
obj
):
amount
=
obj
.
__dict__
[
self
.
field
.
name
]
if
amount
is
None
:
return
None
return
RepanierMoney
(
amount
=
amount
,
decimal_places
=
self
.
field
.
decimal_places
)
def
__get__
(
self
,
obj
,
type
=
None
):
if
obj
is
None
:
raise
AttributeError
(
'Can only be accessed via an instance.'
)
if
isinstance
(
obj
.
__dict__
[
self
.
field
.
name
],
BaseExpression
):
return
obj
.
__dict__
[
self
.
field
.
name
]
if
not
isinstance
(
obj
.
__dict__
[
self
.
field
.
name
],
RepanierMoney
):
obj
.
__dict__
[
self
.
field
.
name
]
=
self
.
_money_from_obj
(
obj
)
return
obj
.
__dict__
[
self
.
field
.
name
]
def
__set__
(
self
,
obj
,
value
):
if
isinstance
(
value
,
tuple
):
value
=
RepanierMoney
(
amount
=
value
[
0
],
decimal_places
=
self
.
field
.
decimal_places
)
if
isinstance
(
value
,
RepanierMoney
):
obj
.
__dict__
[
self
.
field
.
name
]
=
value
.
amount
elif
isinstance
(
value
,
BaseExpression
):
obj
.
__dict__
[
self
.
field
.
name
]
=
value
else
:
if
value
:
value
=
str
(
value
)
obj
.
__dict__
[
self
.
field
.
name
]
=
self
.
field
.
to_python
(
value
)
class
ModelMoneyField
(
models
.
DecimalField
):
def
formfield
(
self
,
**
kwargs
):
defaults
=
{
'form_class'
:
FormMoneyField
}
defaults
.
update
(
kwargs
)
return
super
(
ModelMoneyField
,
self
).
formfield
(
**
defaults
)
def
to_python
(
self
,
value
):
if
isinstance
(
value
,
Expression
):
return
value
if
isinstance
(
value
,
RepanierMoney
):
value
=
value
.
amount
if
isinstance
(
value
,
tuple
):
value
=
value
[
0
]
return
super
(
ModelMoneyField
,
self
).
to_python
(
value
)
def
get_db_prep_save
(
self
,
value
,
connection
):
if
isinstance
(
value
,
Expression
):
return
value
if
isinstance
(
value
,
RepanierMoney
):
value
=
value
.
amount
return
super
(
ModelMoneyField
,
self
).
get_db_prep_save
(
value
,
connection
)
def
contribute_to_class
(
self
,
cls
,
name
):
super
(
ModelMoneyField
,
self
).
contribute_to_class
(
cls
,
name
)
setattr
(
cls
,
self
.
name
,
MoneyFieldProxy
(
self
))
class
MoneyInput
(
NumberInput
):
def
render
(
self
,
name
,
value
,
attrs
=
None
):
if
value
is
None
:
value
=
''
final_attrs
=
self
.
build_attrs
(
attrs
,
type
=
self
.
input_type
,
name
=
name
)
if
value
!=
''
:
# Only add the 'value' attribute if a value is non-empty.
final_attrs
[
'value'
]
=
force_text
(
self
.
_format_value
(
value
))
if
repanier
.
apps
.
REPANIER_SETTINGS_AFTER_AMOUNT
:
return
format_html
(
'<input{} /> {}'
,
flatatt
(
final_attrs
),
repanier
.
apps
.
REPANIER_SETTINGS_CURRENCY_DISPLAY
)
else
:
return
format_html
(
'{} <input{} />'
,
repanier
.
apps
.
REPANIER_SETTINGS_CURRENCY_DISPLAY
,
flatatt
(
final_attrs
))
class
FormMoneyField
(
DecimalField
):
widget
=
MoneyInput
def
to_python
(
self
,
value
):
# Important : Do not validate if self.disabled
value
=
(
not
self
.
disabled
and
super
(
FormMoneyField
,
self
).
to_python
(
value
))
or
DECIMAL_ZERO
return
RepanierMoney
(
value
)
def
prepare_value
(
self
,
value
):
try
:
return
value
.
amount
except
:
return
value
# def validate(self, value):
# super(DecimalField, self).validate(value)
# if value in self.empty_values or not self.required:
# return
# # Check for NaN, Inf and -Inf values. We can't compare directly for NaN,
# # since it is never equal to itself. However, NaN is the only value that
# # isn't equal to itself, so we can use this to identify NaN
# if value != value or value == Decimal("Inf") or value == Decimal("-Inf"):
# raise ValidationError(self.error_messages['invalid'], code='invalid')
# sign, digittuple, exponent = value.amount.as_tuple()
# decimals = abs(exponent)
# # digittuple doesn't include any leading zeros.
# digits = len(digittuple)
# if decimals > digits:
# # We have leading zeros up to or past the decimal point. Count
# # everything past the decimal point as a digit. We do not count
# # 0 before the decimal point as a digit since that would mean
# # we would not allow max_digits = decimal_places.
# digits = decimals
# whole_digits = digits - decimals
#
# if self.max_digits is not None and digits > self.max_digits:
# raise ValidationError(
# self.error_messages['max_digits'],
# code='max_digits',
# params={'max': self.max_digits},
# )
# if self.decimal_places is not None and decimals > self.decimal_places:
# raise ValidationError(
# self.error_messages['max_decimal_places'],
# code='max_decimal_places',
# params={'max': self.decimal_places},
# )
# if (self.max_digits is not None and self.decimal_places is not None
# and whole_digits > (self.max_digits - self.decimal_places)):
# raise ValidationError(
# self.error_messages['max_whole_digits'],
# code='max_whole_digits',
# params={'max': (self.max_digits - self.decimal_places)},
# )
# return value
repanier/fields/__init__.py
0 → 100644
View file @
6f4929c2
repanier/management/commands/back_to_send.py
View file @
6f4929c2
# -*- coding: utf-8 -*-
from
django.core.cache
import
cache
from
django.core.management.base
import
BaseCommand
from
menus.menu_pool
import
menu_pool
from
repanier.const
import
*
...
...
@@ -10,10 +11,11 @@ class Command(BaseCommand):
help
=
'Back to send'
def
handle
(
self
,
*
args
,
**
options
):
permanence
=
Permanence
.
objects
.
filter
(
id
=
6
).
order_by
().
first
()
permanence
=
Permanence
.
objects
.
filter
(
id
=
6
).
order_by
(
'?'
).
first
()
if
PERMANENCE_PLANNED
==
permanence
.
status
and
permanence
.
highest_status
==
PERMANENCE_SEND
:
OfferItem
.
objects
.
filter
(
permanence_id
=
permanence
.
id
).
update
(
is_active
=
True
)
permanence
.
status
=
PERMANENCE_SEND
permanence
.
save
(
update_fields
=
[
'status'
])
menu_pool
.
clear
()
cache
.
clear
()
repanier/management/commands/move_pictures.py
View file @
6f4929c2
...
...
@@ -47,7 +47,7 @@ class Command(BaseCommand):
for
product
in
Product
.
objects
.
all
():
if
product
.
picture
is
not
None
:
self
.
move
(
record
=
product
,
to_subdir
=
"product"
+
os
.
sep
+
str
(
product
.
producer
.
id
),
size
=
"M"
)
for
obj
in
OfferItem
.
objects
.
filter
(
product_id
=
product
.
id
).
order_by
():
for
obj
in
OfferItem
.
objects
.
filter
(
product_id
=
product
.
id
).
order_by
(
'?'
):
obj
.
picture2
=
product
.
picture2
obj
.
save
()
...
...
repanier/models/__init__.py
0 → 100644
View file @
6f4929c2
# -*- coding: utf-8
# non proxies
from
bankaccount
import
BankAccount
from
configuration
import
Configuration
from
customer
import
Customer
from
deliveryboard
import
DeliveryBoard
from
invoice
import
CustomerInvoice
,
ProducerInvoice
,
CustomerProducerInvoice
from
lut
import
LUT_ProductionMode
,
LUT_DeliveryPoint
,
LUT_DepartmentForCustomer
,
LUT_PermanenceRole
from
offeritem
import
OfferItem
from
permanence
import
Permanence
from
permanenceboard
import
PermanenceBoard
from
producer
import
Producer
from
product
import
Product
,
Product_Translation
from
purchase
import
Purchase
from
staff
import
Staff
# after Producer and Product
from
box
import
BoxContent
# proxies
from
box
import
Box
from
invoice
import
CustomerSend
from
offeritem
import
OfferItemSend
,
OfferItemClosed
from
permanence
import
PermanenceInPreparation
,
PermanenceDone
\ No newline at end of file
repanier/models/bankaccount.py
0 → 100644
View file @
6f4929c2
# -*- coding: utf-8
from
__future__
import
unicode_literals
from
django.core.validators
import
MinValueValidator
from
django.db
import
models
from
django.db.models.signals
import
pre_save
from
django.dispatch
import
receiver
from
django.utils.translation
import
ugettext_lazy
as
_
from
repanier.apps
import
REPANIER_SETTINGS_PERMANENCE_NAME
from
repanier.const
import
*
from
repanier.fields.RepanierMoneyField
import
ModelMoneyField
class
BankAccount
(
models
.
Model
):
permanence
=
models
.
ForeignKey
(
'Permanence'
,
verbose_name
=
REPANIER_SETTINGS_PERMANENCE_NAME
,
on_delete
=
models
.
PROTECT
,
blank
=
True
,
null
=
True
)
producer
=
models
.
ForeignKey
(
'Producer'
,
verbose_name
=
_
(
"producer"
),
on_delete
=
models
.
PROTECT
,
blank
=
True
,
null
=
True
)
customer
=
models
.
ForeignKey
(
'Customer'
,
verbose_name
=
_
(
"customer"
),
on_delete
=
models
.
PROTECT
,
blank
=
True
,
null
=
True
)
operation_date
=
models
.
DateField
(
_
(
"operation_date"
),
db_index
=
True
)
operation_comment
=
models
.
CharField
(
_
(
"operation_comment"
),
max_length
=
100
,
null
=
True
,
blank
=
True
)
operation_status
=
models
.
CharField
(
max_length
=
3
,
choices
=
LUT_BANK_TOTAL
,
default
=
BANK_NOT_LATEST_TOTAL
,
verbose_name
=
_
(
"Bank balance status"
),
db_index
=
True
)
bank_amount_in
=
ModelMoneyField
(
_
(
"bank_amount_in"
),
help_text
=
_
(
'payment_on_the_account'
),
max_digits
=
8
,
decimal_places
=
2
,
default
=
DECIMAL_ZERO
,
validators
=
[
MinValueValidator
(
0
)])
bank_amount_out
=
ModelMoneyField
(
_
(
"bank_amount_out"
),
help_text
=
_
(
'payment_from_the_account'
),
max_digits
=
8
,
decimal_places
=
2
,
default
=
DECIMAL_ZERO
,
validators
=
[
MinValueValidator
(
0
)])
producer_invoice
=
models
.
ForeignKey
(
'ProducerInvoice'
,
verbose_name
=
_
(
"producer_invoice"
),
blank
=
True
,
null
=
True
,
on_delete
=
models
.
PROTECT
,
db_index
=
True
)
customer_invoice
=
models
.
ForeignKey
(
'CustomerInvoice'
,
verbose_name
=
_
(
"customer_invoice"
),
blank
=
True
,
null
=
True
,
on_delete
=
models
.
PROTECT
,
db_index
=
True
)
is_updated_on
=
models
.
DateTimeField
(
_
(
"is_updated_on"
),
auto_now
=
True
)
def
get_bank_amount_in
(
self
):
if
self
.
operation_status
in
[
BANK_PROFIT
,
BANK_TAX
]:
return
"<i>%s</i>"
%
(
self
.
bank_amount_in
if
self
.
bank_amount_in
.
amount
!=
DECIMAL_ZERO
else
EMPTY_STRING
)
else
:
return
self
.
bank_amount_in
if
self
.
bank_amount_in
.
amount
!=
DECIMAL_ZERO
else
EMPTY_STRING
get_bank_amount_in
.
short_description
=
(
_
(
"bank_amount_in"
))
get_bank_amount_in
.
allow_tags
=
True
get_bank_amount_in
.
admin_order_field
=
'bank_amount_in'
def
get_bank_amount_out
(
self
):
if
self
.
operation_status
in
[
BANK_PROFIT
,
BANK_TAX
]:
return
"<i>%s</i>"
%
(
self
.
bank_amount_out
if
self
.
bank_amount_out
.
amount
!=
DECIMAL_ZERO
else
EMPTY_STRING
)
else
:
return
self
.
bank_amount_out
if
self
.
bank_amount_out
.
amount
!=
DECIMAL_ZERO
else
EMPTY_STRING
get_bank_amount_out
.
short_description
=
(
_
(
"bank_amount_out"
))
get_bank_amount_out
.
allow_tags
=
True
get_bank_amount_out
.
admin_order_field
=
'bank_amount_out'
def
get_producer
(
self
):
if
self
.
producer
is
not
None
:
return
self
.
producer
.
short_profile_name
else
:
if
self
.
customer
is
None
:
# This is a total, show it
from
repanier.apps
import
REPANIER_SETTINGS_GROUP_NAME
if
self
.
operation_status
==
BANK_LATEST_TOTAL
:
return
"<b>%s</b>"
%
"=== %s"
%
REPANIER_SETTINGS_GROUP_NAME
else
:
return
"<b>%s</b>"
%
"--- %s"
%
REPANIER_SETTINGS_GROUP_NAME
return
EMPTY_STRING
get_producer
.
short_description
=
(
_
(
"producer"
))
get_producer
.
allow_tags
=
True
get_producer
.
admin_order_field
=
'producer'
def
get_customer
(
self
):
if
self
.
customer
is
not
None
:
return
self
.
customer
.
short_basket_name
else
:
if
self
.
producer
is
None
:
# This is a total, show it
from
repanier.apps
import
REPANIER_SETTINGS_BANK_ACCOUNT
if
self
.
operation_status
==
BANK_LATEST_TOTAL
:
if
REPANIER_SETTINGS_BANK_ACCOUNT
is
not
None
:
return
"<b>%s</b>"
%
REPANIER_SETTINGS_BANK_ACCOUNT
else
:
return
"<b>%s</b>"
%
"=============="
else
:
if
REPANIER_SETTINGS_BANK_ACCOUNT
is
not
None
:
return
"<b>%s</b>"
%
REPANIER_SETTINGS_BANK_ACCOUNT
else
:
return
"<b>%s</b>"
%
"--------------"
return
EMPTY_STRING
get_customer
.
short_description
=
(
_
(
"customer"
))
get_customer
.
allow_tags
=
True
get_customer
.
admin_order_field
=
'customer'
class
Meta
:
verbose_name
=
_
(
"bank account movement"
)
verbose_name_plural
=
_
(
"bank account movements"
)
ordering
=
(
'-operation_date'
,
'-id'
)
index_together
=
[
[
'operation_date'
,
'id'
],
[
'customer_invoice'
,
'operation_date'
,
'id'
],
[
'producer_invoice'
,
'operation_date'
,
'operation_date'
,
'id'
],
[
'permanence'
,
'customer'
,
'producer'
,
'operation_date'
,
'id'
],
]
@
receiver
(
pre_save
,
sender
=
BankAccount
)
def
bank_account_pre_save
(
sender
,
**
kwargs
):
bank_account
=
kwargs
[
"instance"
]
if
bank_account
.
producer
is
None
and
bank_account
.
customer
is
None
:
initial_balance
=
BankAccount
.
objects
.
filter
(
producer__isnull
=
True
,
customer__isnull
=
True
).
order_by
(
'?'
).
first
()
if
initial_balance
is
None
:
bank_account
.
operation_status
=
BANK_LATEST_TOTAL
bank_account
.
permanence
=
None
bank_account
.
operation_comment
=
_
(
"Initial balance"
)
bank_account
.
producer_invoice
=
None
bank_account
.
customer_invoice
=
None
repanier/models/box.py
0 → 100644
View file @
6f4929c2
# -*- coding: utf-8
from
__future__
import
unicode_literals
from
django.core.validators
import
MinValueValidator
from
django.db
import
models
from
django.db.models.signals
import
pre_save
from
django.dispatch
import
receiver
from
django.utils.encoding
import
python_2_unicode_compatible
from
django.utils.translation
import
ugettext_lazy
as
_
from
repanier.const
import
*
from
repanier.fields.RepanierMoneyField
import
ModelMoneyField
from
repanier.models.producer
import
Producer
from
repanier.models.product
import
Product
,
product_pre_save
@
python_2_unicode_compatible
class
Box
(
Product
):
def
save_update_stock
(
self
):
# stock : max_digits=9, decimal_places=3 => 1000000 > max(stock)
stock
=
1000000
for
box_content
in
BoxContent
.
objects
.
filter
(
box_id
=
self
.
id
,
product__limit_order_quantity_to_stock
=
True
,
content_quantity__gt
=
DECIMAL_ZERO
,
product__is_box
=
False
# Disallow recursivity
).
prefetch_related
(
"product"
).
only
(
"content_quantity"
,
"product__stock"
,
"product__limit_order_quantity_to_stock"
).
order_by
(
'?'
):
stock
=
min
(
stock
,
box_content
.
product
.
stock
//
box_content
.
content_quantity
)
if
stock
<
1000000
:
self
.
stock
=
stock
else
:
self
.
stock
=
DECIMAL_ZERO
self
.
limit_order_quantity_to_stock
=
True
self
.
save
(
update_fields
=
[
'stock'
,
'limit_order_quantity_to_stock'
])
class
Meta
:
proxy
=
True
verbose_name
=
_
(
"box"
)
verbose_name_plural
=
_
(
"boxes"
)
# ordering = ("sort_order",)
def
__str__
(
self
):
return
'%s'
%
self
.
long_name
@
receiver
(
pre_save
,
sender
=
Box
)
def
box_pre_save
(
sender
,
**
kwargs
):
box
=
kwargs
[
"instance"
]
box
.
is_box
=
True
box
.
producer_id
=
Producer
.
objects
.
filter
(
represent_this_buyinggroup
=
True
).
order_by
(
'?'
).
only
(
'id'
).
first
().
id
box
.
order_unit
=
PRODUCT_ORDER_UNIT_PC
box
.
producer_unit_price
=
box
.
customer_unit_price
box
.
producer_vat
=
box
.
customer_vat
# ! Important to initialise all fields of the box. Remember : a box is a product.
product_pre_save
(
sender
,
**
kwargs
)
@
python_2_unicode_compatible
class
BoxContent
(
models
.
Model
):
box
=
models
.
ForeignKey
(
'Box'
,
verbose_name
=
_
(
"box"
),
null
=
True
,
blank
=
True
,
db_index
=
True
,
on_delete
=
models
.
PROTECT
)
product
=
models
.
ForeignKey
(
'Product'
,
verbose_name
=
_
(
"product"
),
related_name
=
'box_content'
,
null
=
True
,
blank
=
True
,
db_index
=
True
,
on_delete
=
models
.
PROTECT
)
content_quantity
=
models
.
DecimalField
(
_
(
"content quantity"
),
default
=
DECIMAL_ZERO
,
max_digits
=
6
,
decimal_places
=
3
,
validators
=
[
MinValueValidator
(
0
)])
calculated_customer_content_price
=
ModelMoneyField
(
_
(
"customer content price"
),
default
=
DECIMAL_ZERO
,
max_digits
=
8
,
decimal_places
=
2
)
calculated_content_deposit
=
ModelMoneyField
(
_
(
"content deposit"
),
help_text
=
_
(
'deposit to add to the original content price'
),
default
=
DECIMAL_ZERO
,
max_digits
=
8
,
decimal_places
=
2
)
def
get_calculated_customer_content_price
(
self
):
# workaround for a display problem with Money field in the admin list_display
return
self
.
calculated_customer_content_price
+
self
.
calculated_content_deposit
get_calculated_customer_content_price
.
short_description