Exemplo n.º 1
0
        public virtual Dictionary <CostType, double> Calculate(IList costTypes, GetCurrentCostTable costTable, GetCurrentDailyCostTable dailyTable, GetCurrentCruiseExpenseTable getCruiseTable, Cruise activecruise, IList bookings, SailsModule module, bool partnership)
        {
            Cruise = activecruise;
            // Nếu là chi phí từng tàu, tính chi phí cho tàu đó
            // Nếu là chi phí tổng, tính chi phí từng tàu rồi sau đó cộng lại

            #region -- Chi phí cho một tàu --
            if (Cruise != null)
            {
                // Dựng bảng dịch vụ trắng
                Dictionary <CostType, ExpenseService> serviceMap   = new Dictionary <CostType, ExpenseService>();
                Dictionary <CostType, double>         serviceTotal = new Dictionary <CostType, double>();
                foreach (CostType type in costTypes)
                {
                    serviceMap.Add(type, null);
                    serviceTotal.Add(type, 0);
                }

                #region -- Tạo bảng giá trắng và lấy giá nhập thủ công theo thuyến --
                // Kiểm tra xem đã có giá các dịch vụ nào
                foreach (ExpenseService service in Services)
                {
                    // Nếu không thuộc diện tính chi phí cho ngày (không nằm trong danh sách chi phí)
                    if (!serviceMap.ContainsKey(service.Type))
                    {
                        continue;
                    }

                    serviceMap[service.Type] = service;

                    // Nếu là giá nhập thủ công thì cộng luôn
                    if (service.Type.IsDailyInput)
                    {
                        serviceTotal[service.Type] += service.Cost;
                    }
                }
                #endregion

                int adultHaiPhong = 0;
                int childHaiPhong = 0;

                // Tính giá từng dịch vụ với từng booking (chi phí theo số khách )
                #region -- Dịch vụ theo booking (chi phí theo số khách) --
                foreach (Booking booking in bookings)
                {
                    Dictionary <CostType, double> bookingCost = booking.Cost(costTable(Date, booking.Trip, booking.TripOption), costTypes);

                    // Sau khi có bảng giá từng booking thì cộng vào tổng
                    foreach (CostType type in costTypes)
                    {
                        serviceTotal[type] += bookingCost[type];
                    }

                    // Đồng thời tính số người để tính giá thuê tàu Hải Phong luôn
                    adultHaiPhong += booking.Adult;
                    childHaiPhong += booking.Child;
                }
                #endregion

                #region -- Chi phí theo chuyến --
                bool _isRun = bookings.Count > 0; // Nếu có booking thì tính chi phí theo chuyến (tàu có chạy)

                if (_isRun)
                {
                    DailyCostTable table = dailyTable(Date);
                    if (table != null)
                    {
                        foreach (DailyCost cost in dailyTable(Date).Costs)
                        {
                            if (serviceTotal.ContainsKey(cost.Type))
                            {
                                serviceTotal[cost.Type] += cost.Cost; // Luôn cộng luôn chi phí vào tổng
                            }
                        }
                    }
                }

                #endregion

                #region -- Giá tàu Hải Phong --

                // Chỉ tính giá tàu Hải Phong nếu đây là bảng chi phí cho một tàu
                CruiseExpenseTable cruiseTable = getCruiseTable(Date, Cruise);
                CalculateCruiseExpense(costTypes, serviceTotal, adultHaiPhong, childHaiPhong, cruiseTable);

                #endregion

                #region -- Trước khi trả về kết quả, kiểm tra cơ sở dữ liệu --
                foreach (CostType type in costTypes)
                {
                    // Bỏ qua dịch vụ theo ngày vì đã lưu theo từng dịch vụ riêng rẽ
                    if (type.IsDailyInput)
                    {
                        continue;
                    }
                    if (serviceMap[type] != null)
                    {
                        // Nếu giá dịch vụ trong CSDL không bằng thực tính
                        if (serviceMap[type].Cost != serviceTotal[type])
                        {
                            serviceMap[type].Cost = serviceTotal[type];
                            module.SaveOrUpdate(serviceMap[type]);
                        }
                        // Ngược lại thì bỏ qua
                    }
                    else
                    {
                        // Nếu chưa có thì cập nhật mới
                        if (type.DefaultAgency == null && partnership)
                        {
                            throw new Exception("You must config default agency for " + type.Name);
                        }
                        ExpenseService service = new ExpenseService();
                        service.Expense  = this;
                        service.Cost     = serviceTotal[type];
                        service.Name     = string.Format("{0:dd/MM/yyyy}- {1}", Date, type.Name);
                        service.Paid     = 0;
                        service.Supplier = type.DefaultAgency;
                        if (service.Supplier != null)
                        {
                            service.Phone = type.DefaultAgency.Phone;
                        }
                        service.Type = type;
                        module.SaveOrUpdate(service);
                    }
                }
                #endregion
                return(serviceTotal);
            }
            #endregion

            #region -- Chi phí cho tất cả các tàu --
            Dictionary <CostType, double> total = new Dictionary <CostType, double>();
            #region -- Lấy về chi phí cho từng tàu nếu là chi phí tổng --

            //Chi phí cho từng tàu
            //Dictionary<int, SailExpense> expenseCruise = new Dictionary<int, SailExpense>();
            IList cruises = module.CruiseGetAll();

            #region -- Tạo bảng giá trắng --
            foreach (CostType type in costTypes)
            {
                total.Add(type, 0);
            }
            #endregion

            foreach (Cruise cruise in cruises)
            {
                SailExpense expense = module.ExpenseGetByDate(cruise, Date);

                IList filtered = new ArrayList();
                foreach (Booking booking in bookings)
                {
                    if (booking.Cruise != null && booking.Cruise.Id == cruise.Id)
                    {
                        filtered.Add(booking);
                    }
                }

                Dictionary <CostType, double> expenses = expense.Calculate(costTypes, costTable, dailyTable,
                                                                           getCruiseTable, cruise, filtered, module,
                                                                           partnership);
                foreach (CostType type in costTypes)
                {
                    total[type] += expenses[type];
                }
            }

            #endregion

            return(total);

            #endregion
        }
        public static void Export(IList list, int count, IList expenseList, DateTime _date, string bookingFormat, HttpResponse Response, string templatePath, SailsTrip trip, SailsAdminBasePage page)
        {
            SailsModule module = page.Module;
            // Bắt đầu thao tác export

            ExcelFile excelFile = new ExcelFile();

            excelFile.LoadXls(templatePath);

            // Số lệnh điều tua = số lượng group
            int numberOfGroup = -1;

            foreach (Booking booking in list)
            {
                if (booking.Group > numberOfGroup)
                {
                    numberOfGroup = booking.Group;
                }
            }

            foreach (ExpenseService service in expenseList)
            {
                if (service.Group > numberOfGroup)
                {
                    numberOfGroup = service.Group;
                }
            }

            if (numberOfGroup <= 0)
            {
                numberOfGroup = 1; // Tối thiểu là 1 group
            }

            #region -- sheet 0: Lệnh điều tour --
            for (int ii = 0; ii <= numberOfGroup; ii++)
            {
                // Mở sheet 0
                ExcelWorksheet originSheet = excelFile.Worksheets[0];

                int numberOfBooking = 0;
                foreach (Booking booking in list)
                {
                    if (booking.Group == ii)
                    {
                        numberOfBooking++;
                    }
                }

                if (numberOfBooking == 0 && ii == 0)
                {
                    continue;
                }

                ExcelWorksheet sheet = excelFile.Worksheets.AddCopy("LenhDieuTour" + ii, originSheet);

                #region -- Thông tin chung --

                if (expenseList != null)
                {
                    // Các thông tin chèn thêm
                    foreach (ExpenseService service in expenseList)
                    {
                        if (service.Group != ii)
                        {
                            continue;
                        }

                        switch (service.Type.Id)
                        {
                        case SailsModule.GUIDE_COST:
                            if (service.Type.IsCustomType || service.Supplier == null)
                            {
                                if (string.IsNullOrEmpty(service.Name) && service.Supplier != null)
                                {
                                    sheet.Cells["C3"].Value = service.Supplier.Name;
                                }
                                else
                                {
                                    sheet.Cells["C3"].Value = service.Name;
                                }
                                if (string.IsNullOrEmpty(service.Name) && service.Supplier != null)
                                {
                                    sheet.Cells["F3"].Value = service.Supplier.Phone;
                                }
                                else
                                {
                                    sheet.Cells["F3"].Value = service.Phone;
                                }
                            }
                            else
                            {
                                sheet.Cells["C3"].Value = service.Supplier.Name;
                                sheet.Cells["f3"].Value = service.Supplier.Phone;
                            }
                            break;

                        case SailsModule.TRANSPORT:
                            if (service.Type.IsCustomType || service.Supplier == null)
                            {
                                if (string.IsNullOrEmpty(service.Name) && service.Supplier != null)
                                {
                                    sheet.Cells["C4"].Value = service.Supplier.Name;
                                }
                                else
                                {
                                    sheet.Cells["C4"].Value = service.Name;
                                }
                                if (string.IsNullOrEmpty(service.Name) && service.Supplier != null)
                                {
                                    sheet.Cells["F4"].Value = service.Supplier.Phone;
                                }
                                else
                                {
                                    sheet.Cells["F4"].Value = service.Phone;
                                }
                            }
                            else
                            {
                                sheet.Cells["C4"].Value = service.Supplier.Name;
                                sheet.Cells["f4"].Value = service.Supplier.Phone;
                            }
                            break;

                        case SailsModule.HOTEL:
                            if (service.Supplier != null)
                            {
                                sheet.Cells["C7"].Value = service.Supplier.Name;
                            }
                            else
                            {
                                sheet.Cells["C7"].Value = service.Name;
                            }
                            break;
                        }
                    }
                }

                sheet.Cells["D1"].Value = _date;

                // Tính tổng pax
                int adult = 0;
                int child = 0;
                int baby  = 0;

                int pAdult = 0;
                int pChild = 0;
                int pBaby  = 0;

                foreach (Booking booking in list)
                {
                    if (booking.StartDate == _date && booking.Group == ii)
                    {
                        adult += booking.Adult;
                        child += booking.Child;
                        baby  += booking.Baby;
                    }
                    else if (booking.Group == ii)
                    {
                        pAdult += booking.Adult;
                        pChild += booking.Child;
                        pBaby  += booking.Baby;
                    }
                }

                int pax = adult + child + pAdult + pChild;

                sheet.Cells["C5"].Value  = page.UserIdentity.FullName;
                sheet.Cells["C6"].Value  = pax;
                sheet.Cells["C12"].Value = adult;
                sheet.Cells["D12"].Value = child;
                sheet.Cells["E12"].Value = baby;

                sheet.Cells["C18"].Value = pAdult;
                sheet.Cells["D18"].Value = pChild;
                sheet.Cells["E18"].Value = pBaby;

                #endregion

                #region -- Sao chép các dòng --

                // Sao chép dòng đầu theo số lượng booking
                // Dòng đầu tiên là dòng 11
                const int firstrow = 10;

                // Đếm số book trong ngày
                int curr = 0;
                foreach (Booking booking in list)
                {
                    if (booking.StartDate == _date && booking.Group == ii)
                    {
                        curr += 1;
                    }
                }

                sheet.Rows[16].InsertCopy(count - curr - 1, sheet.Rows[firstrow]);
                if (curr > 0)
                {
                    sheet.Rows[firstrow].InsertCopy(curr - 1, sheet.Rows[firstrow]);
                }
                int firstProw = 16 + curr;

                #endregion

                #region -- Thông tin từng booking --

                // Ghi vào file excel theo từng dòng
                int crow  = firstrow;
                int cProw = firstProw - 1;
                foreach (Booking booking in list)
                {
                    if (booking.Group != ii)
                    {
                        continue;
                    }
                    sheet.Cells["D2"].Value = string.Format("{0}{1:ddMMyy}-{2:00}", booking.Trip.TripCode, booking.StartDate, booking.Group);
                    int current;
                    int index;
                    if (booking.StartDate != _date)
                    {
                        // Dòng previous hiện tại
                        current = cProw;
                        // Index = cột previous hiện tại - previous đầu tiên
                        index = cProw - firstProw + 2;
                        cProw++;
                    }
                    else
                    {
                        current = crow;
                        index   = crow - firstrow + 1;
                        crow++;
                    }
                    sheet.Cells[current, 0].Value = index; // Cột index
                    string name = booking.CustomerName.Replace("<br/>", "\n");
                    if (name.Length > 0)
                    {
                        name = name.Remove(name.Length - 1);
                    }
                    sheet.Cells[current, 1].Value = name;                   // Cột name
                    sheet.Cells[current, 2].Value = booking.Adult;          // Cột adult
                    sheet.Cells[current, 3].Value = booking.Child;          // Cột child
                    sheet.Cells[current, 4].Value = booking.Baby;           // Cột baby
                    sheet.Cells[current, 5].Value = booking.Trip.TripCode;  // Cột trip code
                    sheet.Cells[current, 6].Value = booking.PickupAddress;  // Cột pickup address
                    sheet.Cells[current, 7].Value = booking.SpecialRequest; // Cột special request

                    sheet.Cells[current, 9].Style.Borders.SetBorders(MultipleBorders.Outside, System.Drawing.Color.Black, LineStyle.Thin);

                    if (booking.Agency != null)
                    {
                        sheet.Cells[current, 8].Value = booking.Agency.Name; // Cột agency

                        if (!string.IsNullOrEmpty(booking.AgencyCode))
                        {
                            sheet.Cells[current, 9].Value = booking.AgencyCode;
                            // Chỉ hiển thị nếu có agency (cột TA COde)
                        }
                        else
                        {
                            if (booking.CustomBookingId > 0)
                            {
                                sheet.Cells[current, 9].Value = string.Format(bookingFormat, booking.CustomBookingId);
                            }
                            else
                            {
                                sheet.Cells[current, 9].Value = string.Format(bookingFormat, booking.Id);
                            }
                        }
                    }
                    else
                    {
                        sheet.Cells[current, 8].Value = SailsModule.NOAGENCY; // Hiển thị oriental nếu ko có agency

                        if (booking.CustomBookingId > 0)
                        {
                            sheet.Cells[current, 9].Value = string.Format(bookingFormat, booking.CustomBookingId);
                        }
                        else
                        {
                            sheet.Cells[current, 9].Value = string.Format(bookingFormat, booking.Id);
                        }
                    }

                    if (booking.PickupTime != null)
                    {
                        sheet.Cells[current, 10].Value = booking.PickupTime.Value.ToString("HH:mm");
                    }

                    if (booking.SeeoffTime != null)
                    {
                        sheet.Cells[current, 11].Value = booking.SeeoffTime.Value.ToString("HH:mm");
                    }

                    if (trip.Name.ToLower() != "airport transfer")
                    {
                        sheet.Columns[11].Delete();
                    }

                    if (trip.Name.ToLower() != "airport transfer")
                    {
                        sheet.Columns[10].Delete();
                    }
                }


                #endregion

                // Mở sheet 1
                originSheet = excelFile.Worksheets[1];
                ExcelWorksheet budget = excelFile.Worksheets.AddCopy("Budget" + ii, originSheet);

                budget.Cells["C3"].Value = sheet.Cells["C3"].Value;
                budget.Cells["C4"].Value = sheet.Cells["C4"].Value;
                budget.Cells["A1"].Value = sheet.Cells["D1"].Value;
                budget.Cells["C5"].Value = page.UserIdentity.FullName;
                budget.Cells["C6"].Value = sheet.Cells["C6"].Value;

                budget.Cells["A1"].Value = string.Format("{0}{1:ddMMyyyy}", trip.TripCode, _date);

                // Các chi phí xuất ra bao gồm chi phí theo ngày và chi phí theo khách
                ExpenseCalculator calculator = new ExpenseCalculator(module, true);
                SailExpense       expense    = module.ExpenseGetByDate(trip, _date);
                IList             expenses   = module.ExpenseServiceGet(trip, _date, _date, null, null, null, null, false, null, 0, "");


                CostingTable cost      = calculator.GetCurrentTable(_date, trip, TripOption.Option1);
                IList        costTypes = new ArrayList();
                foreach (KeyValuePair <CostType, double> entry in module.CostTypeGetAutoDailyBase())
                {
                    costTypes.Add(entry.Key);
                }
                Dictionary <CostType, Costing> unitPrices = cost.GetCostMap(costTypes);


                const int first = 8;
                curr = first;

                foreach (ExpenseService entry in expenses)
                {
                    if (entry.Group != ii)
                    {
                        continue;
                    }

                    if (entry.Type.IsPayNow)
                    {
                        if (entry.Type.IsDailyInput)// Nếu là chi phí nhập tay
                        {
                            if (entry.Cost == 0)
                            {
                                continue;
                            }
                            budget.Rows[curr].InsertCopy(1, budget.Rows[curr]);
                            budget.Cells[curr, 0].Value = curr - first + 1;
                            budget.Cells[curr, 1].Value = _date;
                            if (entry.Type.Name.ToLower().Contains("others"))
                            {
                                budget.Cells[curr, 2].Value = entry.Name;
                            }
                            else
                            {
                                budget.Cells[curr, 2].Value = entry.Type.Name;
                            }
                            budget.Cells[curr, 3].Value = entry.Cost; // chi phí dành cho cả đoàn
                            budget.Cells[curr, 4].Value = entry.Cost;
                            curr++;
                        }
                        else if (!entry.Type.IsMonthly && !entry.Type.IsYearly)
                        {
                            double value = unitPrices[entry.Type].Adult * adult;

                            if (value > 0)
                            {
                                budget.Rows[curr].InsertCopy(1, budget.Rows[curr]);
                                budget.Cells[curr, 0].Value = curr - first + 1;
                                budget.Cells[curr, 1].Value = _date;
                                budget.Cells[curr, 2].Value = entry.Type.Name + " (adult)";
                                budget.Cells[curr, 3].Value = unitPrices[entry.Type].Adult; // giá adult
                                budget.Cells[curr, 4].Value = value;
                                curr++;
                            }

                            value = unitPrices[entry.Type].Child * child;

                            if (value > 0)
                            {
                                budget.Rows[curr].InsertCopy(1, budget.Rows[curr]);
                                budget.Cells[curr, 0].Value = curr - first + 1;
                                budget.Cells[curr, 1].Value = _date;
                                budget.Cells[curr, 2].Value = entry.Type.Name + " (child)";
                                budget.Cells[curr, 3].Value = unitPrices[entry.Type].Child; // giá adult
                                budget.Cells[curr, 4].Value = value;
                                curr++;
                            }

                            value = unitPrices[entry.Type].Baby * baby;

                            if (value > 0)
                            {
                                budget.Rows[curr].InsertCopy(1, budget.Rows[curr]);
                                budget.Cells[curr, 0].Value = curr - first + 1;
                                budget.Cells[curr, 1].Value = _date;
                                budget.Cells[curr, 2].Value = entry.Type.Name + " (baby)";
                                budget.Cells[curr, 3].Value = unitPrices[entry.Type].Baby; // giá adult
                                budget.Cells[curr, 4].Value = value;
                                curr++;
                            }
                        }
                    }
                }
            }

            #endregion

            #region -- sheet 1:
            //if (excelFile.Worksheets.Count == 1)
            //{
            //    goto end;
            //}
            //ExcelWorksheet budget = excelFile.Worksheets[1];
            #endregion

end:
            #region -- Trả dữ liệu về cho người dùng --

            Response.Clear();
            Response.Buffer      = true;
            Response.ContentType = "application/vnd.ms-excel";
            Response.AppendHeader("content-disposition",
                                  "attachment; filename=" + string.Format("Lenhdieutour{0:dd_MMM}.xls", _date));

            MemoryStream m = new MemoryStream();

            excelFile.SaveXls(m);

            Response.OutputStream.Write(m.GetBuffer(), 0, m.GetBuffer().Length);
            Response.OutputStream.Flush();
            Response.OutputStream.Close();

            m.Close();
            Response.End();

            #endregion
        }
