using System;
using System.Collections.Generic;
using System.Linq;
using Winbooks.TORM.DAL.Accounting;
using Winbooks.TORM.OM;
using Winbooks.TORM.DAL;

using Winbooks.Apis.Services;
using Winbooks.TORM.OM.Accounting;
using Winbooks.TORM.OM.Logistics;
using Winbooks.Apis.Services.v2;
using Country = Winbooks.TORM.OM.Country;
using Currency = Winbooks.TORM.OM.Currency;

namespace Winbooks.Apis.Demo
{
    public class MainExample
    {
        private static EntitiesServices _folder;

        public static string MainExecute(EntitiesServices folder)
        {
            Tools.LogFile = "";
            _folder = folder;
            return ExecuteMainExample();
        }
        public static string ExecuteMainExample()
        {
            //Console.WriteLine("Cleaning database for fresh demo ...");
            //DemoHelper.CleanUpDataForDemo(folderPARFIWEB);
            //Console.WriteLine("Cleaning database: OK");

            #region ******** CUSTOMER ********
            Console.WriteLine();
            Console.WriteLine("********* CUSTOMER *********");
            Console.WriteLine();

            //GETTING INFO OF CUSTOMER COSMOSHOP
            Customer cosmoCustomer = _folder.GetByCode<Customer>("COSMOSHOP");
            if (cosmoCustomer == null)
                Console.WriteLine("Getting customer by Code COSMOSHOP: failed");
            else
                Console.WriteLine("Getting customer by Code COSMOSHOP: OK (code:" + cosmoCustomer.Code + ")");

            //GETTING INFO OF CUSTOMER WHICH HAVE ID 
            Customer CustomerWithId = _folder.GetById<Customer>("79A2E56E-2BE7-4216-BA75-9F9400FB45BD");
            Console.WriteLine("Getting customer by Id : OK");

            //CREATE CONDITION : FIND CUSTOMER WHICH HAVE THIRD AND THIRD NAME IS "COSMO BRITISH SHOP"
            ICriteria criteria = new CustomerDAO().CreateCriteria();
            criteria.CreateAlias("th", typeof(Third), Third.Names.Id, Customer.Names.Third_Id);
            criteria.Add(Condition.Eq("th." + Third.Names.Name, "Cosmo British Shop"));

            //GET CUSTOMER BY FILTER
            Customer customerByFilter = _folder.GetFilter<Customer>(criteria);
            Console.WriteLine("Getting customer by name 'Cosmo British Shop' : OK");

            //GETTING INFO OF CUSTOMER COSMOSHOP WITH 2 LEVEL
            Customer cosmoCustomerWith2Level = _folder.GetByCode<Customer>("COSMOSHOP", 2, true);
            //NOW YOU HAVE INFO THIRD OF 'COSMOSHOP' CUSTOMER
            Third thirdOfCosmoCustomer = cosmoCustomerWith2Level.Third;
            Console.WriteLine("Getting Customer with 2 level : OK");

            //USING BaseEntitySetting 
            BaseEntitySetting setting = new BaseEntitySetting();
            setting.SendEntityLevel = 2;
            setting.GetEntityLevel = 2;
            setting.IsShowId = false;
            setting.IsValidate = true;

            //GETTING INFO OF CUSTOMER COSMOSHOP WITH SETTING
            Customer cosmoCustomerWithBaseEntitySetting = _folder.GetByCode<Customer>("COSMOSHOP", setting);
            //INFO THIRD OF COSMOSHOP CUSTOMER
            Third third = cosmoCustomerWithBaseEntitySetting.Third;
            Console.WriteLine("Getting customer using BaseEntitySetting : OK");

            //GET ALL CUSTOMER IN FOLDER PARFIWEB
            IList<Customer> allCustomer = _folder.GetAll<Customer>();
            Console.WriteLine("Getting all customers : OK - " + allCustomer.Count + " records");

            //CREATE CONDITION : GET TOP 10 CUSTOMER WITH COUNTRY IS BE
            ICriteria criteriaFilterAll = new CustomerDAO().CreateCriteria();
            criteriaFilterAll.CreateAlias("th", typeof(Third), Third.Names.Id, Customer.Names.Third_Id);
            criteriaFilterAll.CreateAlias(JoinType.InnerJoin, "th", "vatCountry",
                typeof(Winbooks.TORM.OM.Country), Winbooks.TORM.OM.Country.Names.Id,
                Third.Names.VatCountry_Id);
            criteriaFilterAll.Add(Condition.Eq("vatCountry." + Country.Names.Code, "BE"));
            criteriaFilterAll.SetFirstResult(0);
            criteriaFilterAll.SetMaxResults(10);
            //GET FILTER ALL 
            IList<Customer> lstCustomerBE = _folder.GetFilterAll<Customer>(criteriaFilterAll);
            Console.WriteLine("Getting 10 customers with vatcountry in BE : OK");

            //UPDATE BY CODE
            cosmoCustomer.Memo = "this is the memo for customer Cosmo";
            _folder.UpdateByCode<Customer>(cosmoCustomer, 1);
            Console.WriteLine("Uppdate customer by code : OK");

            //UPDATE BY ID
            CustomerWithId.Memo = "this is the memo update customer by id";
            _folder.UpdateById<Customer>(cosmoCustomer, 1);
            Console.WriteLine("Uppdate customer by id : OK");

            //MODIFY A CUSTOMER AND SUBENTITY INSIDE
            cosmoCustomerWith2Level.Memo = "this customer is modified with sub entities inside";
            cosmoCustomerWith2Level.Third.WebSite = "www.cosmoshop.com";

            //SETTING LEVEL INFO FOR SENDING TO API
            _folder.UpdateById<Customer>(cosmoCustomerWith2Level, 2);
            Console.WriteLine("Uppdate customer [ id with 2 level : OK");

            //ANOTHER WAY TO UPDATE CUSTOMER
            Customer newCustomerHaveSameCode = new Customer();
            //SET CUSTOMER CODE IS AN EXISTING CUSTOMER CODE
            newCustomerHaveSameCode.Code = "COSMOSHOP";
            newCustomerHaveSameCode.Vat = new VatAccount();
            //SET VAT.CODE IS AN EXISTING VAT => SO REST API WILL UPDATE VAT OF CUSTOMER IS THE EXISTING VAT HAVE CODE "PST6"
            newCustomerHaveSameCode.Vat.Code = "PST6";
            //BECAUSE WE INTEND TO UPDATE EXISTING CUSTOMER NOT INSERT, ALL MANDATORY FIELDS IS ALREADY EXISTED IN SERVER => SO IN CLIENT, WE SKIP VALIDATION STEP BY SETTING ISVALIDATED = FALSE
            _folder.UpdateByCode<Customer>(newCustomerHaveSameCode, 2, false);
            Console.WriteLine("Update customer by another way : OK");

            //MODIFY A LIST OF CUSTOMER  
            foreach (var customer in lstCustomerBE)
            {
                customer.Third.WebSite = "www." + customer.Third.Code.ToLower().Trim(' ') + ".com";
            }
            //SETTING LEVEL INFO FOR SENDING TO API
            _folder.UpdateCollection(lstCustomerBE, 2);
            Console.WriteLine("Update list customers : OK");

            //CREATE SINGLE CUSTOMER 
            Customer newCustomer = new Customer();
            newCustomer.MemoType = MemoType.Green;
            newCustomer.Code = "ALICE";
            newCustomer.Memo = "this memo is for customer Alice Wilder";
            //CREATE MANDATORY OBJECT
            newCustomer.Third = new Third();
            newCustomer.Third.Code = "ALICE";
            newCustomer.Third.Name = "Alice Wilder";
            newCustomer.Third.WebSite = "www.alice-wilder.com";

            //INSERT NEW CUSTOMER TO FOLDER PARFIWEB
            _folder.Insert<Customer>(newCustomer, 2);
            Console.WriteLine("Create new customer Alice : OK");

            //CREATE CUSTOMER WITH SUB ENTITIESKYLIE MINOGUE  
            Customer customerWithSubEntity = new Customer();
            customerWithSubEntity.Code = "KYLIE";
            customerWithSubEntity.MemoType = MemoType.Green;
            customerWithSubEntity.Memo = "this memo is for customer Kylie Minogue";
            //CREATE MANDATORY OBJECT
            customerWithSubEntity.Third = new Third();
            customerWithSubEntity.Third.Code = "KYLIE";
            customerWithSubEntity.Third.Name = "Kylie Minogue";
            customerWithSubEntity.Third.WebSite = "www.kylie-minogue.com";
            //CREATE SUB ENTITY
            customerWithSubEntity.PriceDiscounts = new List<CustomerPriceDiscount>();
            //CREATE PRICEDISCOUNT WITH ITEM 008
            CustomerPriceDiscount customerPriceDiscount = new CustomerPriceDiscount();
            customerPriceDiscount.Customer = customerWithSubEntity;
            customerPriceDiscount.Item = new Item();
            customerPriceDiscount.Item.Code = "CBURT";
            customerPriceDiscount.Item.Name = "CBURT";
            customerPriceDiscount.Item.StockManagementType = StockManagementType.Batch;
            customerPriceDiscount.Item.StockValuationMethod = StockValuationMethod.FIFO;
            customerPriceDiscount.Item.CoefSale2StockQuantity = 0;
            customerWithSubEntity.PriceDiscounts.Add(customerPriceDiscount);

            _folder.Insert<Customer>(customerWithSubEntity, 3);
            Console.WriteLine("Create new customer with sub entities : OK");

            //ADDING SECOND CONTACT TO CUSTOMER
            Customer addingSecondContact = new Customer();
            addingSecondContact.Code = "KYLIE";
            addingSecondContact.Third = new Third();
            addingSecondContact.Third.Code = "KYLIE";
            addingSecondContact.Third.Contacts = new List<Third_Contact>();
            Third_Contact thirdContact = new Third_Contact();
            thirdContact.Third = new Third();
            thirdContact.Third.Code = "KYLIE";
            thirdContact.Contact = new Contact();
            thirdContact.Contact.EmailAddresses = new List<EmailAddress>();
            thirdContact.Contact.EmailAddresses.Add(new EmailAddress("kylie_minogue@gmail.com"));
            thirdContact.Contact.MemoType = MemoType.Green;
            thirdContact.Contact.PhoneNumbers = new List<PhoneNumber>();
            thirdContact.Contact.PhoneNumbers.Add(new PhoneNumber("+016 256 992 4556"));
            thirdContact.Contact.FirstName = "Kylie";
            thirdContact.Contact.LastName = "Minogue";
            thirdContact.Contact.EmailAddressOther = "kylie_minogue@hotmail.com";
            /* Code for the 2.4
            thirdContact.Address = new Address();
            thirdContact.Address.Address1 = "3 rue Jean Perrin";
            thirdContact.Address.Address1 = "700 Boulevard Jean-Jules Herbert";
            thirdContact.Address.Address2 = "4 rue Théodore Blanc";
            thirdContact.Address.PhoneNo = "+33 1 6486 8800";

            thirdContact.Address.Country = new Country();
            thirdContact.Address.Country.Code = "BE";
            thirdContact.Address.Zip = "4650";
            */
            addingSecondContact.Third.Contacts.Add(thirdContact);

            _folder.Insert<Customer>(addingSecondContact, 5, false);
            Console.WriteLine("Adding second contact to customer : OK");

            //CREATE A LIST OF CUSTOMER
            List<string> customerNames = new List<string>() { "Adam", "Miranda", "Jordin", "Sparks", "Austin" };
            List<Customer> lstNewCustomers = new List<Customer>();
            foreach (var customerName in customerNames)
            {
                Customer cust = new Customer();
                cust.Code = customerName.Trim(' ').ToUpper();
                cust.MemoType = MemoType.Green;
                cust.Memo = "this is the memo of " + customerName;
                cust.Third = new Third();
                cust.Third.Name = customerName;
                cust.Third.Code = customerName.Trim(' ').ToUpper();
                cust.Third.WebSite = "www." + customerName.Trim(' ').ToLower();
                lstNewCustomers.Add(cust);
            }

            //INSERT A LIST OF CUSTOMER
            _folder.InsertCollection(lstNewCustomers, 2);
            Console.WriteLine("Insert a list of customers : OK");

            //DELETE A CUSTOMER BY CODE
            _folder.DeleteByCode<Customer>("ADAM");
            Console.WriteLine("Delete customer by code 'ADAM' : OK");

            //DELETE A CUSTOMER BY ID
            Guid CustomerId = _folder.GetByCode<Customer>("AUSTIN", true).Id;
            _folder.DeleteById<Customer>(CustomerId);
            Console.WriteLine("Delete customer by id : OK");

            //DELETE A LIST CUSTOMER BY FILTER 
            object[] arrayCustomerCode = new string[] { "ADAM", "MIRANDA", "Jordin", "SPARKS" };
            ICriteria filterDelete = new CustomerDAO().CreateCriteria();
            filterDelete.Add(Condition.In(Customer.Names.Code, arrayCustomerCode));

            _folder.DeleteFilter<Customer>(filterDelete);
            Console.WriteLine("Delete customer by filter : OK");

            //GET CUSTOMERBALANCE OF A CUSTOMER
            var balanceFilterCriteria = new CustomerBalanceDAO().CreateCriteria();
            balanceFilterCriteria.CreateAlias("customer", typeof(Customer), CustomerBalance.Names.Id,
                CustomerBalance.Names.Parent_Id);
            balanceFilterCriteria.Add(Condition.Eq("customer." + Customer.Names.Code, "CERISIERS"));
            var lstCustomerBalance = _folder.GetFilterAll<CustomerBalance>(balanceFilterCriteria, 1);
            Console.WriteLine("Getting customer balance of customer 'CERISIERS' : OK - " + lstCustomerBalance.Count + " records");

            //GET CUSTOMERBALANCE OF A LIST OF CUSTOMER
            var balanceFilterCriteria2 = new CustomerBalanceDAO().CreateCriteria();
            balanceFilterCriteria2.CreateAlias("customer", typeof(Customer), CustomerBalance.Names.Id,
                CustomerBalance.Names.Parent_Id);
            balanceFilterCriteria2.Add(Condition.In("customer." + Customer.Names.Code, new string[] { "DEAN", "DELPH", "COSMOSHOP" }));
            //WE SHOULD SET ENTITYLEVEL IS 2, SO NOW WE WILL KNOW WHICH CUSTOMER BALANCE BELONG TO WHICH CUSTOMER BY OBJECT CUSTOMER INSIDE
            var lstCustomerBalanceOfListCustomer = _folder.GetFilterAll<CustomerBalance>(balanceFilterCriteria2, 2);
            Console.WriteLine("Getting customer balance of list customer : OK - " + lstCustomerBalanceOfListCustomer.Count + " records");

            #endregion

            #region ******** GLACCOUNT - GENEREAL ACCOUNT ********
            Console.WriteLine();
            Console.WriteLine("********* GLACCOUNT - GENEREAL ACCOUNT *********");
            Console.WriteLine();

            //GET BY CODE
            //BY SETTING PARAMETER isShowId = false,THE RESULT RETURN WILL NOT INCLUDE PROPERTY ID, JUST THE CODE
            GLAccount glaccountByCode = _folder.GetByCode<GLAccount>("284000", false);
            Console.WriteLine("Getting glaccount by code '284000': OK");

            //GET BY ID
            //BY SETTING PARAMETER isShowId = true, THE RESULT RETURN WITH ID INSIDE
            _folder.Setting.GetEntityLevel = 2;
            GLAccount glAccountById = _folder.GetById<GLAccount>("74EE6FE6-1F37-44C3-853F-9F9400B4C66C", true);
            Console.WriteLine("Getting glaccount by id : OK");

            //GET BY FILTER : FIND GLACCOUNT HAS  NAME 'Capital Souscrit Ou Capital Personnel'
            ICriteria glAccoutCritetia = new GLAccountDAO().CreateCriteria();
            glAccoutCritetia.Add(Condition.Eq(GLAccount.Names.Name, "Capital Souscrit Ou Capital Personnel"));
            //SEND FILTER REQUEST TO API
            GLAccount glAccountGetByFilter = _folder.GetFilter<GLAccount>(glAccoutCritetia);
            Console.WriteLine("Getting glaccount by name 'Capital Souscrit Ou Capital Personnel' : OK");

            //RETRIEVE SUB ENTITY
            GLAccount glAccountIn2Level = _folder.GetByCode<GLAccount>("284000", 2);
            Console.WriteLine("Getting glaccount with 2 level : OK");

            //GET ALL GLACCOUNT
            IList<GLAccount> lstAllGlAccounts = _folder.GetAll<GLAccount>(1);
            Console.WriteLine("Getting all glaccounts : OK - " + lstAllGlAccounts.Count + " records");


            //GET FILTER ALL 
            //FIND ALL GLACOUNT WHICH HAVE VAT.CODE IS 'BSP21'
            ICriteria criteriaFilterAllGLAccount = new GLAccountDAO().CreateCriteria();
            criteriaFilterAllGLAccount.CreateAlias("vatAccount", typeof(Vat), Vat.Names.Id, GLAccount.Names.Vat_Id);
            criteriaFilterAllGLAccount.Add(Condition.Eq("vatAccount." + Vat.Names.Code, "BSP21"));
            IList<GLAccount> lstGLAccountFilterByVatCode = _folder.GetFilterAll<GLAccount>(criteriaFilterAllGLAccount);
            Console.WriteLine("Getting all glaccounts with vat code 'BSP21' : OK - " + lstGLAccountFilterByVatCode.Count + " records");

            //UPDATE A GLACCOUNT BY ID
            //THIS IS THE GLACCOUNT I HAVE FROM RAPI WITH ID INSIDE
            //NOW I UPDATE 2 PROPERTY AND SEND BACK TO API
            glAccountById.Memo = "this is the memo for demo updating GLAccount By Id";
            glAccountById.MemoType = MemoType.Green;
            _folder.UpdateById<GLAccount>(glAccountById);
            Console.WriteLine("Update glaccount by id : OK");

            //UPDATE A GLACCOUNT BY CODE
            //THIS IS THE GLACCOUNT I HAVE FROM RAPI WITHOUT ID INSIDE, JUST THE CODE
            //NOW I UPDATE 2 PROPERTY AND SEND BACK TO API
            glaccountByCode.Memo = "this is the memo for demo updating GLAccount by Code";
            glaccountByCode.MemoType = MemoType.Yellow;
            _folder.UpdateByCode<GLAccount>(glaccountByCode);
            Console.WriteLine("Update glaccount by code : OK");

            //ANOTHER WAY FOR UPDATING GLACCOUNT
            GLAccount updateGlAccount = new GLAccount();
            //THERE'S ALREADY A GLACCOUNT WITH THIS CODE IN API DATABAASE
            updateGlAccount.Code = "120000";
            updateGlAccount.Memo = "This is the memo for updating glaccount 120000";
            updateGlAccount.MemoType = MemoType.Green;
            //SEND BACK TO API, SKIP THE VALIDATION STEP BY SETTING PARAMETER ISVALIDATED = FALSE
            _folder.Insert<GLAccount>(updateGlAccount, false);
            Console.WriteLine("Update glaccount by another way : OK");

            //UPDATE LIST OF GLACCOUNT
            foreach (var glAccount in lstGLAccountFilterByVatCode)
            {
                glAccount.Memo = "this is the demo for updating glaccount " + glAccount.Name;
                glAccount.MemoType = MemoType.Green;
            }
            _folder.UpdateCollection(lstGLAccountFilterByVatCode);
            Console.WriteLine("Update list glaccounts : OK");

            //ADD ONE GLACCOUNT
            GLAccount newGlAccount = new GLAccount();
            newGlAccount.Code = "180617";
            newGlAccount.Type = 0;
            newGlAccount.Side = 0;
            newGlAccount.MemoType = MemoType.Green;
            newGlAccount.Name = "Led Zeppelin7";

            _folder.Insert<GLAccount>(newGlAccount);
            Console.WriteLine("Insert a new glaccount : OK");

            //ADD ONE GLACCOUNT WITH SUBENTITY INSIDE
            GLAccount newGLAccountWithSubEntity = new GLAccount();
            newGLAccountWithSubEntity.Code = "203718";
            newGLAccountWithSubEntity.Type = 0;
            newGLAccountWithSubEntity.Name = "Alfonso Christopher";
            newGLAccountWithSubEntity.MemoType = MemoType.Green;
            //SET CATEGORY IS AN EXISTING GLCATEGORY WITH CODE VI
            newGLAccountWithSubEntity.Category = new GLCategory();
            newGLAccountWithSubEntity.Category.Code = "VI";
            //NAMESCURRENT IS A SUB-ENTITIES WITH HAVE CASCADE ALL-DELETE-ORPHAN
            newGLAccountWithSubEntity.NamesCurrent = new List<GLAccount_Name>();
            //CREATE NEW GLACCOUNT_NAME
            GLAccount_Name glAccountName = new GLAccount_Name();
            glAccountName.GLAccount = newGLAccountWithSubEntity;
            glAccountName.Name = "Alfonso Christopher";
            glAccountName.BookYear_Id = new Guid("F8999D9A-7EB6-471C-A48F-9F9400B4C5BE");
            glAccountName.Language_Code = "ta";
            //add back to lst NamesCurrent
            newGLAccountWithSubEntity.NamesCurrent.Add(glAccountName);
            //REMEMBER TO SET ENTITYLEVEL EQUAL TO LEVEL WE MODIFY DATA
            _folder.Insert<GLAccount>(newGLAccountWithSubEntity, 2, true, true);
            Console.WriteLine("Insert a new glaccount with sub entity : OK");

            //INSERT A LIST OF GLACCOUNT
            List<GLAccount> lstNewGLAccounts = new List<GLAccount>();
            Dictionary<string, string> dictionGLCodeAndName = new Dictionary<string, string>() { { "259634", "Cash EUR" }, { "299343", "HN-saving seabank USD" }, { "147365", "Advances detailed by receivers" }, { "102832", "ACB cash back" } };
            foreach (var glCodeAndName in dictionGLCodeAndName)
            {
                GLAccount newGLAccount = new GLAccount();
                newGLAccount.Code = glCodeAndName.Key;
                newGLAccount.Type = 0;
                newGLAccount.Side = 0;
                newGLAccount.MemoType = MemoType.Green;
                newGLAccount.Memo = "this is the memo for " + glCodeAndName.Value;
                newGLAccount.Name = glCodeAndName.Value;
                lstNewGLAccounts.Add(newGLAccount);
            }
            _folder.InsertCollection(lstNewGLAccounts, 2);
            Console.WriteLine("Insert list glaccounts : OK");

            //DELETE A GLACCOUNT BY CODE- need to have a procedure delete GLAccount
            // create criteria get all GLAccountBalance_Tot with parent_id is id of glaccount 180617
            var critGLAccountBalance_Tot = new GLAccountBalance_TotDAO().CreateCriteria()
                .CreateAlias("glaccount", typeof(GLAccount), GLAccount.Names.Id, GLAccountBalance_Tot.Names.Parent_Id)
                .Add(Condition.Eq("glaccount." + GLAccount.Names.Code, "180617"));
            _folder.DeleteFilter<GLAccountBalance_Tot>(critGLAccountBalance_Tot);
            // create criteria get all GLAccountBalance_TotCurrency with parent_id is id of glaccount 180617
            var critGLAccountBalanceTot_Currency = new GLAccountBalance_TotCurrencyDAO().CreateCriteria().CreateAlias("glaccount", typeof(GLAccount), GLAccount.Names.Id, GLAccountBalance_TotCurrency.Names.Parent_Id)
                .Add(Condition.Eq("glaccount." + GLAccount.Names.Code, "180617"));
            _folder.DeleteFilter<GLAccountBalance_TotCurrency>(critGLAccountBalanceTot_Currency);
            _folder.DeleteByCode<GLAccount>("180617");

            // folderPARFIWEB.DeleteByCode<GLAccount>("180617");
            Console.WriteLine("Delete glaccount by code '180617' : OK");

            Guid IdToDelete = _folder.GetByCode<GLAccount>("102832", true).Id;
            //DELETE BY ID- need to have a procedure delete GLAccount
            var critGLAccountBalance_Tot102832 = new GLAccountBalance_TotDAO().CreateCriteria()
                .CreateAlias("glaccount", typeof(GLAccount), GLAccount.Names.Id, GLAccountBalance_Tot.Names.Parent_Id)
                .Add(Condition.Eq("glaccount." + GLAccount.Names.Code, "102832"));
            _folder.DeleteFilter<GLAccountBalance_Tot>(critGLAccountBalance_Tot102832);
            // create criteria get all GLAccountBalance_TotCurrency with parent_id is id of glaccount 102832
            var critGLAccountBalanceTot_Currency102832 = new GLAccountBalance_TotCurrencyDAO().CreateCriteria().CreateAlias("glaccount", typeof(GLAccount), GLAccount.Names.Id, GLAccountBalance_TotCurrency.Names.Parent_Id)
                .Add(Condition.Eq("glaccount." + GLAccount.Names.Code, "102832"));
            _folder.DeleteFilter<GLAccountBalance_TotCurrency>(critGLAccountBalanceTot_Currency102832);
            _folder.DeleteById<GLAccount>(IdToDelete);
            Console.WriteLine("Delete glaccount by id : OK");

            //DELETE GLACCOUNT BY FILTER
            string[] lstGlaccountCode = new string[] { "259634", "299343", "147365" };
            //ICriteria filterByCriteria = new GLAccountDAO().CreateCriteria();
            //filterByCriteria.Add(Condition.In(GLAccount.Names.Code, lstGlaccountCode));
            // get lst glaccount 
            //var lstGLAccount = folderPARFIWEB.GetFilterAll<GLAccount>(filterByCriteria);
            //if(lstGLAccount != null)
            //{
            foreach (var glCode in lstGlaccountCode)
            {
                // create filter GLAccountBalance_Tot
                var critChildGLAccountBalanceTot = new GLAccountBalance_TotDAO().CreateCriteria()
                    .CreateAlias("glaccount", typeof(GLAccount), GLAccount.Names.Id, GLAccountBalance_Tot.Names.Parent_Id)
                    .Add(Condition.Eq("glaccount." + GLAccount.Names.Code, glCode));
                _folder.DeleteFilter<GLAccountBalance_Tot>(critChildGLAccountBalanceTot);
                // create filter GLAccountBalanceTot_Currency
                var critChildGLAccountBalanceTot_Currency = new GLAccountBalance_TotCurrencyDAO().CreateCriteria().CreateAlias("glaccount", typeof(GLAccount), GLAccount.Names.Id, GLAccountBalance_TotCurrency.Names.Parent_Id).Add(Condition.Eq("glaccount." + GLAccount.Names.Code, glCode));
                _folder.DeleteFilter<GLAccountBalance_TotCurrency>(critChildGLAccountBalanceTot_Currency);
                // now ok to delete glaccount 
                _folder.DeleteByCode<GLAccount>(glCode);

            }
            //}
            //folderPARFIWEB.DeleteFilter<GLAccount>(filterDeleteByCriteria);
            Console.WriteLine("Delete glaccount by filter : OK");

            //RETRIEVE THE BALANCES OF ONE GLACCOUNT
            ICriteria glAccountBalanceFilter = new GLAccountBalanceDAO().CreateCriteria();
            glAccountBalanceFilter.CreateAlias("glaccount", typeof(GLAccount), GLAccount.Names.Id,
                GLAccountBalance.Names.Parent_Id);
            glAccountBalanceFilter.Add(Condition.Eq("glaccount." + GLAccount.Names.Code, "100000"));
            IList<GLAccountBalance> glAccountBalance = _folder.GetFilterAll<GLAccountBalance>(glAccountBalanceFilter);
            Console.WriteLine("Retrieve the balances of one glaccount : OK - " + glAccountBalance.Count + " records");

            //RETREIVE THE BALANCES OF A LIST GLACCOUNT
            ICriteria glAccountBalanceFilterByListGLAcc = new GLAccountBalanceDAO().CreateCriteria();
            glAccountBalanceFilterByListGLAcc.CreateAlias("glaccount", typeof(GLAccount), GLAccount.Names.Id,
                GLAccountBalance.Names.Parent_Id);
            glAccountBalanceFilterByListGLAcc.Add(Condition.In("glaccount." + GLAccount.Names.Code,
                new string[] { "110000", "130000", "162000" }));
            IList<GLAccountBalance> lstGlAccountBalances =
                _folder.GetFilterAll<GLAccountBalance>(glAccountBalanceFilterByListGLAcc, 2);
            Console.WriteLine("Retrieve the balances of list glaccounts 110000 ,130000 ,162000 : OK - " + lstGlAccountBalances.Count + " records");

            #endregion

            #region ******** GLTRANSACTION ********
            Console.WriteLine();
            Console.WriteLine("********* GLTRANSACTION *********");
            Console.WriteLine();
            //RETRIEVE TRANSACTIONS OF ONE CUSTOMER : NOT MATCHED
            var lstConditionJournal = new List<Condition>();
            lstConditionJournal.Add(Condition.NotEq("gltransheader_journal." + Journal.Names.Type, JournalType.Sales));
            lstConditionJournal.Add(Condition.NotEq("gltransheader_journal." + Journal.Names.Type, JournalType.SalesCreditNote));
            lstConditionJournal.Add(Condition.NotEq("gltransheader_journal." + Journal.Names.Type, JournalType.Purchase));
            lstConditionJournal.Add(Condition.NotEq("gltransheader_journal." + Journal.Names.Type, JournalType.PurchaseCreditNote));
            lstConditionJournal.Add(Condition.NotEq(GLTrans.Names.LineOrder, 0));

            var critGLTransNotMatch = new GLTransDAO().CreateCriteria();
            critGLTransNotMatch.CreateAlias("customer", typeof(Customer), Customer.Names.Id, GLTrans.Names.Customer_Id);
            critGLTransNotMatch.CreateAlias(JoinType.LeftOuterJoin, "glmatch", typeof(GLMatch), GLMatch.Names.Id, GLTrans.Names.GLMatch_Id);
            critGLTransNotMatch.CreateAlias("gltransheader", typeof(GLTransHeader), GLTransHeader.Names.Id, GLTrans.Names.GLTransHeader_Id);
            critGLTransNotMatch.CreateAlias("gltransheader", "gltransheader_journal", typeof(Journal), Journal.Names.Id, GLTransHeader.Names.Journal_Id);
            critGLTransNotMatch.Add(Condition.Or(Condition.IsNull(GLTrans.Names.GLMatch_Id), Condition.Eq("glmatch." + GLMatch.Names.IsMatched, false)));
            critGLTransNotMatch.Add(Condition.Or(Condition.Eq(GLTrans.Names.LineOrder, 0), Condition.And(lstConditionJournal)));
            critGLTransNotMatch.Add(Condition.Eq("customer." + Customer.Names.Code, "STAR"));
            IList<GLTrans> lstGlTransOfCustomer = _folder.GetFilterAll<GLTrans>(critGLTransNotMatch);
            Console.WriteLine("Retrieve transactions not matched of one customer : OK - " + lstGlTransOfCustomer.Count + " records");

            //RETRIEVE TRANSACTION OF ONE CUSTOMER BETWEEN BETWEEN 9/2011 AND 5/2012
            ICriteria getTransBetween2Periods = new GLTransDAO().CreateCriteria();
            getTransBetween2Periods.CreateAlias("customer", typeof(Customer), Customer.Names.Id,
                GLTrans.Names.Customer_Id);
            getTransBetween2Periods.Add(Condition.Eq("customer." + Customer.Names.Code, "STAR"));
            getTransBetween2Periods.CreateAlias("bookPeriod", typeof(BookPeriod), BookPeriod.Names.Id,
                GLTrans.Names.BookPeriod_Id);
            getTransBetween2Periods.Add(Condition.Gt("bookPeriod." + BookPeriod.Names.Begin, new DateTime(2011, 9, 1)));
            getTransBetween2Periods.Add(Condition.Le("bookPeriod." + BookPeriod.Names.End, new DateTime(2012, 5, 31)));
            IList<GLTrans> lstGLTransBetween2Period = _folder.GetFilterAll<GLTrans>(getTransBetween2Periods, 2);
            Console.WriteLine("Retrieve transactions of one customer between 9/2011 and 5/2012: OK - " + lstGLTransBetween2Period.Count + " records");

            //RETRIEVE TRANSACTIONS OF ONE GLACCOUNT 
            ICriteria getTransOfOneGlacccount = new GLTransDAO().CreateCriteria();
            getTransOfOneGlacccount.CreateAlias("glaccount", typeof(GLAccount), GLAccount.Names.Id,
                GLTrans.Names.GLAccount_Id);

            getTransOfOneGlacccount.Add(Condition.Eq("glaccount." + GLAccount.Names.Code, "200000"));

            IList<GLTrans> lstGLTransOfGLAccount = _folder.GetFilterAll<GLTrans>(getTransOfOneGlacccount);
            Console.WriteLine("Retrieve transactions of one glaccount : OK - " + lstGLTransOfGLAccount.Count + " records");
            #endregion

            #region ******** POSTING GLTRANSACTION ********

            Console.WriteLine();
            Console.WriteLine("*********  POSTING SALE GLTRANSACTION  *********");
            Console.WriteLine();

            //BEGIN GET THE PERIOD 12 OF THE BOOKYEAR 2012
            Console.WriteLine("Getting the last Period of last Bookyear.");
            var periodCriteria = new BookPeriodDAO().CreateCriteria()
                .Add(Condition.NotEq(BookPeriod.Names.Number, 0))
                .Add(Condition.NotEq(BookPeriod.Names.Number, 13))
                .SetFirstResult(0).SetMaxResults(1)
                .Order(BookPeriod.Names.RelatedYear, false)
                .Order(BookPeriod.Names.RelatedMonth, false);

            BookPeriod bookPeriod = _folder.GetFilter<BookPeriod>(periodCriteria);
            if (bookPeriod == null)
            {
                return "Cannot find any Periods of the last Bookyear in the current folder.";
            }
            Console.WriteLine("Getting the last Period of last Bookyear - " + bookPeriod.Name + " : OK");
            //END GET PERIOD

            //BEGIN GET CUSTOMER
            Console.WriteLine("Getting the Customer with Code is ALICE");
            Customer customerALICE = _folder.GetByCode<Customer>("ALICE");
            if (customerALICE == null)
            {
                return ("Cannot find Customer with the Code is ALICE in the current folder.");
            }
            Console.WriteLine("Getting the Customer with Code is ALICE : OK");
            //END GET CUSTOMER

            //BEGIN GET DEFAULT CENTRAL ACCOUNT FOR CUSTOMER
            var customerCentralAccountCriteria = new GLAccount_CentralAccountTypeDAO().CreateCriteria()
                .CreateAlias("gLAccount", typeof(GLAccount), GLAccount.Names.Id, GLAccount_CentralAccountType.Names.GLAccount_Id)
                .CreateAlias("centralAccountType", typeof(CentralAccountType), CentralAccountType.Names.Id, GLAccount_CentralAccountType.Names.CentralAccountType_Id)
                .CreateAlias("gLAccount", "gLAccountBookYear", typeof(GLAccount_BookYear), GLAccount_BookYear.Names.GLAccount_Id, GLAccount.Names.Id)
                .Add(Condition.Eq("centralAccountType." + CentralAccountType.Names.Class, CAClass.Customer))
                .Add(Condition.Eq("gLAccountBookYear." + GLAccount_BookYear.Names.BookYear_Id, bookPeriod.BookYear_Id))
                .SetFirstResult(0).SetMaxResults(1);

            GLAccount_CentralAccountType defaultCustomerAccount = _folder.GetFilter<GLAccount_CentralAccountType>(customerCentralAccountCriteria);
            if (defaultCustomerAccount == null)
            {
                return ("Cannot find Customer specific account");
            }
            //END GET DEFAULT CENTRAL ACCOUNT FOR CUSTOMER

            //BEGIN GET JOURNAL
            Console.WriteLine("Getting the Journal with Code FACT");
            var journalCriteria = new JournalDAO().CreateCriteria()
                .Add(Condition.Eq(Journal.Names.BookYear_Id, bookPeriod.BookYear_Id))
                .Add(Condition.Eq(Journal.Names.Code, "FACT"))
                .SetFirstResult(0).SetMaxResults(1);

            Journal journal = _folder.GetFilter<Journal>(journalCriteria);
            if (journal == null)
            {
                return ("Cannot find Journal with the Code FACT in the current folder.");
            }
            Console.WriteLine("Getting the Journal with Code FACT : OK");
            //END GET JOURNAL

            //BEGIN GET CURRENCY
            Console.WriteLine("Getting the Currency with Code EUR");
            Currency currency = _folder.GetByCode<Currency>("EUR");
            if (currency == null)
            {
                return ("Cannot find Currency with the Code EUR in the current folder.");
            }
            Console.WriteLine("Getting the Currency with Code EUR : OK");
            //END GET CURRENCY

            //BEGIN GET VAT
            Console.WriteLine("Getting the VAT with Code 21");
            Vat vat = _folder.GetByCode<Vat>("21", true);
            if (vat == null)
            {
                return ("Cannot find Currency with the Code is EUR in the current folder.");
            }
            Console.WriteLine("Getting the VAT with Code 21 : OK");
            //END GET VAT

            //BEGIN TO GET GLACCOUNT OF VAT
            Console.WriteLine("Getting GLAccount for the VAT with Code 21");
            var vatGLAccountCriteria = new GLAccount_CentralAccountTypeDAO().CreateCriteria()
                .CreateAlias("centralAccountType", typeof(CentralAccountType), CentralAccountType.Names.Id, GLAccount_CentralAccountType.Names.CentralAccountType_Id)
                .Add(Condition.Eq(GLAccount_CentralAccountType.Names.CentralAccountType_Id, vat.CentralAccountType_Id))
                .SetFirstResult(0).SetMaxResults(1);

            GLAccount_CentralAccountType vatGLAccount = _folder.GetFilter<GLAccount_CentralAccountType>(vatGLAccountCriteria);
            if (vatGLAccount == null)
            {
                return ("Cannot find the GLAccount for VAT with Code 21");
            }
            Console.WriteLine("Getting GLAccount for the VAT with Code 21 : OK");
            //END TO GET GLACCOUNT OF VAT

            //BEGIN GET SALE GLACCOUNT
            Console.WriteLine("Getting the turnover Account 700000");
            var turnOverGLAccountCriteria = new GLAccountDAO().CreateCriteria()
                .CreateAlias("gLAccountBookYear", typeof(GLAccount_BookYear), GLAccount_BookYear.Names.GLAccount_Id, GLAccount.Names.Id)
                .Add(Condition.Eq("gLAccountBookYear." + GLAccount_BookYear.Names.BookYear_Id, bookPeriod.BookYear_Id))
                .Add(Condition.Eq(GLAccount.Names.Code, "700000"))
                .SetFirstResult(0).SetMaxResults(1);

            GLAccount turnOverAccount = _folder.GetFilter<GLAccount>(turnOverGLAccountCriteria);
            if (turnOverAccount == null)
            {
                return ("Cannot find GLAccount with the Code is 700000 in the current folder.");
            }
            Console.WriteLine("Getting the turnover Account 700000 : OK");
            //END GET SALE GLACCOUNT

            //GET LAST GLTRANSHEADER DOCUMENT NUMBER
            Console.WriteLine("Getting the last Document Number of Folder");
            var lastHeaderCriteria = new GLTransHeaderDAO().CreateCriteria()
                .CreateAlias("journal", typeof(Journal), Journal.Names.Id, GLTransHeader.Names.Journal_Id)
                .CreateAlias("bookPeriod", typeof(BookPeriod), BookPeriod.Names.Id, GLTransHeader.Names.BookPeriod_Id)
                .Add(Condition.Eq("journal." + Journal.Names.Id, journal.Id))
                .Order(GLTransHeader.Names.DocNumber, false)
                .SetFirstResult(0).SetMaxResults(1);

            GLTransHeader lastHeader = _folder.GetFilter<GLTransHeader>(lastHeaderCriteria);
            long documentNumber = 1;

            if (lastHeader != null)
            {
                Console.WriteLine("Getting the last Document Number of Folder - " + lastHeader.DocNumber + " : OK");
                documentNumber = lastHeader.DocNumber + 1;
            }
            else
                Console.WriteLine("Folder has no document");

            Console.WriteLine("Creating the Document Number " + documentNumber + " for " + journal.Code + " Journal in " + bookPeriod.Name);
            decimal totalAmount = 1000;
            decimal vatBaseAmount = Decimal.Round((1000 / (1 + vat.Rate.Value)), (currency.NumberOfDecimals ?? 2), MidpointRounding.AwayFromZero);
            decimal vatTaxAmount = totalAmount - vatBaseAmount;

            GLTransHeader header = new GLTransHeader();
            header.Journal_Id = journal.Id;
            header.BookPeriod = bookPeriod;
            header.DocNumber = documentNumber;
            header.BookDate = bookPeriod.Begin;
            header.DueDate = header.BookDate;
            //CREATE TRANSACTION FOR CUSTOMER
            GLTrans glTransCustomer = CreateTransaction(header, currency, customerALICE);
            glTransCustomer.GLAccount_Id = customerALICE.GLAccount_Id == Guid.Empty ? defaultCustomerAccount.GLAccount_Id : customerALICE.GLAccount_Id;
            glTransCustomer.CentralAccountType_Id = customerALICE.GLAccount2_Id == Guid.Empty ? defaultCustomerAccount.CentralAccountType_Id : customerALICE.GLAccount2_Id;
            glTransCustomer.Customer = customerALICE;
            glTransCustomer.Amount = totalAmount;
            glTransCustomer.CurrencyAmount = totalAmount;
            glTransCustomer.VatBaseAmount = glTransCustomer.CurrencyVatBaseAmount = vatBaseAmount;
            glTransCustomer.VatTaxAmount = glTransCustomer.CurrencyVatTaxAmount = vatTaxAmount;
            glTransCustomer.TurnOverAmount = vatBaseAmount;
            glTransCustomer.IsCoda = false;
            header.GLTransactions.Add(glTransCustomer);

            //CREATE THE VAT TURN OVER TRANSACTION
            GLTrans glTransTurnOver = CreateTransaction(header, currency, customerALICE);
            glTransTurnOver.GLAccount_Id = turnOverAccount.Id;
            glTransTurnOver.Vat_Id = vat.Id;
            glTransTurnOver.Amount = vatBaseAmount * -1;
            glTransTurnOver.CurrencyAmount = glTransTurnOver.Amount;
            glTransTurnOver.IsCoda = false;
            header.GLTransactions.Add(glTransTurnOver);

            //CREATE THE VAT TRANSACTION
            GLTrans glTransVAT = CreateTransaction(header, currency, customerALICE);
            glTransVAT.GLAccount_Id = vatGLAccount.GLAccount_Id;
            glTransVAT.CentralAccountType_Id = vatGLAccount.CentralAccountType_Id;
            glTransVAT.Vat_Id = vat.Id;
            glTransVAT.Amount = vatTaxAmount * -1;
            glTransVAT.CurrencyAmount = glTransVAT.Amount;
            glTransVAT.VatBaseAmount = vatBaseAmount;
            glTransVAT.CurrencyVatBaseAmount = glTransVAT.VatBaseAmount;
            glTransVAT.IsVatAllocation = true;
            glTransVAT.IsCoda = false;
            header.GLTransactions.Add(glTransVAT);


            _folder.Insert<GLTransHeader>(header, 2);
            Console.WriteLine("Creating the Document Number " + documentNumber + " for " + journal.Code + " Journal in " + bookPeriod.Name + " : OK");

            Console.WriteLine();
            Console.WriteLine("*********  END POSTING SALE GLTRANSACTION *********");
            Console.WriteLine();
            #endregion ******** POSTING GLTRANSACTION ********

            Console.WriteLine("Press any key to cleanup database for next demo : ");
            Console.ReadLine();
            Console.WriteLine("Cleaning database ....");
            CleanUpDataForDemo(_folder);
            Console.WriteLine("Cleaning database : OK");
            Console.WriteLine();
            Console.WriteLine("-------------------------THE END------------------------");
            Console.WriteLine("--------------THANKS YOU FOR USING OUR DEMO--------------");
            Console.ReadLine();
            return "OK";
        }
        private static GLTrans CreateTransaction(GLTransHeader header, Currency currency, Customer customer)
        {
            if (header == null) return null;

            GLTrans glTrans = new GLTrans();
            glTrans.Header = header;
            glTrans.BookPeriod = header.BookPeriod;
            glTrans.Currency = currency;
            glTrans.ValueDate = header.BookPeriod.Begin;
            glTrans.Customer = customer;

            return glTrans;
        }
        public static void CleanUpDataForDemo(EntitiesServices entityService)
        {
            //Delete transaction associcated with customer ALICE
            if (entityService.GetFilterAll<GLTrans>(new GLTransDAO().CreateCriteria()
                .CreateAlias("customer_asociatied", typeof(Customer), Customer.Names.Id, GLTrans.Names.Customer_Id)
                .Add(Condition.Eq("customer_asociatied." + Customer.Names.Code, "ALICE"))
                .JsonCriteriaSerialize()) != null)
            {
                entityService.DeleteFilter<GLTrans>(
              new GLTransDAO().CreateCriteria()
                  .CreateAlias("customer_asociatied", typeof(Customer), Customer.Names.Id, GLTrans.Names.Customer_Id)
                  .Add(Condition.Eq("customer_asociatied." + Customer.Names.Code, "ALICE"))
                  .JsonCriteriaSerialize());
            }

            // Delete Customer Alice
            if (entityService.GetByCode<Customer>("ALICE") != null)
            {
                entityService.DeleteByCode<Customer>("ALICE");
            }
            // Delete Customer kylie 
            if (entityService.GetByCode<Customer>("KYLIE") != null)
            {
                entityService.DeleteByCode<Customer>("KYLIE");
            }
            //Delete customer Miranda
            if (entityService.GetByCode<Customer>("MIRANDA") != null)
            {
                entityService.DeleteByCode<Customer>("MIRANDA");
            }
            //Delete customer Jordin 
            if (entityService.GetByCode<Customer>("JORDIN") != null)
            {
                entityService.DeleteByCode<Customer>("JORDIN");
            }
            //Delete customer Sparks
            if (entityService.GetByCode<Customer>("SPARKS") != null)
            {
                entityService.DeleteByCode<Customer>("SPARKS");
            }
            //Delete glaccount 180617
            DeleteGLAccountByCode("180617", entityService);

            //Delete glaccount 102832
            DeleteGLAccountByCode("102832", entityService);

            //Delete glaccount 203718
            DeleteGLAccountByCode("203718", entityService);

            //Delete glaccount 259634
            DeleteGLAccountByCode("259634", entityService);

            //Delete glaccount 299343
            DeleteGLAccountByCode("299343", entityService);

            //Delete glaccount 147365
            DeleteGLAccountByCode("147365", entityService);
        }

