trex-model 1.2.17__tar.gz → 1.2.19__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 (59) hide show
  1. {trex-model-1.2.17 → trex-model-1.2.19}/PKG-INFO +1 -1
  2. {trex-model-1.2.17 → trex-model-1.2.19}/setup.py +1 -1
  3. {trex-model-1.2.17 → trex-model-1.2.19}/trex_model.egg-info/PKG-INFO +1 -1
  4. {trex-model-1.2.17 → trex-model-1.2.19}/trex_model.egg-info/SOURCES.txt +1 -0
  5. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/customer_models.py +3 -1
  6. trex-model-1.2.19/trexmodel/models/datastore/marketing_models.py +226 -0
  7. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/merchant_models.py +12 -6
  8. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/ndb_models.py +2 -1
  9. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/redemption_catalogue_models.py +10 -4
  10. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/system_models.py +19 -4
  11. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/user_models.py +46 -4
  12. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/program_conf.py +12 -3
  13. {trex-model-1.2.17 → trex-model-1.2.19}/LICENSE +0 -0
  14. {trex-model-1.2.17 → trex-model-1.2.19}/MANIFEST.in +0 -0
  15. {trex-model-1.2.17 → trex-model-1.2.19}/README.md +0 -0
  16. {trex-model-1.2.17 → trex-model-1.2.19}/setup.cfg +0 -0
  17. {trex-model-1.2.17 → trex-model-1.2.19}/trex_model.egg-info/dependency_links.txt +0 -0
  18. {trex-model-1.2.17 → trex-model-1.2.19}/trex_model.egg-info/requires.txt +0 -0
  19. {trex-model-1.2.17 → trex-model-1.2.19}/trex_model.egg-info/top_level.txt +0 -0
  20. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/__init__.py +0 -0
  21. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/conf.py +0 -0
  22. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/__init__.py +0 -0
  23. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/__init__.py +0 -0
  24. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/admin_models.py +0 -0
  25. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/analytic_models.py +0 -0
  26. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/app_models.py +0 -0
  27. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/coporate_models.py +0 -0
  28. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/customer_model_helpers.py +0 -0
  29. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/fb_subsriber_models.py +0 -0
  30. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/import_models.py +0 -0
  31. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/inventory_model.py +0 -0
  32. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/loyalty_models.py +0 -0
  33. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/lucky_draw_models.py +0 -0
  34. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/membership_models.py +0 -0
  35. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/message_model_helper.py +0 -0
  36. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/message_models.py +0 -0
  37. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/model_decorators.py +0 -0
  38. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/pos_models.py +0 -0
  39. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/prepaid_models.py +0 -0
  40. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/product_models.py +0 -0
  41. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/program_models.py +0 -0
  42. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/rating_models.py +0 -0
  43. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/redeem_models.py +0 -0
  44. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/reward_model_helpers.py +0 -0
  45. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/reward_models.py +0 -0
  46. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/spending_base_program_model.py +0 -0
  47. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/task_models.py +0 -0
  48. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/test_models.py +0 -0
  49. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/transaction_models.py +0 -0
  50. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/datastore/voucher_models.py +0 -0
  51. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/merchant_helpers.py +0 -0
  52. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/model_decorator.py +0 -0
  53. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/models/prepaid_helpers.py +0 -0
  54. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/pos_conf.py +0 -0
  55. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/utils/__init__.py +0 -0
  56. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/utils/gcloud/__init__.py +0 -0
  57. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/utils/gcloud/datastore_util.py +0 -0
  58. {trex-model-1.2.17 → trex-model-1.2.19}/trexmodel/utils/model/__init__.py +0 -0
  59. {trex-model-1.2.17 → trex-model-1.2.19}/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.2.17
3
+ Version: 1.2.19
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.2.17',
6
+ version='1.2.19',
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.2.17
3
+ Version: 1.2.19
4
4
  Summary: TRex database module package