Exemplo n.º 3
0
        public virtual Dictionary <CostType, double> Calculate(IList costTypes, GetCurrentCostTable costTable, GetCurrentDailyCostTable dailyTable, GetCurrentCruiseExpenseTable getCruiseTable, Cruise activecruise, IList bookings, SailsModule module, bool partnership)
        {
            Cruise = activecruise;

            if (Cruise != null)
            {
                Dictionary <CostType, ExpenseService> serviceMap   = new Dictionary <CostType, ExpenseService>();
                Dictionary <CostType, double>         serviceTotal = new Dictionary <CostType, double>();
                foreach (CostType type in costTypes)
                {
                    serviceMap.Add(type, null);
                    serviceTotal.Add(type, 0);
                }

                foreach (ExpenseService service in Services)
                {
                    if (!serviceMap.ContainsKey(service.Type))
                    {
                        continue;
                    }
                    serviceMap[service.Type] = service;
                    if (service.Type.IsDailyInput)
                    {
                        serviceTotal[service.Type] += service.Cost;
                    }
                }
                int adultHaiPhong = 0;
                int childHaiPhong = 0;

                foreach (Booking booking in bookings)
                {
                    Dictionary <CostType, double> bookingCost = booking.Cost(costTable(Date, booking.Trip, booking.TripOption), costTypes);
                    foreach (CostType type in costTypes)
                    {
                        serviceTotal[type] += bookingCost[type];
                    }

                    adultHaiPhong += booking.Adult;
                    childHaiPhong += booking.Child;
                }

                bool _isRun = bookings.Count > 0;

                if (_isRun)
                {
                    DailyCostTable table = dailyTable(Date);
                    if (table != null)
                    {
                        foreach (DailyCost cost in dailyTable(Date).Costs)
                        {
                            if (serviceTotal.ContainsKey(cost.Type))
                            {
                                serviceTotal[cost.Type] += cost.Cost;
                            }
                        }
                    }
                }

                CruiseExpenseTable cruiseTable = getCruiseTable(Date, Cruise);
                CalculateCruiseExpense(costTypes, serviceTotal, adultHaiPhong, childHaiPhong, cruiseTable);

                foreach (CostType type in costTypes)
                {
                    if (type.IsDailyInput)
                    {
                        continue;
                    }
                    if (serviceMap[type] != null)
                    {
                        if (serviceMap[type].Cost != serviceTotal[type])
                        {
                            serviceMap[type].Cost = serviceTotal[type];
                            module.SaveOrUpdate(serviceMap[type]);
                        }
                    }
                    else
                    {
                        if (type.DefaultAgency == null && partnership)
                        {
                            throw new Exception("You must config default agency for " + type.Name);
                        }
                        ExpenseService service = new ExpenseService();
                        service.Expense  = this;
                        service.Cost     = serviceTotal[type];
                        service.Name     = string.Format("{0:dd/MM/yyyy}- {1}", Date, type.Name);
                        service.Paid     = 0;
                        service.Supplier = type.DefaultAgency;
                        if (service.Supplier != null)
                        {
                            service.Phone = type.DefaultAgency.Phone;
                        }
                        service.Type = type;
                        module.SaveOrUpdate(service);
                    }
                }
                return(serviceTotal);
            }

            Dictionary <CostType, double> total = new Dictionary <CostType, double>();
            IList cruises = module.CruiseGetAll();

            foreach (CostType type in costTypes)
            {
                total.Add(type, 0);
            }

            foreach (Cruise cruise in cruises)
            {
                Expense expense = module.ExpenseGetByDate(cruise, Date);

                IList filtered = new ArrayList();
                foreach (Booking booking in bookings)
                {
                    if (booking.Cruise != null && booking.Cruise.Id == cruise.Id)
                    {
                        filtered.Add(booking);
                    }
                }

                Dictionary <CostType, double> expenses = expense.Calculate(costTypes, costTable, dailyTable,
                                                                           getCruiseTable, cruise, filtered, module,
                                                                           partnership);
                foreach (CostType type in costTypes)
                {
                    total[type] += expenses[type];
                }
            }
            return(total);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Tính toán chi phí đưa về dạng từ điển: loại chi phí - chi phí
        /// </summary>
        /// <param name="costTypes">Toàn bộ chi phí tính được theo ngày</param>
        /// <param name="costTable">Hàm lấy bảng giá theo khách theo thời điểm xác định</param>
        /// <param name="dailyTable">Hàm lấy bảng giá theo chuyến</param>
        /// <param name="getCruiseTable">Bảng giá thuê tàu</param>
        /// <param name="activecruise">Tàu hiện tại</param>
        /// <param name="bookings">Danh sách booking có trong ngày</param>
        /// <param name="module">SailsModule (dùng để tác động tới CSDL)</param>
        /// <param name="partnership">Có quản lý đối tác sử dụng chi phí không</param>
        /// <returns></returns>
        public virtual Dictionary <CostType, double> Calculate(IList costTypes, GetCurrentCostTable costTable, GetCurrentDailyCostTable dailyTable, GetCurrentCruiseExpenseTable getCruiseTable, SailsTrip activecruise, IList bookings, SailsModule module, bool partnership, Organization org = null)
        {
            _trip = activecruise;
            // Nếu là chi phí từng tàu, tính chi phí cho tàu đó
            // Nếu là chi phí tổng, tính chi phí từng tàu rồi sau đó cộng lại

            #region -- Chi phí cho một hành trình --
            if (_trip != null)
            {
                // Dựng bảng dịch vụ trắng: mỗi loại dịch vụ phát sinh một chi phí duy nhất
                var serviceMap   = new Dictionary <CostType, ExpenseService>();
                var serviceTotal = new Dictionary <CostType, double>();
                foreach (CostType type in costTypes)
                {
                    serviceMap.Add(type, null);
                    serviceTotal.Add(type, 0);
                }

                #region -- Tạo bảng giá trắng và lấy giá nhập thủ công theo thuyến --
                // Kiểm tra xem đã có giá các dịch vụ nào
                foreach (ExpenseService service in Services)
                {
                    serviceMap[service.Type] = service;
                    // Nếu không thuộc diện tính chi phí cho ngày (không nằm trong danh sách chi phí)
                    //TODO: Kiểm tra lại có cần điều kiện sau không?
                    if (!serviceMap.ContainsKey(service.Type)) //|| !Trip.CostTypes.Contains(service.Type))
                    {
                        continue;
                    }


                    // Nếu là giá nhập thủ công thì cộng luôn
                    if (service.Type.IsDailyInput)
                    {
                        serviceTotal[service.Type] += service.Cost;
                    }
                }
                #endregion

                int adultHaiPhong = 0;
                int childHaiPhong = 0;

                // Tính giá từng dịch vụ với từng booking (chi phí theo số khách )
                #region -- Dịch vụ theo booking (chi phí theo số khách) - chỉ dùng để tính vào tổng chi phí không lưu vào CSDL --
                foreach (Booking booking in bookings)
                {
                    Dictionary <CostType, double> bookingCost;
                    try
                    {
                        bookingCost = booking.Cost(costTable(Date, booking.Trip, booking.TripOption), costTypes);
                    }
                    catch (Exception ex)
                    {
                        break;
                    }

                    // Sau khi có bảng giá từng booking thì cộng vào tổng
                    foreach (CostType type in costTypes)
                    {
                        serviceTotal[type] += bookingCost[type];
                    }

                    // Đồng thời tính số người để tính giá thuê tàu Hải Phong luôn
                    adultHaiPhong += booking.Adult;
                    childHaiPhong += booking.Child;
                }
                #endregion

                // Bắt đầu tính chi phí từ tháng 7, còn trước tháng 7 không sử dụng biện pháp này
                if (Date >= new DateTime(2013, 7, 1))
                //if (true) //TODO: chuyển sang điều kiện datetime, đang debug
                {
                    #region -- Dịch vụ theo booking (chi phí theo số khách) chia nhỏ theo group --

                    int numberOfGroup = NumberOfGroup;
                    for (int ii = 1; ii <= numberOfGroup; ii++)
                    {
                        var serviceGroup = new Dictionary <CostType, double>();
                        foreach (CostType type in costTypes)
                        {
                            serviceGroup.Add(type, 0);
                        }

                        foreach (Booking booking in bookings)
                        {
                            if (booking.Group == ii)
                            {
                                Dictionary <CostType, double> bookingCost;
                                try
                                {
                                    bookingCost = booking.Cost(costTable(Date, booking.Trip, booking.TripOption),
                                                               costTypes);
                                }
                                catch (Exception ex)
                                {
                                    continue;
                                }
                                // Sau khi có bảng giá từng booking thì cộng vào tổng
                                foreach (CostType type in costTypes)
                                {
                                    serviceGroup[type] += bookingCost[type];
                                }
                            }
                        }

                        // Sau khi có chi phí tổng rồi check CSDL
                        foreach (CostType type in costTypes)
                        {
                            // Bỏ qua dịch vụ theo ngày vì đã lưu theo từng dịch vụ riêng rẽ
                            if (type.IsDailyInput)
                            {
                                continue;
                            }

                            #region -- Check trong cơ sở dữ liệu --

                            bool found = false;
                            foreach (ExpenseService service in Services)
                            {
                                if (service.Type.Id == type.Id && service.Group == ii)
                                {
                                    // Đã có dịch vụ, nếu chi phí không bằng thực tính thì lưu lại
                                    if (service.Cost != serviceGroup[type])
                                    {
                                        service.Cost = serviceGroup[type];
                                        module.SaveOrUpdate(service);
                                    }
                                    // Đã thấy service thì có thể break
                                    found = true;
                                    break;
                                }
                            }

                            if (!found && serviceGroup[type] > 0) // Nếu chưa có và phát sinh chi phí thì tạo mới
                            {
                                if (type.DefaultAgency == null && partnership)
                                {
                                    throw new Exception("You must config default agency for " + type.Name);
                                }
                                var service = new ExpenseService();
                                service.Expense  = this;
                                service.Cost     = serviceGroup[type];
                                service.Name     = string.Format("{0:dd/MM/yyyy}- {1}", Date, type.Name);
                                service.Paid     = 0;
                                service.Supplier = type.DefaultAgency;
                                service.Group    = ii;
                                if (service.Supplier != null)
                                {
                                    service.Phone = type.DefaultAgency.Phone;
                                }
                                service.Type = type;
                                module.SaveOrUpdate(service);
                            }

                            #endregion
                        }
                    }

                    #endregion
                }

                #region -- Chi phí theo chuyến: bỏ qua không sử dụng --
                //bool _isRun = bookings.Count > 0; // Nếu có booking thì tính chi phí theo chuyến (tàu có chạy)

                //if (_isRun)
                //{
                //    DailyCostTable table = dailyTable(Date);
                //    if (table != null)
                //    {
                //        foreach (DailyCost cost in dailyTable(Date).Costs)
                //        {
                //            if (serviceTotal.ContainsKey(cost.Type))
                //            {
                //                serviceTotal[cost.Type] += cost.Cost; // Luôn cộng luôn chi phí vào tổng
                //            }
                //        }
                //    }
                //}

                #endregion

                #region -- Giá tàu Hải Phong --

                // Chỉ tính giá tàu Hải Phong nếu đây là bảng chi phí cho một tàu
                CruiseExpenseTable cruiseTable = getCruiseTable(_date, _trip);
                CalculateCruiseExpense(costTypes, serviceTotal, adultHaiPhong, childHaiPhong, cruiseTable);

                #endregion

                #region -- Trước khi trả về kết quả, kiểm tra cơ sở dữ liệu --
                foreach (CostType type in costTypes)
                {
                    // Bỏ qua dịch vụ theo ngày vì đã lưu theo từng dịch vụ riêng rẽ
                    if (type.IsDailyInput)
                    {
                        continue;
                    }

                    #region -- Bỏ qua không lưu chi phí phát sinh theo số khách ở đây --
                    //if (serviceMap[type] != null)
                    //{
                    //    // Nếu giá dịch vụ trong CSDL không bằng thực tính
                    //    if (serviceMap[type].Cost != serviceTotal[type])
                    //    {
                    //        serviceMap[type].Cost = serviceTotal[type];
                    //        module.SaveOrUpdate(serviceMap[type]);
                    //    }
                    //    // Ngược lại thì bỏ qua
                    //}
                    //else
                    //{
                    //    // Nếu chưa có thì cập nhật mới: đối với chi phí tính theo đầu người là chủ yếu
                    //    if (type.DefaultAgency == null && partnership)
                    //    {
                    //        throw new Exception("You must config default agency for " + type.Name);
                    //    }
                    //    var service = new ExpenseService();
                    //    service.Expense = this;
                    //    service.Cost = serviceTotal[type];
                    //    service.Name = string.Format("{0:dd/MM/yyyy}- {1}", Date, type.Name);
                    //    service.Paid = 0;
                    //    service.Supplier = type.DefaultAgency;
                    //    if (service.Supplier != null)
                    //    {
                    //        service.Phone = type.DefaultAgency.Phone;
                    //    }
                    //    service.Type = type;
                    //    module.SaveOrUpdate(service);
                    //}
                    #endregion
                }
                #endregion

                return(serviceTotal);
            }
            #endregion

            #region -- Chi phí cho tất cả các hành trình trong ngày --
            var total = new Dictionary <CostType, double>();

            #region -- Lấy về chi phí cho từng tàu nếu là chi phí tổng --

            //Chi phí cho từng tàu
            //Dictionary<int, SailExpense> expenseCruise = new Dictionary<int, SailExpense>();
            IList trips;
            if (org != null)
            {
                trips = module.TripGetByOrganization(org);
            }
            else
            {
                trips = module.TripGetAll(false, null);
            }

            #region -- Tạo bảng giá trắng --
            foreach (CostType type in costTypes)
            {
                total.Add(type, 0);
            }
            #endregion

            foreach (SailsTrip trip in trips)
            {
                SailExpense expense = module.ExpenseGetByDate(trip, _date);
                if (expense.Id < 0)
                {
                    module.SaveOrUpdate(expense);
                }

                IList filtered = new ArrayList(); // Lọc các booking theo hành trình xác định
                foreach (Booking booking in bookings)
                {
                    if (booking.Trip != null && booking.Trip.Id == trip.Id)
                    {
                        filtered.Add(booking);
                    }
                }

                Dictionary <CostType, double> expenses = expense.Calculate(costTypes, costTable, dailyTable,
                                                                           getCruiseTable, trip, filtered, module,
                                                                           partnership);
                foreach (CostType type in costTypes)
                {
                    total[type] += expenses[type];
                }
            }

            #endregion

            return(total);

            #endregion
        }