trex-model 1.5.24__tar.gz → 1.5.26__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of trex-model might be problematic. Click here for more details.

Files changed (64) hide show
  1. {trex-model-1.5.24 → trex-model-1.5.26}/PKG-INFO +1 -1
  2. {trex-model-1.5.24 → trex-model-1.5.26}/setup.py +1 -1
  3. {trex-model-1.5.24 → trex-model-1.5.26}/trex_model.egg-info/PKG-INFO +1 -1
  4. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/customer_models.py +17 -3
  5. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/marketing_models.py +24 -1
  6. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/membership_models.py +18 -16
  7. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/merchant_models.py +1 -1
  8. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/ndb_models.py +31 -1
  9. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/rating_models.py +34 -8
  10. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/redeem_models.py +16 -4
  11. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/redemption_catalogue_models.py +26 -1
  12. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/transaction_models.py +7 -0
  13. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/voucher_models.py +9 -10
  14. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/merchant_helpers.py +3 -0
  15. {trex-model-1.5.24 → trex-model-1.5.26}/LICENSE +0 -0
  16. {trex-model-1.5.24 → trex-model-1.5.26}/MANIFEST.in +0 -0
  17. {trex-model-1.5.24 → trex-model-1.5.26}/README.md +0 -0
  18. {trex-model-1.5.24 → trex-model-1.5.26}/setup.cfg +0 -0
  19. {trex-model-1.5.24 → trex-model-1.5.26}/trex_model.egg-info/SOURCES.txt +0 -0
  20. {trex-model-1.5.24 → trex-model-1.5.26}/trex_model.egg-info/dependency_links.txt +0 -0
  21. {trex-model-1.5.24 → trex-model-1.5.26}/trex_model.egg-info/requires.txt +0 -0
  22. {trex-model-1.5.24 → trex-model-1.5.26}/trex_model.egg-info/top_level.txt +0 -0
  23. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/__init__.py +0 -0
  24. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/conf.py +0 -0
  25. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/__init__.py +0 -0
  26. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/__init__.py +0 -0
  27. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/admin_models.py +0 -0
  28. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/analytic_models.py +0 -0
  29. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/app_models.py +0 -0
  30. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/coporate_models.py +0 -0
  31. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/customer_model_helpers.py +0 -0
  32. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/fb_subsriber_models.py +0 -0
  33. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/helper/__init__.py +0 -0
  34. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/helper/reward_model_helpers.py +0 -0
  35. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/helper/reward_transaction_helper.py +0 -0
  36. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/import_models.py +0 -0
  37. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/inventory_model.py +0 -0
  38. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/loyalty_models.py +0 -0
  39. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/lucky_draw_models.py +0 -0
  40. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/merchant_promotion_models.py +0 -0
  41. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/message_model_helper.py +0 -0
  42. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/message_models.py +0 -0
  43. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/model_decorators.py +0 -0
  44. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/pos_models.py +0 -0
  45. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/prepaid_models.py +0 -0
  46. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/product_models.py +0 -0
  47. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/program_models.py +0 -0
  48. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/recruit_models.py +0 -0
  49. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/referral_program_model.py +0 -0
  50. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/reward_models.py +0 -0
  51. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/spending_base_program_model.py +0 -0
  52. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/system_models.py +0 -0
  53. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/task_models.py +0 -0
  54. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/test_models.py +0 -0
  55. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/datastore/user_models.py +0 -0
  56. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/model_decorator.py +0 -0
  57. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/models/prepaid_helpers.py +0 -0
  58. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/pos_conf.py +0 -0
  59. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/program_conf.py +0 -0
  60. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/utils/__init__.py +0 -0
  61. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/utils/gcloud/__init__.py +0 -0
  62. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/utils/gcloud/datastore_util.py +0 -0
  63. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/utils/model/__init__.py +0 -0
  64. {trex-model-1.5.24 → trex-model-1.5.26}/trexmodel/utils/model/model_util.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: trex-model
