Passed
Push — master ( babb16...96e596 )
by Jordi
04:46
created

InvoiceView.to_localized_time()   A

Complexity

Conditions 2

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 11
dl 0
loc 15
rs 9.85
c 0
b 0
f 0
cc 2
nop 3
1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of SENAITE.CORE
4
#
5
# Copyright 2018 by it's authors.
6
# Some rights reserved. See LICENSE.rst, CONTRIBUTORS.rst.
7
8
from bika.lims import _
9
from bika.lims import api
10
from bika.lims.browser import BrowserView
11
from bika.lims.interfaces import IAnalysis
12
from bika.lims.interfaces import IAnalysisProfile
13
from bika.lims.interfaces import IInvoiceView
14
from bika.lims.utils import createPdf
15
from plone.memoize import view
16
from Products.CMFPlone.i18nl10n import ulocalized_time
17
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
18
from senaite.core.supermodel.model import SuperModel
19
from zope.i18n.locales import locales
20
from zope.interface import implements
21
22
23
class InvoiceView(BrowserView):
24
    """Analyses Invoice View
25
    """
26
    implements(IInvoiceView)
27
28
    template = ViewPageTemplateFile("templates/invoice.pt")
29
    print_template = ViewPageTemplateFile("templates/invoice_print.pt")
30
    content = ViewPageTemplateFile("templates/invoice_content.pt")
31
32
    def __init__(self, context, request):
33
        self.context = context
34
        self.request = request
35
36
    def __call__(self):
37
        # TODO: Refactor to permission
38
        # Control the visibility of the invoice create/print document actions
39
        if api.get_review_status(self.context) in ["verified", "published"]:
40
            self.request["verified"] = 1
41
        return self.template()
42
43
    @property
44
    def sample(self):
45
        """Returns a supermodel of the sample
46
        """
47
        return SuperModel(self.context)
48
49
    def to_localized_time(self, date, **kw):
50
        """Converts the given date to a localized time string
51
        """
52
        if date is None:
53
            return ""
54
        # default options
55
        options = {
56
            "long_format": True,
57
            "time_only": False,
58
            "context": api.get_portal(),
59
            "request": api.get_request(),
60
            "domain": "senaite.core",
61
        }
62
        options.update(kw)
63
        return ulocalized_time(date, **options)
64
65
    @view.memoize
66
    def get_currency_symbol(self):
67
        """Get the currency Symbol
68
        """
69
        locale = locales.getLocale("en")
70
        setup = api.get_setup()
71
        currency = setup.getCurrency()
72
        return locale.numbers.currencies[currency].symbol
73
74
    @view.memoize
75
    def get_decimal_mark(self):
76
        """Returns the decimal mark
77
        """
78
        setup = api.get_setup()
79
        return setup.getDecimalMark()
80
81
    def format_price(self, price):
82
        """Formats the price with the set decimal mark and currency
83
        """
84
        # ensure we have a float
85
        price = api.to_float(price, default=0.0)
86
        dm = self.get_decimal_mark()
87
        cur = self.get_currency_symbol()
88
        price = "%s %.2f" % (cur, price)
89
        return price.replace(".", dm)
90
91
    def get_billable_items(self):
92
        """Return a list of billable items
93
        """
94
        items = []
95
        for obj in self.context.getBillableItems():
96
            if self.is_profile(obj):
97
                items.append({
98
                    "obj": obj,
99
                    "title": obj.Title(),
100
                    "vat": obj.getAnalysisProfileVAT(),
101
                    "price": self.format_price(obj.getAnalysisProfilePrice()),
102
                })
103
            if self.is_analysis(obj):
104
                items.append({
105
                    "obj": obj,
106
                    "title": obj.Title(),
107
                    "vat": obj.getVAT(),
108
                    "price": self.format_price(obj.getPrice()),
109
                })
110
        return items
111
112
    def is_profile(self, obj):
113
        """Checks if the object is a profile
114
        """
115
        return IAnalysisProfile.providedBy(obj)
116
117
    def is_analysis(self, obj):
118
        """Checks if the object is an analysis
119
        """
120
        return IAnalysis.providedBy(obj)
121
122
    def add_status_message(self, message, level="info"):
123
        """Set a portal status message
124
        """
125
        return self.context.plone_utils.addPortalMessage(message, level)
126
127
128 View Code Duplication
class InvoicePrintView(InvoiceView):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
129
    """Print view w/o outer contents
130
    """
131
    template = ViewPageTemplateFile("templates/invoice_print.pt")
132
133
    def __call__(self):
134
        pdf = self.create_pdf()
135
        filename = "{}.pdf".format(self.context.getId())
136
        return self.download(pdf, filename)
137
138
    def create_pdf(self):
139
        """Create the invoice PDF
140
        """
141
        invoice = self.template()
142
        return createPdf(invoice)
143
144
    def download(self, data, filename, content_type="application/pdf"):
145
        """Download the PDF
146
        """
147
        self.request.response.setHeader(
148
            "Content-Disposition", "inline; filename=%s" % filename)
149
        self.request.response.setHeader("Content-Type", content_type)
150
        self.request.response.setHeader("Content-Length", len(data))
151
        self.request.response.setHeader("Cache-Control", "no-store")
152
        self.request.response.setHeader("Pragma", "no-cache")
153
        self.request.response.write(data)
154
155
156
class InvoiceCreate(InvoicePrintView):
157
    """Create the invoice
158
    """
159
160
    def __call__(self):
161
        # Create the invoice object and link it to the current AR.
162
        pdf = self.create_pdf()
163
        invoice = self.context.createInvoice(pdf)
164
        self.add_status_message(_("Invoice {} created").format(
165
            api.get_id(invoice)))
166
167
        # Reload the page to see the the new fields
168
        self.request.response.redirect(
169
            "%s/invoice" % self.aq_parent.absolute_url())
170