Beispiel #1
0
    def post(self, request, pk, *args, **kwargs):
        """
        Parses the income statement and balance sheet sheet request, sent in the form of:
         {"IncomeStatement": [{
                "Period": "2016-01",
                "Account": "Value"},{..}]
            }
        """
        try:
            company = AccountsUtils.get_company(pk)

            try:
                entries, error_tags = AccountingUtils.parse_statement(request, company, request.data,
                                                                      FinancialStatementEntry.INCOME_STATEMENT)
                FinancialStatementEntry.objects.bulk_create(entries)
            except Exception as e:
                error = ["%s" % e]
                return Utils.dispatch_failure(request, 'DATA_PARSING_ISSUE', error)

            serializer = FinancialStatementEntrySerializer(entries, many=True)
            if len(serializer.data) > 0:
                return Utils.dispatch_success(request, serializer.data)
            return Utils.dispatch_success(request, 'NO_DATA_CHANGES')
        except Exception as e:
            return Utils.dispatch_failure(request, 'INTERNAL_SERVER_ERROR')
Beispiel #2
0
    def connect(self, request, company):
        """
           Connects a company to Xero
           company must be included in the querystring /?company=<id>
        """
        try:
            secret_keys = Utils.get_access_keys(company)

            consumer_key = secret_keys.client_id
            consumer_secret = secret_keys.client_secret

            global credentials
            call_back_uri = settings.XERO_CALL_BACK_URI + "/" + company

            # call_back_url = 'http://localhost/oauth'
            if AccountingConfiguration.PRIVATE == secret_keys.type:
                credentials = PrivateCredentials(consumer_key=consumer_key,rsa_key=consumer_secret)
                OAUTH_PERSISTENT_SERVER_STORAGE.update({'consumer_key':credentials.consumer_key})
                OAUTH_PERSISTENT_SERVER_STORAGE.update({'rsa_key':credentials.rsa_key})
                url = call_back_uri
            else:
                credentials = PublicCredentials(consumer_key, consumer_secret, callback_uri=call_back_uri)
                # Save generated credentials details to persistent storage
                for key, value in credentials.state.items():
                    OAUTH_PERSISTENT_SERVER_STORAGE.update({key: value})

                LoginInfo.objects.create(company_id=company, status=LoginInfo.IN_PROGRESS, created=timezone.now())
                url = credentials.url

        except Exception as e:
            auth_cancel_url = settings.QBO_AUTH_CANCEL_URL
            Utils.send_company_misconfig(company,e)
            return redirect(auth_cancel_url + '/error')
        return Utils.redirect_response(url)
    def connect(self, request, company_id):
        """
           Connects a company to quickbooks
           company must be included in the querystring /?company=<id>
           :param company_id:
           :return: Redirect url of QuickBook
        """
        try:
            if not getDiscoveryDocument:
                # todo: need to clarify this scenario occurs or not and handle correct redirct urls
                auth_cancel_url = settings.QBO_AUTH_CANCEL_URL
                return redirect(auth_cancel_url)
            url = getDiscoveryDocument.auth_endpoint

            configuration = Utils.get_access_keys(company_id)
            client_id = configuration.client_id

            params = {
                'scope': settings.ACCOUNTING_SCOPE,
                'redirect_uri': settings.REDIRECT_URI,
                'response_type': 'code',
                'state': company_id,
                'client_id': client_id
            }
            url += '?' + urllib.urlencode(params)
            LoginInfo.objects.create(company_id=company_id,
                                     status=LoginInfo.IN_PROGRESS,
                                     created=timezone.now())
            return redirect(url)
        except Exception as e:
            auth_cancel_url = settings.QBO_AUTH_CANCEL_URL
            Utils.send_company_misconfig(company_id, e)
            return redirect(auth_cancel_url + '/error')
    def trail_balance(self, pk, request):
        """
        Get the trail balance profile from Quick Books
        :param pk: company: Company ID
        :return: Response of trail balance
        """
        try:
            meta = CompanyMeta.objects.filter(company_id=pk).first()

            if meta.monthly_reporting_current_period:
                st = time.time()

                # this will grab the trial balance for the companymeta.monthly_reporting_current_period
                # plus 23 more months worth of history.
                job = group(
                    trial_balance_for_period.s(pk, i) for i in range(0, 23))
                result = job.apply_async()
            else:
                return Utils.dispatch_failure(
                    request, 'MISSING_MONTHLY_REPORTING_CURRENT_PERIOD')

            # note: this bit of code basically turns this into a synchronous call, this is intended behaviour for now
            #       todo: phase 2 we need to add sockets for better communication with UI
            while not result.ready():
                continue

            print('##### CELERY get TB now takes {:.2f}s'.format(time.time() -
                                                                 st))
            return Utils.dispatch_success(request,
                                          'TRIAL_BALANCE_RECEIVED_SUCCESS')
        except Exception as e:
            return Utils.dispatch_failure(request, 'INTERNAL_SERVER_ERROR')
