def check_incoming_payments(self): """ This function will automaticly execute pairing of payments. Then it will take all invoices from metrocar that are in ACTIVE state and compare them to there doppelganger in Flexibee. """ self.pair_payments() from metrocar.invoices.models import Invoice from datetime import datetime #get all unpaid invoices from db unpaid_inv = Invoice.objects.all().filter(status='ACTIVE') for inv in unpaid_inv: try: #get doppelganger from Flexibee flex_inv = self.faktura.get_vydana_faktura_by_code(code='inv' + str(inv.id)) if flex_inv['stavUhrK'] == 'stavUhr.uhrazeno': #TODO osetreni castecne uhrady #set also metrocar invoice to PAID inv.status = 'PAID' inv.payment_datetime = datetime.now() inv.save() except FlexipyException as e: get_logger().error( "Error during automatic pairing of payments in Flexibee, error was " + str(e))
def create_invoice(cls, usr): """ Creates, saves and returns new invoice for the given user. Also subtracts the invoice price from the user's account """ activities = usr.get_invoiceable_activities() if len(activities) > 0: inv = Invoice(user=usr) inv.save() sum = inv.total_price_with_tax() if settings.ACCOUNTING_ENABLED == False: pdf = inv.get_printable_invoice() inv.pdf_invoice = pdf.generate_pdf() #if total price is less then zero then all these activites where taken from account #therefore invoice was already paid if sum < 0: inv.status = 'PAID' if settings.ACCOUNTING_ENABLED: try: accounting = importlib.import_module( settings.ACCOUNTING['IMPLEMENTATION']) account_instance = accounting.get_accounting_instance() account_instance.create_invoice(inv) inv.pdf_invoice = account_instance.print_invoice(inv) except ImportError, ex: get_logger().error( "Can't import accounting implementation from settings") inv.save() return inv
def send_mail(cls, recipients, template_code, template_lang, params, params2={}, attachment_path=None): """ Generic wrapper for saving e-mails with """ et = EmailTemplate.objects.get(code=template_code, language=template_lang) if isinstance(params, Model): # if object instance, convert to the dict from metrocar.utils.serializers import to_dict params = to_dict(params) #params is list of dict, we need only dict so !! TODO CRITICAL can something be at higher indexes?? params = params[0] assert isinstance(params, dict) params.update(params2) subject = et.render_subject( ** params) message = et.render_content( ** params) email = EmailMessage(subject, message, settings.EMAIL_HOST_USER, recipients) if(attachment_path != None): email.attach_file(attachment_path) try: email.send(fail_silently=False) get_logger().info("Mail " + template_code + "_" + template_lang + " sent to " + str(recipients)) except Exception as ex: get_logger().error("Mail " + template_code + "_" + template_lang + " could not be sent. Exception was: " + str(ex))
def send_by_email(self): """ Sends email documenting invoice having the PDF attached """ from metrocar.utils.models import EmailTemplate from django.core.mail import EmailMessage from metrocar.utils.serializers import to_dict from metrocar.utils.log import get_logger self.pdf_invoice.open(mode='rb') if self.status == 'PAID': et = EmailTemplate.objects.get(code='INV_' + self.user.language) else: et = EmailTemplate.objects.get(code='INV_A_' + self.user.language) params = to_dict(self) params = params[0] subject = et.render_subject(**params) message = et.render_content(**params) email = EmailMessage(subject, message, settings.EMAIL_HOST_USER, [self.user.email]) email.attach('Invoice.pdf', self.pdf_invoice.read(), PrintableInvoicePdf.get_mime()) try: email.send(fail_silently=False) get_logger().info("Mail INV_" + self.user.language + " sent to " + str([self.user.email])) except Exception as ex: get_logger().error("Mail INV_" + self.user.language + " could not be sent. Exception was: " + str(ex)) self.pdf_invoice.close()
def print_invoice(self, invoice): """ This method print invoice in flexibee into pdf and save it to MEDIA_ROOT/files/invoices It returns path to the file. """ try: flex_inv = self.faktura.get_vydana_faktura_by_code(code='inv' + str(invoice.id)) pdf = self.faktura.get_faktura_vydana_pdf(flex_inv['id']) filename = '%s_%s' % (invoice.user.username, invoice.variable_symbol) save_to = os.path.join('invoices', strftime('%Y-%m')) from django.conf import settings save_path = os.path.join(settings.MEDIA_ROOT, save_to) if not os.path.exists(save_path): os.makedirs(save_path) file = open('%s/%s.pdf' % (save_path, filename), 'wb') file.write(pdf) file.close() get_logger().info("Pdf of invoice id=" + str(invoice.id) + " successfully created.") return '%s/%s.pdf' % (save_to, filename) except FlexipyException as e: get_logger().error( "Error during pdf printig invoice from Flexibee, error was " + str(e))
def pair_payments(self): """ This function is flexibee specific, because flexibee can pait payemnts automaticly, just by comparing incoming payments vs with invoice vs. """ try: self.faktura.proved_sparovani_plateb() get_logger().info("Automatic pairing of payments in Flexibee successfully executed.") except FlexipyException as e: get_logger().error("Error during automatic pairing of payments in Flexibee, error was " + str(e))
def get_invoice(self, invoice): """ This function get invoice from accounting system. """ try: flex_inv = self.faktura.get_vydana_faktura_by_code(code='inv' + str(invoice.id), detail='full') return flex_inv except FlexipyException as e: get_logger().error("Can't get invoice with id=" + str(invoice.id) + ". Complete error: " + str(e)) return None
def handle_noargs(self, **options): """ This command should be automaticly executed by cron for example every hour or at least once a day. """ if settings.ACCOUNTING_ENABLED: try: accounting = importlib.import_module(settings.ACCOUNTING['IMPLEMENTATION']) account_instance = accounting.get_accounting_instance() account_instance.check_incoming_payments() except ImportError, ex: get_logger().error("Can't import accounting implementation from settings")
def delete_invoice(self, invoice): """ This function delete invoice from Flexibee. It is used when manager deletes invoice from metrocar administration. :param invoice: metrocar.invoices.models.Invoice object """ try: flexInvoice = self.faktura.get_vydana_faktura_by_code(code='inv' + str(invoice.id)) flexID = flexInvoice['id'] self.faktura.delete_vydana_faktura(flexID) get_logger().info("Invoice with flexibee id " + str(invoice.id) + " was successfully deleted.") except FlexipyException as e: get_logger().error("Error during deletion of invoice in Flexibee, error was " + str(e))
def get_all_users_invoices(self, user): """ This function get list of all invoices in Flexibee which belong to MetrocarUser. :param user: metrocar.user_management.models.MetorcarUser :returns: List of all users invoices. """ list_invoices = [] #MetrocarUser is specified by specific_number which is created from his id-card number #query="specSym='0'" try: list_invoices = self.faktura.get_all_vydane_faktury(query="specSym='" + str(user.specific_symbol) + "'") except FlexipyException as e: get_logger().error("Error during readinf of users invoices in Flexibee, error was " + str(e)) return list_invoices
def handle_noargs(self, **options): """ This command should be automaticly executed by cron for example every hour or at least once a day. """ if settings.ACCOUNTING_ENABLED: try: accounting = importlib.import_module( settings.ACCOUNTING['IMPLEMENTATION']) account_instance = accounting.get_accounting_instance() account_instance.check_incoming_payments() except ImportError, ex: get_logger().error( "Can't import accounting implementation from settings")
def pair_payments(self): """ This function is flexibee specific, because flexibee can pait payemnts automaticly, just by comparing incoming payments vs with invoice vs. """ try: self.faktura.proved_sparovani_plateb() get_logger().info( "Automatic pairing of payments in Flexibee successfully executed." ) except FlexipyException as e: get_logger().error( "Error during automatic pairing of payments in Flexibee, error was " + str(e))
def send_warning_mail(self): """ Sends warning about negative balance on user account. """ if DEBUG is False: from metrocar.utils.models import EmailTemplate from django.core.mail import EmailMessage from metrocar.utils.log import get_logger et = EmailTemplate.objects.get(code='TAR_' + self.user.language) email = EmailMessage(et.subject, et.content, settings.EMAIL_HOST_USER, [self.user.email]) try: email.send(fail_silently=False) get_logger().info("Mail TAR_" + self.user.language + " sent to " + str([self.user.email])) except Exception as ex: get_logger().error("Mail TAR_" + self.user.language + " could not be sent. Exception was: " + str(ex))
def update_invoice(self, invoice): """ This method is called when invoice is updated through admin interface of metrocar system. This should not happen as manager should rather use web interface of Flexibee. But still just for precaution. Also there are only two types of fields that can be modified in admin interface. """ #first i will get this invoice from flexibee try: flex_inv = self.faktura.get_vydana_faktura_by_code(code='inv' + str(invoice.id)) flex_inv['datVyst'] = str(invoice.draw_date) flex_inv['datSplat'] = str(invoice.due_date) inv_id = flex_inv['id'] self.faktura.update_vydana_faktura(inv_id, flex_inv) get_logger().info("Invoice id: " + str(invoice.id) + " successfully updated.") except FlexipyException as e: get_logger().error("Error during update of invoice in Flexibee, error was " + str(e))
def get_all_users_invoices(self, user): """ This function get list of all invoices in Flexibee which belong to MetrocarUser. :param user: metrocar.user_management.models.MetorcarUser :returns: List of all users invoices. """ list_invoices = [] #MetrocarUser is specified by specific_number which is created from his id-card number #query="specSym='0'" try: list_invoices = self.faktura.get_all_vydane_faktury( query="specSym='" + str(user.specific_symbol) + "'") except FlexipyException as e: get_logger().error( "Error during readinf of users invoices in Flexibee, error was " + str(e)) return list_invoices
def delete_invoice(self, invoice): """ This function delete invoice from Flexibee. It is used when manager deletes invoice from metrocar administration. :param invoice: metrocar.invoices.models.Invoice object """ try: flexInvoice = self.faktura.get_vydana_faktura_by_code( code='inv' + str(invoice.id)) flexID = flexInvoice['id'] self.faktura.delete_vydana_faktura(flexID) get_logger().info("Invoice with flexibee id " + str(invoice.id) + " was successfully deleted.") except FlexipyException as e: get_logger().error( "Error during deletion of invoice in Flexibee, error was " + str(e))
def update_invoice(self, invoice): """ This method is called when invoice is updated through admin interface of metrocar system. This should not happen as manager should rather use web interface of Flexibee. But still just for precaution. Also there are only two types of fields that can be modified in admin interface. """ #first i will get this invoice from flexibee try: flex_inv = self.faktura.get_vydana_faktura_by_code(code='inv' + str(invoice.id)) flex_inv['datVyst'] = str(invoice.draw_date) flex_inv['datSplat'] = str(invoice.due_date) inv_id = flex_inv['id'] self.faktura.update_vydana_faktura(inv_id, flex_inv) get_logger().info("Invoice id: " + str(invoice.id) + " successfully updated.") except FlexipyException as e: get_logger().error( "Error during update of invoice in Flexibee, error was " + str(e))
def create_or_get_custom_permission(modelname, name, codename): modelname = modelname.lower() ct = unless(ContentType.DoesNotExist, ContentType.objects.get)(model=modelname) if not ct: # happens in the initial syncdb when creating the default Subsidiary, # but since it's going to have to be edited and .save()d anyway, # it doesn't matter # TODO: refactoring return None perm, created = Permission.objects.get_or_create( codename=codename, content_type__pk=ct.id, defaults={ 'name': name[:50], # permission name can be at most 50 chars long! 'content_type': ct, }) if (created == True): get_logger().info("Created new permission: " + unicode(perm)) return perm
def create_or_get_custom_permission(modelname, name, codename): modelname = modelname.lower() ct = unless(ContentType.DoesNotExist, ContentType.objects.get)(model=modelname) if not ct: # happens in the initial syncdb when creating the default Subsidiary, # but since it's going to have to be edited and .save()d anyway, # it doesn't matter # TODO: refactoring return None perm, created = Permission.objects.get_or_create( codename=codename, content_type__pk=ct.id, defaults={ 'name': name[:50], # permission name can be at most 50 chars long! 'content_type': ct, }) if(created == True): get_logger().info("Created new permission: " + unicode(perm)) return perm
def print_invoice(self, invoice): """ This method print invoice in flexibee into pdf and save it to MEDIA_ROOT/files/invoices It returns path to the file. """ try: flex_inv = self.faktura.get_vydana_faktura_by_code(code='inv' + str(invoice.id)) pdf = self.faktura.get_faktura_vydana_pdf(flex_inv['id']) filename = '%s_%s' % (invoice.user.username, invoice.variable_symbol) save_to = os.path.join('invoices', strftime('%Y-%m')) from django.conf import settings save_path = os.path.join(settings.MEDIA_ROOT, save_to) if not os.path.exists(save_path): os.makedirs(save_path) file = open('%s/%s.pdf' % (save_path, filename), 'wb') file.write(pdf) file.close() get_logger().info("Pdf of invoice id=" + str(invoice.id) + " successfully created.") return '%s/%s.pdf' % (save_to, filename) except FlexipyException as e: get_logger().error("Error during pdf printig invoice from Flexibee, error was " + str(e))
def send_mail(cls, recipients, template_code, template_lang, params, params2={}, attachment_path=None): """ Generic wrapper for saving e-mails with """ et = EmailTemplate.objects.get(code=template_code, language=template_lang) if isinstance(params, Model): # if object instance, convert to the dict from metrocar.utils.serializers import to_dict params = to_dict(params) #params is list of dict, we need only dict so !! TODO CRITICAL can something be at higher indexes?? params = params[0] assert isinstance(params, dict) params.update(params2) subject = et.render_subject(**params) message = et.render_content(**params) email = EmailMessage(subject, message, settings.EMAIL_HOST_USER, recipients) if (attachment_path != None): email.attach_file(attachment_path) try: email.send(fail_silently=False) get_logger().info("Mail " + template_code + "_" + template_lang + " sent to " + str(recipients)) except Exception as ex: get_logger().error("Mail " + template_code + "_" + template_lang + " could not be sent. Exception was: " + str(ex))
def check_incoming_payments(self): """ This function will automaticly execute pairing of payments. Then it will take all invoices from metrocar that are in ACTIVE state and compare them to there doppelganger in Flexibee. """ self.pair_payments() from metrocar.invoices.models import Invoice from datetime import datetime #get all unpaid invoices from db unpaid_inv = Invoice.objects.all().filter(status='ACTIVE') for inv in unpaid_inv: try: #get doppelganger from Flexibee flex_inv = self.faktura.get_vydana_faktura_by_code(code='inv' + str(inv.id)) if flex_inv['stavUhrK'] == 'stavUhr.uhrazeno': #TODO osetreni castecne uhrady #set also metrocar invoice to PAID inv.status = 'PAID' inv.payment_datetime = datetime.now() inv.save() except FlexipyException as e: get_logger().error("Error during automatic pairing of payments in Flexibee, error was " + str(e))
def create_invoice(self, invoice): """ This method except metrocar Invoice object. It creates invoice in accouting system(Flexibee). :param invoice: metrocar.invoices.models.Invoice object """ #get config conf = self.faktura.conf paid_ammout_sum = Decimal() invoice_items = [] invoice_params = {} for item in invoice.get_items(): #account activity of item activity = item.account_activity # if accountacitivity is negative then it means #that it was already credited(paid) from users account if activity.is_positive() == False: paid_ammout_sum += activity.money_amount it_price = str(item.amount) it = {'kod': 'item' + str(item.id), 'nazev': str(activity.as_concrete_class()), 'typSzbDphK': 'typSzbDph.dphZakl', 'szbDph': '21', 'zdrojProSkl': False, 'ucetni': True, 'cenaMj': it_price, 'typPolozkyK': conf.get_typ_polozky_vydane()[0]} invoice_items.append(it) # i need infromation about address of user for invoice inv_address = invoice.user.get_invoice_address() street = inv_address.street + ' ' + str(inv_address.land_registry_number) address_params = {'nazFirmy': invoice.user.full_name(), 'ulice': street, 'mesto': inv_address.city, 'psc': inv_address.zip_code, 'postovniShodna': True} invoice_params = {'typUcOp': 'code:' + conf.get_typ_ucetni_operace()[0], 'specSym': str(invoice.specific_symbol), 'datSplat': str(invoice.due_date), 'clenDph': 'code:01-02'} invoice_params.update(address_params) # now check if invoice is paid aka money where already taken from user's account if invoice.status == 'PAID': invoice_params['stavUhrK'] = 'stavUhr.uhrazenoRucne' else: #if not paid substract already paid items if paid_ammout_sum != 0: #already paid items declare as already paid it_price = str(paid_ammout_sum) it = {'kod': 'itemUhr', 'nazev': 'J*z uhrazeno z vaseho konta', 'typSzbDphK': 'typSzbDph.dphZakl', 'szbDph': '21', 'zdrojProSkl': False, 'ucetni': True, 'cenaMj': it_price, 'typPolozkyK': conf.get_typ_polozky_vydane()[0]} invoice_items.append(it) try: result = self.faktura.create_vydana_faktura(kod='inv' + str(invoice.id), var_sym=invoice.variable_symbol, datum_vyst=str(invoice.draw_date), dalsi_param=invoice_params, polozky_faktury=invoice_items) if result[0] == True: get_logger().info("Invoice with flexibee id " + str(result[1]) + " was successfully created.") else: get_logger().error("Invoice was not created in Flexibee. Errors are " + str(result[2])) except FlexipyException as e: get_logger().error("Error during creation of invoice in Flexibee, error was " + str(e))
def create_invoice(self, invoice): """ This method except metrocar Invoice object. It creates invoice in accouting system(Flexibee). :param invoice: metrocar.invoices.models.Invoice object """ #get config conf = self.faktura.conf paid_ammout_sum = Decimal() invoice_items = [] invoice_params = {} for item in invoice.get_items(): #account activity of item activity = item.account_activity # if accountacitivity is negative then it means #that it was already credited(paid) from users account if activity.is_positive() == False: paid_ammout_sum += activity.money_amount it_price = str(item.amount) it = { 'kod': 'item' + str(item.id), 'nazev': str(activity.as_concrete_class()), 'typSzbDphK': 'typSzbDph.dphZakl', 'szbDph': '21', 'zdrojProSkl': False, 'ucetni': True, 'cenaMj': it_price, 'typPolozkyK': conf.get_typ_polozky_vydane()[0] } invoice_items.append(it) # i need infromation about address of user for invoice inv_address = invoice.user.get_invoice_address() street = inv_address.street + ' ' + str( inv_address.land_registry_number) address_params = { 'nazFirmy': invoice.user.full_name(), 'ulice': street, 'mesto': inv_address.city, 'psc': inv_address.zip_code, 'postovniShodna': True } invoice_params = { 'typUcOp': 'code:' + conf.get_typ_ucetni_operace()[0], 'specSym': str(invoice.specific_symbol), 'datSplat': str(invoice.due_date), 'clenDph': 'code:01-02' } invoice_params.update(address_params) # now check if invoice is paid aka money where already taken from user's account if invoice.status == 'PAID': invoice_params['stavUhrK'] = 'stavUhr.uhrazenoRucne' else: #if not paid substract already paid items if paid_ammout_sum != 0: #already paid items declare as already paid it_price = str(paid_ammout_sum) it = { 'kod': 'itemUhr', 'nazev': 'J*z uhrazeno z vaseho konta', 'typSzbDphK': 'typSzbDph.dphZakl', 'szbDph': '21', 'zdrojProSkl': False, 'ucetni': True, 'cenaMj': it_price, 'typPolozkyK': conf.get_typ_polozky_vydane()[0] } invoice_items.append(it) try: result = self.faktura.create_vydana_faktura( kod='inv' + str(invoice.id), var_sym=invoice.variable_symbol, datum_vyst=str(invoice.draw_date), dalsi_param=invoice_params, polozky_faktury=invoice_items) if result[0] == True: get_logger().info("Invoice with flexibee id " + str(result[1]) + " was successfully created.") else: get_logger().error( "Invoice was not created in Flexibee. Errors are " + str(result[2])) except FlexipyException as e: get_logger().error( "Error during creation of invoice in Flexibee, error was " + str(e))
@property def amount(self): """ Returns amount of money """ return abs(self.account_activity.money_amount) def amount_with_tax(self): """ Returns item's amount of money with tax added """ tax = abs(self.amount) * Decimal( self.invoice.user.home_subsidiary.tax_rate / 100) return abs(self.amount) + tax signals.post_save.connect(InvoiceItem.objects.create_for_invoice, Invoice) if settings.ACCOUNTING_ENABLED: try: accounting = importlib.import_module( settings.ACCOUNTING['IMPLEMENTATION']) account_instance = accounting.get_accounting_instance() signals.post_delete.connect(account_instance.delete_invoice_receiver, Invoice) signals.post_save.connect(account_instance.save_invoice_receiver, Invoice) except ImportError, ex: get_logger().error( "Can't import accounting implementation from settings")