예제 #1
0
 def prepareDealsReport(self, begin, end, account_id, group_dates):
     if account_id == 0:
         self.report_failure.emit(
             g_tr('Reports',
                  "You should select account to create Deals report"))
         return False
     if group_dates == 1:
         self.query = executeSQL(
             self.db, "SELECT asset, "
             "strftime('%s', datetime(open_timestamp, 'unixepoch', 'start of day')) as open_timestamp, "
             "strftime('%s', datetime(close_timestamp, 'unixepoch', 'start of day')) as close_timestamp, "
             "SUM(open_price*qty)/SUM(qty) as open_price, SUM(close_price*qty)/SUM(qty) AS close_price, "
             "SUM(qty) as qty, SUM(fee) as fee, SUM(profit) as profit, "
             "coalesce(100*SUM(qty*(close_price-open_price)-fee)/SUM(qty*open_price), 0) AS rel_profit "
             "FROM deals_ext "
             "WHERE account_id=:account_id AND close_timestamp>=:begin AND close_timestamp<=:end "
             "GROUP BY asset, open_timestamp, close_timestamp "
             "ORDER BY close_timestamp, open_timestamp",
             [(":account_id", account_id), (":begin", begin),
              (":end", end)],
             forward_only=False)
     else:
         self.query = executeSQL(
             self.db,
             "SELECT asset, open_timestamp, close_timestamp, open_price, close_price, "
             "qty, fee, profit, rel_profit FROM deals_ext "
             "WHERE account_id=:account_id AND close_timestamp>=:begin AND close_timestamp<=:end",
             [(":account_id", account_id), (":begin", begin),
              (":end", end)],
             forward_only=False)
     return True
예제 #2
0
def addNewAsset(db, symbol, name, asset_type, isin, data_source=-1):
    _ = executeSQL(
        db, "INSERT INTO assets(name, type_id, full_name, isin, src_id) "
        "VALUES(:symbol, :type, :full_name, :isin, :data_src)",
        [(":symbol", symbol), (":type", asset_type), (":full_name", name),
         (":isin", isin), (":data_src", data_source)])
    db.commit()
    asset_id = readSQL(db, "SELECT id FROM assets WHERE name=:symbol",
                       [(":symbol", symbol)])
    if asset_id is not None:
        logging.info(
            g_tr('', "New asset with id ") + f"{asset_id}" +
            g_tr('', " was added: ") + f"{symbol} - '{name}'")
    else:
        logging.error(g_tr('', "Failed to add new asset: "), + f"{symbol}")
    return asset_id
예제 #3
0
 def deleteOperation(self):
     if QMessageBox().warning(
             None, g_tr('LedgerOperationsView', "Confirmation"),
             g_tr('LedgerOperationsView',
                  "Are you sure to delete selected transacion?"),
             QMessageBox.Yes, QMessageBox.No) == QMessageBox.No:
         return
     index = self.table_view.currentIndex()
     operations_model = self.table_view.model()
     operation_type = operations_model.data(
         operations_model.index(index.row(), 0))
     mapper = self.operations[operation_type][self.OP_MAPPER]
     mapper.model().removeRow(0)
     mapper.model().submitAll()
     self.stateIsCommitted.emit()
     operations_model.select()
예제 #4
0
파일: ledger.py 프로젝트: uMag/ledger
 def setBalancesCurrency(self, currency_id, currency_name):
     if self.balance_currency != currency_id:
         self.balance_currency = currency_id
         balances_model = self.balances_view.model()
         balances_model.setHeaderData(
             balances_model.fieldIndex("balance_adj"), Qt.Horizontal,
             g_tr('Ledger', "Balance, ") + currency_name)
         self.updateBalancesView()
