FuelProcessing.Data — Data Access Layer¶
Обзор¶
FuelProcessing.Data — это уровень доступа к данным, содержащий репозитории, Entity Framework контекст, API клиенты для интеграции с ВИНК и бизнес-сервисы.
Структура¶
FuelProcessing.Data/
├── Context/
│ ├── DataContext.cs # Основной EF DbContext
│ ├── BuildConfigs/ # IEntityTypeConfiguration реализации
│ │ ├── CompanyConfiguration.cs
│ │ └── DirectContractOverdraftResetRequestConfiguration.cs
│ └── Seed/ # Начальные данные (seed data)
│ ├── AdminConfiguration.cs
│ ├── RoleConfiguration.cs
│ ├── SystemConfigConfiguration.cs
│ └── SystemSettingsConfigureation.cs
├── Repository/
│ ├── Base/
│ │ ├── BaseRepository.cs # Базовый класс репозитория
│ │ └── ApiBaseRepository.cs # Для API операций
│ ├── CardRepository.cs
│ ├── CompanyRepository.cs
│ ├── DirectContractRepository.cs
│ ├── FinanceTransactionRepository.cs
│ ├── ContractTermRepository.cs
│ ├── ContractTermTemplateRepository.cs
│ ├── UserRepository.cs
│ ├── ReportRepository.cs
│ ├── NewsRepository.cs
│ ├── CardChangeLogRepository.cs
│ ├── CurrentContractBalanceRepository.cs
│ ├── ContractPayInfoRepository.cs
│ ├── CardGroupRepository.cs
│ ├── FuelTypeRepository.cs
│ ├── FuelTypeForMapRepository.cs
│ ├── NewsCompanyRepository.cs
│ ├── RegionDirectContractWithVendorDiscountRepository.cs
│ └── ... (17 репозиториев)
├── Mapping/ # AutoMapper профили
├── Helpers/ # Вспомогательные классы
├── Migrations/ # EF Core миграции (200+ файлов)
├── Services/ # Бизнес-сервисы
├── Workers/ # Фоновые задачи
└── LoggerConfig.cs # Конфигурация Serilog
DataContext¶
Entity Framework Core контекст с PostgreSQL.
Базовый класс¶
public class DataContext : IdentityDbContext<
User, Role, int,
IdentityUserClaim<int>, UserRole, IdentityUserLogin<int>,
IdentityRoleClaim<int>, IdentityUserToken<int>>
{
public DataContext(DbContextOptions<DataContext> options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
}
public override EntityEntry<TEntity> Update<TEntity>(TEntity entity)
{
if (entity is Entity entityItem)
entityItem.LastModifed = DateTime.UtcNow;
SaveChanges();
return base.Update(entity);
}
}
DbSet Properties (70+ сущностей)¶
| DbSet | Описание |
|---|---|
Companies |
Компании |
Cards |
Топливные карты |
CardGroups |
Группы карт |
CardOwners |
Владельцы карт |
CardOwnerLimits |
Лимиты владельцев |
CardLogs |
Логи изменений карт |
CardChangeLogs |
История изменений |
IssuingСards |
Выдачи карт |
DirectContracts |
Прямые договоры между компаниями |
DirectContractsWithVendor |
Прямые договоры с ВИНК |
DirectContractOverdraftResetRequests |
Запросы сброса овердрафта |
ContractTerms |
Условия по договору |
ContractTermTemplates |
Шаблоны условий по договору |
ContractTermTemplatePlans |
Запланированные шаблоны скидок |
ContractPayInfos |
Оплаты по договору |
ContractPayInfoDatas |
Данные о предыдущих платежах |
CurrentContractBalances |
Текущие балансы |
CurrentComissionBalances |
Баланс по комиссиям |
CurrentTemporaryOverdrafts |
Изменения временного овердрафта |
FinanceTransaction |
Финансовые транзакции |
FinanceTransactionParts |
Части финансовой транзакции |
DeletedFinanceTransactionForReports |
Удаленные транзакции для отчетов |
MinusBalanceTransactionToDirectContracts |
Транзакции при отрицательном балансе |
GasStations |
Заправки (АЗС) |
GasStationsForRouting |
Заправки для построения маршрутов |
FuelOnGasStations |
Топливо на АЗС |
FuelOnGasStationsForRouting |
Цены заправок для маршрутов |
FuelTypes |
Виды топлива (АИ-96, дизель и т.д.) |
FuelCategories |
Категории топлива (газ, бензин) |
FuelTypeVink |
Названия по версии ВИНК |
FuelTypeVinkForRouting |
Виды топлива по версии ВИНК для маршрута |
FuelTypeVinkDiscounts |
Скидки на топливо ВИНК по договору |
FuelPriceForTemplates |
Цена для топлива по шаблону |
FuelPriceForTemplatePlans |
Запланированная цена топлива по шаблону |
RosneftVinkFuelTypes |
Типы топлива Роснефть |
GlobaltruckVinkFuelTypes |
Типы топлива Globaltruck |
GasStationBrands |
Бренды заправок |
GasStationVinkBrands |
Бренды заправок по ВИНК |
Regions |
Регионы |
ApiRegionVinks |
Регионы по версии ВИНК |
Tracks |
Трассы |
Users |
Пользователи (Identity) |
Roles |
Роли (Identity) |
OrganisationInfo |
Информация по организациям |
Resources |
Ресурсы (локализация) |
Cultures |
Культуры (локализация) |
SystemSettings |
Настройки системы |
SystemConfigs |
Конфиги системы |
SystemDatas |
Системные настройки |
ApiMonitoring |
Данные синхронизации |
MonitorProcessInfos |
Данные мониторинга |
ApiCardInfos |
Данные API по карте |
ApiCardGroupInfos |
Данные API по группе |
ApiLimitInfo |
Данные API по лимитам |
Limits |
Лимиты |
LimitVinkHistory |
История лимитов ВИНК |
Currencies |
Валюты |
CompanySettings |
Настройки компаний |
News |
Новости |
NewsCompanies |
Новости, которые посмотрела компания |
Reports |
Отчеты |
VinkDiscountForTemplates |
Шаблон скидок ВИНК |
VinkDiscountForTemplatesPlan |
Запланированные скидки ВИНК |
VinkDiscountContractTemplatesPlan |
Планирование шаблона ВИНК |
AccountReceivables |
Таблица должников |
CommentsAndAccountReceivable |
Комментарии к дебиторке |
UserAccountReceivableNoticeViews |
Представления уведомлений |
BalanceActions |
Действия с балансом |
StsCards |
Данные СТС |
DirectContractOverdraftDateTimes |
Изменения состояния овердрафтов |
MonitoringTransactions |
Мониторинг транзакций |
TransactionRequestFaileds |
Неудавшиеся транзакции |
TaskLimits |
Задачи лимитов |
TaskBlocks |
Задачи блокировок |
TaskReports |
Задачи на формирование отчетов |
OfflineTaskBlocks |
Оффлайн задачи блокировок |
OfflineTaskLimits |
Оффлайн задачи лимитов |
OfflineHistories |
Оффлайн история |
RecalculateTransactionTasks |
Задачи пересчета транзакций |
NoFuelGoods |
Товары не топлива |
CardTaskBlockResponses |
Ответы задач блокировки карт |
CardOwnerCardLogs |
Логи владельцев карт |
SummaryContractBalances |
Сводки по балансам |
SummaryComissions |
Сводки по комиссиям |
Конфигурация¶
// Startup.cs / Program.cs
services.AddDbContextPool<DataContext>(options =>
options.UseNpgsql(Configuration.GetConnectionString("DefaultConnection"))
);
Entity Framework Configurations¶
IEntityTypeConfiguration Implementations¶
Файлы в Context/BuildConfigs/:
| Класс | Сущность | Назначение |
|---|---|---|
CompanyConfiguration |
Company |
JSON конвертеры для SelfDirectContarctWithWink и CardTypes |
DirectContractOverdraftResetRequestConfiguration |
DirectContractOverdraftResetRequest |
Конфигурация запросов сброса овердрафта |
Seed Configurations¶
Файлы в Context/Seed/:
| Класс | Назначение |
|---|---|
AdminConfiguration |
Создание администратора (info@wellsoft.pro) |
RoleConfiguration |
Инициализация ролей пользователей |
SystemConfigConfiguration |
Начальные системные конфиги |
SystemSettingsConfigureation |
Начальные настройки системы |
Репозитории¶
Базовый репозиторий¶
public class BaseRepository<T> : ISelfTransientLifetime where T : Entity
{
protected readonly DataContext _context;
public DbSet<T> entities;
// CRUD операции
public virtual IQueryable<T> GetAll()
public virtual IQueryable<T> GetAllForRead() // AsNoTracking
public virtual T GetById(int id)
public virtual T Add(T entity, bool isTransaction = false)
public virtual void Update(T entity, bool isTransaction = false)
public virtual void Delete(int id, bool isTransaction = false)
public virtual void Delete(T entity, bool isTransaction = false)
public virtual void AddRange(IEnumerable<T> entityArr, bool isTransaction = false)
public virtual void UpdateRange(IEnumerable<T> entityArr, bool isTransaction = false)
public virtual void RemoveRange(IEnumerable<T> entityArr, bool isTransaction = false)
public virtual void Save()
public virtual async Task SaveAsync()
}
Особенности:
- Автоматическое обновление LastModifed при изменении
- Интеграция с LogUserActionService для логирования
- Параметр isTransaction для пакетных операций
ApiBaseRepository¶
public class ApiBaseRepository<T> : BaseRepository<T> where T : Entity
{
// Помечает операции как выполняемые API (блокирует лог)
public bool IsApiExecutor { get; set; } = true;
}
Список репозиториев¶
| Репозиторий | Базовый класс | Особые методы |
|---|---|---|
CardRepository |
BaseRepository<Card> |
GetByNumber(), CheckCompany(), UpdateStatusHistory(), UpdateWithTrackActivity(), MassBlockCard() |
CompanyRepository |
BaseRepository<Company> |
GetAll() фильтрует IsBrandCompany = false |
DirectContractRepository |
BaseRepository<DirectContract> |
При Add() создает CurrentContractBalance, при Delete() устанавливает IsHidden = true |
FinanceTransactionRepository |
BaseRepository<FinanceTransaction> |
Базовая реализация |
ContractTermRepository |
BaseRepository<ContractTerm> |
Базовая реализация |
ContractTermTemplateRepository |
BaseRepository<ContractTermTemplate> |
Базовая реализация |
UserRepository |
BaseRepository<User> |
Базовая реализация |
ReportRepository |
BaseRepository<Report> |
GetAll(int companyId) с фильтрацией по ролям |
NewsRepository |
BaseRepository<News> |
Базовая реализация |
CardChangeLogRepository |
BaseRepository<CardChangeLog> |
Базовая реализация |
CurrentContractBalanceRepository |
BaseRepository<CurrentContractBalance> |
Базовая реализация |
ContractPayInfoRepository |
BaseRepository<ContractPayInfo> |
Базовая реализация |
CardGroupRepository |
BaseRepository<CardGroup> |
Базовая реализация |
FuelTypeRepository |
BaseRepository<FuelType> |
Базовая реализация |
FuelTypeForMapRepository |
BaseRepository<FuelTypeForMap> |
Базовая реализация |
NewsCompanyRepository |
BaseRepository<NewsCompany> |
Базовая реализация |
RegionDirectContractWithVendorDiscountRepository |
BaseRepository<RegionDirectContractWithVendorDiscount> |
Базовая реализация |
CardRepository - Особенности¶
public class CardRepository : BaseRepository<Card>
{
// Поиск карты по номеру
public Card GetByNumber(string number)
// Проверка компании на доступ к перепродаже
public void CheckCompany(Card card)
// Логирование изменений статуса блокировки
public void UpdateStatusHistory(Card card, bool isTransaction = false)
public void UpdateStatusHistoryBatch(IEnumerable<Card> cards)
// Обновление с отслеживанием активности для синхронизации с ВИНК
public void UpdateWithTrackActivity(Card entity, bool isTransaction = false, string? comment = "")
// Массовая блокировка карт
public void MassBlockCard(List<Card> entityList, string? comment = "")
}
Статусы синхронизации:
- StatusSyncCard.Синхронизирован - синхронизировано
- StatusSyncCard.ВПроцессеСинхронизации - в процессе
- StatusSyncCard.Неопределен - не определен
Миграции¶
Структура¶
FuelProcessing.Data/Migrations/
├── 20210404101024_Initial.cs # Первичная миграция
├── 20210404135633_companyAndSeed.cs # Компании и начальные данные
├── 20210406081253_initCoreModels.cs # Инициализация основных моделей
├── 20210427103003_cards.cs # Карты
├── 20210422123758_direactContracWithWink.cs # Прямые договоры с ВИНК
├── 20210524131821_apisettingscontract.cs # API настройки контрактов
├── 20210525143440_transactiontype.cs # Типы транзакций
├── 20210617165923_GroupSync.cs # Групповая синхронизация
├── 20210715101233_payInfo.cs # Информация об оплатах
├── 20210803122651_fuelTemplatePrice.cs # Цены топлива по шаблону
├── 20210903121758_transactionUtc.cs # UTC время транзакций
├── 20211117063623_addSystemDatas.cs # Системные данные
├── 20211203104405_ditributorFields.cs # Поля дистрибьютора
├── 20220314115703_AddMonitoringTransactions.cs # Мониторинг транзакций
├── 20220329101620_FixUser.cs # Исправление пользователя
├── 20220408104008_addOffDiscountFiled.cs # Скидки
├── 20220511115703_addClientApiAcessField.cs # Доступ к API
├── 20220706074106_add-field-vink.cs # Поля ВИНК
├── 20220817122146_addedNewFieldApiMonitoringTatneftSoapSuccessDateTime.cs
├── 20220914070050_addNewEntityReport.cs # Отчеты
├── 20221107121504_addNewEntityVinkDiscount.cs # Скидки ВИНК
├── 20221129111212_newEntitiesForTemplatePlans.cs # Шаблоны планов
├── 20230307114407_addNewEntityForFuelTypeVinkForRouting.cs # Типы топлива для маршрутов
├── 20230412103811_CompanyEdo.cs # ЭДО компаний
├── 20230601114953_addNewFieldIsVirtualForCard.cs # Виртуальные карты
├── 20230717103749_addNewFieldForHiddenCard.cs # Скрытые карты
├── 20230829081822_addNewEntityForRecalculateTransactionTask.cs # Пересчет транзакций
├── 20230927100021_addNewEntityTaskReport.cs # Задачи отчетов
├── 20231122102639_modernCalculateBalanceAction.cs # Расчет баланса
├── 20240129043350_genitiveCaseFIOField.cs # ФИО в родительном падеже
├── 20240216085739_avarageSumTwoWeekDailyPumping.cs # Средние чеки
├── 20240422081750_newFieldForTaskComment.cs # Комментарии задач
├── 20250304052942_addNewFieldForDCWVAPIURLLukoil.cs # URL Лукойл
├── 20250319064852_newEntityForViewDebt.cs # Просмотр долгов
├── 20250423034937_newAccountReceivable.cs # Дебиторская задолженность
├── 20250711081541_textForSBPQR.cs # СБП QR
├── 20250716062058_calculateFTField.cs # Расчет полей ФТ
├── 20250808051855_cardLogCardOwners.cs # Логи владельцев карт
├── 20250917082606_cardResponseFromServer.cs # Ответы сервера карт
├── 20251014095826_addNewFieldForContractTermTemplate.cs # Поля шаблонов
├── 20251112083529_managementCardBlock.cs # Блокировка карт менеджером
├── 20251112142207_superUserBlocked.cs # Блокировка суперюзером
├── 20251217110845_addDirectContractOverdraftResetRequest.cs # Сброс овердрафта
├── 20251217124917_addNewFieldForTransaction.cs # Поля транзакций
├── 20251217131443_addFinanceTransactionVinkGasStationBrandSnapshot.cs # Снапшоты
├── 20251217133623_addNewFieldForGasStationTransaction.cs # Поля АЗС
├── 20251225130742_addDebtTextForModalLess15000.cs # Текст долга для модального окна
├── 20251226192006_newFieldsForCompanySettingsVAT.cs # НДС компаний
└── DataContextModelSnapshot.cs # Снапшот модели
Ключевые миграции по хронологии¶
| Период | Миграции | Основные изменения |
|---|---|---|
| 2021-04 | Initial, companyAndSeed, initCoreModels | Создание базы, компании, пользователи |
| 2021-04-05 | cards, direactContracWithWink | Карты, прямые договоры |
| 2021-05 | api settings, transactiontype | API интеграция, типы транзакций |
| 2021-06-07 | GroupSync, payInfo, fuelTemplatePrice | Синхронизация, оплаты, цены |
| 2021-08-09 | transactionUtc, partTimeUtc, checkBalanceVal | UTC время, балансы |
| 2021-11 | addSystemDatas, ditributorFields, recoverPassword | Системные данные, дистрибьюторы |
| 2022-01-04 | auto-input, directContractOverdraftInfo, AddMonitoringTransactions | Автозаполнение, овердрафт |
| 2022-04-08 | addOffDiscountFiled, addLogCard, addClientApiAcessField | Скидки, логи, API доступ |
| 2022-08-09 | addedNewFieldApiMonitoring, addNewEntityReport | API мониторинг, отчеты |
| 2022-11 | addNewEntityVinkDiscount, newEntitiesForTemplatePlans | Скидки ВИНК, шаблоны планов |
| 2023-03-05 | FuelTypeVinkForRouting, CompanyEdo, addNewFieldIsVirtualForCard | Маршрутизация, ЭДО |
| 2023-07-09 | addNewEntityForRecalculateTransactionTask, modernCalculateBalanceAction | Пересчет транзакций |
| 2024-01-04 | genitiveCaseFIOField, avarageSumTwoWeekDailyPumping, newFieldForTaskComment | ФИО, статистика |
| 2025-03-05 | newAccountReceivable, calculateFTField, cardLogCardOwners | Дебиторка, расчеты |
| 2025-07-12 | textForSBPQR, cardResponseFromServer | СБП, ответы сервера |
| 2025-11-12 | managementCardBlock, superUserBlocked, addDirectContractOverdraftResetRequest | Блокировки, сброс овердрафта |
| 2025-12 | addNewFieldForTransaction, addDebtTextForModalLess15000, newFieldsForCompanySettingsVAT | Транзакции, долги, НДС |
Управление миграциями¶
# Создание новой миграции
dotnet ef migrations add MigrationName --project FuelProcessing.Data
# Применение миграций
dotnet ef database update --project FuelProcessing.Data
# Откат к конкретной миграции
dotnet ef database update MigrationName --project FuelProcessing.Data
# Просмотр SQL для миграции
dotnet ef migrations script MigrationName --project FuelProcessing.Data
API клиенты ВИНК¶
IApiService — базовый интерфейс¶
Все 11 API клиентов реализуют общий интерфейс:
public interface IApiService
{
bool IsTest { get; set; }
void InitRestClient(DirectContractWithVendor settings, bool isTest = false);
// Синхронизация
List<Card> GetCards(int directContractWithVendorId);
void GetTransactions();
void GetGasStations();
void GetBalance();
// Управление
List<SimpleRepeatItem> AddLimitsToCards(List<Limit> limit);
void RestoreLimits(List<LimitVinkHistory> model);
void BlockCard(CardBlockRepeat cardInfo);
RepeatResultAnswer RepeatBlockCard(CardBlockRepeat cardInfo);
// Запросы
IEnumerable<ApiLimitInfo> GetLimits(string cardNumber);
IEnumerable<FinanceTransaction> GetFinanceTransactionsByMounth(
DirectContractWithVendor settings);
}
ApiExecutor — координатор¶
public class ApiExecutor
{
public void Sync(VinkApiTypeSync typeSync)
{
// Автоматическая инициализация нужного API сервиса
var apiService = _apiServiceFactory.Create(vinkType);
// Выполнение с мониторингом
ActionWithMonitoring(() =>
{
switch (typeSync)
{
case VinkApiTypeSync.Cards:
apiService.GetCards(contractId);
break;
case VinkApiTypeSync.Balance:
apiService.GetBalance();
break;
// ...
}
}, settings, typeSync);
}
}
Типы синхронизации¶
public enum VinkApiTypeSync
{
Cards, // Синхронизация карт
GasStations, // Синхронизация АЗС
HistoryTransactions, // Исторические транзакции
Balance, // Баланс договора
AddLimitsToCards // Установка лимитов
}
Бизнес-сервисы¶
FinancePartTransactionService¶
Основной сервис расчёта транзакций.
public class FinancePartTransactionService
{
// Распределение транзакции по частям
public async Task PartTransactions(FinanceTransaction transaction)
// Установка ВИНК -> дистрибьютор
private void SetVinkToVkrPart(FinanceTransaction transaction)
// Установка дистрибьютор -> покупатель
private void SetPart(FinanceTransaction transaction)
// Установка для отрицательного баланса
private void SetNegativePart(FinanceTransaction transaction)
}
BillingService¶
Сервис управления балансами.
public class BillingService
{
// Получение баланса
public async Task<decimal> GetBalanceAsync(int contractId)
// Пополнение баланса
public async Task ReplenishAsync(int contractId, decimal sum)
// Списание
public async Task WriteOffAsync(int contractId, decimal sum)
// Установка временного овердрафта
public async Task SetTempOverdraftAsync(int contractId,
decimal sum, DateTime until)
}
Singletons¶
TransactionManager¶
Координатор операций обработки транзакций.
public class TransactionManager
{
// Флаги состояния
public bool IsSyncTransaction { get; set; }
public bool IsRecalculateTransaction { get; set; }
public bool IsCalculateBalance { get; set; }
public bool IsReconciliationOfBalances { get; set; }
public bool IsHourCheckBalance { get; set; }
// Проверки возможности выполнения
public bool CanCalculateBalance()
=> !IsReconciliationOfBalances && !IsHourCheckBalance;
public bool CanRecalculateTransaction()
=> !IsReconciliationOfBalances;
}
Фоновые задачи (Workers)¶
Quartz Configuration¶
public class QuartzConfiguration
{
public static void AddDSimpleIntervalJob<T>(
string jobName,
Func<ISimpleScheduleBuilder, ISimpleScheduleBuilder> schedule)
where T : IJob
{
// Регистрация задачи с интервалом
}
}
Расписание задач¶
| Задача | Интервал | Назначение |
|---|---|---|
FinanceTransactionCalculateJob |
5 мин | Расчёт транзакций |
ApiJob (Cards) |
2 часа | Синхронизация карт |
ApiJob (Balance) |
20 мин | Синхронизация балансов |
BillingJob |
08:00, 20:00 | Сверка балансов |
Коды ответов API¶
public enum ApiResponseCodes
{
Success = 0,
NoProxy = 1,
Timeout = 2,
NetworkError = 3,
InvalidResponse = 4,
MaxRetriesExceeded = 5,
ServerError = 6
}
Связанная документация¶
- Domain Layer (Core) — доменные модели
- API интеграции — подробнее о ВИНК
- TransactionHandler — фоновая обработка