Beispiel #5
0
    def get(self, request, pk, report_identifier):
        """
        Gets a Company's Questionnaire answers for the requested period

        If called with no period specified, it simply returns a blank set of questions. The functionality supports
        the UI which dynamically displays the questions returned by the server.
        """
        try:
            response = None
            response_status = status.HTTP_200_OK

            context = {'request': request,
                       'company': pk,
                       'period': report_identifier}
            print('############### BEFORE INT COMPARISON')
            # todo: logic needs to be cleaned up. questions and has_answers have overlapping functionality that can be
            #       simplified

            questions = ReportingUtils.get_questionnaire_objects(pk, report_identifier)
            has_answers = ReportingUtils.has_answers_for_period(pk, report_identifier)

            if questions and has_answers:
                # return Q n A for requested period.
                serializer = QuestionWithAnswerSerializer(questions, many=True, context=context)
                if len(serializer.data) > 0:
                    return Utils.dispatch_success(request,serializer.data)
                return Utils.dispatch_success(request,'NO_ANSWER_FOUND')
            return Utils.dispatch_success (request, 'DATA_NOT_FOUND')
        except Exception as e:
            return Utils.dispatch_failure(request,'INTERNAL_SERVER_ERROR')
Beispiel #6
0
    def get(self, request, pk):
        """
        Gets a Company's Questionnaire answers
        """
        try:
            response = None
            response_status = status.HTTP_200_OK

            context = {'request': request,
                       'company': pk,
                       }

            # get an empty set of questions
            qs1 = Question.objects.filter(Q(common_to_all_companies=True, show_on_ui=True) |
                                          Q(common_to_all_companies=False,show_on_ui=True,company=pk))\
                                          .all()

            qs1 = ReportingUtils.sanitize_next_questions(qs1)

            serializer = QuestionWithAnswerSerializer(qs1, many=True, context=context)
            if len (serializer.data) > 0:
                return Utils.dispatch_success (request,serializer.data)
            return Utils.dispatch_success (request,'NO_ANSWER_FOUND')
        except Exception as e:
            return Utils.dispatch_failure(request,'INTERNAL_SERVER_ERROR')
Beispiel #7
0
    def put(self, request, pk, report_identifier, *args, **kwargs):
        """
        Updates a Company's Monthly Report instance Monthly Report Period or Monthly Report ID
        """
        try:
            company = AccountsUtils.get_company(pk)
            if '-' in report_identifier:
                monthly_report = ReportingUtils.get_monthly_report(pk=pk, period=report_identifier)
            else:
                monthly_report = ReportingUtils.get_monthly_report(pk=pk, report_id=report_identifier)
            response_status = status.HTTP_200_OK  # default to OK and override if not

            if monthly_report:
                data = request.data
                data['company'] = company.id
                serializer = MonthlyReportSerializer(monthly_report, data=data,
                                                     context={'request': request, 'company_id': pk}, partial=True)

                if serializer.is_valid():
                    serializer.save()
                    return Utils.dispatch_success(request,serializer.data)
                else:
                    return Utils.dispatch_failure (request,'VALIDATION_ERROR',serializer.errors)

            return Utils.dispatch_failure(request,'MONTHLY_REPORT_NOT_FOUND')
        except Exception as e:
            return Utils.dispatch_failure (request,'INTERNAL_SERVER_ERROR')