5
5
  Home-page: https://bitbucket.org/lokjac/trex-model
6
6
  Author: Jack Lok
@@ -28,6 +28,7 @@ trexmodel/models/datastore/import_models.py
28
28
  trexmodel/models/datastore/inventory_model.py
29
29
  trexmodel/models/datastore/loyalty_models.py
30
30
  trexmodel/models/datastore/lucky_draw_models.py
31
+ trexmodel/models/datastore/marketing_models.py
31
32
  trexmodel/models/datastore/membership_models.py
32
33
  trexmodel/models/datastore/merchant_models.py
33
34
  trexmodel/models/datastore/message_model_helper.py
@@ -70,6 +70,8 @@ class Customer(BaseNModel, DictModel, FullTextSearchable):
70
70
 
71
71
  kpi_summary = ndb.JsonProperty()
72
72
 
73
+ device_details = ndb.JsonProperty()
74
+
73
75
  fulltextsearch_field_name = 'name'
74
76
 
75
77
  dict_properties = ['name', 'mobile_phone', 'email', 'gender', 'birth_date', 'reference_code', 'merchant_reference_code',
@@ -77,7 +79,7 @@ class Customer(BaseNModel, DictModel, FullTextSearchable):
77
79
  'reward_summary', 'entitled_voucher_summary', 'prepaid_summary', 'kpi_summary', 'entitled_lucky_draw_ticket_summary',
78
80
  'entitled_birthday_reward_summary', 'tier_membership_key',
79
81
  'registered_outlet_key', 'registered_merchant_acct_key', 'registered_datetime', 'modified_datetime',
80
-
82
+ 'registered_user_acct',
81
83
 
82
84
  ]
83
85
 