예제 #5
0
파일: ledger.py 프로젝트: uMag/ledger
 def setHoldingsCurrency(self, currency_id, currency_name):
     if self.holdings_currency != currency_id:
         self.holdings_currency = currency_id
         holidings_model = self.holdings_view.model()
         holidings_model.setHeaderData(
             holidings_model.fieldIndex("value_adj"), Qt.Horizontal,
             g_tr('Ledger', "Value, ") + currency_name)
         self.updateHoldingsView()
예제 #6
0
파일: slips.py 프로젝트: grunichev/ledger
 def loadFileSlipJSON(self):
     json_file, _filter = \
         QFileDialog.getOpenFileName(self, g_tr('ImportSlipDialog', "Select file with slip JSON data"),
                                     ".", "JSON files (*.json)")
     if json_file:
         with open(json_file) as f:
             self.slip_json = json.load(f)
         self.parseJSON()
예제 #7
0
    def get_slip(self, timestamp, amount, fn, fd, fp, slip_type):
        date_time = datetime.fromtimestamp(timestamp).strftime('%Y%m%dT%H%M%S')

        session_id = self.get_ru_tax_session()
        if session_id == '':
            return None
        s = requests.Session()
        s.headers['ClientVersion'] = '2.9.0'
        s.headers['Device-Id'] = str(uuid.uuid1())
        s.headers['Device-OS'] = 'Android'
        s.headers['sessionId'] = session_id
        s.headers['Content-Type'] = 'application/json; charset=UTF-8'
        s.headers['Accept-Encoding'] = 'gzip'
        s.headers['User-Agent'] = 'okhttp/4.2.2'
        payload = '{' + f'"qr": "t={date_time}&s={amount:.2f}&fn={fn}&i={fd}&fp={fp}&n={slip_type}"' + '}'
        response = s.post('https://irkkt-mobile.nalog.ru:8888/v2/ticket',
                          data=payload)
        if response.status_code != 200:
            if response.status_code == 401 and response.text == "Session was not found":
                self.refresh_session()
            else:
                logging.error(
                    g_tr('SlipsTaxAPI', "Get ticket id failed: ") +
                    f"{response}/{response.text} for {payload}")
            return None
        logging.info(g_tr('SlipsTaxAPI', "Slip found: " + response.text))
        json_content = json.loads(response.text)
        if json_content[
                'status'] != '2':  # Valid slip status is 2, other statuses are not fully clear
            logging.warning(
                g_tr(
                    'ImportSlipDialog',
                    "Operation might be pending on server side. Try again later."
                ))
            return None
        url = "https://irkkt-mobile.nalog.ru:8888/v2/tickets/" + json_content[
            'id']
        response = s.get(url)
        if response.status_code != 200:
            logging.error(
                g_tr('SlipsTaxAPI', "Get ticket failed: ") +
                f"{response}/{response.text}")
            return None
        logging.info(g_tr('SlipsTaxAPI', "Slip loaded: " + response.text))
        slip_json = json.loads(response.text)
        return slip_json
예제 #8
0
 def storeIBAsset(self, IBasset):
     asset_id = readSQL(self.db, "SELECT id FROM assets WHERE name=:symbol",
                        [(":symbol", IBasset.symbol)])
     if asset_id is not None:
         return asset_id
     try:
         asset_type = IBKR.AssetType[IBasset.assetCategory]
     except:
         logging.error(
             g_tr('StatementLoader', "Asset type ") +
             f"{IBasset.assetCategory}" +
             g_tr('StatementLoader', " is not supported"))
         return None
     if IBasset.subCategory == "ETF":
         asset_type = PredefinedAsset.ETF
     return addNewAsset(IBasset.symbol, IBasset.description, asset_type,
                        IBasset.isin)
