PayCell

1. Ilkin olaraq ConfigurationController controllerinin ne ish gorduyunu arashdiririq:


package com.azercell.paycell.paycellconsumer.controller;

import com.azercell.paycell.paycellconsumer.model.ShortNumberConfiguration;
import com.azercell.paycell.paycellconsumer.model.dto.ShortNumberConfigurationResponseDto;
import com.azercell.paycell.paycellconsumer.service.ShortNumberConfigurationService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequiredArgsConstructor
@Tag(name = "ConfigurationController")
@RequestMapping("/configurations")
public class ConfigurationController {

private final ShortNumberConfigurationService shortNumberConfigurationService;

@GetMapping
@Operation(
summary = "Retrieve paycell configuration data",
description = "Retrieves the current paycell configuration data from the database."
)
public List<ShortNumberConfigurationResponseDto> getShortNumberConfiguration() {
List<ShortNumberConfiguration> configurations = shortNumberConfigurationService.getShortNumberConfigurations();
return configurations.stream().map(c -> {
Long fullPrice = c.getAmountInCents() + c.getFeeAmountInCents();
return new ShortNumberConfigurationResponseDto(c.getServiceType(), c.getAmountInCents().toString(), fullPrice.toString());
}).collect(Collectors.toList());
}
}


GET /configurations endpoint-ini addım-addım izah edirəm. Service layer-ə də baxırıq:



[5 tools called]



Mapper-ə baxırıq:



[3 tools called]



GET /configurations endpoint-ini addım-addım izah edirəm:


## GET /configurations — addım-addım analiz


### Controller (ConfigurationController.java)


#### Sətir 16-19: Class declaration və dependencies

```java

@RestController                    // REST controller (HTTP endpoint-lər üçün)

@RequiredArgsConstructor          // Lombok: constructor injection

@Tag(name = "ConfigurationController")  // Swagger UI-da görünəcək ad

@RequestMapping("/configurations") // Base path: /configurations

public class ConfigurationController {

    private final ShortNumberConfigurationService shortNumberConfigurationService;

}

```

Nə edir:

- `@RestController` — Spring-ə REST controller olduğunu bildirir

- `@RequiredArgsConstructor` — Lombok constructor yaradır

- `@RequestMapping("/configurations")` — Base path `/configurations`


---


#### Sətir 24-28: Endpoint annotation

```java

@GetMapping                        // HTTP GET metodu

@Operation(                       // Swagger documentation

    summary = "Retrieve paycell configuration data",

    description = "Retrieves the current paycell configuration data from the database."

)

```

Nə edir:

- `@GetMapping` — GET request qəbul edir

- `@Operation` — Swagger UI-da görünəcək açıqlama


Endpoint URL: `GET http://localhost:8080/configurations`


---


#### Sətir 29: Metod signature

```java

public List<ShortNumberConfigurationResponseDto> getShortNumberConfiguration() {

```

Nə edir:

- `List<ShortNumberConfigurationResponseDto>` — Response tipi (list)

- Parametr yoxdur — bütün konfiqurasiyaları qaytarır


---


#### Sətir 30: Service çağırışı

```java

List<ShortNumberConfiguration> configurations = 

    shortNumberConfigurationService.getShortNumberConfigurations();

```

Nə edir:

- Service-dən bütün konfiqurasiyaları alır

- `ShortNumberConfiguration` list qaytarır


---


#### Sətir 31-34: Response mapping

```java

return configurations.stream().map(c -> {

    Long fullPrice = c.getAmountInCents() + c.getFeeAmountInCents();

    return new ShortNumberConfigurationResponseDto(

        c.getServiceType(),              // Məsələn: 9204

        c.getAmountInCents().toString(), // Məsələn: "20"

        fullPrice.toString()             // Məsələn: "22"

    );

}).collect(Collectors.toList());

```

Nə edir:

- Stream ilə hər konfiqurasiyanı map edir

- `fullPrice` hesablayır: `amountInCents + feeAmountInCents`

- `ShortNumberConfigurationResponseDto` yaradır

- List-ə toplayır


---


### Service layer (ShortNumberConfigurationServiceImpl.java)


#### Sətir 23-24: Service metodu

```java

@Override

public List<ShortNumberConfiguration> getShortNumberConfigurations() {

    return configurationCache.getShortNumberConfigurations();

}

```

Nə edir:

- Cache service-ə yönləndirir

- Cache service DB-dən oxuyur


---


### Cache layer (ShortNumberConfigurationRedisCache.java)


#### Sətir 43-50: Cache metodu