@@ -0,0 +1,226 @@
1
+ '''
2
+ Created on 8 Jan 2024
3
+
4
+ @author: jacklok
5
+ '''
6
+ from trexmodel.models.datastore.ndb_models import BaseNModel, DictModel
7
+ from google.cloud import ndb
8
+ from trexmodel.models.datastore.merchant_models import MerchantUser,\
9
+ MerchantAcct
10
+ from trexlib.utils.string_util import is_not_empty, random_string
11
+ from datetime import datetime
12
+ from trexmodel import program_conf, conf
13
+ import trexmodel.conf as model_conf
14
+ import logging
15
+
16
+ logger = logging.getLogger('model')
17
+
18
+ class PushNotificationSetup(BaseNModel, DictModel):
19
+ '''
20
+ Merchant Acct as ancestor
21
+
22
+ '''
23
+
24
+ title = ndb.StringProperty(required=True)
25
+ desc = ndb.StringProperty(required=True)
26
+ send_mode = ndb.StringProperty(required=True, default="send_now", choices=set(['send_now','send_schedule']))
27
+ schedule_datetime = ndb.DateTimeProperty(required=False)
28
+
29
+ content_settings = ndb.JsonProperty()
30
+
31
+ is_archived = ndb.BooleanProperty(required=True)
32
+
33
+ created_datetime = ndb.DateTimeProperty(required=True, auto_now_add=True)
34
+ archived_datetime = ndb.DateTimeProperty(required=False)
35
+
36
+ created_by = ndb.KeyProperty(name="created_by", kind=MerchantUser)
37
+ created_by_username = ndb.StringProperty(required=False)
38
+
39
+ archived_by = ndb.KeyProperty(name="created_by", kind=MerchantUser)
40
+ archived_by_username = ndb.StringProperty(required=False)
41
+
42
+ send = ndb.BooleanProperty(required=True, default=False)
43
+ sent_datetime = ndb.DateTimeProperty(required=False)
44
+
45
+ dict_properties = [
46
+ 'title', 'desc', 'send_mode', 'schedule_datetime',
47
+ 'content_type', 'content_value', 'content_settings',
48
+ 'created_datetime', 'send', 'sent_datetime',
49
+ ]
50
+
51
+ @property
52
+ def merchant_acct_entity(self):
53
+ return MerchantAcct.fetch(self.key.parent().urlsafe())
54
+
55
+ @property
56
+ def content_type(self):
57
+ if self.content_settings:
58
+ return self.content_settings.get('content_type')
59
+
60
+ @property
61
+ def content_value(self):
62
+ if self.content_settings:
63
+ return self.content_settings.get('content_value')
64
+
65
+ @property
66
+ def image_url(self):
67
+ if self.content_settings:
68
+ if self.content_settings.get('content_type')=='image':
69
+ return self.content_settings.get('content_value')
70
+
71
+ @property
72
+ def text_data(self):
73
+ if self.content_settings:
74
+ if self.content_settings.get('content_type')=='text':
75
+ return self.content_settings.get('content_value')
76
+
77
+ @property
78
+ def action_link(self):
79
+ if self.content_settings:
80
+ if self.content_settings.get('content_type')=='action_link':
81
+ return self.content_settings.get('content_value')
82
+
83
+ @staticmethod
84
+ def create(merchant_acct, title=None, desc=None, send_mode=None, schedule_datetime=None, content_settings={},
85
+ created_by=None):
86
+
87
+ created_by_username = None
88
+ if is_not_empty(created_by):
89
+ if isinstance(created_by, MerchantUser):
90
+ created_by_username = created_by.username
91
+
92
+
93
+ push_notification_setup = PushNotificationSetup(
94
+ parent = merchant_acct.create_ndb_key(),
95
+ title = title,
96
+ desc = desc,
97
+ send_mode = send_mode,
98
+ schedule_datetime = schedule_datetime,
99
+ content_settings = content_settings,
100
+ is_archived = False,
101
+ created_by = created_by.create_ndb_key(),
102
+ created_by_username = created_by_username,
103
+ )
104
+ push_notification_setup.put()
105
+
106
+ return push_notification_setup
107
+
108
+
109
+ def to_configuration(self):
110
+ return {
111
+
112
+ }
113
+
114
+ def archived(self, archived_by=None):
115
+
116
+ archived_by_username = None
117
+ if is_not_empty(archived_by):
118
+ if isinstance(archived_by, MerchantUser):
119
+ archived_by_username = archived_by.username
120
+
121
+ self.is_archived = True
122
+ self.archived_datetime = datetime.utcnow()
123
+ self.archived_by = archived_by.create_ndb_key()
124
+ self.archived_by_username = archived_by_username
125
+ self.put()
126
+
127
+ def update_as_send(self):
128
+ self.send = True
129
+ self.sent_datetime = datetime.utcnow()
130
+ self.put()
131
+
132
+ @staticmethod
133
+ def list_by_merchant_acct(merchant_acct):
134
+ return PushNotificationSetup.query(ndb.AND(PushNotificationSetup.is_archived!=True), ancestor=merchant_acct.create_ndb_key()).fetch(limit=model_conf.MAX_FETCH_RECORD)
135
+
136
+ @staticmethod
137
+ def list_archived_by_merchant_acct(merchant_acct):
138
+ return PushNotificationSetup.query(ndb.AND(PushNotificationSetup.is_archived==True), ancestor=merchant_acct.create_ndb_key()).fetch(limit=model_conf.MAX_FETCH_RECORD)
139
+
140
+ @staticmethod
141
+ def list(schedule_datetime=datetime.utcnow()):
142
+ result = PushNotificationSetup.query(
143
+ ndb.AND(
144
+ PushNotificationSetup.send==False,
145
+ PushNotificationSetup.schedule_datetime<=schedule_datetime)).fetch(offset=0, limit=conf.MAX_FETCH_RECORD)
146
+ return result
147
+
148
+ class MarketingImage(BaseNModel, DictModel):
149
+ '''
150
+ Merchant Account as ancestor
151
+ '''
152
+ image_label = ndb.StringProperty(required=True)
153
+ image_file_type = ndb.StringProperty(required=True)
154
+ image_file_public_url = ndb.StringProperty(required=True)
155
+ image_file_storage_filename = ndb.StringProperty(required=True)
156
+
157
+ dict_properties = ['image_label', 'image_file_public_url', 'image_file_storage_filename', 'image_file_type']
158
+
159
+ @staticmethod
160
+ def list_by_merchant_acct(merchant_acct):
161
+ result = MarketingImage.query(ancestor=merchant_acct.create_ndb_key()).fetch(limit=conf.MAX_FETCH_RECORD)
162
+ return result
163
+
164
+ @staticmethod
165
+ def upload_file(uploading_file, image_label, merchant_acct, bucket, image_file_type=None):
166
+ file_prefix = random_string(8)
167
+ image_file_storage_filename = 'merchant/'+merchant_acct.key_in_str+'/marketing/'+file_prefix+'-'+uploading_file.filename
168
+ blob = bucket.blob(image_file_storage_filename)
169
+
170
+ logger.debug('image_label=%s', image_label)
171
+ logger.debug('image_file_storage_filename=%s', image_file_storage_filename)
172
+
173
+ blob.upload_from_string(
174
+ uploading_file.read(),
175
+ content_type=uploading_file.content_type
176
+ )
177
+
178
+ uploaded_url = blob.public_url
179
+
180
+ logger.debug('image_file_type=%s', image_file_type)
181
+
182
+ image_file = MarketingImage(
183
+ parent = merchant_acct.create_ndb_key(),
184
+ image_label = image_label,
185
+ image_file_public_url = uploaded_url,
186
+ image_file_storage_filename = image_file_storage_filename,
187
+ image_file_type = image_file_type,
188
+ )
189
+
190
+ image_file.put()
191
+
192
+ return image_file
193
+
194
+ @staticmethod
195
+ def remove_file(image_file, bucket):
196
+
197
+ old_logo_blob = bucket.get_blob(image_file.image_file_storage_filename)
198
+ if old_logo_blob:
199
+ old_logo_blob.delete()
200
+ image_file.delete()
201
+
202
+ class ScheduledPushNotificationHistory(BaseNModel, DictModel):
203
+ push_notification_setup = ndb.KeyProperty(name="push_notification_setup", kind=PushNotificationSetup)
204
+ created_datetime = ndb.DateTimeProperty(required=True, auto_now_add=True)
205
+ send = ndb.BooleanProperty(required=True, default=False)
206
+ scheduled_datetime = ndb.DateTimeProperty(required=True)
207
+ sent_datetime = ndb.DateTimeProperty(required=False)
208
+
209
+ @staticmethod
210
+ def create(push_notification_setup, scheduled_datetime=None):
211
+ if scheduled_datetime is None:
212
+ scheduled_datetime = datetime.utcnow()
213
+ ScheduledPushNotificationHistory(
214
+ push_notification_setup = push_notification_setup.create_ndb_key(),
215
+ scheduled_datetime = scheduled_datetime,
216
+ ).put()
217
+
218
+
219
+ @staticmethod
220
+ def list(scheduled_datetime=datetime.utcnow()):
221
+ result = ScheduledPushNotificationHistory.query(
222
+ ndb.AND(
223
+ ScheduledPushNotificationHistory.send==False,
224
+ ScheduledPushNotificationHistory.scheduled_datetime<=scheduled_datetime)).fetch(offset=0, limit=conf.MAX_FETCH_RECORD)
225
+ return result
226
+
@@ -60,6 +60,7 @@ class MerchantAcct(MerchantMin):
60
60
  dashboard_stat_figure = ndb.JsonProperty()