예제 #9
0
 def loadIBCorpAction(self, IBCorpAction):
     if IBCorpAction.code == Code.CANCEL:
         logging.warning(
             g_tr('StatementLoader', "*** MANUAL ACTION REQUIRED ***"))
         logging.warning(
             f"Corporate action cancelled {IBCorpAction.type} for account "
             f"{IBCorpAction.accountId} ({IBCorpAction.currency}): {IBCorpAction.actionDescription}"
         )
         logging.warning(
             f"@{IBCorpAction.dateTime} for {IBCorpAction.symbol}: Qty {IBCorpAction.quantity}, "
             f"Value {IBCorpAction.value}, Type {IBCorpAction.type}, Code {IBCorpAction.code}"
         )
         return
     if IBCorpAction.assetCategory == AssetClass.STOCK and (
             IBCorpAction.type == Reorg.MERGER
             or IBCorpAction.type == Reorg.SPINOFF):
         account_id = self.findAccountID(IBCorpAction.accountId,
                                         IBCorpAction.currency)
         if account_id is None:
             logging.error(
                 g_tr('StatementLoader', "Account ") +
                 f"{IBCorpAction.accountId} ({IBCorpAction.currency})" +
                 g_tr('StatementLoader', " not found. Skipping trade #") +
                 f"{IBCorpAction.transactionID}")
             return
         asset_id = self.findAssetID(IBCorpAction.symbol)
         timestamp = int(IBCorpAction.dateTime.timestamp())
         settlement = timestamp
         if IBCorpAction.transactionID:
             number = IBCorpAction.transactionID
         else:
             number = ""
         qty = IBCorpAction.quantity
         self.createTrade(account_id, asset_id, timestamp, settlement,
                          number, qty, 0, 0)
     logging.warning(
         g_tr('StatementLoader', "*** MANUAL ACTION REQUIRED ***"))
     logging.warning(
         f"Corporate action {IBCorpAction.type} for account "
         f"{IBCorpAction.accountId} ({IBCorpAction.currency}): {IBCorpAction.actionDescription}"
     )
     logging.warning(
         f"@{IBCorpAction.dateTime} for {IBCorpAction.symbol}: Qty {IBCorpAction.quantity}, "
         f"Value {IBCorpAction.value}, Type {IBCorpAction.type}, Code {IBCorpAction.code}"
     )
예제 #10
0
 def loadIBFee(self, fee):
     account_id = self.findAccountID(fee.accountId, fee.currency)
     if account_id is None:
         logging.error(g_tr('StatementLoader', "Account ") + f"{fee.accountId} ({fee.currency})" +
                       g_tr('StatementLoader', " not found. Skipping fee #") + f"{fee.transactionID}")
         return
     timestamp = int(fee.dateTime.timestamp())
     amount = float(fee.amount)  # value may be both positive and negative
     note = fee.description
     query = executeSQL(self.db,"INSERT INTO actions (timestamp, account_id, peer_id) VALUES "
                            "(:timestamp, :account_id, (SELECT organization_id FROM accounts WHERE id=:account_id))",
                    [(":timestamp", timestamp), (":account_id", account_id)])
     pid = query.lastInsertId()
     _ = executeSQL(self.db, "INSERT INTO action_details (pid, category_id, sum, note) "
                             "VALUES (:pid, :category_id, :sum, :note)",
                    [(":pid", pid), (":category_id", PredefinedCategory.Fees), (":sum", amount), (":note", note)])
     self.db.commit()
     logging.info(g_tr('StatementLoader', "Fee added: ") + f"{note}, {amount}")
예제 #11
0
 def loadIBFlex(self, filename):
     try:
         report = parser.parse(filename)
     except Exception as e:
         logging.error(g_tr('StatementLoader', "Failed to parse Interactive Brokers flex-report") + f": {e}")
         return False
     for statement in report.FlexStatements:
         self.loadIBStatement(statement)
     return True
예제 #12
0
 def interceptRequest(self, info):
     url = info.firstPartyUrl().url()  # Get intercepted URL
     if str.startswith(url, "https://irkkt-mobile.nalog.ru:8888/"):
         info.block(True)
         params = dict(parse.parse_qsl(parse.urlsplit(url).query))
         auth_code = params['code']
         auth_state = params['state']
         logging.info(g_tr('SlipsTaxAPI', "ESIA login completed"))
         self.response_intercepted.emit(auth_code, auth_state)