Beispiel #8
0
def trial_balance_for_period(pk, period_offset):
    cm = CompanyMeta.objects.filter(company_id=pk).first()
    cm.save()

    company = AccountsUtils.get_company(pk)
    st = time.time()
    credentials = AccountingUtils.get_credentials_by_company(company)
    if not credentials:
        return

    if not cm.monthly_reporting_current_period:
        return

    if company.accounting_type.lower() == Company.QUICKBOOKS.lower():
        period = cm.monthly_reporting_current_period - relativedelta(
            months=+period_offset, day=31)
        # print('##### Getting TRIAL BALANCE for period ', period)

        query = '?start_date=' + period.strftime(
            '%Y-%m-1') + '&end_date=' + period.strftime('%Y-%m-%d')
        # print('####### QBO TB QUERY ', query)
        # for query in query_list:
        trial_balance_response, status_code = Utils.get_trial_balance(
            credentials.accessToken, credentials.realmId, query)
        if status_code >= 400:
            bearer = Utils.get_bearer_token_from_refresh_token(
                credentials.refreshToken)
            new_credentials = AccountingUtils.updateAccountingSession(
                company, bearer.accessToken, bearer.refreshToken,
                credentials.realmId)
            trial_balance_response, status_code = Utils.get_trial_balance(
                new_credentials.accessToken, new_credentials.realmId, query)
            if status_code >= 400:
                return

        from .third_party.quickbooks import QuickBooks
        entries = QuickBooks.save_trial_balance(company,
                                                trial_balance_response)
        TrialBalance.objects.bulk_create(entries)

    if company.accounting_type.lower() == Company.XERO.lower():
        period = cm.monthly_reporting_current_period - relativedelta(
            months=+period_offset, day=31)
        # params = {'fromDate': str(period.strftime('%Y-%m-01')), 'toDate': str(period.strftime('%Y-%m-%d'))}
        params = {'date': str(period.strftime('%Y-%m-%d'))}
        auth = Utils.get_xero_auth(pk)
        credentials = Utils.get_xero_credentials(pk, **auth)
        xero = Xero(credentials)
        trialbalance = xero.reports.get('TrialBalance', params=params)
        XeroAccountings.save_trial_balance(company, trialbalance[0])

    # print('{:.2f}s Elapsed'.format(time.time() - st))

    # print('Took {:.2f}s Total'.format(time.time() - st))

    cm.trialbalance_last_refresh_date = datetime.datetime.now()
    cm.trialbalance_dl_complete = True
    cm.save()

    return
    def auth_code_handler(self, request, pk=None):
        """
            Handles the authentication Code from quickbooks redirect
            :param pk: Company ID
            :param request:
            :return:
        """
        try:
            state = request.GET.get('state', None)
            error = request.GET.get('error', None)
            auth_cancel_url = settings.QBO_AUTH_CANCEL_URL
            print('############ auth code handler state ', state)

            if error == 'access_denied':
                print('############ auth code handerl access deined ', error)
                return redirect(auth_cancel_url)
            if state is None:
                return redirect(auth_cancel_url)

            auth_code = request.GET.get('code', None)
            print('############ auth code handerl code ', auth_code)
            if auth_code is None:
                return redirect(auth_cancel_url)

            company = AccountsUtils.get_company(state)
            bearer = Utils.get_bearer_token(auth_code)
            realmId = request.GET.get('realmId', None)
            AccountingUtils.updateAccountingSession(company,
                                                    bearer.accessToken,
                                                    bearer.refreshToken,
                                                    realmId)
            qb_status = LoginInfo.objects.filter(
                company=company,
                status=LoginInfo.IN_PROGRESS,
                created__range=[
                    timezone.now() - datetime.timedelta(minutes=10),
                    timezone.now()
                ]).first()
            qb_status.status = LoginInfo.COMPLETED

            # todo: change this env variable for production
            #qbo_auth_redirect_url = os.environ.get('QBO_AUTH_REDIRECT_URL')
            auth_redirect_url = settings.QBO_AUTH_REDIRECT_URL

            #auth_redirect_url = os.environ.get ('QBO_AUTH_REDIRECT_URL','http://ec2-52-207-28-114.compute-1.amazonaws.com/IX/coa-match/quickbooks')

            return redirect(auth_redirect_url)

            #return Utils.dispatch_success(request,"successfully authenticated")
        except Exception as e:
            # todo: need to clarify this scenario occurs or not and handle correct redirect urls
            auth_cancel_url = settings.QBO_AUTH_CANCEL_URL
            Utils.send_company_misconfig(pk, e)
            return redirect(auth_cancel_url + '/error')