61
61
  currency_code = ndb.StringProperty(required=False, default='MYR')
62
62
  locale = ndb.StringProperty(required=False, default='en_MY')
63
+ timezone = ndb.StringProperty(required=False, default='Asia/Kuala_Lumpur')
63
64
  api_key = ndb.StringProperty(required=False)
64
65
 
65
66
  account_plan = ndb.JsonProperty()
@@ -85,8 +86,10 @@ class MerchantAcct(MerchantMin):
85
86
  stat_figure_update_interval_in_minutes = conf.MERCHANT_STAT_FIGURE_UPDATE_INTERVAL_IN_MINUTES
86
87
  stat_figure_update_datetime_format = '%d-%m-%Y %H:%M:%S'
87
88
 
88
- dict_properties = ['company_name', 'brand_name', 'contact_name', 'business_reg_no', 'mobile_phone', 'office_phone', 'fax_phone', 'email', 'account_code', 'country',
89
+ dict_properties = ['company_name', 'brand_name', 'contact_name', 'business_reg_no', 'mobile_phone',
90
+ 'office_phone', 'fax_phone', 'email', 'account_code', 'country',
89
91
  'registered_datetime', 'modified_datetime', 'plan_start_date', 'plan_end_date', 'currency_code',
92
+ 'timezone',
90
93
  'published_program_configuration', 'published_voucher_configuration', 'membership_configuration',
91
94
  'tier_membership_configuration', 'prepaid_configuration', 'lucky_draw_configuration', 'product_modifier_configuration',
92
95
  'dashboard_stat_figure', 'program_settings', 'is_tier_membership_configured', 'website',
@@ -224,8 +227,7 @@ class MerchantAcct(MerchantMin):
224
227
  @staticmethod
225
228
  def update_details(merchant_acct, company_name=None, brand_name=None, business_reg_no=None, contact_name=None,
226
229
  email=None, mobile_phone=None, office_phone=None, currency_code=None,
227
-
228
- country=None, website=None):
230
+ country=None, timezone=None, website=None):
229
231
 
230
232
 
231
233
 
@@ -238,7 +240,9 @@ class MerchantAcct(MerchantMin):
238
240
  merchant_acct.office_phone = office_phone
239
241
  merchant_acct.currency_code = currency_code
240
242
  merchant_acct.country = country
243
+ merchant_acct.timezone = timezone
241
244
  merchant_acct.website = website
245
+
242
246
  merchant_acct.put()
243
247
 
244
248
  @staticmethod
@@ -882,7 +886,7 @@ class MerchantAcct(MerchantMin):
882
886
  @staticmethod
883
887
  def create(company_name=None, brand_name=None, contact_name=None, email=None, mobile_phone=None, office_phone=None,
884
888
  plan_start_date=None, plan_end_date=None,
885
- account_code=None, currency_code=None, country=None, website=None,
889
+ account_code=None, currency_code=None, country=None, timezone=None, website=None,
886
890
  product_package=None,loyalty_package=None, outlet_limit=1
887
891
  ):
888
892
 
@@ -906,7 +910,8 @@ class MerchantAcct(MerchantMin):
906
910
  plan_start_date = plan_start_date,
907
911
  plan_end_date = plan_end_date,
908
912
  currency_code = currency_code,
909
- country = country,
913
+ country = country,
914
+ timezone = timezone,
910
915
  website = website,
911
916
  api_key = random_string(24),
912
917
  program_settings = MerchantAcct.default_program_settings(),
@@ -925,7 +930,7 @@ class MerchantAcct(MerchantMin):
925
930
  @staticmethod
926
931
  def update(merchant_acct, company_name=None, brand_name=None, contact_name=None, email=None, mobile_phone=None, office_phone=None,
927
932
  plan_start_date=None, plan_end_date=None,
928
- currency_code=None, country=None, website=None,
933
+ currency_code=None, country=None, timezone=None, website=None,
929
934
  product_package=None,loyalty_package=None, outlet_limit=1,
930
935
  ):
931
936
 
@@ -945,6 +950,7 @@ class MerchantAcct(MerchantMin):
945
950
  merchant_acct.plan_end_date = plan_end_date
946
951
  merchant_acct.currency_code = currency_code
947
952
  merchant_acct.country = country
953
+ merchant_acct.timezone = timezone
948
954
  merchant_acct.website = website
949
955
  merchant_acct.account_plan = account_plan
950
956
 
@@ -327,7 +327,8 @@ class BaseNModel(DictModel, NDBModel):
327
327
  if more:
328
328
  return search_results, next_cursor.to_websafe_string().decode('utf-8')
329
329
  else:
330
- return search_results, 'None'
330
+ #return search_results, 'None'
331
+ return search_results, None
331
332
 
332
333
  else:
333
334
  search_results = query.fetch(limit=limit, offset=offset, keys_only=keys_only)
@@ -43,12 +43,14 @@ class RedemptionCatalogue(BaseNModel, DictModel):
43
43
  image_storage_filename = ndb.StringProperty(required=False)
44
44
  image_public_url = ndb.StringProperty(required=False)
45
45
 
46
+ loyalty_package = ndb.StringProperty(required=False, default=program_conf.LOYALTY_PACKAGE_SCALE)
47
+
46
48
  dict_properties = [
47
49
  "label","desc","completed_status","start_date","end_date","created_datetime",
48
50
  "redeem_reward_format","catalogue_settings", "image_storage_filename", "image_public_url",
49
51
  "exclusive_tags_list", "exclusive_memberships_list", "exclusive_tier_memberships_list",
50
52
  "completed_prograss_in_percentage","completed_status_index", "catalogue_items",
51
- "is_enabled", "is_disabled", "is_archived", "is_published",
53
+ "is_enabled", "is_disabled", "is_archived", "is_published", "loyalty_package",
52
54
  ]
53
55
 
54
56
  @property
@@ -92,14 +94,15 @@ class RedemptionCatalogue(BaseNModel, DictModel):
92
94
 
93
95
  @property
94
96
  def completed_prograss_in_percentage(self):
95
- return program_conf.redemption_catalogue_completed_progress_percentage(self.completed_status)
97
+ return program_conf.redemption_catalogue_completed_progress_percentage(self.completed_status, self.loyalty_package)
96
98
 
97
99
  @property
98
100
  def completed_status_index(self):
99
101
  return program_conf.get_redemption_catalogue_completed_status_index(self.completed_status)
100
102
 
101
103
  @staticmethod
102
- def create(merchant_acct, label=None, desc=None, start_date=None, end_date=None, redeem_reward_format=None, created_by=None):
104
+ def create(merchant_acct, label=None, desc=None, start_date=None, end_date=None, redeem_reward_format=None,
105
+ created_by=None, loyalty_package=program_conf.LOYALTY_PACKAGE_SCALE):
103
106
 
104
107
  created_by_username = None
105
108
  if is_not_empty(created_by):
@@ -117,6 +120,7 @@ class RedemptionCatalogue(BaseNModel, DictModel):
117
120
  created_by_username = created_by_username,
118
121
  completed_status = program_conf.REDEMPTION_CATALOGUE_STATUS_DEFINED_CATALOGUE,
119
122
  catalogue_settings = {},
123
+ loyalty_package = loyalty_package,
120
124
  )