예제 #13
0
 def onOperationContextMenu(self, pos):
     self.current_index = self.table_view.indexAt(pos)
     contextMenu = QMenu(self.table_view)
     actionReconcile = QAction(text=g_tr('LedgerOperationsView',
                                         "Reconcile"),
                               parent=self)
     actionReconcile.triggered.connect(self.reconcileAtCurrentOperation)
     actionCopy = QAction(text=g_tr('LedgerOperationsView', "Copy"),
                          parent=self)
     actionCopy.triggered.connect(self.copyOperation)
     actionDelete = QAction(text=g_tr('LedgerOperationsView', "Delete"),
                            parent=self)
     actionDelete.triggered.connect(self.deleteOperation)
     contextMenu.addAction(actionReconcile)
     contextMenu.addSeparator()
     contextMenu.addAction(actionCopy)
     contextMenu.addAction(actionDelete)
     contextMenu.popup(self.table_view.viewport().mapToGlobal(pos))
예제 #14
0
파일: downloader.py 프로젝트: uMag/ledger
def get_web_data(url):
    response = requests.get(url)
    if response.status_code == 200:
        return response.text
    else:
        logging.error(f"URL: {url}" +
                      g_tr('QuotesUpdateDialog', " failed with response ") +
                      f"{response}")
        return ''
예제 #15
0
def MakeBackup(db_file, backup_path):
    db = sqlite3.connect(db_file)

    for table in backup_list:
        data = pd.read_sql_query(f"SELECT * FROM {table}", db)
        data.to_csv(f"{backup_path}/{table}.csv", sep="|", header=True, index=False)

    db.close()
    logging.info(g_tr('', "Backup saved in: ") + backup_path)
예제 #16
0
 def createDividend(self, timestamp, account_id, asset_id, amount, note):
     id = readSQL(
         self.db, "SELECT id FROM dividends WHERE timestamp=:timestamp "
         "AND account_id=:account_id AND asset_id=:asset_id AND note=:note",
         [(":timestamp", timestamp), (":account_id", account_id),
          (":asset_id", asset_id), (":note", note)])
     if id:
         logging.warning(
             g_tr('StatementLoader', "Dividend already exists: ") +
             f"{note}")
         return
     _ = executeSQL(
         self.db,
         "INSERT INTO dividends (timestamp, account_id, asset_id, sum, note) "
         "VALUES (:timestamp, :account_id, :asset_id, :sum, :note)",
         [(":timestamp", timestamp), (":account_id", account_id),
          (":asset_id", asset_id), (":sum", amount), (":note", note)])
     self.db.commit()
     logging.info(g_tr('StatementLoader', "Dividend added: ") + f"{note}")
예제 #17
0
 def loadReport(self):
     report_file, active_filter = \
         QFileDialog.getOpenFileName(None, g_tr('StatementLoader', "Select statement file to import"),
                                     ".", f"{ReportType.IBKR};;{ReportType.Quik}")
     if report_file:
         result = self.loaders[active_filter](report_file)
         if result:
             self.load_completed.emit()
         else:
             self.load_failed.emit()
예제 #18
0
 def loadIBWithholdingTax(self, tax):
     if tax.assetCategory != AssetClass.STOCK:
         logging.error(
             g_tr('StatementLoader', "Withholding tax for ") +
             f"{tax.assetCategory}" +
             g_tr('StatementLoader', " not implemented"))
         return
     account_id = self.findAccountID(tax.accountId, tax.currency)
     if account_id is None:
         logging.error(
             g_tr('StatementLoader', "Account ") +
             f"{tax.accountId} ({tax.currency})" +
             g_tr('StatementLoader', " not found. Skipping tax #") +
             f"{tax.transactionID}")
         return
     asset_id = self.findAssetID(tax.symbol)
     timestamp = int(tax.dateTime.timestamp())
     amount = float(tax.amount)
     note = tax.description
     self.addWithholdingTax(timestamp, account_id, asset_id, amount, note)
