|
|
@@ -1,4 +1,5 @@
|
|
1
|
1
|
from decimal import Decimal as D
|
|
|
2
|
+import warnings
|
|
2
|
3
|
|
|
3
|
4
|
from django.db import models
|
|
4
|
5
|
from django.conf import settings
|
|
|
@@ -173,6 +174,21 @@ class AbstractStockRecord(models.Model):
|
|
173
|
174
|
verbose_name = _("Stock record")
|
|
174
|
175
|
verbose_name_plural = _("Stock records")
|
|
175
|
176
|
|
|
|
177
|
+ @property
|
|
|
178
|
+ def net_stock_level(self):
|
|
|
179
|
+ """
|
|
|
180
|
+ The effective number in stock (eg available to buy).
|
|
|
181
|
+
|
|
|
182
|
+ This is correct property to show the customer, not the num_in_stock
|
|
|
183
|
+ field as that doesn't account for allocations. This can be negative in
|
|
|
184
|
+ some unusual circumstances
|
|
|
185
|
+ """
|
|
|
186
|
+ if self.num_in_stock is None:
|
|
|
187
|
+ return 0
|
|
|
188
|
+ if self.num_allocated is None:
|
|
|
189
|
+ return self.num_in_stock
|
|
|
190
|
+ return self.num_in_stock - self.num_allocated
|
|
|
191
|
+
|
|
176
|
192
|
# 2-stage stock management model
|
|
177
|
193
|
|
|
178
|
194
|
def allocate(self, quantity):
|
|
|
@@ -189,6 +205,9 @@ class AbstractStockRecord(models.Model):
|
|
189
|
205
|
allocate.alters_data = True
|
|
190
|
206
|
|
|
191
|
207
|
def is_allocation_consumption_possible(self, quantity):
|
|
|
208
|
+ """
|
|
|
209
|
+ Test if a proposed stock consumption is permitted
|
|
|
210
|
+ """
|
|
192
|
211
|
return quantity <= min(self.num_allocated, self.num_in_stock)
|
|
193
|
212
|
|
|
194
|
213
|
def consume_allocation(self, quantity):
|
|
|
@@ -213,32 +232,23 @@ class AbstractStockRecord(models.Model):
|
|
213
|
232
|
self.save()
|
|
214
|
233
|
cancel_allocation.alters_data = True
|
|
215
|
234
|
|
|
216
|
|
- @property
|
|
217
|
|
- def net_stock_level(self):
|
|
218
|
|
- """
|
|
219
|
|
- Return the effective number in stock. This is correct property to show
|
|
220
|
|
- the customer, not the num_in_stock field as that doesn't account for
|
|
221
|
|
- allocations. This can be negative in some unusual circumstances
|
|
222
|
|
- """
|
|
223
|
|
- if self.num_in_stock is None:
|
|
224
|
|
- return 0
|
|
225
|
|
- if self.num_allocated is None:
|
|
226
|
|
- return self.num_in_stock
|
|
227
|
|
- return self.num_in_stock - self.num_allocated
|
|
228
|
|
-
|
|
229
|
235
|
@property
|
|
230
|
236
|
def is_below_threshold(self):
|
|
231
|
237
|
if self.low_stock_threshold is None:
|
|
232
|
238
|
return False
|
|
233
|
239
|
return self.net_stock_level < self.low_stock_threshold
|
|
234
|
240
|
|
|
235
|
|
- # Stock wrapper methods
|
|
|
241
|
+ # Stock wrapper methods - deprecated since 0.6
|
|
236
|
242
|
|
|
237
|
243
|
@property
|
|
238
|
244
|
def is_available_to_buy(self):
|
|
239
|
245
|
"""
|
|
240
|
246
|
Return whether this stockrecord allows the product to be purchased
|
|
241
|
247
|
"""
|
|
|
248
|
+ warnings.warn((
|
|
|
249
|
+ "StockRecord.is_available_to_buy is deprecated and will be "
|
|
|
250
|
+ "removed in 0.7. Use a strategy class to determine availability "
|
|
|
251
|
+ "instead"), DeprecationWarning)
|
|
242
|
252
|
return get_partner_wrapper(self.partner_id).is_available_to_buy(self)
|
|
243
|
253
|
|
|
244
|
254
|
def is_purchase_permitted(self, user=None, quantity=1, product=None):
|
|
|
@@ -246,6 +256,10 @@ class AbstractStockRecord(models.Model):
|
|
246
|
256
|
Return whether this stockrecord allows the product to be purchased by a
|
|
247
|
257
|
specific user and quantity
|
|
248
|
258
|
"""
|
|
|
259
|
+ warnings.warn((
|
|
|
260
|
+ "StockRecord.is_purchase_permitted is deprecated and will be "
|
|
|
261
|
+ "removed in 0.7. Use a strategy class to determine availability "
|
|
|
262
|
+ "instead"), DeprecationWarning)
|
|
249
|
263
|
return get_partner_wrapper(
|
|
250
|
264
|
self.partner_id).is_purchase_permitted(
|
|
251
|
265
|
self, user, quantity, product)
|
|
|
@@ -257,6 +271,10 @@ class AbstractStockRecord(models.Model):
|
|
257
|
271
|
to the overall availability mark-up. For example, "instock",
|
|
258
|
272
|
"unavailable".
|
|
259
|
273
|
"""
|
|
|
274
|
+ warnings.warn((
|
|
|
275
|
+ "StockRecord.availability_code is deprecated and will be "
|
|
|
276
|
+ "removed in 0.7. Use a strategy class to determine availability "
|
|
|
277
|
+ "instead"), DeprecationWarning)
|
|
260
|
278
|
return get_partner_wrapper(self.partner_id).availability_code(self)
|
|
261
|
279
|
|
|
262
|
280
|
@property
|
|
|
@@ -265,6 +283,10 @@ class AbstractStockRecord(models.Model):
|
|
265
|
283
|
Return a product's availability as a string that can be displayed to
|
|
266
|
284
|
the user. For example, "In stock", "Unavailable".
|
|
267
|
285
|
"""
|
|
|
286
|
+ warnings.warn((
|
|
|
287
|
+ "StockRecord.availability is deprecated and will be "
|
|
|
288
|
+ "removed in 0.7. Use a strategy class to determine availability "
|
|
|
289
|
+ "instead"), DeprecationWarning)
|
|
268
|
290
|
return get_partner_wrapper(self.partner_id).availability(self)
|
|
269
|
291
|
|
|
270
|
292
|
def max_purchase_quantity(self, user=None):
|
|
|
@@ -273,6 +295,10 @@ class AbstractStockRecord(models.Model):
|
|
273
|
295
|
|
|
274
|
296
|
:param user: (optional) The user who wants to purchase
|
|
275
|
297
|
"""
|
|
|
298
|
+ warnings.warn((
|
|
|
299
|
+ "StockRecord.max_purchase_quantity is deprecated and will be "
|
|
|
300
|
+ "removed in 0.7. Use a strategy class to determine availability "
|
|
|
301
|
+ "instead"), DeprecationWarning)
|
|
276
|
302
|
return get_partner_wrapper(
|
|
277
|
303
|
self.partner_id).max_purchase_quantity(self, user)
|
|
278
|
304
|
|
|
|
@@ -281,13 +307,21 @@ class AbstractStockRecord(models.Model):
|
|
281
|
307
|
"""
|
|
282
|
308
|
Return the estimated dispatch date for a line
|
|
283
|
309
|
"""
|
|
|
310
|
+ warnings.warn((
|
|
|
311
|
+ "StockRecord.dispatch_date is deprecated and will be "
|
|
|
312
|
+ "removed in 0.7. Use a strategy class to determine availability "
|
|
|
313
|
+ "instead"), DeprecationWarning)
|
|
284
|
314
|
return get_partner_wrapper(self.partner_id).dispatch_date(self)
|
|
285
|
315
|
|
|
286
|
316
|
@property
|
|
287
|
317
|
def lead_time(self):
|
|
|
318
|
+ warnings.warn((
|
|
|
319
|
+ "StockRecord.lead_time is deprecated and will be "
|
|
|
320
|
+ "removed in 0.7. Use a strategy class to determine availability "
|
|
|
321
|
+ "instead"), DeprecationWarning)
|
|
288
|
322
|
return get_partner_wrapper(self.partner_id).lead_time(self)
|
|
289
|
323
|
|
|
290
|
|
- # Price methods
|
|
|
324
|
+ # Price methods - deprecated in 0.6
|
|
291
|
325
|
|
|
292
|
326
|
@property
|
|
293
|
327
|
def price_incl_tax(self):
|
|
|
@@ -298,6 +332,10 @@ class AbstractStockRecord(models.Model):
|
|
298
|
332
|
domain specific. This class needs to be subclassed and tax logic
|
|
299
|
333
|
added to this method.
|
|
300
|
334
|
"""
|
|
|
335
|
+ warnings.warn((
|
|
|
336
|
+ "StockRecord.price_incl_tax is deprecated and will be "
|
|
|
337
|
+ "removed in 0.7. Use a strategy class to determine price "
|
|
|
338
|
+ "information instead"), DeprecationWarning, stacklevel=2)
|
|
301
|
339
|
if self.price_excl_tax is None:
|
|
302
|
340
|
return D('0.00')
|
|
303
|
341
|
return self.price_excl_tax + self.price_tax
|
|
|
@@ -307,6 +345,10 @@ class AbstractStockRecord(models.Model):
|
|
307
|
345
|
"""
|
|
308
|
346
|
Return a product's tax value
|
|
309
|
347
|
"""
|
|
|
348
|
+ warnings.warn((
|
|
|
349
|
+ "StockRecord.price_incl_tax is deprecated and will be "
|
|
|
350
|
+ "removed in 0.7. Use a strategy class to determine price "
|
|
|
351
|
+ "information instead"), DeprecationWarning)
|
|
310
|
352
|
return get_partner_wrapper(self.partner_id).calculate_tax(self)
|
|
311
|
353
|
|
|
312
|
354
|
|