Пример #1
0
        public void StatementMatch()
        {
            Utils.Check(SessionData.StatementMatch != null, "Invalid call to StatementMatch");
            MatchInfo match   = SessionData.StatementMatch.ToObject <MatchInfo>();
            int       acct    = SessionData.StatementImport.id;
            Account   account = Database.Get <Account>(acct);
            // The existing transaction to match (or empty record if none)
            Extended_Document transaction = match.transaction < 0 ? Database.EmptyRecord <Extended_Document>() :
                                            SessionData.StatementImport.transactions[match.transaction].ToObject <Extended_Document>();
            // The statement transaction
            dynamic current = SessionData.StatementImport.import[match.current];

            Utils.Check(current != null, "No current transaction");
            bool    same           = match.type == "Same";
            bool    documentHasVat = false;
            bool    payment        = false;
            decimal cAmount        = current.Amount;
            int     id             = transaction.idDocument ?? 0;
            DocType type;

            if (match.transaction >= 0)
            {
                type = (DocType)transaction.DocumentTypeId;
            }
            else
            {
                switch (match.type)
                {
                case "Deposit":
                    Utils.Check(account.AccountTypeId == (int)AcctType.Bank || account.AccountTypeId == (int)AcctType.OtherAsset ||
                                account.AccountTypeId == (int)AcctType.OtherLiability, "Deposit not to bank account");
                    type = DocType.Deposit;
                    break;

                case "CardCredit":
                    Utils.Check(account.AccountTypeId == (int)AcctType.CreditCard, "Credit not to credit card");
                    type = DocType.CreditCardCredit;
                    break;

                case "Transfer":
                    type = DocType.Transfer;
                    break;

                case "CustomerPayment":
                    type = DocType.Payment;
                    break;

                case "Subscriptions":
                    type = DocType.Subscriptions;
                    break;

                case "Withdrawal":
                    Utils.Check(account.AccountTypeId == (int)AcctType.Bank || account.AccountTypeId == (int)AcctType.OtherAsset ||
                                account.AccountTypeId == (int)AcctType.OtherLiability, "Withdrawal not to bank account");
                    type = DocType.Withdrawal;
                    break;

                case "CardCharge":
                    Utils.Check(account.AccountTypeId == (int)AcctType.CreditCard, "Charge not to credit card");
                    type = DocType.CreditCardCharge;
                    break;

                case "BillPayment":
                    type = DocType.BillPayment;
                    break;

                default:
                    throw new CheckException("Unknown match type {0}", match.type);
                }
            }
            GetParameters["acct"] = acct.ToString();                // This bank account
            string nameType = "O";

            // Call appropriate method to get Record, and therefore transaction
            // Also set Module and Method, so appropriate template is used to display transaction before posting
            switch (type)
            {
            case DocType.Payment:
                Module = "customer";
                Method = "payment";
                Customer cust = new Customer()
                {
                    CopyFrom = this
                };
                cust.Payment(id);
                this.Record = cust.Record;
                this.Form   = cust.Form;
                payment     = true;
                nameType    = "C";
                break;

            case DocType.BillPayment:
                Module = "supplier";
                Method = "payment";
                Supplier supp = new Supplier()
                {
                    CopyFrom = this
                };
                supp.Payment(id);
                this.Record = supp.Record;
                this.Form   = supp.Form;
                payment     = true;
                nameType    = "S";
                break;

            case DocType.Withdrawal:
            case DocType.Deposit:
            case DocType.CreditCardCharge:
            case DocType.CreditCardCredit:
                Method = "document";
                Document(id, type);
                documentHasVat = true;
                break;

            case DocType.Transfer:
                Method = "transfer";
                Transfer(id);
                break;

            case DocType.Subscriptions:
                Module = "Members";
                Method = "document";
                Members member = new Members()
                {
                    CopyFrom = this
                };
                member.Document(id);
                this.Record = member.Record;
                this.Form   = member.Form;
                nameType    = "M";
                break;

            default:
                throw new CheckException("Unexpected document type:{0}", type.UnCamel());
            }
            dynamic record = (JObject)Record;
            dynamic doc    = record.header;

            if (id == 0 && type == DocType.Transfer && cAmount > 0)
            {
                // New transfer in
                doc.TransferAccountId   = acct;
                doc.DocumentAccountId   = 0;
                doc.DocumentAccountName = "";
            }
            if (string.IsNullOrWhiteSpace(doc.DocumentMemo.ToString()))
            {
                // Generate a memo
                string name = current.Name;
                string memo = current.Memo;
                if (string.IsNullOrWhiteSpace(memo))
                {
                    memo = name;
                }
                else if (!memo.Contains(name))
                {
                    memo = name + " " + memo;
                }
                doc.DocumentMemo = memo;
            }
            if (!same && type != DocType.Subscriptions)
            {
                // They want to create a new document - try to guess the DocumentName
                string name        = doc.DocumentName;
                string currentName = current.Name;
                currentName = currentName.Split('\n', '\t')[0];
                if (string.IsNullOrWhiteSpace(name) || (!payment && name.SimilarTo(currentName) < 0.5))
                {
                    doc.DocumentName          = currentName;
                    doc.DocumentNameAddressId = 0;
                    float maxsimilarity = 0.4999f;
                    foreach (NameAddress n in Database.Query <NameAddress>("SELECT * FROM NameAddress WHERE Type = " + Database.Quote(nameType)
                                                                           + " AND Name <= " + Database.Quote(currentName)
                                                                           + " AND Name LIKE " + Database.Quote(currentName.Length <= 5 ? currentName : currentName.Substring(0, 5) + "%")))
                    {
                        float similarity = n.Name.SimilarTo(currentName);
                        if (similarity > maxsimilarity)
                        {
                            doc.DocumentName          = n.Name;
                            doc.DocumentNameAddressId = n.idNameAddress;
                            maxsimilarity             = similarity;
                        }
                    }
                }
            }
            doc.DocumentDate = current.Date;
            decimal tAmount = doc.DocumentAmount;
            decimal diff    = Math.Abs(cAmount) - Math.Abs(tAmount);

            doc.DocumentAmount += diff;
            if (same)
            {
                Utils.Check(diff == 0, "Amounts must be the same");
            }
            else
            {
                // New transaction
                doc.DocumentOutstanding = doc.DocumentAmount;
                doc.Clr        = "";
                doc.idDocument = doc.Id = null;
                if (Utils.ExtractNumber(doc.DocumentIdentifier.ToString()) > 0)
                {
                    doc.DocumentIdentifier = "<next>";
                }
            }
            if (string.IsNullOrEmpty(doc.DocumentIdentifier.ToString()))
            {
                if (current.Id != null)
                {
                    doc.DocumentIdentifier = current.Id;
                }
                else
                {
                    int no = Utils.ExtractNumber(current.Name.ToString());
                    if (no != 0)
                    {
                        doc.DocumentIdentifier = no.ToString();
                    }
                }
            }
            if (diff != 0 && documentHasVat)
            {
                // Adjust first line to account for difference
                if (record.detail.Count == 0)
                {
                    record.detail.Add(new InvoiceLine().ToJToken());
                }
                dynamic line = record.detail[0];
                decimal val  = line.LineAmount + line.VatAmount + diff;
                if (line.VatRate != 0)
                {
                    line.VatAmount = Math.Round(val * line.VatRate / (100 + line.VatRate), 2);
                    val           -= line.VatAmount;
                }
                line.LineAmount = val;
            }
            if (payment && !same)
            {
                removePayments(record);
            }
            record.StatementAccount = acct;
            if (same)
            {
                // Just post the new information
                if (type == DocType.Transfer)
                {
                    record = record.header;                             // Transfer posts header alone
                }
                AjaxReturn p = StatementMatchSave((JObject)record);
                if (p.error == null)
                {
                    Redirect(p.redirect);                               // If no error, go on with matching
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Save a matched transaction.
        /// May be called direct from StatementMatch for Same transactions,
        /// or when the user presses "Save" for other transactions
        /// </summary>
        public AjaxReturn StatementMatchSave(JObject json)
        {
            Utils.Check(SessionData.StatementMatch != null, "Invalid call to StatementMatchSave");
            MatchInfo match        = SessionData.StatementMatch.ToObject <MatchInfo>();
            JArray    transactions = SessionData.StatementImport.transactions;
            dynamic   transaction  = match.transaction < 0 ? null : SessionData.StatementImport.transactions[match.transaction];
            DocType   type         = match.transaction < 0 ? match.type == "Transfer" ? DocType.Transfer : DocType.Withdrawal :
                                     (DocType)((JObject)transactions[match.transaction]).AsInt("DocumentTypeId");
            AjaxReturn result;

            switch (type)
            {
            case DocType.Payment:
                result = new Customer()
                {
                    Context        = Context,
                    GetParameters  = GetParameters,
                    PostParameters = PostParameters,
                    Parameters     = Parameters,
                }.PaymentSave(json.To <CustomerSupplier.PaymentDocument>());
                break;

            case DocType.BillPayment:
                result = new Supplier()
                {
                    Context        = Context,
                    GetParameters  = GetParameters,
                    PostParameters = PostParameters,
                    Parameters     = Parameters,
                }.PaymentSave(json.To <CustomerSupplier.PaymentDocument>());
                break;

            case DocType.Withdrawal:
            case DocType.Deposit:
            case DocType.CreditCardCharge:
            case DocType.CreditCardCredit:
                result = DocumentSave(json.To <BankingDocument>());
                break;

            case DocType.Transfer:
                result = TransferSave(json.To <TransferDocument>());
                break;

            case DocType.Subscriptions:
                result = new Members()
                {
                    Context        = Context,
                    GetParameters  = GetParameters,
                    PostParameters = PostParameters,
                    Parameters     = Parameters,
                }.DocumentSave(json.To <Members.SubscriptionDocument>());
                break;

            default:
                throw new CheckException("Unexpected document type:{0}", type.UnCamel());
            }
            if (result.error == null)
            {
                if (match.transaction >= 0 && match.type == "Same")
                {
                    transaction.Matched = 1;
                }
                JArray items = SessionData.StatementImport.import;
                items.RemoveAt(match.current);
                int acct = SessionData.StatementImport.id;
                result.redirect = "/banking/" + (items.Count == 0 ? "detail.html?id=" + acct : "statementmatching.html");
            }
            return(result);
        }