예제 #19
0
 def loadIBDividend(self, dividend):
     if dividend.assetCategory != AssetClass.STOCK:
         logging.error(
             g_tr('StatementLoader', "Dividend for ") +
             f"{dividend.assetCategory}" +
             g_tr('StatementLoader', " not implemented"))
         return
     account_id = self.findAccountID(dividend.accountId, dividend.currency)
     if account_id is None:
         logging.error(
             g_tr('StatementLoader', "Account ") +
             f"{dividend.accountId} ({dividend.currency})" +
             g_tr('StatementLoader', " not found. Skipping dividend #") +
             f"{dividend.transactionID}")
         return
     asset_id = self.findAssetID(dividend.symbol)
     timestamp = int(dividend.dateTime.timestamp())
     amount = float(dividend.amount)
     note = dividend.description
     self.createDividend(timestamp, account_id, asset_id, amount, note)
예제 #20
0
파일: slips.py 프로젝트: grunichev/ledger
    def parseQRdata(self, qr_data):
        self.QR_data = qr_data

        logging.info(g_tr('ImportSlipDialog', "QR: " + self.QR_data))
        parts = re.match(self.QR_pattern, qr_data)
        if not parts:
            logging.warning(
                g_tr(
                    'ImportSlipDialog',
                    "QR available but pattern isn't recognized: " +
                    self.QR_data))
        for timestamp_pattern in self.timestamp_patterns:
            datetime = QDateTime.fromString(parts.group(1), timestamp_pattern)
            if datetime.isValid():
                self.SlipTimstamp.setDateTime(datetime)
        self.SlipAmount.setText(parts.group(2))
        self.FN.setText(parts.group(3))
        self.FD.setText(parts.group(4))
        self.FP.setText(parts.group(5))
        self.SlipType.setText(parts.group(6))
        self.qr_data_validated.emit()
예제 #21
0
    def loadIBTransactionTax(self, IBtax):
        account_id = self.findAccountID(IBtax.accountId, IBtax.currency)
        if account_id is None:
            logging.error(g_tr('StatementLoader', "Account ") + f"{IBtax.accountId} ({IBtax.currency})" +
                          g_tr('StatementLoader', " not found. Tax #") + f"{IBtax.tradeID}" +
                          g_tr('StatementLoader', " skipped"))
            return
        timestamp = int(datetime.combine(IBtax.date, datetime.min.time()).timestamp())
        amount = float(IBtax.taxAmount)  # value is negative already
        note = f"{IBtax.symbol} ({IBtax.description}) - {IBtax.taxDescription} (#{IBtax.tradeId})"

        id = readSQL(self.db, "SELECT id FROM all_operations WHERE type = :type "
                              "AND timestamp=:timestamp AND account_id=:account_id AND amount=:amount",
                     [(":timestamp", timestamp), (":type", TransactionType.Action),
                      (":account_id", account_id), (":amount", amount)])
        if id:
            logging.warning(g_tr('StatementLoader', "Tax transaction #") + f"{IBtax.tradeId}" +
                            g_tr('StatementLoader', " already exists"))
            return
        query = executeSQL(self.db,
                           "INSERT INTO actions (timestamp, account_id, peer_id) VALUES "
                           "(:timestamp, :account_id, (SELECT organization_id FROM accounts WHERE id=:account_id))",
                           [(":timestamp", timestamp), (":account_id", account_id)])
        pid = query.lastInsertId()
        _ = executeSQL(self.db, "INSERT INTO action_details (pid, category_id, sum, note) "
                                "VALUES (:pid, :category_id, :sum, :note)",
                       [(":pid", pid), (":category_id", PredefinedCategory.Taxes), (":sum", amount), (":note", note)])
        self.db.commit()
        logging.info(g_tr('StatementLoader', "Transaction tax added: ") + f"{note}, {amount}")