```java

@Override

public List<ShortNumberConfiguration> getShortNumberConfigurations() {

    log.info("Get ShortNumberConfigurations from DB");

    List<ShortNumberConfigurationEntity> entities = valueMapper.getShortNumberConfigurations();

    

    return entities.stream()

            .map(this::mapToShortNumberConfiguration)  // Entity → Model

            .peek(this::cacheShortNumberConfiguration)  // Redis-ə yazır

            .collect(Collectors.toList());

}

```

Nə edir:

- DB-dən entity-ləri alır

- Entity-ləri model-ə çevirir

- Hər birini Redis-ə yazır (cache)

- List qaytarır


---


#### Sətir 53-69: Entity → Model mapping

```java

private ShortNumberConfiguration mapToShortNumberConfiguration(ShortNumberConfigurationEntity entity) {

    if (entity == null) {

        return null;

    }

    Long price = toCents(entity.getPrice());           // BigDecimal → Long (cents)

    Long priceFull = toCents(entity.getPriceFull());   // BigDecimal → Long (cents)

    return new ShortNumberConfiguration(

        entity.getDiameterChargingFeeNumber(),    // Məsələn: "123456"

        entity.getDiameterChargingFullNumber(),   // Məsələn: "123457"

        entity.getDiameterRefundWithoutFeeNumber(), // Məsələn: "123458"

        entity.getDiameterRefundFullNumber(),      // Məsələn: "123459"

        entity.getRefillProfileId(),               // Məsələn: "PROFILE_123"

        price,                                      // Məsələn: 2000 (20 manat = 2000 qəpik)

        Math.max(0, priceFull - price),            // Fee: priceFull - price

        entity.getServiceType()                    // Məsələn: 9204

    );

}

```

Nə edir:

- DB entity-sini model-ə çevirir

- `toCents()` — manatı qəpikə çevirir (məs. 20.00 → 2000)

- `feeAmountInCents` hesablayır: `priceFull - price`


---


### Database layer (value-mapper.xml)


#### Sətir 42-45: SQL query

```xml

<select id="getShortNumberConfigurations" resultMap="shortNumberConfigResultMap">

    SELECT PRICE, PRICE_FULL, CHARGING_DIAMETER_FEE, CHARGING_DIAMETER_FULL, 

           DIAMETER_NUM, DIAMETER_NUM_FULL, PAYMENT_PROFILE, SERVICE_TYPE 

    FROM SUBDEALER.PAYCELL_VALUES

    WHERE sysdate BETWEEN valid_from AND valid_to

</select>

```

Nə edir:

- `SUBDEALER.PAYCELL_VALUES` cədvəlindən oxuyur

- Yalnız aktiv (valid_from və valid_to arasında) qeydləri gətirir

- Bütün konfiqurasiyaları qaytarır


---


## Tam axın diagramı


```

1. Client → GET /configurations

   ↓

2. ConfigurationController.getShortNumberConfiguration() (sətir 29)

   ↓

3. ShortNumberConfigurationService.getShortNumberConfigurations() (sətir 30)

   ↓

4. ShortNumberConfigurationRedisCache.getShortNumberConfigurations() (sətir 43)

   ↓

5. ValueMapper.getShortNumberConfigurations() → SQL query (sətir 45)

   ↓

6. Oracle DB → SUBDEALER.PAYCELL_VALUES table

   ↓

7. Entity → Model mapping (sətir 47-48)

   ↓

8. Redis cache-ə yazır (sətir 49)

   ↓

9. Controller-də Response mapping (sətir 31-34)

   ↓

10. JSON response qaytarır

```


---


## Nümunə response


```json

[

  {

    "serviceType": 9204,

    "price": "20",

    "price_full": "22"

  },

  {

    "serviceType": 2206,

    "price": "200",

    "price_full": "220"

  }

]

```


---


## Nə üçün lazımdır?


- Short number konfiqurasiyalarını görmək

- Test və debug üçün

- Frontend/başqa servislər üçün məlumat


Swaggerden sorgu atdiqda bu response qayidir:

[
  {
    "serviceType": 2206,
    "price": "200",
    "price_full": "220"
  },
  {
    "serviceType": 2208,
    "price": "500",
    "price_full": "550"
  },
  {
    "serviceType": 9200,
    "price": "50",
    "price_full": "50"
  },
  {
    "serviceType": 9202,
    "price": "100",
    "price_full": "100"
  },
  {
    "serviceType": 9204,
    "price": "20",
    "price_full": "20"
  },
  {
    "serviceType": 220669,
    "price": "200",
    "price_full": "220"
  },
  {
    "serviceType": 220869,
    "price": "500",
    "price_full": "550"
  },
  {
    "serviceType": 920069,
    "price": "50",
    "price_full": "50"
  },
  {
    "serviceType": 920269,
    "price": "100",
    "price_full": "100"
  },
  {
    "serviceType": 920469,
    "price": "20",
    "price_full": "20"
  }
]



2. Ikinci endpoint ShortNumberController.


