def validate(self, value): super(SketchFileValidator, self).validate(value) fzzName = value.filename fzzNameLower = fzzName.lower() if not (fzzNameLower.endswith('.fzz')): raise Invalid( _(u"We can only produce from shareable Fritzing sketch files (.fzz)")) # use StringIO to make the blob to look like a file object: fzzData = StringIO(value.data) zf = None try: zf = zipfile.ZipFile(fzzData) except: raise Invalid( _(u"Hmmm, '%s' doesn't seem to be a valid .fzz file. Sorry, we only support those at this time." % fzzName)) pairs = getboardsize.fromZipFile(zf, fzzName) if not (len(pairs) >= 2): raise Invalid( _(u"No boards found in '%s'." % fzzName)) if not (len(pairs) == 2): raise Invalid( _(u"Multiple boards found in '%s'. Sorry, we still work on the support for multiple boards per file." % fzzName)) value.width = pairs[0] / 10 value.height = pairs[1] / 10 return True
class PayPalCheckout(grok.View): """Order checkout """ grok.name('paypal_checkout') grok.require('zope2.View') grok.context(IFabOrder) label = _(u"PayPal Checkout") description = _(u"Order checkout") def update(self): portal_workflow = getToolByName(self, 'portal_workflow') review_state = getStateId(None, self.context, portal_workflow) if review_state != 'open': self.addStatusMessage(_(u"Already checked out."), "info") return if not self.context.area > 0: self.addStatusMessage( _(u"Sketches missing/invalid, checkout aborted."), "error") return portal_workflow.doActionFor(self.context, action='submit') # send e-mails sendStatusMail(self.context) self.request.set('disable_border', 1) def addStatusMessage(self, message, messageType): IStatusMessage(self.request).addStatusMessage(message, messageType) faborderURL = self.context.absolute_url() self.request.response.redirect(faborderURL)
class Index(grok.View): """Review the order """ grok.require('zope2.View') grok.context(IFabOrder) label = _(u"Order your PCBs") description = _(u"Review the order") # make tools availible to the template as view.toolname() from fritzing.fab.tools \ import encodeFilename, getStateId, getStateTitle, isStateId def update(self): member = self.context.portal_membership.getAuthenticatedMember() self.isManager = member.has_role('Manager') if not (self.isManager): self.request.set('disable_border', 1) if self.context.shipTo: self.shipToTitle = IFabOrder['shipTo'].vocabulary.getTerm( self.context.shipTo).title primeCostsPerSquareCm = 0.21 earningsPerSquareCm = 0.7 * (self.context.pricePerSquareCm - primeCostsPerSquareCm) devHourCosts = 50.0 self.devMinutes = (earningsPerSquareCm * self.context.area) / (devHourCosts / 60.0)
class Edit(dexterity.EditForm): """Edit the order """ grok.name('edit') grok.require('cmf.ModifyPortalContent') grok.context(IFabOrder) schema = IFabOrder label = _(u"Edit order") description = _(u"Edit the order")
class Checkout(grok.View): """Order checkout """ grok.name('checkout') grok.require('cmf.ModifyPortalContent') grok.context(IFabOrder) label = _(u"Checkout") description = _(u"Order checkout") def render(self): faborderURL = self.context.absolute_url() self.request.response.redirect(faborderURL)
class CheckoutSuccess(grok.View): """Order checkout success """ grok.name('checkout_success') grok.require('zope2.View') grok.context(IFabOrder) label = _(u"Checkout") description = _(u"Order checkout") def render(self): faborderURL = self.context.absolute_url() self.request.response.redirect(faborderURL)
class AddForm(dexterity.AddForm): """adds a sketch """ grok.name('sketch') grok.require('cmf.AddPortalContent') grok.context(IFabOrder) schema = ISketch label = _(u"Add Sketch") description = u'' def create(self, data): sketch = createObject('sketch') sketch.id = data['orderItem'].filename.encode("ascii") # lets make shure this file doesn't already exist if self.context.hasObject(sketch.id): IStatusMessage(self.request).addStatusMessage( _(u"A Sketch with this name already exists."), "error") return None sketch.title = data['orderItem'].filename sketch.orderItem = data['orderItem'] sketch.copies = data['copies'] sketch.check = True return sketch def add(self, object): if isinstance(object, Item): self.context._setObject(object.id, object)
def sendStatusMail(context): """Sends notification on the order status to the orderer and faborders.salesEmail """ mail_text = u"" charset = 'utf-8' portal = getSite() mail_template = portal.mail_order_status_change faborders = context.aq_parent from_address = faborders.salesEmail from_name = "Fritzing Fab" to_address = context.email user = context.getOwner() to_name = user.getProperty('fullname') # we expect a name to contain non-whitespace characters: if not re.search('\S', to_name): to_name = u"%s" % user state_id = getStateId(False, context) state_title = getStateTitle(False, context) delivery_date = faborders.nextProductionDelivery mail_subject = _(u"Your Fritzing Fab order #%s is now %s") % ( context.id, state_title.lower()) mail_text = mail_template( to_name=to_name, to_address=to_address, state_id=state_id, state_title=state_title, delivery_date=delivery_date, faborder=context, ship_to=IFabOrder['shipTo'].vocabulary.getTerm(context.shipTo).title, ) try: host = getToolByName(context, 'MailHost') # send our copy: host.send( MIMEText(mail_text, 'plain', charset), mto=formataddr((from_name, from_address)), mfrom=formataddr((from_name, from_address)), subject=mail_subject, charset=charset, msg_type="text/plain", ) # send notification for the orderer: host.send( MIMEText(mail_text, 'plain', charset), mto=formataddr((to_name, to_address)), mfrom=formataddr((from_name, from_address)), subject=mail_subject, charset=charset, msg_type="text/plain", ) except SMTPRecipientsRefused: # Don't disclose email address on failure raise SMTPRecipientsRefused('Recipient address rejected by server')
def update(self): portal_workflow = getToolByName(self, 'portal_workflow') review_state = getStateId(None, self.context, portal_workflow) if review_state != 'open': self.addStatusMessage(_(u"Already checked out."), "info") return if not self.context.area > 0: self.addStatusMessage(_(u"Sketches missing/invalid, checkout aborted."), "error") return portal_workflow.doActionFor(self.context, action='submit') # send e-mails sendStatusMail(self.context) self.request.set('disable_border', 1)
def sendStatusMail(context): """Sends notification on the order status to the orderer and faborders.salesEmail """ mail_text = u"" charset = 'utf-8' portal = getSite() mail_template = portal.mail_order_status_change faborders = context.aq_parent from_address = faborders.salesEmail from_name = "Fritzing Fab" to_address = context.email user = context.getOwner() to_name = user.getProperty('fullname') # we expect a name to contain non-whitespace characters: if not re.search('\S', to_name): to_name = u"%s" % user state_id = getStateId(False, context) state_title = getStateTitle(False, context) delivery_date = faborders.nextProductionDelivery mail_subject = _(u"Your Fritzing Fab order #%s is now %s") % (context.id, state_title.lower()) mail_text = mail_template( to_name = to_name, to_address = to_address, state_id = state_id, state_title = state_title, delivery_date = delivery_date, faborder = context, ship_to = IFabOrder['shipTo'].vocabulary.getTerm(context.shipTo).title, ) try: host = getToolByName(context, 'MailHost') # send our copy: host.send( MIMEText(mail_text, 'plain', charset), mto = formataddr((from_name, from_address)), mfrom = formataddr((from_name, from_address)), subject = mail_subject, charset = charset, msg_type="text/plain", ) # send notification for the orderer: host.send( MIMEText(mail_text, 'plain', charset), mto = formataddr((to_name, to_address)), mfrom = formataddr((from_name, from_address)), subject = mail_subject, charset = charset, msg_type="text/plain", ) except SMTPRecipientsRefused: # Don't disclose email address on failure raise SMTPRecipientsRefused('Recipient address rejected by server')
def update(self): portal_workflow = getToolByName(self, 'portal_workflow') review_state = getStateId(None, self.context, portal_workflow) if review_state != 'open': self.addStatusMessage(_(u"Already checked out."), "info") return if not self.context.area > 0: self.addStatusMessage( _(u"Sketches missing/invalid, checkout aborted."), "error") return portal_workflow.doActionFor(self.context, action='submit') # send e-mails sendStatusMail(self.context) self.request.set('disable_border', 1)
def validate(self, value): super(SketchFileValidator, self).validate(value) fzzName = value.filename fzzNameLower = fzzName.lower() if not (fzzNameLower.endswith('.fzz')): raise Invalid( _(u"We can only produce from shareable Fritzing sketch files (.fzz)" )) # use StringIO to make the blob to look like a file object: fzzData = StringIO(value.data) zf = None try: zf = zipfile.ZipFile(fzzData) except: raise Invalid( _(u"Hmmm, '%s' doesn't seem to be a valid .fzz file. Sorry, we only support those at this time." % fzzName)) pairs = getboardsize.fromZipFile(zf, fzzName) if not (len(pairs) >= 2): raise Invalid(_(u"No boards found in '%s'." % fzzName)) if not (len(pairs) == 2): raise Invalid( _(u"Multiple boards found in '%s'. Sorry, we still work on the support for multiple boards per file." % fzzName)) value.width = pairs[0] / 10 value.height = pairs[1] / 10 return True
def create(self, data): sketch = createObject('sketch') sketch.id = data['orderItem'].filename.encode("ascii") # lets make shure this file doesn't already exist if self.context.hasObject(sketch.id): IStatusMessage(self.request).addStatusMessage( _(u"A Sketch with this name already exists."), "error") return None sketch.title = data['orderItem'].filename sketch.orderItem = data['orderItem'] sketch.copies = data['copies'] sketch.check = True return sketch
def checkEMail(eMailAddress): """Check if the e-mail address looks valid """ if not (eMailMatch(eMailAddress)): raise Invalid(_(u"Invalid e-mail address")) return True
class ISketch(form.Schema): """A Fritzing Sketch file """ orderItem = NamedBlobFile( title = _(u"Sketch file"), description = _(u"The .fzz file of your sketch")) copies = Int( title = _(u"Copies"), description = _(u"The more copies, the cheaper each one gets"), min = 1, default = 1) form.omitted('check') check = Bool( title = _(u"File Check"), description = _(u"Have us check your design for an extra 4 EUR"), default = True) form.omitted( 'width', 'height', 'area') width = Float( title = _(u"Width"), description = _(u"The width of this sketch in cm"), min = 0.0, default = 0.0) height = Float( title = _(u"Height"), description = _(u"The height of this sketch in cm"), min = 0.0, default = 0.0) area = Float( title = _(u"Area"), description = _(u"The area of this sketch in cm^2"), min = 0.0, default = 0.0)
class IFabOrders(form.Schema): """Fritzing Fab orders Folder """ title = TextLine( title = _(u"Order-folder name"), description = _(u"The title of this fab-instance")) description = Text( title = _(u"Order-folder description"), description = _(u"The description (also subtitle) of this fab-instance")) salesEmail = TextLine( title = _(u"Sales e-mail"), description = _(u"Order status changes are e-mailed to this address"), constraint = checkEMail) shippingGermany = Float( title = _(u"Shipping Costs Germany"), description = _(u"The shipping costs for Germany in Euro"), min = 0.0, default = 4.0) shippingEU = Float( title = _(u"Shipping Costs EU"), description = _(u"The shipping costs for the EU in Euro"), min = 0.0, default = 6.0) shippingWorld = Float( title = _(u"Shipping Costs outside EU"), description = _(u"The shipping costs for otside of the EU in Euro"), min = 0.0, default = 6.0) taxesGermany = Float( title = _(u"Taxes Germany"), description = _(u"The taxes for Germany in Percent"), min = 0.0, default = 19.0) taxesEU = Float( title = _(u"Taxes EU"), description = _(u"The taxes for the EU in Percent"), min = 0.0, default = 19.0) taxesWorld = Float( title = _(u"Taxes outside EU"), description = _(u"The taxes for outside of the EU in Percent"), min = 0.0, default = 0.0) nextProductionDelivery = Date( title = _(u"Next production delivery date"), description = _(u"Estimated delivery date of PCBs from the next production"), required = False) nextProductionClosingDate = Date( title = _(u"Next production closing date"), description = _(u"Orders must be send in before this date to be included in the next production run"), required = False) editableContent = RichText( title = _(u"Order-folder text"), description = _(u"The text of this fab-instance"))
class IFabOrder(form.Schema): """Fritzing Fab order details """ shipTo = Choice( title = _(u"Shipping Area"), description = _(u"Where you are located"), vocabulary = SimpleVocabulary([ SimpleTerm(value = u'germany', title = _(u'Germany')), SimpleTerm(value = u'eu', title = _(u'European Union (EU)')), SimpleTerm(value = u'world', title = _(u'Worldwide')) ])) email = TextLine( title = _(u"E-Mail"), description = _(u"Your e-mail address"), constraint = checkEMail) form.omitted( 'telephone', 'area', 'pricePerSquareCm', 'priceNetto', 'priceShipping', 'numberOfQualityChecks', 'priceQualityChecksNetto', 'taxesPercent', 'taxes', 'priceTotalNetto', 'priceTotalBrutto', 'trackingNumber') telephone = ASCIILine( title = _(u"Telephone number"), description = _(u"We prefer a mobile number")) area = Float( title = _(u"Area"), description = _(u"The total area of all sketches in cm^2"), min = 0.0, default = 0.0) pricePerSquareCm = Float( title = _(u"Price per cm^2"), description = _(u"The price per cm^2 in Euro"), min = 0.0, default = 0.0) priceNetto = Float( title = _(u"Netto price"), description = _(u"The netto price without shipping in Euro"), min = 0.0, default = 0.0) priceShipping = Float( title = _(u"Shipping costs"), description = _(u"The shipping costs in Euro"), min = 0.0, default = 0.0) numberOfQualityChecks = Int( title = _(u"Number of quality checks"), description = _(u"Number of quality checks"), min = 0, default = 0) priceQualityChecksNetto = Float( title = _(u"Costs for quality checks"), description = _(u"The costs for quality checks in Euro"), min = 0.0, default = 0.0) taxesPercent = Float( title = _(u"Percent Taxes"), description = _(u"Taxes like VAT in Percent"), min = 0.0, default = 0.0) taxes = Float( title = _(u"Taxes"), description = _(u"Taxes like VAT"), min = 0.0, default = 0.0) priceTotalNetto = Float( title = _(u"Total Netto"), description = _(u"The netto price costs in Euro"), min = 0.0, default = 0.0) priceTotalBrutto = Float( title = _(u"Total"), description = _(u"The price including shipping costs and taxes in Euro"), min = 0.0, default = 0.0) trackingNumber = TextLine( title = _(u"Tracking Number"), description = _(u"The tracking number assigned by the parcel service"))