예제 #22
0
 def refresh_session(self):
     session_id = self.get_ru_tax_session()
     client_secret = readSQL(
         self.db,
         "SELECT value FROM settings WHERE name='RuTaxClientSecret'")
     refresh_token = readSQL(
         self.db,
         "SELECT value FROM settings WHERE name='RuTaxRefreshToken'")
     s = requests.Session()
     s.headers['ClientVersion'] = '2.9.0'
     s.headers['Device-Id'] = str(uuid.uuid1())
     s.headers['Device-OS'] = 'Android'
     s.headers['sessionId'] = session_id
     s.headers['Content-Type'] = 'application/json; charset=UTF-8'
     s.headers['Accept-Encoding'] = 'gzip'
     s.headers['User-Agent'] = 'okhttp/4.2.2'
     payload = '{' + f'"client_secret":"{client_secret}","refresh_token":"{refresh_token}"' + '}'
     response = s.post(
         'https://irkkt-mobile.nalog.ru:8888/v2/mobile/users/refresh',
         data=payload)
     if response.status_code == 200:
         logging.info(
             g_tr('SlipsTaxAPI', "Session refreshed: ") +
             f"{response.text}")
         json_content = json.loads(response.text)
         new_session_id = json_content['sessionId']
         new_refresh_token = json_content['refresh_token']
         _ = executeSQL(
             self.db,
             "UPDATE settings SET value=:new_session WHERE name='RuTaxSessionId'",
             [(":new_session", new_session_id)])
         _ = executeSQL(
             self.db,
             "UPDATE settings SET value=:new_refresh_token WHERE name='RuTaxRefreshToken'",
             [(":new_refresh_token", new_refresh_token)])
     else:
         logging.error(
             g_tr('SlipsTaxAPI', "Can't refresh session, response: ") +
             f"{response}/{response.text}")
예제 #23
0
파일: slips.py 프로젝트: grunichev/ledger
 def loadFileQR(self):
     self.initUi()
     qr_file, _filter = \
         QFileDialog.getOpenFileName(self, g_tr('ImportSlipDialog', "Select file with QR code"),
                                     ".", "JPEG images (*.jpg);;PNG images (*.png)")
     if qr_file:
         barcodes = pyzbar.decode(Image.open(qr_file),
                                  symbols=[pyzbar.ZBarSymbol.QRCODE])
         if barcodes:
             self.qr_data_available.emit(barcodes[0].data.decode('utf-8'))
         else:
             logging.warning('ImportSlipDialog',
                             "No QR codes were found in file")
예제 #24
0
    def loadIBStatement(self, IBstatement):
        logging.info(
            g_tr('StatementLoader', "Load IB Flex-statement for account ") +
            f"{IBstatement.accountId} " + g_tr('StatementLoader', "from ") +
            f"{IBstatement.fromDate}" + g_tr('StatementLoader', " to ") +
            f"{IBstatement.toDate}")

        for asset in IBstatement.SecuritiesInfo:
            if self.storeIBAsset(asset) is None:
                return False

        for trade in IBstatement.Trades:
            try:
                self.ib_trade_loaders[trade.assetCategory](trade)
            except:
                logging.error(
                    g_tr('StatementLoader', "Load of ") +
                    f"{trade.assetCategory}" +
                    g_tr('StatementLoader',
                         " is not implemented. Skipping trade #") +
                    f"{trade.tradeID}")

        for tax in IBstatement.TransactionTaxes:
            self.loadIBTransactionTax(tax)

        for corp_action in IBstatement.CorporateActions:
            self.loadIBCorpAction(corp_action)

        # 1st loop to load all dividends separately - to allow tax match in 2nd loop
        for cash_transaction in IBstatement.CashTransactions:
            if cash_transaction.type == CashAction.DIVIDEND:
                self.loadIBDividend(cash_transaction)
        for cash_transaction in IBstatement.CashTransactions:
            if cash_transaction.type == CashAction.WHTAX:
                self.loadIBWithholdingTax(cash_transaction)
            elif cash_transaction.type == CashAction.FEES:
                self.loadIBFee(cash_transaction)
            elif cash_transaction.type == CashAction.DEPOSITWITHDRAW:
                self.loadIBDepositWithdraw(cash_transaction)