Beispiel #10
0
    def post(self, request, pk, *args, **kwargs):
        try:
            company = AccountsUtils.get_company(pk)
            # print('CoAMap POST - request.data ', request.data)
            updated_maps = AccountingUtils.set_coa_map(company, request.data)
            serializer = UpdatedCoAMapSerializer(updated_maps, many=True)
            if len(serializer.data):
                return Utils.dispatch_success(request, serializer.data)
            return Utils.dispatch_success(request, "NO_DATA_CHANGES")

        except Exception as e:
            return Utils.dispatch_failure(request, 'INTERNAL_SERVER_ERROR')
Beispiel #11
0
 def get(self, request, *args, **kwargs):
     try:
         company_id = request.GET.get('company', None)
         # Check company is exists
         is_valid_company, message = Utils.check_company_exists(company_id)
         if not is_valid_company:
             return Utils.dispatch_failure(request, "RESOURCE_NOT_FOUND")
         return Accounting().get_instance_by_id(company_id).connect(request, company_id)
     except KeyError:
         return redirect(request.META["HTTP_REFERRER"])
     except Exception as e:
         return Utils.dispatch_failure(request, 'INTERNAL_SERVER_ERROR')
Beispiel #12
0
    def get(self, request, pk, *args, **kwargs):
        """
        Lists all monthly reports for the specified companies
        """
        try:
            self.queryset = MonthlyReport.objects.filter(company=pk).order_by('period_ending')

            if len (self.queryset) == 0:
                return Utils.dispatch_success(request,'DATA_NOT_FOUND')
            return super(MonthlyReportList, self).get(request)
        except Exception:
            return Utils.dispatch_failure(request, 'INTERNAL_SERVER_ERROR')
Beispiel #13
0
 def delete(self, request, pk, *args, **kwargs):
     try:
         if self.request.user.is_superuser:
             company = AccountsUtils.get_company(pk)
             if TrialBalance.objects.filter(company=company).count():
                 TrialBalance.objects.filter(company=company).delete()
                 return Utils.dispatch_success(request, 'DELETED_SUCCESSFULLY')
             else:
                 return Utils.dispatch_failure(request, "OBJECT_RESOURCE_NOT_FOUND")
         return Utils.dispatch_failure(request, 'UNAUTHORIZED_ACCESS')
     except Exception as e:
         return Utils.dispatch_failure(request, 'INTERNAL_SERVER_ERROR')
Beispiel #14
0
 def put(self, request, pk, *args, **kwargs):
     """
     Updates verified by user in CoAMap for a company in the database
     """
     try:
         company = AccountsUtils.get_company(pk)
         coamap = CoAMap.objects.filter(company_id=company)
         for entry in coamap:
             entry.verified_by_user = False
             entry.save()
         return Utils.dispatch_success(request, 'COAMAP_UPDATED_SUCCESSFULLY')
     except Exception as e:
         return Utils.dispatch_failure(request, 'INTERNAL_SERVER_ERROR')
Beispiel #15
0
 def get_instance_by_id(self, company_id):
     """
     This Wrapper method returns the object of the class for using in accounting system
     :param accounting_type:Name of the accounting system
     :return: Object of the accounting system to be accessed
     """
     accounting_type = Utils.capitalize(
         Utils.get_accounting_type(company_id))
     if accounting_type == Company.QUICKBOOKS:
         return QuickBooks()
     elif accounting_type == Company.XERO:
         return XeroAccountings()
     elif accounting_type == Company.SAGE:
         return SageAccountings()
