Example #1
0
        /// <summary>
        /// List all the journals that post to this account, along with document info and the balance after the posting.
        /// Detects documents which are splits (i.e. have more than 2 journals) and sets the DocumentAccountName to "-split-"
        /// </summary>
        protected IEnumerable <JObject> detailsWithBalance(int id)
        {
            JObject last    = null;             // previous document
            int     lastId  = 0;                // Id of previous journal
            decimal balance = 0;                // Running total balance

            // Query gets all journals to this account, joined to document header
            // Then joins to any other journals for this document, so documents with only 2 journals
            // will appear once, but if there are more than 2 journals the document will appear more times
            foreach (JObject l in Database.Query(@"SELECT Journal.idJournal, Document.*, NameAddress.Name As DocumentName, DocType, Journal.Cleared AS Clr, Journal.Amount As DocumentAmount, AccountName As DocumentAccountName
FROM Journal
LEFT JOIN Document ON idDocument = Journal.DocumentId
LEFT JOIN DocumentType ON DocumentType.idDocumentType = Document.DocumentTypeId
LEFT JOIN NameAddress ON NameAddress.idNameAddress = Journal.NameAddressId
LEFT JOIN Journal AS J ON J.DocumentId = Journal.DocumentId AND J.AccountId <> Journal.AccountId
LEFT JOIN Account ON Account.idAccount = J.AccountId
WHERE Journal.AccountId = " + id + @"
ORDER BY DocumentDate, idDocument"))
            {
                if (last != null)
                {
                    if (lastId == l.AsInt("idJournal"))
                    {
                        // More than 1 line in this document
                        last["DocumentAccountName"] = "-split-";
                        // Only emit each journal to this account once
                        continue;
                    }
                    balance        += last.AsDecimal("DocumentAmount");
                    last["Balance"] = balance;
                    yield return(last);
                }
                last   = l;
                lastId = l.AsInt("idJournal");
            }
            if (last != null)
            {
                balance        += last.AsDecimal("DocumentAmount");
                last["Balance"] = balance;
                yield return(last);
            }
        }
Example #2
0
        public void Reconcile(int id)
        {
            JObject header         = Database.QueryOne("*", "WHERE idAccount = " + id, "Account");
            JObject openingBalance = Database.QueryOne("SELECT SUM(Amount) AS OpeningBalance FROM Journal WHERE AccountId = " + id
                                                       + " AND Cleared = 'X'");

            header["OpeningBalance"] = openingBalance == null ? 0 : openingBalance.AsDecimal("OpeningBalance");
            Title += " - " + header.AsString("AccountName");
            checkAccountIsAcctType(id, AcctType.Bank, AcctType.CreditCard,
                                   AcctType.OtherAsset, AcctType.OtherLiability);
            Record = new JObject().AddRange("header", header,
                                            "detail", Database.Query(@"SELECT Extended_Document.*, Journal.idJournal, Journal.Cleared, Journal.Amount
FROM Journal
JOIN Extended_Document ON idDocument = DocumentId
WHERE Journal.AccountId = " + id + @"
AND Journal.Cleared <> 'X'
ORDER BY DocumentDate, idDocument"));
        }
Example #3
0
        /// <summary>
        /// Update a journal line
        /// </summary>
        public override void Update(JObject dataOut)
        {
            if (dataOut["AccountId"] == null)
            {
                return;                                                 // Can't post if no account
            }
            int id = dataOut.AsInt("idDocument");

            if (id == 0)
            {
                return;                                 // Can't post if no document
            }
            bool    newTran = id != _tranId;
            DocType docType = (DocType)dataOut.AsInt("DocumentTypeId");

            if (newTran)
            {
                // New document
                _vat       = 0;
                _vatAmount = 0;
                dataOut["DocumentAddress"] = string.Join("\r\n", Enumerable.Range(1, 5).Select(i => dataOut.AsString("Address" + i)).Where(s => !string.IsNullOrEmpty(s)).ToArray());
                if (!_module.Database.RecordExists("Document", dataOut.AsInt("idDocument")))
                {
                    dataOut["VatPaid"] = 0;
                }
                base.Update(dataOut);                           // Save the document
                _tranId = id;
                _line   = 0;
                // Save the last invoice/cheque/etc. no
                int number = Utils.ExtractNumber(dataOut.AsString("DocumentIdentifier"));
                switch (docType)
                {
                case DocType.Invoice:
                case DocType.CreditMemo:
                    if (number > _lastInvoiceNumber)
                    {
                        _lastInvoiceNumber = number;
                    }
                    break;

                case DocType.Bill:
                case DocType.Credit:
                    if (number > _lastBillNumber)
                    {
                        _lastBillNumber = number;
                    }
                    break;

                case DocType.Withdrawal:
                case DocType.CreditCardCharge:
                    registerNumber(_lastChequeNumber, dataOut.AsInt("AccountId"), number);
                    break;

                case DocType.Deposit:
                case DocType.CreditCardCredit:
                    registerNumber(_lastDepositNumber, dataOut.AsInt("AccountId"), number);
                    break;

                case DocType.GeneralJournal:
                    if (number > _lastJournalNumber)
                    {
                        _lastJournalNumber = number;
                    }
                    break;
                }
                // Delete any existing lines
                _module.Database.Execute("DELETE FROM Line WHERE idLine IN (SELECT idJournal FROM Journal WHERE DocumentId = " + _tranId + ")");
                _module.Database.Execute("DELETE FROM Journal WHERE DocumentId = " + _tranId);
            }
            dataOut["DocumentId"] = _tranId;
            dataOut["JournalNum"] = ++_line;
            dataOut["Memo"]       = dataOut["DocumentMemo"];
            _module.Database.Update("Journal", dataOut);                // Save the journal
            if (dataOut.AsInt("AccountId") == (int)Acct.VATControl)
            {
                // This is the VAT journal
                _vatAmount += dataOut.AsDecimal("Amount");
                if (_vat != 0)
                {
                    // There is already a VAT journal - delete it
                    _module.Database.Execute("DELETE FROM Line WHERE idLine IN (SELECT idJournal FROM Journal WHERE DocumentId = " + _tranId + " AND JournalNum = " + _vat + ")");
                    _module.Database.Execute("DELETE FROM Journal WHERE DocumentId = " + _tranId + " AND JournalNum = " + _vat);
                    _module.Database.Execute("UPDATE Journal SET JournalNum = JournalNum - 1 WHERE DocumentId = " + _tranId + " AND JournalNum > " + _vat);
                    // Bump this journal a line earlier
                    dataOut["JournalNum"] = --_line;
                    dataOut["Amount"]     = _vatAmount;
                    _module.Database.Update("Journal", dataOut);
                }
                _vat = _line;                   // Remember, to avoid 2 VAT lines
            }
            // 2nd and subsequent journals (except VAT journal) have lines
            // NB VAT Payments to HMRC have are exceptions - they have a line for the VAT payment
            if (!newTran && (_line == 2 || dataOut.AsInt("AccountId") != (int)Acct.VATControl))
            {
                int sign = AppModule.SignFor(docType);
                dataOut["idLine"]     = dataOut["idJournal"];
                dataOut["LineAmount"] = sign * dataOut.AsDecimal("Amount");
                dataOut["Qty"]        = sign * dataOut.AsDecimal("Qty");
                dataOut["VatRate"]    = dataOut.AsDecimal("VatRate");
                dataOut["VatAmount"]  = sign * dataOut.AsDecimal("VatAmount");
                _module.Database.Update("Line", dataOut);
            }
        }
Example #4
0
 /// <summary>
 /// Extract the value directly as a decimal
 /// </summary>
 public decimal Value(JObject record)
 {
     return(record.AsDecimal(Names.DataName));
 }
Example #5
0
 public override FieldValue ValueFor(JObject o)
 {
     return(new FieldValue <decimal>(o.AsDecimal(Names.DataName)));
 }