<s> import datetime <EOL> import logging <EOL> from django . contrib import messages <EOL> from django . core . exceptions import ValidationError <EOL> from django . db . models import Sum <EOL> from django . template . defaultfilters import slugify <EOL> from django . utils . translation import ugettext_lazy as _ <EOL> from ralph . admin . helpers import get_value_by_relation_path <EOL> from ralph . helpers import generate_pdf_response <EOL> from ralph . lib . external_services import ExternalService <EOL> from ralph . reports . models import Report , ReportTemplate <EOL> logger = logging . getLogger ( __name__ ) <EOL> class ReportTemplateNotDefined ( ValidationError ) : <EOL> pass <EOL> class InvoiceReportMixin ( object ) : <EOL> actions = [ '<STR_LIT>' ] <EOL> _invoice_report_select_related = [ ] <EOL> _invoice_report_common_fields = [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] <EOL> _price_field = '<STR_LIT>' <EOL> _invoice_report_name = '<STR_LIT>' <EOL> _invoice_report_item_fields = [ ] <EOL> _invoice_report_empty_value = '<STR_LIT:->' <EOL> _invoice_report_datetime_format = '<STR_LIT>' <EOL> def invoice_report ( self , request , queryset ) : <EOL> """<STR_LIT>""" <EOL> queryset = self . _get_invoice_report_queryset ( queryset ) <EOL> try : <EOL> self . _validate ( queryset ) <EOL> return self . _generate_invoice_report ( request , queryset ) <EOL> except ValidationError as e : <EOL> messages . error ( request , e . message ) <EOL> invoice_report . short_description = _ ( '<STR_LIT>' ) <EOL> def _validate ( self , queryset ) : <EOL> """<STR_LIT>""" <EOL> values_distinct = queryset . values ( <EOL> * self . _invoice_report_common_fields <EOL> ) . distinct ( ) <EOL> if values_distinct . count ( ) != <NUM_LIT:1> : <EOL> raise ValidationError ( self . _get_non_unique_error ( queryset ) ) <EOL> if not all ( values_distinct [ <NUM_LIT:0> ] . values ( ) ) : <EOL> raise ValidationError ( "<STR_LIT>" . format ( '<STR_LIT:U+002CU+0020>' . join ( <EOL> self . _invoice_report_common_fields <EOL> ) ) ) <EOL> def _get_non_unique_error ( self , queryset ) : <EOL> """<STR_LIT>""" <EOL> non_unique = { } <EOL> for field in self . _invoice_report_common_fields : <EOL> items = queryset . values ( field ) . distinct ( ) <EOL> if items . count ( ) != <NUM_LIT:1> : <EOL> if field == '<STR_LIT>' : <EOL> data = '<STR_LIT:U+002CU+0020>' . join ( <EOL> item [ field ] . strftime ( "<STR_LIT>" ) <EOL> for item in items if item [ field ] <EOL> ) <EOL> else : <EOL> data = '<STR_LIT:U+002CU+0020>' . join ( <EOL> item [ field ] for item in items if item [ field ] <EOL> ) <EOL> non_unique [ field ] = data <EOL> non_unique_items = '<STR_LIT:U+0020>' . join ( [ <EOL> '<STR_LIT>' . format ( key , value ) <EOL> for key , value in non_unique . items ( ) if value <EOL> ] ) <EOL> return '<STR_LIT>' . format ( <EOL> _ ( '<STR_LIT>' ) , non_unique_items , <EOL> ) <EOL> def _generate_invoice_report ( self , request , queryset ) : <EOL> """<STR_LIT>""" <EOL> logger . info ( '<STR_LIT>' . format ( <EOL> queryset . model <EOL> ) ) <EOL> data = self . _get_report_data ( request , queryset ) <EOL> content = self . _get_pdf_content ( data ) <EOL> file_name = '<STR_LIT>' . format ( <EOL> self . _invoice_report_name , data [ '<STR_LIT:id>' ] , <EOL> ) <EOL> return generate_pdf_response ( content , file_name ) <EOL> def _get_report_data ( self , request , queryset ) : <EOL> """<STR_LIT>""" <EOL> first_item = queryset [ <NUM_LIT:0> ] <EOL> data = { <EOL> '<STR_LIT:id>' : str ( slugify ( first_item . invoice_no ) ) , <EOL> '<STR_LIT>' : queryset . model . _meta . model_name , <EOL> '<STR_LIT>' : { <EOL> '<STR_LIT>' : first_item . invoice_no , <EOL> '<STR_LIT>' : first_item . invoice_date , <EOL> '<STR_LIT>' : first_item . provider , <EOL> '<STR_LIT>' : datetime . datetime . now ( ) . strftime ( <EOL> self . _invoice_report_datetime_format <EOL> ) , <EOL> } , <EOL> '<STR_LIT>' : list ( map ( self . _parse_item , queryset ) ) , <EOL> '<STR_LIT>' : queryset . aggregate ( <EOL> Sum ( self . _price_field ) <EOL> ) . get ( '<STR_LIT>' . format ( self . _price_field ) ) <EOL> } <EOL> logger . info ( '<STR_LIT>' . format ( data ) ) <EOL> return data <EOL> def _get_pdf_content ( self , data ) : <EOL> try : <EOL> report = Report . objects . get ( name = self . _invoice_report_name ) <EOL> template = report . templates . filter ( default = True ) . first ( ) <EOL> except ( Report . DoesNotExist , ReportTemplate . DoesNotExist ) : <EOL> raise ReportTemplateNotDefined ( <EOL> '<STR_LIT>' <EOL> ) <EOL> logger . info ( '<STR_LIT>' . format ( <EOL> report . name , template . template . path <EOL> ) ) <EOL> template_content = '<STR_LIT>' <EOL> with open ( template . template . path , '<STR_LIT:rb>' ) as f : <EOL> template_content = f . read ( ) <EOL> service_pdf = ExternalService ( '<STR_LIT>' ) <EOL> result = service_pdf . run ( <EOL> template = template_content , <EOL> data = data , <EOL> ) <EOL> return result <EOL> def _get_invoice_report_queryset ( self , queryset ) : <EOL> """<STR_LIT>""" <EOL> return queryset . select_related ( * self . _invoice_report_select_related ) <EOL> def _parse_item ( self , item ) : <EOL> """<STR_LIT>""" <EOL> result = { } <EOL> for f in self . _invoice_report_item_fields : <EOL> val = get_value_by_relation_path ( item , f ) <EOL> if callable ( val ) : <EOL> val = val ( ) <EOL> elif isinstance ( val , datetime . datetime ) : <EOL> val = val . strftime ( self . _invoice_report_datetime_format ) <EOL> result [ f ] = str ( val or self . _invoice_report_empty_value ) <EOL> return result <EOL> class AssetInvoiceReportMixin ( InvoiceReportMixin ) : <EOL> _invoice_report_select_related = [ <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' <EOL> ] <EOL> _invoice_report_item_fields = [ <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' <EOL> ] </s>