121
125
 
122
126
  redemption_catalogue.put()
@@ -124,7 +128,8 @@ class RedemptionCatalogue(BaseNModel, DictModel):
124
128
  return redemption_catalogue
125
129
 
126
130
  @staticmethod
127
- def update(redemption_catalogue, label=None, desc=None, start_date=None, end_date=None, redeem_reward_format=None, modified_by=None):
131
+ def update(redemption_catalogue, label=None, desc=None, start_date=None, end_date=None,
132
+ redeem_reward_format=None, modified_by=None, loyalty_package=program_conf.LOYALTY_PACKAGE_SCALE):
128
133
 
129
134
  modified_by_username = None
130
135
  if is_not_empty(modified_by):
@@ -140,6 +145,7 @@ class RedemptionCatalogue(BaseNModel, DictModel):
140
145
 
141
146
  redemption_catalogue.modified_by = modified_by.create_ndb_key()
142
147
  redemption_catalogue.modified_by_username = modified_by_username
148
+ redemption_catalogue.loyalty_package = loyalty_package
143
149
 
144
150
  redemption_catalogue.put()
145
151
 
@@ -3,10 +3,9 @@ Created on 20 Apr 2020
3
3
 
4
4
  @author: jacklok
5
5
  '''
6
- from trexmodel import conf as model_conf
6
+ from trexmodel import conf as model_conf, conf
7
7
  from google.cloud import ndb
8
8
  from trexmodel.models.datastore.ndb_models import BaseNModel, DictModel
9
-
10
9
 
11
10
  class Country(BaseNModel, DictModel):
12
11
  cnty_id = ndb.IntegerProperty(required=True)
@@ -158,9 +157,25 @@ class Tagging(BaseNModel, DictModel):
158
157
  @classmethod
159
158
  def get_by_label(cls, parent, label):
160
159
  return cls.query(ndb.AND(cls.label==label), ancestor=parent).fetch(limit=1)
160
+
161
+
162
+
163
+ '''
164
+ class ScheduledProjectExecutionHistory(BaseNModel, DictModel):
165
+ merchant_acct = ndb.KeyProperty(name="merchant_acct", kind=MerchantAcct)
166
+ merchant_program = ndb.KeyProperty(name="merchant_program", kind=MerchantProgram)
167
+ created_datetime = ndb.DateTimeProperty(required=True, auto_now_add=True)
161
168
 
