+<project version="4">
|
|
3
|
+ <component name="ChangeListManager">
|
|
4
|
+ <list default="true" id="8287082c-5144-4790-9da1-578e292318f7" name="Default" comment="" />
|
|
5
|
+ <ignored path="tamron.iws" />
|
|
6
|
+ <ignored path=".idea/workspace.xml" />
|
|
7
|
+ <ignored path=".idea/dataSources.local.xml" />
|
|
8
|
+ <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
|
|
9
|
+ <option name="TRACKING_ENABLED" value="true" />
|
|
10
|
+ <option name="SHOW_DIALOG" value="false" />
|
|
11
|
+ <option name="HIGHLIGHT_CONFLICTS" value="true" />
|
|
12
|
+ <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
|
13
|
+ <option name="LAST_RESOLUTION" value="IGNORE" />
|
|
14
|
+ </component>
|
|
15
|
+ <component name="CreatePatchCommitExecutor">
|
|
16
|
+ <option name="PATCH_PATH" value="" />
|
|
17
|
+ </component>
|
|
18
|
+ <component name="ExecutionTargetManager" SELECTED_TARGET="default_target" />
|
|
19
|
+ <component name="FavoritesManager">
|
|
20
|
+ <favorites_list name="tamron" />
|
|
21
|
+ </component>
|
|
22
|
+ <component name="FileEditorManager">
|
|
23
|
+ <leaf>
|
|
24
|
+ <file leaf-file-name="tamron.ini" pinned="false" current-in-tab="false">
|
|
25
|
+ <entry file="file://$PROJECT_DIR$/tamron/uwsgi.bak/tamron.ini">
|
|
26
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
27
|
+ <state relative-caret-position="255">
|
|
28
|
+ <caret line="17" column="61" selection-start-line="17" selection-start-column="61" selection-end-line="17" selection-end-column="61" />
|
|
29
|
+ <folding />
|
|
30
|
+ </state>
|
|
31
|
+ </provider>
|
|
32
|
+ </entry>
|
|
33
|
+ </file>
|
|
34
|
+ <file leaf-file-name="tamron_nginx.conf" pinned="false" current-in-tab="true">
|
|
35
|
+ <entry file="file://$PROJECT_DIR$/tamron/uwsgi.bak/tamron_nginx.conf">
|
|
36
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
37
|
+ <state relative-caret-position="480">
|
|
38
|
+ <caret line="32" column="50" selection-start-line="32" selection-start-column="50" selection-end-line="32" selection-end-column="50" />
|
|
39
|
+ <folding />
|
|
40
|
+ </state>
|
|
41
|
+ </provider>
|
|
42
|
+ </entry>
|
|
43
|
+ </file>
|
|
44
|
+ </leaf>
|
|
45
|
+ </component>
|
|
46
|
+ <component name="FileTemplateManagerImpl">
|
|
47
|
+ <option name="RECENT_TEMPLATES">
|
|
48
|
+ <list>
|
|
49
|
+ <option value="Python Script" />
|
|
50
|
+ </list>
|
|
51
|
+ </option>
|
|
52
|
+ </component>
|
|
53
|
+ <component name="IdeDocumentHistory">
|
|
54
|
+ <option name="CHANGED_PATHS">
|
|
55
|
+ <list>
|
|
56
|
+ <option value="$PROJECT_DIR$/tamron/basemodels.py" />
|
|
57
|
+ <option value="$PROJECT_DIR$/account/admin.py" />
|
|
58
|
+ <option value="$PROJECT_DIR$/product/admin.py" />
|
|
59
|
+ <option value="$PROJECT_DIR$/integral/admin.py" />
|
|
60
|
+ <option value="$PROJECT_DIR$/page/views.py" />
|
|
61
|
+ <option value="$PROJECT_DIR$/product/models.py" />
|
|
62
|
+ <option value="$PROJECT_DIR$/integral/models.py" />
|
|
63
|
+ <option value="$PROJECT_DIR$/tamron/settings.py" />
|
|
64
|
+ <option value="$PROJECT_DIR$/api/urls.py" />
|
|
65
|
+ <option value="$PROJECT_DIR$/tamron/local_settings.py" />
|
|
66
|
+ <option value="$PROJECT_DIR$/page/templates/page/clerk_oauth.html" />
|
|
67
|
+ <option value="$PROJECT_DIR$/page/sale_views.py" />
|
|
68
|
+ <option value="$PROJECT_DIR$/page/templates/page/clerk_sale.html" />
|
|
69
|
+ <option value="$PROJECT_DIR$/page/templates/page/clerk_into.html" />
|
|
70
|
+ <option value="$PROJECT_DIR$/tamron/urls.py" />
|
|
71
|
+ <option value="$PROJECT_DIR$/page/info_views.py" />
|
|
72
|
+ <option value="$PROJECT_DIR$/utils/error/errno_utils.py" />
|
|
73
|
+ <option value="$PROJECT_DIR$/page/oauth_views.py" />
|
|
74
|
+ <option value="$PROJECT_DIR$/account/models.py" />
|
|
75
|
+ <option value="$PROJECT_DIR$/page/templates/page/clerk_info.html" />
|
|
76
|
+ <option value="$PROJECT_DIR$/tamron/uwsgi.bak/tamron.ini" />
|
|
77
|
+ <option value="$PROJECT_DIR$/tamron/uwsgi.bak/tamron_nginx.conf" />
|
|
78
|
+ </list>
|
|
79
|
+ </option>
|
|
80
|
+ </component>
|
|
81
|
+ <component name="JsBuildToolGruntFileManager" detection-done="true" sorting="DEFINITION_ORDER" />
|
|
82
|
+ <component name="JsBuildToolPackageJson" detection-done="true" sorting="DEFINITION_ORDER" />
|
|
83
|
+ <component name="JsGulpfileManager">
|
|
84
|
+ <detection-done>true</detection-done>
|
|
85
|
+ <sorting>DEFINITION_ORDER</sorting>
|
|
86
|
+ </component>
|
|
87
|
+ <component name="ProjectFrameBounds">
|
|
88
|
+ <option name="x" value="65" />
|
|
89
|
+ <option name="y" value="24" />
|
|
90
|
+ <option name="width" value="1301" />
|
|
91
|
+ <option name="height" value="744" />
|
|
92
|
+ </component>
|
|
93
|
+ <component name="ProjectLevelVcsManager" settingsEditedManually="false">
|
|
94
|
+ <OptionsSetting value="true" id="Add" />
|
|
95
|
+ <OptionsSetting value="true" id="Remove" />
|
|
96
|
+ <OptionsSetting value="true" id="Checkout" />
|
|
97
|
+ <OptionsSetting value="true" id="Update" />
|
|
98
|
+ <OptionsSetting value="true" id="Status" />
|
|
99
|
+ <OptionsSetting value="true" id="Edit" />
|
|
100
|
+ <ConfirmationsSetting value="0" id="Add" />
|
|
101
|
+ <ConfirmationsSetting value="0" id="Remove" />
|
|
102
|
+ </component>
|
|
103
|
+ <component name="ProjectView">
|
|
104
|
+ <navigator currentView="ProjectPane" proportions="" version="1">
|
|
105
|
+ <flattenPackages />
|
|
106
|
+ <showMembers />
|
|
107
|
+ <showModules />
|
|
108
|
+ <showLibraryContents />
|
|
109
|
+ <hideEmptyPackages />
|
|
110
|
+ <abbreviatePackageNames />
|
|
111
|
+ <autoscrollToSource />
|
|
112
|
+ <autoscrollFromSource />
|
|
113
|
+ <sortByType />
|
|
114
|
+ <manualOrder />
|
|
115
|
+ <foldersAlwaysOnTop value="true" />
|
|
116
|
+ </navigator>
|
|
117
|
+ <panes>
|
|
118
|
+ <pane id="Scratches" />
|
|
119
|
+ <pane id="Scope" />
|
|
120
|
+ <pane id="ProjectPane">
|
|
121
|
+ <subPane>
|
|
122
|
+ <PATH>
|
|
123
|
+ <PATH_ELEMENT>
|
|
124
|
+ <option name="myItemId" value="tamron" />
|
|
125
|
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
|
|
126
|
+ </PATH_ELEMENT>
|
|
127
|
+ </PATH>
|
|
128
|
+ <PATH>
|
|
129
|
+ <PATH_ELEMENT>
|
|
130
|
+ <option name="myItemId" value="tamron" />
|
|
131
|
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
|
|
132
|
+ </PATH_ELEMENT>
|
|
133
|
+ <PATH_ELEMENT>
|
|
134
|
+ <option name="myItemId" value="tamron" />
|
|
135
|
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
|
136
|
+ </PATH_ELEMENT>
|
|
137
|
+ </PATH>
|
|
138
|
+ </subPane>
|
|
139
|
+ </pane>
|
|
140
|
+ </panes>
|
|
141
|
+ </component>
|
|
142
|
+ <component name="PropertiesComponent">
|
|
143
|
+ <property name="last_opened_file_path" value="$PROJECT_DIR$" />
|
|
144
|
+ <property name="WebServerToolWindowFactoryState" value="false" />
|
|
145
|
+ <property name="js-jscs-nodeInterpreter" value="$USER_HOME$/.nvm/versions/node/v6.10.0/bin/node" />
|
|
146
|
+ </component>
|
|
147
|
+ <component name="RecentsManager">
|
|
148
|
+ <key name="CopyFile.RECENT_KEYS">
|
|
149
|
+ <recent name="$PROJECT_DIR$/page" />
|
|
150
|
+ <recent name="$PROJECT_DIR$/page/templates/page" />
|
|
151
|
+ </key>
|
|
152
|
+ </component>
|
|
153
|
+ <component name="RunManager" selected="Django server.tamron">
|
|
154
|
+ <configuration default="true" type="DjangoTestsConfigurationType" factoryName="Django tests">
|
|
155
|
+ <option name="INTERPRETER_OPTIONS" value="" />
|
|
156
|
+ <option name="PARENT_ENVS" value="true" />
|
|
157
|
+ <envs>
|
|
158
|
+ <env name="PYTHONUNBUFFERED" value="1" />
|
|
159
|
+ </envs>
|
|
160
|
+ <option name="SDK_HOME" value="" />
|
|
161
|
+ <option name="WORKING_DIRECTORY" value="" />
|
|
162
|
+ <option name="IS_MODULE_SDK" value="false" />
|
|
163
|
+ <option name="ADD_CONTENT_ROOTS" value="true" />
|
|
164
|
+ <option name="ADD_SOURCE_ROOTS" value="true" />
|
|
165
|
+ <module name="tamron" />
|
|
166
|
+ <EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
|
|
167
|
+ <option name="TARGET" value="" />
|
|
168
|
+ <option name="SETTINGS_FILE" value="" />
|
|
169
|
+ <option name="CUSTOM_SETTINGS" value="false" />
|
|
170
|
+ <option name="USE_OPTIONS" value="false" />
|
|
171
|
+ <option name="OPTIONS" value="" />
|
|
172
|
+ <method />
|
|
173
|
+ </configuration>
|
|
174
|
+ <configuration default="true" type="JavascriptDebugType" factoryName="JavaScript Debug">
|
|
175
|
+ <method />
|
|
176
|
+ </configuration>
|
|
177
|
+ <configuration default="true" type="PyBehaveRunConfigurationType" factoryName="Behave">
|
|
178
|
+ <option name="INTERPRETER_OPTIONS" value="" />
|
|
179
|
+ <option name="PARENT_ENVS" value="true" />
|
|
180
|
+ <envs />
|
|
181
|
+ <option name="SDK_HOME" value="" />
|
|
182
|
+ <option name="WORKING_DIRECTORY" value="" />
|
|
183
|
+ <option name="IS_MODULE_SDK" value="false" />
|
|
184
|
+ <option name="ADD_CONTENT_ROOTS" value="true" />
|
|
185
|
+ <option name="ADD_SOURCE_ROOTS" value="true" />
|
|
186
|
+ <module name="tamron" />
|
|
187
|
+ <EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
|
|
188
|
+ <option name="ADDITIONAL_ARGS" value="" />
|
|
189
|
+ <method />
|
|
190
|
+ </configuration>
|
|
191
|
+ <configuration default="true" type="PyLettuceRunConfigurationType" factoryName="Lettuce">
|
|
192
|
+ <option name="INTERPRETER_OPTIONS" value="" />
|
|
193
|
+ <option name="PARENT_ENVS" value="true" />
|
|
194
|
+ <envs />
|
|
195
|
+ <option name="SDK_HOME" value="" />
|
|
196
|
+ <option name="WORKING_DIRECTORY" value="" />
|
|
197
|
+ <option name="IS_MODULE_SDK" value="false" />
|
|
198
|
+ <option name="ADD_CONTENT_ROOTS" value="true" />
|
|
199
|
+ <option name="ADD_SOURCE_ROOTS" value="true" />
|
|
200
|
+ <module name="tamron" />
|
|
201
|
+ <EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
|
|
202
|
+ <option name="ADDITIONAL_ARGS" value="" />
|
|
203
|
+ <method />
|
|
204
|
+ </configuration>
|
|
205
|
+ <configuration default="true" type="Python.DjangoServer" factoryName="Django server">
|
|
206
|
+ <option name="INTERPRETER_OPTIONS" value="" />
|
|
207
|
+ <option name="PARENT_ENVS" value="true" />
|
|
208
|
+ <envs>
|
|
209
|
+ <env name="PYTHONUNBUFFERED" value="1" />
|
|
210
|
+ </envs>
|
|
211
|
+ <option name="SDK_HOME" value="" />
|
|
212
|
+ <option name="WORKING_DIRECTORY" value="" />
|
|
213
|
+ <option name="IS_MODULE_SDK" value="false" />
|
|
214
|
+ <option name="ADD_CONTENT_ROOTS" value="true" />
|
|
215
|
+ <option name="ADD_SOURCE_ROOTS" value="true" />
|
|
216
|
+ <module name="tamron" />
|
|
217
|
+ <option name="launchJavascriptDebuger" value="false" />
|
|
218
|
+ <option name="port" value="8000" />
|
|
219
|
+ <option name="host" value="" />
|
|
220
|
+ <option name="additionalOptions" value="" />
|
|
221
|
+ <option name="browserUrl" value="" />
|
|
222
|
+ <option name="runTestServer" value="false" />
|
|
223
|
+ <option name="runNoReload" value="false" />
|
|
224
|
+ <option name="useCustomRunCommand" value="false" />
|
|
225
|
+ <option name="customRunCommand" value="" />
|
|
226
|
+ <method />
|
|
227
|
+ </configuration>
|
|
228
|
+ <configuration default="true" type="PythonConfigurationType" factoryName="Python">
|
|
229
|
+ <option name="INTERPRETER_OPTIONS" value="" />
|
|
230
|
+ <option name="PARENT_ENVS" value="true" />
|
|
231
|
+ <envs>
|
|
232
|
+ <env name="PYTHONUNBUFFERED" value="1" />
|
|
233
|
+ </envs>
|
|
234
|
+ <option name="SDK_HOME" value="" />
|
|
235
|
+ <option name="WORKING_DIRECTORY" value="" />
|
|
236
|
+ <option name="IS_MODULE_SDK" value="false" />
|
|
237
|
+ <option name="ADD_CONTENT_ROOTS" value="true" />
|
|
238
|
+ <option name="ADD_SOURCE_ROOTS" value="true" />
|
|
239
|
+ <module name="tamron" />
|
|
240
|
+ <EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
|
|
241
|
+ <option name="SCRIPT_NAME" value="" />
|
|
242
|
+ <option name="PARAMETERS" value="" />
|
|
243
|
+ <option name="SHOW_COMMAND_LINE" value="false" />
|
|
244
|
+ <method />
|
|
245
|
+ </configuration>
|
|
246
|
+ <configuration default="true" type="Tox" factoryName="Tox">
|
|
247
|
+ <option name="INTERPRETER_OPTIONS" value="" />
|
|
248
|
+ <option name="PARENT_ENVS" value="true" />
|
|
249
|
+ <envs />
|
|
250
|
+ <option name="SDK_HOME" value="" />
|
|
251
|
+ <option name="WORKING_DIRECTORY" value="" />
|
|
252
|
+ <option name="IS_MODULE_SDK" value="false" />
|
|
253
|
+ <option name="ADD_CONTENT_ROOTS" value="true" />
|
|
254
|
+ <option name="ADD_SOURCE_ROOTS" value="true" />
|
|
255
|
+ <EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
|
|
256
|
+ <module name="tamron" />
|
|
257
|
+ <method />
|
|
258
|
+ </configuration>
|
|
259
|
+ <configuration default="true" type="js.build_tools.gulp" factoryName="Gulp.js">
|
|
260
|
+ <node-interpreter>project</node-interpreter>
|
|
261
|
+ <node-options />
|
|
262
|
+ <gulpfile />
|
|
263
|
+ <tasks />
|
|
264
|
+ <arguments />
|
|
265
|
+ <envs />
|
|
266
|
+ <method />
|
|
267
|
+ </configuration>
|
|
268
|
+ <configuration default="true" type="js.build_tools.npm" factoryName="npm">
|
|
269
|
+ <command value="run-script" />
|
|
270
|
+ <scripts />
|
|
271
|
+ <node-interpreter value="project" />
|
|
272
|
+ <envs />
|
|
273
|
+ <method />
|
|
274
|
+ </configuration>
|
|
275
|
+ <configuration default="true" type="tests" factoryName="Attests">
|
|
276
|
+ <option name="INTERPRETER_OPTIONS" value="" />
|
|
277
|
+ <option name="PARENT_ENVS" value="true" />
|
|
278
|
+ <envs />
|
|
279
|
+ <option name="SDK_HOME" value="" />
|
|
280
|
+ <option name="WORKING_DIRECTORY" value="" />
|
|
281
|
+ <option name="IS_MODULE_SDK" value="false" />
|
|
282
|
+ <option name="ADD_CONTENT_ROOTS" value="true" />
|
|
283
|
+ <option name="ADD_SOURCE_ROOTS" value="true" />
|
|
284
|
+ <module name="tamron" />
|
|
285
|
+ <EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
|
|
286
|
+ <option name="SCRIPT_NAME" value="" />
|
|
287
|
+ <option name="CLASS_NAME" value="" />
|
|
288
|
+ <option name="METHOD_NAME" value="" />
|
|
289
|
+ <option name="FOLDER_NAME" value="" />
|
|
290
|
+ <option name="TEST_TYPE" value="TEST_SCRIPT" />
|
|
291
|
+ <option name="PATTERN" value="" />
|
|
292
|
+ <option name="USE_PATTERN" value="false" />
|
|
293
|
+ <method />
|
|
294
|
+ </configuration>
|
|
295
|
+ <configuration default="true" type="tests" factoryName="Doctests">
|
|
296
|
+ <option name="INTERPRETER_OPTIONS" value="" />
|
|
297
|
+ <option name="PARENT_ENVS" value="true" />
|
|
298
|
+ <envs />
|
|
299
|
+ <option name="SDK_HOME" value="" />
|
|
300
|
+ <option name="WORKING_DIRECTORY" value="" />
|
|
301
|
+ <option name="IS_MODULE_SDK" value="false" />
|
|
302
|
+ <option name="ADD_CONTENT_ROOTS" value="true" />
|
|
303
|
+ <option name="ADD_SOURCE_ROOTS" value="true" />
|
|
304
|
+ <module name="tamron" />
|
|
305
|
+ <EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
|
|
306
|
+ <option name="SCRIPT_NAME" value="" />
|
|
307
|
+ <option name="CLASS_NAME" value="" />
|
|
308
|
+ <option name="METHOD_NAME" value="" />
|
|
309
|
+ <option name="FOLDER_NAME" value="" />
|
|
310
|
+ <option name="TEST_TYPE" value="TEST_SCRIPT" />
|
|
311
|
+ <option name="PATTERN" value="" />
|
|
312
|
+ <option name="USE_PATTERN" value="false" />
|
|
313
|
+ <method />
|
|
314
|
+ </configuration>
|
|
315
|
+ <configuration default="true" type="tests" factoryName="Nosetests">
|
|
316
|
+ <option name="INTERPRETER_OPTIONS" value="" />
|
|
317
|
+ <option name="PARENT_ENVS" value="true" />
|
|
318
|
+ <envs />
|
|
319
|
+ <option name="SDK_HOME" value="" />
|
|
320
|
+ <option name="WORKING_DIRECTORY" value="" />
|
|
321
|
+ <option name="IS_MODULE_SDK" value="false" />
|
|
322
|
+ <option name="ADD_CONTENT_ROOTS" value="true" />
|
|
323
|
+ <option name="ADD_SOURCE_ROOTS" value="true" />
|
|
324
|
+ <module name="tamron" />
|
|
325
|
+ <EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
|
|
326
|
+ <option name="SCRIPT_NAME" value="" />
|
|
327
|
+ <option name="CLASS_NAME" value="" />
|
|
328
|
+ <option name="METHOD_NAME" value="" />
|
|
329
|
+ <option name="FOLDER_NAME" value="" />
|
|
330
|
+ <option name="TEST_TYPE" value="TEST_SCRIPT" />
|
|
331
|
+ <option name="PATTERN" value="" />
|
|
332
|
+ <option name="USE_PATTERN" value="false" />
|
|
333
|
+ <option name="PARAMS" value="" />
|
|
334
|
+ <option name="USE_PARAM" value="false" />
|
|
335
|
+ <method />
|
|
336
|
+ </configuration>
|
|
337
|
+ <configuration default="true" type="tests" factoryName="Unittests">
|
|
338
|
+ <option name="INTERPRETER_OPTIONS" value="" />
|
|
339
|
+ <option name="PARENT_ENVS" value="true" />
|
|
340
|
+ <envs />
|
|
341
|
+ <option name="SDK_HOME" value="" />
|
|
342
|
+ <option name="WORKING_DIRECTORY" value="" />
|
|
343
|
+ <option name="IS_MODULE_SDK" value="false" />
|
|
344
|
+ <option name="ADD_CONTENT_ROOTS" value="true" />
|
|
345
|
+ <option name="ADD_SOURCE_ROOTS" value="true" />
|
|
346
|
+ <module name="tamron" />
|
|
347
|
+ <EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
|
|
348
|
+ <option name="SCRIPT_NAME" value="" />
|
|
349
|
+ <option name="CLASS_NAME" value="" />
|
|
350
|
+ <option name="METHOD_NAME" value="" />
|
|
351
|
+ <option name="FOLDER_NAME" value="" />
|
|
352
|
+ <option name="TEST_TYPE" value="TEST_SCRIPT" />
|
|
353
|
+ <option name="PATTERN" value="" />
|
|
354
|
+ <option name="USE_PATTERN" value="false" />
|
|
355
|
+ <option name="PUREUNITTEST" value="true" />
|
|
356
|
+ <option name="PARAMS" value="" />
|
|
357
|
+ <option name="USE_PARAM" value="false" />
|
|
358
|
+ <method />
|
|
359
|
+ </configuration>
|
|
360
|
+ <configuration default="true" type="tests" factoryName="py.test">
|
|
361
|
+ <option name="INTERPRETER_OPTIONS" value="" />
|
|
362
|
+ <option name="PARENT_ENVS" value="true" />
|
|
363
|
+ <envs />
|
|
364
|
+ <option name="SDK_HOME" value="" />
|
|
365
|
+ <option name="WORKING_DIRECTORY" value="" />
|
|
366
|
+ <option name="IS_MODULE_SDK" value="false" />
|
|
367
|
+ <option name="ADD_CONTENT_ROOTS" value="true" />
|
|
368
|
+ <option name="ADD_SOURCE_ROOTS" value="true" />
|
|
369
|
+ <module name="tamron" />
|
|
370
|
+ <EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
|
|
371
|
+ <option name="SCRIPT_NAME" value="" />
|
|
372
|
+ <option name="CLASS_NAME" value="" />
|
|
373
|
+ <option name="METHOD_NAME" value="" />
|
|
374
|
+ <option name="FOLDER_NAME" value="" />
|
|
375
|
+ <option name="TEST_TYPE" value="TEST_SCRIPT" />
|
|
376
|
+ <option name="PATTERN" value="" />
|
|
377
|
+ <option name="USE_PATTERN" value="false" />
|
|
378
|
+ <option name="testToRun" value="" />
|
|
379
|
+ <option name="keywords" value="" />
|
|
380
|
+ <option name="params" value="" />
|
|
381
|
+ <option name="USE_PARAM" value="false" />
|
|
382
|
+ <option name="USE_KEYWORD" value="false" />
|
|
383
|
+ <method />
|
|
384
|
+ </configuration>
|
|
385
|
+ <configuration default="false" name="tamron" type="Python.DjangoServer" factoryName="Django server">
|
|
386
|
+ <option name="INTERPRETER_OPTIONS" value="" />
|
|
387
|
+ <option name="PARENT_ENVS" value="true" />
|
|
388
|
+ <envs>
|
|
389
|
+ <env name="PYTHONUNBUFFERED" value="1" />
|
|
390
|
+ </envs>
|
|
391
|
+ <option name="SDK_HOME" value="" />
|
|
392
|
+ <option name="WORKING_DIRECTORY" value="" />
|
|
393
|
+ <option name="IS_MODULE_SDK" value="false" />
|
|
394
|
+ <option name="ADD_CONTENT_ROOTS" value="true" />
|
|
395
|
+ <option name="ADD_SOURCE_ROOTS" value="true" />
|
|
396
|
+ <module name="tamron" />
|
|
397
|
+ <option name="launchJavascriptDebuger" value="false" />
|
|
398
|
+ <option name="port" value="8000" />
|
|
399
|
+ <option name="host" value="" />
|
|
400
|
+ <option name="additionalOptions" value="" />
|
|
401
|
+ <option name="browserUrl" value="" />
|
|
402
|
+ <option name="runTestServer" value="false" />
|
|
403
|
+ <option name="runNoReload" value="false" />
|
|
404
|
+ <option name="useCustomRunCommand" value="false" />
|
|
405
|
+ <option name="customRunCommand" value="" />
|
|
406
|
+ <method />
|
|
407
|
+ </configuration>
|
|
408
|
+ <list size="1">
|
|
409
|
+ <item index="0" class="java.lang.String" itemvalue="Django server.tamron" />
|
|
410
|
+ </list>
|
|
411
|
+ </component>
|
|
412
|
+ <component name="ShelveChangesManager" show_recycled="false">
|
|
413
|
+ <option name="remove_strategy" value="false" />
|
|
414
|
+ </component>
|
|
415
|
+ <component name="TaskManager">
|
|
416
|
+ <task active="true" id="Default" summary="Default task">
|
|
417
|
+ <changelist id="8287082c-5144-4790-9da1-578e292318f7" name="Default" comment="" />
|
|
418
|
+ <created>1497849391019</created>
|
|
419
|
+ <option name="number" value="Default" />
|
|
420
|
+ <option name="presentableId" value="Default" />
|
|
421
|
+ <updated>1497849391019</updated>
|
|
422
|
+ </task>
|
|
423
|
+ <servers />
|
|
424
|
+ </component>
|
|
425
|
+ <component name="ToolWindowManager">
|
|
426
|
+ <frame x="65" y="24" width="1301" height="744" extended-state="6" />
|
|
427
|
+ <editor active="false" />
|
|
428
|
+ <layout>
|
|
429
|
+ <window_info id="Project" active="true" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.16756341" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
|
|
430
|
+ <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
|
|
431
|
+ <window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="true" content_ui="tabs" />
|
|
432
|
+ <window_info id="Database" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
|
433
|
+ <window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
|
434
|
+ <window_info id="Python Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
|
435
|
+ <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
|
436
|
+ <window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
|
437
|
+ <window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
|
|
438
|
+ <window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
|
|
439
|
+ <window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
|
|
440
|
+ <window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
|
|
441
|
+ <window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
|
|
442
|
+ <window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
|
|
443
|
+ <window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
|
|
444
|
+ <window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
|
445
|
+ <window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
|
446
|
+ <window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
|
447
|
+ </layout>
|
|
448
|
+ </component>
|
|
449
|
+ <component name="Vcs.Log.UiProperties">
|
|
450
|
+ <option name="RECENTLY_FILTERED_USER_GROUPS">
|
|
451
|
+ <collection />
|
|
452
|
+ </option>
|
|
453
|
+ <option name="RECENTLY_FILTERED_BRANCH_GROUPS">
|
|
454
|
+ <collection />
|
|
455
|
+ </option>
|
|
456
|
+ </component>
|
|
457
|
+ <component name="VcsContentAnnotationSettings">
|
|
458
|
+ <option name="myLimit" value="2678400000" />
|
|
459
|
+ </component>
|
|
460
|
+ <component name="XDebuggerManager">
|
|
461
|
+ <breakpoint-manager>
|
|
462
|
+ <option name="time" value="2" />
|
|
463
|
+ </breakpoint-manager>
|
|
464
|
+ <watches-manager />
|
|
465
|
+ </component>
|
|
466
|
+ <component name="editorHistoryManager">
|
|
467
|
+ <entry file="file://$PROJECT_DIR$/page/models.py">
|
|
468
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
469
|
+ <state relative-caret-position="0">
|
|
470
|
+ <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
|
|
471
|
+ </state>
|
|
472
|
+ </provider>
|
|
473
|
+ </entry>
|
|
474
|
+ <entry file="file://$PROJECT_DIR$/account/admin.py">
|
|
475
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
476
|
+ <state relative-caret-position="165">
|
|
477
|
+ <caret line="13" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="23" selection-end-column="0" />
|
|
478
|
+ </state>
|
|
479
|
+ </provider>
|
|
480
|
+ </entry>
|
|
481
|
+ <entry file="file://$PROJECT_DIR$/tamron/basemodels.py">
|
|
482
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
483
|
+ <state relative-caret-position="105">
|
|
484
|
+ <caret line="7" column="94" selection-start-line="7" selection-start-column="79" selection-end-line="7" selection-end-column="94" />
|
|
485
|
+ </state>
|
|
486
|
+ </provider>
|
|
487
|
+ </entry>
|
|
488
|
+ <entry file="file://$PROJECT_DIR$/integral/admin.py">
|
|
489
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
490
|
+ <state relative-caret-position="150">
|
|
491
|
+ <caret line="10" column="38" selection-start-line="10" selection-start-column="38" selection-end-line="10" selection-end-column="38" />
|
|
492
|
+ </state>
|
|
493
|
+ </provider>
|
|
494
|
+ </entry>
|
|
495
|
+ <entry file="file://$PROJECT_DIR$/product/admin.py">
|
|
496
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
497
|
+ <state relative-caret-position="390">
|
|
498
|
+ <caret line="26" column="0" selection-start-line="26" selection-start-column="0" selection-end-line="26" selection-end-column="60" />
|
|
499
|
+ </state>
|
|
500
|
+ </provider>
|
|
501
|
+ </entry>
|
|
502
|
+ <entry file="file://$PROJECT_DIR$/integral/views.py">
|
|
503
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
504
|
+ <state relative-caret-position="60">
|
|
505
|
+ <caret line="4" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="4" selection-end-column="0" />
|
|
506
|
+ </state>
|
|
507
|
+ </provider>
|
|
508
|
+ </entry>
|
|
509
|
+ <entry file="file://$PROJECT_DIR$/page/views.py">
|
|
510
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
511
|
+ <state relative-caret-position="60">
|
|
512
|
+ <caret line="4" column="0" selection-start-line="4" selection-start-column="0" selection-end-line="4" selection-end-column="0" />
|
|
513
|
+ </state>
|
|
514
|
+ </provider>
|
|
515
|
+ </entry>
|
|
516
|
+ <entry file="file://$PROJECT_DIR$/product/models.py">
|
|
517
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
518
|
+ <state relative-caret-position="308">
|
|
519
|
+ <caret line="43" column="104" selection-start-line="43" selection-start-column="104" selection-end-line="43" selection-end-column="104" />
|
|
520
|
+ </state>
|
|
521
|
+ </provider>
|
|
522
|
+ </entry>
|
|
523
|
+ <entry file="file://$PROJECT_DIR$/integral/models.py">
|
|
524
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
525
|
+ <state relative-caret-position="360">
|
|
526
|
+ <caret line="24" column="30" selection-start-line="24" selection-start-column="30" selection-end-line="24" selection-end-column="30" />
|
|
527
|
+ </state>
|
|
528
|
+ </provider>
|
|
529
|
+ </entry>
|
|
530
|
+ <entry file="file://$PROJECT_DIR$/tamron/settings.py">
|
|
531
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
532
|
+ <state relative-caret-position="312">
|
|
533
|
+ <caret line="200" column="6" selection-start-line="200" selection-start-column="0" selection-end-line="200" selection-end-column="6" />
|
|
534
|
+ <folding />
|
|
535
|
+ </state>
|
|
536
|
+ </provider>
|
|
537
|
+ </entry>
|
|
538
|
+ <entry file="file://$PROJECT_DIR$/tamron/local_settings.py">
|
|
539
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
540
|
+ <state relative-caret-position="420">
|
|
541
|
+ <caret line="28" column="32" selection-start-line="28" selection-start-column="32" selection-end-line="28" selection-end-column="32" />
|
|
542
|
+ </state>
|
|
543
|
+ </provider>
|
|
544
|
+ </entry>
|
|
545
|
+ <entry file="file://$PROJECT_DIR$/api/urls.py">
|
|
546
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
547
|
+ <state relative-caret-position="120">
|
|
548
|
+ <caret line="8" column="44" selection-start-line="8" selection-start-column="44" selection-end-line="8" selection-end-column="44" />
|
|
549
|
+ </state>
|
|
550
|
+ </provider>
|
|
551
|
+ </entry>
|
|
552
|
+ <entry file="file://$PROJECT_DIR$/page/templates/page/clerk_oauth.html">
|
|
553
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
554
|
+ <state relative-caret-position="360">
|
|
555
|
+ <caret line="57" column="18" selection-start-line="25" selection-start-column="12" selection-end-line="57" selection-end-column="18" />
|
|
556
|
+ <folding />
|
|
557
|
+ </state>
|
|
558
|
+ </provider>
|
|
559
|
+ </entry>
|
|
560
|
+ <entry file="file://$PROJECT_DIR$/page/templates/page/clerk_sale.html">
|
|
561
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
562
|
+ <state relative-caret-position="273">
|
|
563
|
+ <caret line="160" column="0" selection-start-line="160" selection-start-column="0" selection-end-line="160" selection-end-column="0" />
|
|
564
|
+ <folding />
|
|
565
|
+ </state>
|
|
566
|
+ </provider>
|
|
567
|
+ </entry>
|
|
568
|
+ <entry file="file://$PROJECT_DIR$/utils/error/errno_utils.py">
|
|
569
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
570
|
+ <state relative-caret-position="75">
|
|
571
|
+ <caret line="5" column="26" selection-start-line="5" selection-start-column="6" selection-end-line="5" selection-end-column="26" />
|
|
572
|
+ </state>
|
|
573
|
+ </provider>
|
|
574
|
+ </entry>
|
|
575
|
+ <entry file="file://$PROJECT_DIR$/account/models.py">
|
|
576
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
577
|
+ <state relative-caret-position="521">
|
|
578
|
+ <caret line="88" column="38" selection-start-line="88" selection-start-column="38" selection-end-line="88" selection-end-column="38" />
|
|
579
|
+ </state>
|
|
580
|
+ </provider>
|
|
581
|
+ </entry>
|
|
582
|
+ <entry file="file://$PROJECT_DIR$/tamron/urls.py">
|
|
583
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
584
|
+ <state relative-caret-position="465">
|
|
585
|
+ <caret line="31" column="55" selection-start-line="31" selection-start-column="55" selection-end-line="31" selection-end-column="55" />
|
|
586
|
+ </state>
|
|
587
|
+ </provider>
|
|
588
|
+ </entry>
|
|
589
|
+ <entry file="file://$PROJECT_DIR$/page/sale_views.py">
|
|
590
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
591
|
+ <state relative-caret-position="311">
|
|
592
|
+ <caret line="97" column="18" selection-start-line="97" selection-start-column="10" selection-end-line="97" selection-end-column="18" />
|
|
593
|
+ </state>
|
|
594
|
+ </provider>
|
|
595
|
+ </entry>
|
|
596
|
+ <entry file="file://$PROJECT_DIR$/page/info_views.py">
|
|
597
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
598
|
+ <state relative-caret-position="300">
|
|
599
|
+ <caret line="20" column="42" selection-start-line="20" selection-start-column="42" selection-end-line="20" selection-end-column="42" />
|
|
600
|
+ </state>
|
|
601
|
+ </provider>
|
|
602
|
+ </entry>
|
|
603
|
+ <entry file="file://$PROJECT_DIR$/page/oauth_views.py">
|
|
604
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
605
|
+ <state relative-caret-position="135">
|
|
606
|
+ <caret line="9" column="37" selection-start-line="9" selection-start-column="31" selection-end-line="9" selection-end-column="37" />
|
|
607
|
+ </state>
|
|
608
|
+ </provider>
|
|
609
|
+ </entry>
|
|
610
|
+ <entry file="file://$PROJECT_DIR$/page/templates/page/clerk_info.html">
|
|
611
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
612
|
+ <state relative-caret-position="48">
|
|
613
|
+ <caret line="44" column="0" selection-start-line="44" selection-start-column="0" selection-end-line="44" selection-end-column="0" />
|
|
614
|
+ </state>
|
|
615
|
+ </provider>
|
|
616
|
+ </entry>
|
|
617
|
+ <entry file="file://$PROJECT_DIR$/tamron/uwsgi.bak/tamron.ini">
|
|
618
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
619
|
+ <state relative-caret-position="255">
|
|
620
|
+ <caret line="17" column="61" selection-start-line="17" selection-start-column="61" selection-end-line="17" selection-end-column="61" />
|
|
621
|
+ <folding />
|
|
622
|
+ </state>
|
|
623
|
+ </provider>
|
|
624
|
+ </entry>
|
|
625
|
+ <entry file="file://$PROJECT_DIR$/tamron/uwsgi.bak/tamron_nginx.conf">
|
|
626
|
+ <provider selected="true" editor-type-id="text-editor">
|
|
627
|
+ <state relative-caret-position="480">
|
|
628
|
+ <caret line="32" column="50" selection-start-line="32" selection-start-column="50" selection-end-line="32" selection-end-column="50" />
|
|
629
|
+ <folding />
|
|
630
|
+ </state>
|
|
631
|
+ </provider>
|
|
632
|
+ </entry>
|
|
633
|
+ </component>
|
|
634
|
+</project>
|
|
|
@@ -0,0 +1,8 @@
|
|
1
|
+# See the menu of settings available here:
|
|
2
|
+# https://github.com/timothycrosley/isort/wiki/isort-Settings
|
|
3
|
+
|
|
4
|
+[settings]
|
|
5
|
+indent=' '
|
|
6
|
+line_length=120
|
|
7
|
+lines_after_imports=2
|
|
8
|
+skip=migrations
|
|
|
@@ -0,0 +1,23 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+from django.contrib import admin
|
|
4
|
+
|
|
5
|
+from account.models import FranchiserInfo, SaleclerkInfo
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+class FranchiserInfoAdmin(admin.ModelAdmin):
|
|
9
|
+ readonly_fields = ('franchiser_id', )
|
|
10
|
+ list_display = ('franchiser_id', 'franchiser_name', 'franchiser_addr', 'franchiser_phone', 'franchiser_boss_name', 'franchiser_boss_phone', 'status', 'created_at', 'updated_at')
|
|
11
|
+ search_fields = ('franchiser_id', 'franchiser_name', 'franchiser_addr', 'franchiser_phone', 'franchiser_boss_name', 'franchiser_boss_phone')
|
|
12
|
+ list_filter = ('status', )
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+class SaleclerkInfoAdmin(admin.ModelAdmin):
|
|
16
|
+ readonly_fields = ('franchiser_id', )
|
|
17
|
+ list_display = ('franchiser_id', 'clerk_id', 'clerk_name', 'clerk_sex', 'clerk_phone', 'user_status', 'status', 'created_at', 'updated_at')
|
|
18
|
+ search_fields = ('franchiser_id', 'clerk_id', 'clerk_name', 'clerk_phone')
|
|
19
|
+ list_filter = ('user_status', 'status')
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+admin.site.register(FranchiserInfo, FranchiserInfoAdmin)
|
|
23
|
+admin.site.register(SaleclerkInfo, SaleclerkInfoAdmin)
|
|
|
@@ -0,0 +1,55 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+from __future__ import unicode_literals
|
|
3
|
+
|
|
4
|
+from django.db import models, migrations
|
|
5
|
+import shortuuidfield.fields
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+class Migration(migrations.Migration):
|
|
9
|
+
|
|
10
|
+ dependencies = [
|
|
11
|
+ ]
|
|
12
|
+
|
|
13
|
+ operations = [
|
|
14
|
+ migrations.CreateModel(
|
|
15
|
+ name='FranchiserInfo',
|
|
16
|
+ fields=[
|
|
17
|
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
|
18
|
+ ('status', models.BooleanField(default=True, help_text='\u72b6\u6001', db_index=True, verbose_name='status')),
|
|
19
|
+ ('created_at', models.DateTimeField(help_text='\u521b\u5efa\u65f6\u95f4', verbose_name='created_at', auto_now_add=True)),
|
|
20
|
+ ('updated_at', models.DateTimeField(help_text='\u66f4\u65b0\u65f6\u95f4', verbose_name='updated_at', auto_now=True)),
|
|
21
|
+ ('franchiser_id', shortuuidfield.fields.ShortUUIDField(editable=False, max_length=22, blank=True, help_text='\u7ecf\u9500\u5546\u552f\u4e00\u6807\u8bc6', unique=True, db_index=True)),
|
|
22
|
+ ('franchiser_name', models.CharField(help_text='\u7ecf\u9500\u5546\u540d\u79f0', max_length=255, null=True, verbose_name='franchiser_name', blank=True)),
|
|
23
|
+ ('franchiser_addr', models.CharField(help_text='\u7ecf\u9500\u5546\u5730\u5740', max_length=255, null=True, verbose_name='franchiser_addr', blank=True)),
|
|
24
|
+ ('franchiser_phone', models.CharField(help_text='\u7ecf\u9500\u5546\u8054\u7cfb\u7535\u8bdd', max_length=255, null=True, verbose_name='franchiser_phone', blank=True)),
|
|
25
|
+ ('franchiser_boss_name', models.CharField(help_text='\u7ecf\u9500\u5546\u8001\u677f\u540d\u79f0', max_length=255, null=True, verbose_name='franchiser_boss_name', blank=True)),
|
|
26
|
+ ('franchiser_boss_phone', models.CharField(help_text='\u7ecf\u9500\u5546\u8001\u677f\u8054\u7cfb\u7535\u8bdd', max_length=255, null=True, verbose_name='franchiser_boss_phone', blank=True)),
|
|
27
|
+ ],
|
|
28
|
+ options={
|
|
29
|
+ 'verbose_name': 'franchiserinfo',
|
|
30
|
+ 'verbose_name_plural': 'franchiserinfo',
|
|
31
|
+ },
|
|
32
|
+ ),
|
|
33
|
+ migrations.CreateModel(
|
|
34
|
+ name='SaleclerkInfo',
|
|
35
|
+ fields=[
|
|
36
|
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
|
37
|
+ ('status', models.BooleanField(default=True, help_text='\u72b6\u6001', db_index=True, verbose_name='status')),
|
|
38
|
+ ('created_at', models.DateTimeField(help_text='\u521b\u5efa\u65f6\u95f4', verbose_name='created_at', auto_now_add=True)),
|
|
39
|
+ ('updated_at', models.DateTimeField(help_text='\u66f4\u65b0\u65f6\u95f4', verbose_name='updated_at', auto_now=True)),
|
|
40
|
+ ('franchiser_id', models.CharField(max_length=255, blank=True, help_text='\u7ecf\u9500\u5546\u552f\u4e00\u6807\u8bc6', null=True, verbose_name='franchiser_id', db_index=True)),
|
|
41
|
+ ('clerk_id', shortuuidfield.fields.ShortUUIDField(editable=False, max_length=22, blank=True, help_text='\u5e97\u5458\u552f\u4e00\u6807\u8bc6', unique=True, db_index=True)),
|
|
42
|
+ ('clerk_name', models.CharField(help_text='\u5e97\u5458\u540d\u79f0', max_length=255, null=True, verbose_name='clerk_name', blank=True)),
|
|
43
|
+ ('clerk_sex', models.IntegerField(default=1, help_text='\u5e97\u5458\u6027\u522b', verbose_name='clerk_sex', choices=[(1, '\u7537'), (0, '\u5973')])),
|
|
44
|
+ ('clerk_phone', models.CharField(help_text='\u5e97\u5458\u8054\u7cfb\u7535\u8bdd', max_length=255, null=True, verbose_name='clerk_phone', blank=True)),
|
|
45
|
+ ('openid', models.CharField(null=True, max_length=255, blank=True, help_text='\u5fae\u4fe1 OpenID', unique=True, verbose_name='openid', db_index=True)),
|
|
46
|
+ ('unionid', models.CharField(null=True, max_length=255, blank=True, help_text='\u5fae\u4fe1 UnionID', unique=True, verbose_name='unionid', db_index=True)),
|
|
47
|
+ ('user_status', models.IntegerField(default=0, verbose_name='user_status', choices=[(-1, '\u5df2\u62d2\u7edd'), (0, '\u672a\u9a8c\u8bc1'), (1, '\u5df2\u6fc0\u6d3b'), (2, '\u5df2\u7981\u7528'), (3, '\u5df2\u5220\u9664'), (10, '\u5df2\u5206\u914d')])),
|
|
48
|
+ ('refused_reason', models.TextField(help_text='\u5ba1\u6838\u62d2\u7edd\u539f\u56e0', null=True, verbose_name='refused_reason', blank=True)),
|
|
49
|
+ ],
|
|
50
|
+ options={
|
|
51
|
+ 'verbose_name': 'saleclerkinfo',
|
|
52
|
+ 'verbose_name_plural': 'saleclerkinfo',
|
|
53
|
+ },
|
|
54
|
+ ),
|
|
55
|
+ ]
|
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+from __future__ import unicode_literals
|
|
3
|
+
|
|
4
|
+from django.db import models, migrations
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+ dependencies = [
|
|
10
|
+ ('account', '0001_initial'),
|
|
11
|
+ ]
|
|
12
|
+
|
|
13
|
+ operations = [
|
|
14
|
+ migrations.AlterModelOptions(
|
|
15
|
+ name='franchiserinfo',
|
|
16
|
+ options={'verbose_name': '\u7ecf\u9500\u5546\u4fe1\u606f\u8868', 'verbose_name_plural': '\u7ecf\u9500\u5546\u4fe1\u606f\u8868'},
|
|
17
|
+ ),
|
|
18
|
+ migrations.AddField(
|
|
19
|
+ model_name='saleclerkinfo',
|
|
20
|
+ name='integral',
|
|
21
|
+ field=models.IntegerField(default=0, help_text='\u79ef\u5206', verbose_name='integral'),
|
|
22
|
+ ),
|
|
23
|
+ migrations.AlterField(
|
|
24
|
+ model_name='saleclerkinfo',
|
|
25
|
+ name='clerk_sex',
|
|
26
|
+ field=models.IntegerField(default=1, help_text='\u5e97\u5458\u6027\u522b', db_index=True, verbose_name='clerk_sex', choices=[(1, '\u7537'), (0, '\u5973')]),
|
|
27
|
+ ),
|
|
28
|
+ migrations.AlterField(
|
|
29
|
+ model_name='saleclerkinfo',
|
|
30
|
+ name='user_status',
|
|
31
|
+ field=models.IntegerField(default=0, help_text='\u7528\u6237\u72b6\u6001', db_index=True, verbose_name='user_status', choices=[(-1, '\u5df2\u62d2\u7edd'), (0, '\u672a\u9a8c\u8bc1'), (1, '\u5df2\u6fc0\u6d3b'), (2, '\u5df2\u7981\u7528'), (3, '\u5df2\u5220\u9664'), (10, '\u5df2\u5206\u914d')]),
|
|
32
|
+ ),
|
|
33
|
+ ]
|
|
|
@@ -0,0 +1,19 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+from __future__ import unicode_literals
|
|
3
|
+
|
|
4
|
+from django.db import models, migrations
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+ dependencies = [
|
|
10
|
+ ('account', '0002_auto_20170619_1635'),
|
|
11
|
+ ]
|
|
12
|
+
|
|
13
|
+ operations = [
|
|
14
|
+ migrations.AddField(
|
|
15
|
+ model_name='saleclerkinfo',
|
|
16
|
+ name='franchiser_name',
|
|
17
|
+ field=models.CharField(help_text='\u7ecf\u9500\u5546\u540d\u79f0', max_length=255, null=True, verbose_name='franchiser_name', blank=True),
|
|
18
|
+ ),
|
|
19
|
+ ]
|
|
|
@@ -0,0 +1,92 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+from django.db import models
|
|
4
|
+from django.utils.translation import ugettext_lazy as _
|
|
5
|
+from shortuuidfield import ShortUUIDField
|
|
6
|
+
|
|
7
|
+from tamron.basemodels import CreateUpdateMixin
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+class FranchiserInfo(CreateUpdateMixin):
|
|
11
|
+ franchiser_id = ShortUUIDField(_(u'franchiser_id'), max_length=255, help_text=u'经销商唯一标识', db_index=True, unique=True)
|
|
12
|
+ franchiser_name = models.CharField(_(u'franchiser_name'), max_length=255, blank=True, null=True, help_text=u'经销商名称')
|
|
13
|
+ franchiser_addr = models.CharField(_(u'franchiser_addr'), max_length=255, blank=True, null=True, help_text=u'经销商地址')
|
|
14
|
+ franchiser_phone = models.CharField(_(u'franchiser_phone'), max_length=255, blank=True, null=True, help_text=u'经销商联系电话')
|
|
15
|
+ franchiser_boss_name = models.CharField(_(u'franchiser_boss_name'), max_length=255, blank=True, null=True, help_text=u'经销商老板名称')
|
|
16
|
+ franchiser_boss_phone = models.CharField(_(u'franchiser_boss_phone'), max_length=255, blank=True, null=True, help_text=u'经销商老板联系电话')
|
|
17
|
+
|
|
18
|
+ class Meta:
|
|
19
|
+ verbose_name = _(u'经销商信息表')
|
|
20
|
+ verbose_name_plural = _(u'经销商信息表')
|
|
21
|
+
|
|
22
|
+ def __unicode__(self):
|
|
23
|
+ return unicode(self.pk)
|
|
24
|
+
|
|
25
|
+ @property
|
|
26
|
+ def data(self):
|
|
27
|
+ return {
|
|
28
|
+ 'franchiser_id': self.franchiser_id,
|
|
29
|
+ 'franchiser_name': self.franchiser_name,
|
|
30
|
+ }
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+class SaleclerkInfo(CreateUpdateMixin):
|
|
34
|
+ MALE = 1
|
|
35
|
+ FEMALE = 0
|
|
36
|
+
|
|
37
|
+ SEX_TYPE = (
|
|
38
|
+ (MALE, u'男'),
|
|
39
|
+ (FEMALE, u'女'),
|
|
40
|
+ )
|
|
41
|
+
|
|
42
|
+ REFUSED = -1
|
|
43
|
+ UNVERIFIED = 0
|
|
44
|
+ ACTIVATED = 1
|
|
45
|
+ DISABLED = 2
|
|
46
|
+ DELETED = 3
|
|
47
|
+ ASSIGN = 10
|
|
48
|
+
|
|
49
|
+ USER_STATUS = (
|
|
50
|
+ (REFUSED, u'已拒绝'),
|
|
51
|
+ (UNVERIFIED, u'未验证'),
|
|
52
|
+ (ACTIVATED, u'已激活'),
|
|
53
|
+ (DISABLED, u'已禁用'),
|
|
54
|
+ (DELETED, u'已删除'),
|
|
55
|
+ (ASSIGN, u'已分配'),
|
|
56
|
+ )
|
|
57
|
+
|
|
58
|
+ franchiser_id = models.CharField(_(u'franchiser_id'), max_length=255, blank=True, null=True, help_text=u'经销商唯一标识', db_index=True)
|
|
59
|
+ franchiser_name = models.CharField(_(u'franchiser_name'), max_length=255, blank=True, null=True, help_text=u'经销商名称')
|
|
60
|
+ clerk_id = ShortUUIDField(_(u'clerk_id'), max_length=255, help_text=u'店员唯一标识', db_index=True, unique=True)
|
|
61
|
+ clerk_name = models.CharField(_(u'clerk_name'), max_length=255, blank=True, null=True, help_text=u'店员名称')
|
|
62
|
+ clerk_sex = models.IntegerField(_(u'clerk_sex'), choices=SEX_TYPE, default=MALE, help_text=u'店员性别', db_index=True)
|
|
63
|
+ clerk_phone = models.CharField(_(u'clerk_phone'), max_length=255, blank=True, null=True, help_text=u'店员联系电话')
|
|
64
|
+
|
|
65
|
+ openid = models.CharField(_(u'openid'), max_length=255, blank=True, null=True, help_text=u'微信 OpenID', db_index=True, unique=True)
|
|
66
|
+ unionid = models.CharField(_(u'unionid'), max_length=255, blank=True, null=True, help_text=u'微信 UnionID', db_index=True, unique=True)
|
|
67
|
+
|
|
68
|
+ integral = models.IntegerField(_(u'integral'), default=0, help_text=u'积分')
|
|
69
|
+
|
|
70
|
+ user_status = models.IntegerField(_(u'user_status'), choices=USER_STATUS, default=UNVERIFIED, help_text=u'用户状态', db_index=True)
|
|
71
|
+ refused_reason = models.TextField(_(u'refused_reason'), blank=True, null=True, help_text=u'审核拒绝原因')
|
|
72
|
+
|
|
73
|
+ class Meta:
|
|
74
|
+ verbose_name = _(u'saleclerkinfo')
|
|
75
|
+ verbose_name_plural = _(u'saleclerkinfo')
|
|
76
|
+
|
|
77
|
+ def __unicode__(self):
|
|
78
|
+ return unicode(self.pk)
|
|
79
|
+
|
|
80
|
+ @property
|
|
81
|
+ def data(self):
|
|
82
|
+ return {
|
|
83
|
+ 'franchiser_id': self.franchiser_id,
|
|
84
|
+ 'franchiser_name': self.franchiser_name,
|
|
85
|
+ 'clerk_id': self.clerk_id,
|
|
86
|
+ 'clerk_name': self.clerk_name,
|
|
87
|
+ 'clerk_sex': self.clerk_sex,
|
|
88
|
+ 'clerk_phone': self.clerk_phone,
|
|
89
|
+ 'integral': self.integral,
|
|
90
|
+ 'status': self.user_status,
|
|
91
|
+ 'refused_reason': self.refused_reason,
|
|
92
|
+ }
|
|
|
@@ -0,0 +1,4 @@
|
|
1
|
+from django.test import TestCase
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+# Create your tests here.
|
|
|
@@ -0,0 +1,4 @@
|
|
1
|
+from django.shortcuts import render
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+# Create your views here.
|
|
|
@@ -0,0 +1,4 @@
|
|
1
|
+from django.contrib import admin
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+# Register your models here.
|
|
|
@@ -0,0 +1,4 @@
|
|
1
|
+from django.db import models
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+# Create your models here.
|
|
|
@@ -0,0 +1,4 @@
|
|
1
|
+from django.test import TestCase
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+# Create your tests here.
|
|
|
@@ -0,0 +1,11 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+from django.conf.urls import url
|
|
4
|
+
|
|
5
|
+from page import oauth_views, sale_views
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+urlpatterns = [
|
|
9
|
+ url(r'^clerk/submit$', oauth_views.clerk_submit_api, name='clerk_submit_api'), # 店员信息提交
|
|
10
|
+ url(r'^clerk/sale/submit$', sale_views.clerk_sale_submit_api, name='clerk_sale_submit_api'), # 店员销售信息提交
|
|
11
|
+]
|
|
|
@@ -0,0 +1,4 @@
|
|
1
|
+from django.shortcuts import render
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+# Create your views here.
|
|
|
@@ -0,0 +1,9 @@
|
|
1
|
+#!/bin/bash
|
|
2
|
+
|
|
3
|
+echo '>> iSort'
|
|
4
|
+./isort.sh
|
|
5
|
+echo
|
|
6
|
+
|
|
7
|
+echo '>> PEP8'
|
|
8
|
+./pep8.sh
|
|
9
|
+echo
|
|
|
@@ -0,0 +1,15 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+from django.contrib import admin
|
|
4
|
+
|
|
5
|
+from integral.models import SaleclerkIntegralIncomeExpensesInfo
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+class SaleclerkIntegralIncomeExpensesInfoAdmin(admin.ModelAdmin):
|
|
9
|
+ readonly_fields = ('franchiser_id', 'clerk_id', 'type', 'code', 'integral', 'left_integral')
|
|
10
|
+ list_display = ('franchiser_id', 'clerk_id', 'type', 'code', 'integral', 'left_integral', 'remark', 'status', 'created_at', 'updated_at')
|
|
11
|
+ search_fields = ('code', 'remark')
|
|
12
|
+ list_filter = ('franchiser_id', 'type', 'status')
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+admin.site.register(SaleclerkIntegralIncomeExpensesInfo, SaleclerkIntegralIncomeExpensesInfoAdmin)
|
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+from __future__ import unicode_literals
|
|
3
|
+
|
|
4
|
+from django.db import models, migrations
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+ dependencies = [
|
|
10
|
+ ]
|
|
11
|
+
|
|
12
|
+ operations = [
|
|
13
|
+ migrations.CreateModel(
|
|
14
|
+ name='SaleclerkIntegralIncomeExpensesInfo',
|
|
15
|
+ fields=[
|
|
16
|
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
|
17
|
+ ('status', models.BooleanField(default=True, help_text='\u72b6\u6001', db_index=True, verbose_name='status')),
|
|
18
|
+ ('created_at', models.DateTimeField(help_text='\u521b\u5efa\u65f6\u95f4', verbose_name='created_at', auto_now_add=True)),
|
|
19
|
+ ('updated_at', models.DateTimeField(help_text='\u66f4\u65b0\u65f6\u95f4', verbose_name='updated_at', auto_now=True)),
|
|
20
|
+ ('franchiser_id', models.CharField(max_length=255, blank=True, help_text='\u7ecf\u9500\u5546\u552f\u4e00\u6807\u8bc6', null=True, verbose_name='franchiser_id', db_index=True)),
|
|
21
|
+ ('clerk_id', models.CharField(max_length=255, blank=True, help_text='\u5e97\u5458\u552f\u4e00\u6807\u8bc6', null=True, verbose_name='clerk_id', db_index=True)),
|
|
22
|
+ ('type', models.IntegerField(default=0, help_text='\u6536\u652f\u7c7b\u522b', db_index=True, verbose_name='type', choices=[(0, '\u6536\u5165'), (1, '\u652f\u51fa'), (2, '\u89e3\u51bb')])),
|
|
23
|
+ ('code', models.CharField(help_text='\u673a\u8eab\u7801', max_length=255, null=True, verbose_name='code', blank=True)),
|
|
24
|
+ ('integral', models.IntegerField(default=0, help_text='\u589e\u51cf\u79ef\u5206', verbose_name='integral')),
|
|
25
|
+ ('left_integral', models.IntegerField(default=0, help_text='\u79ef\u5206\u589e\u51cf\u540e\u6570\u91cf(\u5206)', verbose_name='left_integral')),
|
|
26
|
+ ('remark', models.CharField(help_text='\u5907\u6ce8', max_length=255, null=True, verbose_name='remark', blank=True)),
|
|
27
|
+ ],
|
|
28
|
+ options={
|
|
29
|
+ 'verbose_name': 'saleclerkintegralincomeexpensesinfo',
|
|
30
|
+ 'verbose_name_plural': 'saleclerkintegralincomeexpensesinfo',
|
|
31
|
+ },
|
|
32
|
+ ),
|
|
33
|
+ ]
|
|
|
@@ -0,0 +1,19 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+from __future__ import unicode_literals
|
|
3
|
+
|
|
4
|
+from django.db import models, migrations
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+ dependencies = [
|
|
10
|
+ ('integral', '0001_initial'),
|
|
11
|
+ ]
|
|
12
|
+
|
|
13
|
+ operations = [
|
|
14
|
+ migrations.AlterField(
|
|
15
|
+ model_name='saleclerkintegralincomeexpensesinfo',
|
|
16
|
+ name='code',
|
|
17
|
+ field=models.CharField(max_length=255, blank=True, help_text='\u673a\u8eab\u7801', null=True, verbose_name='code', db_index=True),
|
|
18
|
+ ),
|
|
19
|
+ ]
|
|
|
@@ -0,0 +1,36 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+from django.db import models
|
|
4
|
+from django.utils.translation import ugettext_lazy as _
|
|
5
|
+
|
|
6
|
+from tamron.basemodels import CreateUpdateMixin
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+class SaleclerkIntegralIncomeExpensesInfo(CreateUpdateMixin):
|
|
10
|
+ INCOME = 0
|
|
11
|
+ EXPENSE = 1
|
|
12
|
+ UNFREEZE = 2
|
|
13
|
+
|
|
14
|
+ TYPE = (
|
|
15
|
+ (INCOME, u'收入'),
|
|
16
|
+ (EXPENSE, u'支出'),
|
|
17
|
+ (UNFREEZE, u'解冻'),
|
|
18
|
+ )
|
|
19
|
+
|
|
20
|
+ franchiser_id = models.CharField(_(u'franchiser_id'), max_length=255, blank=True, null=True, help_text=u'经销商唯一标识', db_index=True)
|
|
21
|
+ clerk_id = models.CharField(_(u'clerk_id'), max_length=255, blank=True, null=True, help_text=u'店员唯一标识', db_index=True)
|
|
22
|
+
|
|
23
|
+ type = models.IntegerField(_(u'type'), choices=TYPE, default=INCOME, help_text=u'收支类别', db_index=True)
|
|
24
|
+
|
|
25
|
+ code = models.CharField(_(u'code'), max_length=255, blank=True, null=True, help_text=u'机身码', db_index=True)
|
|
26
|
+ integral = models.IntegerField(_(u'integral'), default=0, help_text=u'增减积分')
|
|
27
|
+ left_integral = models.IntegerField(_(u'left_integral'), default=0, help_text=u'积分增减后数量(分)')
|
|
28
|
+
|
|
29
|
+ remark = models.CharField(_(u'remark'), max_length=255, blank=True, null=True, help_text=u'备注')
|
|
30
|
+
|
|
31
|
+ class Meta:
|
|
32
|
+ verbose_name = _(u'saleclerkintegralincomeexpensesinfo')
|
|
33
|
+ verbose_name_plural = _(u'saleclerkintegralincomeexpensesinfo')
|
|
34
|
+
|
|
35
|
+ def __unicode__(self):
|
|
36
|
+ return unicode(self.pk)
|
|
|
@@ -0,0 +1,4 @@
|
|
1
|
+from django.test import TestCase
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+# Create your tests here.
|
|
|
@@ -0,0 +1,4 @@
|
|
1
|
+from django.shortcuts import render
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+# Create your views here.
|
|
|
@@ -0,0 +1,3 @@
|
|
1
|
+#!/bin/bash
|
|
2
|
+
|
|
3
|
+isort -rc -sp . .
|
|
|
@@ -0,0 +1,11 @@
|
|
1
|
+#!/usr/bin/env python
|
|
2
|
+import os
|
|
3
|
+import sys
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+if __name__ == "__main__":
|
|
7
|
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tamron.settings")
|
|
8
|
+
|
|
9
|
+ from django.core.management import execute_from_command_line
|
|
10
|
+
|
|
11
|
+ execute_from_command_line(sys.argv)
|
|
|
@@ -0,0 +1,4 @@
|
|
1
|
+from django.contrib import admin
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+# Register your models here.
|
|
|
@@ -0,0 +1,22 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+from __future__ import division
|
|
4
|
+
|
|
5
|
+from django.conf import settings
|
|
6
|
+from django.shortcuts import render
|
|
7
|
+
|
|
8
|
+from account.models import SaleclerkInfo
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+def clerk_info_oauth(request):
|
|
12
|
+ unionid = request.GET.get('unionid', '')
|
|
13
|
+
|
|
14
|
+ try:
|
|
15
|
+ clerk = SaleclerkInfo.objects.get(unionid=unionid)
|
|
16
|
+ except SaleclerkInfo.DoesNotExist:
|
|
17
|
+ clerk = None
|
|
18
|
+
|
|
19
|
+ return render(request, 'page/clerk_info.html', {
|
|
20
|
+ 'domain': settings.DOMAIN,
|
|
21
|
+ 'clerk_info': clerk and clerk.data,
|
|
22
|
+ })
|
|
|
@@ -0,0 +1,4 @@
|
|
1
|
+from django.db import models
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+# Create your models here.
|
|
|
@@ -0,0 +1,70 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+from __future__ import division
|
|
4
|
+
|
|
5
|
+from django.conf import settings
|
|
6
|
+from django.db import transaction
|
|
7
|
+from django.shortcuts import render
|
|
8
|
+from logit import logit
|
|
9
|
+
|
|
10
|
+from account.models import FranchiserInfo, SaleclerkInfo
|
|
11
|
+from utils.error.errno_utils import FranchiserStatusCode, SaleclerkStatusCode
|
|
12
|
+from utils.error.response_utils import response
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+def clerk_oauth(request):
|
|
16
|
+ unionid = request.GET.get('unionid', '')
|
|
17
|
+
|
|
18
|
+ chisers = FranchiserInfo.objects.filter(status=True)
|
|
19
|
+ chisers = [chiser.data for chiser in chisers]
|
|
20
|
+
|
|
21
|
+ try:
|
|
22
|
+ clerk = SaleclerkInfo.objects.get(unionid=unionid)
|
|
23
|
+ except SaleclerkInfo.DoesNotExist:
|
|
24
|
+ clerk = None
|
|
25
|
+
|
|
26
|
+ return render(request, 'page/clerk_oauth.html', {
|
|
27
|
+ 'domain': settings.DOMAIN,
|
|
28
|
+ 'chisers': chisers,
|
|
29
|
+ 'clerk_info': clerk and clerk.data,
|
|
30
|
+ 'modified': bool((not clerk) or (clerk and clerk.user_status in [SaleclerkInfo.UNVERIFIED, SaleclerkInfo.REFUSED])), # 是否可以更改信息
|
|
31
|
+ })
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+@logit
|
|
35
|
+@transaction.atomic
|
|
36
|
+def clerk_submit_api(request):
|
|
37
|
+ """ 店员授权信息提交 """
|
|
38
|
+ unionid = request.POST.get('unionid', '')
|
|
39
|
+ openid = request.POST.get('openid', '')
|
|
40
|
+ phone = request.POST.get('phone', '')
|
|
41
|
+ chiser = request.POST.get('chiser', '')
|
|
42
|
+
|
|
43
|
+ if SaleclerkInfo.objects.filter(clerk_phone=phone).exclude(unionid=unionid).exists():
|
|
44
|
+ return response(SaleclerkStatusCode.CLERK_PHONE_ALREADY_EXISTS)
|
|
45
|
+
|
|
46
|
+ try:
|
|
47
|
+ franchiser = FranchiserInfo.objects.get(franchiser_id=chiser)
|
|
48
|
+ except FranchiserInfo.DoesNotExist:
|
|
49
|
+ return response(FranchiserStatusCode.CHISER_NOT_FOUND)
|
|
50
|
+
|
|
51
|
+ fields = {
|
|
52
|
+ 'franchiser_id': chiser,
|
|
53
|
+ 'franchiser_name': franchiser.franchiser_name,
|
|
54
|
+ 'clerk_name': request.POST.get('name', ''),
|
|
55
|
+ 'clerk_sex': int(request.POST.get('sex', 1)),
|
|
56
|
+ 'clerk_phone': phone,
|
|
57
|
+ 'openid': openid,
|
|
58
|
+ 'user_status': SaleclerkInfo.UNVERIFIED,
|
|
59
|
+ }
|
|
60
|
+
|
|
61
|
+ lensman, created = SaleclerkInfo.objects.select_for_update().get_or_create(unionid=unionid, defaults=fields)
|
|
62
|
+ # 状态为 UNVERIFIED 的允许修改, 其他需要登录摄影师 APP 进行信息的修改
|
|
63
|
+ if lensman.user_status not in [SaleclerkInfo.UNVERIFIED, SaleclerkInfo.REFUSED]:
|
|
64
|
+ return response(SaleclerkInfo.LENSMAN_ALREADY_NOT_UNVERIFIED)
|
|
65
|
+ if not created:
|
|
66
|
+ for key, value in fields.iteritems():
|
|
67
|
+ setattr(lensman, key, value)
|
|
68
|
+ lensman.save()
|
|
69
|
+
|
|
70
|
+ return response(200, 'Submit Success', u'提交成功', {})
|
|
|
@@ -0,0 +1,111 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+from __future__ import division
|
|
4
|
+
|
|
5
|
+from django.conf import settings
|
|
6
|
+from django.db import transaction
|
|
7
|
+from django.shortcuts import render
|
|
8
|
+from logit import logit
|
|
9
|
+
|
|
10
|
+from account.models import SaleclerkInfo
|
|
11
|
+from integral.models import SaleclerkIntegralIncomeExpensesInfo
|
|
12
|
+from product.models import ProductCodeSubmitLogInfo, ProductInfo, ProductModelInfo
|
|
13
|
+from utils.error.errno_utils import ProductModelStatusCode, ProductStatusCode, SaleclerkStatusCode
|
|
14
|
+from utils.error.response_utils import response
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+def clerk_sale_oauth(request):
|
|
18
|
+ unionid = request.GET.get('unionid', '')
|
|
19
|
+
|
|
20
|
+ models = ProductModelInfo.objects.filter(status=True)
|
|
21
|
+ models = [model.data for model in models]
|
|
22
|
+
|
|
23
|
+ try:
|
|
24
|
+ clerk = SaleclerkInfo.objects.get(unionid=unionid)
|
|
25
|
+ except SaleclerkInfo.DoesNotExist:
|
|
26
|
+ clerk = None
|
|
27
|
+
|
|
28
|
+ return render(request, 'page/clerk_sale.html', {
|
|
29
|
+ 'domain': settings.DOMAIN,
|
|
30
|
+ 'models': models,
|
|
31
|
+ 'clerk_info': clerk and clerk.data,
|
|
32
|
+ })
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+@logit
|
|
36
|
+@transaction.atomic
|
|
37
|
+def clerk_sale_submit_api(request):
|
|
38
|
+ """ 店员信息提交 """
|
|
39
|
+ clerk_id = request.POST.get('clerk_id', '')
|
|
40
|
+ model_id = request.POST.get('model_id', '')
|
|
41
|
+ code = request.POST.get('code', '')
|
|
42
|
+ name = request.POST.get('name', '')
|
|
43
|
+ sex = int(request.POST.get('sex', 1))
|
|
44
|
+ age = int(request.POST.get('age', 1))
|
|
45
|
+ phone = request.POST.get('phone', '')
|
|
46
|
+
|
|
47
|
+ # 店员是否存在
|
|
48
|
+ try:
|
|
49
|
+ clerk = SaleclerkInfo.objects.select_for_update().get(clerk_id=clerk_id)
|
|
50
|
+ except SaleclerkInfo.DoesNotExist:
|
|
51
|
+ return response(SaleclerkStatusCode.CLERK_NOT_FOUND)
|
|
52
|
+
|
|
53
|
+ # 店员是否激活
|
|
54
|
+ if clerk.user_status != SaleclerkInfo.ACTIVATED:
|
|
55
|
+ return response(SaleclerkStatusCode.CLERK_NOT_ACTIVATED)
|
|
56
|
+
|
|
57
|
+ # 型号是否存在
|
|
58
|
+ try:
|
|
59
|
+ model = ProductModelInfo.objects.get(model_id=model_id)
|
|
60
|
+ except ProductModelInfo.DoesNotExist:
|
|
61
|
+ return response(ProductModelStatusCode.MODEL_NOT_FOUND)
|
|
62
|
+
|
|
63
|
+ # 记录销售提交记录
|
|
64
|
+ ProductCodeSubmitLogInfo.objects.create(
|
|
65
|
+ model_id=model.model_id,
|
|
66
|
+ model_name=model.model_name,
|
|
67
|
+ code=code,
|
|
68
|
+ franchiser_id=clerk.franchiser_id,
|
|
69
|
+ clerk_id=clerk.clerk_id,
|
|
70
|
+ consumer_name=name,
|
|
71
|
+ consumer_sex=sex,
|
|
72
|
+ consumer_age=age,
|
|
73
|
+ consumer_phone=phone,
|
|
74
|
+ )
|
|
75
|
+
|
|
76
|
+ # 产品是否存在
|
|
77
|
+ try:
|
|
78
|
+ product = ProductInfo.objects.select_for_update().get(model_id=model_id, code=code)
|
|
79
|
+ except ProductInfo.DoesNotExist:
|
|
80
|
+ return response(ProductStatusCode.PRODUCT_NOT_FOUND)
|
|
81
|
+
|
|
82
|
+ # 产品是否使用
|
|
83
|
+ if product.code_status:
|
|
84
|
+ return response(ProductStatusCode.PRODUCT_HAS_USED)
|
|
85
|
+
|
|
86
|
+ # 产品使用
|
|
87
|
+ product.code_status = True
|
|
88
|
+ product.integral_status = True
|
|
89
|
+ product.franchiser_id = clerk.franchiser_id
|
|
90
|
+ product.clerk_id = clerk.clerk_id
|
|
91
|
+ product.consumer_name = name
|
|
92
|
+ product.consumer_sex = sex
|
|
93
|
+ product.consumer_age = age
|
|
94
|
+ product.consumer_phone = phone
|
|
95
|
+ product.save()
|
|
96
|
+
|
|
97
|
+ # 店员积分
|
|
98
|
+ clerk.integral += product.integral
|
|
99
|
+ clerk.save()
|
|
100
|
+
|
|
101
|
+ # 店员积分记录
|
|
102
|
+ SaleclerkIntegralIncomeExpensesInfo.objects.create(
|
|
103
|
+ franchiser_id=clerk.franchiser_id,
|
|
104
|
+ clerk_id=clerk.clerk_id,
|
|
105
|
+ type=SaleclerkIntegralIncomeExpensesInfo.INCOME,
|
|
106
|
+ code=code,
|
|
107
|
+ integral=product.integral,
|
|
108
|
+ left_integral=clerk.integral,
|
|
109
|
+ )
|
|
110
|
+
|
|
111
|
+ return response(200, 'Submit Success', u'提交成功', {})
|
|
|
@@ -0,0 +1,74 @@
|
|
1
|
+{% load staticfiles %}
|
|
2
|
+
|
|
3
|
+<!DOCTYPE html>
|
|
4
|
+<html lang="zh-CN">
|
|
5
|
+ <head>
|
|
6
|
+ <meta charset="utf-8">
|
|
7
|
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
|
8
|
+ <meta name="format-detection" content="telephone=no,email=no,address=no">
|
|
9
|
+ <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
|
|
10
|
+ <title>店员销售</title>
|
|
11
|
+
|
|
12
|
+ <link href="https://res.wx.qq.com/open/libs/weui/0.4.3/weui.min.css" rel="stylesheet" type="text/css" />
|
|
13
|
+
|
|
14
|
+ <style>
|
|
15
|
+ input:required:invalid {
|
|
16
|
+ color: #E64340;
|
|
17
|
+ }
|
|
18
|
+ input:required:valid {
|
|
19
|
+ color: rgb(0, 0, 0);
|
|
20
|
+ }
|
|
21
|
+ </style>
|
|
22
|
+ </head>
|
|
23
|
+ <body>
|
|
24
|
+ <div class="container" >
|
|
25
|
+ <div class="weui_cells_title">基本信息</div>
|
|
26
|
+ <div class="weui_cells weui_cells_form">
|
|
27
|
+ <div class="weui_cell">
|
|
28
|
+ <div class="weui_cell_hd"><label for="" class="weui_label">姓名</label></div>
|
|
29
|
+ <div class="weui_cell_bd weui_cell_primary">
|
|
30
|
+ <input id="chiser" class="weui_input" type="text" value="{{ clerk_info.franchiser_name }}" disabled>
|
|
31
|
+ </div>
|
|
32
|
+ </div>
|
|
33
|
+ <div class="weui_cell">
|
|
34
|
+ <div class="weui_cell_hd"><label for="" class="weui_label">姓名</label></div>
|
|
35
|
+ <div class="weui_cell_bd weui_cell_primary">
|
|
36
|
+ <input id="name" class="weui_input" type="text" value="{{ clerk_info.clerk_name }}" disabled>
|
|
37
|
+ </div>
|
|
38
|
+ </div>
|
|
39
|
+ <div class="weui_cell">
|
|
40
|
+ <div class="weui_cell_hd"><label for="" class="weui_label">姓名</label></div>
|
|
41
|
+ <div class="weui_cell_bd weui_cell_primary">
|
|
42
|
+ <input id="sex" class="weui_input" type="text" value="{% ifequal clerk_info.clerk_sex 1 %}男{% else %}女{% endifequal %}" disabled>
|
|
43
|
+ </div>
|
|
44
|
+ </div>
|
|
45
|
+ <div class="weui_cell">
|
|
46
|
+ <div class="weui_cell_hd"><label for="" class="weui_label">手机号</label></div>
|
|
47
|
+ <div class="weui_cell_bd weui_cell_primary">
|
|
48
|
+ <input id="phone" class="weui_input" type="text" required="required" pattern="[0-9]{11}" value="{{ clerk_info.clerk_phone }}" disabled>
|
|
49
|
+ </div>
|
|
50
|
+ </div>
|
|
51
|
+ <div class="weui_cell">
|
|
52
|
+ <div class="weui_cell_hd"><label for="" class="weui_label">积分</label></div>
|
|
53
|
+ <div class="weui_cell_bd weui_cell_primary">
|
|
54
|
+ <input id="integral" class="weui_input" type="text" required="required" pattern="[0-9]{11}" value="{{ clerk_info.integral }}" disabled>
|
|
55
|
+ </div>
|
|
56
|
+ </div>
|
|
57
|
+ </div>
|
|
58
|
+ </div>
|
|
59
|
+
|
|
60
|
+ <script src="//cdn.bootcss.com/zepto/1.1.6/zepto.min.js"></script>
|
|
61
|
+ <script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
|
|
62
|
+ <script type="text/javascript" src="{% static 'tamron/js/jswe.js' %}?v=1"></script>
|
|
63
|
+ <script>
|
|
64
|
+ V.initWxData({
|
|
65
|
+ imgUrl: "http://pai.ai/static/pai2/img/paiai_96_96.png",
|
|
66
|
+ link: 'http://api.pai.ai/wx_oauth2?redirect_url=http://pai.ai/page/lensman&scope=snsapi_base',
|
|
67
|
+ desc: "摄影师授权",
|
|
68
|
+ title: "摄影师授权",
|
|
69
|
+ timeLine: ""
|
|
70
|
+ }, true);
|
|
71
|
+ V.hideOptionMenu();
|
|
72
|
+ </script>
|
|
73
|
+ </body>
|
|
74
|
+</html>
|
|
|
@@ -0,0 +1,198 @@
|
|
1
|
+{% load staticfiles %}
|
|
2
|
+
|
|
3
|
+<!DOCTYPE html>
|
|
4
|
+<html lang="zh-CN">
|
|
5
|
+ <head>
|
|
6
|
+ <meta charset="utf-8">
|
|
7
|
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
|
8
|
+ <meta name="format-detection" content="telephone=no,email=no,address=no">
|
|
9
|
+ <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
|
|
10
|
+ <title>店员授权</title>
|
|
11
|
+
|
|
12
|
+ <link href="https://res.wx.qq.com/open/libs/weui/0.4.3/weui.min.css" rel="stylesheet" type="text/css" />
|
|
13
|
+
|
|
14
|
+ <style>
|
|
15
|
+ input:required:invalid {
|
|
16
|
+ color: #E64340;
|
|
17
|
+ }
|
|
18
|
+ input:required:valid {
|
|
19
|
+ color: rgb(0, 0, 0);
|
|
20
|
+ }
|
|
21
|
+ </style>
|
|
22
|
+ </head>
|
|
23
|
+ <body>
|
|
24
|
+ <div class="container" >
|
|
25
|
+ <div class="weui_cells_title">基本信息</div>
|
|
26
|
+ <div class="weui_cells weui_cells_form">
|
|
27
|
+ <div class="weui_cell weui_cell_select weui_select_after">
|
|
28
|
+ <div class="weui_cell_hd"><label for="" class="weui_label">经销商</label></div>
|
|
29
|
+ <div class="weui_cell_bd weui_cell_primary">
|
|
30
|
+ <select id="chiser" class="weui_select" name="select" {% if not modified %}disabled{% endif %}>
|
|
31
|
+ {% for chiser in chisers %}
|
|
32
|
+ <option value="{{ chiser.franchiser_id }}" {% ifequal chiser.franchiser_id clerk_info.franchiser_id %}selected{% endifequal %}>{{ chiser.franchiser_name }}</option>
|
|
33
|
+ {% endfor %}
|
|
34
|
+ </select>
|
|
35
|
+ </div>
|
|
36
|
+ </div>
|
|
37
|
+ <div class="weui_cell">
|
|
38
|
+ <div class="weui_cell_hd"><label for="" class="weui_label">姓名</label></div>
|
|
39
|
+ <div class="weui_cell_bd weui_cell_primary">
|
|
40
|
+ <input id="name" class="weui_input" type="text" value="{{ clerk_info.clerk_name }}" placeholder="请输入姓名" {% if not modified %}disabled{% endif %}>
|
|
41
|
+ </div>
|
|
42
|
+ </div>
|
|
43
|
+ <div class="weui_cell weui_cell_select weui_select_after">
|
|
44
|
+ <div class="weui_cell_hd"><label for="" class="weui_label">性别</label></div>
|
|
45
|
+ <div class="weui_cell_bd weui_cell_primary">
|
|
46
|
+ <select id="sex" class="weui_select" name="select" {% if not modified %}disabled{% endif %}>
|
|
47
|
+ <option value="1" {% ifequal clerk_info.clerk_sex 1 %}selected{% endifequal %}>男</option>
|
|
48
|
+ <option value="0" {% ifequal clerk_info.clerk_sex 0 %}selected{% endifequal %}>女</option>
|
|
49
|
+ </select>
|
|
50
|
+ </div>
|
|
51
|
+ </div>
|
|
52
|
+ <div class="weui_cell">
|
|
53
|
+ <div class="weui_cell_hd"><label for="" class="weui_label">手机号</label></div>
|
|
54
|
+ <div class="weui_cell_bd weui_cell_primary">
|
|
55
|
+ <input id="phone" class="weui_input" type="text" required="required" pattern="[0-9]{11}" value="{{ clerk_info.clerk_phone }}" placeholder="请输入手机号" {% if not modified %}disabled{% endif %}>
|
|
56
|
+ </div>
|
|
57
|
+ </div>
|
|
58
|
+ </div>
|
|
59
|
+
|
|
60
|
+ {% if clerk_info %}
|
|
61
|
+ <div class="weui_cells_title">审核状态</div>
|
|
62
|
+ <div class="weui_cells">
|
|
63
|
+ <div class="weui_cell">
|
|
64
|
+ <div class="weui_cell_bd weui_cell_primary">
|
|
65
|
+ <p>状态</p>
|
|
66
|
+ </div>
|
|
67
|
+ <div class="weui_cell_ft">
|
|
68
|
+ {% ifequal clerk_info.status -1 %}已拒绝{% endifequal %}
|
|
69
|
+ {% ifequal clerk_info.status 0 %}审核中{% endifequal %}
|
|
70
|
+ {% ifequal clerk_info.status 1 %}已激活{% endifequal %}
|
|
71
|
+ {% ifequal clerk_info.status 2 %}已禁用{% endifequal %}
|
|
72
|
+ {% ifequal clerk_info.status 3 %}已删除{% endifequal %}
|
|
73
|
+ </div>
|
|
74
|
+ </div>
|
|
75
|
+ </div>
|
|
76
|
+ {% endif %}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+ {% ifequal clerk_info.status -1 %}
|
|
80
|
+ <div class="weui_cells_title">拒绝原因</div>
|
|
81
|
+ <div class="weui_cells">
|
|
82
|
+ <div class="weui_panel_bd">
|
|
83
|
+ <div class="weui_media_box weui_media_text">
|
|
84
|
+ <p class="weui_media_desc">{{ clerk_info.refused_reason|safe|linebreaks }}</p>
|
|
85
|
+ </div>
|
|
86
|
+ </div>
|
|
87
|
+ </div>
|
|
88
|
+ {% endifequal %}
|
|
89
|
+
|
|
90
|
+ <br>
|
|
91
|
+
|
|
92
|
+ {% if modified %}<button id="submit" class="weui_btn weui_btn_warn">确认</button>{% endif %}
|
|
93
|
+
|
|
94
|
+ <div class="weui_dialog_alert" id="dialog" style="display: none">
|
|
95
|
+ <div class="weui_mask"></div>
|
|
96
|
+ <div class="weui_dialog">
|
|
97
|
+ <div class="weui_dialog_hd"><strong id="title" class="weui_dialog_title">弹窗标题</strong></div>
|
|
98
|
+ <div id="content" class="weui_dialog_bd">弹窗内容,告知当前页面信息等</div>
|
|
99
|
+ <div class="weui_dialog_ft">
|
|
100
|
+ <a href="javascript:;" class="weui_btn_dialog primary">确定</a>
|
|
101
|
+ </div>
|
|
102
|
+ </div>
|
|
103
|
+ </div>
|
|
104
|
+
|
|
105
|
+ <div id="toast" style="display: none;">
|
|
106
|
+ <div class="weui_mask_transparent"></div>
|
|
107
|
+ <div class="weui_toast">
|
|
108
|
+ <i class="weui_icon_toast"></i>
|
|
109
|
+ <p class="weui_toast_content">已完成</p>
|
|
110
|
+ </div>
|
|
111
|
+ </div>
|
|
112
|
+ </div>
|
|
113
|
+
|
|
114
|
+ <script src="//cdn.bootcss.com/zepto/1.1.6/zepto.min.js"></script>
|
|
115
|
+ <script>
|
|
116
|
+ {% if modified %}
|
|
117
|
+ $(function() {
|
|
118
|
+ function getURLParameter(name) {
|
|
119
|
+ return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [null, ''])[1].replace(/\+/g, '%20')) || null;
|
|
120
|
+ }
|
|
121
|
+
|
|
122
|
+ function show_error_dialog(title, content) {
|
|
123
|
+ $('#dialog #title').text(title);
|
|
124
|
+ $('#dialog #content').text(content);
|
|
125
|
+ $('#dialog').show();
|
|
126
|
+ }
|
|
127
|
+
|
|
128
|
+ function data_check() {
|
|
129
|
+ var unionid = getURLParameter('unionid');
|
|
130
|
+ if (!unionid) {
|
|
131
|
+ show_error_dialog('微信授权', '微信授权失败,请重新打开页面');
|
|
132
|
+ return false;
|
|
133
|
+ }
|
|
134
|
+
|
|
135
|
+ var name = $('#name').val();
|
|
136
|
+ if (!name) {
|
|
137
|
+ show_error_dialog('姓名', '姓名错误,请检查重新输入');
|
|
138
|
+ return false;
|
|
139
|
+ }
|
|
140
|
+
|
|
141
|
+ var phone_valid = $('#phone').is(':valid');
|
|
142
|
+ if (!phone_valid) {
|
|
143
|
+ show_error_dialog('手机号', '手机号错误,请检查重新输入');
|
|
144
|
+ return false;
|
|
145
|
+ }
|
|
146
|
+
|
|
147
|
+ return {
|
|
148
|
+ unionid: unionid,
|
|
149
|
+ openid: getURLParameter('openid'),
|
|
150
|
+ chiser: $('#chiser option:checked').val(),
|
|
151
|
+ name: name,
|
|
152
|
+ sex: $('#sex option:checked').val(),
|
|
153
|
+ phone: $('#phone').val(),
|
|
154
|
+ }
|
|
155
|
+ }
|
|
156
|
+
|
|
157
|
+ $('#submit').click(function () {
|
|
158
|
+ var check_result = data_check();
|
|
159
|
+ if (check_result){
|
|
160
|
+ $.ajax({
|
|
161
|
+ type: 'POST',
|
|
162
|
+ url: '{{ domain }}api/clerk/submit',
|
|
163
|
+ data: check_result,
|
|
164
|
+ success: function(data) {
|
|
165
|
+ if (data.status == 200) {
|
|
166
|
+ $('#toast').show();
|
|
167
|
+ setTimeout(function () {
|
|
168
|
+ $('#toast').hide();
|
|
169
|
+ }, 1000);
|
|
170
|
+ window.location.reload();
|
|
171
|
+ } else {
|
|
172
|
+ show_error_dialog('错误', data.description);
|
|
173
|
+ }
|
|
174
|
+ }
|
|
175
|
+ })
|
|
176
|
+ }
|
|
177
|
+ });
|
|
178
|
+
|
|
179
|
+ $('#dialog .weui_btn_dialog').click(function () {
|
|
180
|
+ $('#dialog').hide();
|
|
181
|
+ })
|
|
182
|
+ });
|
|
183
|
+ {% endif %}
|
|
184
|
+ </script>
|
|
185
|
+ <script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
|
|
186
|
+ <script type="text/javascript" src="{% static 'tamron/js/jswe.js' %}?v=1"></script>
|
|
187
|
+ <script>
|
|
188
|
+ V.initWxData({
|
|
189
|
+ imgUrl: "http://pai.ai/static/pai2/img/paiai_96_96.png",
|
|
190
|
+ link: 'http://api.pai.ai/wx_oauth2?redirect_url=http://pai.ai/page/lensman&scope=snsapi_base',
|
|
191
|
+ desc: "摄影师授权",
|
|
192
|
+ title: "摄影师授权",
|
|
193
|
+ timeLine: ""
|
|
194
|
+ }, true);
|
|
195
|
+ V.hideOptionMenu();
|
|
196
|
+ </script>
|
|
197
|
+ </body>
|
|
198
|
+</html>
|
|
|
@@ -0,0 +1,187 @@
|
|
1
|
+{% load staticfiles %}
|
|
2
|
+
|
|
3
|
+<!DOCTYPE html>
|
|
4
|
+<html lang="zh-CN">
|
|
5
|
+ <head>
|
|
6
|
+ <meta charset="utf-8">
|
|
7
|
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
|
8
|
+ <meta name="format-detection" content="telephone=no,email=no,address=no">
|
|
9
|
+ <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
|
|
10
|
+ <title>店员销售</title>
|
|
11
|
+
|
|
12
|
+ <link href="https://res.wx.qq.com/open/libs/weui/0.4.3/weui.min.css" rel="stylesheet" type="text/css" />
|
|
13
|
+
|
|
14
|
+ <style>
|
|
15
|
+ input:required:invalid {
|
|
16
|
+ color: #E64340;
|
|
17
|
+ }
|
|
18
|
+ input:required:valid {
|
|
19
|
+ color: rgb(0, 0, 0);
|
|
20
|
+ }
|
|
21
|
+ </style>
|
|
22
|
+ </head>
|
|
23
|
+ <body>
|
|
24
|
+ <div class="container" >
|
|
25
|
+ <div class="weui_cells_title">机器信息</div>
|
|
26
|
+ <div class="weui_cells weui_cells_form">
|
|
27
|
+ <div class="weui_cell weui_cell_select weui_select_after">
|
|
28
|
+ <div class="weui_cell_hd"><label for="" class="weui_label">型号</label></div>
|
|
29
|
+ <div class="weui_cell_bd weui_cell_primary">
|
|
30
|
+ <select id="model" class="weui_select" name="select">
|
|
31
|
+ {% for model in models %}
|
|
32
|
+ <option value="{{ model.model_id }}">{{ model.model_name }}</option>
|
|
33
|
+ {% endfor %}
|
|
34
|
+ </select>
|
|
35
|
+ </div>
|
|
36
|
+ </div>
|
|
37
|
+ <div class="weui_cell">
|
|
38
|
+ <div class="weui_cell_hd"><label for="" class="weui_label">机身码</label></div>
|
|
39
|
+ <div class="weui_cell_bd weui_cell_primary">
|
|
40
|
+ <input id="code" class="weui_input" type="text" value="" placeholder="请输入机身码">
|
|
41
|
+ </div>
|
|
42
|
+ </div>
|
|
43
|
+ </div>
|
|
44
|
+
|
|
45
|
+ <div class="weui_cells_title">消费者信息</div>
|
|
46
|
+ <div class="weui_cells weui_cells_form">
|
|
47
|
+ <div class="weui_cell">
|
|
48
|
+ <div class="weui_cell_hd"><label for="" class="weui_label">姓名</label></div>
|
|
49
|
+ <div class="weui_cell_bd weui_cell_primary">
|
|
50
|
+ <input id="name" class="weui_input" type="text" value="" placeholder="请输入消费者姓名">
|
|
51
|
+ </div>
|
|
52
|
+ </div>
|
|
53
|
+ <div class="weui_cell weui_cell_select weui_select_after">
|
|
54
|
+ <div class="weui_cell_hd"><label for="" class="weui_label">性别</label></div>
|
|
55
|
+ <div class="weui_cell_bd weui_cell_primary">
|
|
56
|
+ <select id="sex" class="weui_select" name="select">
|
|
57
|
+ <option value="1">男</option>
|
|
58
|
+ <option value="0">女</option>
|
|
59
|
+ </select>
|
|
60
|
+ </div>
|
|
61
|
+ </div>
|
|
62
|
+ <div class="weui_cell weui_cell_select weui_select_after">
|
|
63
|
+ <div class="weui_cell_hd"><label for="" class="weui_label">年龄</label></div>
|
|
64
|
+ <div class="weui_cell_bd weui_cell_primary">
|
|
65
|
+ <select id="age" class="weui_select" name="select">
|
|
66
|
+ <option value="1">18周岁以下</option>
|
|
67
|
+ <option value="2">60周岁以上</option>
|
|
68
|
+ </select>
|
|
69
|
+ </div>
|
|
70
|
+ </div>
|
|
71
|
+ <div class="weui_cell">
|
|
72
|
+ <div class="weui_cell_hd"><label for="" class="weui_label">手机号</label></div>
|
|
73
|
+ <div class="weui_cell_bd weui_cell_primary">
|
|
74
|
+ <input id="phone" class="weui_input" type="text" required="required" pattern="[0-9]{11}" value="" placeholder="请输入消费者手机号">
|
|
75
|
+ </div>
|
|
76
|
+ </div>
|
|
77
|
+ </div>
|
|
78
|
+
|
|
79
|
+ <br>
|
|
80
|
+
|
|
81
|
+ <button id="submit" class="weui_btn weui_btn_warn">确认</button>
|
|
82
|
+
|
|
83
|
+ <div class="weui_dialog_alert" id="dialog" style="display: none">
|
|
84
|
+ <div class="weui_mask"></div>
|
|
85
|
+ <div class="weui_dialog">
|
|
86
|
+ <div class="weui_dialog_hd"><strong id="title" class="weui_dialog_title">弹窗标题</strong></div>
|
|
87
|
+ <div id="content" class="weui_dialog_bd">弹窗内容,告知当前页面信息等</div>
|
|
88
|
+ <div class="weui_dialog_ft">
|
|
89
|
+ <a href="javascript:;" class="weui_btn_dialog primary">确定</a>
|
|
90
|
+ </div>
|
|
91
|
+ </div>
|
|
92
|
+ </div>
|
|
93
|
+
|
|
94
|
+ <div id="toast" style="display: none;">
|
|
95
|
+ <div class="weui_mask_transparent"></div>
|
|
96
|
+ <div class="weui_toast">
|
|
97
|
+ <i class="weui_icon_toast"></i>
|
|
98
|
+ <p class="weui_toast_content">已完成</p>
|
|
99
|
+ </div>
|
|
100
|
+ </div>
|
|
101
|
+ </div>
|
|
102
|
+
|
|
103
|
+ <script src="//cdn.bootcss.com/zepto/1.1.6/zepto.min.js"></script>
|
|
104
|
+ <script>
|
|
105
|
+ $(function() {
|
|
106
|
+ function show_error_dialog(title, content) {
|
|
107
|
+ $('#dialog #title').text(title);
|
|
108
|
+ $('#dialog #content').text(content);
|
|
109
|
+ $('#dialog').show();
|
|
110
|
+ }
|
|
111
|
+
|
|
112
|
+ function data_check() {
|
|
113
|
+ var clerk_id = "{{ clerk_info.clerk_id }}";
|
|
114
|
+ if (!clerk_id) {
|
|
115
|
+ show_error_dialog('微信授权', '微信授权失败,请重新打开页面');
|
|
116
|
+ return false;
|
|
117
|
+ }
|
|
118
|
+
|
|
119
|
+ var code = $('#code').val();
|
|
120
|
+ if (!code) {
|
|
121
|
+ show_error_dialog('机身码', '机身码错误,请检查重新输入');
|
|
122
|
+ return false;
|
|
123
|
+ }
|
|
124
|
+
|
|
125
|
+ var name = $('#name').val();
|
|
126
|
+ if (!name) {
|
|
127
|
+ show_error_dialog('姓名', '姓名错误,请检查重新输入');
|
|
128
|
+ return false;
|
|
129
|
+ }
|
|
130
|
+
|
|
131
|
+ var phone_valid = $('#phone').is(':valid');
|
|
132
|
+ if (!phone_valid) {
|
|
133
|
+ show_error_dialog('手机号', '手机号错误,请检查重新输入');
|
|
134
|
+ return false;
|
|
135
|
+ }
|
|
136
|
+
|
|
137
|
+ return {
|
|
138
|
+ clerk_id: clerk_id,
|
|
139
|
+ model_id: $('#model option:checked').val(),
|
|
140
|
+ code: code,
|
|
141
|
+ name: name,
|
|
142
|
+ sex: $('#sex option:checked').val(),
|
|
143
|
+ age: $('#age option:checked').val(),
|
|
144
|
+ phone: $('#phone').val(),
|
|
145
|
+ }
|
|
146
|
+ }
|
|
147
|
+
|
|
148
|
+ $('#submit').click(function () {
|
|
149
|
+ var check_result = data_check();
|
|
150
|
+ if (check_result){
|
|
151
|
+ $.ajax({
|
|
152
|
+ type: 'POST',
|
|
153
|
+ url: '{{ domain }}api/clerk/sale/submit',
|
|
154
|
+ data: check_result,
|
|
155
|
+ success: function(data) {
|
|
156
|
+ if (data.status == 200) {
|
|
157
|
+ $('#toast').show();
|
|
158
|
+ setTimeout(function () {
|
|
159
|
+ $('#toast').hide();
|
|
160
|
+ }, 1000);
|
|
161
|
+ } else {
|
|
162
|
+ show_error_dialog('错误', data.description);
|
|
163
|
+ }
|
|
164
|
+ }
|
|
165
|
+ })
|
|
166
|
+ }
|
|
167
|
+ });
|
|
168
|
+
|
|
169
|
+ $('#dialog .weui_btn_dialog').click(function () {
|
|
170
|
+ $('#dialog').hide();
|
|
171
|
+ })
|
|
172
|
+ });
|
|
173
|
+ </script>
|
|
174
|
+ <script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
|
|
175
|
+ <script type="text/javascript" src="{% static 'tamron/js/jswe.js' %}?v=1"></script>
|
|
176
|
+ <script>
|
|
177
|
+ V.initWxData({
|
|
178
|
+ imgUrl: "http://pai.ai/static/pai2/img/paiai_96_96.png",
|
|
179
|
+ link: 'http://api.pai.ai/wx_oauth2?redirect_url=http://pai.ai/page/lensman&scope=snsapi_base',
|
|
180
|
+ desc: "摄影师授权",
|
|
181
|
+ title: "摄影师授权",
|
|
182
|
+ timeLine: ""
|
|
183
|
+ }, true);
|
|
184
|
+ V.hideOptionMenu();
|
|
185
|
+ </script>
|
|
186
|
+ </body>
|
|
187
|
+</html>
|
|
|
@@ -0,0 +1,4 @@
|
|
1
|
+from django.test import TestCase
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+# Create your tests here.
|
|
|
@@ -0,0 +1,4 @@
|
|
1
|
+from django.shortcuts import render
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+# Create your views here.
|
|
|
@@ -0,0 +1,9 @@
|
|
1
|
+#!/bin/bash
|
|
2
|
+
|
|
3
|
+# Ignoring autogenerated files
|
|
4
|
+# -- Migration directories
|
|
5
|
+# Ignoring error codes
|
|
6
|
+# -- E128 continuation line under-indented for visual indent
|
|
7
|
+# -- E501 line too long
|
|
8
|
+
|
|
9
|
+pep8 --exclude=migrations --ignore=E128,E501 .
|
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+from django.contrib import admin
|
|
4
|
+
|
|
5
|
+from product.models import ProductCodeSubmitLogInfo, ProductInfo, ProductModelInfo
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+class ProductModelInfoAdmin(admin.ModelAdmin):
|
|
9
|
+ readonly_fields = ('model_id', )
|
|
10
|
+ list_display = ('model_id', 'model_name', 'integral', 'status', 'created_at', 'updated_at')
|
|
11
|
+ search_fields = ('model_id', 'model_name')
|
|
12
|
+ list_filter = ('status', )
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+class ProductInfoAdmin(admin.ModelAdmin):
|
|
16
|
+ list_display = ('model_id', 'model_name', 'code', 'code_status', 'integral', 'integral_status', 'franchiser_id', 'clerk_id', 'consumer_name', 'consumer_sex', 'consumer_age', 'consumer_phone', 'status', 'created_at', 'updated_at')
|
|
17
|
+ search_fields = ('model_id', 'model_name', 'code', 'consumer_name', 'consumer_phone')
|
|
18
|
+ list_filter = ('code_status', 'integral_status', 'franchiser_id', 'consumer_sex', 'status')
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+class ProductCodeSubmitLogInfoAdmin(admin.ModelAdmin):
|
|
22
|
+ list_display = ('model_id', 'model_name', 'code', 'franchiser_id', 'clerk_id', 'consumer_name', 'consumer_sex', 'consumer_age', 'consumer_phone', 'status', 'created_at', 'updated_at')
|
|
23
|
+ search_fields = ('model_id', 'model_name', 'code', 'consumer_name', 'consumer_phone')
|
|
24
|
+ list_filter = ('franchiser_id', 'consumer_sex', 'status')
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+admin.site.register(ProductModelInfo, ProductModelInfoAdmin)
|
|
28
|
+admin.site.register(ProductInfo, ProductInfoAdmin)
|
|
29
|
+admin.site.register(ProductCodeSubmitLogInfo, ProductCodeSubmitLogInfoAdmin)
|
|
|
@@ -0,0 +1,77 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+from __future__ import unicode_literals
|
|
3
|
+
|
|
4
|
+from django.db import models, migrations
|
|
5
|
+import shortuuidfield.fields
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+class Migration(migrations.Migration):
|
|
9
|
+
|
|
10
|
+ dependencies = [
|
|
11
|
+ ]
|
|
12
|
+
|
|
13
|
+ operations = [
|
|
14
|
+ migrations.CreateModel(
|
|
15
|
+ name='ProductCodeSubmitLogInfo',
|
|
16
|
+ fields=[
|
|
17
|
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
|
18
|
+ ('status', models.BooleanField(default=True, help_text='\u72b6\u6001', db_index=True, verbose_name='status')),
|
|
19
|
+ ('created_at', models.DateTimeField(help_text='\u521b\u5efa\u65f6\u95f4', verbose_name='created_at', auto_now_add=True)),
|
|
20
|
+ ('updated_at', models.DateTimeField(help_text='\u66f4\u65b0\u65f6\u95f4', verbose_name='updated_at', auto_now=True)),
|
|
21
|
+ ('model_id', models.CharField(max_length=255, blank=True, help_text='\u578b\u53f7\u552f\u4e00\u6807\u8bc6', null=True, verbose_name='model_id', db_index=True)),
|
|
22
|
+ ('model_name', models.CharField(max_length=255, blank=True, help_text='\u578b\u53f7\u540d\u79f0', null=True, verbose_name='model_name', db_index=True)),
|
|
23
|
+ ('code', models.CharField(help_text='\u673a\u8eab\u7801', max_length=255, null=True, verbose_name='code', blank=True)),
|
|
24
|
+ ('franchiser_id', models.CharField(max_length=255, blank=True, help_text='\u7ecf\u9500\u5546\u552f\u4e00\u6807\u8bc6', null=True, verbose_name='franchiser_id', db_index=True)),
|
|
25
|
+ ('clerk_id', models.CharField(max_length=255, blank=True, help_text='\u5e97\u5458\u552f\u4e00\u6807\u8bc6', null=True, verbose_name='clerk_id', db_index=True)),
|
|
26
|
+ ('consumer_name', models.CharField(help_text='\u6d88\u8d39\u8005\u540d\u79f0', max_length=255, null=True, verbose_name='consumer_name', blank=True)),
|
|
27
|
+ ('consumer_sex', models.IntegerField(default=1, help_text='\u6d88\u8d39\u8005\u6027\u522b', db_index=True, verbose_name='consumer_sex', choices=[(1, '\u7537'), (0, '\u5973')])),
|
|
28
|
+ ('consumer_age', models.IntegerField(default=0, help_text='\u6d88\u8d39\u8005\u5e74\u9f84', verbose_name='consumer_age')),
|
|
29
|
+ ('consumer_phone', models.CharField(help_text='\u6d88\u8d39\u8005\u8054\u7cfb\u7535\u8bdd', max_length=255, null=True, verbose_name='consumer_phone', blank=True)),
|
|
30
|
+ ],
|
|
31
|
+ options={
|
|
32
|
+ 'verbose_name': 'productcodesubmitloginfo',
|
|
33
|
+ 'verbose_name_plural': 'productcodesubmitloginfo',
|
|
34
|
+ },
|
|
35
|
+ ),
|
|
36
|
+ migrations.CreateModel(
|
|
37
|
+ name='ProductInfo',
|
|
38
|
+ fields=[
|
|
39
|
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
|
40
|
+ ('status', models.BooleanField(default=True, help_text='\u72b6\u6001', db_index=True, verbose_name='status')),
|
|
41
|
+ ('created_at', models.DateTimeField(help_text='\u521b\u5efa\u65f6\u95f4', verbose_name='created_at', auto_now_add=True)),
|
|
42
|
+ ('updated_at', models.DateTimeField(help_text='\u66f4\u65b0\u65f6\u95f4', verbose_name='updated_at', auto_now=True)),
|
|
43
|
+ ('model_id', models.CharField(max_length=255, blank=True, help_text='\u578b\u53f7\u552f\u4e00\u6807\u8bc6', null=True, verbose_name='model_id', db_index=True)),
|
|
44
|
+ ('model_name', models.CharField(max_length=255, blank=True, help_text='\u578b\u53f7\u540d\u79f0', null=True, verbose_name='model_name', db_index=True)),
|
|
45
|
+ ('code', models.CharField(help_text='\u673a\u8eab\u7801', max_length=255, null=True, verbose_name='code', blank=True)),
|
|
46
|
+ ('code_status', models.BooleanField(default=False, help_text='\u673a\u8eab\u7801\u72b6\u6001', db_index=True, verbose_name='code_status')),
|
|
47
|
+ ('integral', models.IntegerField(default=0, help_text='\u79ef\u5206', verbose_name='integral')),
|
|
48
|
+ ('integral_status', models.BooleanField(default=False, help_text='\u79ef\u5206\u72b6\u6001', db_index=True, verbose_name='integral_status')),
|
|
49
|
+ ('franchiser_id', models.CharField(max_length=255, blank=True, help_text='\u7ecf\u9500\u5546\u552f\u4e00\u6807\u8bc6', null=True, verbose_name='franchiser_id', db_index=True)),
|
|
50
|
+ ('clerk_id', models.CharField(max_length=255, blank=True, help_text='\u5e97\u5458\u552f\u4e00\u6807\u8bc6', null=True, verbose_name='clerk_id', db_index=True)),
|
|
51
|
+ ('consumer_name', models.CharField(help_text='\u6d88\u8d39\u8005\u540d\u79f0', max_length=255, null=True, verbose_name='consumer_name', blank=True)),
|
|
52
|
+ ('consumer_sex', models.IntegerField(default=1, help_text='\u6d88\u8d39\u8005\u6027\u522b', db_index=True, verbose_name='consumer_sex', choices=[(1, '\u7537'), (0, '\u5973')])),
|
|
53
|
+ ('consumer_age', models.IntegerField(default=0, help_text='\u6d88\u8d39\u8005\u5e74\u9f84', verbose_name='consumer_age')),
|
|
54
|
+ ('consumer_phone', models.CharField(help_text='\u6d88\u8d39\u8005\u8054\u7cfb\u7535\u8bdd', max_length=255, null=True, verbose_name='consumer_phone', blank=True)),
|
|
55
|
+ ],
|
|
56
|
+ options={
|
|
57
|
+ 'verbose_name': 'productinfo',
|
|
58
|
+ 'verbose_name_plural': 'productinfo',
|
|
59
|
+ },
|
|
60
|
+ ),
|
|
61
|
+ migrations.CreateModel(
|
|
62
|
+ name='ProductModelInfo',
|
|
63
|
+ fields=[
|
|
64
|
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
|
65
|
+ ('status', models.BooleanField(default=True, help_text='\u72b6\u6001', db_index=True, verbose_name='status')),
|
|
66
|
+ ('created_at', models.DateTimeField(help_text='\u521b\u5efa\u65f6\u95f4', verbose_name='created_at', auto_now_add=True)),
|
|
67
|
+ ('updated_at', models.DateTimeField(help_text='\u66f4\u65b0\u65f6\u95f4', verbose_name='updated_at', auto_now=True)),
|
|
68
|
+ ('model_id', shortuuidfield.fields.ShortUUIDField(editable=False, max_length=22, blank=True, help_text='\u578b\u53f7\u552f\u4e00\u6807\u8bc6', unique=True, db_index=True)),
|
|
69
|
+ ('model_name', models.CharField(help_text='\u578b\u53f7\u540d\u79f0', max_length=255, null=True, verbose_name='model_name', blank=True)),
|
|
70
|
+ ('integral', models.IntegerField(default=0, help_text='\u578b\u53f7\u79ef\u5206', verbose_name='integral')),
|
|
71
|
+ ],
|
|
72
|
+ options={
|
|
73
|
+ 'verbose_name': '\u4ea7\u54c1\u578b\u53f7\u4fe1\u606f',
|
|
74
|
+ 'verbose_name_plural': '\u4ea7\u54c1\u578b\u53f7\u4fe1\u606f',
|
|
75
|
+ },
|
|
76
|
+ ),
|
|
77
|
+ ]
|
|
|
@@ -0,0 +1,24 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+from __future__ import unicode_literals
|
|
3
|
+
|
|
4
|
+from django.db import models, migrations
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+ dependencies = [
|
|
10
|
+ ('product', '0001_initial'),
|
|
11
|
+ ]
|
|
12
|
+
|
|
13
|
+ operations = [
|
|
14
|
+ migrations.AlterField(
|
|
15
|
+ model_name='productinfo',
|
|
16
|
+ name='code_status',
|
|
17
|
+ field=models.BooleanField(default=False, help_text='\u673a\u8eab\u7801\u72b6\u6001, True\u5df2\u4f7f\u7528\uff0cFalse\u672a\u4f7f\u7528', db_index=True, verbose_name='code_status'),
|
|
18
|
+ ),
|
|
19
|
+ migrations.AlterField(
|
|
20
|
+ model_name='productinfo',
|
|
21
|
+ name='integral_status',
|
|
22
|
+ field=models.BooleanField(default=False, help_text='\u79ef\u5206\u72b6\u6001, True\u5df2\u79ef\u5206\uff0cFalse\u672a\u79ef\u5206', db_index=True, verbose_name='integral_status'),
|
|
23
|
+ ),
|
|
24
|
+ ]
|
|
|
@@ -0,0 +1,99 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+from django.db import models
|
|
4
|
+from django.utils.translation import ugettext_lazy as _
|
|
5
|
+from shortuuidfield import ShortUUIDField
|
|
6
|
+
|
|
7
|
+from tamron.basemodels import CreateUpdateMixin
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+class ProductModelInfo(CreateUpdateMixin):
|
|
11
|
+ model_id = ShortUUIDField(_(u'model_id'), max_length=255, help_text=u'型号唯一标识', db_index=True, unique=True)
|
|
12
|
+ model_name = models.CharField(_(u'model_name'), max_length=255, blank=True, null=True, help_text=u'型号名称')
|
|
13
|
+ integral = models.IntegerField(_(u'integral'), default=0, help_text=u'型号积分')
|
|
14
|
+
|
|
15
|
+ class Meta:
|
|
16
|
+ verbose_name = _(u'产品型号信息')
|
|
17
|
+ verbose_name_plural = _(u'产品型号信息')
|
|
18
|
+
|
|
19
|
+ def __unicode__(self):
|
|
20
|
+ return unicode(self.pk)
|
|
21
|
+
|
|
22
|
+ @property
|
|
23
|
+ def data(self):
|
|
24
|
+ return {
|
|
25
|
+ 'model_id': self.model_id,
|
|
26
|
+ 'model_name': self.model_name,
|
|
27
|
+ 'integral': self.integral,
|
|
28
|
+ }
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+class ProductInfo(CreateUpdateMixin):
|
|
32
|
+ MALE = 1
|
|
33
|
+ FEMALE = 0
|
|
34
|
+
|
|
35
|
+ SEX_TYPE = (
|
|
36
|
+ (MALE, u'男'),
|
|
37
|
+ (FEMALE, u'女'),
|
|
38
|
+ )
|
|
39
|
+
|
|
40
|
+ model_id = models.CharField(_(u'model_id'), max_length=255, blank=True, null=True, help_text=u'型号唯一标识', db_index=True)
|
|
41
|
+ model_name = models.CharField(_(u'model_name'), max_length=255, blank=True, null=True, help_text=u'型号名称', db_index=True)
|
|
42
|
+
|
|
43
|
+ code = models.CharField(_(u'code'), max_length=255, blank=True, null=True, help_text=u'机身码')
|
|
44
|
+ code_status = models.BooleanField(_(u'code_status'), default=False, help_text=u'机身码状态, True已使用,False未使用', db_index=True)
|
|
45
|
+
|
|
46
|
+ integral = models.IntegerField(_(u'integral'), default=0, help_text=u'积分')
|
|
47
|
+ integral_status = models.BooleanField(_(u'integral_status'), default=False, help_text=u'积分状态, True已积分,False未积分', db_index=True)
|
|
48
|
+
|
|
49
|
+ franchiser_id = models.CharField(_(u'franchiser_id'), max_length=255, blank=True, null=True, help_text=u'经销商唯一标识', db_index=True)
|
|
50
|
+ clerk_id = models.CharField(_(u'clerk_id'), max_length=255, blank=True, null=True, help_text=u'店员唯一标识', db_index=True)
|
|
51
|
+
|
|
52
|
+ consumer_name = models.CharField(_(u'consumer_name'), max_length=255, blank=True, null=True, help_text=u'消费者名称')
|
|
53
|
+ consumer_sex = models.IntegerField(_(u'consumer_sex'), choices=SEX_TYPE, default=MALE, help_text=u'消费者性别', db_index=True)
|
|
54
|
+ consumer_age = models.IntegerField(_(u'consumer_age'), default=0, help_text=u'消费者年龄')
|
|
55
|
+ consumer_phone = models.CharField(_(u'consumer_phone'), max_length=255, blank=True, null=True, help_text=u'消费者联系电话')
|
|
56
|
+
|
|
57
|
+ class Meta:
|
|
58
|
+ verbose_name = _(u'productinfo')
|
|
59
|
+ verbose_name_plural = _(u'productinfo')
|
|
60
|
+
|
|
61
|
+ def __unicode__(self):
|
|
62
|
+ return unicode(self.pk)
|
|
63
|
+
|
|
64
|
+ @property
|
|
65
|
+ def data(self):
|
|
66
|
+ return {
|
|
67
|
+ 'model_id': self.model_id,
|
|
68
|
+ 'model_name': self.model_name,
|
|
69
|
+ 'code': self.code,
|
|
70
|
+ }
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+class ProductCodeSubmitLogInfo(CreateUpdateMixin):
|
|
74
|
+ MALE = 1
|
|
75
|
+ FEMALE = 0
|
|
76
|
+
|
|
77
|
+ SEX_TYPE = (
|
|
78
|
+ (MALE, u'男'),
|
|
79
|
+ (FEMALE, u'女'),
|
|
80
|
+ )
|
|
81
|
+
|
|
82
|
+ model_id = models.CharField(_(u'model_id'), max_length=255, blank=True, null=True, help_text=u'型号唯一标识', db_index=True)
|
|
83
|
+ model_name = models.CharField(_(u'model_name'), max_length=255, blank=True, null=True, help_text=u'型号名称', db_index=True)
|
|
84
|
+ code = models.CharField(_(u'code'), max_length=255, blank=True, null=True, help_text=u'机身码')
|
|
85
|
+
|
|
86
|
+ franchiser_id = models.CharField(_(u'franchiser_id'), max_length=255, blank=True, null=True, help_text=u'经销商唯一标识', db_index=True)
|
|
87
|
+ clerk_id = models.CharField(_(u'clerk_id'), max_length=255, blank=True, null=True, help_text=u'店员唯一标识', db_index=True)
|
|
88
|
+
|
|
89
|
+ consumer_name = models.CharField(_(u'consumer_name'), max_length=255, blank=True, null=True, help_text=u'消费者名称')
|
|
90
|
+ consumer_sex = models.IntegerField(_(u'consumer_sex'), choices=SEX_TYPE, default=MALE, help_text=u'消费者性别', db_index=True)
|
|
91
|
+ consumer_age = models.IntegerField(_(u'consumer_age'), default=0, help_text=u'消费者年龄')
|
|
92
|
+ consumer_phone = models.CharField(_(u'consumer_phone'), max_length=255, blank=True, null=True, help_text=u'消费者联系电话')
|
|
93
|
+
|
|
94
|
+ class Meta:
|
|
95
|
+ verbose_name = _(u'productcodesubmitloginfo')
|
|
96
|
+ verbose_name_plural = _(u'productcodesubmitloginfo')
|
|
97
|
+
|
|
98
|
+ def __unicode__(self):
|
|
99
|
+ return unicode(self.pk)
|
|
|
@@ -0,0 +1,4 @@
|
|
1
|
+from django.test import TestCase
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+# Create your tests here.
|
|
|
@@ -0,0 +1,4 @@
|
|
1
|
+from django.shortcuts import render
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+# Create your views here.
|
|
|
@@ -0,0 +1,39 @@
|
|
1
|
+-e git+https://github.com/Brightcells/django-q.git#egg=django-q
|
|
2
|
+-e git+https://github.com/andymccurdy/redis-py.git#egg=redis-py
|
|
3
|
+CodeConvert==2.0.4
|
|
4
|
+Django==1.8.4
|
|
5
|
+MySQL-python==1.2.5
|
|
6
|
+Pillow==3.4.2
|
|
7
|
+StatusCode==1.0.0
|
|
8
|
+TimeConvert==1.4.1
|
|
9
|
+cryptography==1.5.2
|
|
10
|
+django-curtail-uuid==1.0.0
|
|
11
|
+django-detect==1.0.5
|
|
12
|
+django-file-md5==1.0.1
|
|
13
|
+django-ip==1.0.0
|
|
14
|
+django-json-response==1.1.4
|
|
15
|
+django-logit==1.0.6
|
|
16
|
+django-multidomain==1.1.4
|
|
17
|
+django-paginator2==1.0.3
|
|
18
|
+django-rlog==1.0.7
|
|
19
|
+django-shortuuidfield==0.1.3
|
|
20
|
+django-six==1.0.2
|
|
21
|
+djangorestframework==3.6.3
|
|
22
|
+furl==1.0.0
|
|
23
|
+hiredis==0.2.0
|
|
24
|
+isoweek==1.3.3
|
|
25
|
+jsonfield==2.0.2
|
|
26
|
+mock==2.0.0
|
|
27
|
+pep8==1.7.0
|
|
28
|
+pysnippets==1.0.4
|
|
29
|
+pywe-miniapp==1.0.0
|
|
30
|
+pywe-oauth==1.0.3
|
|
31
|
+pywe-response==1.0.1
|
|
32
|
+qiniu==7.1.4
|
|
33
|
+redis-extensions==1.0.50
|
|
34
|
+requests==2.12.4
|
|
35
|
+rlog==0.2
|
|
36
|
+shortuuid==0.5.0
|
|
37
|
+uWSGI==2.0.15
|
|
38
|
+versions==0.10.0
|
|
39
|
+wechatpy==1.2.8
|
|
|
@@ -0,0 +1,13 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+from django.db import models
|
|
4
|
+from django.utils.translation import ugettext_lazy as _
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+class CreateUpdateMixin(models.Model):
|
|
8
|
+ status = models.BooleanField(_(u'status'), default=True, help_text=_(u'状态'), db_index=True)
|
|
9
|
+ created_at = models.DateTimeField(_(u'created_at'), auto_now_add=True, editable=True, help_text=_(u'创建时间'))
|
|
10
|
+ updated_at = models.DateTimeField(_(u'updated_at'), auto_now=True, editable=True, help_text=_(u'更新时间'))
|
|
11
|
+
|
|
12
|
+ class Meta:
|
|
13
|
+ abstract = True
|
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+import redis_extensions as redis
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+def redis_conf(conf):
|
|
7
|
+ return {
|
|
8
|
+ 'host': conf.get('HOST', 'localhost'),
|
|
9
|
+ 'port': conf.get('PORT', 6379),
|
|
10
|
+ 'password': '{}:{}'.format(conf.get('USER', ''), conf.get('PASSWORD', '')) if conf.get('USER') else '',
|
|
11
|
+ 'db': conf.get('db', 0),
|
|
12
|
+ }
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+def redis_connect(conf):
|
|
16
|
+ return redis.StrictRedisExtensions(connection_pool=redis.ConnectionPool(**redis_conf(conf)))
|
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+import os
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
7
|
+PROJ_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__)))
|
|
8
|
+
|
|
9
|
+TEMPLATES = [
|
|
10
|
+ {
|
|
11
|
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
|
12
|
+ 'DIRS': [os.path.join(BASE_DIR, 'templates')],
|
|
13
|
+ # 'APP_DIRS': True,
|
|
14
|
+ 'OPTIONS': {
|
|
15
|
+ 'context_processors': [
|
|
16
|
+ 'django.template.context_processors.debug',
|
|
17
|
+ 'django.template.context_processors.request',
|
|
18
|
+ 'django.contrib.auth.context_processors.auth',
|
|
19
|
+ 'django.contrib.messages.context_processors.messages',
|
|
20
|
+ ],
|
|
21
|
+ 'loaders': [
|
|
22
|
+ 'django.template.loaders.filesystem.Loader',
|
|
23
|
+ 'django.template.loaders.app_directories.Loader',
|
|
24
|
+ ],
|
|
25
|
+ },
|
|
26
|
+ },
|
|
27
|
+]
|
|
28
|
+
|
|
29
|
+DOMAIN = 'http://127.0.0.1:9997/'
|
|
|
@@ -0,0 +1,254 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+"""
|
|
4
|
+Django settings for tamron project.
|
|
5
|
+
|
|
6
|
+Generated by 'django-admin startproject' using Django 1.8.4.
|
|
7
|
+
|
|
8
|
+For more information on this file, see
|
|
9
|
+https://docs.djangoproject.com/en/1.8/topics/settings/
|
|
10
|
+
|
|
11
|
+For the full list of settings and their values, see
|
|
12
|
+https://docs.djangoproject.com/en/1.8/ref/settings/
|
|
13
|
+"""
|
|
14
|
+
|
|
15
|
+# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
|
16
|
+import os
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
20
|
+PROJ_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__)))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+# Quick-start development settings - unsuitable for production
|
|
24
|
+# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
|
|
25
|
+
|
|
26
|
+# SECURITY WARNING: keep the secret key used in production secret!
|
|
27
|
+SECRET_KEY = '@!_8xi9(8)gj8zvni#)2-arn)4gn^u&coy-0yld0=1r5*ao@4i'
|
|
28
|
+
|
|
29
|
+# SECURITY WARNING: don't run with debug turned on in production!
|
|
30
|
+DEBUG = True
|
|
31
|
+
|
|
32
|
+ALLOWED_HOSTS = []
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+# Application definition
|
|
36
|
+
|
|
37
|
+INSTALLED_APPS = (
|
|
38
|
+ 'django.contrib.admin',
|
|
39
|
+ 'django.contrib.auth',
|
|
40
|
+ 'django.contrib.contenttypes',
|
|
41
|
+ 'django.contrib.sessions',
|
|
42
|
+ 'django.contrib.messages',
|
|
43
|
+ 'django.contrib.staticfiles',
|
|
44
|
+ 'api',
|
|
45
|
+ 'account',
|
|
46
|
+ 'integral',
|
|
47
|
+ 'page',
|
|
48
|
+ 'product',
|
|
49
|
+)
|
|
50
|
+
|
|
51
|
+MIDDLEWARE_CLASSES = (
|
|
52
|
+ 'django.contrib.sessions.middleware.SessionMiddleware',
|
|
53
|
+ 'django.middleware.common.CommonMiddleware',
|
|
54
|
+ # 'django.middleware.csrf.CsrfViewMiddleware',
|
|
55
|
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
|
|
56
|
+ 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
|
|
57
|
+ 'django.contrib.messages.middleware.MessageMiddleware',
|
|
58
|
+ 'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
|
59
|
+ 'django.middleware.security.SecurityMiddleware',
|
|
60
|
+)
|
|
61
|
+
|
|
62
|
+ROOT_URLCONF = 'tamron.urls'
|
|
63
|
+
|
|
64
|
+TEMPLATES = [
|
|
65
|
+ {
|
|
66
|
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
|
67
|
+ 'DIRS': [os.path.join(BASE_DIR, 'templates')],
|
|
68
|
+ # 'APP_DIRS': True,
|
|
69
|
+ 'OPTIONS': {
|
|
70
|
+ 'context_processors': [
|
|
71
|
+ 'django.template.context_processors.debug',
|
|
72
|
+ 'django.template.context_processors.request',
|
|
73
|
+ 'django.contrib.auth.context_processors.auth',
|
|
74
|
+ 'django.contrib.messages.context_processors.messages',
|
|
75
|
+ ],
|
|
76
|
+ 'loaders': [
|
|
77
|
+ ('django.template.loaders.cached.Loader', [
|
|
78
|
+ 'django.template.loaders.filesystem.Loader',
|
|
79
|
+ 'django.template.loaders.app_directories.Loader',
|
|
80
|
+ ]),
|
|
81
|
+ ],
|
|
82
|
+ },
|
|
83
|
+ },
|
|
84
|
+]
|
|
85
|
+
|
|
86
|
+WSGI_APPLICATION = 'tamron.wsgi.application'
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+# Database
|
|
90
|
+# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
|
|
91
|
+
|
|
92
|
+DATABASES = {
|
|
93
|
+ 'default': {
|
|
94
|
+ 'ENGINE': 'django.db.backends.mysql',
|
|
95
|
+ 'NAME': 'tamron',
|
|
96
|
+ 'USER': 'root',
|
|
97
|
+ 'PASSWORD': '',
|
|
98
|
+ 'CONN_MAX_AGE': 600,
|
|
99
|
+ 'OPTIONS': {
|
|
100
|
+ # Utf8mb4 for Emoji
|
|
101
|
+ #
|
|
102
|
+ # Nickname
|
|
103
|
+ #
|
|
104
|
+ # account.WechatInfo ==> nickname
|
|
105
|
+ # ALTER TABLE account_wechatinfo MODIFY COLUMN nickname VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
|
|
106
|
+ # account.UserInfo ==> nickname
|
|
107
|
+ # ALTER TABLE account_userinfo MODIFY COLUMN nickname VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
|
|
108
|
+ # group.GroupUserInfo ==> nickname
|
|
109
|
+ # ALTER TABLE group_groupuserinfo MODIFY COLUMN nickname VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL;
|
|
110
|
+ # group.GroupPhotoInfo ==> nickname
|
|
111
|
+ # ALTER TABLE group_groupphotoinfo MODIFY COLUMN nickname VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL;
|
|
112
|
+ # group.PhotoCommentInfo ==> nickname
|
|
113
|
+ # ALTER TABLE group_photocommentinfo MODIFY COLUMN nickname VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL;
|
|
114
|
+ # group.PhotoThumbUpInfo ==> nickname
|
|
115
|
+ # ALTER TABLE group_photothumbupinfo MODIFY COLUMN nickname VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL;
|
|
116
|
+ # group.UserMessageInfo ==> nickname
|
|
117
|
+ # ALTER TABLE message_usermessageinfo MODIFY COLUMN from_nickname VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL;
|
|
118
|
+ #
|
|
119
|
+ # Comment
|
|
120
|
+ # group.PhotoCommentInfo ==> comment
|
|
121
|
+ # ALTER TABLE group_photocommentinfo MODIFY COLUMN comment LONGTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
|
|
122
|
+ 'charset': 'utf8mb4',
|
|
123
|
+ },
|
|
124
|
+ }
|
|
125
|
+}
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+# Internationalization
|
|
129
|
+# https://docs.djangoproject.com/en/1.8/topics/i18n/
|
|
130
|
+
|
|
131
|
+LANGUAGE_CODE = 'zh-Hans'
|
|
132
|
+
|
|
133
|
+TIME_ZONE = 'Asia/Shanghai'
|
|
134
|
+
|
|
135
|
+USE_I18N = True
|
|
136
|
+
|
|
137
|
+USE_L10N = True
|
|
138
|
+
|
|
139
|
+USE_TZ = True
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+# Static files (CSS, JavaScript, Images)
|
|
143
|
+# https://docs.djangoproject.com/en/1.8/howto/static-files/
|
|
144
|
+
|
|
145
|
+STATICFILES_DIRS = (
|
|
146
|
+ os.path.join(PROJ_DIR, 'static').replace('\\', '/'),
|
|
147
|
+)
|
|
148
|
+
|
|
149
|
+STATIC_ROOT = os.path.join(BASE_DIR, 'collect_static').replace('\\', '/')
|
|
150
|
+
|
|
151
|
+STATIC_URL = '/static/'
|
|
152
|
+
|
|
153
|
+STATICFILES_FINDERS = (
|
|
154
|
+ 'django.contrib.staticfiles.finders.FileSystemFinder',
|
|
155
|
+ 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
|
156
|
+ # 'django.contrib.staticfiles.finders.DefaultStorageFinder',
|
|
157
|
+)
|
|
158
|
+
|
|
159
|
+MEDIA_ROOT = os.path.join(BASE_DIR, 'media').replace('\\', '/')
|
|
160
|
+
|
|
161
|
+MEDIA_URL = '/media/'
|
|
162
|
+
|
|
163
|
+# Redis 设置
|
|
164
|
+REDIS = {
|
|
165
|
+ 'default': {
|
|
166
|
+ 'HOST': '127.0.0.1',
|
|
167
|
+ 'PORT': 6379,
|
|
168
|
+ 'USER': '',
|
|
169
|
+ 'PASSWORD': '',
|
|
170
|
+ 'db': 0,
|
|
171
|
+ }
|
|
172
|
+}
|
|
173
|
+
|
|
174
|
+# 微信设置
|
|
175
|
+WECHAT = {
|
|
176
|
+ 'JSAPI': {
|
|
177
|
+ 'token': '5201314',
|
|
178
|
+ 'appID': '',
|
|
179
|
+ 'appsecret': '',
|
|
180
|
+ 'mchID': '',
|
|
181
|
+ 'apiKey': '',
|
|
182
|
+ 'mch_cert': '',
|
|
183
|
+ 'mch_key': '',
|
|
184
|
+ 'redpacket': {
|
|
185
|
+
|
|
186
|
+ }
|
|
187
|
+ },
|
|
188
|
+}
|
|
189
|
+
|
|
190
|
+# 微信授权设置
|
|
191
|
+WECHAT_BASE_REDIRECT_URI = 'https://api.pai.ai/base_redirect'
|
|
192
|
+WECHAT_USERINFO_REDIRECT_URI = 'https://api.pai.ai/userinfo_redirect'
|
|
193
|
+WECHAT_OAUTH2_RETRY_REDIRECT_URI = 'https://api.pai.ai/wx_oauth2?redirect_url={}'
|
|
194
|
+
|
|
195
|
+WECHAT_OAUTH2_REDIRECT_URL = 'https://api.pai.ai/wx_oauth2?redirect_url={}'
|
|
196
|
+
|
|
197
|
+# LOGIT 设置
|
|
198
|
+LOGIT_BODY_FLAG = True
|
|
199
|
+LOGIT_RES_FLAG = True
|
|
200
|
+
|
|
201
|
+DOMAIN = ''
|
|
202
|
+
|
|
203
|
+try:
|
|
204
|
+ from local_settings import *
|
|
205
|
+except ImportError:
|
|
206
|
+ pass
|
|
207
|
+
|
|
208
|
+try:
|
|
209
|
+ from func_settings import redis_connect
|
|
210
|
+ REDIS_CACHE = redis_connect(REDIS.get('default', {}))
|
|
211
|
+
|
|
212
|
+ DJLOGIT = {
|
|
213
|
+ 'level': 'DEBUG',
|
|
214
|
+ 'class': 'rlog.RedisListHandler',
|
|
215
|
+ 'redis_client': REDIS_CACHE,
|
|
216
|
+ 'key': 'django:logit:tamron',
|
|
217
|
+ 'formatter': 'verbose',
|
|
218
|
+ }
|
|
219
|
+except ImportError:
|
|
220
|
+ REDIS_CACHE = None
|
|
221
|
+
|
|
222
|
+# 日志设置
|
|
223
|
+LOGGING = {
|
|
224
|
+ 'version': 1,
|
|
225
|
+ 'disable_existing_loggers': False,
|
|
226
|
+ 'formatters': {
|
|
227
|
+ 'verbose': {
|
|
228
|
+ 'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
|
|
229
|
+ },
|
|
230
|
+ 'simple': {
|
|
231
|
+ 'format': '%(levelname)s %(message)s'
|
|
232
|
+ },
|
|
233
|
+ },
|
|
234
|
+ 'handlers': {
|
|
235
|
+ 'logit': DJLOGIT,
|
|
236
|
+ 'console': {
|
|
237
|
+ 'level': 'DEBUG',
|
|
238
|
+ 'class': 'logging.StreamHandler',
|
|
239
|
+ 'formatter': 'verbose'
|
|
240
|
+ },
|
|
241
|
+ },
|
|
242
|
+ 'loggers': {
|
|
243
|
+ 'logit': {
|
|
244
|
+ 'handlers': ['logit'],
|
|
245
|
+ 'level': 'DEBUG',
|
|
246
|
+ 'propagate': True,
|
|
247
|
+ },
|
|
248
|
+ 'console': {
|
|
249
|
+ 'handlers': ['console'],
|
|
250
|
+ 'level': 'DEBUG',
|
|
251
|
+ 'propagate': True,
|
|
252
|
+ },
|
|
253
|
+ },
|
|
254
|
+}
|
|
|
@@ -0,0 +1,300 @@
|
|
1
|
+!(function(e, t) {
|
|
2
|
+ var config = {
|
|
3
|
+ wxconfig: 'http://api.pai.ai/wx/jsapi_signature',
|
|
4
|
+ callback: 'callback'
|
|
5
|
+ }, wxData = {
|
|
6
|
+ debug: false,
|
|
7
|
+ imgUrl: '',
|
|
8
|
+ link: '',
|
|
9
|
+ desc: '',
|
|
10
|
+ title: '',
|
|
11
|
+ timeLine: ''
|
|
12
|
+ }, wxConfig = {
|
|
13
|
+ hide: false,
|
|
14
|
+ close: false
|
|
15
|
+ }, jsApiList = [
|
|
16
|
+ 'checkJsApi',
|
|
17
|
+ 'onMenuShareTimeline',
|
|
18
|
+ 'onMenuShareAppMessage',
|
|
19
|
+ 'onMenuShareQQ',
|
|
20
|
+ 'onMenuShareWeibo',
|
|
21
|
+ 'hideMenuItems',
|
|
22
|
+ 'showMenuItems',
|
|
23
|
+ 'hideAllNonBaseMenuItem',
|
|
24
|
+ 'showAllNonBaseMenuItem',
|
|
25
|
+ 'translateVoice',
|
|
26
|
+ 'startRecord',
|
|
27
|
+ 'stopRecord',
|
|
28
|
+ 'onRecordEnd',
|
|
29
|
+ 'playVoice',
|
|
30
|
+ 'pauseVoice',
|
|
31
|
+ 'stopVoice',
|
|
32
|
+ 'uploadVoice',
|
|
33
|
+ 'downloadVoice',
|
|
34
|
+ 'chooseImage',
|
|
35
|
+ 'previewImage',
|
|
36
|
+ 'uploadImage',
|
|
37
|
+ 'downloadImage',
|
|
38
|
+ 'getNetworkType',
|
|
39
|
+ 'openLocation',
|
|
40
|
+ 'getLocation',
|
|
41
|
+ 'hideOptionMenu',
|
|
42
|
+ 'showOptionMenu',
|
|
43
|
+ 'closeWindow',
|
|
44
|
+ 'scanQRCode',
|
|
45
|
+ 'chooseWXPay',
|
|
46
|
+ 'openEnterpriseRedPacket',
|
|
47
|
+ 'openProductSpecificView',
|
|
48
|
+ 'addCard',
|
|
49
|
+ 'chooseCard',
|
|
50
|
+ 'openCard'
|
|
51
|
+ ], wxApiFun
|
|
52
|
+
|
|
53
|
+ function isOpenOnPC() { // 判断当前网页是否在 PC 浏览器中打开
|
|
54
|
+ var ua = navigator.userAgent
|
|
55
|
+ return /windows nt/i.test(ua) || /macintosh/i.test(ua) || /linux x86_64/i.test(ua)
|
|
56
|
+ }
|
|
57
|
+
|
|
58
|
+ function isOpenInWeixin() { // 判断当前网页是否在微信内置浏览器中打开
|
|
59
|
+ return /micromessenger/i.test(navigator.userAgent)
|
|
60
|
+ }
|
|
61
|
+
|
|
62
|
+ function getWeixinVersion() {
|
|
63
|
+ var ua = navigator.userAgent,
|
|
64
|
+ mt = ua.match(/micromessenger\/([\d.]+)/i)
|
|
65
|
+ return (mt ? mt[1] : '')
|
|
66
|
+ }
|
|
67
|
+
|
|
68
|
+ // This function checks whether Wechat is the appointed version or not
|
|
69
|
+ // Cmp: http://jsperf.com/regexp-test-vs-indexof-ignore-upper-and-lower
|
|
70
|
+ function isWeixinVersion(version) {
|
|
71
|
+ // return new RegExp('micromessenger/' + version , 'i').test(navigator.userAgent)
|
|
72
|
+ return navigator.userAgent.toLowerCase().indexOf('micromessenger/' + version) != -1
|
|
73
|
+ }
|
|
74
|
+
|
|
75
|
+ function hideOptionMenu() {
|
|
76
|
+ wxConfig.hide = true
|
|
77
|
+ fixedWxData()
|
|
78
|
+ }
|
|
79
|
+
|
|
80
|
+ function showOptionMenu() {
|
|
81
|
+ wxConfig.hide = false
|
|
82
|
+ fixedWxData()
|
|
83
|
+ }
|
|
84
|
+
|
|
85
|
+ function closeWindow() {
|
|
86
|
+ wxConfig.close = true
|
|
87
|
+ fixedWxData()
|
|
88
|
+ }
|
|
89
|
+
|
|
90
|
+ function wxReady(data) {
|
|
91
|
+ data = typeof data === 'object' ? data : JSON.parse(data)
|
|
92
|
+ wx.config({
|
|
93
|
+ debug: wxData.debug,
|
|
94
|
+ appId: data.appId,
|
|
95
|
+ timestamp: data.timestamp,
|
|
96
|
+ nonceStr: data.nonceStr,
|
|
97
|
+ signature: data.signature,
|
|
98
|
+ jsApiList: jsApiList
|
|
99
|
+ })
|
|
100
|
+
|
|
101
|
+ var callbacks = {
|
|
102
|
+ trigger: function (res) {
|
|
103
|
+ // alert('用户点击发送给朋友')
|
|
104
|
+ if (JSWE.wxTrigger) {JSWE.wxTrigger(res)}
|
|
105
|
+ },
|
|
106
|
+ success: function (res) {
|
|
107
|
+ // alert('已分享')
|
|
108
|
+ if (JSWE.wxSuccess) {JSWE.wxSuccess(res)}
|
|
109
|
+ },
|
|
110
|
+ cancel: function (res) {
|
|
111
|
+ // alert('已取消')
|
|
112
|
+ if (JSWE.wxCancel) {JSWE.wxCancel(res)}
|
|
113
|
+ },
|
|
114
|
+ fail: function (res) {
|
|
115
|
+ // alert(JSON.stringify(res))
|
|
116
|
+ if (JSWE.wxFail) {JSWE.wxFail(res)}
|
|
117
|
+ }
|
|
118
|
+ }, shareInfo = function(flag) {
|
|
119
|
+ var _share = {
|
|
120
|
+ title: flag ? wxData.title : (wxData.timeLine || wxData.desc),
|
|
121
|
+ link: wxData.link,
|
|
122
|
+ imgUrl: wxData.imgUrl,
|
|
123
|
+ trigger: callbacks.trigger,
|
|
124
|
+ success: callbacks.success,
|
|
125
|
+ cancel: callbacks.cancel,
|
|
126
|
+ fail: callbacks.fail
|
|
127
|
+ }
|
|
128
|
+ if (flag) _share.desc = wxData.desc
|
|
129
|
+ return _share
|
|
130
|
+ }, wxShareApi = function() {
|
|
131
|
+ // 2. 分享接口
|
|
132
|
+ // 2.1 监听“分享给朋友”,按钮点击、自定义分享内容及分享结果接口
|
|
133
|
+ wx.onMenuShareAppMessage(shareInfo(1))
|
|
134
|
+ // 2.2 监听“分享到朋友圈”按钮点击、自定义分享内容及分享结果接口
|
|
135
|
+ wx.onMenuShareTimeline(shareInfo(0))
|
|
136
|
+ // 2.3 监听“分享到QQ”按钮点击、自定义分享内容及分享结果接口
|
|
137
|
+ wx.onMenuShareQQ(shareInfo(1))
|
|
138
|
+ // 2.4 监听“分享到微博”按钮点击、自定义分享内容及分享结果接口
|
|
139
|
+ wx.onMenuShareWeibo(shareInfo(1))
|
|
140
|
+ }, wxMenuApi = function () {
|
|
141
|
+ // 8. 界面操作接口
|
|
142
|
+ // 8.1 隐藏右上角菜单
|
|
143
|
+ // 8.2 显示右上角菜单
|
|
144
|
+ if (wxConfig.hide) {wx.hideOptionMenu()} else {wx.showOptionMenu()}
|
|
145
|
+ // 8.7 关闭当前窗口
|
|
146
|
+ if (wxConfig.close) {wx.closeWindow()}
|
|
147
|
+ }, wxApi = function () {
|
|
148
|
+ wxShareApi()
|
|
149
|
+ wxMenuApi()
|
|
150
|
+ }
|
|
151
|
+
|
|
152
|
+ wx.ready(wxApi)
|
|
153
|
+
|
|
154
|
+ return wxApiFun = wxApi
|
|
155
|
+ }
|
|
156
|
+
|
|
157
|
+ if (isOpenInWeixin() || isOpenOnPC()) {
|
|
158
|
+ if ('undefined' !== typeof JSWE_CONF_UPDATE) JSWE_CONF_UPDATE(config)
|
|
159
|
+ $.ajax({
|
|
160
|
+ url: config.wxconfig,
|
|
161
|
+ type: 'get',
|
|
162
|
+ dataType: 'jsonp',
|
|
163
|
+ jsonpCallback: config.callback,
|
|
164
|
+ data: {
|
|
165
|
+ url: window.location.href.split('#')[0]
|
|
166
|
+ },
|
|
167
|
+ success: wxReady
|
|
168
|
+ })
|
|
169
|
+ }
|
|
170
|
+
|
|
171
|
+ function initWxData(data, flag) {
|
|
172
|
+ for(var d in data) {if (d in wxData) wxData[d] = data[d]}
|
|
173
|
+ if (flag) fixedWxData()
|
|
174
|
+ }
|
|
175
|
+
|
|
176
|
+ function changeWxData(key, value, flag) {
|
|
177
|
+ if (key in falDwxDataata) {wxData[key] = value}
|
|
178
|
+ if (flag) fixedWxData()
|
|
179
|
+ }
|
|
180
|
+
|
|
181
|
+ function fixedWxData() {
|
|
182
|
+ if ('undefined' !== typeof wxApiFun) wxApiFun()
|
|
183
|
+ }
|
|
184
|
+
|
|
185
|
+ // 5 图片接口
|
|
186
|
+ // 5.1 拍照、本地选图
|
|
187
|
+ var images = {
|
|
188
|
+ localIds: [],
|
|
189
|
+ serverIds: []
|
|
190
|
+ };
|
|
191
|
+ function chooseImage(count, directUpload, isShowProgressTips) {
|
|
192
|
+ if ('undefined' === typeof count) {count = 9}
|
|
193
|
+ if ('undefined' === typeof directUpload) {directUpload = false}
|
|
194
|
+ if ('undefined' === typeof isShowProgressTips) {isShowProgressTips = 1}
|
|
195
|
+ wx.chooseImage({
|
|
196
|
+ count: count, // 默认9
|
|
197
|
+ sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
|
|
198
|
+ sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
|
|
199
|
+ success: function (res) {
|
|
200
|
+ var localIds = res.localIds; // 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片
|
|
201
|
+ images.localIds = localIds;
|
|
202
|
+ // 判断是否直接上传
|
|
203
|
+ if (directUpload) {setTimeout(uploadImages(localIds, isShowProgressTips), 100)}
|
|
204
|
+ // 拍照、本地选图成功后的回调函数
|
|
205
|
+ if (JSWE.wxChooseImageSuccess) {JSWE.wxChooseImageSuccess(res)}
|
|
206
|
+ }
|
|
207
|
+ });
|
|
208
|
+ }
|
|
209
|
+
|
|
210
|
+ // 5.3 上传图片
|
|
211
|
+ function uploadImage(localId, isShowProgressTips) {
|
|
212
|
+ // 上传图片为异步处理,重复上传同一图片,返回的serverId也是不同的
|
|
213
|
+ wx.uploadImage({
|
|
214
|
+ localId: localId, // 需要上传的图片的本地ID,由chooseImage接口获得
|
|
215
|
+ isShowProgressTips: 1, // 默认为1,显示进度提示
|
|
216
|
+ success: function (res) {
|
|
217
|
+ var serverId = res.serverId; // 返回图片的服务器端ID
|
|
218
|
+ images.serverIds.push(serverId);
|
|
219
|
+ // 上传图片成功后的回调函数
|
|
220
|
+ if (JSWE.wxUploadImageSuccess) {JSWE.wxUploadImageSuccess(res)}
|
|
221
|
+ }
|
|
222
|
+ });
|
|
223
|
+ }
|
|
224
|
+
|
|
225
|
+ function uploadImages(localIds, isShowProgressTips) {
|
|
226
|
+ if ('undefined' === typeof localIds) {localIds = images.localIds}
|
|
227
|
+ if ('undefined' === typeof isShowProgressTips) {isShowProgressTips = 1}
|
|
228
|
+ images.serverIds = [];
|
|
229
|
+ for (var index in localIds) {uploadImage(localIds[index], isShowProgressTips)}
|
|
230
|
+ }
|
|
231
|
+
|
|
232
|
+ // 10 微信支付接口
|
|
233
|
+ // 10.1 发起一个支付请求
|
|
234
|
+ function chooseWXPay(wxpay_params) {
|
|
235
|
+ wx.chooseWXPay({
|
|
236
|
+ timestamp: wxpay_params.timeStamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
|
|
237
|
+ nonceStr: wxpay_params.nonceStr, // 支付签名随机串,不长于 32 位
|
|
238
|
+ package: wxpay_params.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***)
|
|
239
|
+ signType: wxpay_params.signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
|
|
240
|
+ paySign: wxpay_params.paySign, // 支付签名
|
|
241
|
+ success: function (res) {
|
|
242
|
+ // 支付成功后的回调函数
|
|
243
|
+ if (JSWE.wxPaySuccess) {JSWE.wxPaySuccess(res)}
|
|
244
|
+ }
|
|
245
|
+ })
|
|
246
|
+ }
|
|
247
|
+
|
|
248
|
+ // xx 微信原生企业红包接口
|
|
249
|
+ // xx.1 发起一个发送原生企业红包请求
|
|
250
|
+ function openEnterpriseRedPacket(wxredpack_params) {
|
|
251
|
+ wx.openEnterpriseRedPacket({
|
|
252
|
+ timeStamp: wxredpack_params.timeStamp, // 红包签名时间戳,注意原生企业红包接口timeStamp字段名需大写其中的S字符,而支付接口timeStamp字段名无需大写其中的S字符。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
|
|
253
|
+ nonceStr: wxredpack_params.nonceStr, // 红包签名随机串,不长于 32 位
|
|
254
|
+ package: encodeURIComponent(wxredpack_params.package), // 发放红包接口返回的prepay_id参数值,提交格式如:prepay_id=***)
|
|
255
|
+ signType: wxredpack_params.signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
|
|
256
|
+ paySign: wxredpack_params.paySign, // 红包签名
|
|
257
|
+ success: function (res) {
|
|
258
|
+ // 发送原生企业红包成功后的回调函数
|
|
259
|
+ if (JSWE.wxEnterpriseRedPacketSuccess) {JSWE.wxEnterpriseRedPacketSuccess(res)}
|
|
260
|
+ }
|
|
261
|
+ })
|
|
262
|
+ }
|
|
263
|
+
|
|
264
|
+ var v = {
|
|
265
|
+ version: '1.0.5',
|
|
266
|
+
|
|
267
|
+ // Basic Vars
|
|
268
|
+ config: config,
|
|
269
|
+ wxData: wxData,
|
|
270
|
+ jsApiList: jsApiList,
|
|
271
|
+
|
|
272
|
+ // Weixin Function
|
|
273
|
+ isOpenInWeixin: isOpenInWeixin,
|
|
274
|
+ getWeixinVersion: getWeixinVersion,
|
|
275
|
+ isWeixinVersion: isWeixinVersion,
|
|
276
|
+
|
|
277
|
+ // Menu Function
|
|
278
|
+ hideOptionMenu: hideOptionMenu,
|
|
279
|
+ showOptionMenu: showOptionMenu,
|
|
280
|
+ closeWindow: closeWindow,
|
|
281
|
+
|
|
282
|
+ // Share Function
|
|
283
|
+ initWxData: initWxData,
|
|
284
|
+ changeWxData: changeWxData,
|
|
285
|
+ fixedWxData: fixedWxData,
|
|
286
|
+
|
|
287
|
+ // Image Function
|
|
288
|
+ images: images,
|
|
289
|
+ chooseImage: chooseImage,
|
|
290
|
+ uploadImage: uploadImage,
|
|
291
|
+ uploadImages: uploadImages,
|
|
292
|
+
|
|
293
|
+ // Pay Function
|
|
294
|
+ chooseWXPay: chooseWXPay,
|
|
295
|
+
|
|
296
|
+ // EnterpriseRedPacket Function
|
|
297
|
+ openEnterpriseRedPacket: openEnterpriseRedPacket
|
|
298
|
+ }
|
|
299
|
+ e.JSWE = e.V = v
|
|
300
|
+})(window)
|
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+"""tamron URL Configuration
|
|
4
|
+
|
|
5
|
+The `urlpatterns` list routes URLs to views. For more information please see:
|
|
6
|
+ https://docs.djangoproject.com/en/1.8/topics/http/urls/
|
|
7
|
+Examples:
|
|
8
|
+Function views
|
|
9
|
+ 1. Add an import: from my_app import views
|
|
10
|
+ 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
|
|
11
|
+Class-based views
|
|
12
|
+ 1. Add an import: from other_app.views import Home
|
|
13
|
+ 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
|
|
14
|
+Including another URLconf
|
|
15
|
+ 1. Add an import: from blog import urls as blog_urls
|
|
16
|
+ 2. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls))
|
|
17
|
+"""
|
|
18
|
+from django.conf.urls import include, url
|
|
19
|
+from django.contrib import admin
|
|
20
|
+
|
|
21
|
+from page import info_views, oauth_views, sale_views
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+urlpatterns = [
|
|
25
|
+ url(r'^admin/', include(admin.site.urls)),
|
|
26
|
+ url(r'^api/', include('api.urls', namespace='api')),
|
|
27
|
+]
|
|
28
|
+
|
|
29
|
+urlpatterns += [
|
|
30
|
+ url(r'^page/clerk$', oauth_views.clerk_oauth, name='clerk_oauth'), # 店员授权页面
|
|
31
|
+ url(r'^page/clerk/sale$', sale_views.clerk_sale_oauth, name='clerk_sale_oauth'), # 店员销售授权页面
|
|
32
|
+ url(r'^page/clerk/info$', info_views.clerk_info_oauth, name='clerk_info_oauth'), # 店员信息授权页面
|
|
33
|
+]
|
|
|
@@ -0,0 +1,2 @@
|
|
1
|
+killall -9 uwsgi
|
|
2
|
+echo "2敏加油~~~!!!↖(^ω^)↗"
|
|
|
@@ -0,0 +1,2 @@
|
|
1
|
+nohup uwsgi --ini pai2.ini &>pai2.log &
|
|
2
|
+echo "Start Success !!!"
|
|
|
@@ -0,0 +1,27 @@
|
|
1
|
+# tamron_uwsgi.ini file
|
|
2
|
+[uwsgi]
|
|
3
|
+
|
|
4
|
+# Django-related settings
|
|
5
|
+# the base directory (full path)
|
|
6
|
+chdir = /home/paiai/work/tamron
|
|
7
|
+# Django's wsgi file
|
|
8
|
+module = tamron.wsgi
|
|
9
|
+# the virtualenv (full path)
|
|
10
|
+# home = /path/to/virtualenv
|
|
11
|
+
|
|
12
|
+# process-related settings
|
|
13
|
+# master
|
|
14
|
+master = true
|
|
15
|
+# maximum number of worker processes
|
|
16
|
+processes = 10
|
|
17
|
+# the socket (use the full path to be safe
|
|
18
|
+socket = /home/paiai/work/tamron/tamron/uwsgi/tamron.sock
|
|
19
|
+# ... with appropriate permissions - may be needed
|
|
20
|
+chmod-socket = 777
|
|
21
|
+# clear environment on exit
|
|
22
|
+vacuum = true
|
|
23
|
+
|
|
24
|
+# 11: Resource temporarily unavailable
|
|
25
|
+reload-mercy = 64
|
|
26
|
+max-requests = 8192
|
|
27
|
+listen = 4096
|
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+# tamron_nginx.conf
|
|
2
|
+
|
|
3
|
+# the upstream component nginx needs to connect to
|
|
4
|
+upstream pai2 {
|
|
5
|
+ # server unix:///home/paiai/work/tamron/tamron/uwsgi/tamron.sock; # for a file socket
|
|
6
|
+ server 127.0.0.1:8888; # for a web port socket (we'll use this first)
|
|
7
|
+}
|
|
8
|
+
|
|
9
|
+# configuration of the server
|
|
10
|
+server {
|
|
11
|
+ # the port your site will be served on
|
|
12
|
+ listen 80;
|
|
13
|
+ # the domain name it will serve for
|
|
14
|
+ server_name .tamron.xfoto.com.cn; # substitute your machine's IP address or FQDN
|
|
15
|
+ charset utf-8;
|
|
16
|
+
|
|
17
|
+ # max upload size
|
|
18
|
+ client_max_body_size 75M; # adjust to taste
|
|
19
|
+
|
|
20
|
+ # Django media
|
|
21
|
+ location /media {
|
|
22
|
+ alias /home/paiai/work/tamron/media; # your Django project's media files - amend as required
|
|
23
|
+ }
|
|
24
|
+
|
|
25
|
+ location /static {
|
|
26
|
+ alias /home/paiai/work/tamron/collect_static; # your Django project's static files - amend as required
|
|
27
|
+ }
|
|
28
|
+
|
|
29
|
+ # Finally, send all non-media requests to the Django server.
|
|
30
|
+ location / {
|
|
31
|
+ # uwsgi_pass tamron;
|
|
32
|
+ proxy_pass http://tamron;
|
|
33
|
+ include /home/paiai/work/tamron/tamron/uwsgi/uwsgi_params; # the uwsgi_params file you installed
|
|
34
|
+ }
|
|
35
|
+}
|
|
|
@@ -0,0 +1,15 @@
|
|
1
|
+uwsgi_param QUERY_STRING $query_string;
|
|
2
|
+uwsgi_param REQUEST_METHOD $request_method;
|
|
3
|
+uwsgi_param CONTENT_TYPE $content_type;
|
|
4
|
+uwsgi_param CONTENT_LENGTH $content_length;
|
|
5
|
+
|
|
6
|
+uwsgi_param REQUEST_URI $request_uri;
|
|
7
|
+uwsgi_param PATH_INFO $document_uri;
|
|
8
|
+uwsgi_param DOCUMENT_ROOT $document_root;
|
|
9
|
+uwsgi_param SERVER_PROTOCOL $server_protocol;
|
|
10
|
+uwsgi_param UWSGI_SCHEME $scheme;
|
|
11
|
+
|
|
12
|
+uwsgi_param REMOTE_ADDR $remote_addr;
|
|
13
|
+uwsgi_param REMOTE_PORT $remote_port;
|
|
14
|
+uwsgi_param SERVER_PORT $server_port;
|
|
15
|
+uwsgi_param SERVER_NAME $server_name;
|
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+"""
|
|
2
|
+WSGI config for tamron project.
|
|
3
|
+
|
|
4
|
+It exposes the WSGI callable as a module-level variable named ``application``.
|
|
5
|
+
|
|
6
|
+For more information on this file, see
|
|
7
|
+https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/
|
|
8
|
+"""
|
|
9
|
+
|
|
10
|
+import os
|
|
11
|
+
|
|
12
|
+from django.core.wsgi import get_wsgi_application
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tamron.settings")
|
|
16
|
+
|
|
17
|
+application = get_wsgi_application()
|
|
|
@@ -0,0 +1,62 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+from StatusCode import BaseStatusCode, StatusCodeField
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+class FranchiserStatusCode(BaseStatusCode):
|
|
7
|
+ """ 店员相关错误码 4001xx """
|
|
8
|
+ CHISER_NOT_FOUND = StatusCodeField(400001, 'Chiser Not Found', description=u'经销商不存在')
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+class SaleclerkStatusCode(BaseStatusCode):
|
|
12
|
+ """ 店员相关错误码 4001xx """
|
|
13
|
+ CLERK_NOT_FOUND = StatusCodeField(400101, 'Clerk Not Found', description=u'店员不存在')
|
|
14
|
+ # 手机号
|
|
15
|
+ CLERK_PHONE_ALREADY_EXISTS = StatusCodeField(400105, 'Clerk Phone Already Exists', description=u'手机号已经存在')
|
|
16
|
+ # 状态
|
|
17
|
+ CLERK_ALREADY_NOT_UNVERIFIED = StatusCodeField(400110, 'Clerk Already Not Unverified', description=u'店员帐号已激活')
|
|
18
|
+ CLERK_NOT_ACTIVATED = StatusCodeField(400115, 'Clerk Not Activated', description=u'店员帐号未激活')
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+class ProductModelStatusCode(BaseStatusCode):
|
|
22
|
+ """ 型号相关错误码 4010xx """
|
|
23
|
+ MODEL_NOT_FOUND = StatusCodeField(401001, 'Model Not Found', description=u'型号不存在')
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+class ProductStatusCode(BaseStatusCode):
|
|
27
|
+ """ 产品相关错误码 4020xx """
|
|
28
|
+ PRODUCT_NOT_FOUND = StatusCodeField(402001, 'Product Not Found', description=u'产品不存在')
|
|
29
|
+ # 状态
|
|
30
|
+ PRODUCT_HAS_USED = StatusCodeField(402011, 'Product Has Used', description=u'产品已使用')
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+class OrderStatusCode(BaseStatusCode):
|
|
34
|
+ """ 订单/支付相关错误码 4040xx """
|
|
35
|
+ WX_UNIFIED_ORDER_FAIL = StatusCodeField(404000, 'WX Unified Order Fail', description=u'微信统一下单失败')
|
|
36
|
+ WX_ORDER_NOT_FOUND = StatusCodeField(404001, 'WX Order Not Found', description=u'订单不存在')
|
|
37
|
+ WX_ORDER_NOT_PAY = StatusCodeField(404002, 'WX Order Not Pay', description=u'订单未支付')
|
|
38
|
+ WX_ORDER_PAYING = StatusCodeField(404003, 'WX Order Paying', description=u'订单支付中')
|
|
39
|
+ WX_ORDER_PAY_FAIL = StatusCodeField(404009, 'WX Order Pay Fail', description=u'微信支付失败')
|
|
40
|
+ SIGN_CHECK_FAIL = StatusCodeField(404010, 'Sign Check Fail', description=u'签名校验失败')
|
|
41
|
+ FEE_CHECK_FAIL = StatusCodeField(404011, 'FEE Check Fail', description=u'金额校验失败')
|
|
42
|
+ NO_DETAIL_PERMISSION = StatusCodeField(404015, 'No Detail Permission', description=u'无详情权限')
|
|
43
|
+ WX_ORDER_PAID_ALREADY_EXISTS = StatusCodeField(404020, 'WX Order Paid Already Exists', description=u'照片已购买')
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+class PayStatusCode(BaseStatusCode):
|
|
47
|
+ """ 支付相关错误码 4041xx """
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+class WithdrawStatusCode(BaseStatusCode):
|
|
51
|
+ """ 提现相关错误码 4042xx """
|
|
52
|
+ BALANCE_NOT_ENOUGH = StatusCodeField(404200, 'Balance Not Enough', description=u'提现金额不足')
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+class MessageStatusCode(BaseStatusCode):
|
|
56
|
+ """ 消息相关错误码 4090xx """
|
|
57
|
+ MESSAGE_NOT_FOUND = StatusCodeField(409001, 'Message Not Found', description=u'消息不存在')
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+class TokenStatusCode(BaseStatusCode):
|
|
61
|
+ """ 票据相关错误码 4090xx """
|
|
62
|
+ TOKEN_NOT_FOUND = StatusCodeField(409901, 'Token Not Found', description=u'票据不存在')
|
|
|
@@ -0,0 +1,18 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+from django.http import JsonResponse
|
|
4
|
+from StatusCode import StatusCodeField
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+def response_data(status_code=200, message=None, description=None, data={}, **kwargs):
|
|
8
|
+ return dict({
|
|
9
|
+ 'status': status_code,
|
|
10
|
+ 'message': message,
|
|
11
|
+ 'description': description,
|
|
12
|
+ 'data': data,
|
|
13
|
+ }, **kwargs)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+def response(status_code=200, message=None, description=None, data={}, **kwargs):
|
|
17
|
+ message, description = (message or status_code.message, description or status_code.description) if isinstance(status_code, StatusCodeField) else (message, description)
|
|
18
|
+ return JsonResponse(response_data(status_code, message, description, data, **kwargs), safe=False)
|
|
|
@@ -0,0 +1,6 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+from django.conf import settings
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+r = settings.REDIS_CACHE
|
|
|
@@ -0,0 +1,68 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+# 唯一标识相关
|
|
4
|
+UUID_LIST = 'uuid:list' # List,唯一标识列表
|
|
5
|
+
|
|
6
|
+# 用户相关
|
|
7
|
+PROFILE_INFO = 'profile:info:%s' # STRING,用户信息,user_id
|
|
8
|
+
|
|
9
|
+# 导游相关
|
|
10
|
+TOUR_GUIDE_GROUP_GEO_INFO = 'tour:guide:group:geo:info:%s' # ZSET,旅游团地理位置信息,group_id
|
|
11
|
+TOUR_GUIDE_GROUP_GEO_SUBMIT_DT = 'tour:guide:group:geo:submit:dt:%s' # ZSET,旅游团地理位置最后上传时间,group_id
|
|
12
|
+TOUR_GUIDE_GROUP_CUR_SESSION = 'tour:guide:group:cur:session:%s' # STRING,旅游团当前Session,group_id,导游设置集合时间的时候更新
|
|
13
|
+TOUR_GUIDE_GROUP_CUR_GATHER_INFO = 'tour:guide:group:cur:gather:info:%s' # STRING,旅游团当前Session,group_id,导游设置集合时间的时候更新
|
|
14
|
+TOUR_GUIDE_GROUP_USER_GEO_LIST = 'tour:guide:group:user:geo:list:%s:%s:%s' # LIST,旅游团当前用户地理位置列表,group_id、session_id、user_id
|
|
15
|
+
|
|
16
|
+TOUR_GUIDE_GROUP_USER_OWN = 'tour:guide:group:user:own:%s' # STRING,导游当前拥有的旅行团,user_id,导游创建旅行团的时候更新
|
|
17
|
+TOUR_GUIDE_GROUP_USER_BELONG = 'tour:guide:group:user:belong:%s' # STRING,用户当前所属旅行团,user_id,用户加入旅行团的时候更新
|
|
18
|
+
|
|
19
|
+# 群组相关
|
|
20
|
+GROUP_INFO = 'group:info:%s' # STRING,群组信息,group_id
|
|
21
|
+
|
|
22
|
+# 群组用户相关
|
|
23
|
+GROUP_USERS_INFO = 'group:users:info:%s' # STRING,群组用户信息,group_id
|
|
24
|
+GROUP_USERS_KV_INFO = 'group:users:kv:info:%s' # STRING,群组用户信息,group_id
|
|
25
|
+GROUP_USERS_APPLYING_SET = 'group:users:applying:set:%s' # SET,群组用户申请集合,group_id
|
|
26
|
+GROUP_USERS_PASSED_SET = 'group:users:passed:set:%s' # SET,群组用户通过集合,group_id
|
|
27
|
+GROUP_USERS_REFUSED_SET = 'group:users:refused:set:%s' # SET,群组用户拒绝集合,group_id
|
|
28
|
+GROUP_USERS_DELETED_SET = 'group:users:deleted:set:%s' # SET,群组用户移除集合,group_id
|
|
29
|
+GROUP_USERS_QUIT_SET = 'group:users:quit:set:%s' # SET,群组用户退出集合,group_id
|
|
30
|
+
|
|
31
|
+# 群组照片相关
|
|
32
|
+GROUP_PHOTO_DATA = 'group:photo:data:%s' # STRING,群组数据记录,group_id
|
|
33
|
+GROUP_PHOTO_THUMB_UP = 'group:photo:thumb:up:%s:%s' # STRING,群组照片用户点赞记录,photo_id、user_id
|
|
34
|
+GROUP_PHOTO_COMMENT_LIST = 'group:photo:comment:list:%s' # STRING,群组照片用户评论列表,photo_id
|
|
35
|
+GROUP_PHOTO_THUMB_UP_LIST = 'group:photo:thumb:up:list:%s' # STRING,群组照片用户点赞列表,photo_id
|
|
36
|
+GROUP_PHOTO_WATCHER_SET = 'group:photo:watcher:set:%s' # SET,群组照片用户关注集合,photo_id,关注即评论点赞
|
|
37
|
+GROUP_LAST_PHOTO_PK = 'group:last:photo:pk:%s' # STRING,群组最后一张照片PK,group_id
|
|
38
|
+
|
|
39
|
+# 摄影师照片相关
|
|
40
|
+LENSMAN_PHOTO_ORDER_RECORD = 'lensman:photo:order:record:%s:%s' # STRING,摄影师照片购买记录,photo_id、user_id
|
|
41
|
+
|
|
42
|
+# 摄影师简报相关
|
|
43
|
+# 收入
|
|
44
|
+TOTAL_INCOME = 'total:income:%s:%s' # STRING,总收入,user_id、photo_type
|
|
45
|
+WEEK_INCOME = 'week:income:%s:%s:%s' # STRING,周收入,user_id、photo_type、Week.thisweek().isoformat()
|
|
46
|
+TODAY_INCOME = 'today:income:%s:%s:%s' # STRING,日收入,user_id、photo_type、tc.local_string(format='%Y%m%d')
|
|
47
|
+# 上传
|
|
48
|
+TODAY_UPLOAD_PHOTO_AMOUNT = 'today:upload:photo:amount:%s:%s' # STRING,日上传照片数量,user_id、tc.local_string(format='%Y%m%d')
|
|
49
|
+# 售出
|
|
50
|
+WEEK_SOLD = 'week:sold:%s:%s:%s' # STRING,周售出,user_id、photo_type、Week.thisweek().isoformat()
|
|
51
|
+
|
|
52
|
+# 摄影师定价相关
|
|
53
|
+LENSMAN_PHOTO_PRICE_FIXED = 'lensman:photo:price:fixed:%s' # STRING,摄影师照片定价(单位:分),user_id
|
|
54
|
+
|
|
55
|
+# 系统消息相关
|
|
56
|
+SYSTEM_MESSAGE_READ_INFO = 'system:message:read:info:%s' # STRING,系统消息读取信息,user_id
|
|
57
|
+SYSTEM_MESSAGE_DELETED_INFO = 'system:message:deleted:info:%s' # STRING,系统消息删除信息,user_id
|
|
58
|
+
|
|
59
|
+# 游客入口相关
|
|
60
|
+GUEST_ENTRANCE_CONTROL_INFO = 'guest:entrance:control:info:%s' # STRING,游客入口控制信息,src
|
|
61
|
+
|
|
62
|
+# APP 相关
|
|
63
|
+LATEST_APP_INFO = 'latest:app:info:%s' # STRING,最新 APP 信息,src
|
|
64
|
+APP_SETTINGS_INFO = 'app:settings:info:%s:%s:%s' # STRING,APP 设置信息,platform、channel、version
|
|
65
|
+APP_PATCH_INFO = 'app:patch:info:%s:%s:%s' # STRING,APP 补丁信息,platform、version、src
|
|
66
|
+
|
|
67
|
+# BOX 相关
|
|
68
|
+BOX_PROGRAM_VERSION_INFO = 'box:program:version:info' # STRING,BOX 程序版本信息
|