package com.azercell.paycell.paycellconsumer.controller;

import com.azercell.paycell.paycellconsumer.service.ShortNumberConfigurationCache;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
@Tag(name = "ShortNumberController")
@RequestMapping("/api/v1/short-number")
public class ShortNumberController {

private final ShortNumberConfigurationCache cacheService;

@PutMapping("/flush")
public void flush() {
cacheService.flush();
}
}




PUT /api/v1/short-number/flush endpoint-ini addım-addım izah edirəm:



[3 tools called]



PUT /api/v1/short-number/flush endpoint-ini addım-addım izah edirəm:


## PUT /api/v1/short-number/flush — detallı izah


### Nə edir?

Redis cache-i təmizləyir (bütün short number konfiqurasiyalarını silir).


---


## Setir-setir izah


### Sətir 10-13: Class declaration

```java

@RestController                    // REST controller

@RequiredArgsConstructor          // Lombok: constructor injection

@Tag(name = "ShortNumberController")  // Swagger UI-da görünəcək ad

@RequestMapping("/api/v1/short-number")  // Base path

public class ShortNumberController {

```

Nə edir:

- `@RestController` — REST endpoint-lər üçün

- `@RequestMapping("/api/v1/short-number")` — Base path


Endpoint URL: `PUT http://localhost:8080/api/v1/short-number/flush`


---


### Sətir 15: Dependency injection

```java

private final ShortNumberConfigurationCache cacheService;

```

Nə edir:

- `ShortNumberConfigurationCache` service-ini inject edir

- Cache əməliyyatları üçün istifadə olunur


---


### Sətir 18-21: Endpoint metodu

```java

@PutMapping("/flush")             // HTTP PUT metodu

public void flush() {             // Parametr yoxdur, response yoxdur

    cacheService.flush();         // Cache-i təmizləyir

}

```

Nə edir:

- `@PutMapping("/flush")` — PUT request qəbul edir

- `cacheService.flush()` — Cache-i təmizləyir


---


## Service layer (ShortNumberConfigurationRedisCache.java)


### Sətir 37-40: Flush metodu

```java

@Override

@CacheEvict(value = REDIS_SHORT_NUMBER_CACHE_NAME, allEntries = true)

public void flush() {

    log.info("Flush {} redis cache", REDIS_SHORT_NUMBER_CACHE_NAME);

}

```

Nə edir:

- `@CacheEvict` — Spring Cache annotation

- `allEntries = true` — Bütün key-ləri silir

- `REDIS_SHORT_NUMBER_CACHE_NAME` — `"shortNumberConfigCache"`


---


## Tam axın


```

1. Client → PUT /api/v1/short-number/flush

   ↓

2. Controller.flush() (sətir 20)

   ↓

3. cacheService.flush() (sətir 20)

   ↓

4. @CacheEvict annotation işləyir (sətir 37)

   ↓

5. Redis-dən BÜTÜN key-lər silinir:

   - shortNumberConfigCache::2206

   - shortNumberConfigCache::2208

   - shortNumberConfigCache::9200

   - ... (hamısı)

   ↓

6. Response: 200 OK (boş body)

```


---


## Nə üçün lazımdır?


### Ssenari 1: DB-də dəyişiklik

```

1. DB admin → DB-də konfiqurasiya dəyişir

2. Sən → PUT /api/v1/short-number/flush çağırırsan

3. Cache təmizlənir

4. Növbəti çağırışda → DB-dən yeni məlumat oxuyur

```


### Ssenari 2: Test

```

1. Test zamanı cache-i təmizləmək lazımdır

2. flush() çağırırsan

3. Cache təmizlənir

```


---


## Nümunə istifadə


### Swagger UI-da:

1. PUT /api/v1/short-number/flush → "Try it out"

2. "Execute"

3. Response: 200 OK (boş body)


### Terminaldan:

```bash

curl -X PUT http://localhost:8080/api/v1/short-number/flush \

  -u apiuser:apipass

```


---


## Nə baş verir?


### Əvvəl (Redis-də):

```

✅ shortNumberConfigCache::2206

✅ shortNumberConfigCache::2208

✅ shortNumberConfigCache::9200

... (10 key)

```


### flush() çağırılandan sonra:

```

❌ (hamısı silindi)

```


### Növbəti GET /configurations çağırışında:

```

1. Cache-də yoxdur → DB-dən oxuyur

2. Yenidən Redis-ə yazır

3. Response qaytarır

```


---


## Xülasə


Bu endpoint Redis cache-i təmizləyir. DB-də dəyişiklik olduqda və ya test zamanı istifadə olunur.

















Комментарии

Популярные сообщения из этого блога

Lesson_2: Operations in Java

Lesson1: JDK, JVM, JRE

Interview questions