162
-
163
-
169
+ @staticmethod
170
+ def create(merchant_acct, merchant_program):
171
+ ScheduledProjectExecutionHistory(
172
+ merchant_acct = merchant_acct.create_ndb_key(),
173
+ merchant_program = merchant_program.create_ndb_key(),
174
+ ).put()
175
+
176
+ '''
177
+
178
+
164
179
 
165
180
 
166
181
 
@@ -45,6 +45,8 @@ class UserMin(BaseNModel, DictModel, UserMixin):
45
45
  demo_account = ndb.BooleanProperty(required=False, default=False)
46
46
  deleted = ndb.BooleanProperty(required=False, default=False)
47
47
 
48
+
49
+
48
50
  dict_properties = ['user_id', 'name', 'email', 'gravatar_url', 'active', 'locked', 'lock_expiry_datetime']
49
51
 
50
52
  @classmethod
@@ -352,11 +354,13 @@ class User(UserBase):
352
354
  redeem_pin = ndb.StringProperty(required=False)
353
355
  status = ndb.StringProperty(required=False, default=USER_STATUS_ANONYMOUS)
354
356
  new_message_count = ndb.IntegerProperty(required=False, default=0)
357
+ device_details = ndb.JsonProperty()
358
+
355
359
  dict_properties = [
356
360
  'mobile_phone', 'email', 'password', 'name', 'birth_date', 'gender',
357
361
  'reference_code', 'country', 'state', 'city', 'postcode',
358
- 'address', 'redeem_pin', 'new_message_count', 'status'
359
-
362
+ 'address', 'redeem_pin', 'new_message_count', 'status',
363
+ 'device_details',
360
364
  ]
361
365
 
362
366
  #unique_attributes = 'email,username'
@@ -364,7 +368,7 @@ class User(UserBase):
364
368
  audit_properties = [
365
369
  'mobile_phone', 'email', 'password', 'name', 'birth_date', 'gender',
366
370
  'reference_code', 'country', 'state', 'city', 'postcode',
367
- 'address', 'redeem_pin', 'status'
371
+ 'address', 'redeem_pin', 'status', 'device_details',
368
372
 
369
373
  ]
370
374
 
@@ -405,7 +409,45 @@ class User(UserBase):
405
409
  """Returns `True` if the user is active."""
406
410
  logger.info('calling is_active')
407
411
  return self.active
408
-
412
+
413
+ def update_device_details(self, platform, device_token):
414
+ if self.device_details:
415
+ found_device_details_list_by_platform = self.device_details.get(platform)
416
+ if found_device_details_list_by_platform:
417
+ is_found = False
418
+ for device_details_by_platform in found_device_details_list_by_platform:
419
+ device_token_by_platform = device_details_by_platform.get('device_token')
420
+ if device_token_by_platform:
421
+ device_details_by_platform['last_updated_datetime'] = datetime.utcnow().strftime("%d-%m-%Y %H:%M:%S")
422
+ is_found = True
423
+ break
424
+
425
+ if is_found == False:
426
+ found_device_details_list_by_platform.append(
427
+ {
428
+ 'device_token' : device_token,
429
+ 'last_updated_datetime' : datetime.utcnow().strftime("%d-%m-%Y %H:%M:%S"),
430
+ }
431
+ )
432
+
433
+
434
+ else:
435
+ self.device_details[platform] = [
436
+ {
437
+ 'device_token' : device_token,
438
+ 'last_updated_datetime' : datetime.utcnow().strftime("%d-%m-%Y %H:%M:%S"),
439
+ }
440
+ ]
441
+ else:
442
+ self.device_details = {
443
+ platform : [
444
+ {
445
+ 'device_token' : device_token,
446
+ 'last_updated_datetime' : datetime.utcnow().strftime("%d-%m-%Y %H:%M:%S"),
447
+ }
448
+ ]
449
+ }
450
+ self.put()
409
451
 
410
452
  class DeletedUser(User):
411
453
  deleted_datetime = ndb.DateTimeProperty(required=False, auto_now_add=True)
@@ -291,7 +291,13 @@ REDEMPTION_CATALOGUE_STATUS = (
291
291
  REDEMPTION_CATALOGUE_STATUS_PUBLISH
292
292
  )
293
293
 
294
-
294
+ LITE_REDEMPTION_CATALOGUE_STATUS = (
295
+ REDEMPTION_CATALOGUE_STATUS_DEFINED_CATALOGUE,
296
+ REDEMPTION_CATALOGUE_STATUS_DEFINE_ITEM,
297
+ REDEMPTION_CATALOGUE_STATUS_UPLOAD_MATERIAL,
298
+ REDEMPTION_CATALOGUE_STATUS_REVIEW,
299
+ REDEMPTION_CATALOGUE_STATUS_PUBLISH
300
+ )
295
301
 
296
302
 
297
303
 
@@ -544,7 +550,10 @@ def lucky_draw_program_completed_progress_percentage(completed_status):
544
550
  print('lucky_draw_program_completed_progress_percentage: completed_status_index(%s)=%s'% (completed_status,completed_status_index))
545
551
  return int((completed_status_index+1)/len(LUCKY_DRAW_PROGRAM_STATUS) * 100)
546
552
 
547
- def redemption_catalogue_completed_progress_percentage(completed_status):
553
+ def redemption_catalogue_completed_progress_percentage(completed_status, loyalty_package):
548
554
  completed_status_index = get_redemption_catalogue_completed_status_index(completed_status)
549
555
  print('redemption_catalogue_completed_progress_percentage: completed_status_index(%s)=%s'% (completed_status,completed_status_index))
550
- return int((completed_status_index+1)/len(REDEMPTION_CATALOGUE_STATUS) * 100)
556
+ if loyalty_package == LOYALTY_PACKAGE_LITE:
557
+ return int((completed_status_index+1)/len(LITE_REDEMPTION_CATALOGUE_STATUS) * 100)
558
+ else:
559
+ return int((completed_status_index+1)/len(REDEMPTION_CATALOGUE_STATUS) * 100)
File without changes
File without changes
File without changes
File without changes