Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

models.py 3.1KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. import datetime
  2. import os
  3. import csv
  4. from django.db import models
  5. Product = models.get_model('catalogue', 'Product')
  6. class RangeProductFileUpload(models.Model):
  7. range = models.ForeignKey('offer.Range', related_name='file_uploads')
  8. filepath = models.CharField(max_length=255)
  9. size = models.PositiveIntegerField()
  10. uploaded_by = models.ForeignKey('auth.User')
  11. date_uploaded = models.DateTimeField(auto_now_add=True)
  12. PENDING, FAILED, PROCESSED = 'Pending', 'Failed', 'Processed'
  13. choices = (
  14. (PENDING, PENDING),
  15. (FAILED, FAILED),
  16. (PROCESSED, PROCESSED),
  17. )
  18. status = models.CharField(max_length=32, choices=choices, default=PENDING)
  19. error_message = models.CharField(max_length=255, null=True)
  20. # Post-processing audit fields
  21. date_processed = models.DateTimeField(null=True)
  22. num_new_skus = models.PositiveIntegerField(null=True)
  23. num_unknown_skus = models.PositiveIntegerField(null=True)
  24. num_duplicate_skus = models.PositiveIntegerField(null=True)
  25. class Meta:
  26. ordering = ('-date_uploaded',)
  27. @property
  28. def filename(self):
  29. return os.path.basename(self.filepath)
  30. def mark_as_failed(self, message=None):
  31. self.date_processed = datetime.datetime.now()
  32. self.error_message = message
  33. self.status = self.FAILED
  34. self.save()
  35. def mark_as_processed(self, num_new, num_unknown, num_duplicate):
  36. self.status = self.PROCESSED
  37. self.date_processed = datetime.datetime.now()
  38. self.num_new_skus = num_new
  39. self.num_unknown_skus = num_unknown
  40. self.num_duplicate_skus = num_duplicate
  41. self.save()
  42. def was_processing_successful(self):
  43. return self.status == self.PROCESSED
  44. def process(self):
  45. """
  46. Process the file upload and add products to the range
  47. """
  48. all_ids = set(self.extract_ids())
  49. products = self.range.included_products.all()
  50. existing_skus = set(products.values_list('stockrecord__partner_sku', flat=True))
  51. existing_upcs = set(products.values_list('upc', flat=True))
  52. existing_ids = existing_skus.union(existing_upcs)
  53. new_ids = all_ids - existing_ids
  54. products = Product._default_manager.filter(
  55. models.Q(stockrecord__partner_sku__in=new_ids) |
  56. models.Q(upc__in=new_ids))
  57. for product in products:
  58. self.range.included_products.add(product)
  59. # Processing stats
  60. found_skus = set(products.values_list('stockrecord__partner_sku', flat=True))
  61. found_upcs = set(products.values_list('upc', flat=True))
  62. found_ids = found_skus.union(found_upcs)
  63. missing_ids = new_ids - found_ids
  64. dupes = set(all_ids).intersection(existing_ids)
  65. self.mark_as_processed(len(found_ids), len(missing_ids), len(dupes))
  66. def extract_ids(self):
  67. """
  68. Extract all SKU- or UPC-like strings from the file
  69. """
  70. reader = csv.reader(open(self.filepath, 'r'))
  71. for row in reader:
  72. for field in row:
  73. yield field
  74. def delete_file(self):
  75. os.unlink(self.filepath)