3
- Version: 1.5.24
3
+ Version: 1.5.26
4
4
  Summary: TRex database module package
5
5
  Home-page: https://bitbucket.org/lokjac/trex-model
6
6
  Author: Jack Lok
@@ -3,7 +3,7 @@ with open("README.md", "r") as fh:
3
3
  long_description = fh.read()
4
4
  setuptools.setup(
5
5
  name='trex-model',
6
- version='1.5.24',
6
+ version='1.5.26',
7
7
  author="Jack Lok",
8
8
  author_email="sglok77@gmail.com",
9
9
  description="TRex database module package",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: trex-model
3
- Version: 1.5.24
3
+ Version: 1.5.26
4
4
  Summary: TRex database module package
5
5
  Home-page: https://bitbucket.org/lokjac/trex-model
6
6
  Author: Jack Lok
@@ -314,7 +314,21 @@ class Customer(BaseNModel, DictModel, FullTextSearchable):
314
314
  password=None, reference_code=None,
315
315
  is_email_verified=False, is_mobile_phone_verified=False):
316
316
 
317
- created_user = User.create(name=name, email=email, mobile_phone=mobile_phone,
317
+ if is_not_empty(email):
318
+ checking_user = User.get_by_email(email)
319
+ elif is_not_empty(mobile_phone):
320
+ checking_user = User.get_by_email(mobile_phone)
321
+
322
+ if checking_user is not None:
323
+ created_user = checking_user
324
+ created_user.name = name
325
+ created_user.email = email
326
+ created_user.mobile_phone = mobile_phone
327
+ created_user.gender = gender
328
+ created_user.password = password
329
+ created_user.birth_date = birth_date
330
+ else:
331
+ created_user = User.create(name=name, email=email, mobile_phone=mobile_phone,
318
332
  gender=gender, birth_date=birth_date,
319
333
  password=password, reference_code=reference_code,
320
334
  is_email_verified=is_email_verified,
@@ -910,11 +924,11 @@ class CustomerMembership(BaseNModel, DictModel):
910
924
 
911
925
 
912
926
  @staticmethod
913
- def create(customer, merchant_membership, entitled_datetime=None, assigned_outlet=None, assigned_by=None):
927
+ def create(customer, merchant_membership, entitled_datetime=None, assigned_outlet=None, assigned_by=None, number_of_year=None):
914
928
  if entitled_datetime is None:
915
929
  entitled_datetime = datetime.utcnow()
916
930
 
917
- expiry_date = merchant_membership.calc_expiry_date(start_date=entitled_datetime)
931
+ expiry_date = merchant_membership.calc_expiry_date(start_date=entitled_datetime, number_of_year=number_of_year)
918
932
  logger.debug('expiry_date=%s', expiry_date)
919
933
  merchant_acct = merchant_membership.merchant_acct
920
934
  customer_membership = CustomerMembership(
@@ -14,6 +14,7 @@ import trexmodel.conf as model_conf
14
14
  import logging
15
15
  from _datetime import timedelta
16
16
  from trexconf.program_conf import MERCHANT_NEWS_STATUS_PUBLISH
17
+ from trexconf.conf import MERCHANT_NEWS_BASE_URL
17
18
 
18
19
  logger = logging.getLogger('model')
19
20
 
@@ -223,6 +224,22 @@ class MarketingImage(BaseNModel, DictModel):
223
224
 
224
225
  return image_file
225
226
 
227
+ @staticmethod
228
+ def create_upload_file(image_label, image_file_storage_filename, public_url, merchant_acct, image_file_type=None):
229
+ logger.debug('image_file_type=%s', image_file_type)
230
+
231
+ image_file = MarketingImage(
232
+ parent = merchant_acct.create_ndb_key(),
233
+ image_label = image_label,
234
+ image_file_public_url = public_url,
235
+ image_file_storage_filename = image_file_storage_filename,
236
+ image_file_type = image_file_type,
237
+ )
238
+
239
+ image_file.put()
240
+
241
+ return image_file
242
+
226
243
  @staticmethod
227
244
  def remove_file(image_file, bucket):
228
245
 
@@ -313,7 +330,8 @@ class MerchantNewsFile(BaseNModel, DictModel):
313
330
 
314
331
 
315
332
  dict_properties = ['image_url', 'completed_progress_in_percentage','is_published', 'is_enabled',
316
- 'label', 'desc', 'news_text', 'start_date', 'end_date', 'enabled', 'is_archived',
333
+ 'label', 'desc', 'news_text', 'start_date', 'end_date', 'enabled', 'is_archived',
334
+ 'news_public_url',
317
335
  'completed_status']
318
336
 
319
337
  @property
@@ -326,6 +344,10 @@ class MerchantNewsFile(BaseNModel, DictModel):
326
344
  return self.news_file_public_url
327
345
  else:
328
346
  return conf.MERCHANT_NEWS_DEFAULT_IMAGE
347
+
348
+ @property
349
+ def news_public_url(self):
350
+ return '%s/merchant/marketing/news/%s/show' % (MERCHANT_NEWS_BASE_URL, self.key_in_str)
329
351
 
330
352
  @property
331
353
  def completed_progress_in_percentage(self):
@@ -480,6 +502,7 @@ class MerchantNewsFile(BaseNModel, DictModel):
480
502
  'content' : self.news_text,
481
503
  'start_datetime' : self.start_date.strftime('%d-%m-%Y %H:%M:%S'),
482
504
  'end_datetime' : self.end_date.strftime('%d-%m-%Y %H:%M:%S'),
505
+ 'news_public_url' : self.news_public_url,
483
506
  }
484
507
 
485
508
  def publish(self, published_by=None):
@@ -67,29 +67,31 @@ class MembershipBase(BaseNModel, DictModel):
67
67
  def list_by_merchant_acct(cls, merchant_acct, is_archived=False):
68
68
  return cls.query(ndb.AND(MerchantMembership.archived == is_archived), ancestor=merchant_acct.create_ndb_key()).fetch(limit=model_conf.MAX_FETCH_RECORD)
69
69
 
70
- def calc_expiry_date(self, start_date=None):
70
+ def calc_expiry_date(self, start_date=None, number_of_year=None):
71
71
 
72
72
  if start_date is None:
73
73
  start_date = datetime.utcnow()
74
74
 
75
75
  logger.debug('start_date=%s', start_date)
76
76
  logger.debug('self.expiration_type=%s', self.expiration_type)
77
+ if is_not_empty(number_of_year) and isinstance(number_of_year, int):
78
+ return start_date + relativedelta(years=number_of_year)
79
+ else:
80
+ if self.expiration_type == program_conf.MEMBERSHIP_EXPIRATION_TYPE_AFTER_YEAR:
81
+ return start_date + relativedelta(years=self.expiration_value)
82
+
83
+ elif self.expiration_type == program_conf.MEMBERSHIP_EXPIRATION_TYPE_AFTER_MONTH:
84
+ return start_date + relativedelta(months=self.expiration_value)
77
85
 
78
- if self.expiration_type == program_conf.MEMBERSHIP_EXPIRATION_TYPE_AFTER_YEAR:
79
- return start_date + relativedelta(years=self.expiration_value)
80
-
81
- elif self.expiration_type == program_conf.MEMBERSHIP_EXPIRATION_TYPE_AFTER_MONTH:
82
- return start_date + relativedelta(months=self.expiration_value)
83
-
84
- elif self.expiration_type == program_conf.MEMBERSHIP_EXPIRATION_TYPE_AFTER_WEEK:
85
- return start_date + relativedelta(weeks=self.expiration_value)
86
-
87
- elif self.expiration_type == program_conf.MEMBERSHIP_EXPIRATION_TYPE_AFTER_DAY:
88
- return start_date + relativedelta(days=self.expiration_value)
89
-
90
- else:
91
- #for no expiration
92
- return datetime.max
86
+ elif self.expiration_type == program_conf.MEMBERSHIP_EXPIRATION_TYPE_AFTER_WEEK:
87
+ return start_date + relativedelta(weeks=self.expiration_value)
88
+
89
+ elif self.expiration_type == program_conf.MEMBERSHIP_EXPIRATION_TYPE_AFTER_DAY:
90
+ return start_date + relativedelta(days=self.expiration_value)
91
+
92
+ else:
93
+ #for no expiration
94
+ return datetime.max
93
95
 
94
96
  @classmethod
95
97
  def upload_membership_card_image(cls, membership, uploading_file, merchant_acct, bucket, modified_by=None):
@@ -1442,7 +1442,7 @@ class Outlet(BusinessEntity, FullTextSearchable):
1442
1442
 
1443
1443
  @property
1444
1444
  def merchant_acct_key(self):
1445
- return self.key.parent().urlsafe()
1445
+ return self.key.parent().urlsafe().decode('utf-8')
1446
1446
 
1447
1447
  @property
1448
1448
  def outlet_key(self):
@@ -17,7 +17,33 @@ from trexconf import conf as lib_conf
17
17
  from trexconf import conf as model_conf
18
18
  from google.cloud.datastore.helpers import GeoPoint
19
19
 
20
- logger = logging.getLogger('model')
20
+ #logger = logging.getLogger('model')
21
+ logger = logging.getLogger('target_debug')
22
+
23
+ def clone_entity(entity, parent=None, **extra_args):
24
+ """
25
+ Clone an NDB entity and return the clone.
26
+
27
+ Args:
28
+ entity: The NDB entity to be cloned.
29
+ extra_args: Additional properties to override in the cloned entity.
30
+
31
+ Returns:
32
+ A new instance of the entity's class with copied properties.
33
+ """
34
+ klass = entity.__class__
35
+ props = {}
36
+
37
+ for prop_name, prop in klass._properties.items():
38
+ logger.debug('clone prop_name=%s', prop_name)
39
+ if not isinstance(prop, ndb.ComputedProperty):
40
+ props[prop_name] = getattr(entity, prop_name)
41
+
42
+ props.update(extra_args)
43
+ if parent:
44
+ return klass(parent=parent, **props)
45
+ else:
46
+ return klass(**props)
21
47
 
22
48
  def convert_to_serializable_value(val, none_as_empty_string=False, gmt=0,
23
49
  datetime_format=lib_conf.DEFAULT_DATETIME_FORMAT,
@@ -223,6 +249,10 @@ class NDBModel(object):
223
249
  def create_ndb_key(self):
224
250
  return ndb.Key(flat=self.key.flat())
225
251
 
252
+ def clone(self, parent=None, **overrides):
253
+ return clone_entity(self, parent=parent, **overrides)
254
+
255
+
226
256
  class BaseNModel(DictModel, NDBModel):
227
257
 
228
258
  saved = False
@@ -10,9 +10,10 @@ from trexmodel.models.datastore.user_models import User
10
10
  from trexconf import conf
11
11
  from datetime import datetime, timedelta
12
12
  import logging
13
- from trexmodel.models.datastore.transaction_models import SalesTransaction
13
+ from trexmodel.models.datastore.transaction_models import CustomerTransaction
14
14
 
15
- logger = logging.getLogger('model')
15
+ #logger = logging.getLogger('model')
16
+ logger = logging.getLogger('target_debug')
16
17
 
17
18
  class RatingBase(BaseNModel, DictModel):
18
19
  user_acct = ndb.KeyProperty(name="user_acct", kind=User)
@@ -95,6 +96,24 @@ class OutletRating(RatingBase):
95
96
 
96
97
 
97
98
  outlet_rating.put()
99
+
100
+ @staticmethod
101
+ def update(user_acct, outlet, service_rating=.5, ambience_rating=.5, food_rating=.5, value_rating=.5):
102
+
103
+ outlet_rating = OutletRating.get_user_rating_by_outlet(user_acct, outlet)
104
+ if outlet_rating:
105
+ outlet_rating.previous_service_rating = outlet_rating.service_rating
106
+ outlet_rating.previous_ambience_rating = outlet_rating.ambience_rating
107
+ outlet_rating.previous_food_rating = outlet_rating.food_rating
108
+ outlet_rating.previous_value_rating = outlet_rating.value_rating
109
+
110
+ outlet_rating.service_rating = service_rating
111
+ outlet_rating.ambience_rating = ambience_rating
112
+ outlet_rating.food_rating = food_rating
113
+ outlet_rating.value_rating = value_rating
114
+
115
+
116
+ outlet_rating.put()
98
117
 
99
118
  @staticmethod
100
119
  def __calculate_rating(rating_list):
@@ -146,18 +165,25 @@ class TransactionRating(RatingBase):
146
165
  remarks = ndb.StringProperty(required=False)
147
166
  created_datetime = ndb.DateTimeProperty(required=True, auto_now_add=True)
148
167
 
149
- dict_properties = ['transaction_id','service_rating', 'ambience_rating', 'food_rating','value_rating',
168
+ dict_properties = ['transaction_id','service_rating', 'ambience_rating', 'food_rating','value_rating', 'remarks',
150
169
  ]
151
170
 
152
171
  @staticmethod
153
172
  def create(user_acct, transaction_id, service_rating=.5, ambience_rating=.5, food_rating=.5, value_rating=.5,
154
173
  remarks=None, for_testing=False):
155
- sales_transaction = SalesTransaction.get_by_transaction_id(transaction_id)
156
- if sales_transaction is not None:
157
- outlet = sales_transaction.transact_outlet_entity
158
- merchant_acct = sales_transaction.transact_merchant_acct
159
-
174
+ customer_transaction = CustomerTransaction.get_by_transaction_id(transaction_id)
175
+
176
+ logger.info('customer_transaction=%s', customer_transaction)
177
+ logger.info('for_testing=%s', for_testing)
178
+
179
+ if customer_transaction is not None:
180
+ outlet = customer_transaction.transact_outlet_entity
181
+ merchant_acct = customer_transaction.transact_merchant_acct
182
+
160
183
  transaction_rating = TransactionRating.get_by_transaction_id(transaction_id)
184
+
185
+ logger.info('transaction_rating=%s', transaction_rating)
186
+
161
187
  if transaction_rating is None:
162
188
  transaction_rating = TransactionRating(
163
189
  user_acct = user_acct.create_ndb_key(),
@@ -151,6 +151,11 @@ class CustomerRedemption(BaseNModel, DictModel):
151
151
  def redeemed_outlet_details(self):
152
152
  if self.redeemed_outlet:
153
153
  return Outlet.fetch(self.redeemed_outlet_key)
154
+
155
+ @property
156
+ def redeemed_outlet_name(self):
157
+ if self.redeemed_outlet_details:
158
+ return self.redeemed_outlet_details.name
154
159
 
155
160
  @property
156
161
  def redeemed_customer_key(self):
@@ -246,10 +251,17 @@ class CustomerRedemption(BaseNModel, DictModel):
246
251
  return CustomerRedemption.query(ndb.AND(CustomerRedemption.status==status), ancestor=customer.create_ndb_key()).fetch(limit=limit)
247
252
 
248
253
  @staticmethod
249
- def list_customer_redemption(customer_acct, offset=0, limit=conf.PAGINATION_SIZE, start_cursor=None, return_with_cursor=False):
250
- query = CustomerRedemption.query(ancestor = customer_acct.create_ndb_key()).order(-CustomerRedemption.redeemed_datetime)
251
-
252
- return CustomerRedemption.list_all_with_condition_query(query, offset=offset, limit=limit, start_cursor=start_cursor, return_with_cursor=return_with_cursor)
254
+ def list_customer_redemption(customer_acct, offset=0, limit=conf.PAGINATION_SIZE, start_cursor=None, return_with_cursor=False, reverse_order=True, keys_only=False):
255
+ if keys_only:
256
+ query = CustomerRedemption.query(ancestor = customer_acct.create_ndb_key())
257
+ return CustomerRedemption.list_all_with_condition_query(query, offset=offset, limit=limit, keys_only=True)
258
+ else:
259
+ if reverse_order:
260
+ query = CustomerRedemption.query(ancestor = customer_acct.create_ndb_key()).order(-CustomerRedemption.redeemed_datetime)
261
+ else:
262
+ query = CustomerRedemption.query(ancestor = customer_acct.create_ndb_key()).order(CustomerRedemption.redeemed_datetime)
263
+
264
+ return CustomerRedemption.list_all_with_condition_query(query, offset=offset, limit=limit, start_cursor=start_cursor, return_with_cursor=return_with_cursor)
253
265
 
254
266
  @staticmethod
255
267
  def list_by_outlet(redeemed_outlet, offset=0, limit=conf.PAGINATION_SIZE, start_cursor=None, return_with_cursor=False):
@@ -12,6 +12,8 @@ from trexmodel.models.datastore.merchant_models import MerchantUser,\
12
12
  MerchantAcct
13
13
  from trexlib.utils.string_util import is_not_empty, is_empty
14
14
  from trexmodel.models.datastore.model_decorators import model_transactional
15
+ from trexconf.program_conf import REDEMPTION_CATALOGUE_STATUS_DEFINED_CATALOGUE,\
16
+ REDEMPTION_CATALOGUE_STATUS_NEW
15
17
 
16
18
  logger = logging.getLogger('model')
17
19
 
@@ -49,7 +51,7 @@ class RedemptionCatalogue(BaseNModel, DictModel):
49
51
  "redeem_reward_format","catalogue_settings", "image_storage_filename", "image_public_url",
50
52
  "exclusive_tags_list", "exclusive_memberships_list", "exclusive_tier_memberships_list",
51
53
  "completed_progress_in_percentage","completed_status_index", "catalogue_items",
52
- "is_enabled", "is_disabled", "is_archived", "is_published", "loyalty_package",
54
+ "is_enabled", "is_disabled", "is_archived", "is_published", "loyalty_package", "is_expired",
53
55
  ]
54
56
 
55
57
  @property
@@ -64,6 +66,10 @@ class RedemptionCatalogue(BaseNModel, DictModel):
64
66
  def is_archived(self):
65
67
  return self.archived
66
68
 
69
+ @property
70
+ def is_expired(self):
71
+ return self.end_date<datetime.today().date()
72
+
67
73
  @property
68
74
  def is_published(self):
69
75
  return self.completed_status == program_conf.PROGRAM_STATUS_PUBLISH
@@ -157,6 +163,25 @@ class RedemptionCatalogue(BaseNModel, DictModel):
157
163
  return redemption_catalogue
158
164
 
159
165
 
166
+ def clone(self, created_by=None, **overrides):
167
+ created_datetime = datetime.utcnow();
168
+ overrides.setdefault('created_datetime', created_datetime)
169
+ overrides.setdefault('modified_datetime', created_datetime)
170
+ overrides.setdefault('published_datetime', None)
171
+ overrides.setdefault('archived_datetime', None)
172
+ overrides.setdefault('completed_status', REDEMPTION_CATALOGUE_STATUS_NEW)
173
+
174
+ created_by_username = None
175
+ if is_not_empty(created_by):
176
+ if isinstance(created_by, MerchantUser):
177
+ created_by_username = created_by.username
178
+
179
+ overrides.setdefault('created_by', created_by.create_ndb_key())
180
+ overrides.setdefault('created_by_username', created_by_username)
181
+
182
+ new_cloned = super().clone(parent=self.key.parent(), **overrides)
183
+ return new_cloned
184
+
160
185
  def remove_redemption_catalogue_item(self, voucher_index, modified_by=None):
161
186
  modified_by_username = None
162
187
  if is_not_empty(modified_by):
@@ -266,6 +266,13 @@ class CustomerTransaction(SalesTransaction):
266
266
  if self.transact_outlet:
267
267
  return Outlet.fetch(self.transact_outlet.urlsafe())
268
268
 
269
+ @property
270
+ def transact_outlet_name(self):
271
+ outlet = self.transact_outlet_details
272
+ if outlet:
273
+ return self.transact_outlet_details.name
274
+ else:
275
+ return ''
269
276
 
270
277
  @property
271
278
  def purchased_merchant_membership_key(self):
@@ -385,6 +385,14 @@ class MerchantVoucher(VoucherBase):
385
385
  final_list.append(v)
386
386
  return final_list
387
387
 
388
+ @staticmethod
389
+ def list_latest_by_merchant_account(merchant_acct):
390
+ vouchers_list = MerchantVoucher.query(ndb.AND(MerchantVoucher.archived==False), ancestor=merchant_acct.create_ndb_key()).fetch(limit=model_conf.MAX_FETCH_RECORD)
391
+ final_list = []
392
+ for v in vouchers_list:
393
+ final_list.append(v)
394
+ return final_list
395
+
388
396
  @staticmethod
389
397
  def list_archived_by_merchant_account(merchant_acct):
390
398
  return MerchantVoucher.query(ndb.AND(MerchantVoucher.archived==True), ancestor=merchant_acct.create_ndb_key()).fetch(limit=model_conf.MAX_FETCH_RECORD)
@@ -393,16 +401,7 @@ class MerchantVoucher(VoucherBase):
393
401
  def list_published_by_merchant_account(merchant_acct):
394
402
  return MerchantVoucher.query(ndb.AND(MerchantVoucher.completed_status==program_conf.VOUCHER_STATUS_PUBLISH), ancestor=merchant_acct.create_ndb_key()).fetch(limit=model_conf.MAX_FETCH_RECORD)
395
403
 
396
- @staticmethod
397
- def list_latest_by_merchant_account(merchant_acct):
398
- published_vouchers_list = MerchantVoucher.query(ndb.AND(MerchantVoucher.completed_status==program_conf.VOUCHER_STATUS_PUBLISH), ancestor=merchant_acct.create_ndb_key()).fetch(limit=model_conf.MAX_FETCH_RECORD)
399
-
400
- filtered_out_archived_vouchers_list = []
401
- for voucher in published_vouchers_list:
402
- if voucher.archived==False:
403
- filtered_out_archived_vouchers_list.append(voucher)
404
-
405
- return filtered_out_archived_vouchers_list
404
+
406
405
 
407
406
  class BrandVouhcer(VoucherBase):
408
407
  #merchant_acct = ndb.KeyProperty(name="merchant_acct", kind=MerchantAcct)
@@ -45,6 +45,9 @@ def construct_merchant_acct_info(merchant_acct):
45
45
 
46
46
  if merchant_acct.published_news_configuration:
47
47
  merchant_news_list = merchant_acct.published_news_configuration['news']
48
+
49
+ for news in merchant_news_list:
50
+ logger.debug('news public url=%s', news.get('news_public_url'))
48
51
 
49
52
  published_redemption_catalogue_configuration = merchant_acct.published_redemption_catalogue_configuration
50
53
  catalogues_list = []
File without changes
File without changes
File without changes
File without changes