예제 #25
0
 def addWithholdingTax(self, timestamp, account_id, asset_id, amount, note):
     parts = re.match(IBKR.TaxNotePattern, note)
     if not parts:
         logging.warning(g_tr('StatementLoader', "*** MANUAL ENTRY REQUIRED ***"))
         logging.warning(g_tr('StatementLoader', "Unhandled tax pattern found: ") + f"{note}")
         return
     dividend_note = parts.group(1) + '%'
     country_code = parts.group(2)
     try:
         dividend_id, old_tax = readSQL(self.db,
                                        "SELECT id, sum_tax FROM dividends "
                                        "WHERE timestamp=:timestamp AND account_id=:account_id "
                                        "AND asset_id=:asset_id AND note LIKE :dividend_description",
                                        [(":timestamp", timestamp), (":account_id", account_id),
                                         (":asset_id", asset_id), (":dividend_description", dividend_note)])
     except:
         logging.warning(g_tr('StatementLoader', "Dividend not found for withholding tax: ") + f"{note}")
         return
     _ = executeSQL(self.db, "UPDATE dividends SET sum_tax=:tax, note_tax=:note WHERE id=:dividend_id",
                    [(":dividend_id", dividend_id), (":tax", old_tax + amount), (":note", country_code + " tax")])
     self.db.commit()
     logging.info(g_tr('StatementLoader', "Withholding tax added: ") + f"{note}")
예제 #26
0
    def setType(self, trade_type):
        # if (self.p_type == type):
        #     return
        self.p_type = trade_type

        if self.p_type:
            self.label.setText(g_tr('TradeAction', "CORP.ACTION"))
            self.palette.setColor(self.label.foregroundRole(),
                                  CustomColor.DarkBlue)
            self.label.setPalette(self.palette)
        else:
            self.label.setText(g_tr('TradeAction', "TRADE"))
            self.palette.setColor(self.label.foregroundRole(),
                                  CustomColor.DarkGreen)
            self.label.setPalette(self.palette)
        #         else:
        #             self.label.setText("SELL")
        #             self.palette.setColor(self.label.foregroundRole(), CustomColor.DarkRed)
        #             self.label.setPalette(self.palette)
        # else:
        #     self.label.setText("UNKNOWN")
        self.changed.emit()
예제 #27
0
    def createTrade(self, account_id, asset_id, timestamp, settlement, number, qty, price, fee, coupon=0.0):
        trade_id = readSQL(self.db,
                           "SELECT id FROM trades "
                           "WHERE timestamp=:timestamp AND asset_id = :asset "
                           "AND account_id = :account AND number = :number AND qty = :qty AND price = :price",
                           [(":timestamp", timestamp), (":asset", asset_id), (":account", account_id),
                            (":number", number), (":qty", qty), (":price", price)])
        if trade_id:
            logging.info(g_tr('StatementLoader', "Trade #") + f"{number}" +
                         g_tr('StatementLoader', " already exists in ledger. Skipped"))
            return

        _ = executeSQL(self.db,
                       "INSERT INTO trades (timestamp, settlement, corp_action_id, number, account_id, "
                       "asset_id, qty, price, fee, coupon) "
                       "VALUES (:timestamp, :settlement, 0, :number, :account, "
                       ":asset, :qty, :price, :fee, :coupon)",
                       [(":timestamp", timestamp), (":settlement", settlement), (":number", number),
                        (":account", account_id), (":asset", asset_id), (":qty", float(qty)),
                        (":price", float(price)), (":fee", -float(fee)), (":coupon", float(coupon))])
        self.db.commit()
        logging.info(f"Trade #{number} added for account {account_id} asset {asset_id} @{timestamp}: {qty}x{price}")