Beispiel #16
0
    def trail_balance(self, id, request):
        """
        Get Trail Balance From Database
        :param id: Company Id
        :return: Response
        """
        try:
            entries = TrialBalance.objects.filter(company=id)
            serializer = TrialBalanceSerializer(entries, many=True)
            if len(serializer.data) > 0:
                return Utils.dispatch_success(request, serializer.data)
            return Utils.dispatch_success(request, 'NO_DATA_CHANGES')

        except Exception:
            return Utils.dispatch_failure(request, "INTERNAL_SERVER_ERROR")
Beispiel #17
0
 def delete(self, request, pk, *args, **kwargs):
     try:
         if self.request.user.is_superuser:
             company = AccountsUtils.get_company(pk)
             if FinancialStatementEntry.objects.filter(company=company,
                                                       statement_type=FinancialStatementEntry.INCOME_STATEMENT,
                                                       ).count():
                 FinancialStatementEntry.objects.filter(company=company,
                                                        statement_type=FinancialStatementEntry.INCOME_STATEMENT,
                                                        ).delete()
                 return Utils.dispatch_success(request, 'DELETED_SUCCESSFULLY')
             return Utils.dispatch_success(request, "DATA_NOT_FOUND")
         return Utils.dispatch_failure(request, 'UNAUTHORIZED_ACCESS')
     except Exception as e:
         return Utils.dispatch_failure(request, 'INTERNAL_SERVER_ERROR')
Beispiel #18
0
    def get(self, request, pk, report_identifier, *args, **kwargs):
        """
        Gets a Company's Monthly Report instance by Monthly Report Period or Monthly Report ID
        """
        try:
            if '-' in report_identifier:
                monthly_report = ReportingUtils.get_monthly_report(pk=pk, period=report_identifier)
            else:
                monthly_report = ReportingUtils.get_monthly_report(pk=pk, report_id=report_identifier)

            if monthly_report:
                serializer = MonthlyReportSerializer(monthly_report, context={'request': request, 'company_id': pk})
                return Utils.dispatch_success(request,serializer.data)
            return Utils.dispatch_failure(request,'MONTHLY_REPORT_NOT_FOUND')
        except Exception as e:
            return Utils.dispatch_failure (request,'INTERNAL_SERVER_ERROR')
Beispiel #19
0
    def has_permission(self, request, view):
        try:
            split_url = request.META.get('PATH_INFO').split("/")

            if split_url[3] == "docs":
                return request.user.is_authenticated()

            if len(view.kwargs) == 0 or split_url[3] != "company":
                if request.user.is_superuser:
                    return request.user and request.user.is_authenticated()
                else:
                    raise UnauthorizedAccess

            is_valid_company, message = Utils.check_company_exists(view.kwargs["pk"])
            if not is_valid_company:
                raise ResourceNotFound

            if request.user.is_superuser:
                return request.user and request.user.is_authenticated()
            else:

                return ((request.user.is_superuser or request.user.company.id == int(
                    view.kwargs["pk"])) and request.user.is_authenticated())

        except APIException as err:
            raise err
Beispiel #20
0
 def get(self, request, pk, *args, **kwargs):
     """
     Check to see if the Accounting System token is still valid for the company
     """
     try:
         return Accounting().get_instance_by_id(pk).is_token_valid(pk, request)
     except Exception as e:
         return Utils.dispatch_failure(request, 'INTERNAL_SERVER_ERROR')
