Changeset 12090 for main/waeup.ikoba/trunk/src/waeup/ikoba/customers
- Timestamp:
- 29 Nov 2014, 07:57:51 (10 years ago)
- Location:
- main/waeup.ikoba/trunk/src/waeup/ikoba/customers
- Files:
-
- 4 added
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
main/waeup.ikoba/trunk/src/waeup/ikoba/customers/applications.py
r12089 r12090 129 129 def translated_class_name(self): 130 130 try: 131 DOCTYPES_DICT = getUtility(ICustomersUtils).DOCTYPES_DICT132 return DOCTYPES_DICT[self.class_name]131 APPTYPES_DICT = getUtility(ICustomersUtils).APPTYPES_DICT 132 return APPTYPES_DICT[self.class_name] 133 133 except KeyError: 134 134 return … … 157 157 return implementedBy(SampleApplication) 158 158 159 @grok.subscribe(IApplication, grok.IObjectAddedEvent) 160 def handle_document_added(application, event): 161 """If an application is added the transition create is fired. 162 The latter produces a logging message. 163 """ 164 if IWorkflowState(application).getState() is None: 165 IWorkflowInfo(application).fireTransition('create') 166 return -
main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser.py
r12089 r12090 51 51 ICustomer, ICustomersContainer, ICustomerRequestPW, ICustomersUtils, 52 52 ICustomerDocument, ICustomerDocumentsContainer, ICustomerCreate, 53 ICustomerPDFDocument 53 ICustomerPDFDocument, IApplicationsContainer, IApplication 54 54 ) 55 55 from waeup.ikoba.customers.catalog import search … … 1024 1024 self.context.customer, customerview, 1025 1025 omit_fields=self.omit_fields) 1026 1027 # Pages for customer applications 1028 1029 class ApplicationsBreadcrumb(Breadcrumb): 1030 """A breadcrumb for the applications container. 1031 """ 1032 grok.context(IApplicationsContainer) 1033 title = _('Applications') 1034 1035 1036 class ApplicationBreadcrumb(Breadcrumb): 1037 """A breadcrumb for the customer container. 1038 """ 1039 grok.context(IApplication) 1040 1041 @property 1042 def title(self): 1043 return self.context.application_id 1044 1045 1046 class ApplicationsManageFormPage(IkobaEditFormPage): 1047 """ Page to manage the customer applications 1048 1049 This manage form page is for both customers and customers officers. 1050 """ 1051 grok.context(IApplicationsContainer) 1052 grok.name('index') 1053 grok.require('waeup.viewCustomer') 1054 form_fields = grok.AutoFields(IApplicationsContainer) 1055 grok.template('applicationsmanagepage') 1056 pnav = 4 1057 1058 @property 1059 def manage_applications_allowed(self): 1060 return checkPermission('waeup.editApplications', self.context) 1061 1062 def unremovable(self, application): 1063 usertype = getattr(self.request.principal, 'user_type', None) 1064 if not usertype: 1065 return False 1066 if not self.manage_applications_allowed: 1067 return True 1068 return (self.request.principal.user_type == 'customer' and \ 1069 application.state in (APPROVED, REJECTED, EXPIRED)) 1070 1071 @property 1072 def label(self): 1073 return _('${a}: Applications', 1074 mapping = {'a':self.context.__parent__.display_fullname}) 1075 1076 @jsaction(_('Remove selected applications')) 1077 def delApplication(self, **data): 1078 form = self.request.form 1079 if 'val_id' in form: 1080 child_id = form['val_id'] 1081 else: 1082 self.flash(_('No application selected.'), type="warning") 1083 self.redirect(self.url(self.context)) 1084 return 1085 if not isinstance(child_id, list): 1086 child_id = [child_id] 1087 deleted = [] 1088 for id in child_id: 1089 # Customers are not allowed to remove used applications 1090 application = self.context.get(id, None) 1091 if application is not None and not self.unremovable(application): 1092 del self.context[id] 1093 deleted.append(id) 1094 if len(deleted): 1095 self.flash(_('Successfully removed: ${a}', 1096 mapping = {'a': ', '.join(deleted)})) 1097 self.context.writeLogMessage( 1098 self,'removed: %s' % ', '.join(deleted)) 1099 self.redirect(self.url(self.context)) 1100 return 1101 1102 1103 class ApplicationAddFormPage(IkobaAddFormPage): 1104 """ Page to add an application 1105 """ 1106 grok.context(IApplicationsContainer) 1107 grok.name('addapp') 1108 grok.template('applicationaddform') 1109 grok.require('waeup.editApplications') 1110 form_fields = grok.AutoFields(IApplication) 1111 label = _('Add application') 1112 pnav = 4 1113 1114 @property 1115 def selectable_apptypes(self): 1116 apptypes = getUtility(ICustomersUtils).SELECTABLE_APPTYPES_DICT 1117 return sorted(apptypes.items()) 1118 1119 @action(_('Create application'), style='primary') 1120 def createApplication(self, **data): 1121 form = self.request.form 1122 customer = self.context.__parent__ 1123 apptype = form.get('apptype', None) 1124 # Here we can create various instances of Application derived 1125 # classes depending on the apptype parameter given in form. 1126 application = createObject('waeup.%s' % apptype) 1127 self.context.addApplication(application) 1128 apptype = getUtility(ICustomersUtils).SELECTABLE_APPTYPES_DICT[apptype] 1129 self.flash(_('${a} created.', 1130 mapping = {'a': apptype})) 1131 self.context.writeLogMessage( 1132 self,'added: %s %s' % (apptype, application.application_id)) 1133 self.redirect(self.url(self.context)) 1134 return 1135 1136 @action(_('Cancel'), validator=NullValidator) 1137 def cancel(self, **data): 1138 self.redirect(self.url(self.context)) 1139 1140 1141 class ApplicationDisplayFormPage(IkobaDisplayFormPage): 1142 """ Page to view a application 1143 """ 1144 grok.context(IApplication) 1145 grok.name('index') 1146 grok.require('waeup.viewCustomer') 1147 grok.template('applicationpage') 1148 form_fields = grok.AutoFields(IApplication).omit('last_transition_date') 1149 pnav = 4 1150 1151 #@property 1152 #def label(self): 1153 # return _('${a}: Application ${b}', mapping = { 1154 # 'a':self.context.customer.display_fullname, 1155 # 'b':self.context.application_id}) 1156 1157 @property 1158 def label(self): 1159 return _('${a}', mapping = {'a':self.context.title}) 1160 1161 1162 class ApplicationManageFormPage(IkobaEditFormPage): 1163 """ Page to edit a application 1164 """ 1165 grok.context(IApplication) 1166 grok.name('manage') 1167 grok.require('waeup.manageCustomer') 1168 grok.template('applicationeditpage') 1169 form_fields = grok.AutoFields(IApplication).omit('last_transition_date') 1170 pnav = 4 1171 deletion_warning = _('Are you sure?') 1172 1173 #@property 1174 #def label(self): 1175 # return _('${a}: Application ${b}', mapping = { 1176 # 'a':self.context.customer.display_fullname, 1177 # 'b':self.context.application_id}) 1178 1179 @property 1180 def label(self): 1181 return _('${a}', mapping = {'a':self.context.title}) 1182 1183 @action(_('Save'), style='primary') 1184 def save(self, **data): 1185 msave(self, **data) 1186 return 1187 1188 1189 class ApplicationEditFormPage(ApplicationManageFormPage): 1190 """ Page to edit a application 1191 """ 1192 grok.name('edit') 1193 grok.require('waeup.handleCustomer') 1194 1195 def update(self): 1196 if not self.context.is_editable: 1197 emit_lock_message(self) 1198 return 1199 return super(ApplicationEditFormPage, self).update() 1200 1201 @action(_('Save'), style='primary') 1202 def save(self, **data): 1203 msave(self, **data) 1204 return 1205 1206 @action(_('Final Submit'), warning=WARNING) 1207 def finalsubmit(self, **data): 1208 msave(self, **data) 1209 IWorkflowInfo(self.context).fireTransition('submit') 1210 self.flash(_('Form has been submitted.')) 1211 self.redirect(self.url(self.context)) 1212 return 1213 1214 1215 class ApplicationTriggerTransitionFormPage(IkobaEditFormPage): 1216 """ View to trigger customer application transitions 1217 """ 1218 grok.context(IApplication) 1219 grok.name('trigtrans') 1220 grok.require('waeup.triggerTransition') 1221 grok.template('trigtrans') 1222 label = _('Trigger application transition') 1223 pnav = 4 1224 1225 def update(self): 1226 return super(IkobaEditFormPage, self).update() 1227 1228 def getTransitions(self): 1229 """Return a list of dicts of allowed transition ids and titles. 1230 1231 Each list entry provides keys ``name`` and ``title`` for 1232 internal name and (human readable) title of a single 1233 transition. 1234 """ 1235 wf_info = IWorkflowInfo(self.context) 1236 allowed_transitions = [t for t in wf_info.getManualTransitions()] 1237 return [dict(name='', title=_('No transition'))] +[ 1238 dict(name=x, title=y) for x, y in allowed_transitions] 1239 1240 @action(_('Save'), style='primary') 1241 def save(self, **data): 1242 form = self.request.form 1243 if 'transition' in form and form['transition']: 1244 transition_id = form['transition'] 1245 wf_info = IWorkflowInfo(self.context) 1246 wf_info.fireTransition(transition_id) 1247 return 1248 1249 class PDFApplicationsOverviewPage(UtilityView, grok.View): 1250 """Deliver an overview slip. 1251 """ 1252 grok.context(IApplicationsContainer) 1253 grok.name('overview_slip.pdf') 1254 grok.require('waeup.viewCustomer') 1255 prefix = 'form' 1256 1257 omit_fields = ('suspended', 'sex', 1258 'suspended_comment',) 1259 1260 form_fields = None 1261 1262 @property 1263 def label(self): 1264 portal_language = getUtility(IIkobaUtils).PORTAL_LANGUAGE 1265 return translate(_('Applications of'), 1266 'waeup.ikoba', target_language=portal_language) \ 1267 + ' %s' % self.context.customer.display_fullname 1268 1269 @property 1270 def tabletitle(self): 1271 portal_language = getUtility(IIkobaUtils).PORTAL_LANGUAGE 1272 tabletitle = [] 1273 tabletitle.append(translate(_('Customer Applications'), 'waeup.ikoba', 1274 target_language=portal_language)) 1275 return tabletitle 1276 1277 def render(self): 1278 portal_language = getUtility(IIkobaUtils).PORTAL_LANGUAGE 1279 Id = translate(_('Id'), 'waeup.ikoba', target_language=portal_language) 1280 Title = translate(_('Title'), 'waeup.ikoba', target_language=portal_language) 1281 Type = translate(_('Type'), 'waeup.ikoba', target_language=portal_language) 1282 State = translate(_('State'), 'waeup.ikoba', target_language=portal_language) 1283 LT = translate(_('Last Transition'), 'waeup.ikoba', target_language=portal_language) 1284 tableheader = [] 1285 tabledata = [] 1286 contenttitle = [] 1287 for i in range(1,3): 1288 tabledata.append(sorted( 1289 [value for value in self.context.values()])) 1290 tableheader.append([(Id, 'application_id', 2), 1291 (Title, 'title', 6), 1292 (Type, 'translated_class_name', 6), 1293 (State, 'translated_state', 2), 1294 (LT, 'formatted_transition_date', 3), 1295 ]) 1296 customerview = CustomerBasePDFFormPage(self.context.customer, 1297 self.request, self.omit_fields) 1298 customers_utils = getUtility(ICustomersUtils) 1299 return customers_utils.renderPDF( 1300 self, 'overview_slip.pdf', 1301 self.context.customer, customerview, 1302 tableheader=tableheader, 1303 tabledata=tabledata, 1304 omit_fields=self.omit_fields) 1305 1306 1307 class PDFApplicationSlipPage(UtilityView, grok.View): 1308 """Deliver pdf file including metadata. 1309 """ 1310 grok.context(IApplication) 1311 grok.name('application_slip.pdf') 1312 grok.require('waeup.viewCustomer') 1313 prefix = 'form' 1314 1315 omit_fields = ('suspended', 'sex', 1316 'suspended_comment',) 1317 1318 #form_fields = grok.AutoFields(ICustomerPDFApplication).omit( 1319 # 'last_transition_date') 1320 form_fields =() 1321 1322 @property 1323 def label(self): 1324 portal_language = getUtility(IIkobaUtils).PORTAL_LANGUAGE 1325 return '%s of %s\nTitle: %s' % ( 1326 self.context.translated_class_name, 1327 self.context.customer.display_fullname, 1328 self.context.title) 1329 1330 def render(self): 1331 portal_language = getUtility(IIkobaUtils).PORTAL_LANGUAGE 1332 customerview = CustomerBasePDFFormPage(self.context.customer, 1333 self.request, self.omit_fields) 1334 customers_utils = getUtility(ICustomersUtils) 1335 return customers_utils.renderPDF( 1336 self, 'application_slip.pdf', 1337 self.context.customer, customerview, 1338 omit_fields=self.omit_fields) -
main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/documentaddform.pt
r12015 r12090 1 1 <form action="." tal:attributes="action request/URL" method="post" 2 enctype="multipart/form-data" >2 enctype="multipart/form-data" i18n:domain="waeup.ikoba"> 3 3 <table class="form-table"> 4 4 <tbody> 5 5 <tr> 6 6 <td class="fieldname"> 7 <span >Document Type</span>:7 <span i18n:translate="">Document Type</span>: 8 8 </td> 9 9 <td> -
main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/documentpage.pt
r12056 r12090 1 <div class="wfstatus-sub" i18n:domain="waeup. kofa">1 <div class="wfstatus-sub" i18n:domain="waeup.ikoba"> 2 2 Document State: <span tal:replace="context/translated_state"> 3 3 VERIFICATIONSTATE</span> -
main/waeup.ikoba/trunk/src/waeup/ikoba/customers/container.py
r11997 r12090 1 ## $Id : container.py 8737 2012-06-17 07:32:08Z henrik$1 ## $Id$ 2 2 ## 3 3 ## Copyright (C) 2014 Uli Fouquet & Henrik Bettermann … … 66 66 return new_id 67 67 68 def archive(self, id=None):69 raise NotImplementedError()70 71 def clear(self, id=None, archive=True):72 raise NotImplementedError()73 74 68 def addCustomer(self, customer): 75 69 """Add a customer with subcontainers. -
main/waeup.ikoba/trunk/src/waeup/ikoba/customers/customer.py
r12087 r12090 43 43 from waeup.ikoba.customers.utils import generate_customer_id, path_from_custid 44 44 from waeup.ikoba.customers.documents import CustomerDocumentsContainer 45 from waeup.ikoba.customers.applications import ApplicationsContainer 45 46 from waeup.ikoba.utils.helpers import attrs_to_fields, now, copy_filesystem_tree 46 47 … … 183 184 documents = CustomerDocumentsContainer() 184 185 customer['documents'] = documents 186 applications = ApplicationsContainer() 187 customer['applications'] = applications 185 188 return 186 189 -
main/waeup.ikoba/trunk/src/waeup/ikoba/customers/interfaces.py
r12089 r12090 47 47 """ 48 48 49 def archive(id=None):50 """Create on-dist archive of customers.51 52 If id is `None`, all customers are archived.53 54 If id contains a single id string, only the respective55 customers are archived.56 57 If id contains a list of id strings all of the respective58 customers types are saved to disk.59 """60 61 def clear(id=None, archive=True):62 """Remove customers of type given by 'id'.63 64 Optionally archive the customers.65 66 If id is `None`, all customers are archived.67 68 If id contains a single id string, only the respective69 customers are archived.70 71 If id contains a list of id strings all of the respective72 customer types are saved to disk.73 74 If `archive` is ``False`` none of the archive-handling is done75 and respective customers are simply removed from the76 database.77 """78 79 49 unique_customer_id = Attribute("""A unique customer id.""") 80 50 -
main/waeup.ikoba/trunk/src/waeup/ikoba/customers/permissions.py
r12065 r12090 48 48 49 49 50 class EditApplications(grok.Permission): 51 grok.name('waeup.editApplications') 52 53 50 54 class UploadCustomerFile(grok.Permission): 51 55 grok.name('waeup.uploadCustomerFile') … … 93 97 'waeup.manageCustomer', 'waeup.viewCustomersContainer', 94 98 'waeup.editCustomerDocuments', 'waeup.uploadCustomerFile', 95 'waeup.viewCustomersTab', 'waeup.triggerTransition') 99 'waeup.viewCustomersTab', 'waeup.triggerTransition', 100 'waeup.editApplications') 96 101 97 102 -
main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_container.py
r11997 r12090 1 ## $Id : test_container.py 7811 2012-03-08 19:00:51Z uli$1 ## $Id$ 2 2 ## 3 3 ## Copyright (C) 2014 Uli Fouquet & Henrik Bettermann … … 68 68 return 69 69 70 def test_base(self):71 # We cannot call the fundamental methods of a base in that case72 container = CustomersContainer()73 self.assertRaises(74 NotImplementedError, container.archive)75 self.assertRaises(76 NotImplementedError, container.clear)77 # We cannot add arbitrary objects78 #department = Department()79 #self.assertRaises(80 # TypeError, container.addCustomer, department)81 82 83 70 def test_logger(self): 84 71 # We can get a logger from root -
main/waeup.ikoba/trunk/src/waeup/ikoba/customers/utils.py
r12089 r12090 33 33 from waeup.ikoba.interfaces import MessageFactory as _ 34 34 from waeup.ikoba.interfaces import ( 35 CREATED, STARTED, REQUESTED, APPROVED, IIkobaUtils, IExtFileStore) 35 STARTED, CREATED, REQUESTED, APPROVED, SUBMITTED, VERIFIED, REJECTED, 36 EXPIRED, 37 IIkobaUtils, IExtFileStore) 36 38 from waeup.ikoba.customers.interfaces import ICustomersUtils 37 39 from waeup.ikoba.browser.interfaces import IPDFCreator … … 300 302 301 303 TRANSLATED_APPLICATION_STATES = { 304 CREATED: _('created'), 305 SUBMITTED: _('submitted for approval'), 306 APPROVED: _('approved'), 307 REJECTED: _('rejected'), 308 EXPIRED:_('expired') 302 309 } 303 310 … … 307 314 } 308 315 316 APPTYPES_DICT = { 317 'SampleApplication': 'Sample Application', 318 } 319 309 320 SELECTABLE_DOCTYPES_DICT = DOCTYPES_DICT 321 322 SELECTABLE_APPTYPES_DICT = APPTYPES_DICT 310 323 311 324 def getPDFCreator(self, context=None): -
main/waeup.ikoba/trunk/src/waeup/ikoba/customers/viewlets.py
r12062 r12090 27 27 from waeup.ikoba.customers.interfaces import ( 28 28 ICustomer, ICustomersContainer, 29 ICustomerDocumentsContainer, ICustomerDocument) 29 ICustomerDocumentsContainer, ICustomerDocument, 30 IApplicationsContainer, IApplication) 30 31 from waeup.ikoba.customers.browser import ( 31 32 CustomersContainerPage, CustomersContainerManagePage, 32 33 CustomerBaseDisplayFormPage, 33 DocumentsManageFormPage, DocumentDisplayFormPage, DocumentManageFormPage) 34 DocumentsManageFormPage, DocumentDisplayFormPage, DocumentManageFormPage, 35 ApplicationsManageFormPage, ApplicationDisplayFormPage, 36 ApplicationManageFormPage) 34 37 35 38 grok.context(IIkobaObject) # Make IIkobaObject the default context … … 107 110 targets += [ 108 111 {'url':customer_url, 'title':'Base Data'}, 109 {'url':customer_url + '/documents', 'title':_('Documents')}, 112 {'url':customer_url + '/applications', 'title':_('My Applications')}, 113 {'url':customer_url + '/documents', 'title':_('My Documents')}, 110 114 {'url':customer_url + '/history', 'title':_('History')}, 111 115 ] … … 148 152 text = _(u'Base Data') 149 153 154 155 class CustomerManageApplicationsLink(CustomerManageLink): 156 grok.order(3) 157 link = 'applications' 158 text = _(u'Applications') 159 160 150 161 class CustomerManageDocumentsLink(CustomerManageLink): 151 grok.order( 3)162 grok.order(4) 152 163 link = 'documents' 153 164 text = _(u'Documents') … … 298 309 299 310 300 class PDF OverviewActionButton(ManageActionButton):311 class PDFDocumentOverviewActionButton(ManageActionButton): 301 312 grok.order(2) 302 313 grok.context(ICustomerDocumentsContainer) … … 351 362 icon = 'actionicon_view.png' 352 363 353 class PDFSlipActionButton(ManageActionButton): 364 365 class PDFDocumentSlipActionButton(ManageActionButton): 354 366 grok.order(3) 355 367 grok.context(ICustomerDocument) … … 359 371 text = _('Download document slip') 360 372 target = 'document_slip.pdf' 373 374 # Viewlets for customer applications 375 376 class AddApplicationActionButton(AddActionButton): 377 grok.order(1) 378 grok.context(IApplicationsContainer) 379 grok.view(ApplicationsManageFormPage) 380 grok.require('waeup.editApplications') 381 text = _('Add application') 382 target = 'addapp' 383 384 385 class PDFApplicationOverviewActionButton(ManageActionButton): 386 grok.order(2) 387 grok.context(IApplicationsContainer) 388 grok.view(ApplicationsManageFormPage) 389 grok.require('waeup.viewCustomer') 390 icon = 'actionicon_pdf.png' 391 text = _('Download applications overview') 392 target = 'overview_slip.pdf' 393 394 395 class ApplicationManageActionButton(ManageActionButton): 396 grok.order(1) 397 grok.context(IApplication) 398 grok.view(ApplicationDisplayFormPage) 399 grok.require('waeup.manageCustomer') 400 text = _('Manage') 401 target = 'manage' 402 403 404 class ApplicationEditActionButton(ManageActionButton): 405 grok.order(1) 406 grok.context(IApplication) 407 grok.view(ApplicationDisplayFormPage) 408 grok.require('waeup.handleCustomer') 409 text = _('Edit') 410 target = 'edit' 411 412 @property 413 def target_url(self): 414 if not self.context.is_editable: 415 return '' 416 return self.view.url(self.view.context, self.target) 417 418 419 class ApplicationTrigTransActionButton(ManageActionButton): 420 grok.order(2) 421 grok.context(IApplication) 422 grok.view(ApplicationDisplayFormPage) 423 grok.require('waeup.triggerTransition') 424 icon = 'actionicon_trigtrans.png' 425 text = _(u'Transition') 426 target = 'trigtrans' 427 428 429 class ApplicationViewActionButton(ManageActionButton): 430 grok.order(1) 431 grok.context(IApplication) 432 grok.view(ApplicationManageFormPage) 433 grok.require('waeup.handleCustomer') 434 text = _('View') 435 target = 'index' 436 icon = 'actionicon_view.png' 437 438 439 class PDFApplicationSlipActionButton(ManageActionButton): 440 grok.order(3) 441 grok.context(IApplication) 442 grok.view(ApplicationDisplayFormPage) 443 grok.require('waeup.viewCustomer') 444 icon = 'actionicon_pdf.png' 445 text = _('Download application slip') 446 target = 'application_slip.pdf' 447
Note: See TracChangeset for help on using the changeset viewer.