예제 #28
0
    def login_fns(self):
        client_secret = readSQL(
            self.db,
            "SELECT value FROM settings WHERE name='RuTaxClientSecret'")
        inn = self.InnEdit.text()
        password = self.PasswordEdit.text()

        s = requests.Session()
        s.headers['ClientVersion'] = '2.9.0'
        s.headers['Device-Id'] = str(uuid.uuid1())
        s.headers['Device-OS'] = 'Android'
        s.headers['Content-Type'] = 'application/json; charset=UTF-8'
        s.headers['Accept-Encoding'] = 'gzip'
        s.headers['User-Agent'] = 'okhttp/4.2.2'
        payload = '{' + f'"client_secret":"{client_secret}","inn":"{inn}","password":"******"' + '}'
        response = s.post(
            'https://irkkt-mobile.nalog.ru:8888/v2/mobile/users/lkfl/auth',
            data=payload)
        if response.status_code != 200:
            logging.error(
                g_tr('SlipsTaxAPI', "FNS login failed: ") +
                f"{response}/{response.text}")
            return
        logging.info(
            g_tr('SlipsTaxAPI', "FNS login successful: ") + f"{response.text}")
        json_content = json.loads(response.text)
        new_session_id = json_content['sessionId']
        new_refresh_token = json_content['refresh_token']
        _ = executeSQL(
            self.db,
            "UPDATE settings SET value=:new_session WHERE name='RuTaxSessionId'",
            [(":new_session", new_session_id)])
        _ = executeSQL(
            self.db,
            "UPDATE settings SET value=:new_refresh_token WHERE name='RuTaxRefreshToken'",
            [(":new_refresh_token", new_refresh_token)])
        self.db.commit()
        self.accept()
예제 #29
0
 def init_db(self, db):
     self.dialog = ReferenceDataDialog(
         db,
         "accounts",
         [("id", None, 0, None, None),
          ("name", g_tr('AccountSelector',
                        "Name"), -1, Qt.AscendingOrder, None),
          ("type_id", None, 0, None, None),
          ("currency_id", "Currency", None, None, ReferenceLookupDelegate),
          ("active", "Act", 32, None, ReferenceBoolDelegate),
          ("number", "Account #", None, None, None),
          ("reconciled_on", "Reconciled @",
           self.fontMetrics().width("00/00/0000 00:00:00") * 1.1, None,
           ReferenceTimestampDelegate),
          ("organization_id", "Bank", None, None, ReferenceLookupDelegate)],
         title=g_tr('AccountSelector', "Accounts"),
         search_field="full_name",
         toggle=("active", "Show inactive"),
         relations=[("type_id", "account_types", "id", "name",
                     "Account type:"),
                    ("currency_id", "currencies", "id", "name", None),
                    ("organization_id", "agents", "id", "name", None)])
     super().init_db("accounts", "name")
예제 #30
0
파일: taxes.py 프로젝트: uMag/ledger
    def save2file(self, taxes_file, year, account_id):
        year_begin = int(time.mktime(datetime.strptime(f"{year}", "%Y").timetuple()))
        year_end = int(time.mktime(datetime.strptime(f"{year + 1}", "%Y").timetuple()))

        workbook = xlsxwriter.Workbook(filename=taxes_file)
        formats = xslxFormat(workbook)

        for report in self.reports:
            sheet = workbook.add_worksheet(name=report)
            self.reports[report](sheet, account_id, year_begin, year_end, formats)
        try:
            workbook.close()
        except:
            logging.error(g_tr('TaxesRus', "Can't write tax report into file ") + f"'{taxes_file}'")