Beispiel #21
0
    def post(self, request, pk, *args, **kwargs):
        """
        Starts a new monthly report for the current reporting period, and moves next period ahead by 1 month to prepare
        for the next time. Will not create one that already exists, or create another one until the previous one
        is completed, this is a business rule.
        """
        try:
            company = AccountsUtils.get_company(pk)
            response_status = status.HTTP_200_OK
            response = ''

            meta = CompanyMeta.objects.filter(company_id=pk).first()
            current_period = meta.monthly_reporting_current_period
            next_period = meta.monthly_reporting_next_period

            if current_period is None:
                Utils.send_company_meta(request.user,"PERIOD")
                return Utils.dispatch_failure(request,'MISSING_MONTHLY_REPORTING_CURRENT_PERIOD')

            try:
                # does one exist for the current period
                report = MonthlyReport.objects.filter(company=company, period_ending=current_period).first()
                print('######## CURR AND NEXT - start as: c: ', current_period, ' n: ', next_period, ' rpt: ', report)
            except Exception as e:
                error = ["%s" % e]
                return Utils.dispatch_failure (request,'DATA_PARSING_ISSUE', error)


            # if it doesn't exist, or if the previous one has been completed, then it's ok to create a new one
            if not report or report.status == 'Complete':
                # todo: Due date is not relevant, remove it. We allow them to report any time after the end of the current
                # during initial setup, we do not advance the reporting dates. There is no initial setup for Form Entry
                # aka manual reporting
                if not meta.is_initial_setup:
                    print('#### moving period forward for new monthly report')
                    current_period = next_period
                    next_period = next_period + relativedelta(months=+1, day=31)
                    meta.monthly_reporting_current_period = current_period
                    meta.monthly_reporting_next_period = next_period
                    meta.monthly_reporting_current_period_status = 'IN_PROGRESS'
                    meta.save()
                    print('######## CURR AND NEXT - not initial setup, after move forward ', current_period, next_period)

                print('#### creating new monthly report for current period = ', meta.monthly_reporting_current_period)
                report = MonthlyReport(status='In Progress', company_id=pk, period_ending=current_period)
                report.save()

                response = serializers.serialize('json', [report, ])
                # return response
                return Utils.dispatch_success(request,[response])
            else:
                # was using HTTP_304_NOT_MODIFIED, but when this status is returned the JSON message is null which causes
                # problems for the UI
                # 409 causes the UI to stop processing because it thinks theres an error, but there isn't one.
                # so changing to 200 OK instead since it's OK to move forward
                # response_status = status.HTTP_409_CONFLICT
                return Utils.dispatch_success(request,'MONTHLY_REPORT_ALREADY_EXISTS_WITH_INPROGRESS')

        except Exception as e:
            return Utils.dispatch_failure (request,'INTERNAL_SERVER_ERROR')
Beispiel #22
0
    def get(self, request, pk, *args, **kwargs):
        """
        Gets the Balance Sheet Financial Statement Entries from the database
        Range can be specified by adding ?start_date=YYYY-MM-DD&end_date=YYYY-MM-DD

        No date params will return all entries for the specified company.
        end_date param only will provide data for that specific period.
        A start_date without an end_date, it will cause an error.
        """
        try:
            company = AccountsUtils.get_company(pk)

            # todo: query variable is never used, and appears to be unncessary
            query, dates = Utils.validate_query(request, dateformat=True)

            # todo: figure out why order_by isn't workin on these query_sets, ordering added to model as workaround
            if not dates:
                print('########### not dates')
                queryset = FinancialStatementEntry.objects.filter(company=company,
                                                                  statement_type=FinancialStatementEntry.BALANCE_SHEET)
            else:
                if dates[0] == 'ERROR':
                    return Utils.dispatch_failure(request, dates[1])
                elif len(dates) == 2:
                    queryset = FinancialStatementEntry.objects.filter(company=company,
                                                                      period_ending__range=(dates[0], dates[1]),
                                                                      statement_type=FinancialStatementEntry.BALANCE_SHEET,
                                                                      )
                elif len(dates) == 1:
                    print(dates)
                    queryset = FinancialStatementEntry.objects.filter(company=company,
                                                                      period_ending=dates[0],
                                                                      statement_type=FinancialStatementEntry.BALANCE_SHEET,
                                                                      )
                else:
                    print(dates)
                    queryset = FinancialStatementEntry.objects.filter(company=company,
                                                                      statement_type=FinancialStatementEntry.BALANCE_SHEET)

            if queryset:
                serializer = FinancialStatementEntrySerializer(queryset, many=True)
                return Utils.dispatch_success(request, serializer.data)
            return Utils.dispatch_success(request, 'DATA_NOT_FOUND')
        except Exception as e:
            return Utils.dispatch_failure(request, 'INTERNAL_SERVER_ERROR')