        private static void DeleteGLAccountByCode(string glAccountCode, EntitiesServices entityService)
        {
            if (entityService.GetByCode<GLAccount>(glAccountCode) != null)
            {
                var critGLAccountBalance_Tot = new GLAccountBalance_TotDAO().CreateCriteria()
                    .CreateAlias("glaccount", typeof(GLAccount), GLAccount.Names.Id, GLAccountBalance_Tot.Names.Parent_Id)
                    .Add(Condition.Eq("glaccount." + GLAccount.Names.Code, glAccountCode));
                // checking this criteria is exist 
                var lstGLAccountBalance_Tot = entityService.GetFilterAll<GLAccountBalance_Tot>(critGLAccountBalance_Tot);
                if (lstGLAccountBalance_Tot != null && lstGLAccountBalance_Tot.Count > 0)
                {
                    entityService.DeleteFilter<GLAccountBalance_Tot>(critGLAccountBalance_Tot);
                }

                // create criteria get all GLAccountBalance_TotCurrency with parent_id is id of glaccount
                var critGLAccountBalanceTot_Currency = new GLAccountBalance_TotCurrencyDAO().CreateCriteria().CreateAlias("glaccount", typeof(GLAccount), GLAccount.Names.Id, GLAccountBalance_TotCurrency.Names.Parent_Id)
                    .Add(Condition.Eq("glaccount." + GLAccount.Names.Code, glAccountCode));
                // checking this criteria is exist 
                var lstGLAccountBalanceTot_Currency = entityService.GetFilterAll<GLAccountBalance_TotCurrency>(critGLAccountBalanceTot_Currency);
                if (lstGLAccountBalanceTot_Currency != null && lstGLAccountBalanceTot_Currency.Any())
                {
                    entityService.DeleteFilter<GLAccountBalance_TotCurrency>(critGLAccountBalanceTot_Currency);
                }
                //entityService.DeleteFilter<GLAccountBalance_TotCurrency>(critGLAccountBalanceTot_Currency);
                entityService.DeleteByCode<GLAccount>(glAccountCode);
            }
        }

    }
}