Beispiel #23
0
 def get(self, request, pk, *args, **kwargs):
     """
     Gets the trial balance from online and writes to database
     """
     # Check company is exists
     try:
         return Accounting().get_instance_by_id(pk).trail_balance(pk, request)
     except Exception as e:
         return Utils.dispatch_failure(request, 'INTERNAL_SERVER_ERROR')
Beispiel #24
0
    def get(self, request, pk, *args, **kwargs):
        """
        Gets the Income Statement Financial Statement Entries from the database
        Range can be specified by adding ?start_date=YYYY-MM-DD&end_date=YYYY-MM-DD


        No date params will return all entries for the specified company.
        end_date param only will provide data for that specific period.
        A start_date without an end_date, it will cause an error.
        """
        try:
            company = AccountsUtils.get_company(pk)

            query, dates = Utils.validate_query(request, dateformat=True)

            if not dates:
                queryset = FinancialStatementEntry.objects.filter(company=company,
                                                                  statement_type=FinancialStatementEntry.INCOME_STATEMENT)
            else:
                if dates[0] == 'ERROR':
                    return Utils.dispatch_failure(request, dates[1])
                elif len(dates) == 2:
                    queryset = FinancialStatementEntry.objects.filter(company=company,
                                                                      period_ending__range=(dates[0], dates[1]),
                                                                      statement_type=FinancialStatementEntry.INCOME_STATEMENT,
                                                                      )
                elif len(dates) == 1:
                    queryset = FinancialStatementEntry.objects.filter(company=company,
                                                                      period_ending=dates[0],
                                                                      statement_type=FinancialStatementEntry.INCOME_STATEMENT,
                                                                      )
                else:
                    queryset = FinancialStatementEntry.objects.filter(company=company,
                                                                      statement_type=FinancialStatementEntry.INCOME_STATEMENT)

            queryset = queryset.order_by('value')

            if queryset:
                serializer = FinancialStatementEntrySerializer(queryset, many=True)
                return Utils.dispatch_success(request, serializer.data)
            return Utils.dispatch_success(request, 'DATA_NOT_FOUND')

        except Exception as e:
            return Utils.dispatch_failure(request, 'INTERNAL_SERVER_ERROR')
    def save_trial_balance(company, response):
        """
        Parses the quickbooks JSON Response of the trial balance
        follows the format provided here https://developer.intuit.com/docs/api/accounting/trial%20balance
        :param company:
        :param response:
        :return: trial_balances
        """
        period = Utils.format_period(response["Header"]["EndPeriod"])

        currency = response["Header"]["Currency"]
        headers = [
            column["ColTitle"]
            if column["ColTitle"] != "" else column["ColType"]
            for column in response["Columns"]["Column"]
        ]
        entries = []

        if response["Rows"]:
            for row in response["Rows"]["Row"]:
                d = {}

                if 'ColData' in row:

                    for i in range(len(row["ColData"])):
                        d[headers[i]] = row["ColData"][i]["value"]
                        if i == 0:
                            d['id'] = row["ColData"][i]["id"]

                    d['Debit'] = float(d["Debit"]) if d["Debit"] != "" else 0
                    d['Credit'] = float(
                        d["Credit"]) if d["Credit"] != "" else 0

                    rows_affected = TrialBalance.objects.filter(
                        company=company, period=period,
                        gl_account_id=d["id"]).update(
                            debit=d["Debit"],
                            credit=d["Credit"],
                            gl_account_name=d["Account"])
                    if rows_affected == 0:
                        entry = TrialBalance(company=company,
                                             gl_account_name=d["Account"],
                                             debit=d["Debit"],
                                             credit=d["Credit"],
                                             period=period,
                                             currency=currency,
                                             gl_account_id=d["id"])

                        entries.append(entry)

                else:
                    print("Dont process the row")

        #TrialBalance.objects.bulk_create(entries)

        return entries
Beispiel #26
0
    def delete(self, request,pk, report_identifier, *args, **kwargs):
        """
        Updates a Company's Monthly Report instance Monthly Report Period or Monthly Report ID
        """
        try:
            # TODO: Can you delete monthly reports? pls confirm
            if self.request.user.is_superuser:
                if '-' in report_identifier:
                    monthly_report = ReportingUtils.get_monthly_report(pk=pk, period=report_identifier)
                else:
                    monthly_report = ReportingUtils.get_monthly_report(pk=pk, report_id=report_identifier)
                if monthly_report:
                    monthly_report.delete()
                    return Utils.dispatch_success(request,'DELETED_SUCCESSFULLY')
                return Utils.dispatch_failure(request, 'MONTHLY_REPORT_NOT_FOUND')
            return Utils.dispatch_failure(request,'UNAUTHORIZED_ACCESS')

        except Exception as e:
            return Utils.dispatch_failure (request,'INTERNAL_SERVER_ERROR')
Beispiel #27
0
 def get(self, request, pk, *args, **kwargs):
     """
     Gets the Chart of accounts from online and writes to database
     """
     # Check company is exists
     try:
         return Accounting().get_instance_by_id(pk).chart_of_accounts(pk, request)
     except Exception as e:
         print(e)
         return Utils.dispatch_failure(request, 'INTERNAL_SERVER_ERROR')
    def disconnect(self, pk, request):
        """
        Disconnect the QuickBooks
        :param pk: Company ID
        :return: Response
        """
        company = AccountsUtils.get_company(pk)

        credentials = AccountingUtils.get_credentials_by_company(company)
        try:
            revoke_response = Utils.revoke_token(credentials.accessToken)
            if "Token is incorrect" in revoke_response:
                return Utils.dispatch_failure(request,
                                              "NO_TOKEN_AUTHENTICATION")
            return Utils.dispatch_success(request, "REVOKE_SUCCESSFULL")

        except Exception as e:
            print(e)
            return Utils.dispatch_failure(request, "NO_TOKEN_AUTHENTICATION")
 def is_token_valid(self, pk, request):
     """
     Check the validity of Token
     :param pk: Company ID
     :return: Response of validation
     """
     try:
         company = AccountsUtils.get_company(pk)
         credentials = AccountingOauth2.objects.filter(
             company=company).first()
         if credentials:
             sample_response, status_code = Utils.get_company_info(
                 credentials.accessToken, credentials.realmId)
             if status_code >= 400:
                 bearer = get(credentials.refreshToken)
                 new_credentials = AccountingUtils.updateAccountingSession(
                     company, bearer.accessToken, bearer.refreshToken,
                     credentials.realmId)
                 sample_response, status_code = Utils.get_company_info(
                     new_credentials.accessToken, new_credentials.realmId)
                 if status_code >= 400:
                     return Utils.dispatch_failure(
                         request, 'NO_TOKEN_AUTHENTICATION')
             return Utils.dispatch_success(request,
                                           "AUTHENTICATED_SUCCESSFULLY")
         return Utils.dispatch_failure(request, 'NO_TOKEN_AUTHENTICATION')
     except Exception as e:
         return Utils.dispatch_failure(request, 'NO_TOKEN_AUTHENTICATION')
Beispiel #30
0
    def get(self, request, pk, *args, **kwargs):
        """
        Creates the CoAMap for a company from the CoA in the database
        """
        try:
            company = AccountsUtils.get_company(pk)
            coa = CoA.objects.filter(company=company)
            remap = request.GET.get('remap', None)
            if coa:
                default_mappings = DefaultAccountTagMapping.objects.filter(software__iexact=company.accounting_type)

                if not default_mappings:
                    return Utils.dispatch_failure(request, "OBJECT_RESOURCE_NOT_FOUND")

                # todo: make sure abstract financial statement entry tags are not getting processed in the CoA Mapping
                try:
                    entries = AccountingUtils.create_coa_map(request, company, default_mappings, coa, remap)
                except Exception as e:
                    error = ["%s" % e]
                    return Utils.dispatch_failure(request, 'DATA_PARSING_ISSUE', error)

                if len(entries) > 0:
                    serializer = CoAMapSerializer(entries, many=True)
                    return Utils.dispatch_success(request, serializer.data)
                return Utils.dispatch_success(request, "NO_DATA_CHANGES")
            return Utils.dispatch_failure(request, "OBJECT_RESOURCE_NOT_FOUND")

        except Exception as e:
            return Utils.dispatch_failure(request, 'INTERNAL_SERVER_ERROR')