first commit

This commit is contained in:
ExtraNetwork
2026-05-12 17:04:54 +03:00
commit e5c4b6aa13
1425 changed files with 284735 additions and 0 deletions

102
.drone.yml Normal file
View File

@@ -0,0 +1,102 @@
kind: pipeline
type: docker
name: api-extranetwork
# Sadece main branch'te tetiklenir
trigger:
branch:
- main
event:
- push
steps:
# -------------------------------------------------------
# 1. Bağımlılıkları kur
# -------------------------------------------------------
- name: composer-install
image: composer:2.2
volumes:
- name: composer-cache
path: /root/.composer/cache
commands:
- composer install --no-dev --optimize-autoloader --no-interaction --prefer-dist
# -------------------------------------------------------
# 2. PHP Unit testlerini çalıştır
# -------------------------------------------------------
- name: tests
image: php:7.3-cli
commands:
- apt-get update -qq
- apt-get install -y --no-install-recommends libzip-dev libpng-dev libxml2-dev libonig-dev > /dev/null 2>&1
- docker-php-ext-install pdo pdo_mysql zip mbstring > /dev/null 2>&1
- cp .env.example .env
- php artisan key:generate
- vendor/bin/phpunit --no-coverage --stop-on-failure
environment:
DB_CONNECTION: sqlite
DB_DATABASE: ":memory:"
depends_on:
- composer-install
# -------------------------------------------------------
# 3. Docker image build & Gitea Container Registry'e push
# -------------------------------------------------------
- name: docker-build-push
image: plugins/docker
settings:
registry: git.extranetwork.net
repo: git.extranetwork.net/gitea/api-extranetwork
username:
from_secret: GITEA_USER
password:
from_secret: GITEA_TOKEN
tags:
- latest
- ${DRONE_COMMIT_SHA:0:8}
build_args:
- APP_ENV=production
depends_on:
- tests
when:
branch:
- main
event:
- push
# -------------------------------------------------------
# 4. SSH ile sunucuya deploy et
# -------------------------------------------------------
- name: deploy
image: appleboy/drone-ssh
settings:
host:
from_secret: DEPLOY_HOST
user:
from_secret: DEPLOY_USER
key:
from_secret: DEPLOY_SSH_KEY
port: 22
script:
- cd /opt/api.extranetwork.com
- docker compose pull
- docker compose up -d --remove-orphans
- docker compose exec -T app php artisan migrate --force
- docker compose exec -T app php artisan config:cache
- docker compose exec -T app php artisan route:cache
- docker compose exec -T app php artisan view:cache
- echo "Deploy tamamlandı - $(date)"
depends_on:
- docker-build-push
when:
branch:
- main
event:
- push
# -------------------------------------------------------
# Uçucu volume (composer cache pipeline içinde paylaşılır)
# -------------------------------------------------------
volumes:
- name: composer-cache
temp: {}

15
.editorconfig Normal file
View File

@@ -0,0 +1,15 @@
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.yml]
indent_size = 2

54
.env.example Normal file
View File

@@ -0,0 +1,54 @@
APP_NAME=Lumen
APP_ENV=local
APP_KEY=bae48aba23b3e4395b7f1b484dd25192
APP_DEBUG=true
APP_URL=http://api.extranetwork.local
APP_TIMEZONE=Europe/Istanbul
CLIENT_SERVER=http://www.extranetwork.com
LOG_CHANNEL=stack
LOG_SLACK_WEBHOOK_URL=
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=enw_20201106
DB_USERNAME=root
DB_PASSWORD=1722
MAIL_DRIVER=log
MAIL_HOST=smtp.yandex.com.tr
MAIL_PORT=465
MAIL_USERNAME=noreply@extranetwork.com
MAIL_PASSWORD=8KSLQzxuGg4vEfSFkaA4
MAIL_ENCRYPTION=ssl
JWT_SECRET=JhbGciOiJIUzI1N0eXAiOiJKV1QiLC
CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_DRIVER=sync
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
FILESYSTEM_DRIVER=C:\www\api.extranetwork.com\public
IMAGE_URL=http://api.extranetwork.local
GOOGLE_APPLICATION_CREDENTIALS=''
QUEUE_CONNECTION=database
APP_LANGUAGE_JSON_STORED_FOLDER=C:\www\www.extranetwork.com\public
MAIN_HOST_ADDRESS=http://myweb.extranetwork.local
MYWEB_LANGUAGE_JSON_STORED_FOLDER=C:\www\www.myweb.com\resources\lang\
BOOKING_ENGINE_LANGUAGE_JSON_STORED_FOLDER=C:\www\be.extranetwork.com\resources\lang\
BOOKING_ENGINE_URL=http://be.extranetwork.local
ZIP_FILES_URL=http://api.extranetwork.local/property-zip-files/
PAYMENT_FORM_LINK=http://be.extranetwork.local/link/
ENW_CONTACT_FORM_MAILTO=
STRIPE_ENWKEY=sk_test_51HuYHvEa9cmPdLq3ANG7ZYaGB9zMuhQZlwH19axJRauZsMnnpnuGBN1h8iAfr9kNVWe4FWcEcvZiMjn3hhBELHHx00hiBgjO41
PROPERTY_FILES_URL=http://local-api.extranetwork.com/property-files/

38
.gitignore vendored Normal file
View File

@@ -0,0 +1,38 @@
/vendor
/.idea
/.vscode
Homestead.json
Homestead.yaml
.env
composer.lock
# Büyük SQL dosyaları
*.sql
# Public upload klasörleri
/public/property-photos/
/public/property-files/
/public/property-zip-files/
/public/property-map/
/public/property-group/
/public/property-catalog/
/public/property-web-content/
/public/property-web-popup/
/public/blog/
# Storage (log, cache vs.)
/storage/logs/*
!/storage/logs/.gitignore
/storage/framework/cache/data/
/storage/framework/sessions/
/storage/framework/views/
/resources/lang/
# OS
.DS_Store
Thumbs.db
# Node
node_modules/
npm-debug.log

6
.styleci.yml Normal file
View File

@@ -0,0 +1,6 @@
php:
preset: laravel
disabled:
- unused_use
js: true
css: true

391
API_FLOW.md Normal file
View File

@@ -0,0 +1,391 @@
# API Akış Şeması — ExtraNetWork
300+ endpoint, 60+ controller, 9 channel manager entegrasyonu, 3 metasearch entegrasyonu.
---
## 1. Middleware Zinciri
```mermaid
graph LR
A[Client] --> B[cors]
B --> C[LanguageSetting]
C --> D{Public?}
D -->|Evet| Z[Controller]
D -->|Hayır| E[jwt.auth]
E --> F[userRoutePermissionAuthorize]
F --> G[property]
G --> H{Wizard gerekli mi?}
H -->|Evet| I[contentWizard]
H -->|Hayır| J{Channel sync?}
I --> J
J -->|Evet| K[checkPropertyChannelConnection]
J -->|Hayır| Z
K --> Z
Z --> S[Service]
S --> R[Repository]
R --> DB[(MySQL)]
```
| Middleware | Amaç |
| -------------------------------- | ---------------------------------------------- |
| `cors` | CORS başlıkları |
| `LanguageSetting` | TR/EN/DE dil seçimi |
| `jwt.auth` | JWT + `api_access_token` doğrulama |
| `userRoutePermissionAuthorize` | RBAC permission kontrolü |
| `property` | `user_property_mapping` ile property ownership |
| `contentWizard` | Onboarding tamamlanma kontrolü |
| `checkPropertyChannelConnection` | Channel bağlantı durumu |
| `bookingEngineToken` | BookingEngine widget token |
| `myWebToken` | MyWeb template token |
---
## 2. Genel Request Lifecycle
```mermaid
sequenceDiagram
participant C as Client
participant MW as Middleware Stack
participant Ctrl as Controller
participant Svc as Service
participant Repo as Repository
participant DB as MySQL
C->>MW: HTTP + authToken
MW->>MW: cors → lang → jwt → permission → property → wizard
MW->>Ctrl: Request + credentials + property
Ctrl->>Ctrl: Validator->validate(params)
Ctrl->>Svc: business call
Svc->>Repo: findByCriteria / create / update
Repo->>DB: SQL
DB-->>Repo: rows
Repo-->>Svc: data
Svc-->>Ctrl: ['status','data','message']
Ctrl-->>C: apiResponse(status, message, data, code)
```
---
## 3. Auth Akışı (Login / Refresh / Logout)
```mermaid
sequenceDiagram
participant U as User
participant A as AuthController
participant J as JwtService
participant T as ApiAccessTokenService
participant M as UserPropertyMappingService
participant DB
U->>A: POST auth/login {email, password, remember_me}
A->>DB: user where email & status=1
A->>A: Hash::check
A->>J: jwtCreate(user_id, remember_me, day_counter=5)
J-->>A: {token, exp}
A->>T: create({token: md5(jwt), expire_date, user_id, invalidate=0})
A->>M: select(user_property_mapping where user_id, status=1)
M-->>A: property_list
A-->>U: {token, expire_time, locale, property_list, user}
Note over U,A: Refresh
U->>A: GET auth/refresh-token (authToken header)
A->>T: token bul (md5, expire>now, invalidate=0)
A->>J: jwtCreate(day_counter=0.5)
A->>T: update aynı token row
A-->>U: {new token, expire_time}
Note over U,A: Logout
U->>A: POST logout (authToken header)
A->>T: update invalidate=1
A-->>U: 200 Logged out
```
---
## 4. Property Erişim Kontrolü
```mermaid
graph TD
A[Request + property_id] --> B[jwt.auth ✓]
B --> C[userRoutePermissionAuthorize]
C -->|permission yok| X[403]
C --> D[PropertyMiddleware]
D --> E{user_property_mapping<br/>user_id+property_id+status=1}
E -->|yok| X
E --> F{Wizard route?}
F -->|Evet| G{property.wizard_status<br/>= complete?}
G -->|Hayır| Y[422 Wizard incomplete]
G --> H[Controller]
F -->|Hayır| H
H --> I[Service: property_id ile scope]
I --> J[(DB)]
```
---
## 5. Booking Lifecycle (BookingEngine)
```mermaid
sequenceDiagram
participant G as Guest
participant BE as BookingEngine Widget
participant API as BookingEngine\BookingController
participant Inv as Inventory/Rate
participant Pay as PaymentLinkController
participant DB
G->>BE: arama (checkin/checkout, pax)
BE->>API: POST /v1/search
API->>Inv: availability + rates
Inv->>DB: property_room_rate_mapping + availability
API-->>BE: rate listesi
G->>BE: oda seç
BE->>API: POST /v1/booking
API->>DB: insert booking + booking_contact + booking_room + booking_room_pax
API-->>BE: booking_code (status=2 Pending)
G->>BE: ödemeyi onayla
BE->>API: POST /v1/bookingConfirm
API->>Pay: paymentLinkInitialize
Pay->>DB: insert payment_transaction (status=2 Start)
Pay-->>BE: redirect URL
G->>Pay: 3D Secure / POS
Pay->>API: callback /paymentRedirect/{code}
API->>DB: payment_transaction.status=1, booking.status=1
API->>API: send confirmation email
API-->>G: confirmation page
```
**Status kodları:**
- `booking.status`: 0=İptal/Refund, 1=Confirmed, 2=Pending
- `booking_payment.status`: 0=İptal, 1=Confirmed, 2=Pending
- `payment_transaction.status`: 0=Error, 1=Success, 2=Start, 3=Pending, 4=Cancel/Refund, 5=Manual
---
## 6. Channel Sync Akışı
```mermaid
graph TD
A[Property Manager] -->|property/property-channel-mapping/add| B[PropertyChannelMappingController]
B --> C[(property_channel_mapping)]
C --> D[Job: PropertyCatalogServiceJob]
D --> E{Channel?}
E -->|Reseliva| R1[ChannelManager/Reseliva]
E -->|Channex| R2[ChannelManager/Channex]
E -->|HotelRunner| R3[ChannelManager/HotelRunner]
E -->|ElektraWeb| R4[ChannelManager/ElektraWeb]
E -->|Athena/Fina/SistemOtel/1C/HyperGuest| R5[Diğer Adapters]
R1 & R2 & R3 & R4 & R5 --> X[Remote Channel API]
X --> L[Sync log + status update]
L --> N[Dashboard'da görünür]
```
---
## 7. Inventory & Rate Update (Channel-Connection-Protected)
```mermaid
sequenceDiagram
participant M as Manager
participant API as PropertyRoomRateMappingController
participant CC as checkPropertyChannelConnection
participant DB
participant Ch as Remote Channel
M->>API: POST property/room-rate-mapping/bulk-update
API->>CC: Channel bağlı mı?
CC->>DB: property_channel_mapping.status
alt Bağlı değil
CC-->>M: 403 Channel disconnected
else Bağlı
API->>DB: update room_rate_mapping (price/availability)
API->>Ch: push update
Ch-->>API: ack
API-->>M: success
end
```
---
## 8. Wizard Onboarding
```mermaid
graph TD
A[property/create] --> B[(property: wizard incomplete)]
B --> C1[contact/update]
B --> C2[room/add-room-bed]
B --> C3[room-fact-mapping/update]
B --> C4[room-photo-mapping/update]
B --> C5[awards-certificates/list]
B --> C6[fact/get-subcategory-facts]
B --> C7[executive/list]
C1 & C2 & C3 & C4 & C5 & C6 & C7 --> D[property/update/content-code]
D --> E[(wizard_status = complete)]
E --> F[Diğer property endpoint'leri açılır]
```
---
## 9. Web Site Builder (MyWeb)
```mermaid
sequenceDiagram
participant M as Manager
participant API as PropertyWebController
participant DB
participant FS as FileStorage/CDN
participant V as Visitor
participant MyW as MyWebContentController
M->>API: web/create → property_web
M->>API: web/update-content → component & content
M->>API: web/meta-tag/sync
M->>API: web/popup/create
M->>API: web/publish → status=PUBLISHED
API->>FS: assets
V->>MyW: web/home (myWebToken)
MyW->>DB: property_web_content + components
MyW-->>V: render data (frontend tarafı şablonlar)
```
---
## 10. Reputation Management
```mermaid
graph TD
A[reputation-management/channel/get] --> B[(reputation_channels)]
A --> C[reputation-management/channel/sync]
C --> J[Job: PropertyReviewServiceJob]
J --> D{Source}
D -->|TripAdvisor| T[TripAdvisor API]
D -->|Google| G[Google Places API]
D -->|Booking| BK[Booking API]
T & G & BK --> R[(reviews)]
R --> AN[Job: PropertyReviewAnalyzeServiceJob<br/>NLP/sentiment]
AN --> S[(review_statistics)]
S --> RS[reputation-management/review/statistics]
```
---
## 11. CPA (Competitor Price Analysis)
```mermaid
graph TD
A[cpa/property/competitor/create] --> B[(property_competitors)]
B --> C[cpa/property/competitor/sync]
C --> D[Crawler/OTA API]
D --> E[(competitor_prices günlük)]
E --> F[cpa/property/competitor/analysis]
F --> G[cpa/property/best-available-price]
F --> H[cpa/property/promotion-available]
F --> I[cpa/property/quick-pricing/rate]
G & H & I --> J[Manager dashboard önerileri]
```
---
## 12. Endpoint Domain Özet Tablosu
| # | Domain | Controller(lar) | Endpoint | Açıklama |
| --: | ------------------- | ----------------------------------------------------- | -------: | ------------------------------------------------------------------------------------ |
| 1 | Auth | AuthController | 3 | login / refresh / logout |
| 2 | User | UserController | 17 | register, profile, password, mapping |
| 3 | Property | PropertyController | 12 | CRUD + dashboard + raporlar |
| 4 | Property Info | Contact, Brand, Config, Executive | 14 | Detay bilgi yönetimi |
| 5 | Content | Content, Fact, FactMapping, AdditionalInfo | 11 | Property metadata |
| 6 | Photo | PropertyPhoto + Category + Mapping | 11 | Foto yönetimi & CDN |
| 7 | Place | PropertyPlaceController | 15 | Tesis içi yer/alan |
| 8 | Awards | PropertyAwardCertificates | 5 | Sertifikalar |
| 9 | Room | PropertyRoom + Type/View/Bed/Size | 20+ | Oda yapısı |
| 10 | Rate | PropertyRoomRate + Mapping/Channel/Setup/Inclusion | 27 | Rate & inventory |
| 11 | Channel | PropertyChannel + Mapping/Group/Contact/Category | 23 | OTA dağıtım |
| 12 | Cancellation Policy | PropertyCancellationPolicy | 5 | İptal kuralları |
| 13 | Pricing Policy | PropertyPersonPricingPolicy | 7 | Yetişkin/çocuk fiyat |
| 14 | Booking | PropertyBookingController + Ticket | 11 | Rezervasyon ops |
| 15 | Payment | PaymentController + PaymentLink | 16 | Ödeme + manual link + taksit |
| 16 | Offer | PropertyOfferController | 11 | Teklif yönetimi |
| 17 | Promotion | PropertyPromotionController | 7 | Promosyon & kampanya |
| 18 | Coupon/Addon | PropertyCoupon + Addon | 4 | Ek ürün/kupon |
| 19 | CPA | CompetitorPriceAnalysis + Group + QuickPricing | 15+ | Rakip analizi |
| 20 | Web Builder | PropertyWebController + Content/Popup/Component | 30+ | Website yönetimi |
| 21 | MyWeb | MyWebContentController | 22+ | Public site render |
| 22 | Booking Engine | BookingEngine\BookingController + Search | 17 | Embedded widget |
| 23 | Channel Manager | 9 entegrasyon adapter'ı | 21 | Reseliva, Channex, HotelRunner, ElektraWeb, Athena, Fina, SistemOtel, 1C, HyperGuest |
| 24 | MetaSearch | Trivago, Yandex, Google | 8 | Meta arama |
| 25 | Reputation | ReputationManagementController | 4 | Yorum & istatistik |
| 26 | AI | AIController | 1 | OpenAI |
| 27 | Export | ExportPdfController | 5 | PDF/Excel |
| 28 | Utility | Language, Currency, Destination, Chain, Test, Contact | 11 | Referans veri |
**Toplam:** ~300+ endpoint, ~60 controller dosyası.
---
## 13. Auth Header Konvansiyonu
| Tip | Header | Doğrulayan |
| --------------- | ----------------------------- | ------------------------------ |
| App API | `authToken: <jwt>` | `JwtMiddleware` |
| BookingEngine | `bookingEngineToken: <token>` | `BookingEngineTokenMiddleware` |
| MyWeb | `myWebToken: <token>` | `MyWebTokenMiddleware` |
| Channel Manager | partner-specific header | İlgili adapter |
---
## 14. Body Konvansiyonu
| Endpoint Tipi | Body Şeması |
| ------------------ | -------------------------------------------------------------------------- |
| Login | `{ "email", "password", "remember_me", "locale", "onesignal_key" }` (flat) |
| Tüm App API (POST) | `{ "params": { ... } }` (controller'lar `$this->request->params` okur) |
| BookingEngine | `{ "params": { ... } }` veya path param |
| ChannelManager | adapter'a özel JSON şeması |
---
## 15. Asenkron Olaylar (Queue Driver: database)
| Job | Tetikleyici | Görev |
| --------------------------------- | ----------------------- | ---------------- |
| `PropertyCatalogServiceJob` | property/channel update | Catalog senkronu |
| `PropertyReviewServiceJob` | reputation sync | Review fetch |
| `PropertyReviewAnalyzeServiceJob` | review save | NLP/sentiment |
| `SlackLogJob` | sistem logu | Slack bildirim |
Mail kuyrukları: `userCreateMail`, `UserForgotPassword`.
---
## 16. Status Kodları Özeti
| Tablo | Alan | Değerler |
| ------------------- | ---------- | --------------------------------------------------------------- |
| user | status | 0 inaktif / 1 aktif |
| user | user_type | 0 normal / 1 admin |
| api_access_token | invalidate | 0 geçerli / 1 iptal |
| booking | status | 0 İptal / 1 Onaylı / 2 Pending |
| booking_payment | status | 0 İptal / 1 Onaylı / 2 Pending |
| payment_transaction | status | 0 Error / 1 Success / 2 Start / 3 Pending / 4 Cancel / 5 Manual |
| property | status | 0 inaktif / 1 aktif |
---
## 17. Hızlı Bakış: Tipik İstek Hayatı
```
1. Client → POST /app/v1/property/info/get (Header: authToken)
2. cors → LanguageSetting → jwt.auth → userRoutePermissionAuthorize → property
3. PropertyController@getProperty
4. PropertyService->select(criteria scoped to property_id)
5. PropertyRepository->findByCriteria
6. MySQL property + relations (with: 'propertyContact', 'propertyType', ...)
7. apiResponse(1, null, $data, 200)
```

82
Dockerfile Normal file
View File

@@ -0,0 +1,82 @@
FROM php:7.3-apache-buster
# Debian Buster EOL olduğu için repo adreslerini archive'a taşıyoruz
RUN sed -i 's|http://deb.debian.org/debian|http://archive.debian.org/debian|g' /etc/apt/sources.list \
&& sed -i 's|http://security.debian.org/debian-security|http://archive.debian.org/debian-security|g' /etc/apt/sources.list \
&& sed -i '/buster-updates/d' /etc/apt/sources.list \
&& apt-get update
# Sistem paketleri + PHP extension kurulumu
RUN apt-get install -y --no-install-recommends \
git \
unzip \
zip \
nano \
curl \
libzip-dev \
libpng-dev \
libjpeg-dev \
libfreetype6-dev \
libxml2-dev \
zlib1g-dev \
libonig-dev \
&& docker-php-ext-configure gd \
--with-freetype-dir=/usr/include/ \
--with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install \
pdo \
pdo_mysql \
gd \
zip \
mbstring \
exif \
&& rm -rf /var/lib/apt/lists/*
# Composer 2.2 kurulumu - PHP 7.3 için güvenli sürüm
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
&& php composer-setup.php --2.2 --install-dir=/usr/local/bin --filename=composer \
&& php -r "unlink('composer-setup.php');"
# Apache modları
RUN a2enmod rewrite
# Apache VirtualHost ayarı
RUN cat > /etc/apache2/sites-available/000-default.conf <<'EOF'
<VirtualHost *:80>
ServerName localhost
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html/public
<Directory /var/www/html/public>
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
<Directory /var/www/html>
AllowOverride All
Require all granted
</Directory>
Alias /uploads /home/uploads
<Directory /home/uploads>
Options FollowSymLinks
AllowOverride None
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
EOF
# Upload klasörü
RUN mkdir -p /home/uploads \
&& chown -R www-data:www-data /home/uploads \
&& chmod -R 775 /home/uploads
WORKDIR /var/www/html
CMD ["apache2-foreground"]

233
PROJECT_SUMMARY.md Normal file
View File

@@ -0,0 +1,233 @@
# ExtraNetWork API — Teknik Özet
## Genel Bilgiler
| Özellik | Değer |
| ------------- | ----------------------------------------- |
| Framework | Laravel Lumen 5.8 |
| PHP | >= 7.1.3 |
| App Versiyonu | 1.5.22 |
| Veritabanı | MySQL (`utf8mb4`, host: `mysql-master`) |
| Queue Driver | Database (jobs tablosu) |
| Mail Driver | SMTP — Gmail (`noreply@extranetwork.com`) |
---
## Mimari
```
app/
├── Http/Controllers/ → 86 Controller
├── Core/
│ ├── Service/ → 142 Service
│ ├── Repository/ → 176 Repository
│ └── Validator/ → 132 Validator
├── Models/ → 196 Model
├── Jobs/ → 6 Job
├── Events/ → 2 Event
├── Listeners/ → 1 Listener
├── Channels/ → OneSignal push
└── Http/Middleware/ → 11 Middleware
```
**Katmanlı mimari:** Controller → Service → Repository → Model
---
## Servisler & URL'ler
| Servis | URL |
| -------------- | ------------------------------ |
| API | `https://api.extranetwork.com` |
| Web | `https://www.extranetwork.com` |
| Client App | `https://app.extranetwork.com` |
| Booking Engine | `https://be.extranetwork.com` |
| Image CDN | `https://cdn.extranetwork.com` |
---
## Veritabanı (100+ tablo)
### Ana Tablolar
| Grup | Tablolar |
| --------------- | --------------------------------------------------------------------------------------------------------- |
| Kullanıcı | `user`, `permission`, `permission_group`, `user_property_mapping` |
| Mülk (Property) | `property`, `property_type`, `property_chain`, `property_brand`, `property_contact`, `property_executive` |
| Oda | `property_room`, `property_room_type`, `property_room_bed`, `property_room_view_type` |
| Fotoğraf | `property_photo`, `property_photo_category`, `property_room_photo_mapping` |
| İçerik | `property_content`, `property_content_category`, `property_fact`, `property_fact_mapping` |
| Fiyat & Oran | `property_room_rate`, `property_room_rate_mapping`, `property_room_rate_channel_mapping` |
| Kanal | `property_channel`, `property_channel_mapping`, `property_channel_category` |
| Rezervasyon | `booking`, `booking_contact`, `booking_room_pax`, `booking_addon`, `booking_payment` |
| Politika | `property_cancellation_policy`, `property_pricing_policy_adult`, `property_pricing_policy_child` |
| Web | `property_web`, `property_web_content`, `property_web_menu`, `property_web_meta_tag` |
| Diğer | `property_promotion`, `property_coupon`, `property_addon`, `property_award_certificate`, `site_config` |
---
## Modeller & İlişkiler
### Property (Ana Model)
```
Property
├── hasMany → PropertyPhoto, PropertyRoom, PropertyExecutive, PropertyUser
├── hasOne → PropertyContact, PropertyWeb, PropertyBrand, PropertyChain
└── belongsTo → PropertyType, Destination
```
### Booking
```
Booking
├── hasMany → BookingRoomPax, BookingAddon, BookingPayment
└── hasOne → BookingContact
```
### Offer
```
Offer
├── hasMany → OfferContactMapping, OfferFactMapping
└── hasOne → OfferPaymentType
```
---
## Controller Grupları
### Auth & Kullanıcı
- `AuthController` — login, refresh-token, logout
- `UserController` — CRUD, şifre sıfırlama, rol yönetimi
### Property Yönetimi
- `PropertyController` — CRUD, dashboard, raporlar
- `PropertyPhotoController` — yükleme, sıralama, yayınlama
- `PropertyContactController`, `PropertyExecutiveController`, `PropertyBrandController`
- `PropertyRoomController`, `PropertyRoomBedController`, `PropertyRoomTypeController`
### Fiyat & Oran
- `PropertyRoomRateController`, `PropertyRoomRateMappingController`
- `PropertyRoomRateChannelMappingController`
- `PropertyQuickPricingController`, `PropertyPersonPricingPolicyController`
- `PropertyOfferController`, `PropertyNonrefundableController`
- `PropertyCancellationPolicyController`
### Kanal Yönetimi
- `PropertyChannelController`, `PropertyChannelMappingController`
- `PropertyChannelGroupController`, `PropertyChannelCategoryController`
- `CompetitorPriceAnalysisController`
### İçerik & Web
- `PropertyContentController`, `PropertyFactController`
- `PropertyWebController`, `PropertyWebContentController`, `PropertyWebMenuController`
- `PropertyPlaceController`, `PropertyAdditionalInfoController`
### Rezervasyon & Ödeme
- `PropertyBookingController`
- `PaymentController`, `PaymentLinkController`
- `PropertyBookingTicketController`
### Özel
- `AIController` — OpenAI entegrasyonu
- `ReputationManagementController` — Review/yorum yönetimi
- `PropertyAwardCertificatesController`
- `ExportPdfController`, `DashboardPlusService` controllers
---
## Middleware
| Middleware | Görev |
| ------------------------------------------ | ------------------------ |
| `JwtMiddleware` | JWT token doğrulama |
| `CorsMiddleware` | CORS başlıkları |
| `LanguageSettingMiddleware` | Dil seçimi |
| `PropertyMiddleware` | Property context |
| `UserRoutePermissionAuthorize` | RBAC yetki kontrolü |
| `BookingEngineTokenMiddleware` | Booking engine auth |
| `MyWebTokenMiddleware` | MyWeb auth |
| `CheckPropertyChannelConnectionMiddleware` | Kanal bağlantı doğrulama |
| `ContentWizardMiddleware` | İçerik sihirbazı akışı |
---
## Jobs (Queue)
| Job | Görev |
| --------------------------------- | ---------------------- |
| `PropertyReviewServiceJob` | Review senkronizasyonu |
| `PropertyReviewAnalyzeServiceJob` | Review analizi |
| `PropertyCatalogServiceJob` | Katalog güncellemeleri |
| `SlackLogJob` | Slack bildirim logları |
---
## Route Yapısı
```
POST /app/v1/auth/login
POST /app/v1/auth/refresh-token
POST /app/v1/user/register
POST /app/v1/logout
GET /property-comparison/{weekKey}
POST /web/check-domain
[Protected - /app/v1]
├── /property/** → Property CRUD & yönetim
├── /property-room/** → Oda yönetimi
├── /property-rate/** → Fiyat & oran
├── /property-channel/** → Kanal yönetimi
├── /booking/** → Rezervasyon
├── /payment/** → Ödeme
├── /property-web/** → Web içerik
└── /user/** → Kullanıcı yönetimi
```
---
## Temel Paketler
| Paket | Sürüm | Kullanım |
| ------------------------- | ------ | -------------- |
| `laravel/lumen-framework` | 5.8 | Framework |
| `firebase/php-jwt` | ^5.0 | JWT auth |
| `stripe/stripe-php` | ^7.66 | Ödeme |
| `google/cloud-vision` | ^0.24 | Görsel analiz |
| `maatwebsite/excel` | ^3.1 | Excel export |
| `barryvdh/laravel-dompdf` | ^0.8.7 | PDF üretimi |
| `intervention/image` | ^2.5 | Görsel işleme |
| `predis/predis` | ^1.1 | Redis |
| `ramsey/uuid` | ^4.1 | UUID üretimi |
| `symfony/translation` | 4.4.1 | Çeviri desteği |
---
## Dil Desteği
`config/` altında hazır dil paketi dosyaları:
- `language-pack-en.php` — İngilizce
- `language-pack-de.php` — Almanca
- `language-pack-tr.php` — Türkçe
---
## Entegrasyonlar
- **Stripe** — Ödeme işlemleri
- **OpenAI** — AI özellikler (`AIController`)
- **Google Cloud Vision** — Görsel analiz
- **OneSignal** — Push bildirim (`OneSignalChannel`)
- **Slack** — Log bildirimleri (`SlackLogJob`)
- **Redis** — Cache & queue
- **Gmail SMTP** — Mail gönderimi

51
README.md Normal file
View File

@@ -0,0 +1,51 @@
# api.extranetwork.com
Laravel 5.x tabanlı ExtraNetwork API backend.
## Gereksinimler
- PHP 7.3
- MySQL 8.0
- Docker & Docker Compose
- Composer 2.2
## Kurulum
```bash
# Bağımlılıkları kur
composer install
# .env dosyasını oluştur
cp .env.example .env
php artisan key:generate
# Veritabanı migrate
php artisan migrate
```
## Docker ile Çalıştırma
```bash
docker compose up -d
```
Uygulama `http://localhost:8073` adresinde çalışır.
## CI/CD
Drone CI pipeline otomatik olarak:
1. `composer install` çalıştırır
2. PHPUnit testlerini çalıştırır
3. Docker image build edip Gitea registry'e push eder
4. SSH ile sunucuya deploy eder
### Drone Secrets (Ayarlanması gerekenler)
| Secret | Açıklama |
| ---------------- | --------------------------- |
| `GITEA_USER` | Gitea kullanıcı adı |
| `GITEA_TOKEN` | Gitea access token |
| `DEPLOY_HOST` | Deploy sunucusu IP/hostname |
| `DEPLOY_USER` | SSH kullanıcısı |
| `DEPLOY_SSH_KEY` | SSH private key |

View File

@@ -0,0 +1,22 @@
<?php
namespace App\Channels;
use Illuminate\Notifications\Notification;
class OneSignalChannel
{
/**
* Send the given notification.
*
* @param mixed $notifiable
* @param \Illuminate\Notifications\Notification $notification
* @return void
*/
public function send($notifiable, Notification $notification)
{
$message = $notification->toOneSignal($notifiable);
// Send notification to the $notifiable instance...
}
}

View File

View File

@@ -0,0 +1,48 @@
<?php
namespace App\Console\Commands\ApplicationLanguageFiles;
use App\Core\Service\LanguageBaseService;
use App\Exceptions\ApiErrorException;
use Illuminate\Console\Command;
use Exception;
use Illuminate\Support\Facades\Log;
class ApplicationFillTableLanguageKey extends Command
{
protected $signature = 'cron:create-application-fill-table-language-key'; // read table name column, update table key column
protected $description = '';
private $languageBaseService;
public function __construct(
LanguageBaseService $languageBaseService
)
{
$this->languageBaseService = $languageBaseService;
parent::__construct();
}
public function handle()
{
try {
$this->info(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' LANGUAGE BASE START');
$process = $this->languageBaseService->fillApplicationLanguageKeys();
if($process['status'] != 'success'){
throw new Exception($process['message']) ;
}
$this->info(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' LANGUAGE BASE FINISHED');
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' ERROR: ' . $message);
}
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace App\Console\Commands\ApplicationLanguageFiles;
use App\Core\Service\LanguageBaseService;
use App\Exceptions\ApiErrorException;
use Illuminate\Console\Command;
use Exception;
use Illuminate\Support\Facades\Log;
class ApplicationLanguageBaseData extends Command
{
protected $signature = 'cron:create-application-language-base-data'; // tables to translate_base table import data ..
protected $description = '';
private $languageBaseService;
public function __construct(
LanguageBaseService $languageBaseService
)
{
$this->languageBaseService = $languageBaseService;
parent::__construct();
}
public function handle()
{
try {
$this->info(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' LANGUAGE BASE START');
$process = $this->languageBaseService->createApplicationLanguageBaseData();
if($process['status'] != 'success'){
throw new Exception($process['message']) ;
}
$this->info(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' LANGUAGE BASE FINISHED');
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' ERROR: ' . $message);
}
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace App\Console\Commands\ApplicationLanguageFiles;
use App\Core\Service\LanguageBaseService;
use App\Exceptions\ApiErrorException;
use Illuminate\Console\Command;
use Exception;
use Illuminate\Support\Facades\Log;
class ApplicationLanguageFiles extends Command
{
protected $signature = 'cron:create-application-language-files'; // fill common.json ...
protected $description = '';
private $languageBaseService;
public function __construct(
LanguageBaseService $languageBaseService
)
{
$this->languageBaseService = $languageBaseService;
parent::__construct();
}
public function handle()
{
try {
$this->info(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' LANGUAGE CREATE JSON START');
$process = $this->languageBaseService->createApplicationLanguageFiles();
if($process['status'] != 'success'){
throw new Exception($process['message']) ;
}
$this->info(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' LANGUAGE CREATE JSON FINISHED');
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' ERROR: ' . $message);
}
}
}

View File

@@ -0,0 +1,356 @@
<?php
namespace App\Console\Commands\ChannelManager;
use App\Core\Mail\LogMail;
use App\Core\Service\ChannelManagerPropertyMappingService;
use App\Core\Service\PropertyBookingEngineService;
use App\Core\Service\PropertyChannelMappingService;
use App\Core\Service\PropertyRoomRateChannelMappingService;
use App\Core\Service\PropertyRoomRatePriceService;
use App\Exceptions\ApiErrorException;
use App\Http\Controllers\BookingEngine\V1\SearchController;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class BestAvailableRateSyncService extends Command
{
protected $signature = 'cron:bar-sync-service {--property_id=}';
protected $description = '';
protected $mailer;
public function __construct(
Mailer $mailer,
ChannelManagerPropertyMappingService $channelManagerPropertyMappingService,
PropertyRoomRateChannelMappingService $propertyRoomRateChannelMappingService,
PropertyBookingEngineService $propertyBookingEngineService,
PropertyRoomRatePriceService $propertyRoomRatePriceService
)
{
parent::__construct();
$this->mailer = $mailer;
$this->channelManagerPropertyMappingService = $channelManagerPropertyMappingService;
$this->propertyRoomRateChannelMappingService = $propertyRoomRateChannelMappingService;
$this->propertyBookingEngineService = $propertyBookingEngineService;
$this->propertyRoomRatePriceService = $propertyRoomRatePriceService;
}
public function handle()
{
$this->info(date('Y-m-d H:i:s') . ' : Start');
$requestParam =
[
'criteria' =>
[
['field' => 'status', 'condition' => '=', 'value' => 1],
['field' => 'channel_manager_id', 'condition' => '=', 'value' => 2],//Channex
['field' => 'channel_manager_property_id', 'condition' => '!=', 'value' => null],
],
'with' => ['property']
];
$howManyDays = 90;
if (!is_null($this->option('property_id'))) {
$requestParam['criteria'][] = ['field' => 'property_id', 'condition' => '=', 'value' => $this->option('property_id')];
$howManyDays = 6 * 30;
}
$channelManagerPropertyMapping = $this->channelManagerPropertyMappingService->select($requestParam);
$channelManagerPropertyMapping = $channelManagerPropertyMapping['status'] == 'success' ? $channelManagerPropertyMapping['data'] : [];
foreach ($channelManagerPropertyMapping as $propertyMapping) {
if ($propertyMapping['property']['status'] != 1) {
$this->error(date('Y-m-d H:i:s') . ' : ' . $propertyMapping['property']['name']);
continue;
}
$response = ['status' => false, 'message' => ''];
try {
$propertyRoomRateChannelMappingParam = [
'criteria' => [
['field' => 'channel_id', 'condition' => '=', 'value' => 5],//Kanal Yöentimi
['field' => 'property_id', 'condition' => '=', 'value' => $propertyMapping['property_id']],
['field' => 'status', 'condition' => '=', 'value' => 1],
],
'with' => [
'propertyRoomRateMapping.propertyRoomRate.propertyRoomRateAccommodation',
'propertyRoomRateMapping.propertyRoom.propertyRoomType',
]
];
$propertyRoomRateChannelMapping = $this->propertyRoomRateChannelMappingService->select($propertyRoomRateChannelMappingParam);
$propertyRoomRateChannelMapping = $propertyRoomRateChannelMapping['status'] == 'success' ? $propertyRoomRateChannelMapping['data'] : [];
$propertyRoomRateChannelMappingCollect = collect($propertyRoomRateChannelMapping);
$propertyBookingEngineParam = [
'criteria' => [
['field' => 'property_id', 'condition' => '=', 'value' => $propertyMapping['property_id']],
['field' => 'channel_id', 'condition' => '=', 'value' => 1],
['field' => 'status', 'condition' => '=', 'value' => 1],
],
'with' => ['channel', 'property.propertyBookingEngineToken'],
'firstRow' => 1
];
$propertyBookingEngine = $this->propertyBookingEngineService->select($propertyBookingEngineParam, ['id', 'property_id', 'channel_id', 'token']);
$propertyBookingEngine = $propertyBookingEngine['status'] == 'success' ? $propertyBookingEngine['data'] : [];
if (empty($propertyBookingEngine)) {
$this->info(date('Y-m-d H:i:s') . ' : None Booking Engine!');
continue;
}
$searchController = App::make("App\Http\Controllers\BookingEngine\V1\SearchController");
$roomRateFormatted = [];
$today = Carbon::now()->startOfDay()->toDateTimeString();
if (!is_null($this->option('property_id'))) {
$today = Carbon::now()->startOfDay()->toDateTimeString();
} else {
//00:00 04:00 08:00 12:00 16:00 20:00
$processHour = (integer)Carbon::now()->format('H');
switch ($processHour) {
case ($processHour >= 0 && $processHour <= 2) :
case ($processHour > 8 && $processHour <= 10):
case ($processHour > 16 && $processHour <= 18):
$today = Carbon::now()->startOfDay()->toDateTimeString();
break;
case ($processHour > 2 && $processHour <= 4) :
case ($processHour > 10 && $processHour <= 12):
case ($processHour > 18 && $processHour <= 20) :
$today = Carbon::now()->startOfDay()->addDays($howManyDays)->toDateTimeString();
break;
case ($processHour > 4 && $processHour <= 6) :
case ($processHour > 12 && $processHour <= 14):
case ($processHour > 20 && $processHour <= 22) :
$today = Carbon::now()->startOfDay()->addDays($howManyDays * 2)->toDateTimeString();
break;
case ($processHour > 6 && $processHour <= 8) :
case ($processHour > 14 && $processHour <= 16):
case ($processHour > 22 && $processHour < 24) :
$today = Carbon::now()->startOfDay()->addDays($howManyDays * 3)->toDateTimeString();
break;
}
}
for ($i = 0; $i < $howManyDays; $i++) {
$checkIn = Carbon::parse($today)->addDays($i)->toDateString();
$checkOut = Carbon::parse($checkIn)->addDay()->toDateString();
$searchRequestJson = [
'date' => [
'checkIn' => $checkIn,
'checkOut' => $checkOut,
],
'rooms' => [
[
'adults' => 2,
'children' => 0,
'age' => [],
]
],
'property' => [],
'ipAddress' => '185.137.215.118',
'isMobile' => null,
'noneCacheSearch' => true,
'min_stay_disabled' => true
];
$requestCreate = Request::create(null, null, [], [], [], [], json_encode($searchRequestJson));
$requestCreate->headers->set('channelId', '1');
$requestCreate->headers->set('bookingEnginePropertyId', $propertyMapping['property_id']);
$requestCreate->headers->set('channelToken', $propertyBookingEngine['channel']['token']);
$requestCreate->headers->set('bookingEngineToken', $propertyBookingEngine['property']['property_booking_engine_token']['token']);
$search = $searchController->search($requestCreate);
$search = json_decode(json_encode($search), 1);
$this->info(date('Y-m-d H:i:s') . ' : ' . $propertyBookingEngine['property']['name'] . ' - ' . $checkIn);
if ($search['original']['status'] == 200) {
if (empty($search['original']['data']['properties'])) {
//Rate Stop or Price 0 Case
foreach ($propertyRoomRateChannelMapping as $roomRateChannelMapping) {
$referenceRoomRateMapping = $propertyRoomRateChannelMappingCollect
->where('property_room_rate_mapping.room_id', $roomRateChannelMapping['property_room_rate_mapping']['room_id'])
->where('property_room_rate_mapping.property_room_rate.name', 'Best Available Rate')->first();
if (!empty($referenceRoomRateMapping)) {
$roomRateKey = '1|' . $referenceRoomRateMapping['property_room_rate_mapping']['room_id'] . '|' . $referenceRoomRateMapping['property_room_rate_mapping']['id'] . '|' . $checkIn;
$roomRateFormatted[$roomRateKey] = [
'setup_type_id' => '1',
'room_id' => $referenceRoomRateMapping['property_room_rate_mapping']['room_id'],
'room_rate_mapping_id' => $referenceRoomRateMapping['property_room_rate_mapping']['id'],
'date' => $checkIn,
'amount' => 0
];
}
}
//Rate Stop or Price 0 Case
$this->info(date('Y-m-d H:i:s') . ' : ' . $propertyBookingEngine['property']['name'] . ' - ' . $checkIn . ' - NONE');
continue;
}
$property = reset($search['original']['data']['properties']);
if (empty($property)) {
$this->info(date('Y-m-d H:i:s') . ' : ' . $propertyBookingEngine['property']['name'] . ' - ' . $checkIn . ' - NONE');
continue;
}
if (!isset($property['availabilities'])) {
$this->info(date('Y-m-d H:i:s') . ' : ' . $propertyBookingEngine['property']['name'] . ' - ' . $checkIn . ' - NONE');
continue;
}
$propertyAvailability = reset($property['availabilities']);
if (empty($propertyAvailability)) {
$this->info(date('Y-m-d H:i:s') . ' : ' . $propertyBookingEngine['property']['name'] . ' - ' . $checkIn . ' - NONE');
continue;
}
/*dd($propertyAvailability['rooms']);
$propertyAvailabilityRoom = reset($propertyAvailability['rooms']);
if (empty($propertyAvailability)) {
$this->info(date('Y-m-d H:i:s') . ' : ' . $propertyBookingEngine['property']['name'] . ' - ' . $checkIn . ' - NONE');
continue;
}
$propertyAvailabilityRoom['rates'] = collect($propertyAvailabilityRoom['rates'])->sortBy('total')->toArray();
*/
foreach ($propertyAvailability['rooms'] as $roomId => $room) {
foreach ($room['rates'] as $roomRateInnerKey => $roomRate) {
/*$propertyAvailabilityRoomRate = reset($propertyAvailabilityRoom['rates']);
if (empty($propertyAvailabilityRoomRate)) {
$this->info(date('Y-m-d H:i:s') . ' : ' . $propertyBookingEngine['property']['name'] . ' - ' . $checkIn . ' - NONE');
continue;
}*/
$propertyAvailabilityRoomRatePrices = reset($roomRate['requestedRoomPrice']);
if (empty($propertyAvailabilityRoomRatePrices)) {
$this->info(date('Y-m-d H:i:s') . ' : ' . $propertyBookingEngine['property']['name'] . ' - ' . $checkIn . ' - NONE');
continue;
}
$propertyAvailabilityRoomRatePrice = reset($propertyAvailabilityRoomRatePrices['prices']);
if (empty($propertyAvailabilityRoomRatePrice)) {
$this->info(date('Y-m-d H:i:s') . ' : ' . $propertyBookingEngine['property']['name'] . ' - ' . $checkIn . ' - NONE');
continue;
}
$this->info(date('Y-m-d H:i:s') . ' : ' . $propertyBookingEngine['property']['id'] . ' - ' . $propertyBookingEngine['property']['name'] . ' - ' . $checkIn . ' - ' . $propertyAvailabilityRoomRatePrice['total']);
$referenceRoomRateMapping = $propertyRoomRateChannelMappingCollect
->where('property_room_rate_mapping.room_id', $roomId)
->where('property_room_rate_mapping.property_room_rate.name', 'Best Available Rate')->first();
if (empty($referenceRoomRateMapping)) {
$this->info(date('Y-m-d H:i:s') . ' : None Best Available Rate! PropertyId: ' . $propertyMapping['property_id'] . ' Room: ' . $room['name']);
continue;
}
/*if($referenceRoomRateMapping['property_room_rate_mapping']['id'] != 6003) {
continue;
}*/
$roomRateKey = '1|' . $referenceRoomRateMapping['property_room_rate_mapping']['room_id'] . '|' . $referenceRoomRateMapping['property_room_rate_mapping']['id'] . '|' . $checkIn;
if (!isset($roomRateFormatted[$roomRateKey])) {
$roomRateFormatted[$roomRateKey] = [
'setup_type_id' => '1',
'room_id' => $referenceRoomRateMapping['property_room_rate_mapping']['room_id'],
'room_rate_mapping_id' => $referenceRoomRateMapping['property_room_rate_mapping']['id'],
'date' => $checkIn,
'amount' => $propertyAvailabilityRoomRatePrice['total']
];
}
if ($propertyAvailabilityRoomRatePrice['total'] < $roomRateFormatted[$roomRateKey]['amount']) {
$roomRateFormatted[$roomRateKey]['amount'] = $propertyAvailabilityRoomRatePrice['total'];
}
}
}
} else {
$this->info(date('Y-m-d H:i:s') . ' : ' . $propertyBookingEngine['property']['name'] . ' - ' . $checkIn . ' - NONE');
}
}
$requestParams = [
'property_id' => $propertyMapping['property_id'],
'channel_id' => 5,
'availability' => [],
'user_id' => 1,
'rates' => $roomRateFormatted
];
$roomRateUpdate = $this->propertyRoomRatePriceService->roomRateUpdate($requestParams);
if ($roomRateUpdate['status'] != 'success') {
throw new ApiErrorException($roomRateUpdate['message']);
}
$response['status'] = true;
$this->info(date('Y-m-d H:i:s') . ' : ' . $propertyBookingEngine['property']['id'] . ' : ' . $propertyBookingEngine['property']['name'] . ' - Today: ' . $today . ' - OK');
Log::debug($propertyBookingEngine['property']['id'] . ' : ' . $propertyBookingEngine['property']['name'] . ' - Today: ' . $today . ' - OK');
} catch (ApiErrorException $e) {
$response['message'] = implode(', ', $e->getMessageArr());
$this->error(date('Y-m-d H:i:s') . ' : ' . $response['message']);
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$response['message'] = $e->getMessage();
}
}
$this->info(date('Y-m-d H:i:s') . ' : Finished');
}
}

View File

@@ -0,0 +1,130 @@
<?php
namespace App\Console\Commands\ChannelManager;
use App\Core\Mail\LogMail;
use App\Core\Service\ChannelManagerBookingService;
use App\Exceptions\ApiErrorException;
use App\Models\Booking;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Log;
use Exception;
class MetaCancellationService extends Command
{
protected $signature = 'cron:meta-cancellation-service';
protected $description = '';
protected $channelService;
public function __construct(
Mailer $mailer,
ChannelManagerBookingService $channelManagerBookingService
)
{
parent::__construct();
$this->mailer = $mailer;
$this->channelManagerBookingService = $channelManagerBookingService;
}
public function handle()
{
$this->info(date('Y-m-d H:i:s') . ' : Start');
$today = Carbon::now()->startOfDay()->toDateString();
if(!Carbon::parse($today)->isLastOfMonth()) {
$this->alert(date('Y-m-d H:i:s') . ' : Not Today!');
return false;
}
$fistDayOfMonth = Carbon::parse($today)->startOfMonth()->toDateString();
$lastDayOfMonth = Carbon::parse($today)->addMonth()->startOfMonth()->toDateString();
$cancellationBooking = Booking::where('channel_id', 1)
->where('status', 0)
->where('checkout_date', '>', $fistDayOfMonth)
->where('checkout_date', '<', $lastDayOfMonth)
//->where('id', 68690)
->with('channelManagerBooking')
->with('bookingRoom')
->get();
//11 - Trivago
$cancellationBooking = $cancellationBooking ? $cancellationBooking->toArray() : [];
foreach ($cancellationBooking as $booking) {
try {
if (empty($booking['channel_manager_booking'])) {
$this->line(date('Y-m-d H:i:s') . ' : Booking ID: ' . $booking['id']);
continue;
}
$channelBookingCheck = collect($booking['channel_manager_booking'])
->where('channel_manager_id', 11)
->where('type', 'Booking')
->where('is_pushed', 1)
->isEmpty();
if ($channelBookingCheck) {
$this->line(date('Y-m-d H:i:s') . ' : Booking ID: ' . $booking['id']);
continue;
}
$channelCancelCheck = collect($booking['channel_manager_booking'])
->where('channel_manager_id', 11)
->where('type', 'Cancel')
->where('is_pushed', 1)
->isEmpty();
if (!$channelCancelCheck) {
$this->line(date('Y-m-d H:i:s') . ' : Booking ID: ' . $booking['id']);
continue;
}
$channelManagerBookingCreateParam = [
'property_id' => $booking['property_id'],
'booking_id' => $booking['id'],
'channel_manager_id' => 11,
'type' => 'Cancel',
];
$this->channelManagerBookingService->create($channelManagerBookingCreateParam);
$this->info(date('Y-m-d H:i:s') . ' : Booking ID: ' . $booking['id']);
} catch (ApiErrorException $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $e->getMessage());
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $message);
}
}
$this->info(date('Y-m-d H:i:s') . ' : Finished');
}
}

View File

@@ -0,0 +1,72 @@
<?php
namespace App\Console\Commands\ChannelManager;
use App\Core\Mail\LogMail;
use App\Core\Service\PropertyRoomRatePriceService;
use App\Core\Service\PropertyRoomService;
use App\Exceptions\ApiErrorException;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Maatwebsite\Excel\Facades\Excel;
use PhpOffice\PhpSpreadsheet\IOFactory;
class PropertyBookingSyncService extends Command
{
protected $signature = 'cron:propertybooking-sync-service';
protected $description = '';
protected $mailer;
public function __construct(
Mailer $mailer,
PropertyRoomService $propertyRoomService,
PropertyRoomRatePriceService $propertyRoomRatePriceService
)
{
parent::__construct();
$this->mailer = $mailer;
$this->propertyRoomService = $propertyRoomService;
$this->propertyRoomRatePriceService = $propertyRoomRatePriceService;
}
public function handle()
{
$sourcePath = 'C:\www\api.extranetwork.com\app\Console\Commands\ChannelManager\akgun.xlsx';
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
$spreadsheet = $reader->load($sourcePath);
$sheet = $spreadsheet->getSheet($spreadsheet->getFirstSheetIndex());
$rows = $sheet->toArray();
$rowKey = 0;
foreach ($rows as $row) {
$rowKey++;
if($rowKey < 3) {
continue;
}
dd($row);
}
//dd(file_exists($sourcePath));
$this->info(date('Y-m-d H:i:s') . ' : Start');
$this->info(date('Y-m-d H:i:s') . ' : Finished');
}
}

View File

@@ -0,0 +1,222 @@
<?php
namespace App\Console\Commands\ChannelManager;
use App\Core\Mail\LogMail;
use App\Core\Service\ChannelManager\Reseliva;
use App\Core\Service\ChannelManagerService;
use App\Core\Service\PropertyRoomAvailabilityQueueService;
use App\Core\Service\PropertyRoomRatePriceService;
use App\Core\Service\PropertyRoomService;
use App\Exceptions\ApiErrorException;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class PropertyChannelSyncService extends Command
{
protected $signature = 'cron:propertychannel-sync-service';
protected $description = '';
protected $mailer;
public function __construct(
Mailer $mailer,
PropertyRoomService $propertyRoomService,
PropertyRoomRatePriceService $propertyRoomRatePriceService
)
{
parent::__construct();
$this->mailer = $mailer;
$this->propertyRoomService = $propertyRoomService;
$this->propertyRoomRatePriceService = $propertyRoomRatePriceService;
}
public function handle()
{
$sourceChannelId = 1; //Booking Engine
$targetChannelId = 5; //Channel Manager
$propertyIdList = [1098];
$this->info(date('Y-m-d H:i:s') . ' : Start');
foreach ($propertyIdList as $propertyId) {
$this->info(date('Y-m-d H:i:s') . ' - AVAILABILITY START : Property: ' . $propertyId . ' : SourceChannelId: ' . $sourceChannelId . ' : TargetChannelId: ' . $targetChannelId);
$isPropertyRoomAvailabilityUpdate = false;
DB::beginTransaction();
try {
$propertyRoomAvailabilityUpdateQuery = <<<BUR
UPDATE property_room_availability SET status = 1 WHERE property_id = {$propertyId} AND date >= curdate() AND channel_id IS NULL AND status = 1;
BUR;
$propertyRoomAvailabilityUpdate = DB::select(DB::raw($propertyRoomAvailabilityUpdateQuery));
$isPropertyRoomAvailabilityUpdate = true;
} catch (ApiErrorException $e) {
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $e->getMessage());
} catch (\Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $message);
}
if ($isPropertyRoomAvailabilityUpdate) {
DB::commit();
$this->info(date('Y-m-d H:i:s') . ' - AVAILABILITY SUCCESS : Property: ' . $propertyId . ' : SourceChannelId: ' . $sourceChannelId . ' : TargetChannelId: ' . $targetChannelId);
} else {
DB::rollBack();
$this->info(date('Y-m-d H:i:s') . ' - AVAILABILITY ERROR : Property: ' . $propertyId . ' : SourceChannelId: ' . $sourceChannelId . ' : TargetChannelId: ' . $targetChannelId);
}
$this->info(date('Y-m-d H:i:s') . ' - AVAILABILITY FINISHED : Property: ' . $propertyId . ' : SourceChannelId: ' . $sourceChannelId . ' : TargetChannelId: ' . $targetChannelId);
$this->info(date('Y-m-d H:i:s') . ' - RATE START : Property: ' . $propertyId . ' : SourceChannelId: ' . $sourceChannelId . ' : TargetChannelId: ' . $targetChannelId);
$requestParams = [
'property_id' => $propertyId,
'channel_id' => $sourceChannelId,
'start_date' => Carbon::now()->toDateString(),
'end_date' => Carbon::now()->addMonths(6)->subDay()->toDateString(),
//'start_date' => '2023-03-01',
//'end_date' => '2024-01-01',
];
$propertyRoomType = $this->propertyRoomService->getPropertyRoomInventory($requestParams);
if ($propertyRoomType['status'] != 'success') {
throw new ApiErrorException($propertyRoomType['message']);
}
$propertyRoomType = $propertyRoomType['data'];
$propertyRoomRateAvailability = collect($propertyRoomType);
$roomRates = [];
foreach ($propertyRoomRateAvailability as $room) {
foreach ($room['property_room_rate_mapping'] as $roomRateMapping) {
foreach ($room['room_availability'] as $date => $roomAvailability) {
$roomRates[$room['id']]['availability'][$date] = $roomAvailability['value'];
}
$roomRates[$room['id']]['rate'][$roomRateMapping['id']] = [
'roomName' => $room['name'],
'roomRateName' => $roomRateMapping['name'],
'currencyCode' => $roomRateMapping['currency_code'],
];
$roomRatePrices = reset($roomRateMapping['prices']);
foreach ($roomRatePrices['price'] as $date => $roomRatePrice) {
$roomRates[$room['id']]['rate'][$roomRateMapping['id']]['price'][$date] = $roomRatePrice['value'];
$roomRates[$room['id']]['rate'][$roomRateMapping['id']]['stopSell'][$date] = $roomRatePrice['stop_sell'];
}
foreach ($roomRatePrices['stop_sell'] as $date => $stopSell) {
$roomRates[$room['id']]['rate'][$roomRateMapping['id']]['stopSell'][$date] = $stopSell['value'];
}
foreach ($roomRatePrices['min_stay'] as $date => $minStay) {
$roomRates[$room['id']]['rate'][$roomRateMapping['id']]['minStay'][$date] = $minStay['value'];
}
}
}
$roomRateFormatted = [];
foreach ($roomRates as $roomId => $roomRateMapping) {
foreach ($roomRateMapping['rate'] as $roomRateMappingId => $roomRate) {
foreach ($roomRate['price'] as $date => $price) {
$roomRateKey = '1|' . $roomId . '|' . $roomRateMappingId . '|' . $date;
$roomRateFormatted[$roomRateKey] = [
'setup_type_id' => '1',
'room_id' => $roomId,
'room_rate_mapping_id' => $roomRateMappingId,
'date' => $date,
'amount' => is_null($price) ? 0 : $price,
'min_stay' => $roomRate['minStay'][$date],
'stop_sell' => $roomRate['stopSell'][$date],
];
}
}
}
$isPropertyRoomRateUpdate = false;
DB::beginTransaction();
try {
$roomRateFormattedChunked = array_chunk($roomRateFormatted, 1000);
foreach ($roomRateFormattedChunked as $roomRateFormattedParsed) {
$requestParams = [
'property_id' => $propertyId,
'channel_id' => $targetChannelId,
'rates' => $roomRateFormattedParsed
];
$roomRateUpdate = $this->propertyRoomRatePriceService->roomRateUpdate($requestParams);
if ($roomRateUpdate['status'] != 'success') {
throw new ApiErrorException($roomRateUpdate['message']);
}
}
$isPropertyRoomRateUpdate = true;
} catch (ApiErrorException $e) {
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $e->getMessage());
} catch (\Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $message);
}
if ($isPropertyRoomRateUpdate) {
DB::commit();
$this->info(date('Y-m-d H:i:s') . ' - RATE SUCCESS : Property: ' . $propertyId . ' : SourceChannelId: ' . $sourceChannelId . ' : TargetChannelId: ' . $targetChannelId);
} else {
DB::rollBack();
$this->info(date('Y-m-d H:i:s') . ' - RATE ERROR : Property: ' . $propertyId . ' : SourceChannelId: ' . $sourceChannelId . ' : TargetChannelId: ' . $targetChannelId);
}
$this->info(date('Y-m-d H:i:s') . ' - RATE FINISHED : Property: ' . $propertyId . ' : SourceChannelId: ' . $sourceChannelId . ' : TargetChannelId: ' . $targetChannelId);
}
$this->info(date('Y-m-d H:i:s') . ' : Finished');
}
}

View File

@@ -0,0 +1,344 @@
<?php
namespace App\Console\Commands\ChannelManager;
use App\Core\Mail\LogMail;
use App\Exceptions\ApiErrorException;
use App\Models\PropertyMeta;
use App\Models\PropertyMetaRoomRate;
use App\Models\PropertyMetaRoomRatePrice;
use App\Models\PropertyRoomRatePrice;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class PropertyMetaRoomRatePriceService extends Command
{
protected $signature = 'cron:propertymeta-roomrateprice-service {--property_id=}';
protected $description = '';
protected $mailer;
public function __construct(
Mailer $mailer
)
{
parent::__construct();
$this->mailer = $mailer;
}
public function handle()
{
$this->info(date('Y-m-d H:i:s') . ' : Start');
if (!is_null($this->option('property_id'))) {
$propertyMeta = PropertyMeta::where('status', 1)->where('property_id', $this->option('property_id'))->with('property')->orderBy('id', 'ASC')->get(['id', 'property_id', 'cancellation_policy', 'adult_policy', 'child_policy', 'promotion', 'status'])->toArray();
} else {
$propertyMeta = PropertyMeta::where('status', 1)->with('property')->orderBy('id', 'ASC')->get(['id', 'property_id', 'cancellation_policy', 'adult_policy', 'child_policy', 'promotion', 'status'])->toArray();
}
foreach ($propertyMeta as $property) {
$this->info(date('Y-m-d H:i:s') . ' : Property Room Rate Price Start: ' . $property['property']['name']);
$roomRateOccupancyPriceParam = [];
$propertyId = $property['property_id'];
$startDate = Carbon::now()->toDateString();
$finishDate = Carbon::parse($startDate)->addDays(360)->toDateString();
$propertyCancellationPolicy = json_decode($property['cancellation_policy'], 1);
$propertyAdultPolicy = json_decode($property['adult_policy'], 1);
$propertyChildPolicy = json_decode($property['child_policy'], 1);
$propertyPromotion = json_decode($property['promotion'], 1);
$propertyRoomRatePrice = PropertyRoomRatePrice::where('property_id', $propertyId)
->where('date', '>=', $startDate)
->where('date', '<=', $finishDate)
->where('channel_id', 1)
//->where('room_rate_mapping_id', 79)//TODO: Delete
//->where('date', '2024-09-01')//TODO: Delete
->where('availability_type_id', 1)
->where('status', 1)
->get(['id', 'property_id', 'property_room_id', 'room_rate_mapping_id', 'date', 'amount', 'currency', 'min_stay', 'stop_sell']);
$propertyRoomRatePrice = $propertyRoomRatePrice->toArray();
$roomRateOccupancy = PropertyMetaRoomRate::where('property_id', $propertyId)->get()->toArray();
//TODO: DEL
//$roomRateOccupancy = collect($roomRateOccupancy)->where('occupancy_code', 'A')->toArray();
$propertyAllPriceCounter = 0;
$roomRateOccupancyPrice = [];
foreach ($propertyRoomRatePrice as $perPropertyRoomRatePrice) {
$roomRateOccupancySelected = collect($roomRateOccupancy)->where('room_rate_mapping_id', $perPropertyRoomRatePrice['room_rate_mapping_id'])->toArray();
foreach ($roomRateOccupancySelected as $roomRateOccupancyKey => $perRoomRateOccupancy) {
$baseAmount = $perPropertyRoomRatePrice['amount'];
$roomRateOccupancyKey = $perRoomRateOccupancy['code'];
$affectedAmountArray = [];
$roomRateMappingId = $perPropertyRoomRatePrice['room_rate_mapping_id'];
$cancellationPolicy = isset($propertyCancellationPolicy[$roomRateMappingId]) ? $propertyCancellationPolicy[$roomRateMappingId] : [];
$adultPolicy = isset($propertyAdultPolicy[$roomRateMappingId]) ? $propertyAdultPolicy[$roomRateMappingId] : [];
$childPolicy = isset($propertyChildPolicy[$roomRateMappingId]) ? $propertyChildPolicy[$roomRateMappingId] : [];
$promotions = isset($propertyPromotion[$roomRateMappingId]) ? $propertyPromotion[$roomRateMappingId] : [];
//dd($promotions,$perPropertyRoomRatePrice,$baseAmount);
$perPersonAmount = $baseAmount / $perRoomRateOccupancy['included_occupancy'];
//Kişi bazlı fiyat hesaplamada baz fiyat dikkate alınır, daha sonra $perPersonAmount baz fiyat üzerinden alınıp çocuk hespaplanır.
//Adult Policy
$affectedAmount = 0;
if ($perRoomRateOccupancy['included_occupancy'] != strlen($perRoomRateOccupancy['occupancy_code'])) {
if (!empty($adultPolicy)) {
if ($perRoomRateOccupancy['included_occupancy'] > strlen($perRoomRateOccupancy['occupancy_code'])) {
$occupancyDifference = $perRoomRateOccupancy['included_occupancy'] - strlen($perRoomRateOccupancy['occupancy_code']);
$adultPolicySelected = collect($adultPolicy)
->where('adult', $occupancyDifference)
->where('adult_action_type', 'DEC')
->first();
if (!empty($adultPolicySelected)) {
if ($adultPolicySelected['type'] == 'PER') {
$affectedAmount = ($baseAmount * $adultPolicySelected['value'] / 100);
} elseif ($adultPolicySelected['type'] == 'FIX') {
$affectedAmount = $adultPolicySelected['value'];
}
$affectedAmountArray[] = $adultPolicySelected['action_type'] == 'DEC' ? ($affectedAmount * -1) : $affectedAmount;
}
}
if (strlen($perRoomRateOccupancy['occupancy_code']) > $perRoomRateOccupancy['included_occupancy']) {
$occupancyDifference = strlen($perRoomRateOccupancy['occupancy_code']) - $perRoomRateOccupancy['included_occupancy'];
$adultPolicySelected = collect($adultPolicy)
->where('adult', $occupancyDifference)
->where('adult_action_type', 'INC')
->first();
if (!empty($adultPolicySelected)) {
if ($adultPolicySelected['type'] == 'PER') {
$affectedAmount = ($baseAmount * $adultPolicySelected['value'] / 100);
} elseif ($adultPolicySelected['type'] == 'FIX') {
$affectedAmount = $adultPolicySelected['value'];
}
$affectedAmountArray[] = $adultPolicySelected['action_type'] == 'DEC' ? ($affectedAmount * -1) : $affectedAmount;
}
}
}
}
//Adult Policy
//Önce Oda Fiyatı Hesaplanır, Yetişkine Göre
$roomAmount = $baseAmount + array_sum($affectedAmountArray);
//Oluşan fiyata göre de iptal politikası uygulanır
//$cancellationPolicy
$affectedAmount = 0;
$isCancellationPolicyActive = false;
if (isset($cancellationPolicy[$perRoomRateOccupancy['cancellation_policy_id']])) {
$cancellationPolicySelected = $cancellationPolicy[$perRoomRateOccupancy['cancellation_policy_id']];
//dd($cancellationPolicy,$perRoomRateOccupancy,$cancellationPolicySelected,$perPropertyRoomRatePrice['date']);
//if ($cancellationPolicySelected['is_affected_price'] == 1) {
$isDateRange = $cancellationPolicySelected['is_date_range'];
$isDateRangeDate = Carbon::parse($perPropertyRoomRatePrice['date'])->between($cancellationPolicySelected['start_date'], $cancellationPolicySelected['finish_date']);
if (($isDateRange && $isDateRangeDate) || empty($isDateRange)) {
if ($cancellationPolicySelected['affect_price_type'] == 'PER') {
$affectedAmount = ($roomAmount * $cancellationPolicySelected['affect_price_value'] / 100);
} elseif ($cancellationPolicySelected['affect_price_type'] == 'FIX') {
$affectedAmount = $cancellationPolicySelected['affect_price_value'];
}
$affectedAmountArray[] = $cancellationPolicySelected['affect_price_action_type'] == 'DEC' ? ($affectedAmount * -1) : $affectedAmount;
$isCancellationPolicyActive = true;
}
//}
}
//$cancellationPolicy
//dd($perRoomRateOccupancy, $perPropertyRoomRatePrice, $cancellationPolicy);
$isCancellationPolicyActive = true;
if ($isCancellationPolicyActive) {
$calculatedAmount = $baseAmount + array_sum($affectedAmountArray);
$promotionsGrouped = collect($promotions)->groupBy('type')->toArray();
/**** PROMOTION START ****/
$totalPromotionDiscount = 0;
foreach ($promotionsGrouped as $promotionsGroupKey => $promotions) {
$promotions = collect($promotions)->sortByDesc('amount')->toArray();
foreach ($promotions as $promotion) {
if ($promotion['min_stay'] > 1) {
continue;
}
if ($promotion['is_mobile']) {
continue;
}
$daysArray = !empty($promotion['days']) ? json_decode($promotion['days'], 1) : [];
if (!in_array((Carbon::parse($perPropertyRoomRatePrice['date'])->dayOfWeek + 1), $daysArray)) {
continue;
}
if ($promotion['type'] == 'PRD') {
if (!Carbon::now()->startOfDay()->between(Carbon::parse($promotion['start_date'])->toDateString(), Carbon::parse($promotion['end_date'])->toDateString())) {
continue;
}
if (!Carbon::parse($perPropertyRoomRatePrice['date'])->startOfDay()->between(Carbon::parse($promotion['reservation_start_date'])->toDateString(), Carbon::parse($promotion['reservation_end_date'])->toDateString())) {
continue;
}
$totalPromotionDiscount += ($calculatedAmount * $promotion['amount']) / 100;
break;
}
if ($promotion['type'] == 'BFD') {
if (Carbon::parse($perPropertyRoomRatePrice['date'])->diffInDays(Carbon::now()->startOfDay()->toDateString()) < $promotion['day_before']) {
continue;
}
$totalPromotionDiscount += ($calculatedAmount * $promotion['amount']) / 100;
break;
}
if ($promotion['type'] == 'DSC') {
$totalPromotionDiscount += ($calculatedAmount * $promotion['amount']) / 100;
break;
}
}
}
$calculatedAmount = moneyDoubleFormatDecimal($calculatedAmount - $totalPromotionDiscount);
$calculatedAmount = $calculatedAmount > 0 ? $calculatedAmount : 0;
/**** PROMOTION FINISHED ****/
$roomRateOccupancyPriceParam[] = [
'property_id' => $property['property_id'],
'room_id' => $perRoomRateOccupancy['room_id'],
'room_rate_mapping_id' => $roomRateMappingId,
'date' => $perPropertyRoomRatePrice['date'],
'code' => $roomRateOccupancyKey,
//'title' => $perRoomRateOccupancy['title'],
//'baseAmount' => $perPropertyRoomRatePrice['amount'],
'amount' => $calculatedAmount,
'currency' => $perPropertyRoomRatePrice['currency'],
'status' => 1,
'created_by' => 1,
'updated_by' => 1,
'created_at' => Carbon::now()->unix(),
'updated_at' => Carbon::now()->unix(),
];
$propertyAllPriceCounter++;
}
}
}
$this->info(date('Y-m-d H:i:s') . ' : Property Room Rate Price Finished: ' . $property['property']['name']);
//dd(collect($roomRateOccupancyPriceParam)->sortBy('room_id')->sortBy('amount')->toArray());
$insertRows = [];
$updateRows = [];
$rowChunk = 0;
foreach ($roomRateOccupancyPriceParam as $roomRateOccupancyPrice) {
$insertRows[$rowChunk][] = $roomRateOccupancyPrice;
if (count($insertRows[$rowChunk]) > 1000) {
$rowChunk++;
}
}
$this->info(date('Y-m-d H:i:s') . ' : Property Room Rate Price to DB Start: ' . $property['property']['name']);
DB::beginTransaction();
PropertyMetaRoomRatePrice::where('property_id', $propertyId)->delete();
if (!empty($insertRows)) {
foreach ($insertRows as $insertRow) {
PropertyMetaRoomRatePrice::insert($insertRow);
}
}
DB::commit();
$this->info(date('Y-m-d H:i:s') . ' : Property Room Rate Price to DB Finished: ' . $property['property']['name']);
}
$this->info(date('Y-m-d H:i:s') . ' : Finished');
}
}

View File

@@ -0,0 +1,309 @@
<?php
namespace App\Console\Commands\ChannelManager;
use App\Core\Mail\LogMail;
use App\Core\Service\ChannelManager\Mirai;
use App\Exceptions\ApiErrorException;
use App\Models\ChannelManagerPropertyMapping;
use App\Models\PropertyMeta;
use App\Models\PropertyMetaRoomRate;
use App\Models\PropertyMetaRoomRateMapping;
use App\Models\PropertyMetaRoomRatePrice;
use App\Models\PropertyRoomAvailability;
use App\Models\PropertyRoomRatePrice;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class PropertyMetaRoomRatePushService extends Command
{
protected $signature = 'cron:propertymeta-roomratepush-service {--property_id=}';
protected $description = '';
protected $mailer;
public function __construct(
Mailer $mailer,
Mirai $miraiService
)
{
parent::__construct();
$this->mailer = $mailer;
$this->miraiService = $miraiService;
}
function getMonthlyPeriod($endDate)
{
$diffInMonths = Carbon::parse()->floorMonth()->diffInMonths(Carbon::parse($endDate)->floorMonth());
$diffInMonths++;
$monthlyPeriod = [];
$startDate = null;
$finishDate = null;
for ($i = 0; $i < $diffInMonths; $i++) {
if (empty($startDate)) {
$startDate = Carbon::now()->toDateString();
$finishDate = Carbon::parse($startDate)->endOfMonth()->toDateString();
} else {
$startDate = Carbon::now()->addMonths($i)->startOfMonth()->toDateString();
$finishDate = Carbon::parse($startDate)->endOfMonth()->toDateString();
}
if ($finishDate > $endDate) {
$finishDate = $endDate;
}
$monthlyPeriod[] = [
'startDate' => $startDate,
'finishDate' => $finishDate,
];
}
return $monthlyPeriod;
}
public function handle()
{
$this->info(date('Y-m-d H:i:s') . ' : Start');
if (!is_null($this->option('property_id'))) {
$propertyMeta = PropertyMeta::where('status', 1)->where('property_id', $this->option('property_id'))->with('property')->orderBy('id', 'ASC')->get(['id', 'property_id', 'cancellation_policy', 'adult_policy', 'child_policy', 'param', 'status'])->toArray();
} else {
$propertyMeta = PropertyMeta::where('status', 1)->with('property')->orderBy('id', 'ASC')->get(['id', 'property_id', 'cancellation_policy', 'adult_policy', 'child_policy', 'param', 'status'])->toArray();
}
foreach ($propertyMeta as $property) {
$propertyId = $property['property_id'];
//Mirai User Setup
$this->miraiService->setupUser($property['paramsArray']['login'], $property['paramsArray']['password']);
$this->info(date('Y-m-d H:i:s') . ' : Property Room Rate Push Start: ' . $property['property']['name']);
//$propertyRoomRatePriceEndDate = PropertyRoomRatePrice::where('property_id', $propertyId)->orderBy('date', 'DESC')->first();
//$propertyRoomRatePriceEndDate = $propertyRoomRatePriceEndDate->toArray() ? $propertyRoomRatePriceEndDate['date'] : null;
//$propertyRoomRatePriceEndDate = '2023-10-31';
//$getMonthlyPeriod = $this->getMonthlyPeriod($propertyRoomRatePriceEndDate);
$getMonthlyPeriod = [];
$getMonthlyPeriod[] = [
'startDate' => Carbon::now()->toDateString(),
//'finishDate' => Carbon::now()->addYear()->toDateString(),
'finishDate' => Carbon::now()->addDays(360)->toDateString(),
];
$propertyMetaRoomRateMapping = PropertyMetaRoomRateMapping::where('property_id', $propertyId)->with('propertyMetaRoomRate')->get()->toArray();
$propertyMetaRoomRateMappingCollect = collect($propertyMetaRoomRateMapping);
$channelManagerPropertyMapping = ChannelManagerPropertyMapping::where('property_id', $propertyId)->where('status', 1)->where('channel_manager_id', 7)->first()->toArray();
if (empty($channelManagerPropertyMapping)) {
continue;
}
$metaRoomRateMapping = [];
$propertyMetaRoomRateMappingGroup = $propertyMetaRoomRateMappingCollect->groupBy('property_meta_room_rate.room_id')->toArray();
foreach ($propertyMetaRoomRateMappingGroup as $roomGroup) {
$roomGroup = reset($roomGroup);
$metaRoomRateMapping[$roomGroup['property_meta_room_rate']['room_id']]['meta_code'] = $roomGroup['meta_code'];
}
foreach ($getMonthlyPeriod as $period) {
$this->info(date('Y-m-d H:i:s') . ' : Meta Availability Start: ' . $property['property']['name'] . ' - ' . $period['startDate'] . ' / ' . $period['finishDate']);
try {
$propertyRoomAvailability = PropertyRoomAvailability::where('property_id', $propertyId)
->where('status', 1)->where('channel_id', null)
->whereBetween('date', [$period['startDate'], $period['finishDate']])
->get(['property_room_id', 'date', 'stop_sell', 'availability'])
->toArray();
$propertyRoomAvailabilityCollect = collect($propertyRoomAvailability);
foreach ($metaRoomRateMapping as $roomId => $metaRoom) {
$metaRoomRateMapping[$roomId]['data'] = $propertyRoomAvailabilityCollect->where('property_room_id', $roomId)->sortBy('date')->toArray();
}
$xmlResponse = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><inventoryUpdate></inventoryUpdate>');
$xmlResponse->addAttribute('hotelId', $channelManagerPropertyMapping['channel_manager_property_id']);
foreach ($metaRoomRateMapping as $roomId => $metaRoom) {
$room = $xmlResponse->addChild('room');
$room->addAttribute('id', $metaRoom['meta_code']);
$roomInventory = $room->addChild('inventory');
foreach ($metaRoom['data'] as $roomRate) {
$roomInventoryAvailability = $roomInventory->addChild('availability');
$roomRate['availability'] = $roomRate['stop_sell'] == 1 ? 0 : $roomRate['availability'];
$roomInventoryAvailability->addAttribute('date', $roomRate['date']);
$roomInventoryAvailability->addAttribute('quantity', $roomRate['availability']);
}
}
$request = $this->miraiService->inventoryRoomRateUpdate('webservice_updater.apro', $xmlResponse->asXML());
if (!$request['status']) {
throw new ApiErrorException('webservice_updater AVAILABILITY Error: ' . $request['message']);
}
} catch (ApiErrorException $e) {
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $e->getMessage());
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $message);
}
$this->info(date('Y-m-d H:i:s') . ' : Meta Price Start: ' . $property['property']['name'] . ' - ' . $period['startDate'] . ' / ' . $period['finishDate']);
try {
$propertyMetaRoomRatePrice = PropertyMetaRoomRatePrice::where('property_id', $propertyId)
->whereBetween('date', [$period['startDate'], $period['finishDate']])->where('status', 1)
->whereIn('code', pickItemFromArray('code', $propertyMetaRoomRateMapping))
->get(['date', 'code', 'amount', 'currency'])
->toArray();
$propertyMetaRoomRatePriceCollect = collect($propertyMetaRoomRatePrice);
if (empty($propertyMetaRoomRatePrice)) {
$this->error(date('Y-m-d H:i:s') . ' : ' . $property['property']['name'] . ' : Price not found!');
continue;
}
$metaRoomRatePrice = [];
$metaRoomPricesOrdered = [];
foreach ($propertyMetaRoomRateMapping as $metaRoom) {
$metaRoomPrices = $propertyMetaRoomRatePriceCollect->where('code', $metaRoom['code'])->sortBy('date')->toArray();
$metaRoomPricesCollect = collect($metaRoomPrices);
$metaRoomPricesGroup = [];
foreach ($metaRoomPrices as $metaRoomPrice) {
$metaRoomPricesGroup[md5($metaRoomPrice['amount'])][$metaRoomPrice['date']] = $metaRoomPrice;
ksort($metaRoomPricesGroup[md5($metaRoomPrice['amount'])]);
}
foreach ($metaRoomPricesGroup as $priceGroupKey => $priceGroup) {
$priceDateGroup = 0;
foreach ($priceGroup as $priceGroupDate => $price) {
if (!isset($metaRoomPricesOrdered[$metaRoom['meta_code']][$priceGroupKey][$priceDateGroup]['startDate'])) {
$metaRoomPricesOrdered[$metaRoom['meta_code']][$priceGroupKey][$priceDateGroup]['startDate'] = $price['date'];
$metaRoomPricesOrdered[$metaRoom['meta_code']][$priceGroupKey][$priceDateGroup]['finishDate'] = $price['date'];
} else {
if (Carbon::parse($metaRoomPricesOrdered[$metaRoom['meta_code']][$priceGroupKey][$priceDateGroup]['finishDate'])->addDay()->toDateString() != $price['date']) {
$priceDateGroup++;
$metaRoomPricesOrdered[$metaRoom['meta_code']][$priceGroupKey][$priceDateGroup]['startDate'] = $price['date'];
} else {
$metaRoomPricesOrdered[$metaRoom['meta_code']][$priceGroupKey][$priceDateGroup]['finishDate'] = $price['date'];
}
$metaRoomPricesOrdered[$metaRoom['meta_code']][$priceGroupKey][$priceDateGroup]['finishDate'] = $price['date'];
}
$metaRoomPricesOrdered[$metaRoom['meta_code']][$priceGroupKey][$priceDateGroup]['amount'] = $price['amount'];
$metaRoomPricesOrdered[$metaRoom['meta_code']][$priceGroupKey][$priceDateGroup]['currency'] = $price['currency'];
//$metaRoomPricesOrdered[$priceGroupKey][$priceDateGroup]['metaCode'] = $metaRoom['meta_code'];
$metaRoomPricesOrdered[$metaRoom['meta_code']][$priceGroupKey][$priceDateGroup]['title'] = $metaRoom['property_meta_room_rate']['title'];
}
}
}
$xmlResponse = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><inventoryUpdate></inventoryUpdate>');
$xmlResponse->addAttribute('hotelId', $channelManagerPropertyMapping['channel_manager_property_id']);
foreach ($metaRoomPricesOrdered as $roomRateMetaCode => $metaRoom) {
foreach ($metaRoom as $priceGroupKey => $metaRoomPriceGroup) {
$room = $xmlResponse->addChild('room');
$room->addAttribute('id', $roomRateMetaCode);
$currency = !empty($metaRoomPriceGroup) ? reset($metaRoomPriceGroup)['currency'] : 'EUR';
$rate = $room->addChild('rate');
$rate->addAttribute('currency', $currency);
foreach ($metaRoomPriceGroup as $metaRoomPrice) {
$planning = $rate->addChild('planning');
$planning->addAttribute('from', $metaRoomPrice['startDate']);
$planning->addAttribute('to', $metaRoomPrice['finishDate']);
$planning->addAttribute('unitPrice', $metaRoomPrice['amount']);
}
}
}
$request = $this->miraiService->inventoryRoomRateUpdate('webservice_updater.apro', $xmlResponse->asXML());
if (!$request['status']) {
throw new ApiErrorException('webservice_updater PRICE Error: ' . $request['message']);
}
//Remove all prices then push to meta
PropertyMetaRoomRatePrice::where('property_id', $propertyId)->delete();
} catch (ApiErrorException $e) {
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $e->getMessage());
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $message);
}
}
}
$this->info(date('Y-m-d H:i:s') . ' : Finished');
}
}

View File

@@ -0,0 +1,288 @@
<?php
namespace App\Console\Commands\ChannelManager;
use App\Core\Mail\LogMail;
use App\Exceptions\ApiErrorException;
use App\Models\PropertyMeta;
use App\Models\PropertyMetaRoomRate;
use App\Models\PropertyRoomRateChannelMapping;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class PropertyMetaRoomRateService extends Command
{
protected $signature = 'cron:propertymeta-roomrate-service {--property_id=}';
protected $description = '';
protected $mailer;
public function __construct(
Mailer $mailer
)
{
parent::__construct();
$this->mailer = $mailer;
}
public function handle()
{
$this->info(date('Y-m-d H:i:s') . ' : Start');
if (!is_null($this->option('property_id'))) {
$propertyMeta = PropertyMeta::where('status', 1)->where('property_id', $this->option('property_id'))->with('property')->orderBy('id', 'ASC')->get(['id', 'property_id', 'status'])->toArray();
} else {
$propertyMeta = PropertyMeta::where('status', 1)->with('property')->orderBy('id', 'ASC')->get(['id', 'property_id', 'status'])->toArray();
}
foreach ($propertyMeta as $property) {
$this->info(date('Y-m-d H:i:s') . ' : Property Policy Start: ' . $property['property']['name']);
//Property All Room Rate Price Policy
$propertyRoomRateChannelMapping = PropertyRoomRateChannelMapping::with('propertyRoomRateMapping')
->with('propertyRoomRateMapping.propertyRoom')
->with('propertyRoomRateMapping.propertyRoomRate')
->with('propertyRoomRateChannelCancellationPolicy.propertyCancellationPolicy')
->with('propertyRoomRateChannelPricingAdultPolicy.propertyPricingPolicyAdult')
->with('propertyRoomRateChannelPricingChildPolicy.propertyPricingPolicyChild')
->with('propertyRoomRateChannelPromotion.propertyPromotion.promotionType')
->get()
->where('property_id', $property['property_id'])->where('channel_id', 1)
->where('status', 1);
$propertyRoomRateChannelMapping = $propertyRoomRateChannelMapping->where('propertyRoomRateMapping', '!=', null)->toArray();
//dd($propertyRoomRateChannelMapping);
$roomRateMappingPolicy = [];
foreach ($propertyRoomRateChannelMapping as $propertyRoom) {
$roomRateMappingPolicy['promotion'][$propertyRoom['room_rate_mapping_id']] = [];
foreach ($propertyRoom['property_room_rate_channel_promotion'] as $propertyRoomRateChannelPromotion) {
if($propertyRoomRateChannelPromotion['status'] != 1) {
continue;
}
$roomRateMappingPolicy['promotion'][$propertyRoom['room_rate_mapping_id']][$propertyRoomRateChannelPromotion['property_promotion_id']] = [
'type' => $propertyRoomRateChannelPromotion['property_promotion']['promotion_type']['type_code'],
'start_date' => $propertyRoomRateChannelPromotion['property_promotion']['start_date'],
'end_date' => $propertyRoomRateChannelPromotion['property_promotion']['end_date'],
'reservation_start_date' => $propertyRoomRateChannelPromotion['property_promotion']['reservation_start_date'],
'reservation_end_date' => $propertyRoomRateChannelPromotion['property_promotion']['reservation_end_date'],
'day_before' => $propertyRoomRateChannelPromotion['property_promotion']['day_before'],
'amount' => $propertyRoomRateChannelPromotion['property_promotion']['amount'],
'min_stay' => $propertyRoomRateChannelPromotion['property_promotion']['min_stay'],
'is_mobile' => $propertyRoomRateChannelPromotion['property_promotion']['is_mobile'],
'days' => $propertyRoomRateChannelPromotion['property_promotion']['days'],
];
}
$roomRateMappingPolicy['cancellation_policy'][$propertyRoom['room_rate_mapping_id']] = [];
foreach ($propertyRoom['property_room_rate_channel_cancellation_policy'] as $propertyRoomRateCancellationPolicy) {
$roomRateMappingPolicy['cancellation_policy'][$propertyRoom['room_rate_mapping_id']][$propertyRoomRateCancellationPolicy['cancellation_policy_id']] = [
'is_affected_price' => $propertyRoomRateCancellationPolicy['property_cancellation_policy']['is_affected_price'],
'affect_price_action_type' => $propertyRoomRateCancellationPolicy['property_cancellation_policy']['affect_price_action_type'],
'affect_price_type' => $propertyRoomRateCancellationPolicy['property_cancellation_policy']['affect_price_type'],
'affect_price_value' => $propertyRoomRateCancellationPolicy['property_cancellation_policy']['affect_price_value'],
'is_date_range' => $propertyRoomRateCancellationPolicy['property_cancellation_policy']['is_date_range'],
'start_date' => $propertyRoomRateCancellationPolicy['property_cancellation_policy']['start_date'],
'finish_date' => $propertyRoomRateCancellationPolicy['property_cancellation_policy']['finish_date'],
];
}
$roomRateMappingPolicy['adult_policy'][$propertyRoom['room_rate_mapping_id']] = [];
foreach ($propertyRoom['property_room_rate_channel_pricing_adult_policy'] as $propertyRoomRateAdultPolicy) {
$roomRateMappingPolicy['adult_policy'][$propertyRoom['room_rate_mapping_id']][$propertyRoomRateAdultPolicy['pricing_policy_adult_id']] = [
'adult_action_type' => $propertyRoomRateAdultPolicy['property_pricing_policy_adult']['adult_action_type'],
'adult' => $propertyRoomRateAdultPolicy['property_pricing_policy_adult']['adult'],
'action_type' => $propertyRoomRateAdultPolicy['property_pricing_policy_adult']['action_type'],
'type' => $propertyRoomRateAdultPolicy['property_pricing_policy_adult']['type'],
'value' => $propertyRoomRateAdultPolicy['property_pricing_policy_adult']['value'],
];
}
$roomRateMappingPolicy['child_policy'][$propertyRoom['room_rate_mapping_id']] = [];
foreach ($propertyRoom['property_room_rate_channel_pricing_child_policy'] as $propertyRoomRateChildPolicy) {
$roomRateMappingPolicy['child_policy'][$propertyRoom['room_rate_mapping_id']][$propertyRoomRateChildPolicy['pricing_policy_child_id']] = [
'adult' => $propertyRoomRateChildPolicy['property_pricing_policy_child']['adult'],
'child_order' => $propertyRoomRateChildPolicy['property_pricing_policy_child']['child_order'],
'child_age_start' => $propertyRoomRateChildPolicy['property_pricing_policy_child']['child_age_start'],
'child_age_end' => $propertyRoomRateChildPolicy['property_pricing_policy_child']['child_age_end'],
'type' => $propertyRoomRateChildPolicy['property_pricing_policy_child']['type'],
'value' => $propertyRoomRateChildPolicy['property_pricing_policy_child']['value'],
];
}
}
//Property All Room Rate Price Policy
$propertyMetaPolicyUpdate = [
'cancellation_policy' => json_encode($roomRateMappingPolicy['cancellation_policy']),
'adult_policy' => json_encode($roomRateMappingPolicy['adult_policy']),
'child_policy' => json_encode($roomRateMappingPolicy['child_policy']),
'promotion' => json_encode($roomRateMappingPolicy['promotion']),
];
PropertyMeta::where('id', $property['id'])->update($propertyMetaPolicyUpdate);
$this->info(date('Y-m-d H:i:s') . ' : Property Policy Finished: ' . $property['property']['name']);
//$propertyMetaTemp
/*$propertyMetaTemp = PropertyMeta::where('property_id', $property['property_id'])->with('property')->get()->first();
$propertyMetaTemp = $propertyMetaTemp->toArray();
$propertyMetaPolicyUpdate = [
'cancellation_policy' => json_decode($propertyMetaTemp['cancellation_policy'], 1),
'adult_policy' => json_decode($propertyMetaTemp['adult_policy'], 1),
'child_policy' => json_decode($propertyMetaTemp['child_policy'], 1),
];*/
//$propertyMetaTemp
$this->info(date('Y-m-d H:i:s') . ' : Property Room Rate Occupancy Start: ' . $property['property']['name']);
//Property All Price Combination
/*$propertyRoomRateChannelMapping = PropertyRoomRateChannelMapping::with('propertyRoomRateMapping')
->with('propertyRoomRateMapping.propertyRoom')
->with('propertyRoomRateMapping.propertyRoomRate')
->with('propertyRoomRateChannelCancellationPolicy.propertyCancellationPolicy')
->with('propertyRoomRateChannelPricingAdultPolicy')
->with('propertyRoomRateChannelPricingChildPolicy')
->get()
->where('property_id', $property['property_id'])->where('channel_id', 1)
->where('status', 1);
$propertyRoomRateChannelMapping = $propertyRoomRateChannelMapping->where('propertyRoomRateMapping', '!=', null)->toArray();*/
$roomRateOccupancy = [];
foreach ($propertyRoomRateChannelMapping as $propertyRoom) {
$roomId = $propertyRoom['property_room_rate_mapping']['room_id'];
$propertyRoomRateMappingId = $propertyRoom['property_room_rate_mapping']['id'];
$occupancyGroup = occupancyGroup(
$propertyRoom['property_room_rate_mapping']['property_room']['max_adult'],
$propertyRoom['property_room_rate_mapping']['property_room']['max_child'],
$propertyRoom['property_room_rate_mapping']['property_room']['max_occupancy']
);
//TODO: Burası incelenebilir, cancellation policy yok ise gelmiyor çünkü....
/*if(empty($propertyRoom['property_room_rate_channel_cancellation_policy'])) {
$propertyRoom['property_room_rate_channel_cancellation_policy'][] = [
'cancellation_policy_id' => 0,
'property_cancellation_policy' => [
'name' => 'Refundable',
'is_nonrefundable' => 0,
]
];
}*/
foreach ($propertyRoom['property_room_rate_channel_cancellation_policy'] as $propertyRoomRateCancellationPolicy) {
foreach ($occupancyGroup as $occupancyCode) {
$roomRateOccupancyKey = $roomId . '-' . $propertyRoomRateMappingId . '-' . $propertyRoomRateCancellationPolicy['cancellation_policy_id'] . '-' . $occupancyCode;
$roomRateOccupancyKey = md5($roomRateOccupancyKey);
$cancellationPolicyName = [];
$cancellationPolicyName[] = $propertyRoomRateCancellationPolicy['property_cancellation_policy']['is_nonrefundable'] ? 'NonRefundable' : 'Refundable';
$cancellationPolicyName[] = !empty($propertyRoomRateCancellationPolicy['property_cancellation_policy']['name']) ? '(' . $propertyRoomRateCancellationPolicy['property_cancellation_policy']['name'] . ')' : null;
$cancellationPolicyName = implode(' ', $cancellationPolicyName);
$roomRateOccupancyTitle = [];
$roomRateOccupancyTitle[] = $propertyRoom['property_room_rate_mapping']['property_room']['name'];
$roomRateOccupancyTitle[] = $propertyRoom['property_room_rate_mapping']['property_room_rate']['name'];
$roomRateOccupancyTitle[] = $cancellationPolicyName;
$roomRateOccupancyTitle[] = $occupancyCode;
$roomRateOccupancyTitle = implode(' - ', $roomRateOccupancyTitle);
$roomRateOccupancy[$roomRateOccupancyKey] = [
'propertyId' => $property['property_id'],
'roomId' => $roomId,
'roomName' => $propertyRoom['property_room_rate_mapping']['property_room']['name'],
'roomRateMappingId' => $propertyRoomRateMappingId,
'roomRateMappingName' => $propertyRoom['property_room_rate_mapping']['property_room_rate']['name'],
'cancellationPolicyId' => $propertyRoomRateCancellationPolicy['cancellation_policy_id'],
'cancellationPolicyName' => $propertyRoomRateCancellationPolicy['property_cancellation_policy']['name'],
'occupancyCode' => $occupancyCode,
'includedOccupancy' => $propertyRoom['property_room_rate_mapping']['included_occupancy'],
'title' => $roomRateOccupancyTitle
];
}
}
}
//Property All Price Combination
$propertyMetaRoomRateParam = [];
foreach ($roomRateOccupancy as $roomRateOccupancyKey => $roomRate) {
//$propertyMetaRoomRateCheck = PropertyMetaRoomRate::where('code', $roomRateOccupancyKey)->count();
$propertyMetaRoomRateParam[] = [
'code' => $roomRateOccupancyKey,
'title' => $roomRate['title'],
'property_id' => $roomRate['propertyId'],
'room_id' => $roomRate['roomId'],
'room_rate_mapping_id' => $roomRate['roomRateMappingId'],
'cancellation_policy_id' => $roomRate['cancellationPolicyId'],
'included_occupancy' => $roomRate['includedOccupancy'],
'occupancy_code' => $roomRate['occupancyCode'],
'status' => 1,
'created_by' => 1,
'updated_by' => 1,
'created_at' => Carbon::now()->unix(),
'updated_at' => Carbon::now()->unix(),
];
/*if ($propertyMetaRoomRateCheck) {
$propertyMetaRoomRateUpdate = PropertyMetaRoomRate::where('code', $roomRateOccupancyKey)->update($propertyMetaRoomRateParam);
} else {
$propertyMetaRoomRateCreate = PropertyMetaRoomRate::create($propertyMetaRoomRateParam);
}*/
//$this->info(date('Y-m-d H:i:s') . ' : Property Room Rate Occupancy: ' . $roomRate['title']);
}
//Delete all codes
if (!empty($propertyMetaRoomRateParam)) {
PropertyMetaRoomRate::where('property_id', $property['property_id'])->delete();
PropertyMetaRoomRate::insert($propertyMetaRoomRateParam);
}
$this->info(date('Y-m-d H:i:s') . ' : Property Room Rate Occupancy Finished: ' . $property['property']['name']);
}
$this->info(date('Y-m-d H:i:s') . ' : Finished');
}
}

View File

@@ -0,0 +1,116 @@
<?php
namespace App\Console\Commands\ChannelManager;
use App\Core\Mail\LogMail;
use App\Core\Service\BookingPaymentService;
use App\Exceptions\ApiErrorException;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class RemovePaymentTokenService extends Command
{
protected $signature = 'cron:remove-payment-token-service';
protected $description = '';
protected $mailer;
public function __construct(
Mailer $mailer,
BookingPaymentService $bookingPaymentService
)
{
parent::__construct();
$this->mailer = $mailer;
$this->bookingPaymentService = $bookingPaymentService;
}
public function handle()
{
try {
$this->info(date('Y-m-d H:i:s') . ' : Start');
$bookingPaymentDataCriteria =
[
'criteria' =>
[
['field' => 'status', 'condition' => '=', 'value' => 2],
['field' => 'type', 'condition' => '=', 'value' => 'ch'],
],
'with' => ['bookingDetail.channelManager'],
'orderBy' => [
['field' => 'id', 'value' => 'ASC']
]
];
$bookingPaymentData = $this->bookingPaymentService->selectPaymentData($bookingPaymentDataCriteria);
$bookingPaymentData = $bookingPaymentData['status'] == 'success' && !empty($bookingPaymentData['data']) ? $bookingPaymentData['data'] : [];
if (!empty($bookingPaymentData)) {
$bookingPaymentDataCollect = collect($bookingPaymentData);
$bookingPaymentData = $bookingPaymentDataCollect->where('booking_detail.checkout_date', '<', Carbon::now()->subDays(7))->toArray();
}
//$bookingPaymentData
foreach ($bookingPaymentData as $bookingPaymentKey => $bookingPayment) {
if (empty($bookingPayment['booking_detail']['channel_manager_id'])) {
continue;
}
$channelManagerId = $bookingPayment['booking_detail']['channel_manager_id'];
switch ($channelManagerId) {
case 2 :
$channelService = App::make("App\Core\Service\ChannelManager\\{$bookingPayment['booking_detail']['channel_manager']['name']}");
$removeCreditCardToken = $channelService->removeCreditCardToken($bookingPayment['data']);
if (!$removeCreditCardToken['status']) {
//Hata maili atılsın
$this->error(date('Y-m-d H:i:s') . ' : Channel: ' . $bookingPayment['booking_detail']['channel_manager']['name'] . ' Token: ' . $bookingPayment['data']);
} else {
$this->bookingPaymentService->updatePaymentData($bookingPayment['id'], ['status' => 1]);
$this->info(date('Y-m-d H:i:s') . ' : Channel: ' . $bookingPayment['booking_detail']['channel_manager']['name'] . ' Token: ' . $bookingPayment['data']);
}
break;
default;
break;
}
}
$this->info(date('Y-m-d H:i:s') . ' : Finished');
} catch (ApiErrorException $e) {
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $e->getMessage());
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $message);
}
}
}

View File

@@ -0,0 +1,957 @@
<?php
namespace App\Console\Commands\ChannelManager;
use App\Core\Mail\CancelBookingMail;
use App\Core\Mail\LogMail;
use App\Core\Mail\ModifiedBookingMail;
use App\Core\Service\BookingContactService;
use App\Core\Service\BookingPaymentService;
use App\Core\Service\BookingRoomService;
use App\Core\Service\BookingService;
use App\Core\Service\ChannelManager\Reseliva;
use App\Core\Service\ChannelManagerBookingService;
use App\Core\Service\ChannelManagerMappingService;
use App\Core\Service\ChannelManagerPropertyMappingService;
use App\Core\Service\ChannelManagerPropertyRateMappingService;
use App\Core\Service\ChannelManagerService;
use App\Core\Service\NewBookingMailService;
use App\Core\Service\PropertyRoomAvailabilityService;
use App\Exceptions\ApiErrorException;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class ReservationPullService extends Command
{
protected $signature = 'cron:reservation-pull-service';
protected $description = '';
protected $mailer;
protected $channelService;
protected $channelManagerPropertyMappingService;
protected $bookingService;
protected $propertyRoomAvailabilityService;
protected $newBookingMailService;
public function __construct(
Mailer $mailer,
ChannelManagerMappingService $channelManagerMappingService,
ChannelManagerPropertyMappingService $channelManagerPropertyMappingService,
BookingService $bookingService,
BookingContactService $bookingContactService,
BookingRoomService $bookingRoomService,
BookingPaymentService $bookingPaymentService,
PropertyRoomAvailabilityService $propertyRoomAvailabilityService,
NewBookingMailService $newBookingMailService,
ChannelManagerService $channelManagerService,
ChannelManagerBookingService $channelManagerBookingService
)
{
parent::__construct();
$this->mailer = $mailer;
$this->channelManagerMappingService = $channelManagerMappingService;
$this->channelManagerPropertyMappingService = $channelManagerPropertyMappingService;
$this->bookingService = $bookingService;
$this->bookingContactService = $bookingContactService;
$this->bookingRoomService = $bookingRoomService;
$this->bookingPaymentService = $bookingPaymentService;
$this->propertyRoomAvailabilityService = $propertyRoomAvailabilityService;
$this->newBookingMailService = $newBookingMailService;
$this->channelManagerService = $channelManagerService;
$this->channelManagerBookingService = $channelManagerBookingService;
}
public function getDateByDay($dates = [])
{
$dateByDay = [];
$diffInDays = Carbon::parse($dates['checkIn'])->floatDiffInDays(Carbon::parse($dates['checkOut']));
for ($i = 0; $i < $diffInDays; $i++) {
$dateByDay[] = Carbon::parse($dates['checkIn'])->addDay($i)->format('Y-m-d');
}
return $dateByDay;
}
public function createBooking($channelCode, $param)
{
$response = ['status' => false, 'message' => ''];
DB::beginTransaction();
try {
$channelService = App::make("App\Core\Service\ChannelManager\\{$channelCode}");
$bookingCode = getCodeGenerate('BKG');
$param['booking']['booking_code'] = $bookingCode;
$param['booking']['extra_param'] = json_encode($param['channel_manager']);
$bookingCreate = $this->bookingService->create($param['booking']);
//$bookingCreate['status'] = 'success';//TODO: Delete
//$bookingCreate['data']['id'] = 1106;
if ($bookingCreate['status'] != 'success') {
throw new ApiErrorException('Booking could not be made, Reservation: ' . $param['booking']['search_key']);
}
$param['booking']['id'] = $bookingCreate['data']['id'];
//INSERT CONTACT DATA
$bookingContactCreateParam = [
'booking_id' => $bookingCreate['data']['id'],
'name' => $param['contact']['name'],
'surname' => $param['contact']['surname'],
'phone_code' => $param['contact']['phone_code'],
'phone_number' => $param['contact']['phone_number'],
'email' => $param['contact']['email'],
'country_code' => fillOnUndefined($param['contact'], 'country_code'),
'note' => !empty($param['contact']['note']) ? $param['contact']['note'] : null,
'language_code' => fillOnUndefined($param['contact'], 'language', 'en'),
'extra_param' => fillOnUndefined($param['contact'], 'extra_param'),
'status' => 1
];
$bookingContactCreate = $this->bookingContactService->create($bookingContactCreateParam);
//$bookingContactCreate['status'] = 'success';
if ($bookingContactCreate['status'] != 'success') {
throw new ApiErrorException('Booking Contact could not be made');
}
//INSERT ROOM DATA
foreach ($param['room'] as $roomOrder => $room) {
$bookingRoomCreateParam = [
'booking_id' => $bookingCreate['data']['id'],
'room_order_number' => ($roomOrder + 1),
'occupancy_code' => $room['occupancy_code'],
'checkin_date' => $room['checkin_date'], //$room['checkin'],
'checkout_date' => $room['checkout_date'],//$room['checkout'],
'rate_key' => fillOnUndefined($room, 'rate_key'),
'rate_key_code' => fillOnUndefined($room, 'rate_key_code'),
'availability_id' => 1,
'availability_code' => 'ROM',
'room_id' => $room['room_id'],
'room_name' => $room['room_name'],
'room_rate_mapping_id' => $room['room_rate_mapping_id'],
'room_rate_name' => $room['room_rate_name'],
'cancellation_policy' => fillOnUndefined($room, 'cancellation_policy'),
'payment_type_code' => fillOnUndefined($room, 'payment_type_code', 'CHN'),
'daily_amount' => fillOnUndefined($room, 'daily_amount'),
'extra_param' => fillOnUndefined($room, 'extra_param'),
'rate_detail' => fillOnUndefined($room, 'rate_detail'),
'total' => $room['total'],
'currency_code' => $room['currency_code'],
'status' => fillOnUndefined($room, 'status', 1),
];
$bookingRoomCreate = $this->bookingRoomService->create($bookingRoomCreateParam);
//$bookingRoomCreate['status'] = 'success';
if ($bookingRoomCreate['status'] != 'success') {
throw new ApiErrorException('Booking Room could not be made');
}
/* ROOM AVAILABILITY */
$dateByDay = [];
$dateByDay = $this->getDateByDay(['checkIn' => $room['checkin_date'], 'checkOut' => $room['checkout_date']]);
foreach ($dateByDay as $day) {
$requestParam = [
'criteria' => [
['field' => 'property_id', 'condition' => '=', 'value' => $param['booking']['property_id']],
['field' => 'property_room_id', 'condition' => '=', 'value' => $room['room_id']],
['field' => 'availability_type_id', 'condition' => '=', 'value' => 1],
['field' => 'date', 'condition' => '=', 'value' => $day]
],
];
$getPropertyRoomAndRoomRateAvailability = $this->propertyRoomAvailabilityService->select($requestParam);
if ($getPropertyRoomAndRoomRateAvailability['status'] != 'success') {
throw new ApiErrorException('getPropertyRoomAndRoomRateAvailability Empty');
}
foreach ($getPropertyRoomAndRoomRateAvailability['data'] as $roomAvailability) {
$roomAvailabilityUpdated = $roomAvailability['availability'] <= 0 ? 0 : ($roomAvailability['availability'] - 1);
$this->propertyRoomAvailabilityService->update($roomAvailability['id'], ['availability' => $roomAvailabilityUpdated]);
}
}
/* ROOM AVAILABILITY */
}
//INSERT PAYMENT DATA
$bookingPaymentCreateParam = [
'booking_id' => $bookingCreate['data']['id'],
'payment_code' => fillOnUndefined($param['payment'], 'payment_code'),
'payment_type_code' => fillOnUndefined($param['payment'], 'payment_type_code'),//Type: CHN
'payment_source_code' => fillOnUndefined($param['payment'], 'payment_source_code'),
'extra_param' => fillOnUndefined($param['payment'], 'extra_param'),
'total' => fillOnUndefined($param['payment'], 'total'),
'currency_code' => fillOnUndefined($param['payment'], 'currency_code'),
'status' => fillOnUndefined($param['payment'], 'status'),//Type: 2
];
$bookingPaymentCreate = $this->bookingPaymentService->create($bookingPaymentCreateParam);
//$bookingPaymentCreate['status'] = 'success';
if ($bookingPaymentCreate['status'] != 'success') {
throw new ApiErrorException('Booking Payment could not be made');
}
//INSERT PAYMENT DATA
//INSERT CHANNEL PAYMENT DATA
if (isset($param['payment_channel']) && !empty($param['payment_channel'])) {
$bookingPaymentDataCreateParam = [
'booking_id' => $bookingCreate['data']['id'],
'type' => fillOnUndefined($param['payment_channel'], 'type'),
'data' => fillOnUndefined($param['payment_channel'], 'data'),
'status' => fillOnUndefined($param['payment_channel'], 'status', 1),
];
$bookingPaymentDataCreate = $this->bookingPaymentService->createPaymentData($bookingPaymentDataCreateParam);
if ($bookingPaymentDataCreate['status'] != 'success') {
throw new ApiErrorException('Booking Channel Payment could not be made');
}
}
//INSERT CHANNEL PAYMENT DATA
$reservationConfirmParam = $channelService->reservationConfirmParam($param['channel_manager']['property_id'], $param['channel_manager']['booking_id'], $bookingCode, $param);
$reservationConfirm = $channelService->reservationConfirm($reservationConfirmParam);
if (!$reservationConfirm['status']) {
throw new ApiErrorException($reservationConfirm['message']);
}
//PUSH CHANNEL MANAGER QUEUE
/*
538 Euphoria Hotel Batumi
541 Intourist Palace Hotel & SPA
545 Metro Sky Tower Hotel
546 Legend Hotel Batumi Convention Center & Spa
548 Legend Business Hotel Batumi
549 Euphoria Apartments
550 City Hotel Batumi
*/
/*if (in_array($bookingCreate['data']['property_id'], [546])) {
$channelManagerBookingParam = [
'property_id' => $bookingCreate['data']['property_id'],
'booking_id' => $bookingCreate['data']['id'],
'channel_manager_id' => $bookingCreate['data']['channel_manager_id'],
'type' => 'Booking',
];
$this->channelManagerBookingService->create($channelManagerBookingParam);
}*/
$channelManagerPropertyMappingCriteria = [
'criteria' =>
[
['field' => 'property_id', 'condition' => '=', 'value' => $bookingCreate['data']['property_id']],
['field' => 'channel_manager_property_id', 'condition' => '=', 'value' => null],
['field' => 'status', 'condition' => '=', 'value' => 1],
]
];
$channelManagerPropertyMapping = $this->channelManagerPropertyMappingService->select($channelManagerPropertyMappingCriteria);
if ($channelManagerPropertyMapping['status'] == 'success' && !empty($channelManagerPropertyMapping['data'])) {
foreach ($channelManagerPropertyMapping['data'] as $channelPropertyData) {
if(in_array($channelPropertyData['channel_manager_id'],[11,13])) {
continue;
}
$channelManagerBookingCreateParam = [
'property_id' => $bookingCreate['data']['property_id'],
'booking_id' => $bookingCreate['data']['id'],
'channel_manager_id' => $channelPropertyData['channel_manager_id'],
'type' => 'Booking',
];
$channelManagerBookingCreate = $this->channelManagerBookingService->create($channelManagerBookingCreateParam);
}
}
//PUSH CHANNEL MANAGER QUEUE
DB::commit();
$mailParams = ['booking_id' => $bookingCreate['data']['id']];
$this->newBookingMailService->process($mailParams);
$response['status'] = true;
$response['data'] = $param;
} catch (ApiErrorException $e) {
$response['message'] = implode(', ', $e->getMessageArr());
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$response['message'] = $e->getMessage();
}
if (!$response['status']) {
DB::rollBack();
}
return $response;
}
public function modifiedBooking($channelCode, $param)
{
$response = ['status' => false, 'message' => ''];
DB::beginTransaction();
try {
$channelService = App::make("App\Core\Service\ChannelManager\\{$channelCode}");
$bookingCode = null;
$bookingDetailParam = [
'criteria' => [
['field' => 'property_id', 'condition' => '=', 'value' => $param['booking']['property_id']],
['field' => 'search_key', 'condition' => '=', 'value' => $param['booking']['search_key']],
//['field' => 'channel_manager_id', 'condition' => '=', 'value' => $param['booking']['channel_manager_id']],
],
'with' => ['bookingRoom', 'bookingContact', 'bookingChannel', 'bookingPayment'],
'firstRow' => true
];
$bookingDetail = $this->bookingService->select($bookingDetailParam);
if ($bookingDetail['status'] != 'success') {
throw new ApiErrorException(lang('Booking could not be found, Reservation: ' . $param['booking']['search_key']));
}
if (!empty($bookingDetail['data'])) {
$bookingCode = $bookingDetail['data']['booking_code'];
$param['booking']['id'] = $bookingDetail['data']['id'];
$param['booking']['booking_code'] = $bookingDetail['data']['booking_code'];
$bookingUpdateParam = [
'channel_booking_code' => fillOnUndefined($param['booking'], 'channel_booking_code'),
'search_key' => $param['booking']['search_key'],
'checkin_date' => $param['booking']['checkin_date'],
'checkout_date' => $param['booking']['checkout_date'],
'payment_type_code' => $param['booking']['payment_type_code'],
'total' => $param['booking']['total'],
'currency_code' => $param['booking']['currency_code'],
];
$bookingUpdate = $this->bookingService->update($bookingDetail['data']['id'], $bookingUpdateParam);
$bookingContactUpdateParam = [
'name' => $param['contact']['name'],
'surname' => $param['contact']['surname'],
'phone_code' => $param['contact']['phone_code'],
'phone_number' => $param['contact']['phone_number'],
'email' => $param['contact']['email'],
'country_code' => !empty($param['contact']['country_code']) ? $param['contact']['country_code'] : null,
'note' => !empty($param['contact']['note']) ? $param['contact']['note'] : null,
'language_code' => fillOnUndefined($param['contact'], 'language_code', 'en')
];
$bookingContactUpdate = $this->bookingContactService->update($bookingDetail['data']['booking_contact']['id'], $bookingContactUpdateParam);
foreach ($bookingDetail['data']['booking_room'] as $roomOrder => $room) {
foreach ($param['room'] as $roomOrderChannel => $roomChannel) {
if ($roomOrder == $roomOrderChannel) {
$bookingRoomUpdateParam = [
'occupancy_code' => $roomChannel['occupancy_code'],
'checkin_date' => $roomChannel['checkin_date'],
'checkout_date' => $roomChannel['checkout_date'],
'room_id' => $roomChannel['room_id'],
'room_name' => $roomChannel['room_name'],
'room_rate_mapping_id' => $roomChannel['room_rate_mapping_id'],
'room_rate_name' => $roomChannel['room_rate_name'],
'rate_detail' => json_encode($roomChannel),
'total' => $roomChannel['total'],
'currency_code' => $roomChannel['currency_code'],
'daily_amount' => fillOnUndefined($roomChannel, 'daily_amount'),
];
$bookingRoomUpdate = $this->bookingRoomService->update($room['id'], $bookingRoomUpdateParam);
/* ROOM AVAILABILITY */
//Eğer odaya ait tarihler farklı ise buraya gelecek.
if (($room['checkin_date'] != $roomChannel['checkin_date']) || ($room['checkout_date'] != $roomChannel['checkout_date'])) {
$dateByDay = [];
$dateByDay['update'] = [];
$dateByDay['current'] = $this->getDateByDay(['checkIn' => $room['checkin_date'], 'checkOut' => $room['checkout_date']]);
$dateByDay['modified'] = $this->getDateByDay(['checkIn' => $roomChannel['checkin_date'], 'checkOut' => $roomChannel['checkout_date']]);
foreach ($dateByDay['current'] as $date) {
$dateByDay['update'][$date] = !isset($dateByDay['update'][$date]) ? 0 : $dateByDay['update'][$date];
$dateByDay['update'][$date]++;
}
foreach ($dateByDay['modified'] as $date) {
$dateByDay['update'][$date] = !isset($dateByDay['update'][$date]) ? 0 : $dateByDay['update'][$date];
$dateByDay['update'][$date]--;
}
ksort($dateByDay['update']);
foreach ($dateByDay['update'] as $day => $availabilityModified) {
$requestParam = [
'criteria' => [
['field' => 'property_id', 'condition' => '=', 'value' => $param['booking']['property_id']],
['field' => 'property_room_id', 'condition' => '=', 'value' => $room['room_id']],
['field' => 'availability_type_id', 'condition' => '=', 'value' => 1],
['field' => 'date', 'condition' => '=', 'value' => $day]
],
];
$getPropertyRoomAndRoomRateAvailability = $this->propertyRoomAvailabilityService->select($requestParam);
if ($getPropertyRoomAndRoomRateAvailability['status'] != 'success') {
throw new ApiErrorException('getPropertyRoomAndRoomRateAvailability Empty');
}
foreach ($getPropertyRoomAndRoomRateAvailability['data'] as $roomAvailability) {
$roomAvailabilityUpdated = 0;
$roomAvailabilityUpdated = $roomAvailability['availability'] + $availabilityModified;
if($roomAvailabilityUpdated < 0) {
$roomAvailabilityUpdated = 0;
}
$this->propertyRoomAvailabilityService->update($roomAvailability['id'], ['availability' => $roomAvailabilityUpdated]);
}
}
}
/* ROOM AVAILABILITY */
}
}
}
//Added New Room Case
if (count($bookingDetail['data']['booking_room']) != count($param['room']) && count($param['room']) > count($bookingDetail['data']['booking_room']) ) {
foreach ($param['room'] as $roomOrderChannel => $roomChannel) {
foreach ($bookingDetail['data']['booking_room'] as $roomOrder => $room) {
if ($roomOrder != $roomOrderChannel) {
$bookingRoomCreateParam = [
'booking_id' => $bookingDetail['data']['id'],
'room_order_number' => ($roomOrderChannel + 1),
'occupancy_code' => $roomChannel['occupancy_code'],
'checkin_date' => $roomChannel['checkin_date'], //$room['checkin'],
'checkout_date' => $roomChannel['checkout_date'],//$room['checkout'],
'rate_key' => fillOnUndefined($roomChannel, 'rate_key'),
'rate_key_code' => fillOnUndefined($roomChannel, 'rate_key_code'),
'availability_id' => 1,
'availability_code' => 'ROM',
'room_id' => $roomChannel['room_id'],
'room_name' => $roomChannel['room_name'],
'room_rate_mapping_id' => $roomChannel['room_rate_mapping_id'],
'room_rate_name' => $roomChannel['room_rate_name'],
'cancellation_policy' => fillOnUndefined($roomChannel, 'cancellation_policy'),
'payment_type_code' => fillOnUndefined($roomChannel, 'payment_type_code', 'CHN'),
'daily_amount' => fillOnUndefined($roomChannel, 'daily_amount'),
'extra_param' => fillOnUndefined($roomChannel, 'extra_param'),
'rate_detail' => fillOnUndefined($roomChannel, 'rate_detail'),
'total' => $roomChannel['total'],
'currency_code' => $roomChannel['currency_code'],
'status' => fillOnUndefined($roomChannel, 'status', 1),
];
$bookingRoomCreate = $this->bookingRoomService->create($bookingRoomCreateParam);
}
}
}
}
//UPDATE PAYMENT DATA
$bookingPaymentUpdateParam = [
'payment_type_code' => fillOnUndefined($param['payment'], 'payment_type_code'),
'payment_source_code' => fillOnUndefined($param['payment'], 'payment_source_code'),
'extra_param' => fillOnUndefined($param['payment'], 'extra_param'),
'total' => fillOnUndefined($param['payment'], 'total'),
'currency_code' => fillOnUndefined($param['payment'], 'currency_code')
];
$bookingPaymentUpdate = $this->bookingPaymentService->update($bookingDetail['data']['booking_payment']['id'], $bookingPaymentUpdateParam);
//UPDATE PAYMENT DATA
//INSERT CHANNEL PAYMENT DATA
if (isset($param['payment_channel']) && !empty($param['payment_channel'])) {
$bookingPaymentDataCreateParam = [
'booking_id' => $bookingDetail['data']['id'],
'type' => fillOnUndefined($param['payment_channel'], 'type'),
'data' => fillOnUndefined($param['payment_channel'], 'data'),
'status' => fillOnUndefined($param['payment_channel'], 'status', 1),
];
$bookingPaymentDataCreate = $this->bookingPaymentService->createPaymentData($bookingPaymentDataCreateParam);
if ($bookingPaymentDataCreate['status'] != 'success') {
throw new ApiErrorException('Booking Channel Payment could not be made');
}
}
//INSERT CHANNEL PAYMENT DATA
} else {
return $this->createBooking($channelCode, $param);
}
$bookingCode = is_null($bookingCode) ? 'ENW' . $param['booking']['search_key'] : $bookingCode;
$reservationConfirmParam = $channelService->reservationConfirmParam($param['channel_manager']['property_id'], $param['channel_manager']['booking_id'], $bookingCode, $param);
$reservationConfirm = $channelService->reservationConfirm($reservationConfirmParam);
if (!$reservationConfirm['status']) {
throw new ApiErrorException($reservationConfirm['message']);
}
$notificationModifiedToPropertyUser = [
'booking_id' => $param['booking']['id'],
];
$this->mailer->onQueue('modifiedBookingMail', new ModifiedBookingMail($notificationModifiedToPropertyUser));
$response['status'] = true;
$response['data'] = $param;
} catch (ApiErrorException $e) {
$response['message'] = implode(', ', $e->getMessageArr());
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$response['message'] = $e->getMessage();
}
if ($response['status']) {
//PUSH CHANNEL MANAGER QUEUE
$channelManagerPropertyMappingCriteria = [
'criteria' =>
[
['field' => 'property_id', 'condition' => '=', 'value' => $bookingDetail['data']['property_id']],
['field' => 'channel_manager_property_id', 'condition' => '=', 'value' => null],
['field' => 'status', 'condition' => '=', 'value' => 1],
]
];
$channelManagerPropertyMapping = $this->channelManagerPropertyMappingService->select($channelManagerPropertyMappingCriteria);
if ($channelManagerPropertyMapping['status'] == 'success' && !empty($channelManagerPropertyMapping['data'])) {
foreach ($channelManagerPropertyMapping['data'] as $channelPropertyData) {
if(in_array($channelPropertyData['channel_manager_id'],[11,13])) {
continue;
}
$channelManagerBookingCreateParam = [
'property_id' => $bookingDetail['data']['property_id'],
'booking_id' => $bookingDetail['data']['id'],
'channel_manager_id' => $channelPropertyData['channel_manager_id'],
'type' => 'Modify',
];
$channelManagerBookingCreate = $this->channelManagerBookingService->create($channelManagerBookingCreateParam);
}
}
//PUSH CHANNEL MANAGER QUEUE
DB::commit();
} else {
DB::rollBack();
}
return $response;
}
public function cancelBooking($channelCode, $param)
{
$response = ['status' => false, 'message' => ''];
DB::beginTransaction();
try {
$channelService = App::make("App\Core\Service\ChannelManager\\{$channelCode}");
$bookingCode = null;
$bookingDetailParam = [
'criteria' => [
['field' => 'property_id', 'condition' => '=', 'value' => $param['booking']['property_id']],
['field' => 'search_key', 'condition' => '=', 'value' => $param['booking']['search_key']],
//['field' => 'channel_manager_id', 'condition' => '=', 'value' => $param['booking']['channel_manager_id']],
],
'with' => ['bookingRoom', 'bookingContact', 'bookingChannel'],
'firstRow' => true
];
$bookingDetail = $this->bookingService->select($bookingDetailParam);
if ($bookingDetail['status'] != 'success') {
throw new ApiErrorException(lang('Booking could not be found, Reservation: ' . $param['booking']['search_key']));
}
if (!empty($bookingDetail['data'])) {
$bookingCode = $bookingDetail['data']['booking_code'];
$param['booking']['id'] = $bookingDetail['data']['id'];
$param['booking']['booking_code'] = $bookingDetail['data']['booking_code'];
$this->bookingService->update($bookingDetail['data']['id'], ['status' => 0]);
foreach ($bookingDetail['data']['booking_room'] as $roomOrder => $room) {
$bookingRoomUpdate = $this->bookingRoomService->update($room['id'], ['status' => 0]);
/* ROOM AVAILABILITY */
$dateByDay = [];
$dateByDay = $this->getDateByDay(['checkIn' => $room['checkin_date'], 'checkOut' => $room['checkout_date']]);
foreach ($dateByDay as $day) {
$requestParam = [
'criteria' => [
['field' => 'property_id', 'condition' => '=', 'value' => $param['booking']['property_id']],
['field' => 'property_room_id', 'condition' => '=', 'value' => $room['room_id']],
['field' => 'availability_type_id', 'condition' => '=', 'value' => 1],
['field' => 'date', 'condition' => '=', 'value' => $day]
],
];
$getPropertyRoomAndRoomRateAvailability = $this->propertyRoomAvailabilityService->select($requestParam);
if ($getPropertyRoomAndRoomRateAvailability['status'] != 'success') {
throw new ApiErrorException('getPropertyRoomAndRoomRateAvailability Empty');
}
foreach ($getPropertyRoomAndRoomRateAvailability['data'] as $roomAvailability) {
$roomAvailabilityUpdated = $roomAvailability['availability'] <= 0 ? 1 : ($roomAvailability['availability'] + 1);
$this->propertyRoomAvailabilityService->update($roomAvailability['id'], ['availability' => $roomAvailabilityUpdated]);
}
}
/* ROOM AVAILABILITY */
}
}
$bookingCode = is_null($bookingCode) ? 'ENW' . $param['booking']['search_key'] : $bookingCode;
$reservationConfirmParam = $channelService->reservationConfirmParam($param['channel_manager']['property_id'], $param['channel_manager']['booking_id'], $bookingCode, $param);
$reservationConfirm = $channelService->reservationConfirm($reservationConfirmParam);
if (!$reservationConfirm['status']) {
throw new ApiErrorException($reservationConfirm['message']);
}
$notificationCancelToPropertyUser = [
'booking_id' => $param['booking']['id'],
];
$this->mailer->onQueue('cancelBookingMail', new CancelBookingMail($notificationCancelToPropertyUser));
$response['status'] = true;
$response['data'] = $param;
} catch (ApiErrorException $e) {
$response['message'] = implode(', ', $e->getMessageArr());
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$response['message'] = $e->getMessage();
}
if ($response['status']) {
//PUSH CHANNEL MANAGER QUEUE
$channelManagerPropertyMappingCriteria = [
'criteria' =>
[
['field' => 'property_id', 'condition' => '=', 'value' => $bookingDetail['data']['property_id']],
['field' => 'channel_manager_property_id', 'condition' => '=', 'value' => null],
['field' => 'status', 'condition' => '=', 'value' => 1],
]
];
$channelManagerPropertyMapping = $this->channelManagerPropertyMappingService->select($channelManagerPropertyMappingCriteria);
if ($channelManagerPropertyMapping['status'] == 'success' && !empty($channelManagerPropertyMapping['data'])) {
foreach ($channelManagerPropertyMapping['data'] as $channelPropertyData) {
if(in_array($channelPropertyData['channel_manager_id'],[11,13])) {
continue;
}
$channelManagerBookingCreateParam = [
'property_id' => $bookingDetail['data']['property_id'],
'booking_id' => $bookingDetail['data']['id'],
'channel_manager_id' => $channelPropertyData['channel_manager_id'],
'type' => 'Cancel',
];
$channelManagerBookingCreate = $this->channelManagerBookingService->create($channelManagerBookingCreateParam);
}
}
//PUSH CHANNEL MANAGER QUEUE
DB::commit();
} else {
DB::rollBack();
}
return $response;
}
public function handle()
{
try {
$this->info(date('Y-m-d H:i:s') . ' : Start');
$channelManagerCriteria =
[
'criteria' =>
[
['field' => 'status', 'condition' => '=', 'value' => 1],
],
'orderBy' => [
['field' => 'id', 'value' => 'ASC']
]
];
$channelManager = $this->channelManagerService->select($channelManagerCriteria);
$channelManagerList = [];
if ($channelManager['status'] == 'success' && !empty($channelManager['data'])) {
$channelManagerList = $channelManager['data'];
}
//CHANNEL MANAGER
foreach ($channelManagerList as $channelKey => $channel) {
$this->info(date('Y-m-d H:i:s') . ' : Channel Start: ' . $channel['name']);
if (!class_exists("App\Core\Service\ChannelManager\\{$channel['name']}")) {
$this->error(date('Y-m-d H:i:s') . ' : Channel: ' . $channel['name'] . ' Class does not exist!');
continue;
}
$channelService = App::make("App\Core\Service\ChannelManager\\{$channel['name']}");
$channelManagerPropertyMappingCriteria = [
'criteria' =>
[
['field' => 'status', 'condition' => '=', 'value' => 1],
['field' => 'channel_manager_id', 'condition' => '=', 'value' => $channel['id']],
['field' => 'channel_manager_property_id', 'condition' => '!=', 'value' => null],
],
'with' => ['channelManagerRoomRate.propertyRoomRateMapping', 'property'],
'orderBy' => [
['field' => 'property_id', 'value' => 'ASC']
]
];
//TODO: Channex limited hotels
if ($channel['id'] == 2) {
$channexPullReservationPropertyIds = [71,313, /*538, 541, 545, 546, 548, 549, 550,*/ 672, 712, 785, 808, 790, 755, 901, 952, 912, 848, 1098, 1103, 1035];
$channelManagerPropertyMappingCriteria['whereIn'][] = ["field" => "property_id", "value" => $channexPullReservationPropertyIds];
}
$channelManagerPropertyMapping = $this->channelManagerPropertyMappingService->select($channelManagerPropertyMappingCriteria);
//Eğer kanala ait bir otel yok ise devam et
if ($channelManagerPropertyMapping['status'] != 'success' || empty($channelManagerPropertyMapping['data'])) {
continue;
}
if ($channelManagerPropertyMapping['status'] == 'success') {
//CHANNEL MANAGER PROPERTY
foreach ($channelManagerPropertyMapping['data'] as $propertyMapping) {
//Property
if (!in_array($propertyMapping['property']['id'],[623])) {
//continue;
}
$this->info(date('Y-m-d H:i:s') . ' : Property: ' . $propertyMapping['property']['id'] . ' - ' . $propertyMapping['property']['name']);
$reservationListParam = $channelService->reservationListParam($propertyMapping['channel_manager_property_id']);
$reservationList = $channelService->reservationList($reservationListParam);
//Eğer kanaldaki otele ait bir rezervasyon yok ise devam et
if (!$reservationList['status']) {
continue;
}
//CHANNEL MANAGER PROPERTY Reservation
foreach ($reservationList['data'] as $reservationKey => $reservation) {
$reservationPullFormatted = $channelService->reservationPullFormattedData($propertyMapping['property_id'], $propertyMapping['channel_manager_property_id'], $reservation);
if (!$reservationPullFormatted['status']) {
//Burada bi hata var demektir, mail atılsın ama sonraki işleme devam edilsin.
//$logMessage
$mailParams = [
'title' => $channel['name'] . ' - ReservationPullService Error - reservationPullFormatted',
'logMessage' => '<pre>' . print_r($reservationPullFormatted, true) . '</pre>'
];
$this->mailer->onQueue('logMail', new LogMail($mailParams));
//$logMessage
$this->error(date('Y-m-d H:i:s') . ' : Property: ' . $propertyMapping['property']['id'] . ' - ' . $propertyMapping['property']['name'].' Error: reservationPullFormattedData');
continue;
}
//TODO: Eğer burada gelen kanal extranetwork ise alınmış gibi yapılıp diğer işleme geçilmeli
if (in_array($reservationPullFormatted['data']['channel_manager']['sub_channel'], ['ExtranetWork'])) {
$reservationConfirmParam = $channelService->reservationConfirmParam($reservationPullFormatted['data']['channel_manager']['property_id'], $reservationPullFormatted['data']['channel_manager']['booking_id'], 'ENW' . $reservationPullFormatted['data']['channel_manager']['booking_id'], $reservationPullFormatted['data']);
$reservationConfirm = $channelService->reservationConfirm($reservationConfirmParam);
if (!$reservationConfirm['status']) {
throw new ApiErrorException($reservationConfirm['message']);
}
continue;
}
$reservationPull = ['status' => false, 'message' => ''];
if ($reservationPullFormatted['type'] == 'createBooking') {
$reservationPull = $this->createBooking($channel['name'], $reservationPullFormatted['data']);
} elseif ($reservationPullFormatted['type'] == 'modifiedBooking') {
//If the modified reservation is not found, first create a reservation.
$bookingDetailParam = [
'criteria' => [
['field' => 'property_id', 'condition' => '=', 'value' => $reservationPullFormatted['data']['booking']['property_id']],
['field' => 'search_key', 'condition' => '=', 'value' => $reservationPullFormatted['data']['booking']['search_key']],
],
'firstRow' => true
];
$bookingDetail = $this->bookingService->select($bookingDetailParam);
if (empty($bookingDetail['data'])) {
$reservationPull = $this->createBooking($channel['name'], $reservationPullFormatted['data']);
} else {
$reservationPull = $this->modifiedBooking($channel['name'], $reservationPullFormatted['data']);
}
} elseif ($reservationPullFormatted['type'] == 'cancelBooking') {
$reservationPull = $this->cancelBooking($channel['name'], $reservationPullFormatted['data']);
}
if ($reservationPull['status']) {
$this->info(date('Y-m-d H:i:s') . ' : Success ' . $reservationPullFormatted['type'] . ': ' . $reservationPull['data']['booking']['booking_code']);
} else {
//$logMessage
$mailParams = [
'title' => $channel['name'] . ' - ReservationPullService Error - Booking',
'logMessage' => '<pre>' . print_r(array_merge($reservationPullFormatted, $reservationPull), true) . '</pre>'
];
$this->mailer->onQueue('logMail', new LogMail($mailParams));
//$logMessage
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $reservationPull['message']);
}
}
}
}
$this->info(PHP_EOL);
}
//dd($channelManagerList);
$this->info(date('Y-m-d H:i:s') . ' : Finished');
} catch (ApiErrorException $e) {
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $e->getMessage());
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $message);
}
}
}

View File

@@ -0,0 +1,150 @@
<?php
namespace App\Console\Commands\ChannelManager;
use App\Core\Mail\LogMail;
use App\Core\Service\ChannelManager\Reseliva;
use App\Core\Service\ChannelManagerBookingService;
use App\Exceptions\ApiErrorException;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Log;
use Exception;
class ReservationPushService extends Command
{
protected $signature = 'cron:reservation-push-service';
protected $description = '';
protected $channelService;
protected $channelManagerBookingService;
public function __construct(
Mailer $mailer,
Reseliva $channelService,
ChannelManagerBookingService $channelManagerBookingService
)
{
parent::__construct();
$this->mailer = $mailer;
$this->channelService = $channelService;
$this->channelManagerBookingService = $channelManagerBookingService;
}
public function handle()
{
$this->info(date('Y-m-d H:i:s') . ' : Start');
$pendingBookingCriteria = [
'criteria' =>
[
//['field' => 'id', 'condition' => '=', 'value' => 22461],#21390
['field' => 'is_pushed', 'condition' => '=', 'value' => null],
['field' => 'status', 'condition' => '=', 'value' => 1],
],
'with' => [
'channelManager',
'bookingDetail.bookingContact', 'bookingDetail.bookingChannel',
'bookingDetail.bookingPayment', 'bookingDetail.bookingPaymentType',
'bookingDetail.bookingStatus', 'bookingDetail.bookingRoom.roomPax.paxCountry'
],
'orderBy' => [
['field' => 'id', 'value' => 'ASC']
],
'take' => 100
];
$pendingBooking = $this->channelManagerBookingService->select($pendingBookingCriteria);
if ($pendingBooking['status'] == 'success') {
$pendingBooking = $pendingBooking['data'];
foreach ($pendingBooking as $booking) {
try {
$this->info(date('Y-m-d H:i:s') . ' : Booking ID: ' . $booking['booking_id']);
$channelService = App::make("App\Core\Service\ChannelManager\\{$booking['channel_manager']['name']}");
$this->info(date('Y-m-d H:i:s') . ' : Channel: ' . $booking['channel_manager']['name']);
if ($booking['channel_manager_id'] == 10) {
//After 3 minutes, the faulty operation is set to status 2 for Hyperguest.
if (Carbon::createFromTimestamp($booking['created_at'])->diffInMinutes(Carbon::now()) > 3) {
$this->channelManagerBookingService->update($booking['id'], ['status' => 2]);
$this->error(date('Y-m-d H:i:s') . ' : Channel: ' . $booking['channel_manager']['name']);
continue;
}
}
//After 30 minutes, the faulty operation is set to status 2.
if (Carbon::createFromTimestamp($booking['created_at'])->diffInMinutes(Carbon::now()) > 30) {
$this->channelManagerBookingService->update($booking['id'], ['status' => 2]);
}
$requestPostReservationPushParam = $channelService->requestPostReservationPushParam($booking['property_id'], $booking['booking_id'], $booking['type'], $booking);
if (empty($requestPostReservationPushParam)) {
throw new ApiErrorException('requestPostReservationPushParam Error');
}
$this->info(date('Y-m-d H:i:s') . ' : Booking ID: ' . $booking['booking_id'] . ' Push');
$this->channelManagerBookingService->update($booking['id'], ['request' => $requestPostReservationPushParam]);
$requestPostReservationPush = $channelService->requestPostReservationPush($requestPostReservationPushParam);
if ($requestPostReservationPush['status']) {
$this->info(date('Y-m-d H:i:s') . ' : Booking ID: ' . $booking['booking_id'] . ' Success');
$this->channelManagerBookingService->update($booking['id'], ['is_pushed' => 1, 'status' => 1, 'response' => $requestPostReservationPush['response']]);
} else {
//$logMessage
$mailParams = [
'title' => 'ReservationPushService Error - ChannelManagerName: ' . $booking['channel_manager']['name'],
'logMessage' => '<pre>' . print_r(array_merge($booking, $requestPostReservationPush), true) . '</pre>'
];
$this->mailer->onQueue('logMail', new LogMail($mailParams));
//$logMessage
$this->error(date('Y-m-d H:i:s') . ' : Booking ID: ' . $booking['booking_id'] . ' Failed');
$this->channelManagerBookingService->update($booking['id'], ['response' => $requestPostReservationPush['message']]);
}
} catch (ApiErrorException $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $e->getMessage());
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $message);
}
}
}
$this->info(date('Y-m-d H:i:s') . ' : Finished');
}
}

View File

@@ -0,0 +1,262 @@
<?php
namespace App\Console\Commands\ChannelManager;
use App\Core\Mail\LogMail;
use App\Core\Service\ChannelManager\Reseliva;
use App\Core\Service\ChannelManagerPropertyMappingService;
use App\Core\Service\ChannelManagerService;
use App\Core\Service\PropertyRoomAvailabilityQueueService;
use App\Exceptions\ApiErrorException;
use App\Models\PropertyRoomAvailabilityQueue;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Log;
class RoomAvailabilityPushService extends Command
{
protected $signature = 'cron:roomavailability-push-service';
protected $description = '';
protected $mailer;
protected $channelService;
protected $channelManagerService;
protected $propertyRoomAvailabilityQueueService;
public function __construct(
Mailer $mailer,
ChannelManagerService $channelManagerService,
PropertyRoomAvailabilityQueueService $propertyRoomAvailabilityQueueService,
ChannelManagerPropertyMappingService $channelManagerPropertyMappingService
)
{
parent::__construct();
$this->mailer = $mailer;
$this->channelManagerService = $channelManagerService;
$this->propertyRoomAvailabilityQueueService = $propertyRoomAvailabilityQueueService;
$this->channelManagerPropertyMappingService = $channelManagerPropertyMappingService;
}
public function handle()
{
try {
$this->info(date('Y-m-d H:i:s') . ' : Start');
//Queue Check
$this->info(date('Y-m-d H:i:s') . ' : Queue Check');
$roomAvailabilityQueueCountCriteria = ['criteria' => [['field' => 'status', 'condition' => '=', 'value' => 1]], 'count' => true];
$roomAvailabilityQueueCount = $this->propertyRoomAvailabilityQueueService->select($roomAvailabilityQueueCountCriteria);
if ($roomAvailabilityQueueCount['status'] == 'success') {
$roomAvailabilityQueueCount = $roomAvailabilityQueueCount['data'];
if ($roomAvailabilityQueueCount > 2000) {
$roomAvailabilityQueueCountGroupByProperty = PropertyRoomAvailabilityQueue::selectRaw('property_id, COUNT(*) as total')
->groupBy('property_id')
->orderByDesc('total')
->first();
$roomAvailabilityQueueCountGroupByProperty = $roomAvailabilityQueueCountGroupByProperty ? $roomAvailabilityQueueCountGroupByProperty->toArray() : null;
if ($roomAvailabilityQueueCountGroupByProperty) {
if ($roomAvailabilityQueueCountGroupByProperty['total'] > 1000) {
PropertyRoomAvailabilityQueue::where('property_id', $roomAvailabilityQueueCountGroupByProperty['property_id'])->delete();
}
}
}
if ($roomAvailabilityQueueCount > 1000) {
$this->error(date('Y-m-d H:i:s') . ' : Queue Alarm: ' . $roomAvailabilityQueueCount);
//Clear Test Property Data
PropertyRoomAvailabilityQueue::where('property_id', 1)->delete();
//$logMessage
$mailParams = [
'title' => 'RoomAvailabilityPushService Error - Queue Error',
'logMessage' => 'Queue: ' . $roomAvailabilityQueueCount
];
$this->mailer->onQueue('logMail', new LogMail($mailParams));
//$logMessage
}
}
//Queue Check
$channelManagerCriteria =
[
'criteria' =>
[
['field' => 'status', 'condition' => '=', 'value' => 1],
],
/*'whereIn' =>
[
['field' => 'id', "value" => [7]]
],*/
'orderBy' => [
['field' => 'id', 'value' => 'ASC']
]
];
$channelManager = $this->channelManagerService->select($channelManagerCriteria);
$channelManagerList = [];
if ($channelManager['status'] == 'success' && !empty($channelManager['data'])) {
$channelManagerList = $channelManager['data'];
}
$roomAvailabilityQueueCriteria =
[
'criteria' =>
[
['field' => 'status', 'condition' => '=', 'value' => 1],
],
'with' => ['property'/*, 'propertyChannelManager.channelManagerRoomRate.propertyRoomRateMapping'*/],
'orderBy' => [
['field' => 'id', 'value' => 'ASC']
],
'take' => 500
];
$roomAvailabilityQueue = $this->propertyRoomAvailabilityQueueService->select($roomAvailabilityQueueCriteria);
if ($roomAvailabilityQueue['status'] == 'success' && !empty($roomAvailabilityQueue['data'])) {
foreach ($roomAvailabilityQueue['data'] as $data) {
$roomAvailabilityQueueData[$data['property_id']][] = $data;
}
$channelManagerPushedIdsList = [];
$channelManagerNoneMappingIdsList = [];
//PROPERTY
foreach ($roomAvailabilityQueueData as $roomAvailabilityQueuePropertyId => $roomAvailabilityQueueProperty) {
//CHANNEL MANAGER
$channelManagerCheckList = [];
foreach ($channelManagerList as $channelKey => $channel) {
if (in_array($channel['id'], [7, 10, 13])) {
continue;
}
$this->info(date('Y-m-d H:i:s') . ' : Channel Start: ' . $channel['name']);
if (!class_exists("App\Core\Service\ChannelManager\\{$channel['name']}")) {
$this->error(date('Y-m-d H:i:s') . ' : Channel: ' . $channel['name'] . ' Class does not exist!');
continue;
}
$channelService = App::make("App\Core\Service\ChannelManager\\{$channel['name']}");
$channelManagerPropertyMappingCriteria = [
'criteria' =>
[
['field' => 'status', 'condition' => '=', 'value' => 1],
['field' => 'property_id', 'condition' => '=', 'value' => $roomAvailabilityQueuePropertyId],
['field' => 'channel_manager_id', 'condition' => '=', 'value' => $channel['id']],
['field' => 'channel_manager_property_id', 'condition' => '!=', 'value' => null],
],
'firstRow' => true,
];
$channelManagerPropertyMapping = $this->channelManagerPropertyMappingService->select($channelManagerPropertyMappingCriteria);
if ($channelManagerPropertyMapping['status'] != 'success' || ($channelManagerPropertyMapping['status'] == 'success' && empty($channelManagerPropertyMapping['data']))) {
$this->info(date('Y-m-d H:i:s') . ' : Channel: ' . $channel['name'] . ' PropertyID: ' . $roomAvailabilityQueuePropertyId . ' : PASS');
continue;
}
$channelManagerCheckList[$channel['id']] = true;
$roomAvailabilityPush = $channelService->roomAvailabilityPush($roomAvailabilityQueuePropertyId, $roomAvailabilityQueueProperty);
if ($roomAvailabilityPush['status']) {
$channelManagerPushedIdsList[$channel['id']] = $roomAvailabilityPush['data']['channelManagerPushedIds'];
$channelManagerNoneMappingIdsList[$channel['id']] = $roomAvailabilityPush['data']['channelManagerNoneMappingIds'];
$this->info(date('Y-m-d H:i:s') . ' : Success: ' . $channel['name']);
} else {
$channelManagerCheckList[$channel['id']] = false;
//$logMessage
$mailParams = [
'title' => $channel['name'] . ' - RoomAvailabilityPushService Error - inventoryRoomRateUpdate Error',
'logMessage' => '<pre>' . print_r($roomAvailabilityPush, true) . '</pre>'
];
$this->mailer->onQueue('logMail', new LogMail($mailParams));
//$logMessage
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $channel['name'] . ' - ' . $roomAvailabilityPush['message']);
}
$this->info(date('Y-m-d H:i:s') . ' : Channel Finished: ' . $channel['name']);
}
if (in_array(false, $channelManagerCheckList)) {
$this->error(date('Y-m-d H:i:s') . ' : Error Break: ' . var_export($channelManagerCheckList));
continue;
}
if (count($channelManagerPushedIdsList) > 1) {
$channelManagerPushedIdIntersect = call_user_func_array('array_intersect', $channelManagerPushedIdsList);
if (!empty($channelManagerPushedIdIntersect)) {
$this->propertyRoomAvailabilityQueueService->delete($channelManagerPushedIdIntersect);
$this->info(date('Y-m-d H:i:s') . ' : channelManagerPushedIdsList Deleted: ' . var_dump($channelManagerPushedIdIntersect));
}
} elseif (!empty($channelManagerPushedIdsList)) {
$this->propertyRoomAvailabilityQueueService->delete(reset($channelManagerPushedIdsList));
$this->info(date('Y-m-d H:i:s') . ' : channelManagerPushedIdsList Deleted: ' . var_dump($channelManagerPushedIdsList));
}
if (empty($channelManagerNoneMappingIdsList)) {
$this->info(date('Y-m-d H:i:s') . ' : channelManagerNoneMappingIdsList Empty');
continue;
}
$channelManagerNoneMappingIdsListMerge = call_user_func_array('array_merge', $channelManagerNoneMappingIdsList);
if (!empty($channelManagerNoneMappingIdsListMerge)) {
$this->propertyRoomAvailabilityQueueService->delete($channelManagerNoneMappingIdsListMerge);
$this->info(date('Y-m-d H:i:s') . ' : channelManagerNoneMappingIdsListMerge Deleted: ' . var_dump($channelManagerNoneMappingIdsListMerge));
}
}
}
$this->info(date('Y-m-d H:i:s') . ' : Finished');
} catch (ApiErrorException $e) {
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $e->getMessage());
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $message);
}
}
}

View File

@@ -0,0 +1,255 @@
<?php
namespace App\Console\Commands\ChannelManager;
use App\Core\Mail\LogMail;
use App\Core\Service\ChannelManager\Reseliva;
use App\Core\Service\ChannelManagerPropertyMappingService;
use App\Core\Service\ChannelManagerService;
use App\Core\Service\PropertyRoomAvailabilityQueueService;
use App\Core\Service\PropertyRoomRatePriceQueueService;
use App\Exceptions\ApiErrorException;
use App\Models\PropertyRoomRatePriceQueue;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Log;
class RoomRatePushService extends Command
{
protected $signature = 'cron:roomrate-push-service';
protected $description = '';
protected $mailer;
protected $channelService;
protected $propertyRoomRatePriceQueueService;
protected $channelManagerService;
protected $propertyRoomAvailabilityQueueService;
public function __construct(
Mailer $mailer,
PropertyRoomRatePriceQueueService $propertyRoomRatePriceQueueService,
ChannelManagerService $channelManagerService,
PropertyRoomAvailabilityQueueService $propertyRoomAvailabilityQueueService,
ChannelManagerPropertyMappingService $channelManagerPropertyMappingService
)
{
parent::__construct();
$this->mailer = $mailer;
$this->propertyRoomRatePriceQueueService = $propertyRoomRatePriceQueueService;
$this->channelManagerService = $channelManagerService;
$this->propertyRoomAvailabilityQueueService = $propertyRoomAvailabilityQueueService;
$this->channelManagerPropertyMappingService = $channelManagerPropertyMappingService;
}
public function handle()
{
//$request = $this->channelService->productList(14480);
try {
$this->info(date('Y-m-d H:i:s') . ' : Start');
//Queue Check
$this->info(date('Y-m-d H:i:s') . ' : Queue Check');
$roomRatePriceQueueCountCriteria = ['criteria' => [['field' => 'status', 'condition' => '=', 'value' => 1]],'count' => true];
$roomRatePriceQueueCount = $this->propertyRoomRatePriceQueueService->select($roomRatePriceQueueCountCriteria);
if($roomRatePriceQueueCount['status'] == 'success') {
$roomRatePriceQueueCount = $roomRatePriceQueueCount['data'];
if($roomRatePriceQueueCount > 1000) {
$this->error(date('Y-m-d H:i:s') . ' : Queue Alarm: '. $roomRatePriceQueueCount);
//Clear Test Property Data
PropertyRoomRatePriceQueue::where('property_id',1)->delete();
//$logMessage
$mailParams = [
'title' => 'RoomRatePushService Error - Queue Error',
'logMessage' => 'Queue: '.$roomRatePriceQueueCount
];
$this->mailer->onQueue('logMail', new LogMail($mailParams));
//$logMessage
}
}
//Queue Check
$channelManagerCriteria =
[
'criteria' =>
[
['field' => 'status', 'condition' => '=', 'value' => 1],
],
/*'whereIn' =>
[
['field' => 'id', "value" => [7]]
],*/
'orderBy' => [
['field' => 'id', 'value' => 'ASC']
]
];
$channelManager = $this->channelManagerService->select($channelManagerCriteria);
$channelManagerList = [];
if ($channelManager['status'] == 'success' && !empty($channelManager['data'])) {
$channelManagerList = $channelManager['data'];
}
$roomRatePriceQueueCriteria =
[
'criteria' =>
[
['field' => 'status', 'condition' => '=', 'value' => 1],
],
'with' => ['property'/*, 'propertyChannelManager.channelManagerRoomRate'*/],
'orderBy' => [
['field' => 'id', 'value' => 'ASC']
],
'take' => 500
];
$roomRatePriceQueue = $this->propertyRoomRatePriceQueueService->select($roomRatePriceQueueCriteria);
if ($roomRatePriceQueue['status'] == 'success' && !empty($roomRatePriceQueue['data'])) {
foreach ($roomRatePriceQueue['data'] as $data) {
$roomRatePriceQueueData[$data['property_id']][] = $data;
}
$channelManagerPushedIdsList = [];
$channelManagerNoneMappingIdsList = [];
//PROPERTY
foreach ($roomRatePriceQueueData as $roomRatePriceQueuePropertyId => $roomRatePriceQueueProperty) {
//CHANNEL MANAGER
$channelManagerCheckList = [];
foreach ($channelManagerList as $channelKey => $channel) {
if(in_array($channel['id'],[7,10, 13])) {
continue;
}
$this->info(date('Y-m-d H:i:s') . ' : Channel Start: ' . $channel['name']);
if(!class_exists("App\Core\Service\ChannelManager\\{$channel['name']}")) {
$this->error(date('Y-m-d H:i:s') . ' : Channel: ' . $channel['name'].' Class does not exist!');
continue;
}
$channelService = App::make("App\Core\Service\ChannelManager\\{$channel['name']}");
$channelManagerPropertyMappingCriteria = [
'criteria' =>
[
['field' => 'status', 'condition' => '=', 'value' => 1],
['field' => 'property_id', 'condition' => '=', 'value' => $roomRatePriceQueuePropertyId],
['field' => 'channel_manager_id', 'condition' => '=', 'value' => $channel['id']],
['field' => 'channel_manager_property_id', 'condition' => '!=', 'value' => null],
],
'firstRow' => true,
];
$channelManagerPropertyMapping = $this->channelManagerPropertyMappingService->select($channelManagerPropertyMappingCriteria);
if ($channelManagerPropertyMapping['status'] != 'success' || ($channelManagerPropertyMapping['status'] == 'success' && empty($channelManagerPropertyMapping['data']))) {
$this->info(date('Y-m-d H:i:s') . ' : Channel: ' . $channel['name'] . ' PropertyID: ' . $roomRatePriceQueuePropertyId . ' : PASS');
continue;
}
$channelManagerCheckList[$channel['id']] = true;
$roomRatePricePush = $channelService->roomRatePricePush($roomRatePriceQueuePropertyId, $roomRatePriceQueueProperty);
if ($roomRatePricePush['status']) {
if (!empty($roomRatePricePush['data']['channelManagerPushedIds']) || !empty($roomRatePricePush['data']['channelManagerNoneMappingIds'])) {
$channelManagerPushedIdsList[$channel['id']] = $roomRatePricePush['data']['channelManagerPushedIds'];
$channelManagerNoneMappingIdsList[$channel['id']] = $roomRatePricePush['data']['channelManagerNoneMappingIds'];
}
$this->info(date('Y-m-d H:i:s') . ' : Channel Success: ' . $channel['name']);
} else {
$channelManagerCheckList[$channel['id']] = false;
//$logMessage
$mailParams = [
'title' => $channel['name'] . ' - RoomRatePushService Error - InventoryRoomRateUpdate Error',
'logMessage' => '<pre>' . print_r($roomRatePricePush, true) . '</pre>'
];
$this->mailer->onQueue('logMail', new LogMail($mailParams));
//$logMessage
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $channel['name'] . ' - ' . $roomRatePricePush['message']);
}
$this->info(date('Y-m-d H:i:s') . ' : Channel Finished: ' . $channel['name']);
}
/*foreach ($channelManagerPushedIdsList as $key => $channelManagerPushedIds) {
if(empty($channelManagerPushedIds)) {
unset($channelManagerPushedIdsList[$key]);
}
}*/
if (in_array(false, $channelManagerCheckList)) {
$this->error(date('Y-m-d H:i:s') . ' : Error Break: ' . var_export($channelManagerCheckList));
continue;
}
if (count($channelManagerPushedIdsList) > 1) {
$channelManagerPushedIdIntersect = call_user_func_array('array_intersect', $channelManagerPushedIdsList);
if (!empty($channelManagerPushedIdIntersect)) {
$this->propertyRoomRatePriceQueueService->delete($channelManagerPushedIdIntersect);
$this->info(date('Y-m-d H:i:s') . ' : $channelManagerPushedIdsList Deleted: ' . var_export($channelManagerPushedIdIntersect));
}
} elseif (!empty($channelManagerPushedIdsList)) {
$this->propertyRoomRatePriceQueueService->delete(reset($channelManagerPushedIdsList));
$this->info(date('Y-m-d H:i:s') . ' : $channelManagerPushedIdsList Deleted: ' . var_export($channelManagerPushedIdsList));
}
if (!empty($channelManagerNoneMappingIdsList)) {
$channelManagerNoneMappingIdsListMerge = call_user_func_array('array_merge', $channelManagerNoneMappingIdsList);
if (!empty($channelManagerNoneMappingIdsListMerge)) {
$this->propertyRoomRatePriceQueueService->delete($channelManagerNoneMappingIdsListMerge);
$this->info(date('Y-m-d H:i:s') . ' : $channelManagerNoneMappingIdsListMerge Deleted: ' . var_dump($channelManagerNoneMappingIdsListMerge));
}
}
}
}
$this->info(date('Y-m-d H:i:s') . ' : Finished');
} catch (ApiErrorException $e) {
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $e->getMessage());
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $message);
}
}
}

View File

@@ -0,0 +1,497 @@
<?php
namespace App\Console\Commands\ChannelManager;
use App\Core\Mail\LogMail;
use App\Core\Service\ChannelManager\Reseliva;
use App\Core\Service\ChannelManagerLogService;
use App\Core\Service\ChannelManagerPropertyMappingService;
use App\Core\Service\ChannelManagerService;
use App\Core\Service\PropertyChannelMappingService;
use App\Core\Service\PropertyRoomAvailabilityQueueService;
use App\Core\Service\PropertyRoomAvailabilityService;
use App\Core\Service\PropertyRoomRateChannelMappingService;
use App\Core\Service\PropertyRoomRatePriceService;
use App\Core\Service\PropertyRoomService;
use App\Exceptions\ApiErrorException;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class ReselivaAvailRateUpdateService extends Command
{
protected $signature = 'cron:reseliva-availrateupdate-service';
protected $description = '';
protected $mailer;
public function __construct(
Mailer $mailer,
PropertyRoomService $propertyRoomService,
PropertyRoomRatePriceService $propertyRoomRatePriceService,
ChannelManagerLogService $channelManagerLogService,
ChannelManagerPropertyMappingService $channelManagerPropertyMappingService,
PropertyRoomRateChannelMappingService $propertyRoomRateChannelMappingService,
PropertyChannelMappingService $propertyChannelMappingService,
PropertyRoomAvailabilityService $propertyRoomAvailabilityService
)
{
parent::__construct();
$this->mailer = $mailer;
$this->propertyRoomService = $propertyRoomService;
$this->propertyRoomRatePriceService = $propertyRoomRatePriceService;
$this->channelManagerLogService = $channelManagerLogService;
$this->channelManagerPropertyMappingService = $channelManagerPropertyMappingService;
$this->propertyRoomRateChannelMappingService = $propertyRoomRateChannelMappingService;
$this->propertyChannelMappingService = $propertyChannelMappingService;
$this->propertyRoomAvailabilityService = $propertyRoomAvailabilityService;
}
public function propertyChannelMapping($propertyId, $channelId)
{
$response = ['status' => false, 'message' => ''];
try {
$propertyChannelMappingCriteria = [
'criteria' => [
['field' => 'channel_id', 'condition' => '=', 'value' => $channelId],
['field' => 'property_id', 'condition' => '=', 'value' => $propertyId],
['field' => 'status', 'condition' => '=', 'value' => 1],
],
'firstRow' => true
];
$propertyChannelMapping = $this->propertyChannelMappingService->select($propertyChannelMappingCriteria);
if ($propertyChannelMapping['status'] != 'success') {
throw new ApiErrorException($propertyChannelMapping['message']);
}
$response = [
'status' => true,
'data' => $propertyChannelMapping['data']
];
} catch (ApiErrorException $e) {
$response['message'] = implode(', ', $e->getMessageArr());
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$response['message'] = $e->getMessage();
}
return $response;
}
public function channelPropertyRoomRate($propertyId, $channelId)
{
$response = ['status' => false, 'message' => ''];
try {
$requestParam = [
'criteria' => [
['field' => 'channel_id', 'condition' => '=', 'value' => $channelId],
['field' => 'property_id', 'condition' => '=', 'value' => $propertyId],
['field' => 'status', 'condition' => '=', 'value' => 1],
],
'with' => [
'propertyRoomRateMapping.propertyRoomRate.propertyRoomRateAccommodation',
'propertyRoomRateMapping.propertyRoom.propertyRoomType',
]
];
$getChannelPropertyRoomRate = $this->propertyRoomRateChannelMappingService->select($requestParam);
if ($getChannelPropertyRoomRate['status'] != 'success' || empty($getChannelPropertyRoomRate['data'])) {
throw new ApiErrorException('Property Room Rate not found');
}
$response = [
'status' => true,
'data' => $getChannelPropertyRoomRate['data']
];
} catch (ApiErrorException $e) {
$response['message'] = implode(', ', $e->getMessageArr());
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$response['message'] = $e->getMessage();
}
return $response;
}
public function channelManagerPropertyCheck($propertyId, $channelId)
{
$response = ['status' => false, 'message' => ''];
try {
$requestParam =
[
'criteria' =>
[
['field' => 'status', 'condition' => '=', 'value' => 1],
['field' => 'property_id', 'condition' => '=', 'value' => $propertyId],
['field' => 'channel_manager_id', 'condition' => '=', 'value' => $channelId],
],
'firstRow' => true
];
$channelManagerPropertyMapping = $this->channelManagerPropertyMappingService->select($requestParam);
if ($channelManagerPropertyMapping['status'] != 'success' || empty($channelManagerPropertyMapping['data'])) {
throw new ApiErrorException('Property Room Rate not found');
}
$channelManagerPropertyMapping = $channelManagerPropertyMapping['data'];
if (!is_null($channelManagerPropertyMapping['channel_manager_property_id'])) {
throw new ApiErrorException('This hotel can only be updated by ENW');
}
$response = [
'status' => true
];
} catch (ApiErrorException $e) {
$response['message'] = implode(', ', $e->getMessageArr());
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$response['message'] = $e->getMessage();
}
return $response;
}
public function handle()
{
$this->info(date('Y-m-d H:i:s') . ' : Start');
$channelId = 1;
$channelManagerId = 1;
$channelManagerLogCriteria = [
'criteria' => [
['field' => 'id', 'condition' => '=', 'value' => 32670],
['field' => 'service', 'condition' => '=', 'value' => 'AvailRateUpdate'],
['field' => 'status', 'condition' => '=', 'value' => null],
],
'orderBy' => [
['field' => 'id', 'value' => 'ASC']
]
];
$channelManagerLog = $this->channelManagerLogService->select($channelManagerLogCriteria);
if ($channelManagerLog['status'] && !empty($channelManagerLog['data'])) {
foreach ($channelManagerLog['data'] as $logData) {
$response = ['status' => false, 'message' => ''];
$payloadXML = simplexml_load_string($logData['request']);
$payloadParam = json_decode(json_encode($payloadXML), 1);
try {
$propertyId = $payloadParam['Hotel']['@attributes']['id'];
$channelManagerPropertyCheck = $this->channelManagerPropertyCheck($propertyId, $channelId);
if (!$channelManagerPropertyCheck['status']) {
throw new ApiErrorException($channelManagerPropertyCheck['message']);
}
$channelPropertyRoomRate = $this->channelPropertyRoomRate($propertyId, $channelId);
if (!$channelPropertyRoomRate['status']) {
throw new ApiErrorException($channelPropertyRoomRate['message']);
}
$channelPropertyRoomRate = $channelPropertyRoomRate['data'];
$channelPropertyRoomRateCollect = collect($channelPropertyRoomRate);
$propertyChannelMapping = $this->propertyChannelMapping($propertyId, $channelId);
if (!$propertyChannelMapping['status']) {
throw new ApiErrorException($propertyChannelMapping['message']);
}
$propertyChannelMapping = $propertyChannelMapping['data'];
$availRateUpdates = singleElementXMLArray($payloadParam['AvailRateUpdate']);
DB::beginTransaction();
foreach ($availRateUpdates as $availRateUpdate) {
$dateRange = [];
$dateRange['startDate'] = $availRateUpdate['DateRange']['@attributes']['from'];
$dateRange['finishDate'] = $availRateUpdate['DateRange']['@attributes']['to'];
if (Carbon::parse($dateRange['startDate'])->isBefore(Carbon::now()->toDateString()) || Carbon::parse($dateRange['finishDate'])->isBefore(Carbon::now()->toDateString())) {
throw new ApiErrorException('Dates to be updated cannot be earlier than today');
}
$roomTypes = singleElementXMLArray($availRateUpdate['RoomType']);
$this->info(date('Y-m-d H:i:s') . ' : ' . $dateRange['startDate'] . ' - ' . $dateRange['finishDate']);
foreach ($roomTypes as $roomType) {
$roomId = $roomType['@attributes']['id'];
$roomCheck = $channelPropertyRoomRateCollect->where('property_room_rate_mapping.room_id', $roomId)->isEmpty();
if ($roomCheck) {
throw new ApiErrorException('Tanımlı ya da aktif olmayan oda');
}
$totalInventoryAvailable = null;
if (isset($roomType['Inventory']['@attributes']['totalInventoryAvailable'])) {
$totalInventoryAvailable = $roomType['Inventory']['@attributes']['totalInventoryAvailable'];
}
$requestParamBase = [
'property_id' => fillOnUndefined($propertyChannelMapping, 'property_id'),
'channel_id' => fillOnUndefined($propertyChannelMapping, 'channel_id'),
'availability_type_id' => fillOnUndefined($propertyChannelMapping, 'property_availability_type_id', 1),
'start_date' => $dateRange['startDate'],
'end_date' => $dateRange['finishDate'],
'include_days' => ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
];
if (!is_null($totalInventoryAvailable)) {
$requestParams = [];
$requestParams = $requestParamBase;
$requestParams['update_type'] = 'availability';
$requestParams['value'] = $totalInventoryAvailable;
$requestParams['room_rates'] = [
['room_id' => $roomId]
];
$propertyRoomRateMapping = $this->propertyRoomAvailabilityService->bulkUpdate($requestParams);
if ($propertyRoomRateMapping['status'] != 'success') {
throw new ApiErrorException($propertyRoomRateMapping['message']);
}
$this->info(date('Y-m-d H:i:s') . ' : Update Type: ' . $requestParams['update_type']);
}
if (isset($roomType['RatePlan'])) {
$ratePlans = singleElementXMLArray($roomType['RatePlan']);
foreach ($ratePlans as $ratePlan) {
$roomRateMappingId = $ratePlan['@attributes']['id'];
$isCloseRoomRateMappingSale = null;
if (isset($ratePlan['@attributes']['closed'])) {
$isCloseRoomRateMappingSale = $ratePlan['@attributes']['closed'] == 'true' ? true : false;
}
$channelRoomRateMappingCheck = $channelPropertyRoomRateCollect->where('room_rate_mapping_id', $roomRateMappingId)->isEmpty();
if ($channelRoomRateMappingCheck) {
throw new ApiErrorException('Tanımlı ya da aktif olmayan oda konaklama');
}
$roomRates = [
'room_id' => $roomId,
'room_rate_mapping_id' => [
$roomRateMappingId
]
];
$paramsListChannel = [];
$paramsListChannel[] = 1;
//CONNECTED CHANNEL RATE UPDATE
$propertyChannelMappingConnectedCriteria = [
'criteria' => [
['field' => 'property_id', 'condition' => '=', 'value' => $requestParamBase['property_id']],
['field' => 'connected_channel_id', 'condition' => '=', 'value' => $requestParamBase['channel_id']],
['field' => 'status', 'condition' => '=', 'value' => 1],
],
'with' => ['channel']
];
$propertyChannelMappingConnected = $this->propertyChannelMappingService->select($propertyChannelMappingConnectedCriteria);
if ($propertyChannelMappingConnected['status'] == 'success') {
foreach ($propertyChannelMappingConnected['data'] as $channel) {
if (!is_null($channel['channel']['parent_id'])) {
continue;
}
$paramsListChannel[] = $channel['channel_id'];
}
}
//CONNECTED CHANNEL RATE UPDATE
foreach ($paramsListChannel as $paramChannelId) {
//Eğer Rate var ise currency check yapılmalı ve PerDay var mı check edilmeli, burada sonra günceleme yaptırılabilri
if (isset($ratePlan['Rate'])) {
$currency = $ratePlan['Rate']['@attributes']['currency'];
$currencyCheck = ($currency == $propertyChannelMapping['currency_code']) ? true : false;
if (!$currencyCheck) {
throw new ApiErrorException('Kanal döviz kuru ile eşleşmeyen döviz kuru, kanal döviz kuru: ' . $propertyChannelMapping['currency_code']);
}
$channelRoomRateMapping = $channelPropertyRoomRateCollect->where('room_rate_mapping_id', $roomRateMappingId)->first();
$amountPerDay = $ratePlan['Rate']['PerDay']['@attributes']['rate'];
$requestParams = [];
$requestParams = $requestParamBase;
$requestParams['update_type'] = 'rate';
$requestParams['value'] = $amountPerDay;
$requestParams['room_rates'] = [$roomRates];
$requestParams['channel_id'] = $paramChannelId;
$propertyRoomRateMapping = $this->propertyRoomRatePriceService->bulkUpdate($requestParams);
if ($propertyRoomRateMapping['status'] != 'success') {
throw new ApiErrorException($propertyRoomRateMapping['message']);
}
$this->info(date('Y-m-d H:i:s') .
' : Update Type: ' .$requestParams['update_type'].
' : Channel ID: '. $requestParams['channel_id'].
' : Room ID: '. $roomRates['room_id']
);
}
//Room Rate Stop Sale
if (!is_null($isCloseRoomRateMappingSale)) {
$requestParams = [];
$requestParams = $requestParamBase;
$requestParams['update_type'] = 'rate_stop_sell';
$requestParams['value'] = $isCloseRoomRateMappingSale ? 1 : 0;
$requestParams['room_rates'] = [$roomRates];
$requestParams['channel_id'] = $paramChannelId;
$propertyRoomRateMapping = $this->propertyRoomRatePriceService->bulkUpdate($requestParams);
if ($propertyRoomRateMapping['status'] != 'success') {
throw new ApiErrorException($propertyRoomRateMapping['message']);
}
$this->info(date('Y-m-d H:i:s') . ' : Update Type: ' . $requestParams['update_type']);
}
//Kısıtlamalar var ise min los
if (isset($ratePlan['Restrictions'])) {
//Minimum Konaklama Gün Sayısı
if (isset($ratePlan['Restrictions']['@attributes']['minLOS'])) {
$minStay = $ratePlan['Restrictions']['@attributes']['minLOS'];
$requestParams = [];
$requestParams = $requestParamBase;
$requestParams['update_type'] = 'min_stay';
$requestParams['value'] = $minStay;
$requestParams['room_rates'] = [$roomRates];
$requestParams['channel_id'] = $paramChannelId;
$propertyRoomRateMapping = $this->propertyRoomRatePriceService->bulkUpdate($requestParams);
if ($propertyRoomRateMapping['status'] != 'success') {
throw new ApiErrorException($propertyRoomRateMapping['message']);
}
$this->info(date('Y-m-d H:i:s') . ' : Update Type: ' . $requestParams['update_type']);
}
}
}
}
}
}
}
$response['status'] = true;
$updateDataLog = [
'response' => json_encode($response),
'status' => 1
];
$channelManagerLog = $this->channelManagerLogService->update($logData['id'], $updateDataLog);
DB::commit();
} catch (ApiErrorException $e) {
$response['message'] = implode(', ', $e->getMessageArr());
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$response['message'] = $e->getMessage();
}
//TODO: mail
if (!$response['status']) {
DB::rollBack();
}
}
}
$this->info(date('Y-m-d H:i:s') . ' : Finished');
}
}

View File

@@ -0,0 +1,784 @@
<?php
namespace App\Console\Commands\ChannelManager;
use App\Core\Mail\CancelBookingMail;
use App\Core\Mail\LogMail;
use App\Core\Mail\ModifiedBookingMail;
use App\Core\Service\BookingContactService;
use App\Core\Service\BookingPaymentService;
use App\Core\Service\BookingRoomService;
use App\Core\Service\BookingService;
use App\Core\Service\ChannelManager\Reseliva;
use App\Core\Service\ChannelManagerMappingService;
use App\Core\Service\ChannelManagerPropertyMappingService;
use App\Core\Service\ChannelManagerPropertyRateMappingService;
use App\Core\Service\NewBookingMailService;
use App\Core\Service\PropertyRoomAvailabilityService;
use App\Exceptions\ApiErrorException;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class ReservationPullService extends Command
{
protected $signature = 'cron:reservation-pull-service';
protected $description = '';
protected $mailer;
protected $channelService;
protected $channelManagerPropertyMappingService;
protected $bookingService;
protected $propertyRoomAvailabilityService;
protected $newBookingMailService;
public function __construct(
Mailer $mailer,
Reseliva $channelService,
ChannelManagerMappingService $channelManagerMappingService,
ChannelManagerPropertyMappingService $channelManagerPropertyMappingService,
BookingService $bookingService,
BookingContactService $bookingContactService,
BookingRoomService $bookingRoomService,
BookingPaymentService $bookingPaymentService,
PropertyRoomAvailabilityService $propertyRoomAvailabilityService,
NewBookingMailService $newBookingMailService
)
{
parent::__construct();
$this->mailer = $mailer;
$this->channelService = $channelService;
$this->channelManagerMappingService = $channelManagerMappingService;
$this->channelManagerPropertyMappingService = $channelManagerPropertyMappingService;
$this->bookingService = $bookingService;
$this->bookingContactService = $bookingContactService;
$this->bookingRoomService = $bookingRoomService;
$this->bookingPaymentService = $bookingPaymentService;
$this->propertyRoomAvailabilityService = $propertyRoomAvailabilityService;
$this->newBookingMailService = $newBookingMailService;
}
public function reservationListParam($channelManagerPropertyId)
{
$userId = Config::get('app.channelManager.reseliva.userId');
$userPSW = Config::get('app.channelManager.reseliva.userPassword');
$requestParam = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><request></request>');
$Authentication = $requestParam->addChild('Authentication');
$Authentication->addChild('UserID', $userId);
$Authentication->addChild('UserPSW', $userPSW);
$Authentication->addChild('PropertyID', $channelManagerPropertyId);
return $requestParam->asXML();
}
public function reservationConfirmParam($propertyId, $channelManagerBookingId, $bookingCode)
{
$userId = Config::get('app.channelManager.reseliva.userId');
$userPSW = Config::get('app.channelManager.reseliva.userPassword');
$requestParam = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><request></request>');
$Authentication = $requestParam->addChild('Authentication');
$Authentication->addChild('UserID', $userId);
$Authentication->addChild('UserPSW', $userPSW);
$Authentication->addChild('PropertyID', $propertyId);
$reservations = $requestParam->addChild('reservations');
$reservation = $reservations->addChild('reservation');
$reservation->addAttribute('reseliva_id', $channelManagerBookingId);
$reservation->addAttribute('pms_id', $bookingCode);
return $requestParam->asXML();
}
public function getDateByDay($dates = [])
{
$dateByDay = [];
$diffInDays = Carbon::parse($dates['checkIn'])->floatDiffInDays(Carbon::parse($dates['checkOut']));
for ($i = 0; $i < $diffInDays; $i++) {
$dateByDay[] = Carbon::parse($dates['checkIn'])->addDay($i)->format('Y-m-d');
}
return $dateByDay;
}
public function createBooking($param)
{
$response = ['status' => false, 'message' => ''];
DB::beginTransaction();
try {
$bookingCode = getCodeGenerate('BKG');
$bookingStatus = 1;
$roomRequest = [];
foreach ($param['room'] as $room) {
$roomRequest[] = [
'adults' => $room['totalpax'],
'children' => $room['totalchd'],
'age' => []
];
}
if (empty(fillOnUndefined($param, 'reservno_ota'))) {
$param['reservno_ota'] = null;
}
$bookingCreateParam = [
'property_id' => $param['property']['id'],
'channel_id' => $param['property']['channel_id'],
'booking_code' => $bookingCode,
'channel_booking_code' => fillOnUndefined($param, 'reservno_ota'),
'search_key' => $param['reservno'],
'checkin_date' => $param['checkinFormatted'],
'checkout_date' => $param['checkoutFormatted'],
'rooms' => json_encode($roomRequest),
'payment_type_code' => 'CHN',
'room_amount' => $param['paymenttotal'],
'addon_amount' => 0,
'discount_amount' => 0,
'total' => $param['paymenttotal'],
'currency_code' => $param['paymentcurr'],
'channel_token' => null,
'booking_engine_token' => null,
'reservation_time' => $param['restimeUnixFormatted'],
'status' => $param['status'] == 'A' ? 1 : 0
];
$bookingCreate = $this->bookingService->create($bookingCreateParam);
//$bookingCreate['status'] = 'success';
//$bookingCreate['data']['id'] = 52;
if ($bookingCreate['status'] != 'success') {
throw new ApiErrorException(lang('Booking could not be made, Reservation: ' . $param['reservno']));
}
//INSERT CONTACT DATA
$bookingContactCreateParam = [
'booking_id' => $bookingCreate['data']['id'],
'name' => $param['firstname'],
'surname' => !empty($param['lastname']) ? $param['lastname'] : null,
'phone_code' => null,
'phone_number' => $param['tel'],
'email' => $param['email'],
'note' => !empty($param['note']) ? $param['note'] : null,
'language_code' => fillOnUndefined($param, 'language', 'en'),
'status' => 1
];
$bookingContactCreate = $this->bookingContactService->create($bookingContactCreateParam);
//$bookingContactCreate['status'] = 'success';
if ($bookingContactCreate['status'] != 'success') {
throw new ApiErrorException(lang('Booking Contact could not be made'));
}
//INSERT ROOM DATA
foreach ($param['room'] as $roomOrder => $room) {
$bookingRoomCreateParam = [
'booking_id' => $bookingCreate['data']['id'],
'room_order_number' => ($roomOrder + 1),
'occupancy_code' => str_repeat('A', $room['totalpax']) . str_repeat('C', $room['totalchd']),
'checkin_date' => $param['checkinFormatted'], //$room['checkin'],
'checkout_date' => $param['checkoutFormatted'],//$room['checkout'],
'rate_key' => null,
'rate_key_code' => null,
'availability_id' => 1,
'availability_code' => 'ROM',
'room_id' => $room['property']['room_id'],
'room_name' => $room['roomtype'],
'room_rate_mapping_id' => $room['property']['room_rate_mapping_id'],
'room_rate_name' => $room['ratename'],
'cancellation_policy' => null,
'payment_type_code' => 'CHN',
'rate_detail' => json_encode($room),
'total' => $room['total_amount'],
'currency_code' => $param['paymentcurr'],
'status' => $param['status'] == 'A' ? 1 : 0
];
$bookingRoomCreate = $this->bookingRoomService->create($bookingRoomCreateParam);
//$bookingRoomCreate['status'] = 'success';
if ($bookingRoomCreate['status'] != 'success') {
throw new ApiErrorException(lang('Booking Room could not be made'));
}
/* ROOM AVAILABILITY */
$dateByDay = [];
$dateByDay = $this->getDateByDay(['checkIn' => $room['checkin'], 'checkOut' => $room['checkout']]);
foreach ($dateByDay as $day) {
$requestParam = [
'criteria' => [
['field' => 'property_id', 'condition' => '=', 'value' => $param['property']['id']],
['field' => 'property_room_id', 'condition' => '=', 'value' => $room['property']['room_id']],
['field' => 'availability_type_id', 'condition' => '=', 'value' => 1],
['field' => 'date', 'condition' => '=', 'value' => $day]
],
];
$getPropertyRoomAndRoomRateAvailability = $this->propertyRoomAvailabilityService->select($requestParam);
if ($getPropertyRoomAndRoomRateAvailability['status'] != 'success') {
throw new ApiErrorException('getPropertyRoomAndRoomRateAvailability Empty');
}
foreach ($getPropertyRoomAndRoomRateAvailability['data'] as $roomAvailability) {
$roomAvailabilityUpdated = $roomAvailability['availability'] <= 0 ? 0 : ($roomAvailability['availability'] - 1);
$this->propertyRoomAvailabilityService->update($roomAvailability['id'], ['availability' => $roomAvailabilityUpdated]);
}
}
/* ROOM AVAILABILITY */
}
//INSERT PAYMENT DATA
$bookingPaymentCreateParam = [
'booking_id' => $bookingCreate['data']['id'],
'payment_code' => (isset($param['cc_token']) && !empty($param['cc_token'])) ? fillOnUndefined($param, 'cc_token') : null,
'payment_type_code' => 'CHN',
'total' => $param['paymenttotal'],
'currency_code' => $param['paymentcurr'],
'status' => 2
];
$bookingPaymentCreate = $this->bookingPaymentService->create($bookingPaymentCreateParam);
//$bookingContactCreate['status'] = 'success';
if ($bookingPaymentCreate['status'] != 'success') {
throw new ApiErrorException(lang('Booking Payment could not be made'));
}
//INSERT PAYMENT DATA
//INSERT CHANNEL PAYMENT DATA
if (isset($param['cc_token']) && !empty($param['cc_token'])) {
$bookingPaymentDataCreateParam = [
'booking_id' => $bookingCreate['data']['id'],
'type' => 'ch',
'data' => md5($param['reservno'].$param['channelManagerPropertyId'].$param['cc_token'])
];
$bookingPaymentDataCreate = $this->bookingPaymentService->createPaymentData($bookingPaymentDataCreateParam);
if ($bookingPaymentDataCreate['status'] != 'success') {
throw new ApiErrorException(lang('Booking Payment could not be made'));
}
}
//INSERT CHANNEL PAYMENT DATA
//$param['reservno'] = '27145472222';
$reservationConfirmParam = $this->reservationConfirmParam($param['channelManagerPropertyId'], $param['reservno'], $bookingCode);
$reservationConfirm = $this->channelService->reservationConfirm($reservationConfirmParam);
if (!$reservationConfirm['status']) {
throw new ApiErrorException($reservationConfirm['message']);
}
DB::commit();
$mailParams = ['booking_id' => $bookingCreate['data']['id']];
$this->newBookingMailService->process($mailParams);
$response['status'] = true;
} catch (ApiErrorException $e) {
$response['message'] = implode(', ', $e->getMessageArr());
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$response['message'] = $e->getMessage();
}
if (!$response['status']) {
DB::rollBack();
}
return $response;
}
public function cancelBooking($param)
{
$response = ['status' => false, 'message' => ''];
DB::beginTransaction();
try {
$bookingCode = null;
$bookingDetailParam = [
'criteria' => [
['field' => 'property_id', 'condition' => '=', 'value' => $param['property']['id']],
['field' => 'search_key', 'condition' => '=', 'value' => $param['reservno']]
],
'with' => ['bookingRoom'],
'firstRow' => true
];
$bookingDetail = $this->bookingService->select($bookingDetailParam);
if ($bookingDetail['status'] != 'success') {
throw new ApiErrorException(lang('Booking could not be found, Reservation: ' . $param['reservno']));
}
if (!empty($bookingDetail['data'])) {
$bookingCode = $bookingDetail['data']['booking_code'];
$this->bookingService->update($bookingDetail['data']['id'], ['status' => 0]);
foreach ($bookingDetail['data']['booking_room'] as $roomOrder => $room) {
$bookingRoomCreate = $this->bookingRoomService->update($room['id'], ['status' => 0]);
/* ROOM AVAILABILITY */
$dateByDay = [];
$dateByDay = $this->getDateByDay(['checkIn' => $room['checkin_date'], 'checkOut' => $room['checkout_date']]);
foreach ($dateByDay as $day) {
$requestParam = [
'criteria' => [
['field' => 'property_id', 'condition' => '=', 'value' => $param['property']['id']],
['field' => 'property_room_id', 'condition' => '=', 'value' => $room['room_id']],
['field' => 'availability_type_id', 'condition' => '=', 'value' => 1],
['field' => 'date', 'condition' => '=', 'value' => $day]
],
];
$getPropertyRoomAndRoomRateAvailability = $this->propertyRoomAvailabilityService->select($requestParam);
if ($getPropertyRoomAndRoomRateAvailability['status'] != 'success') {
throw new ApiErrorException('getPropertyRoomAndRoomRateAvailability Empty');
}
foreach ($getPropertyRoomAndRoomRateAvailability['data'] as $roomAvailability) {
$roomAvailabilityUpdated = $roomAvailability['availability'] <= 0 ? 1 : ($roomAvailability['availability'] + 1);
$this->propertyRoomAvailabilityService->update($roomAvailability['id'], ['availability' => $roomAvailabilityUpdated]);
}
}
/* ROOM AVAILABILITY */
}
}
$response['status'] = true;
$bookingCode = is_null($bookingCode) ? 'ENW' . $param['reservno'] : $bookingCode;
$reservationConfirmParam = $this->reservationConfirmParam($param['channelManagerPropertyId'], $param['reservno'], $bookingCode);
$reservationConfirm = $this->channelService->reservationConfirm($reservationConfirmParam);
if (!$reservationConfirm['status']) {
throw new ApiErrorException($reservationConfirm['message']);
}
$notificationCancelToPropertyUser = [
'channel' => $param['otaname'],
'channelBookingCode' => $param['reservno_ota'],
'propertyChannelManager' => $param['otaname'],//$channelManagerMapping['property_channel_manager']['name'],
'nameSurname' => $param['firstname'] . ' ' . $param['lastname'],
'propertyId' => $param['property']['id'],
];
$this->mailer->onQueue('cancelBookingMail', new CancelBookingMail($notificationCancelToPropertyUser));
} catch (ApiErrorException $e) {
$response['message'] = implode(', ', $e->getMessageArr());
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$response['message'] = $e->getMessage();
}
if ($response['status']) {
DB::commit();
} else {
DB::rollBack();
}
return $response;
}
public function modifiedBooking($param)
{
$response = ['status' => false, 'message' => ''];
DB::beginTransaction();
try {
$bookingCode = null;
$bookingDetailParam = [
'criteria' => [
['field' => 'property_id', 'condition' => '=', 'value' => $param['property']['id']],
['field' => 'search_key', 'condition' => '=', 'value' => $param['reservno']]
],
'with' => ['bookingRoom', 'bookingContact'],
'firstRow' => true
];
$bookingDetail = $this->bookingService->select($bookingDetailParam);
if ($bookingDetail['status'] != 'success') {
throw new ApiErrorException(lang('Booking could not be found, Reservation: ' . $param['reservno']));
}
if (!empty($bookingDetail['data'])) {
$bookingCode = $bookingDetail['data']['booking_code'];
$bookingUpdateParam = [
'channel_booking_code' => fillOnUndefined($param, 'reservno_ota'),
'search_key' => $param['reservno'],
'checkin_date' => $param['checkinFormatted'],
'checkout_date' => $param['checkoutFormatted'],
'payment_type_code' => 'CHN',
'total' => $param['paymenttotal'],
'currency_code' => $param['paymentcurr'],
];
$bookingUpdate = $this->bookingService->update($bookingDetail['data']['id'], $bookingUpdateParam);
$bookingContactUpdateParam = [
'name' => $param['firstname'],
'surname' => $param['lastname'],
'phone_code' => null,
'phone_number' => $param['tel'],
'email' => $param['email'],
'note' => !empty($param['note']) ? $param['note'] : null,
'language_code' => fillOnUndefined($param, 'language', 'en')
];
$bookingContactUpdate = $this->bookingContactService->update($bookingDetail['data']['booking_contact']['id'], $bookingContactUpdateParam);
foreach ($bookingDetail['data']['booking_room'] as $roomOrder => $room) {
foreach ($param['room'] as $roomOrderChannel => $roomChannel) {
if ($roomOrder == $roomOrderChannel) {
$bookingRoomUpdateParam = [
'occupancy_code' => str_repeat('A', $roomChannel['totalpax']) . str_repeat('C', $roomChannel['totalchd']),
'checkin_date' => $roomChannel['checkin'],
'checkout_date' => $roomChannel['checkout'],
'room_id' => $roomChannel['property']['room_id'],
'room_name' => $roomChannel['roomtype'],
'room_rate_mapping_id' => $roomChannel['property']['room_rate_mapping_id'],
'room_rate_name' => $roomChannel['ratename'],
'rate_detail' => json_encode($roomChannel),
'total' => $roomChannel['total_amount'],
'currency_code' => $param['paymentcurr'],
];
$bookingRoomUpdate = $this->bookingRoomService->update($room['id'], $bookingRoomUpdateParam);
}
}
}
}
$response['status'] = true;
$bookingCode = is_null($bookingCode) ? 'ENW' . $param['reservno'] : $bookingCode;
$reservationConfirmParam = $this->reservationConfirmParam($param['channelManagerPropertyId'], $param['reservno'], $bookingCode);
$reservationConfirm = $this->channelService->reservationConfirm($reservationConfirmParam);
if (!$reservationConfirm['status']) {
throw new ApiErrorException($reservationConfirm['message']);
}
$notificationModifiedToPropertyUser = [
'channel' => $param['otaname'],
'channelBookingCode' => $param['reservno_ota'],
'propertyChannelManager' => $param['otaname'],//$channelManagerMapping['property_channel_manager']['name'],
'nameSurname' => $param['firstname'] . ' ' . $param['lastname'],
'propertyId' => $param['property']['id'],
];
$this->mailer->onQueue('modifiedBookingMail', new ModifiedBookingMail($notificationModifiedToPropertyUser));
} catch (ApiErrorException $e) {
$response['message'] = implode(', ', $e->getMessageArr());
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$response['message'] = $e->getMessage();
}
if ($response['status']) {
DB::commit();
} else {
DB::rollBack();
}
return $response;
}
public function handle()
{
//$request = $this->channelService->productList(14480);
try {
/*
1. Reseliva mapping olan oteller çekilecek
2. Her otel için foreach ile reservaion servisi çağrılacak
3. Gelen bilgiler enw ye işlenecek, sonra da confirmcheck yapılacak
* */
$this->info(date('Y-m-d H:i:s') . ' : Start');
$channelManagerMappingCriteria =
[
'criteria' =>
[
['field' => 'status', 'condition' => '=', 'value' => 1],
],
'with' => ['propertyChannelManager'],
'orderBy' => [
['field' => 'id', 'value' => 'ASC']
]
];
$channelManagerMappingData = $this->channelManagerMappingService->select($channelManagerMappingCriteria);
$channelManagerMappingCollect = collect($channelManagerMappingData['data']);
$channelManagerPropertyMappingCriteria = [
'criteria' =>
[
['field' => 'status', 'condition' => '=', 'value' => 1],
['field' => 'channel_manager_id', 'condition' => '=', 'value' => 1],
['field' => 'channel_manager_property_id', 'condition' => '!=', 'value' => null],
//['field' => 'property_id', 'condition' => '=', 'value' => 326],//TODO: Delete
],
'with' => ['channelManagerRoomRate.propertyRoomRateMapping'],
'orderBy' => [
['field' => 'id', 'value' => 'ASC']
]
];
$channelManagerPropertyMapping = $this->channelManagerPropertyMappingService->select($channelManagerPropertyMappingCriteria);
if ($channelManagerPropertyMapping['status'] == 'success') {
foreach ($channelManagerPropertyMapping['data'] as $propertyMapping) {
$channelManagerRoomRateCollect = collect($propertyMapping['channel_manager_room_rate']);
$reservationListParam = $this->reservationListParam($propertyMapping['channel_manager_property_id']);
$reservationList = $this->channelService->reservationList($reservationListParam);
if (!$reservationList['status']) {
//$logMessage
$mailParams = [
'title' => 'ReservationPullService Error - ReservationList Error',
'logMessage' => '<pre>' . $reservationListParam . '</pre>'
];
$this->mailer->onQueue('logMail', new LogMail($mailParams));
//$logMessage
throw new ApiErrorException('ReservationList Error: ' . $reservationList['message']);
}
foreach ($reservationList['data'] as $reservationKey => $reservation) {
//Check Channel Manager Mapping
$channelManagerMapping = $channelManagerMappingCollect->where('channel_manager_channel_id', $reservation['otaname'])->first();
//Eğer ExtranetWork ise içeri almadan onayla
if ($reservation['otaname'] == 'ExtranetWork') {
$reservationConfirmParam = $this->reservationConfirmParam($propertyMapping['channel_manager_property_id'], $reservation['reservno'], 'ENWRES' . $reservation['reservno']);
//$reservationConfirm = $this->channelService->reservationConfirm($reservationConfirmParam);
$reservationConfirm['status'] = true;
if (!$reservationConfirm['status']) {
throw new ApiErrorException($reservationConfirm['message']);
}
continue;
}
if (empty($channelManagerMapping)) {
//Eğer mapping yapılmış kanal bulunamamış ise rezervasyonu içeri alamazsın
//$logMessage
$mailParams = [
'title' => 'ReservationPullService Error - Channel Manager Mapping',
'logMessage' => '<pre>' . print_r(array_merge($propertyMapping, $reservation), true) . '</pre>'
];
$this->mailer->onQueue('logMail', new LogMail($mailParams));
//$logMessage
unset($reservationList['data'][$reservationKey]);
continue;
}
$reservationList['data'][$reservationKey]['property']['id'] = $propertyMapping['property_id'];
$reservationList['data'][$reservationKey]['property']['channel_id'] = $channelManagerMapping['property_channel_id'];
foreach ($reservation['room'] as $roomKey => $room) {
//Check Room Rate Mapping
$channelManagerRoomRate = $channelManagerRoomRateCollect->where('channel_manager_room_id', $room['roomid'])->where('channel_manager_room_rate_id', $room['rateid'])->first();
if (empty($channelManagerRoomRate)) {
$channelManagerRoomRate = $channelManagerRoomRateCollect->where('channel_manager_room_id', $room['roomid'])->first();
}
$reservationList['data'][$reservationKey]['room'][$roomKey]['property']['room_id'] = null;
$reservationList['data'][$reservationKey]['room'][$roomKey]['property']['room_rate_id'] = null;
$reservationList['data'][$reservationKey]['room'][$roomKey]['property']['room_rate_mapping_id'] = null;
$reservationList['data'][$reservationKey]['channelManagerPropertyId'] = $propertyMapping['channel_manager_property_id'];
if (empty($channelManagerRoomRate)) {
//Eğer mapping yapılmış oda bulunamamış ise rezervasyonu içeri alamazsın
//$logMessage
$mailParams = [
'title' => 'ReservationPullService Error - Channel Manager Room Rate Mapping',
'logMessage' => '<pre>' . print_r(array_merge($propertyMapping, $reservation), true) . '</pre>'
];
$this->mailer->onQueue('logMail', new LogMail($mailParams));
//$logMessage
unset($reservationList['data'][$reservationKey]);
$this->error(date('Y-m-d H:i:s') . ' : Error: RoomRate Mapping Reservation: ' . $reservation['reservno']);
//Eşleşmeyen ve iptal edilen işlemin otele bildirilmesi.
if ($reservation['status'] == 'C') {
$notificationCancelToPropertyUser = [
'channel' => $reservation['otaname'],
'channelBookingCode' => $reservation['reservno_ota'],
'propertyChannelManager' => $channelManagerMapping['property_channel_manager']['name'],
'nameSurname' => $reservation['firstname'] . ' ' . $reservation['lastname'],
'propertyId' => $propertyMapping['property_id'],
];
$this->mailer->onQueue('cancelBookingMail', new CancelBookingMail($notificationCancelToPropertyUser));
$reservationConfirmParam = $this->reservationConfirmParam($propertyMapping['channel_manager_property_id'], $reservation['reservno'], 'ENWRES' . $reservation['reservno']);
$reservationConfirm = $this->channelService->reservationConfirm($reservationConfirmParam);
if (!$reservationConfirm['status']) {
throw new ApiErrorException($reservationConfirm['message']);
}
}
} else {
$reservationList['data'][$reservationKey]['room'][$roomKey]['property']['room_id'] = $channelManagerRoomRate['property_room_rate_mapping']['room_id'];
$reservationList['data'][$reservationKey]['room'][$roomKey]['property']['room_rate_id'] = $channelManagerRoomRate['property_room_rate_mapping']['room_rate_id'];
$reservationList['data'][$reservationKey]['room'][$roomKey]['property']['room_rate_mapping_id'] = $channelManagerRoomRate['property_room_rate_mapping']['id'];
}
}
}
foreach ($reservationList['data'] as $reservationKey => $reservation) {
//Eğer ExtranetWork ise içeri almadan onayla
if ($reservation['otaname'] == 'ExtranetWork') {
$reservationConfirmParam = $this->reservationConfirmParam($propertyMapping['channel_manager_property_id'], $reservation['reservno'], 'ENWRES' . $reservation['reservno']);
$reservationConfirm = $this->channelService->reservationConfirm($reservationConfirmParam);
if (!$reservationConfirm['status']) {
throw new ApiErrorException($reservationConfirm['message']);
}
continue;
}
$booking = ['status' => false, 'message' => ''];
if ($reservation['status'] == 'A') {
$booking = $this->createBooking($reservation);
} elseif ($reservation['status'] == 'C') {
$booking = $this->cancelBooking($reservation);
} elseif ($reservation['status'] == 'M') {
$booking = $this->modifiedBooking($reservation);
}
//M Modified kayıt bul güncelle ve sonra mail atılacak cancel ile aynı mail yapısı kullanılacak
if ($booking['status']) {
$this->info(date('Y-m-d H:i:s') . ' : Success: ' . $reservation['reservno']);
} else {
//$logMessage
$mailParams = [
'title' => 'ReservationPullService Error - Booking',
'logMessage' => '<pre>' . print_r(array_merge($booking, $reservation), true) . '</pre>'
];
$this->mailer->onQueue('logMail', new LogMail($mailParams));
//$logMessage
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $booking['message']);
}
}
}
}
$this->info(date('Y-m-d H:i:s') . ' : Finished');
} catch (ApiErrorException $e) {
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $e->getMessage());
} catch
(Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $message);
}
}
}

View File

@@ -0,0 +1,281 @@
<?php
namespace App\Console\Commands\ChannelManager;
use App\Core\Mail\LogMail;
use App\Core\Service\ChannelManager\Reseliva;
use App\Core\Service\ChannelManagerBookingService;
use App\Exceptions\ApiErrorException;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Log;
class ReservationPushService extends Command
{
protected $signature = 'cron:reservation-push-service';
protected $description = '';
protected $channelService;
protected $channelManagerBookingService;
protected $typeMapping;
public function __construct(
Mailer $mailer,
Reseliva $channelService,
ChannelManagerBookingService $channelManagerBookingService
)
{
parent::__construct();
$this->mailer = $mailer;
$this->channelService = $channelService;
$this->channelManagerBookingService = $channelManagerBookingService;
$this->typeMapping = [
'Booking' => 'Book',
'Modify' => 'Modify',
'Cancel' => 'Cancel'
];
}
public function handle()
{
try {
$this->info(date('Y-m-d H:i:s') . ' : Start');
$pendingBookingCriteria = [
'criteria' =>
[
['field' => 'channel_manager_id', 'condition' => '=', 'value' => 1],
['field' => 'is_pushed', 'condition' => '=', 'value' => null],
['field' => 'status', 'condition' => '=', 'value' => 1],
],
'with' => ['bookingDetail.bookingContact', 'bookingDetail.bookingChannel', 'bookingDetail.bookingPayment', 'bookingDetail.bookingPaymentType', 'bookingDetail.bookingStatus', 'bookingDetail.bookingRoom.roomPax.paxCountry'],
'orderBy' => [
['field' => 'id', 'value' => 'ASC']
],
'take' => 100
];
$pendingBooking = $this->channelManagerBookingService->select($pendingBookingCriteria);
if ($pendingBooking['status'] == 'success') {
$pendingBooking = $pendingBooking['data'];
foreach ($pendingBooking as $booking) {
$bookingDetail = $booking['booking_detail'];
$type = $this->typeMapping[$booking['type']];
$serviceRequestName = 'BookingRetrieval';
$xmlResponse = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><' . $serviceRequestName . 'RS></' . $serviceRequestName . 'RS>');
if (in_array($bookingDetail['status'], [0, 3])) {
$Bookings = $xmlResponse->addChild('Bookings');
$Booking = $Bookings->addChild('Booking');
if(Carbon::createFromTimestamp($booking['booking_detail']['created_at'])->lessThan(Carbon::parse('2022-04-01'))) {
$Booking->addAttribute('id', $bookingDetail['id']);
} else {
$Booking->addAttribute('id', $bookingDetail['booking_code']);
}
$Booking->addAttribute('type', 'Cancel');
$Booking->addAttribute('cancelDateTime', Carbon::createFromTimestamp($bookingDetail['updated_at'])->toISOString());
$Hotel = $Booking->addChild('Hotel');
$Hotel->addAttribute('id', $bookingDetail['property_id']);
foreach ($bookingDetail['booking_room'] as $room) {
$RoomStay = $Booking->addChild('RoomStay');
$RoomStay->addAttribute('roomTypeID', $room['room_id']);
$RoomStay->addAttribute('ratePlanID', $room['room_rate_mapping_id']);
$StayDate = $RoomStay->addChild('StayDate');
$StayDate->addAttribute('arrival', $room['checkin_date']);
$StayDate->addAttribute('departure', $room['checkout_date']);
}
} else {
$Bookings = $xmlResponse->addChild('Bookings');
$Booking = $Bookings->addChild('Booking');
if(Carbon::createFromTimestamp($booking['booking_detail']['created_at'])->lessThan(Carbon::parse('2022-04-01'))) {
$Booking->addAttribute('id', $bookingDetail['id']);
} else {
$Booking->addAttribute('id', $bookingDetail['booking_code']);
}
//Book ve Modify Aynı olacak, Cancel
if ($type == 'Book') {
$Booking->addAttribute('type', 'Book');
$Booking->addAttribute('createDateTime', Carbon::createFromTimestamp($bookingDetail['created_at'])->toISOString());
}
if ($type == 'Modify') {
$Booking->addAttribute('type', 'Modify');
$Booking->addAttribute('modifyDateTime', Carbon::createFromTimestamp($bookingDetail['updated_at'])->toISOString());
}
$Hotel = $Booking->addChild('Hotel');
$Hotel->addAttribute('id', $bookingDetail['property_id']);
foreach ($bookingDetail['booking_room'] as $room) {
$RoomStay = $Booking->addChild('RoomStay');
$RoomStay->addAttribute('roomTypeID', $room['room_id']);
$RoomStay->addAttribute('ratePlanID', $room['room_rate_mapping_id']);
$StayDate = $RoomStay->addChild('StayDate');
$StayDate->addAttribute('arrival', $room['checkin_date']);
$StayDate->addAttribute('departure', $room['checkout_date']);
$roomPaxCollect = collect($room['room_pax']);
$GuestCount = $RoomStay->addChild('GuestCount');
$GuestCount->addAttribute('adult', $roomPaxCollect->where('type', 'ADT')->count());
$diffInDays = Carbon::parse($room['checkin_date'])->diffInDays(Carbon::parse($room['checkout_date']));
//dd($room['total'], $diffInDays, $room);
$PerDayRates = $RoomStay->addChild('PerDayRates');
$PerDayRates->addAttribute('currency', $room['currency_code']);
$baseRateDaily = moneyDoubleFormatDecimal($room['total'] / $diffInDays);
$currentDate = $room['checkin_date'];
for ($i = 0; $i < $diffInDays; $i++) {
$PerDayRate = $PerDayRates->addChild('PerDayRate');
$PerDayRate->addAttribute('stayDate', $currentDate);
$PerDayRate->addAttribute('baseRate', $baseRateDaily);
$PerDayRate->addAttribute('hotelServiceFees', 0);
$currentDate = Carbon::parse($currentDate)->addDay()->toDateString();
}
$Total = $RoomStay->addChild('Total');
$Total->addAttribute('amountAfterTaxes', $room['total']);
$Total->addAttribute('amountOfTaxes', 0);
$Total->addAttribute('currency', $room['currency_code']);
$roomNotes['cancellationPolicy'] = 'Cancellation Policy: Refundable';
$cancellationPolicy = json_decode($room['cancellation_policy'],1);
if(!empty($cancellationPolicy) && is_array($cancellationPolicy)) {
if(isset($cancellationPolicy['isNonRefundable']) && $cancellationPolicy['isNonRefundable']) {
$roomNotes['cancellationPolicy'] = 'Cancellation Policy: NonRefundable';
}
}
$roomNotes['payment'] = 'Payment: '.$bookingDetail['booking_payment_type']['name'];
$RoomStay->addChild('RoomNotes', implode('. ',$roomNotes));
}
$PrimaryGuest = $Booking->addChild('PrimaryGuest');
$Name = $PrimaryGuest->addChild('Name');
$Name->addAttribute('givenName', $bookingDetail['booking_contact']['name']);
$Name->addAttribute('surname', $bookingDetail['booking_contact']['surname']);
$Phone = $PrimaryGuest->addChild('Phone');
$Phone->addAttribute('countryCode', $bookingDetail['booking_contact']['phone_code']);
//$Phone->addAttribute('cityAreaCode');
$Phone->addAttribute('number', $bookingDetail['booking_contact']['phone_number']);
$PrimaryGuest->addChild('Email', $bookingDetail['booking_contact']['email']);
$Total = $Booking->addChild('Total');
$Total->addAttribute('amountAfterTaxes', $bookingDetail['total']);
$Total->addAttribute('amountOfTaxes', 0);
$Total->addAttribute('currency', $bookingDetail['currency_code']);
$Booking->addChild('SpecialRequest');
$Booking->addChild('BookingNotes', $bookingDetail['booking_contact']['note']);
}
$this->info(date('Y-m-d H:i:s') . ' : Booking Id: '. $booking['booking_id']. ' Push');
$xmlPayload = $xmlResponse->asXML();
$this->channelManagerBookingService->update($booking['id'], ['request' => $xmlPayload]);
$requestPostReservationPush = $this->channelService->requestPostReservationPush($xmlPayload);
$this->channelManagerBookingService->update($booking['id'], ['response' => $requestPostReservationPush['data']['xmlBase']]);
if ($requestPostReservationPush['status']) {
if($requestPostReservationPush['data']['Status'] == 'success') {
$this->info(date('Y-m-d H:i:s') . ' : Booking Id: '. $booking['booking_id']. ' Success');
$this->channelManagerBookingService->update($booking['id'], ['is_pushed' => 1]);
} else {
//$logMessage
$mailParams = [
'title' => 'ReservationPushService Error - requestPostReservationPush Error',
'logMessage' => '<pre>' . print_r(array_merge($booking, $requestPostReservationPush), true) . '</pre>'
];
$this->mailer->onQueue('logMail', new LogMail($mailParams));
//$logMessage
}
} else {
//$logMessage
$mailParams = [
'title' => 'ReservationPushService Error - requestPostReservationPush Error',
'logMessage' => '<pre>' . print_r(array_merge($booking, $requestPostReservationPush), true) . '</pre>'
];
$this->mailer->onQueue('logMail', new LogMail($mailParams));
//$logMessage
$this->info(date('Y-m-d H:i:s') . ' : Booking Id: '. $booking['booking_id']. ' Failed');
}
}
}
$this->info(date('Y-m-d H:i:s') . ' : Finished');
} catch (ApiErrorException $e) {
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $e->getMessage());
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : Error: ' . $message);
}
}
}

Binary file not shown.

View File

@@ -0,0 +1,188 @@
<?php
namespace App\Console\Commands\CurrencyRates;
use App\Core\Repository\CurrencyRates\CurrencyRatesRepository;
use App\Core\Service\CurrencyService;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
class CurrencyRatesService extends Command
{
protected $signature = 'cron:currency-rates';
protected $description = '';
protected $serviceUrl;
private $currencyRatesRepository;
private $currencyService;
public function __construct(
CurrencyRatesRepository $currencyRatesRepository,
CurrencyService $currencyService
)
{
parent::__construct();
$this->currencyRatesRepository = $currencyRatesRepository;
$this->serviceUrl = 'https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml';
$this->currencyService = $currencyService;
}
public function handle()
{
$currencyList = $this->currencyService->getCurrencyList();
if (!$currencyList['status']) {
$this->error(date('Y-m-d H:i:s') . ' : CurrencyList alınamadı.');
}
$availableCurrencies = [];
foreach ($currencyList['data'] as $currency) {
$availableCurrencies[] = $currency['code'];
}
$availableCurrency = $availableCurrencies;
$this->restClient = new Client(['allow_redirects' => false]);
$request = $this->restClient->GET($this->serviceUrl);
$requestResponse = $request->getBody();
$currencyRatesData = json_decode(json_encode(simplexml_load_string($requestResponse)), 1);
if (empty($currencyRatesData)) {
$this->error(date('Y-m-d H:i:s') . ' : CurrencyRatesData alınamadı.');
return false;
}
//Georgia GEL
$tbcBankApiUrl = 'https://nbg.gov.ge/gw/api/ct/monetarypolicy/currencies/en/json/';
$requestTbcBank = $this->restClient->GET($tbcBankApiUrl);
$requestResponseTbcBank = $requestTbcBank->getBody()->getContents();
$currencyRatesDataTbcBank = json_decode($requestResponseTbcBank, 1);
if (empty($currencyRatesDataTbcBank)) {
$this->error(date('Y-m-d H:i:s') . ' : GEL CurrencyRatesData alınamadı.');
}
$currencyRatesDataTbcBank = reset($currencyRatesDataTbcBank);
$currencyRatesDataTbcBank = collect($currencyRatesDataTbcBank['currencies'])->where('code','EUR')->first();
$currencyRatesData['Cube']['Cube']['Cube'][] = [
'@attributes' => [
'currency' => 'GEL',
'rate' => $currencyRatesDataTbcBank['rate']
]
];
//Georgia GEL
//Morocco MAD
$euroApiUrl = 'https://www.floatrates.com/daily/eur.xml';
$requestEuroApiUrl = $this->restClient->GET($euroApiUrl);
$responseEuroApi = $requestEuroApiUrl->getBody();
$currencyRatesDataEuroApi = json_decode(json_encode(simplexml_load_string($responseEuroApi)), 1);
if (empty($currencyRatesDataEuroApi)) {
$this->error(date('Y-m-d H:i:s') . ' : EUR CurrencyRatesData alınamadı.');
}
$currencyRatesDataEuroApiSelected = collect($currencyRatesDataEuroApi['item'])->where('targetCurrency','MAD')->first();
$currencyRatesData['Cube']['Cube']['Cube'][] = [
'@attributes' => [
'currency' => 'MAD',
'rate' => (float)number_format($currencyRatesDataEuroApiSelected['exchangeRate'],4)
]
];
//Morocco MAD
$currencyRatesDataEuroApiSelected = collect($currencyRatesDataEuroApi['item'])->where('targetCurrency','AZN')->first();
$currencyRatesData['Cube']['Cube']['Cube'][] = [
'@attributes' => [
'currency' => 'AZN',
'rate' => (float)number_format($currencyRatesDataEuroApiSelected['exchangeRate'],4)
]
];
//Azerbaijani AZN
$date = $currencyRatesData['Cube']['Cube']['@attributes']['time'];
$currencyRatesCriteria = [
'criteria' => [
['field' => 'date', 'condition' => '=', 'value' => $date],
],
'count' => true,
];
$currencyRateCount = $this->currencyRatesRepository->findByCriteria($currencyRatesCriteria);
if ($currencyRateCount > 0) {
$this->error(date('Y-m-d H:i:s') . ' : ' . $date . ' tarihi için döviz bilgisi güncel.');
return false;
}
$euroParity[] = [
'currency_code' => 'EUR',
'exc_currency_code' => 'EUR',
'rate' => 1
];
foreach ($currencyRatesData['Cube']['Cube']['Cube'] as $perEuroParity) {
if (in_array($perEuroParity['@attributes']['currency'], $availableCurrency)) {
$euroParity[] = [
'currency_code' => 'EUR',
'exc_currency_code' => $perEuroParity['@attributes']['currency'],
'rate' => floatval($perEuroParity['@attributes']['rate']),
];
}
}
$exchangeParity = [];
foreach ($euroParity as $perParity) {
foreach ($euroParity as $perParityExchange) {
$exchangeParity[$perParity['exc_currency_code'] . $perParityExchange['exc_currency_code']] = [
'currency_code' => $perParity['exc_currency_code'],
'exc_currency_code' => $perParityExchange['exc_currency_code'],
'rate' => $perParityExchange['rate'] / $perParity['rate']
];
$exchangeParity[$perParityExchange['exc_currency_code'] . $perParity['exc_currency_code']] = [
'currency_code' => $perParityExchange['exc_currency_code'],
'exc_currency_code' => $perParity['exc_currency_code'],
'rate' => $perParity['rate'] / $perParityExchange['rate']
];
}
}
ksort($exchangeParity);
foreach ($exchangeParity as $perExchangeParity) {
$data[] = [
'date' => $date,
'currency_code' => $perExchangeParity['currency_code'],
'exc_currency_code' => $perExchangeParity['exc_currency_code'],
'rate' => $perExchangeParity['rate'],
'created_at' => Carbon::now()->timestamp
];
}
$currencyRateUpdate = $this->currencyRatesRepository->insert($data);
if ($currencyRateUpdate['status'] == 'success') {
$this->info(date('Y-m-d H:i:s') . ' : ' . $date . ' tarihi için ' . count($exchangeParity) . ' adet döviz bilgisi güncellendi.');
}
}
}

View File

@@ -0,0 +1,149 @@
<?php
namespace App\Console\Commands\Data;
use App\Exceptions\ApiErrorException;
use App\Models\PropertyWeb;
use App\Models\PropertyWebWeather;
use App\Models\vwActiveProperty;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
class DashboardCacheService extends Command
{
protected $signature = 'cron:dashboard-cache';
protected $description = '';
public function __construct(
Client $restClient
)
{
parent::__construct();
$this->restClient = $restClient;
}
public function handle()
{
try {
$this->info(date('Y-m-d H:i:s') . ' : START');
$bookingService = App::make("App\Core\Service\BookingService");
$propertyWebController = App::make("App\Http\Controllers\V1\PropertyWebController");
$vwActiveProperty = vwActiveProperty::where('commission', '>', 1)->orderBy('id')->get()->toArray();
//$dashboardCountablePlaceCacheKey
$this->info(date('Y-m-d H:i:s') . ' : $dashboardCountablePlaceCacheKey');
foreach ($vwActiveProperty as $property) {
//$dashboardCountablePlaceCacheKey
$dashboardCountablePlaceCacheKey = md5('dashboardCountablePlace-' . $property['id']);
try {
$this->line(date('Y-m-d H:i:s') . ' : ' . $property['id'] . ' - ' . $property['name']);
$propertyWeb = PropertyWeb::where('property_id', $property['id'])->where('status', 1)->orderByDesc('id')->first();
$propertyWeb = $propertyWeb ? $propertyWeb->toArray() : null;
if (empty($propertyWeb)) {
throw new Exception('Empty Web ID');
}
$dashboardCountablePlaceParam = ['property_id' => $property['id']];
$dashboardCountablePlace = $propertyWebController->dashboardCountablePlace($dashboardCountablePlaceParam, $propertyWeb['id']);
if ($dashboardCountablePlace['status']) {
Cache::put($dashboardCountablePlaceCacheKey, $dashboardCountablePlace, 24 * 60 * 60);//1 Day
}
} catch (Exception $e) {
$this->error(date('Y-m-d H:i:s') . ' : ' . $e->getMessage());
}
}
//$getBookingDetailedListCacheKey
$this->info(date('Y-m-d H:i:s') . ' : GetBookingDetailedListCacheKey');
foreach ($vwActiveProperty as $property) {
$getBookingDetailedListCacheKey = md5('getBookingDetailedList-' . $property['id']);
try {
$this->line(date('Y-m-d H:i:s') . ' : ' . $property['id'] . ' - ' . $property['name']);
$getBookingDetailedListParam = ['property_id' => $property['id'], 'channel_id' => 1];
$getBookingDetailedList = $bookingService->getBookingDetailedList($getBookingDetailedListParam);
if ($getBookingDetailedList['status'] == 'success') {
$bookings = collect($getBookingDetailedList['data']);
$channelBookings = $bookings->where('channel_id', '=', 1);
$getBookingEngineBookings = $channelBookings->all();
$paxCountArray = $channelBookings->where('status', '=', 1)->map(function ($booking) {
$roomPaxCount = collect($booking['booking_room'])->map(function ($room) {
return collect($room['room_pax'])->count();
})->values()->first();
return [
'booking_id' => $booking['id'],
'room_pax_count' => $roomPaxCount,
];
})->values()->all();
$totalPaxCount = collect($paxCountArray)->sum('room_pax_count');
$allBookingCount = $channelBookings->count();
$preBookingCount = $channelBookings->where('status', '=', 2)->count();
$successBookingCount = $channelBookings->where('status', '=', 1)->count();
$conversionRate = $allBookingCount > 0 ? ($successBookingCount * 100) / $allBookingCount : 0;
$responseData['all_booking_count'] = $allBookingCount;
$responseData['success_booking_count'] = $successBookingCount;
$responseData['pre_booking_count'] = $preBookingCount;
$responseData['conversion_rate'] = number_format($conversionRate, 2);
$responseData['total_pax_count'] = $totalPaxCount;
Cache::put($getBookingDetailedListCacheKey, $responseData, 24 * 60 * 60);//1 Day
}
} catch (Exception $e) {
$this->error(date('Y-m-d H:i:s') . ' : ' . $e->getMessage());
}
//$getBookingDetailedListCacheKey
}
$this->info(date('Y-m-d H:i:s') . ' : FINISHED');
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' ERROR: ' . $message);
}
}
}

View File

@@ -0,0 +1,128 @@
<?php
namespace App\Console\Commands\Data;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Exception;
use Illuminate\Support\Facades\Log;
use Google\Cloud\Vision\V1\ImageAnnotatorClient;
class HotelBedsList extends Command
{
protected $signature = 'cron:hotelbeds-list';
protected $description = '';
public function __construct()
{
parent::__construct();
}
public function handle()
{
try {
$hotelList = [];
$this->info(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' START');
$baseUrl = 'https://api.hotelbeds.com';
$apiKey = 'ddaa6y6zpf6sy8fne4n2zj7q';
$secret = 'wc87VEfTSD';
$countryCode = 'TR';
$language = 'TUR';
$destinationCode = 'AYT';
$fields = ['code', 'name', 'email', 'countryCode', 'destinationCode', 'city','phones'];
$chunk = 500;
$from = 1;
$to = $chunk;
$isContinue = true;
while ($isContinue) {
$xSignature = hash("sha256", $apiKey . $secret . time());
$urlGenerate = $baseUrl . '/hotel-content-api/1.0/hotels?fields=' . implode(',', $fields) . '&countryCode=' . $countryCode . '&language=' . $language . '&from=' . $from . '&to=' . $to.'&destinationCode='.$destinationCode;
$this->restClient = new Client(['allow_redirects' => false]);
$request = $this->restClient->GET($urlGenerate, [
'headers' => [
'content-type' => 'application/json',
'Api-key' => $apiKey,
'X-Signature' => $xSignature,
],
'body' => null,
]);
Log::debug($xSignature);
$requestResponse = $request->getBody();
$requestResponse = json_decode($requestResponse, 1);
$this->info(date('Y-m-d H:i:s') . ' : ' . $urlGenerate);
$from += $chunk;
$to = $from + $chunk - 1;
if (empty($requestResponse['hotels'])) {
$isContinue = false;
}
foreach ($requestResponse['hotels'] as $hotel) {
if(!isset($hotel['email'])) {
continue;
}
$email = mb_strtolower($hotel['email']);
$hotelList[$email] = [
'code' => $hotel['code'],
'content' => (string)uCase($hotel['name']['content']),
'countryCode' => $hotel['countryCode'],
'email' => $email
];
foreach ($hotel['phones'] as $phone) {
if(in_array($phone['phoneType'], ['PHONEHOTEL','PHONEMANAGEMENT'])) {
$hotelList[$email]['phone'] = $phone['phoneNumber'];
break;
}
}
}
}
// Open a file in write mode ('w')
$fileName = $countryCode.(!empty($destinationCode) ? '-'.$destinationCode : '');
$fp = fopen(resource_path().'/data/'.$fileName.'.csv', 'w');
// Loop through file pointer and a line
foreach ($hotelList as $hotel) {
fputcsv($fp, $hotel);
}
fclose($fp);
$this->info(date('Y-m-d H:i:s') . ' : Total: ' . count($hotelList).' / '. $requestResponse['total']);
$this->info(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' FINISHED');
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' ERROR: ' . $message);
}
}
}

View File

@@ -0,0 +1,130 @@
<?php
namespace App\Console\Commands\Data;
use App\Models\PropertyWeb;
use App\Models\PropertyWebWeather;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Exception;
use Illuminate\Support\Facades\Log;
class WeatherService extends Command
{
protected $signature = 'cron:weather';
protected $description = '';
public function __construct(
Client $restClient
)
{
parent::__construct();
$this->restClient = $restClient;
}
public function handle()
{
try {
$date = date('Y-m-d');
$this->info(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' START');
$baseUrl = 'https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline';
$apiKey = 'GQG8FVH2C7ZZYZXS6PECE2QFX';
$this->restClient = new Client(['http_errors' => false]);
$propertyWeb = PropertyWeb::where('status', 1)
->where('weather_active', 1)->with('property.propertyContact')
//->where('property_id',1231)//TODO:Del
->get()->toArray();
foreach ($propertyWeb as $property) {
$propertyWebWeatherId = null;
$propertyWebWeather = PropertyWebWeather::where('property_id', $property['property']['id'])->first();
if ($propertyWebWeather) {
$propertyWebWeatherId = $propertyWebWeather['id'];
}
$latitude = $property['property']['property_contact']['latitude'];
$longitude = $property['property']['property_contact']['longitude'];
if (!empty($latitude) && !empty($longitude)) {
$requestUrl = $baseUrl . '/' . $latitude . ',' . $longitude . '/' . $date . '?key=' . $apiKey . '&include=days&unitGroup=metric&elements=tempmax,tempmin,temp,conditions,icon';
$requestWeather = $this->restClient->request('GET', $requestUrl);
$getResponseBody = $requestWeather->getBody();
$getResponse = $getResponseBody ? json_decode($getResponseBody, 1) : [];
$propertyWebWeatherParam = [
'property_id' => $property['property']['id'],
'date' => $date,
'temp' => $getResponse['days'][0]['tempmax'],
'conditions' => $getResponse['days'][0]['conditions'],
'icon' => $getResponse['days'][0]['icon'],
'response' => json_encode($getResponse),
'created_by' => 1,
'updated_by' => 1,
];
if (empty($propertyWebWeatherId)) {
$locationUrl = 'https://geocode.maps.co/reverse?lat=' . $latitude . '&lon=' . $longitude . '&api_key=6683d9ee52e5d111344805khdf0451c';
$requestLocation = $this->restClient->request('GET', $locationUrl);
$getResponseBodyLocation = $requestLocation->getBody();
$getResponseLocation = $getResponseBodyLocation ? json_decode($getResponseBodyLocation, 1) : [];
if ($getResponseLocation) {
$location = null;
if(isset($getResponseLocation['address']['province'])) {
$location = $getResponseLocation['address']['province'];
}elseif(isset($getResponseLocation['address']['town'])) {
$location = $getResponseLocation['address']['town'];
}elseif(isset($getResponseLocation['address']['city'])) {
$location = $getResponseLocation['address']['city'];
}
$propertyWebWeatherParam['location'] = $location;
$propertyWebWeatherParam['address'] = json_encode($getResponseLocation);
}
PropertyWebWeather::create($propertyWebWeatherParam);
$this->info(date('Y-m-d H:i:s') . ' : ' . $propertyWebWeatherParam['property_id'] . ' - ' . $propertyWebWeatherParam['date'] . ' : ' . $propertyWebWeatherParam['conditions']. ' : ' . $propertyWebWeatherParam['temp']);
} else {
PropertyWebWeather::where('id', $propertyWebWeatherId)->update($propertyWebWeatherParam);
$this->line(date('Y-m-d H:i:s') . ' : ' . $propertyWebWeatherParam['property_id'] . ' - ' . $propertyWebWeatherParam['date'] . ' : ' . $propertyWebWeatherParam['conditions']. ' : ' . $propertyWebWeatherParam['temp']);
}
}
}
$this->info(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' FINISHED');
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' ERROR: ' . $message);
}
}
}

View File

@@ -0,0 +1,140 @@
<?php
namespace App\Console\Commands\Google;
use App\Models\PropertyWeb;
use App\Models\PropertyWebComponentMapping;
use App\Models\PropertyWebReview;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Exception;
use Illuminate\Support\Facades\Log;
use Google\Cloud\Vision\V1\ImageAnnotatorClient;
class GoogleReview extends Command
{
protected $signature = 'cron:google-review {--property_id=}';
protected $description = '';
public function __construct(
Client $restClient
)
{
parent::__construct();
$this->restClient = $restClient;
}
public function handle()
{
try {
$this->info(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' START');
$baseUrl = 'https://maps.googleapis.com/maps/api/place/details/json';
$apiKey = 'AIzaSyAPsKZ_XasAieKEhbmpOLUpArY2u2UcXuk';
$availableRating = [4,5];
$this->restClient = new Client(['http_errors' => false]);
if (!is_null($this->option('property_id'))) {
$propertyWebComponentMapping = PropertyWebComponentMapping::where('status', 1)->where('component_id', 3)->where('property_id', $this->option('property_id'))->get()->toArray();
} else {
$propertyWebComponentMapping = PropertyWebComponentMapping::where('status', 1)->where('component_id', 3)->get()->toArray();
}
foreach ($propertyWebComponentMapping as $propertyWebComponent) {
if (!isset($propertyWebComponent['parameterArray']['placeId'])) {
continue;
}
$googlePlaceId = trim($propertyWebComponent['parameterArray']['placeId']);
Log::debug('google-review: '.$googlePlaceId);
$params = [
'query' => [
'place_id' => $googlePlaceId,
'key' => $apiKey,
'fields' => 'name,rating,reviews',
'reviews_sort' => 'newest',
'reviews_no_translations' => true,
//'language' => 'tr'
]
];
$requestReview = $this->restClient->request('GET', $baseUrl, $params);
$getResponseBody = $requestReview->getBody();
$getResponse = $getResponseBody ? json_decode($getResponseBody, 1) : [];
$reviews = [];
if(isset($getResponse['result']['reviews'])) {
$reviews = collect($getResponse['result']['reviews'])->sortBy('time')->toArray();
}
foreach ($reviews as $review) {
if(!in_array(fillOnUndefined($review, 'rating'),$availableRating)) {
continue;
}
try {
$code = md5($propertyWebComponent['property_id'].'-'.$review['author_name'] . '-' . $review['time']);
$propertyWebReviewCheck = PropertyWebReview::where('code', $code)->first();
if ($propertyWebReviewCheck) {
$this->error(date('Y-m-d H:i:s') . ' : ' . $propertyWebComponent['property_id'] . ' - ' . $review['author_name'] . ' : ' . $review['rating']);
continue;
}
$propertyWebWeatherParam = [
'property_id' => $propertyWebComponent['property_id'],
'channel' => 'google',
'code' => $code,
'language_code' => fillOnUndefined($review, 'language') ? substr($review['language'],0,2) : null,
'author' => $review['author_name'],
'profile_photo' => fillOnUndefined($review, 'profile_photo_url'),
'rating' => fillOnUndefined($review, 'rating'),
'review' => fillOnUndefined($review, 'text'),
'time' => fillOnUndefined($review, 'time'),
'status' => 1,
'created_by' => 1,
'updated_by' => 1,
];
$propertyWebReviewCreate = PropertyWebReview::create($propertyWebWeatherParam);
$this->info(date('Y-m-d H:i:s') . ' : ' . $propertyWebComponent['property_id'] . ' - ' . $review['author_name'] . ' : ' . $review['rating']);
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' ERROR: ' . $message);
}
}
$this->info(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' FINISHED');
}
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' ERROR: ' . $message);
}
}
}

View File

@@ -0,0 +1,107 @@
<?php
namespace App\Console\Commands\Google;
use App\Models\Property;
use App\Models\PropertyWeb;
use App\Models\PropertyWebComponentMapping;
use App\Models\PropertyWebReview;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Exception;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Log;
use Google\Cloud\Vision\V1\ImageAnnotatorClient;
class GoogleStaticMap extends Command
{
protected $signature = 'cron:google-static-map {--property_id=}';
protected $description = '';
public function __construct(
Client $restClient
)
{
parent::__construct();
$this->restClient = $restClient;
}
public function handle()
{
try {
$this->info(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' START');
$baseUrl = 'https://maps.googleapis.com/maps/api/staticmap';
$apiKey = 'AIzaSyAPsKZ_XasAieKEhbmpOLUpArY2u2UcXuk';
$imageSizes = [];
$imageSizes[] = ['name' => 'square','size' => '250x250'];
$imageSizes[] = ['name' => 'rectangle','size' => '1000x200'];
$this->restClient = new Client(['http_errors' => false]);
if (!is_null($this->option('property_id'))) {
$propertyList = Property::where('status', 1)->where('id', $this->option('property_id'))->with('propertyContact')->get()->toArray();
} else {
$propertyList = Property::where('status', 1)->where('commission','>=', 1)->with('propertyContact')->get()->toArray();
}
foreach ($propertyList as $property) {
if (!isset($property['property_contact'])) {
continue;
}
$folderPath = Config::get('app.fileSystemDriver') . '/property-map/' . $property['id'];
if(!is_dir($folderPath)) {
mkdir($folderPath);
}
foreach ($imageSizes as $imageSize) {
$imageName = 'map-'.$property['id'].'-'.$imageSize['name'].'.png';
$imagePath = Config::get('app.fileSystemDriver') . '/property-map/' . $property['id'] . '/'.$imageName;
if(is_file($imagePath)) {
$this->line(date('Y-m-d H:i:s') . ' : ' . $imageName);
continue;
}
$params = [
'center' => $property['property_contact']['latitude'] . ',' . $property['property_contact']['longitude'],
'size' => $imageSize['size'], //300x300 1000x200
'zoom' => 18,
'format' => 'png',
'scale' => 2,
'markers' => 'color:red|' . $property['property_contact']['latitude'] . ',' . $property['property_contact']['longitude'],
'key' => $apiKey,
'language' => 'en'
];
$imageUrl = $baseUrl . '?' . http_build_query($params, '', '&');
$imageSave = file_put_contents($imagePath, file_get_contents($imageUrl));
$this->info(date('Y-m-d H:i:s') . ' : ' . $imageName);
}
}
$this->info(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' FINISHED');
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' ERROR: ' . $message);
}
}
}

View File

@@ -0,0 +1,72 @@
<?php
namespace App\Console\Commands\Google;
use Illuminate\Console\Command;
use Exception;
use Illuminate\Support\Facades\Log;
use Google\Cloud\Vision\V1\ImageAnnotatorClient;
class GoogleVisioLabel extends Command
{
protected $signature = 'cron:google-visio-label';
protected $description = '';
public function __construct(
)
{
parent::__construct();
}
public function handle()
{
try {
$this->info(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' START');
$googleVisionAuthentication = base_path().'/resources/data/google-vision-authentication.json';
putenv('GOOGLE_APPLICATION_CREDENTIALS='.$googleVisionAuthentication);
$imageAnnotator = new ImageAnnotatorClient();
$fileName = 'https://image.rezervasyon.com/hotel/301356/lavin-otel-10-9566879.jpg';
$fileName = 'https://image.rezervasyon.com/hotel/301356/lavin-otel-10-9566886.jpg';
$fileName = 'https://image.rezervasyon.com/hotel/301356/lavin-otel-10-9566881.jpg';
$fileName = 'https://image.rezervasyon.com/hotel/301356/lavin-otel-10-9566878.jpg';
$image = file_get_contents($fileName);
$response = $imageAnnotator->labelDetection($image);
$labels = $response->getLabelAnnotations();
$labelList = [];
if ($labels) {
foreach ($labels as $label) {
$labelList[] = [
'description' => $label->getDescription(),
'score' => $label->getScore(),
'topicality' => $label->getTopicality(),
];
}
} else {
echo('No label found' . PHP_EOL);
}
$imageAnnotator->close();
print_r($labelList);
$this->info(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' FINISHED');
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' ERROR: ' . $message);
}
}
}

View File

@@ -0,0 +1,122 @@
<?php
namespace App\Console\Commands\Jobs;
use App\Core\Service\BookingService;
use App\Exceptions\ApiErrorException;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Exception;
class BookingCommissionService extends Command
{
protected $signature = 'cron:commission-service';
protected $description = '';
private $bookingService;
public function __construct(
BookingService $bookingService
)
{
parent::__construct();
$this->bookingService = $bookingService;
}
public function handle()
{
$this->info(date('Y-m-d H:i:s') . ' START');
try {
$bookingListParam = [
'criteria' => [
//['field' => 'id', 'condition' => '=', 'value' => 600],
//['field' => 'property_id', 'condition' => '=', 'value' => 313],
['field' => 'commission', 'condition' => '=', 'value' => null],
['field' => 'commission_rate', 'condition' => '=', 'value' => null]
],
'with' => ['bookingChannel.propertyChannelCategory', 'bookingProperty'],
"take" => 10000,
"orderBy" => [
["field" => "id", "value" => "ASC"]
],
];
$bookingList = $this->bookingService->select($bookingListParam);
if ($bookingList['status'] != 'success' || ($bookingList['status'] == 'success' && empty($bookingList['data']))) {
throw new ApiErrorException('Property list not found!');
}
foreach ($bookingList['data'] as $booking) {
$commission = null;
$commissionRate = null;
//$booking['booking_property']['commission'] = 15;//TOOD: DEL
switch ($booking['booking_channel']['channel_category_id']) {
case "3" :
if (fillOnUndefined($booking['booking_property'], 'commission') && $booking['booking_property']['commission'] > 0) {
$commissionRate = $booking['booking_property']['commission'];
$commission = moneyDoubleFormatDecimal($booking['booking_property']['commission'] * $booking['total'] / 100);
}
break;
case "2" :
if (fillOnUndefined($booking['booking_property'], 'commission_offline') && $booking['booking_property']['commission_offline'] > 0) {
$commissionRate = $booking['booking_property']['commission_offline'];
$commission = moneyDoubleFormatDecimal($booking['booking_property']['commission_offline'] * $booking['total'] / 100);
}
break;
case "4" :
if (fillOnUndefined($booking['booking_property'], 'commission_channel') && $booking['booking_property']['commission_channel'] > 0) {
$commissionRate = $booking['booking_property']['commission_channel'];
$commission = moneyDoubleFormatDecimal($booking['booking_property']['commission_channel'] * $booking['total'] / 100);
}
break;
case "7" :
if (fillOnUndefined($booking['booking_property'], 'commission_wholesaler') && $booking['booking_property']['commission_wholesaler'] > 0) {
$commissionRate = $booking['booking_property']['commission_wholesaler'];
$commission = moneyDoubleFormatDecimal($booking['booking_property']['commission_wholesaler'] * $booking['total'] / 100);
}
break;
}
if (!empty($commission) && !empty($commissionRate)) {
$this->bookingService->update($booking['id'], ['commission' => $commission, 'commission_rate' => $commissionRate]);
$this->info(date('Y-m-d H:i:s') . ' Property: ' . $booking['booking_property']['name'] . ' Code: ' . $booking['booking_code'] . ' Commission: ' . $commission . ' Commission Rate: ' . $commissionRate);
} else {
$this->bookingService->update($booking['id'], ['commission' => 0, 'commission_rate' => 0]);
$this->error(date('Y-m-d H:i:s') . ' Property: ' . $booking['booking_property']['name'] . ' Code: ' . $booking['booking_code'] . ' Commission: ' . $commission . ' Commission Rate: ' . $commissionRate);
}
//sleep(1);
}
} catch (ApiErrorException | Exception $e) {
$this->error(date('Y-m-d H:i:s') . ' ERROR:' . $e->getMessage());
}
$this->info(date('Y-m-d H:i:s') . ' FINISHED');
}
}

View File

@@ -0,0 +1,194 @@
<?php
namespace App\Console\Commands\Jobs;
use App\Core\Mail\BookingEngineSearchReportMail;
use App\Core\Service\PropertyService;
use App\Exceptions\ApiErrorException;
use App\Models\Country;
use App\Models\Language;
use App\Models\vwBookingEngineSearch;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class BookingEngineSearchReportService extends Command
{
protected $signature = 'cron:bookingengine-search-report-mail';
protected $description = '';
private $propertyService;
public function __construct(
Mailer $mailer,
PropertyService $propertyService
)
{
parent::__construct();
$this->mailer = $mailer;
$this->propertyService = $propertyService;
}
public function handle()
{
$this->info(date('Y-m-d H:i:s') . ' START');
$reportPropertyList = [506, 529, 1606];
//506 Green Nature Diamond Hotel
//529 Green Nature Resort & Spa Otel
//1606 Green Nature Sarıgerme
$propertyListCriteria = [
'criteria' =>
[
['field' => 'status', 'condition' => '=', 'value' => 1],
],
'with' => ['propertyBrand', 'propertyUser.user'],
'orderBy' => [
['field' => 'id', 'value' => 'ASC']
],
'whereIn' =>
[
['field' => 'id', 'value' => $reportPropertyList]
]
];
$propertyListData = $this->propertyService->select($propertyListCriteria);
$propertyList = [];
if ($propertyListData['status'] == 'success' && !empty($propertyListData['data'])) {
$propertyList = $propertyListData['data'];
}
$reportData = [];
$reportDate = Carbon::now()->subDay()->toDateString();
//$reportDate = '2023-02-28';
$reportDateFormatted = Carbon::parse($reportDate)->format('d.m.Y');
$countryList = Country::all()->toArray();
$languageList = Language::all()->toArray();
$this->info(date('Y-m-d H:i:s') . ' Date: ' . $reportDate);
foreach ($propertyList as $property) {
$reportData = [];
$reportData['propertyId'] = $property['id'];
$reportData['propertyName'] = $property['name'];
$reportData['propertyCountry'] = $property['country'];
$reportData['logo'] = $property['property_brand']['logoUrl'];
$reportData['date'] = $reportDateFormatted;
$reportData['propertyUserEmail'] = collect($property['property_user'])->where('user.email','<>', null)->pluck('user.email')->toArray();
$searchData = vwBookingEngineSearch::where('property_id', $property['id'])
->where('date', $reportDate)
->get()->toArray();
$this->info(date('Y-m-d H:i:s') . ' Property: ' . $reportData['propertyName']);
if (!empty($searchData)) {
$reportData['transaction']['search'] = collect($searchData)->count();
$reportData['transaction']['roomFound'] = collect($searchData)->where('status', 1)->count();
$reportData['transaction']['roomNotFound'] = collect($searchData)->where('status', 0)->count();
$reportData['transaction']['preBooking'] = collect($searchData)->where('status', 2)->count();
$reportData['transaction']['booking'] = collect($searchData)->where('status', 3)->count();
$countryCodes = collect($searchData)->groupBy('country_code')->keys()->toArray();
foreach ($countryCodes as $countryCode) {
$countryText = $countryCode;
$countryTextCheck = collect($countryList)->where('country_code', mb_strtoupper($countryCode))->first();
if (!empty($countryTextCheck)) {
$countryText = $countryTextCheck['name'];
}
$reportData['country'][$countryCode]['text'] = $countryText;
$reportData['country'][$countryCode]['search'] = collect($searchData)->where('country_code', $countryCode)->count();
$reportData['country'][$countryCode]['roomFound'] = collect($searchData)->where('country_code', $countryCode)->where('status', 1)->count();
$reportData['country'][$countryCode]['roomNotFound'] = collect($searchData)->where('country_code', $countryCode)->where('status', 0)->count();
$reportData['country'][$countryCode]['preBooking'] = collect($searchData)->where('country_code', $countryCode)->where('status', 2)->count();
$reportData['country'][$countryCode]['booking'] = collect($searchData)->where('country_code', $countryCode)->where('status', 3)->count();
}
$reportData['country'] = collect($reportData['country'])->sortByDesc('search')->toArray();
$languageCodes = collect($searchData)->groupBy('language_code')->keys()->toArray();
foreach ($languageCodes as $languageCode) {
$languageText = $languageCode;
$languageTextCheck = collect($languageList)->where('code', $languageCode)->first();
if (!empty($languageTextCheck)) {
$languageText = $languageTextCheck['name'];
}
$reportData['language'][$languageCode]['text'] = $languageText;
$reportData['language'][$languageCode]['search'] = collect($searchData)->where('language_code', $languageCode)->count();
$reportData['language'][$languageCode]['roomFound'] = collect($searchData)->where('language_code', $languageCode)->where('status', 1)->count();
$reportData['language'][$languageCode]['roomNotFound'] = collect($searchData)->where('language_code', $languageCode)->where('status', 0)->count();
$reportData['language'][$languageCode]['preBooking'] = collect($searchData)->where('language_code', $languageCode)->where('status', 2)->count();
$reportData['language'][$languageCode]['booking'] = collect($searchData)->where('language_code', $languageCode)->where('status', 3)->count();
}
$reportData['language'] = collect($reportData['language'])->sortByDesc('search')->toArray();
$occupancyCodes = collect($searchData)->groupBy('pax')->keys()->toArray();
foreach ($occupancyCodes as $occupancyCode) {
$reportData['occupancy'][$occupancyCode]['text'] = occupancyCodeFormatted($occupancyCode);
$reportData['occupancy'][$occupancyCode]['count'] = collect($searchData)->where('pax', $occupancyCode)->count();
}
$reportData['occupancy'] = collect($reportData['occupancy'])->sortByDesc('count')->toArray();
//Daily Intensity
$dailyIntensity = [];
foreach ($searchData as $data) {
$checkInDate = $data['checkin_date'];
$checkOutDate = $data['checkout_date'];
$dateDiff = Carbon::parse($data['checkout_date'])->diffInDays(Carbon::parse($data['checkin_date']));
for ($i = 0; $i < $dateDiff; $i++) {
$date = Carbon::parse($checkInDate)->addDays($i)->toDateString();
if (!isset($dailyIntensity[$date])) {
$dailyIntensity[$date]['text'] = Carbon::parse($date)->format('d.m.Y');
$dailyIntensity[$date]['search'] = 0;
$dailyIntensity[$date]['roomFound'] = 0;
$dailyIntensity[$date]['roomNotFound'] = 0;
$dailyIntensity[$date]['preBooking'] = 0;
$dailyIntensity[$date]['booking'] = 0;
}
$dailyIntensity[$date]['search']++;
$dailyIntensity[$date]['roomFound'] += $data['status'] == 1 ? 1 : 0;
$dailyIntensity[$date]['roomNotFound'] += $data['status'] == 0 ? 1 : 0;
$dailyIntensity[$date]['preBooking'] += $data['status'] == 2 ? 1 : 0;
$dailyIntensity[$date]['booking'] += $data['status'] == 3 ? 1 : 0;
}
}
ksort($dailyIntensity);
$reportData['dailyIntensity'] = $dailyIntensity;
//Daily Intensity
}
if (!empty($searchData)) {
$this->mailer->onQueue('bookingEngineSearchReportMail', new BookingEngineSearchReportMail($reportData));
$this->info(date('Y-m-d H:i:s') . ' Property: ' . $reportData['propertyName'] . ' - SENT MAIL');
}
}
$this->info(date('Y-m-d H:i:s') . ' FINISHED');
}
}

View File

@@ -0,0 +1,92 @@
<?php
namespace App\Console\Commands\Jobs;
use App\Models\Property;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Exception;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Artisan;
class DataFetch extends Command
{
protected $signature = 'cron:data-fetch';
public function __construct()
{
parent::__construct();
}
public function handle()
{
$propertyList = Property::whereIn('status', [1, 3])
->where('commission', '>', 1)
//->where('id', 1456)
->with('propertyContractUser')
->with('propertyExecutive.executiveType')
->with('propertyContact')
->with('propertyAdditionalInfos.propertyAdditionalInfoKey')
->with('propertyType')
->with('propertyStatus')
->get();
$propertyList = $propertyList ? $propertyList->toArray() : null;
$propertyListToExcel = [];
foreach ($propertyList as $property) {
$numberOfRooms = collect($property['property_additional_infos'])->where('additional_info_key_id',3)->first();
$numberOfRooms = $numberOfRooms['value'];
$propertyListToExcel[] = [
'contract_user' => $property['property_contract_user']['nameSurname'],
'executive_name_surname' => reset($property['property_executive'])['name_surname'],
'name' => $property['name'],
'phone' => $property['property_contact']['view_full_phone'],
'email' => $property['property_contact']['email'],
'executive_position' => reset($property['property_executive'])['executive_type']['name'],
'executive_phone' => reset($property['property_executive'])['view_full_phone'],
'executive_email' => reset($property['property_executive'])['email'],
'web' => $property['property_contact']['web'],
'address' => $property['property_contact']['address'],
'location' => null, //Bölge
'number_of_rooms' => $numberOfRooms,
'category' => $property['property_type']['name'],
'property_pms' => null,
'property_cm' => null,
'commission' => $property['commission'],
'commission_period' => $property['invoice_type'],
'contract_start' => Carbon::createFromTimestamp($property['created_at'])->format('d.m.Y'),
'contract_finish' => null,
'content' => null,
'dns' => null,
'ssl' => null,
'cm' => null,
'third_party' => null,
'golive' => Carbon::createFromTimestamp($property['created_at'])->format('d.m.Y'),
'training' => null,
'panel' => null,
'official_name' => $property['official_name'],
'tax_office' => $property['tax_office'],
'tax_number' => $property['tax_number'],
'tax_address' => $property['property_contact']['address'],
'status' => $property['property_status']['name'],
'id' => $property['id'],
];
}
$f = fopen("C:\www\api.extranetwork.com\storage/tmp.csv", "w");
foreach ($propertyListToExcel as $property) {
fputcsv($f, $property);
}
}
}

View File

@@ -0,0 +1,97 @@
<?php
namespace App\Console\Commands\Jobs;
use App\Core\Service\JobsService;
use Illuminate\Console\Command;
use Exception;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Artisan;
class MailJobs extends Command
{
/*
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'cron:mail-jobs';
/**
* The console command description.
*
* @var string
*/
protected $mailJobs =
[
"default",
"userCreateMail",
"UserForgotPassword",
"slackLog",
"newBookingMail",
"contactFormMail",
"manualPaymentMail",
"logMail",
"inventoryActionMail",
"bookingTicketMail",
"enwContactFormMail",
"trialFirstMail",
"trialSecondMail",
"cancelBookingMail",
"modifiedBookingMail",
"inventoryPdfLinkMail",
"dailyReportMail",
"bookingPaymentDataCode",
"bookingPropertyAddonUpdateMail",
"offerAcceptMail",
"offerPreConfirmCustomerMail",
"offerPreConfirmPropertyMail",
"bookingEngineSearchReportMail",
"channelManagerNotificationMail",
"bookingInvoiceUpdateMail",
"offerSendMail",
"dailyReportSalesMail",
"affiliateRequestMail",
"propertyProductOfferMail"
];
protected $description = 'Calls All Mail Jobs';
private $jobsService;
public function __construct(JobsService $jobsService)
{
parent::__construct();
$this->jobsService = $jobsService;
}
public function handle()
{
$mailJobsCriteria =
[
"whereIn" =>
[
["field" => "queue", "value" => $this->mailJobs]
],
"orderBy" =>
[
["field" => "id", "value" => "ASC"]
],
"take" => 20
];
$mailJobs = $this->jobsService->getJobsList($mailJobsCriteria, ["queue"]);
foreach ($mailJobs as $perJob) {
try {
Artisan::call("queue:work --queue=" . $perJob["queue"]." --tries=5");
} catch (Exception $e) {
$message = "Mail Job Fail --- Failed Mail : " . $perJob . " ErrorDetail : " . $e->getLine() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
continue;
}
sleep(1);
}
}
}

View File

@@ -0,0 +1,252 @@
<?php
namespace App\Console\Commands\Jobs;
use App\Exceptions\ApiErrorException;
use App\Models\ChannelManagerPropertyMapping;
use App\Models\CurrencyRates;
use App\Models\PropertyPriceComparison;
use App\Models\PropertyRoomRatePrice;
use App\Models\vwActiveProperty;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Exception;
class PriceComparisonService extends Command
{
protected $signature = 'cron:price-comparison-service';
protected $description = '';
private $bookingService;
public function __construct()
{
parent::__construct();
}
public function handle()
{
//$today = '2025-06-05';
$today = Carbon::now()->toDateString();
$today = Carbon::parse($today)->startOfWeek(Carbon::MONDAY);
$year = Carbon::parse($today)->format('Y');
$week = Carbon::parse($today)->isoWeek();
$daysCount = [1, 15, 45, 90];
$exchangeCurrency = 'EUR';
//'BookingEngine'
$comparisonChannels = ['Agoda.com', 'etstur.com', 'Booking.com'];
$exchangeRateUSD = CurrencyRates::where('currency_code', 'USD')->where('exc_currency_code', $exchangeCurrency)->orderBy('date', 'DESC')->first()->toArray();
$exchangeRateUSD = $exchangeRateUSD['rate'];
$competitorPriceAnalysisController = App::make('App\Http\Controllers\V1\CompetitorPriceAnalysisController');
$this->info(date('Y-m-d H:i:s') . ' START');
$queryWeekPrices = [];
$queryWeekPricesDaily = [];
$queryKeyHash = md5($year . '-' . $week);
$propertyList = vwActiveProperty::where('commission', '>', 1)
//->whereIn('id', [1433,1441,1551,1574])
->get()->toArray();
foreach ($propertyList as $property) {
try {
$channelManagerProperty = ChannelManagerPropertyMapping::where('channel_manager_id', 12)
->where('property_id', $property['id'])->first();
$channelManagerProperty = $channelManagerProperty ? $channelManagerProperty->toArray() : null;
$channelManagerPropertyId = $channelManagerProperty ? $channelManagerProperty['channel_manager_property_id'] : null;
$this->info(date('Y-m-d H:i:s') . ' ' . $property['id'] . ' - ' . $property['name']);
if (empty($channelManagerPropertyId)) {
$this->error(date('Y-m-d H:i:s') . ' ' . $property['name'] . ': channelManagerPropertyId!');
continue;
}
foreach ($daysCount as $day) {
//Booking Engine
$queryDate = Carbon::parse($today)->addDays($day)->toDateString();
//FIRST Trigger
$paramCompetitorPrice = ['date' => $queryDate, 'competitor_property_key' => $channelManagerPropertyId, 'currency' => $exchangeCurrency,];
$getPropertyCompetitorPrice = $competitorPriceAnalysisController->getPropertyCompetitorPrice($paramCompetitorPrice);
$this->info(date('Y-m-d H:i:s') . ' ' . $property['id'] . ' - ' . $queryDate);
sleep(1);
$bestPriceOfDay = 0;
$queryWeekPrices[$queryKeyHash][$property['id']]['BookingEngine'][$day] = [
'channel' => 'BookingEngine',
'date' => $queryDate,
'amount' => null,
'currency' => null
];
$propertyPrices = PropertyRoomRatePrice::where('property_id', $property['id'])
->where('channel_id', 5)
->where('stop_sell', 0)
->where('status', 1)
->where('amount', '<>', 0)
->where('amount', '<>', null)
->where('date', $queryDate)
->with('roomRateMapping.propertyRoomRate')
->get();
$propertyPrices = $propertyPrices ? $propertyPrices->toArray() : null;
if (empty($propertyPrices)) {
//continue;
}
$bestPrice = collect($propertyPrices)
->where('room_rate_mapping.property_room_rate.name', 'Best Available Rate')
->sortBy('amount')->first();
if (empty($bestPrice)) {
//continue;
} else {
if ($bestPrice['currency'] != $exchangeCurrency) {
$exchangeRate = CurrencyRates::where('currency_code', $bestPrice['currency'])
->where('exc_currency_code', $exchangeCurrency)
->orderBy('date', 'DESC')->first()->toArray();
$exchangeRate = $exchangeRate['rate'];
$bestPrice['amount'] = $bestPrice['amount'] * $exchangeRate;
}
$bestPrice['amount'] = moneyDoubleFormatDecimal($bestPrice['amount']);
$queryWeekPrices[$queryKeyHash][$property['id']]['BookingEngine'][$day] = [
'channel' => 'BookingEngine',
'date' => $queryDate,
'amount' => $bestPrice['amount'],
'currency' => $exchangeCurrency,
];
$queryWeekPricesDaily[$queryKeyHash][$property['id']][$day] = $bestPrice['amount'];
}
//Booking Engine
//OTHER Channels
$paramCompetitorPrice = ['date' => $queryDate, 'competitor_property_key' => $channelManagerPropertyId, 'currency' => $exchangeCurrency];
$getPropertyCompetitorPrice = $competitorPriceAnalysisController->getPropertyCompetitorPrice($paramCompetitorPrice);
foreach ($comparisonChannels as $comparisonChannel) {
$queryWeekPrices[$queryKeyHash][$property['id']][$comparisonChannel][$day] = [
'channel' => $comparisonChannel,
'date' => $queryDate,
'amount' => null,
'currency' => null
];
if(!isset($queryWeekPricesDaily[$queryKeyHash][$property['id']][$day])) {
$queryWeekPricesDaily[$queryKeyHash][$property['id']][$day] = $queryWeekPrices[$queryKeyHash][$property['id']][$comparisonChannel][$day]['amount'];
}
if ($getPropertyCompetitorPrice['status'] && !empty($getPropertyCompetitorPrice['data']['all'])) {
$getPropertyCompetitorPriceChannel = $getPropertyCompetitorPrice['data']['all'];
$getPropertyCompetitorPriceChannelCheck = collect($getPropertyCompetitorPriceChannel)->where('provider', $comparisonChannel)->first();
if ($getPropertyCompetitorPriceChannelCheck) {
$queryWeekPrices[$queryKeyHash][$property['id']][$comparisonChannel][$day]['amount'] = moneyDoubleFormatDecimal($getPropertyCompetitorPriceChannelCheck['amount'] * $exchangeRateUSD);
$queryWeekPrices[$queryKeyHash][$property['id']][$comparisonChannel][$day]['currency'] = 'EUR';
//BestPriceCheck
if(empty($queryWeekPricesDaily[$queryKeyHash][$property['id']][$day])) {
$queryWeekPricesDaily[$queryKeyHash][$property['id']][$day] = $queryWeekPrices[$queryKeyHash][$property['id']][$comparisonChannel][$day]['amount'];
}elseif ($queryWeekPrices[$queryKeyHash][$property['id']][$comparisonChannel][$day]['amount'] < $queryWeekPricesDaily[$queryKeyHash][$property['id']][$day]) {
$queryWeekPricesDaily[$queryKeyHash][$property['id']][$day] = $queryWeekPrices[$queryKeyHash][$property['id']][$comparisonChannel][$day]['amount'];
}
}
}
}
}
//dd($queryWeekPrices[$queryKeyHash][$property['id']],$queryWeekPricesDaily[$queryKeyHash][$property['id']]);
foreach ($queryWeekPrices[$queryKeyHash][$property['id']] as $channelKey => $channelDays) {
foreach ($channelDays as $channelDayKey => $channelDay) {
//dd($channelDay,$queryWeekPricesDaily[$queryKeyHash][$property['id']][$channelDayKey]);
if ($queryWeekPricesDaily[$queryKeyHash][$property['id']][$channelDayKey] == $channelDay['amount'] && !is_null($channelDay['amount'])) {
$queryWeekPrices[$queryKeyHash][$property['id']][$channelKey][$channelDayKey]['bestPrice'] = true;
} else {
$queryWeekPrices[$queryKeyHash][$property['id']][$channelKey][$channelDayKey]['bestPrice'] = false;
}
}
}
$this->info(date('Y-m-d H:i:s') . ' ' . $property['id'] . ' - ' . $property['name'] . ' OK!');
$propertyComparisonPrice = [
'property_id' => $property['id'],
'week_key' => $queryKeyHash,
'year' => $year,
'week' => $week,
'date' => $today,
'data' => json_encode($queryWeekPrices[$queryKeyHash][$property['id']]),
'status' => 1,
'created_at' => Carbon::now()->unix(),
'updated_at' => Carbon::now()->unix(),
];
$propertyPriceComparisonCheck = PropertyPriceComparison::where('week_key', $queryKeyHash)->where('property_id', $property['id'])->first();
if ($propertyPriceComparisonCheck) {
$propertyPriceComparisonCheck = $propertyPriceComparisonCheck->toArray();
$propertyPriceComparison = PropertyPriceComparison::where('id', $propertyPriceComparisonCheck['id'])->update($propertyComparisonPrice);
} else {
$propertyPriceComparison = PropertyPriceComparison::insert($propertyComparisonPrice);
}
unset($queryWeekPrices[$queryKeyHash]);
} catch (ApiErrorException|Exception $e) {
$this->error(date('Y-m-d H:i:s') . ' ERROR: L: ' . $e->getLine() . ' - ' . $e->getMessage());
}
}
$this->info(date('Y-m-d H:i:s') . ' FINISHED');
}
}

View File

@@ -0,0 +1,113 @@
<?php
namespace App\Console\Commands\Jobs;
use App\Core\Mail\PropertyCatalogMail;
use App\Core\Service\PropertyService;
use App\Exceptions\ApiErrorException;
use App\Models\Country;
use App\Models\Language;
use App\Models\vwBookingEngineSearch;
use Barryvdh\DomPDF\PDF;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
class PropertyCatalogService extends Command
{
protected $signature = 'cron:property-catalog-service {property_id} {language} {--email=}';
protected $description = '';
private $propertyService;
public function __construct(
PDF $pdf,
Mailer $mailer,
PropertyService $propertyService
)
{
parent::__construct();
$this->pdf = $pdf;
$this->mailer = $mailer;
$this->propertyService = $propertyService;
}
public function handle()
{
$this->info(date('Y-m-d H:i:s') . ' START');
$pdfDataRequest = [
'property_id' => $this->argument('property_id'),
'locale' => $this->argument('language')
];
$pdfContentService = App::make('App\Core\Service\PdfContentService');
$factSheetDataResponse = $pdfContentService->factSheetData($pdfDataRequest);
if ($factSheetDataResponse['status'] != 'success') {
throw new Exception($factSheetDataResponse['message']);
}
$pageContent = $factSheetDataResponse['data'];
$pdfLanguage = $pdfDataRequest['locale'];
$this->info(date('Y-m-d H:i:s') . ' PDF');
app('translator')->setLocale($pdfLanguage);
$pdfService = $this->pdf->loadView('pdf.propertyCatalog', compact('pageContent'), [], 'UTF8');
$pdfService->setOptions([
'dpi' => 100,
'isHtml5ParserEnabled' => true,
'isRemoteEnabled' => true,
'chroot', base_path(),
'enable_html5_parser' => true,
'enable_css_float' => true
]);
$hotelName = Str::slug($pageContent['name'], '_', 'en') . '_' . $pdfLanguage;
$pathStorage = Config::get('app.fileSystemDriver') . '/property-catalog/' . $hotelName . '.pdf';
file_put_contents($pathStorage, $pdfService->output());
if ($this->option('email')) {
$this->info(date('Y-m-d H:i:s') . ' E-Mail');
$languageDetail = Language::where('code', $pdfLanguage)->first();
$languageDetail = $languageDetail ? $languageDetail->toArray() : null;
$mailParams = [
'email' => $this->option('email'),
'catalogUrl' => Config::get('app.imageUrl') . '/property-catalog/' . $hotelName . '.pdf',
'propertyName' => $pageContent['name'],
'language' => $pdfLanguage,
'languageText' => __($languageDetail['language_key'],[],'tr'),
'pathStorage' => $pathStorage
];
$this->mailer->send('emails.propertyCatalogMail', ['mailParams' => $mailParams], function ($message) use ($mailParams) {
$message->to($mailParams['email'], 'Extranetwork Property Katalog')
->bcc(Config::get('app.logMailAddress'))
->subject($mailParams['propertyName'] . ' Catalog - ' . $mailParams['languageText'])
//->attach($mailParams['pathStorage'])
->from(Config::get('app.mailSenderAddress'), 'Extranetwork');
});
}
$this->info(date('Y-m-d H:i:s') . ' FINISHED');
}
}

View File

@@ -0,0 +1,117 @@
<?php
namespace App\Console\Commands\Jobs;
use App\Exceptions\ApiErrorException;
use App\Models\ChannelManagerPropertyMapping;
use App\Models\CurrencyRates;
use App\Models\Property;
use App\Models\PropertyPriceComparison;
use App\Models\PropertyRoomRatePrice;
use App\Models\vwActiveProperty;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Exception;
class PropertyInvoiceService extends Command
{
protected $signature = 'cron:property-invoice-service';
protected $description = '';
private $propertyInvoiceService;
public function __construct()
{
parent::__construct();
}
public function handle()
{
$propertyInvoiceService = App::make('App\Core\Service\PropertyInvoiceService');
//BULK
/*$firstAllOfYear = '2022-01-01';
$lastAllOfYear = '2025-10-01';
$startDayOfYear = Carbon::parse($firstAllOfYear)->firstOfMonth()->toDateString();
$lastDayOfYear = Carbon::parse($lastAllOfYear)->firstOfMonth()->toDateString();
$diffInPeriod = Carbon::parse($startDayOfYear)->diffInMonths(Carbon::parse($lastDayOfYear));
$periodList = [];
for ($i = 0; $i < $diffInPeriod; $i++) {
$periodList[] = Carbon::parse($firstAllOfYear)->addMonths($i)->format('Y-m');
}*/
//$periodList[] = '2025-09';
//BULK
//$invoiceWithPeriod = $propertyInvoiceService->invoiceWithPeriod(623, '2025-10');
//dd($invoiceWithPeriod);
//$periodList = ['2025-09'];
//$lastOfMonth = '2025-10-30';
//$dayOfMonth = '2025-10-30';
//$lastOfMonth = Carbon::now()->lastOfMonth()->format('Y-m-d');
//$dayOfMonth = Carbon::now()->format('Y-m-d');
//if ($lastOfMonth != $dayOfMonth) {
//$this->alert(date('Y-m-d H:i:s') . ' : ' . $lastOfMonth . ' - ' . $dayOfMonth);
//return false;
//}
//$period = Carbon::parse($dayOfMonth)->lastOfMonth()->format('Y-m');
//$periodList = [$period];
$year = Carbon::now()->year;
$currentMonth = Carbon::now()->month;
$periodList = [];
for ($month = $currentMonth; $month <= 12; $month++) {
$periodList[] = Carbon::create($year, $month, 1)->format('Y-m');
}
$this->info(date('Y-m-d H:i:s') . ' START');
$propertyList = Property::where('commission', '>', 1)
->whereIn('status', [1,3])
//->whereIn('id', [1810])
->get()->toArray();
foreach ($periodList as $period) {
$this->alert('PERIOD: ' . $period);
foreach ($propertyList as $property) {
try {
$invoiceWithPeriod = $propertyInvoiceService->invoiceWithPeriod($property['id'], $period);
if ($invoiceWithPeriod['status'] == 'success') {
$this->info(date('Y-m-d H:i:s') . ': ' . $period . ' ' . $property['id'] . ' - ' . $property['name'] . ' : ' . $period . ' - ' . $invoiceWithPeriod['data']['total'] . ' ' . $invoiceWithPeriod['data']['currency']);
} else {
$this->error(date('Y-m-d H:i:s') . ': ' . $period . ' ' . $property['id'] . ' - ' . $invoiceWithPeriod['message']);
}
} catch (ApiErrorException | Exception $e) {
$this->error(date('Y-m-d H:i:s') . ' ERROR: L: ' . $e->getLine() . ' - ' . $e->getMessage() . ' - ' . $property['id'] . ' - ' . $property['name']);
}
}
}
$this->info(date('Y-m-d H:i:s') . ' FINISHED');
}
}

View File

@@ -0,0 +1,124 @@
<?php
namespace App\Console\Commands\Jobs;
use App\Exceptions\ApiErrorException;
use App\Models\ChannelManagerPropertyMapping;
use App\Models\CurrencyRates;
use App\Models\Property;
use App\Models\PropertyPriceComparison;
use App\Models\PropertyRoomRatePrice;
use App\Models\vwActiveProperty;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Exception;
class PropertySummaryService extends Command
{
protected $signature = 'cron:property-summary-service';
protected $description = '';
private $propertySummaryService;
public function __construct()
{
parent::__construct();
}
public function handle()
{
$propertySummaryService = App::make('App\Core\Service\PropertySummaryService');
//BULK
/*$firstAllOfYear = '2022-01-01';
$lastAllOfYear = '2027-01-01';
$startDayOfYear = Carbon::parse($firstAllOfYear)->firstOfMonth()->toDateString();
$lastDayOfYear = Carbon::parse($lastAllOfYear)->firstOfMonth()->toDateString();
$diffInPeriod = Carbon::parse($startDayOfYear)->diffInMonths(Carbon::parse($lastDayOfYear));
$periodList = [];
for ($i = 0; $i < $diffInPeriod; $i++) {
$periodList[] = Carbon::parse($firstAllOfYear)->addMonths($i)->format('Y-m');
}*/
//$periodList[] = '2025-09';
//BULK
//$invoiceWithPeriod = $propertyInvoiceService->invoiceWithPeriod(623, '2025-10');
//dd($invoiceWithPeriod);
//$periodList = ['2025-09'];
//$lastOfMonth = '2025-10-30';
//$dayOfMonth = '2025-10-30';
//$lastOfMonth = Carbon::now()->lastOfMonth()->format('Y-m-d');
//$dayOfMonth = Carbon::now()->format('Y-m-d');
//if ($lastOfMonth != $dayOfMonth) {
//$this->alert(date('Y-m-d H:i:s') . ' : ' . $lastOfMonth . ' - ' . $dayOfMonth);
//return false;
//}
//$period = Carbon::parse($dayOfMonth)->lastOfMonth()->format('Y-m');
//$periodList = [$period];
$year = Carbon::now()->year;
$currentMonth = Carbon::now()->month;
$periodList = [];
for ($month = $currentMonth; $month <= 12; $month++) {
$periodList[] = Carbon::create($year, $month, 1)->format('Y-m');
}
//$periodList = ['2025-03'];
$this->info(date('Y-m-d H:i:s') . ' START');
$propertyList = Property::where('commission', '>', 1)
->where('status', 1)
//->whereIn('id', [71])
->get()->toArray();
$types[1] = 'Checkout';
$types[2] = 'Transaction';
foreach ($periodList as $period) {
$this->alert('PERIOD: ' . $period);
foreach ($propertyList as $property) {
try {
foreach ($types as $typeCode => $type) {
$invoiceWithPeriod = $propertySummaryService->summaryWithPeriod($property['id'], $period, $typeCode);
if ($invoiceWithPeriod['status'] == 'success') {
$this->info(date('Y-m-d H:i:s') . ': ' . $period . ' ' . $property['id'] . ' - ' . $property['name'] . ' : ' . $type . ' : ' . $period . ' - ' . $invoiceWithPeriod['data']['total'] . ' ' . $invoiceWithPeriod['data']['currency']);
} else {
$this->error(date('Y-m-d H:i:s') . ': ' . $period . ' ' . $property['id'] . ' - ' . $invoiceWithPeriod['message']);
}
}
} catch (ApiErrorException | Exception $e) {
$this->error(date('Y-m-d H:i:s') . ' ERROR: L: ' . $e->getLine() . ' - ' . $e->getMessage() . ' - ' . $property['id'] . ' - ' . $property['name']);
}
}
}
$this->info(date('Y-m-d H:i:s') . ' FINISHED');
}
}

View File

@@ -0,0 +1,386 @@
<?php
namespace App\Console\Commands\Jobs;
use App\Core\Mail\DailyReportMail;
use App\Core\Mail\TrialFirstMail;
use App\Core\Mail\TrialSecondMail;
use App\Core\Service\CurrencyService;
use App\Core\Service\PropertyService;
use App\Exceptions\ApiErrorException;
use App\Models\PropertyInvoice;
use App\Models\vwActiveProperty;
use App\Models\vwBookingSummary;
use App\Models\vwBookingSummaryAll;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class SummaryReportMail extends Command
{
protected $signature = 'cron:summary-report-mail';
protected $description = '';
private $propertyService;
public function __construct(
Mailer $mailer,
PropertyService $propertyService,
CurrencyService $currencyService
)
{
parent::__construct();
$this->mailer = $mailer;
$this->propertyService = $propertyService;
$this->currencyService = $currencyService;
}
public function handle()
{
$this->info(date('Y-m-d H:i:s') . ' START');
$today = Carbon::now()->subDay()->toDateString();
$report['daily']['data'] = [];
$report['daily']['title'] = 'Daily Report';
$report['daily']['period'] = Carbon::parse($today)->format('d.m.Y');
$daily = vwBookingSummaryAll::where('time', '>', Carbon::parse($today)->toDateString())
->where('time', '<', Carbon::parse($today)->addDay()->toDateString())
->where('commission', '>', 0)
->get()->toArray();
if ($daily) {
$dataCollect = collect($daily);
$dataCollect = $dataCollect->filter(function ($item) {
if ($item['property_id'] == 362) {
//Exclude Commission - Barın Hotel, 34 Hotelbeds, 103 World2Meet
if (!in_array($item['channel_id'], [34, 103])) {
return $item;
}
} else if ($item['property_id'] == 712) {
//Exclude Commission - G Hotels Skopje
if (!in_array($item['id'], [18122, 18091, 18090, 18089, 18088, 18087, 18086])) {
return $item;
}
} else {
return $item;
}
});
$dataCollectGroup = $dataCollect->groupBy('currency_code')->toArray();
foreach ($dataCollectGroup as $currencyCode => $currencyGroup) {
$report['daily']['data'][$currencyCode]['count'] = count($currencyGroup);
$report['daily']['data'][$currencyCode]['total'] = array_sum(pickItemFromArray('total', $currencyGroup));
$report['daily']['data'][$currencyCode]['commission'] = array_sum(pickItemFromArray('commission', $currencyGroup));
}
$report['daily']['summary'] = ['count' => 0, 'total' => 0, 'commission' => 0];
foreach ($report['daily']['data'] as $currentCurrency => $dailyData) {
$lastExchangeRate = $this->currencyService->lastExchangeRate($currentCurrency, 'EUR');
$report['daily']['summary']['count'] += $dailyData['count'];
$report['daily']['summary']['total'] += $dailyData['total'] * $lastExchangeRate['data'];
$report['daily']['summary']['commission'] += $dailyData['commission'] * $lastExchangeRate['data'];
}
}
$report['monthly']['data'] = [];
$report['monthly']['title'] = 'Monthly Report';
$report['monthly']['period'] = Carbon::parse($today)->firstOfMonth()->format('m.Y');
$monthly = vwBookingSummaryAll::where('time', '>', Carbon::parse($today)->firstOfMonth()->toDateString())
->where('time', '<', Carbon::parse($today)->addMonth()->firstOfMonth()->toDateString())
->where('commission', '>', 0)
->get()->toArray();
if ($monthly) {
$dataCollect = collect($monthly);
$dataCollect = $dataCollect->filter(function ($item) {
if ($item['property_id'] == 362) {
//Exclude Commission - Barın Hotel, 34 Hotelbeds, 103 World2Meet
if (!in_array($item['channel_id'], [34, 103])) {
return $item;
}
} else if ($item['property_id'] == 712) {
//Exclude Commission - G Hotels Skopje
if (!in_array($item['id'], [18122, 18091, 18090, 18089, 18088, 18087, 18086])) {
return $item;
}
} else {
return $item;
}
});
$dataCollectGroup = $dataCollect->groupBy('currency_code')->toArray();
foreach ($dataCollectGroup as $currencyCode => $currencyGroup) {
$report['monthly']['data'][$currencyCode]['count'] = count($currencyGroup);
$report['monthly']['data'][$currencyCode]['total'] = array_sum(pickItemFromArray('total', $currencyGroup));
$report['monthly']['data'][$currencyCode]['commission'] = array_sum(pickItemFromArray('commission', $currencyGroup));
}
$report['monthly']['summary'] = ['count' => 0, 'total' => 0, 'commission' => 0];
foreach ($report['monthly']['data'] as $currentCurrency => $dailyData) {
$lastExchangeRate = $this->currencyService->lastExchangeRate($currentCurrency, 'EUR');
$report['monthly']['summary']['count'] += $dailyData['count'];
$report['monthly']['summary']['total'] += $dailyData['total'] * $lastExchangeRate['data'];
$report['monthly']['summary']['commission'] += $dailyData['commission'] * $lastExchangeRate['data'];
}
//summaryCheckout
$monthlyCheckout = vwBookingSummaryAll::where('checkout_period', Carbon::parse($today)->firstOfMonth()->format('Y-m'))
->where('commission', '>', 0)
->get()->toArray();
$dataCollect = collect($monthlyCheckout);
$dataCollect = $dataCollect->filter(function ($item) {
if ($item['property_id'] == 362) {
//Exclude Commission - Barın Hotel, 34 Hotelbeds, 103 World2Meet
if (!in_array($item['channel_id'], [34, 103])) {
return $item;
}
} else if ($item['property_id'] == 712) {
//Exclude Commission - G Hotels Skopje
if (!in_array($item['id'], [18122, 18091, 18090, 18089, 18088, 18087, 18086])) {
return $item;
}
} else {
return $item;
}
});
$dataCollectGroup = $dataCollect->groupBy('currency_code')->toArray();
foreach ($dataCollectGroup as $currencyCode => $currencyGroup) {
$report['monthly']['summaryCheckoutData'][$currencyCode]['count'] = count($currencyGroup);
$report['monthly']['summaryCheckoutData'][$currencyCode]['total'] = array_sum(pickItemFromArray('total', $currencyGroup));
$report['monthly']['summaryCheckoutData'][$currencyCode]['commission'] = array_sum(pickItemFromArray('commission', $currencyGroup));
}
$report['monthly']['summaryCheckout'] = ['count' => 0, 'total' => 0, 'commission' => 0];
foreach ($report['monthly']['summaryCheckoutData'] as $currentCurrency => $dailyData) {
$lastExchangeRate = $this->currencyService->lastExchangeRate($currentCurrency, 'EUR');
$report['monthly']['summaryCheckout']['count'] += $dailyData['count'];
$report['monthly']['summaryCheckout']['total'] += $dailyData['total'] * $lastExchangeRate['data'];
$report['monthly']['summaryCheckout']['commission'] += $dailyData['commission'] * $lastExchangeRate['data'];
}
$monthlySummary = [];
$annuallyMonths = [];
for ($i = 0; $i < 12; $i++) {
$annuallyMonths[] = Carbon::parse($today)->firstOfYear()->addMonths($i)->format('Y-m');
}
$vwBookingSummaryTransaction = vwBookingSummaryAll::whereIn('transaction_period',$annuallyMonths)
->where('commission', '>', 0)
->get()->toArray();
$vwBookingSummaryCheckout = vwBookingSummaryAll::whereIn('checkout_period',$annuallyMonths)
->where('commission', '>', 0)
->get()->toArray();
$vwBookingSummaryTransactionGrouped = collect($vwBookingSummaryTransaction)->groupBy('transaction_period')->toArray();
$vwBookingSummaryCheckoutGrouped = collect($vwBookingSummaryCheckout)->groupBy('checkout_period')->toArray();
$monthlySummary['month'] = [];
foreach ($annuallyMonths as $annuallyMonth) {
//$annuallyMonth = Carbon::parse($annuallyMonth)->format('Y-m');
$monthlySummary['month'][$annuallyMonth] = $annuallyMonth;
$monthlySummary['transaction'][$annuallyMonth]['count'] = 0;
$monthlySummary['transaction'][$annuallyMonth]['total'] = 0;
$monthlySummary['transaction'][$annuallyMonth]['commission'] = 0;
if(isset($vwBookingSummaryTransactionGrouped[$annuallyMonth])) {
$dataCollectGroupCurrency = collect($vwBookingSummaryTransactionGrouped[$annuallyMonth])->groupBy('currency_code')->toArray();
foreach ($dataCollectGroupCurrency as $currencyCode => $currencyGroup) {
$lastExchangeRate = $this->currencyService->lastExchangeRate($currencyCode, 'EUR');
$monthlySummary['transaction'][$annuallyMonth]['count'] += collect($currencyGroup)->count();
$monthlySummary['transaction'][$annuallyMonth]['total'] += collect($currencyGroup)->sum('total') * $lastExchangeRate['data'];
$monthlySummary['transaction'][$annuallyMonth]['commission'] += collect($currencyGroup)->sum('commission') * $lastExchangeRate['data'];
}
}
$monthlySummary['checkout'][$annuallyMonth]['count'] = 0;
$monthlySummary['checkout'][$annuallyMonth]['total'] = 0;
$monthlySummary['checkout'][$annuallyMonth]['commission'] = 0;
if(isset($vwBookingSummaryCheckoutGrouped[$annuallyMonth])) {
$dataCollectGroupCurrency = collect($vwBookingSummaryCheckoutGrouped[$annuallyMonth])->groupBy('currency_code')->toArray();
foreach ($dataCollectGroupCurrency as $currencyCode => $currencyGroup) {
$lastExchangeRate = $this->currencyService->lastExchangeRate($currencyCode, 'EUR');
$monthlySummary['checkout'][$annuallyMonth]['count'] += collect($currencyGroup)->count();
$monthlySummary['checkout'][$annuallyMonth]['total'] += collect($currencyGroup)->sum('total') * $lastExchangeRate['data'];
$monthlySummary['checkout'][$annuallyMonth]['commission'] += collect($currencyGroup)->sum('commission') * $lastExchangeRate['data'];
}
}
}
$report['monthlySummary'] = $monthlySummary;
}
$report['annually']['data'] = [];
$report['annually']['title'] = 'Annually Report';
$report['annually']['period'] = Carbon::parse($today)->firstOfYear()->format('Y');
$annually = vwBookingSummaryAll::where('time', '>', Carbon::parse($today)->firstOfYear()->toDateString())
->where('time', '<', Carbon::parse($today)->addYear()->firstOfYear()->toDateString())
->where('commission', '>', 0)
->get()->toArray();
if ($annually) {
$dataCollect = collect($annually);
$dataCollect = $dataCollect->filter(function ($item) {
if ($item['property_id'] == 362) {
//Exclude Commission - Barın Hotel, 34 Hotelbeds, 103 World2Meet
if (!in_array($item['channel_id'], [34, 103])) {
return $item;
}
} else if ($item['property_id'] == 712) {
//Exclude Commission - G Hotels Skopje
if (!in_array($item['id'], [18122, 18091, 18090, 18089, 18088, 18087, 18086])) {
return $item;
}
} else {
return $item;
}
});
$dataCollectGroup = $dataCollect->groupBy('currency_code')->toArray();
foreach ($dataCollectGroup as $currencyCode => $currencyGroup) {
$report['annually']['data'][$currencyCode]['count'] = count($currencyGroup);
$report['annually']['data'][$currencyCode]['total'] = array_sum(pickItemFromArray('total', $currencyGroup));
$report['annually']['data'][$currencyCode]['commission'] = array_sum(pickItemFromArray('commission', $currencyGroup));
}
$report['annually']['summary'] = ['count' => 0, 'total' => 0, 'commission' => 0];
foreach ($report['annually']['data'] as $currentCurrency => $dailyData) {
$lastExchangeRate = $this->currencyService->lastExchangeRate($currentCurrency, 'EUR');
$report['annually']['summary']['count'] += $dailyData['count'];
$report['annually']['summary']['total'] += $dailyData['total'] * $lastExchangeRate['data'];
$report['annually']['summary']['commission'] += $dailyData['commission'] * $lastExchangeRate['data'];
}
//summaryCheckout Annually
$annuallyCheckout = vwBookingSummaryAll::where('checkout_date', '>=', Carbon::parse($today)->firstOfYear()->format('Y-m-d'))
->where('checkout_date', '<=', Carbon::parse($today)->endOfYear()->format('Y-m-d'))
->where('commission', '>', 0)
->get()->toArray();
$dataCollect = collect($annuallyCheckout);
$dataCollect = $dataCollect->filter(function ($item) {
if ($item['property_id'] == 362) {
//Exclude Commission - Barın Hotel, 34 Hotelbeds, 103 World2Meet
if (!in_array($item['channel_id'], [34, 103])) {
return $item;
}
} else if ($item['property_id'] == 712) {
//Exclude Commission - G Hotels Skopje
if (!in_array($item['id'], [18122, 18091, 18090, 18089, 18088, 18087, 18086])) {
return $item;
}
} else {
return $item;
}
});
$dataCollectGroup = $dataCollect->groupBy('currency_code')->toArray();
foreach ($dataCollectGroup as $currencyCode => $currencyGroup) {
$report['annually']['summaryCheckoutData'][$currencyCode]['count'] = count($currencyGroup);
$report['annually']['summaryCheckoutData'][$currencyCode]['total'] = array_sum(pickItemFromArray('total', $currencyGroup));
$report['annually']['summaryCheckoutData'][$currencyCode]['commission'] = array_sum(pickItemFromArray('commission', $currencyGroup));
}
$report['annually']['summaryCheckout'] = ['count' => 0, 'total' => 0, 'commission' => 0];
foreach ($report['annually']['summaryCheckoutData'] as $currentCurrency => $dailyData) {
$lastExchangeRate = $this->currencyService->lastExchangeRate($currentCurrency, 'EUR');
$report['annually']['summaryCheckout']['count'] += $dailyData['count'];
$report['annually']['summaryCheckout']['total'] += $dailyData['total'] * $lastExchangeRate['data'];
$report['annually']['summaryCheckout']['commission'] += $dailyData['commission'] * $lastExchangeRate['data'];
}
}
//Hotel LIST
$vwActivePropertySummary = [];
$vwActiveProperty = vwActiveProperty::where('commission', '>', 1)->orderByDesc('id')->get()->toArray();
$vwActivePropertySummary['count'] = count($vwActiveProperty);
$vwActivePropertySummary['groupByMonth'] = collect($vwActiveProperty)->sortByDesc('month')->groupBy('month')->toArray();
$vwActivePropertySummary['lastMonth'] = collect($vwActivePropertySummary['groupByMonth'])->take(12)->toArray();
if ($vwActivePropertySummary['lastMonth']) {
foreach ($vwActivePropertySummary['lastMonth'] as $lastMonthKey => $lastMonth) {
$vwActivePropertySummary['lastMonth'][$lastMonthKey] = collect($vwActivePropertySummary['lastMonth'][$lastMonthKey])->sortByDesc('id')->toArray();
if ($vwActivePropertySummary['lastMonth'][$lastMonthKey]) {
$vwActivePropertySummary['lastMonth'][$lastMonthKey] = array_values($vwActivePropertySummary['lastMonth'][$lastMonthKey]);
}
}
}
//Hotel LIST
$report['activeProperty'] = $vwActivePropertySummary;
//Comparative Summary Data
//Carbon::setLocale('tr');
for ($month = 1; $month <= 12; $month++) {
$months[$month] = Carbon::create(null, $month, 1)->translatedFormat('F');
}
$report['comparative']['monthList'] = $months;
$currentYear = Carbon::parse($today)->firstOfYear()->format('Y');
$lastYear = Carbon::parse($today)->subYear()->firstOfYear()->format('Y');
$report['comparative']['yearList'][] = $lastYear;
$report['comparative']['yearList'][] = $currentYear;
$periodList = [];
foreach ([$currentYear,$lastYear] as $periodYear) {
for ($month = 1; $month <= 12; $month++) {
$periodList[] = $periodYear . '-' . str_pad((integer)$month, 2, '0', STR_PAD_LEFT);
}
}
$propertyInvoice = PropertyInvoice::where('status',1)->whereIn('period', $periodList);
$propertyInvoice = $propertyInvoice ? $propertyInvoice->get()->toArray() : [];
foreach ($propertyInvoice as $invoice) {
$periodYear = Carbon::parse($invoice['period'])->format('Y');
$periodMonth = (int)Carbon::parse($invoice['period'])->format('m');
if(!isset($report['comparative']['data'][$periodYear][$periodMonth])) {
$report['comparative']['data'][$periodYear][$periodMonth] = 0;
}
$report['comparative']['data'][$periodYear][$periodMonth]+=$invoice['total'];
}
$comparativeDiff = [];
foreach ($months as $monthKey => $month) {
$comparativeDiff[$monthKey]['amount'] = $report['comparative']['data'][$currentYear][$monthKey] - $report['comparative']['data'][$lastYear][$monthKey];
}
$report['comparative']['diff'] = $comparativeDiff;
//Comparative Summary Data
//$json = json_encode($report, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
//file_put_contents(resource_path('data/data.json'), $json);
//die();
$this->mailer->onQueue('dailyReportMail', new DailyReportMail($report));
$this->info(date('Y-m-d H:i:s') . ' FINISHED');
}
}

View File

@@ -0,0 +1,310 @@
<?php
namespace App\Console\Commands\Jobs;
use App\Core\Mail\DailyReportMail;
use App\Core\Mail\DailyReportMailSales;
use App\Core\Mail\TrialFirstMail;
use App\Core\Mail\TrialSecondMail;
use App\Core\Service\CurrencyService;
use App\Core\Service\PropertyService;
use App\Core\Service\UserService;
use App\Exceptions\ApiErrorException;
use App\Models\vwActiveProperty;
use App\Models\vwBookingSummary;
use App\Models\vwBookingSummaryAll;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class SummaryReportMailSales extends Command
{
protected $signature = 'cron:summary-report-mail-sales';
protected $description = '';
private $propertyService;
public function __construct(
Mailer $mailer,
PropertyService $propertyService,
CurrencyService $currencyService,
UserService $userService
)
{
parent::__construct();
$this->mailer = $mailer;
$this->propertyService = $propertyService;
$this->currencyService = $currencyService;
$this->userService = $userService;
}
public function reportCalculate($userId, $contractUserProperty, $type)
{
$today = Carbon::now()->subDay()->toDateString();
$report = ['data' => null, 'summary' => null];
switch ($type) {
case 'daily':
$vwBookingSummaryAll = vwBookingSummaryAll::where('time', '>', Carbon::parse($today)->toDateString())
->where('time', '<', Carbon::parse($today)->addDay()->toDateString())
->where('commission', '>', 0)
->where('contract_user_id', $userId)
->whereIn('property_id', $contractUserProperty)
->get()->toArray();
break;
case 'monthly':
$monthlySummary = [];
$annuallyMonths = [];
for ($i = 0; $i < 12; $i++) {
$annuallyMonths[] = Carbon::parse($today)->firstOfYear()->addMonths($i)->format('Y-m');
}
$vwBookingSummaryAll = vwBookingSummaryAll::whereIn('transaction_period', [Carbon::parse($today)->firstOfMonth()->format('Y-m')])
->where('commission', '>', 0)
->where('contract_user_id', $userId)
->whereIn('property_id', $contractUserProperty)
->get()->toArray();
$vwBookingSummaryTransaction = vwBookingSummaryAll::whereIn('transaction_period', $annuallyMonths)
->where('commission', '>', 0)
->where('contract_user_id', $userId)
->whereIn('property_id', $contractUserProperty)
->get()->toArray();
$vwBookingSummaryCheckout = vwBookingSummaryAll::whereIn('checkout_period', $annuallyMonths)
->where('commission', '>', 0)
->where('contract_user_id', $userId)
->whereIn('property_id', $contractUserProperty)
->get()->toArray();
$vwBookingSummaryTransactionGrouped = collect($vwBookingSummaryTransaction)->groupBy('transaction_period')->toArray();
$vwBookingSummaryCheckoutGrouped = collect($vwBookingSummaryCheckout)->groupBy('checkout_period')->toArray();
$monthlySummary['month'] = [];
foreach ($annuallyMonths as $annuallyMonth) {
$annuallyMonth = Carbon::parse($annuallyMonth)->format('Y-m');
$monthlySummary['month'][$annuallyMonth] = $annuallyMonth;
$monthlySummary['transaction'][$annuallyMonth]['count'] = 0;
$monthlySummary['transaction'][$annuallyMonth]['total'] = 0;
$monthlySummary['transaction'][$annuallyMonth]['commission'] = 0;
if(isset($vwBookingSummaryTransactionGrouped[$annuallyMonth])) {
$dataCollectGroupCurrency = collect($vwBookingSummaryTransactionGrouped[$annuallyMonth])->groupBy('currency_code')->toArray();
foreach ($dataCollectGroupCurrency as $currencyCode => $currencyGroup) {
$lastExchangeRate = $this->currencyService->lastExchangeRate($currencyCode, 'EUR');
$monthlySummary['transaction'][$annuallyMonth]['count'] += collect($currencyGroup)->count();
$monthlySummary['transaction'][$annuallyMonth]['total'] += collect($currencyGroup)->sum('total') * $lastExchangeRate['data'];
$monthlySummary['transaction'][$annuallyMonth]['commission'] += collect($currencyGroup)->sum('commission') * $lastExchangeRate['data'];
}
}
$monthlySummary['checkout'][$annuallyMonth]['count'] = 0;
$monthlySummary['checkout'][$annuallyMonth]['total'] = 0;
$monthlySummary['checkout'][$annuallyMonth]['commission'] = 0;
if(isset($vwBookingSummaryCheckoutGrouped[$annuallyMonth])) {
$dataCollectGroupCurrency = collect($vwBookingSummaryCheckoutGrouped[$annuallyMonth])->groupBy('currency_code')->toArray();
foreach ($dataCollectGroupCurrency as $currencyCode => $currencyGroup) {
$lastExchangeRate = $this->currencyService->lastExchangeRate($currencyCode, 'EUR');
$monthlySummary['checkout'][$annuallyMonth]['count'] += collect($currencyGroup)->count();
$monthlySummary['checkout'][$annuallyMonth]['total'] += collect($currencyGroup)->sum('total') * $lastExchangeRate['data'];
$monthlySummary['checkout'][$annuallyMonth]['commission'] += collect($currencyGroup)->sum('commission') * $lastExchangeRate['data'];
}
}
}
$report['monthlySummary'] = $monthlySummary;
break;
case 'annually':
$vwBookingSummaryAll = vwBookingSummaryAll::where('time', '>', Carbon::parse($today)->firstOfYear()->toDateString())
->where('time', '<', Carbon::parse($today)->addYear()->firstOfYear()->toDateString())
->where('commission', '>', 0)
->where('contract_user_id', $userId)
->whereIn('property_id', $contractUserProperty)
->get()->toArray();
break;
}
if ($vwBookingSummaryAll) {
$dataCollect = collect($vwBookingSummaryAll);
$dataCollectGroup = $dataCollect->groupBy('property_id')->toArray();
foreach ($dataCollectGroup as $propertyId => $propertyList) {
$property = reset($propertyList);
$report['data'][$propertyId]['id'] = $property['property_id'];
$report['data'][$propertyId]['name'] = $property['property_name'];
$report['data'][$propertyId]['count'] = 0;
$report['data'][$propertyId]['total'] = 0;
$report['data'][$propertyId]['commission'] = 0;
$dataCollectGroupCurrency = collect($propertyList)->groupBy('currency_code')->toArray();
foreach ($dataCollectGroupCurrency as $currencyCode => $currencyGroup) {
$lastExchangeRate = $this->currencyService->lastExchangeRate($currencyCode, 'EUR');
$count = collect($currencyGroup)->count();
$total = collect($currencyGroup)->sum('total');
$commission = collect($currencyGroup)->sum('commission');
$report['data'][$propertyId]['count'] += $count;
$report['data'][$propertyId]['total'] += $total * $lastExchangeRate['data'];
$report['data'][$propertyId]['commission'] += $commission * $lastExchangeRate['data'];
}
}
$report['data'] = collect($report['data'])->sortByDesc('commission')->toArray();
$report['summary']['count'] = collect($report['data'])->sum('count');
$report['summary']['total'] = collect($report['data'])->sum('total');
$report['summary']['commission'] = collect($report['data'])->sum('commission');
}
return $report;
}
public function handle()
{
$this->info(date('Y-m-d H:i:s') . ' START');
$today = Carbon::now()->subDay()->toDateString();
$userListIds = [904, 941, 1485];//41, 22, 883
$userListCriteria = [
'criteria' => [
['field' => 'status', 'condition' => '=', 'value' => 1],
],
'whereIn' => [
['field' => 'id', 'value' => $userListIds]
],
'orderBy' => [
['field' => 'id', 'value' => 'ASC']
]
];
$userList = $this->userService->select($userListCriteria);
foreach ($userList['data'] as $user) {
$contractUserProperty = vwActiveProperty::where('contract_user_id', $user['id'])
//->where('month', '>', '2024-10')
->get()->toArray();
$contractUserProperty = $contractUserProperty ? pickItemFromArray('id',$contractUserProperty) : [];
$this->info(date('Y-m-d H:i:s') . ' : '.$user['nameSurname']);
$report['name'] = $user['nameSurname'];
$report['email'] = $user['email'];
//DAILY
$report['daily']['data'] = [];
$report['daily']['title'] = 'Daily Report';
$report['daily']['type'] = 'daily';
$report['daily']['period'] = Carbon::parse($today)->format('d.m.Y');
$reportCalculate = $this->reportCalculate($user['id'], $contractUserProperty, $report['daily']['type']);
$report['daily']['data'] = $reportCalculate['data'];
$report['daily']['summary'] = $reportCalculate['summary'];
//MONTHLY
$report['monthly']['data'] = [];
$report['monthly']['title'] = 'Monthly Report';
$report['monthly']['type'] = 'monthly';
$report['monthly']['period'] = Carbon::parse($today)->firstOfMonth()->format('m.Y');
$reportCalculate = $this->reportCalculate($user['id'], $contractUserProperty, $report['monthly']['type']);
$report['monthly']['data'] = $reportCalculate['data'];
$report['monthly']['summary'] = $reportCalculate['summary'];
$report['monthlySummary'] = $reportCalculate['monthlySummary'];
//ANNUALLY
$report['annually']['data'] = [];
$report['annually']['title'] = 'Annually Report';
$report['annually']['type'] = 'annually';
$report['annually']['period'] = Carbon::parse($today)->firstOfYear()->format('Y');
$reportCalculate = $this->reportCalculate($user['id'], $contractUserProperty, $report['annually']['type']);
$report['annually']['data'] = $reportCalculate['data'];
$report['annually']['summary'] = $reportCalculate['summary'];
$report['activeProperty'] = vwActiveProperty::where('commission', '>', 1)
->where('contract_user_id', $user['id'])
->whereIn('id', $contractUserProperty)
->orderByDesc('id')
->get()->toArray();
//Property Price Comparison
$priceComparisonLink = null;
$todayComparison = Carbon::now()->toDateString();
$firstDayOfWeek = Carbon::parse($todayComparison)->startOfWeek(Carbon::MONDAY);
//$firstDayOfWeek = Carbon::parse($today)->startOfWeek(Carbon::MONDAY)->toDateString();
//if(Carbon::now()->toDateString() == $firstDayOfWeek) {
$year = Carbon::parse($firstDayOfWeek)->format('Y');
$week = Carbon::parse($firstDayOfWeek)->isoWeek();
$queryKeyHash = md5($year . '-' . $week);
$priceComparisonLink = config('app.url').'/property-comparison/'.$queryKeyHash.'/'.$user['id'];
//}
$report['priceComparisonLink'] = $priceComparisonLink;
//Property Price Comparison
$this->mailer->onQueue('dailyReportSalesMail', new DailyReportMailSales($report));
}
//Hotel LIST
/*$vwActivePropertySummary = [];
$vwActiveProperty = vwActiveProperty::where('commission', '>', 1)->get()->toArray();
$vwActivePropertySummary['count'] = count($vwActiveProperty);
$vwActivePropertySummary['groupByMonth'] = collect($vwActiveProperty)->sortByDesc('month')->groupBy('month')->toArray();
$vwActivePropertySummary['lastMonth'] = collect($vwActivePropertySummary['groupByMonth'])->take(3)->toArray();
//Hotel LIST
$report['activeProperty'] = $vwActivePropertySummary;*/
$this->info(date('Y-m-d H:i:s') . ' FINISHED');
}
}

View File

@@ -0,0 +1,239 @@
<?php
namespace App\Console\Commands\PropertyReviewService;
use App\Exceptions\ApiErrorException;
use App\Models\PropertyReview;
use App\Models\PropertyReviewCategory;
use App\Models\PropertyReviewCategoryMapping;
use App\Models\PropertyReviewKeywordMapping;
use Carbon\Carbon;
use Google\Protobuf\Api;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Http\Request;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Exception;
class PropertyReviewAnalyzeService extends Command
{
protected $signature = 'cron:property-review-analyze-service {review_id}';
protected $description = '';
public function __construct()
{
parent::__construct();
$this->restClient = new Client(['http_errors' => false]);
}
protected function requestService($params = [])
{
$response = ['status' => false, 'message' => '', 'data' => null, 'statusCode' => 500];
try {
$client = new \GuzzleHttp\Client([
'max' => 5,
'strict' => false,
'referer' => false,
'protocols' => ['https'],
'timeout' => 30,
'headers' => [
'Authorization' => 'Bearer ' . config('app.openAISecretKey'),
'Content-Type' => 'application/json',
'Cache-Control' => 'no-cache',
'Connection' => 'keep-alive',
'Accept-Encoding' => 'gzip'
]
]
);
$result = $client->post('https://api.openai.com/v1/chat/completions', [
'body' => json_encode($params['query'])
]);
$result = $result->getBody()->getContents();
$result = json_decode($result, 1);
$choiceMessage = reset($result['choices']);
if (isset($choiceMessage['message']['content'])) {
$choiceMessage = json_decode($choiceMessage['message']['content'], 1);
$data = $choiceMessage;
}
$response = [
'status' => true,
'data' => $data,
];
} catch (ApiErrorException $e) {
$response['message'] = implode(', ', $e->getMessageArr());
$response['statusCode'] = 400;
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$response['message'] = $e->getMessage();
$response['statusCode'] = 500;
}
return $response;
}
public function handle()
{
$this->info(date('Y-m-d H:i:s') . ' START');
//420
$propertyReview = PropertyReview::where('id', $this->argument('review_id'))
->with('channel')
->with('property')
->first();
$propertyReview = $propertyReview ? $propertyReview->toArray() : null;
if (!$propertyReview) {
Log::error('Property Review: ' . $propertyReview['property']['name'] . ' - ' . $propertyReview['channel']['name']);
return false;
}
$propertyReviewCategory = PropertyReviewCategory::where('status', 1)->select(['id', 'name'])->get()->toArray();
$propertyReviewCategoryText = implode(', ', collect($propertyReviewCategory)->pluck('name')->toArray());
$params['query'] = [
'model' => 'gpt-4o',
'response_format' => [
'type' => 'json_object'
],
'messages' => [
[
'role' => 'system',
'content' => 'Sen bir otel gelir yönetimi uzmanısın ve otellere yapılan yorumları değerlendiriyosun. Cevaplar SADECE JSON formatında. Yorumu genel olarak değerlendirip, misafir gibi düşünüp 0: olumsuz,1: olumlu olacak şekilde sentiment alanında işaretleyelim. Gelen yorumları \"' . $propertyReviewCategoryText . '\" kategorilerine göre categories alanında işaretleyip gruplayalım. Her bir gruplanan kategori için de 0: olumsuz,1: olumlu olacak şekilde işaretleyelim, ilgisiz kategorileri eklemeyelim. keywords alanında bu yorum ile ilgili kilit kelimeleri, ileride kelime bulutu yapmak için ingilizce çıkaralım,kelimeler otel ve otelcilik ile ilgili olsun, kelimeler normal metin şeklinde, aralıkları boşluklu ve sadece ilk harfleri büyük olsun, bu kelimeler için de 0: olumsuz,1: olumlu olacak şekilde işaretleyelim. Yorumu da language parametresi altında 2 haneli ISO koduna göre verelim.'
],
[
'role' => 'user',
'content' => $propertyReview['review']
]
]
];
$propertyReviewAnalyze = $this->requestService($params);
//$propertyReviewAnalyze = json_decode('{"status":true,"data":{"sentiment":0,"categories":{"Location":0,"Breakfast":0,"Service":1,"Cleanliness":1,"Room Facilities":0},"keywords":{"Location":0,"Breakfast":0,"Service Quality":1,"Cleaning":1,"Room Amenities":0}}}', 1);
if ($propertyReviewAnalyze['status']) {
DB::beginTransaction();
$transactionSave = false;
try {
$this->info(date('Y-m-d H:i:s') . ': Property Review: ' . $propertyReview['property']['name'] . ' - ' . $propertyReview['channel']['name']);
PropertyReview::where('id', $propertyReview['id'])->update(['sentiment' => $propertyReviewAnalyze['data']['sentiment'], 'language' => $propertyReviewAnalyze['data']['language']]);
//PropertyReviewCategoryMapping
$this->info(date('Y-m-d H:i:s') . ': Property Review Category Mapping: ' . $propertyReview['property']['name'] . ' - ' . $propertyReview['channel']['name']);
$bulkReviewCategoryMapping = [];
PropertyReviewCategoryMapping::where('review_id', $propertyReview['id'])->delete();
foreach ($propertyReviewAnalyze['data']['categories'] as $category => $categorySentiment) {
$categorySelected = collect($propertyReviewCategory)->where('name', $category)->first();
if (isset($categorySelected['id'])) {
$bulkReviewCategoryMapping[] = [
'review_id' => $propertyReview['id'],
'property_id' => $propertyReview['property_id'],
'channel_id' => $propertyReview['channel_id'],
'category_id' => $categorySelected['id'],
'sentiment' => $categorySentiment,
'review_date' => $propertyReview['review_date'],
'status' => 1,
'created_at' => time(),
'updated_at' => time(),
];
}
}
if (!empty($bulkReviewCategoryMapping)) {
PropertyReviewCategoryMapping::insert($bulkReviewCategoryMapping);
}
//PropertyReviewCategoryMapping
//PropertyReviewKeywordMapping
if (is_array($propertyReviewAnalyze['data']['keywords'])) {
$this->info(date('Y-m-d H:i:s') . ': Property Review Keyword Mapping: ' . $propertyReview['property']['name'] . ' - ' . $propertyReview['channel']['name']);
$bulkReviewKeywordMapping = [];
PropertyReviewKeywordMapping::where('review_id', $propertyReview['id'])->delete();
foreach ($propertyReviewAnalyze['data']['keywords'] as $keyword => $keywordSentiment) {
$bulkReviewKeywordMapping[] = [
'review_id' => $propertyReview['id'],
'property_id' => $propertyReview['property_id'],
'channel_id' => $propertyReview['channel_id'],
'keyword' => $keyword,
'sentiment' => $keywordSentiment,
'review_date' => $propertyReview['review_date'],
'status' => 1,
'created_at' => time(),
'updated_at' => time(),
];
}
if (!empty($bulkReviewKeywordMapping)) {
PropertyReviewKeywordMapping::insert($bulkReviewKeywordMapping);
}
}
//PropertyReviewKeywordMapping
//throw new Exception('Booking Room could not be made');
$transactionSave = true;
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$transactionSave = false;
}
if ($transactionSave) {
DB::commit();
} else {
DB::rollBack();
}
}
$this->info(date('Y-m-d H:i:s') . ' FINISHED');
}
}

View File

@@ -0,0 +1,62 @@
<?php
namespace App\Console\Commands\PropertyReviewService;
use App\Exceptions\ApiErrorException;
use App\Jobs\PropertyReviewServiceJob;
use App\Models\PropertyReviewChannelMapping;
use Carbon\Carbon;
use Google\Protobuf\Api;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Exception;
class PropertyReviewScheduleService extends Command
{
protected $signature = 'cron:property-review-schedule-service';
protected $description = '';
public function __construct()
{
parent::__construct();
}
public function handle()
{
$this->info(date('Y-m-d H:i:s') . ' START');
$propertyReviewChannelMapping = PropertyReviewChannelMapping::where('status', 1)
->with('channel')
->with('property')
->get();
$propertyReviewChannelMapping = $propertyReviewChannelMapping ? $propertyReviewChannelMapping->toArray() : null;
foreach ($propertyReviewChannelMapping as $propertyReview) {
if (Carbon::createFromTimestamp($propertyReview['created_at'])->dayName != Carbon::now()->dayName) {
continue;
}
$this->info(date('Y-m-d H:i:s') . ' Property Review: ' . $propertyReview['property']['name'] . ' - ' . $propertyReview['channel']['name']);
dispatch(new PropertyReviewServiceJob($propertyReview['property_id'], $propertyReview['channel_id']));
}
$this->info(date('Y-m-d H:i:s') . ' FINISHED');
}
}

View File

@@ -0,0 +1,738 @@
<?php
namespace App\Console\Commands\PropertyReviewService;
use App\Exceptions\ApiErrorException;
use App\Jobs\PropertyReviewAnalyzeServiceJob;
use App\Jobs\PropertyReviewServiceJob;
use App\Models\PropertyReview;
use App\Models\PropertyReviewChannelMapping;
use Carbon\Carbon;
use Google\Protobuf\Api;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Exception;
class PropertyReviewService extends Command
{
protected $signature = 'cron:property-review-service {property_id} {channel_id}';
protected $description = '';
protected $maxPageSize = 10;
protected $xApiKey = 'sk_live_995958e62147c2ae81f6be573daa7c0d0bcedf550ff5dae52315bd05f1272803';
public function __construct()
{
parent::__construct();
$this->restClient = new Client(['http_errors' => false]);
}
protected function requestService($params)
{
try {
$requestUrl = $params['requestUrl'];
$requestParams['headers']['x-api-key'] = $this->xApiKey;
$requestParams['headers']['Content-Type'] = 'application/json';
unset($params['requestUrl']);
$requestParams['query'] = $params;
$result = $this->restClient->request('GET', $requestUrl, $requestParams);
$getResponseBody = $result->getBody()->getContents();
$getResponseData = $getResponseBody ? json_decode($getResponseBody, 1) : [];
//$getResponseData = json_decode(file_get_contents(storage_path() . '/response.json'), 1);
//$getResponseData = json_decode(file_get_contents(storage_path() . '/google.json'), 1);
//$getResponseData = json_decode(file_get_contents(storage_path() . '/Tripadvisor.json'), 1);
//$getResponseData = json_decode(file_get_contents(storage_path() . '/Tripadvisor.json'), 1);
if (isset($getResponseData['error'])) {
throw new ApiErrorException($getResponseData['detail']);
}
$response['status'] = true;
$response['data'] = $getResponseData;
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::debug($message);
$response['message'] = $e->getMessage();
dd($response);
}
return $response;
}
public function handle()
{
$this->info(date('Y-m-d H:i:s') . ' START');
$propertyReviewChannelMapping = PropertyReviewChannelMapping::where('property_id', $this->argument('property_id'))
->where('channel_id', $this->argument('channel_id'))
->with('channel')
->with('property')
->first();
$propertyReviewChannelMapping = $propertyReviewChannelMapping ? $propertyReviewChannelMapping->toArray() : null;
Log::debug('Property Review: ' . $propertyReviewChannelMapping['property']['name'] . ' - ' . $propertyReviewChannelMapping['channel']['name']);
switch ($propertyReviewChannelMapping['channel_id']) {
//BookingCom
case '1':
$this->info(date('Y-m-d H:i:s') . ' START : ' . $propertyReviewChannelMapping['property']['name'] . ' - ' . $propertyReviewChannelMapping['channel']['name']);
$maxPageSize = 1;
if ($propertyReviewChannelMapping['fetch_status'] == 3) {
$maxPageSize = $this->maxPageSize;
PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 2]);
}
for ($i = 0; $i < $maxPageSize; $i++) {
$requestParams = [
'requestUrl' => 'https://api.stayapi.com/v1/booking/hotel/reviews',
'hotel_id' => $propertyReviewChannelMapping['parameterArray']['hotelId'],
'sort' => 'newest',
'per_page' => 20,
'page' => ($i + 1)
];
$requestReview = $this->requestService($requestParams);
//$bulkReview = [];
if ($requestReview['status']) {
foreach ($requestReview['data']['data']['reviews'] as $review) {
try {
if (empty($review['review']['positive']) && empty($review['review']['negative'])) {
continue;
}
$bulkReview = [
'property_id' => $propertyReviewChannelMapping['property_id'],
'channel_id' => $propertyReviewChannelMapping['channel_id'],
'channel_review_id' => $review['id'],
'author' => $review['guest']['name'],
'title' => fillOnUndefined($review['review'], 'title'),
'review' => $review['review']['positive'] . ' ' . $review['review']['negative'],
'review_date' => Carbon::parse($review['reviewed_date'])->toDateTimeString(),
'rating' => $review['score'],
'top_rating' => 10,
'score' => number_format($review['score'] / 10 * 100, 2),
'language' => $review['review']['language'],
'detail' => json_encode($review),
'status' => 1,
'created_at' => time(),
'updated_at' => time(),
];
$propertyReviewCheck = PropertyReview::where('property_id', $bulkReview['property_id'])
->where('channel_id', $bulkReview['channel_id'])
->where('channel_review_id', $bulkReview['channel_review_id'])
->first();
if (!$propertyReviewCheck) {
$propertyReviewCreate = PropertyReview::create($bulkReview);
dispatch(new PropertyReviewAnalyzeServiceJob($propertyReviewCreate['id']));
$this->info(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
} else {
$this->error(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
}
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
//dd($message);
}
}
}
}
PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 1]);
break;
//Google
case '2':
$this->info(date('Y-m-d H:i:s') . ' START : ' . $propertyReviewChannelMapping['property']['name'] . ' - ' . $propertyReviewChannelMapping['channel']['name']);
$maxPageSize = 1;
if ($propertyReviewChannelMapping['fetch_status'] == 3) {
PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 2]);
}
for ($i = 0; $i < $maxPageSize; $i++) {
$requestParams = [
'requestUrl' => 'https://api.stayapi.com/v1/google_reviews/reviews-paginated',
'data_id' => $propertyReviewChannelMapping['parameterArray']['dataId'],
'sort_by' => 'newest',
'pages' => 10
];
$requestReview = $this->requestService($requestParams);
if ($requestReview['status']) {
foreach ($requestReview['data']['reviews'] as $review) {
if (empty($review['text'])) {
continue;
}
try {
$bulkReview = [
'property_id' => $propertyReviewChannelMapping['property_id'],
'channel_id' => $propertyReviewChannelMapping['channel_id'],
'channel_review_id' => $review['review_id'],
'author' => $review['reviewer']['name'],
'title' => null,
'review' => $review['text'],
'review_date' => Carbon::parse($review['iso_date'])->toDateTimeString(),
'rating' => $review['rating'],
'top_rating' => 5,
'score' => number_format($review['rating'] / 5 * 100, 2),
'language' => null,
'detail' => json_encode($review),
'status' => 1,
'created_at' => time(),
'updated_at' => time(),
];
$propertyReviewCheck = PropertyReview::where('property_id', $bulkReview['property_id'])
->where('channel_id', $bulkReview['channel_id'])
->where('channel_review_id', $bulkReview['channel_review_id'])
->first();
if (!$propertyReviewCheck) {
$propertyReviewCreate = PropertyReview::create($bulkReview);
dispatch(new PropertyReviewAnalyzeServiceJob($propertyReviewCreate['id']));
$this->info(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
} else {
$this->error(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
}
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
//dd($message);
}
}
}
}
PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 1]);
break;
//Tripadvisor
case '3':
$this->info(date('Y-m-d H:i:s') . ' START : ' . $propertyReviewChannelMapping['property']['name'] . ' - ' . $propertyReviewChannelMapping['channel']['name']);
$maxPageSize = 1;
if ($propertyReviewChannelMapping['fetch_status'] == 3) {
$maxPageSize = $this->maxPageSize;
PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 2]);
}
for ($i = 0; $i < $maxPageSize; $i++) {
$requestParams = [
'requestUrl' => 'https://api.stayapi.com/v1/tripadvisor/hotel/reviews/' . $propertyReviewChannelMapping['parameterArray']['hotelId'],
'per_page' => 20,
'page' => ($i + 1)
];
$requestReview = $this->requestService($requestParams);
if ($requestReview['status']) {
foreach ($requestReview['data']['reviews'] as $review) {
if (!fillOnUndefined($review, 'text')) {
continue;
}
try {
$bulkReview = [
'property_id' => $propertyReviewChannelMapping['property_id'],
'channel_id' => $propertyReviewChannelMapping['channel_id'],
'channel_review_id' => $review['id'],
'author' => $review['user']['display_name'],
'title' => fillOnUndefined($review, 'title'),
'review' => fillOnUndefined($review, 'text'),
'review_date' => Carbon::parse($review['created_date'])->toDateTimeString(),
'rating' => $review['rating'],
'top_rating' => 5,
'score' => number_format($review['rating'] / 5 * 100, 2),
'language' => fillOnUndefined($review, 'language'),
'detail' => json_encode($review),
'status' => 1,
'created_at' => time(),
'updated_at' => time(),
];
$propertyReviewCheck = PropertyReview::where('property_id', $bulkReview['property_id'])
->where('channel_id', $bulkReview['channel_id'])
->where('channel_review_id', $bulkReview['channel_review_id'])
->first();
if (!$propertyReviewCheck) {
$propertyReviewCreate = PropertyReview::create($bulkReview);
dispatch(new PropertyReviewAnalyzeServiceJob($propertyReviewCreate['id']));
$this->info(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
} else {
$this->error(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
}
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
//dd($message);
}
}
}
}
PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 1]);
break;
//Agoda
case '4':
$this->info(date('Y-m-d H:i:s') . ' START : ' . $propertyReviewChannelMapping['property']['name'] . ' - ' . $propertyReviewChannelMapping['channel']['name']);
$maxPageSize = 1;
if ($propertyReviewChannelMapping['fetch_status'] == 3) {
$maxPageSize = $this->maxPageSize;
PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 2]);
}
for ($i = 0; $i < $maxPageSize; $i++) {
$requestParams = [
'requestUrl' => 'https://api.stayapi.com/v1/agoda/hotel/reviews/' . $propertyReviewChannelMapping['parameterArray']['hotelId'],
'page' => ($i + 1)
];
$requestReview = $this->requestService($requestParams);
if ($requestReview['status']) {
foreach ($requestReview['data']['reviews'] as $review) {
if (!fillOnUndefined($review, 'comment')) {
continue;
}
try {
$bulkReview = [
'property_id' => $propertyReviewChannelMapping['property_id'],
'channel_id' => $propertyReviewChannelMapping['channel_id'],
'channel_review_id' => $review['review_id'],
'author' => null,
'title' => fillOnUndefined($review, 'title'),
'review' => fillOnUndefined($review, 'comment'),
'review_date' => Carbon::parse($review['date'])->toDateTimeString(),
'rating' => $review['rating'],
'top_rating' => 10,
'score' => number_format($review['rating'] / 10 * 100, 2),
'language' => fillOnUndefined($review, 'language'),
'detail' => json_encode($review),
'status' => 1,
'created_at' => time(),
'updated_at' => time(),
];
$propertyReviewCheck = PropertyReview::where('property_id', $bulkReview['property_id'])
->where('channel_id', $bulkReview['channel_id'])
->where('channel_review_id', $bulkReview['channel_review_id'])
->first();
if (!$propertyReviewCheck) {
$propertyReviewCreate = PropertyReview::create($bulkReview);
dispatch(new PropertyReviewAnalyzeServiceJob($propertyReviewCreate['id']));
$this->info(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
} else {
$this->error(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
}
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
//dd($message);
}
}
}
}
PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 1]);
break;
//Trip.com
case '5':
$this->info(date('Y-m-d H:i:s') . ' START : ' . $propertyReviewChannelMapping['property']['name'] . ' - ' . $propertyReviewChannelMapping['channel']['name']);
$maxPageSize = 1;
if ($propertyReviewChannelMapping['fetch_status'] == 3) {
$maxPageSize = $this->maxPageSize;
PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 2]);
}
for ($i = 0; $i < $maxPageSize; $i++) {
$requestParams = [
'requestUrl' => 'https://api.stayapi.com/v1/tripcom/hotel/reviews/' . $propertyReviewChannelMapping['parameterArray']['hotelId'],
'page' => ($i + 1),
'page_size' => 50
];
$requestReview = $this->requestService($requestParams);
if ($requestReview['status']) {
foreach ($requestReview['data']['data']['reviews'] as $review) {
if (!fillOnUndefined($review, 'text')) {
continue;
}
/* if ($review['source'] != 1) {
continue;
}*/
try {
$bulkReview = [
'property_id' => $propertyReviewChannelMapping['property_id'],
'channel_id' => $propertyReviewChannelMapping['channel_id'],
'channel_review_id' => $review['id'],
'author' => isset($review['reviewer_name']) ? $review['reviewer_name'] : null,
'title' => fillOnUndefined($review, 'title'),
'review' => fillOnUndefined($review, 'text'),
'review_date' => Carbon::parse($review['date'])->toDateTimeString(),
'rating' => $review['rating'],
'top_rating' => 10,
'score' => number_format($review['rating'] / 10 * 100, 2),
'language' => fillOnUndefined($review, 'language'),
'detail' => json_encode($review),
'status' => 1,
'created_at' => time(),
'updated_at' => time(),
];
$propertyReviewCheck = PropertyReview::where('property_id', $bulkReview['property_id'])
->where('channel_id', $bulkReview['channel_id'])
->where('channel_review_id', $bulkReview['channel_review_id'])
->first();
if (!$propertyReviewCheck) {
$propertyReviewCreate = PropertyReview::create($bulkReview);
dispatch(new PropertyReviewAnalyzeServiceJob($propertyReviewCreate['id']));
$this->info(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
} else {
$this->error(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
}
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
//dd($message);
}
}
}
}
PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 1]);
break;
//Expedia.com
case '6':
$this->info(date('Y-m-d H:i:s') . ' START : ' . $propertyReviewChannelMapping['property']['name'] . ' - ' . $propertyReviewChannelMapping['channel']['name']);
$maxPageSize = 1;
if ($propertyReviewChannelMapping['fetch_status'] == 3) {
$maxPageSize = $this->maxPageSize;
PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 2]);
}
for ($i = 0; $i < $maxPageSize; $i++) {
$requestParams = [
'requestUrl' => 'https://api.stayapi.com/v1/expedia/hotel/reviews',
'property_id' => $propertyReviewChannelMapping['parameterArray']['hotelId'],
'page' => $i,
'page_size' => 5
];
$requestReview = $this->requestService($requestParams);
if ($requestReview['status']) {
foreach ($requestReview['data']['reviews'] as $review) {
if (!fillOnUndefined($review, 'text')) {
continue;
}
try {
preg_match('/(\d+)\s*\/\s*(\d+)/', $review['rating'], $matches);
$bulkReview = [
'property_id' => $propertyReviewChannelMapping['property_id'],
'channel_id' => $propertyReviewChannelMapping['channel_id'],
'channel_review_id' => $review['id'],
'author' => isset($review['reviewer_name']) ? $review['reviewer_name'] : null,
'title' => fillOnUndefined($review, 'title'),
'review' => fillOnUndefined($review, 'text'),
'review_date' => Carbon::parse($review['review_date'])->toDateTimeString(),
'rating' => (int)$matches[1],
'top_rating' => 10,
'score' => number_format((int)$matches[1] / 10 * 100, 2),
'language' => fillOnUndefined($review, 'language'),
'detail' => json_encode($review),
'status' => 1,
'created_at' => time(),
'updated_at' => time(),
];
$propertyReviewCheck = PropertyReview::where('property_id', $bulkReview['property_id'])
->where('channel_id', $bulkReview['channel_id'])
->where('channel_review_id', $bulkReview['channel_review_id'])
->first();
if (!$propertyReviewCheck) {
$propertyReviewCreate = PropertyReview::create($bulkReview);
dispatch(new PropertyReviewAnalyzeServiceJob($propertyReviewCreate['id']));
$this->info(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
} else {
$this->error(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
}
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
//dd($message);
}
}
}
}
PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 1]);
break;
//HolidayCheck
case '7':
$this->info(date('Y-m-d H:i:s') . ' START : ' . $propertyReviewChannelMapping['property']['name'] . ' - ' . $propertyReviewChannelMapping['channel']['name']);
$maxPageSize = 1;
if ($propertyReviewChannelMapping['fetch_status'] == 3) {
$maxPageSize = $this->maxPageSize;
PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 2]);
}
for ($i = 0; $i < $maxPageSize; $i++) {
$hotelId = $propertyReviewChannelMapping['parameterArray']['hotelId'];
$limit = 10;
$offset = $i * $limit;
$requestParams = [
'requestUrl' => "https://www.holidaycheck.de/api/hotel-reviews;filter=hotel.id:{$hotelId};limit={$limit};offset={$offset};select=id,user,title,texts,textAdvice,hotel,travelDate,recommendation,ratings,ranking,proofedReservation,ownerComment,additional,entryDate;sort=entryDate:desc",
];
$requestReview = $this->requestService($requestParams);
if ($requestReview['status']) {
$reviews = isset($requestReview['data']['data']['items']) ? $requestReview['data']['data']['items'] : [];
foreach ($reviews as $review) {
$reviewText = fillOnUndefined($review, 'textAdvice');
if (empty($reviewText)) {
$reviewText = fillOnUndefined($review, 'texts.GENERAL');
}
if (empty($reviewText)) {
continue;
}
try {
$rating = fillOnUndefined($review, 'ratings.GENERAL.GENERAL');
$author = fillOnUndefined($review, 'user.firstName');
if (empty($author)) {
$author = fillOnUndefined($review, 'user.name');
}
$bulkReview = [
'property_id' => $propertyReviewChannelMapping['property_id'],
'channel_id' => $propertyReviewChannelMapping['channel_id'],
'channel_review_id' => fillOnUndefined($review, 'id'),
'author' => $author,
'title' => fillOnUndefined($review, 'title'),
'review' => $reviewText,
'review_date' => Carbon::createFromTimestampMs(fillOnUndefined($review, 'entryDate'))->toDateTimeString(),
'rating' => $rating,
'top_rating' => 6,
'score' => number_format($rating / 6 * 100, 2),
'language' => fillOnUndefined($review, 'originalLocale'),
'detail' => json_encode($review),
'status' => 1,
'created_at' => time(),
'updated_at' => time(),
];
$propertyReviewCheck = PropertyReview::where('property_id', $bulkReview['property_id'])
->where('channel_id', $bulkReview['channel_id'])
->where('channel_review_id', $bulkReview['channel_review_id'])
->first();
if (!$propertyReviewCheck) {
$propertyReviewCreate = PropertyReview::create($bulkReview);
dispatch(new PropertyReviewAnalyzeServiceJob($propertyReviewCreate['id']));
$this->info(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
} else {
$this->error(date('Y-m-d H:i:s') . ' - ' . $bulkReview['channel_review_id']);
}
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
//dd($message);
}
}
}
}
PropertyReviewChannelMapping::where('id', $propertyReviewChannelMapping['id'])->update(['fetch_status' => 1]);
break;
}
$this->info(date('Y-m-d H:i:s') . ' FINISHED');
}
}

View File

@@ -0,0 +1,125 @@
<?php
namespace App\Console\Commands\PropertyTrialCheck;
use App\Core\Service\PropertyProductMappingService;
use App\Core\Service\PropertyService;
use App\Exceptions\ApiErrorException;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class PropertyTrialCheck extends Command
{
protected $signature = 'cron:property-trial-check';
protected $description = '';
private $propertyService;
public function __construct(
PropertyService $propertyService,
PropertyProductMappingService $productMappingService
)
{
parent::__construct();
$this->propertyService = $propertyService;
$this->productMappingService = $productMappingService;
}
public function handle()
{
$response = ['status' => false, 'message' => ''];
$propertySelectCriteria = [
'criteria' => [
//['field' => 'id', 'condition' => '=', 'value' => 1],
['field' => 'status', 'condition' => '=', 'value' => 1],
['field' => 'commission', 'condition' => '=', 'value' => null],
['field' => 'created_at', 'condition' => '>', 'value' => Carbon::parse('2021-10-01')->timestamp],
],
'with' => ['propertyProductMapping'],
'orderBy' => [
["field" => "id", "value" => "ASC"]
],
'take' => 100
];
$propertyData = $this->propertyService->select($propertySelectCriteria);
if ($propertyData['status'] == 'success') {
foreach ($propertyData['data'] as $property) {
if (empty($property['property_product_mapping'])) {
continue;
}
$expireDay = Carbon::now()->diff(Carbon::createFromTimestamp($property['created_at']))->days;
$this->info(date('Y-m-d H:i:s') . ' Property: ' . $property['id'] . ' - ' . $property['name'] . ' - ' . $expireDay. ' Day');
if (in_array($expireDay, [30])) {
DB::beginTransaction();
try {
$this->info(date('Y-m-d H:i:s') . ' : Property: ' . $property['id'] . ' - ' . $property['name']);
//Product remove from property
foreach ($property['property_product_mapping'] as $productMapping) {
$this->productMappingService->update($productMapping['id'], ['status' => 0]);
}
//Trial period status
$propertyData = $this->propertyService->update($property['id'], ['status' => 2]);
//Burada otel user larına mail atılabilir, trial süresi biti diye
$response['status'] = true;
} catch (ApiErrorException $e) {
$response['message'] = implode(', ', $e->getMessageArr());
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
}
if ($response['status']) {
DB::commit();
} else {
DB::rollBack();
}
}
//Expiration Check
//Product remove from property via expiration date
foreach ($property['property_product_mapping'] as $productMapping) {
if($productMapping['status'] == 1 && !is_null($productMapping['expiration_date'])) {
if(Carbon::now()->greaterThanOrEqualTo(Carbon::parse($productMapping['expiration_date']))) {
$this->productMappingService->update($productMapping['id'], ['status' => 3]);}
}
}
}
}
}
}

View File

@@ -0,0 +1,83 @@
<?php
namespace App\Console\Commands\PropertyTrialCheck;
use App\Core\Mail\TrialFirstMail;
use App\Core\Mail\TrialSecondMail;
use App\Core\Service\PropertyService;
use App\Exceptions\ApiErrorException;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class PropertyTrialMail extends Command
{
protected $signature = 'cron:property-trial-mail';
protected $description = '';
private $propertyService;
public function __construct(
Mailer $mailer,
PropertyService $propertyService
)
{
parent::__construct();
$this->mailer = $mailer;
$this->propertyService = $propertyService;
}
public function handle()
{
$this->info(date('Y-m-d H:i:s') . ' START');
$propertySelectCriteria = [
'criteria' => [
['field' => 'status', 'condition' => '=', 'value' => 1],
['field' => 'commission', 'condition' => '=', 'value' => null],
],
'orderBy' => [
["field" => "id", "value" => "ASC"]
],
];
$propertyData = $this->propertyService->select($propertySelectCriteria);
if ($propertyData['status'] == 'success') {
foreach ($propertyData['data'] as $property) {
$createDate = Carbon::createFromTimestamp($property['created_at'])->toDateTimeString();
$expireDay = Carbon::now()->diff(Carbon::createFromTimestamp($property['created_at']))->days;
if (in_array($expireDay, [4, 10])) {
if ($expireDay == 4) {
$this->mailer->onQueue('trialFirstMail', new TrialFirstMail(['propertyId' => $property['id']]));
$this->info(date('Y-m-d H:i:s') . ' SENT Day 4: ' . $property['id'] . ' - ' . $property['name'] . ' - ' . $createDate);
}
if ($expireDay == 10) {
$this->mailer->onQueue('trialSecondMail', new TrialSecondMail(['propertyId' => $property['id']]));
$this->info(date('Y-m-d H:i:s') . ' SENT Day 10: ' . $property['id'] . ' - ' . $property['name'] . ' - ' . $createDate);
}
}
}
}
$this->info(date('Y-m-d H:i:s') . ' FINISHED');
}
}

View File

@@ -0,0 +1,57 @@
<?php
namespace App\Console\Commands\PropertyWebCheckDns;
use App\Core\Service\PropertyWebService;
use App\Exceptions\ApiErrorException;
use Illuminate\Console\Command;
use Exception;
use Illuminate\Support\Facades\Log;
class PropertyWebCheckDns extends Command
{
protected $signature = 'cron:property-web-check-dns'; // read table name column, update table key column
protected $description = '';
private $propertyWebService;
public function __construct(
PropertyWebService $propertyWebService
)
{
$this->propertyWebService = $propertyWebService;
parent::__construct();
}
public function handle()
{
try {
$this->info(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' Check DNS Status start');
$process = $this->propertyWebService->checkDnsStatus();
if($process['status'] != 'success'){
throw new Exception($process['message']) ;
}
$this->info(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' Check DNS Status finished');
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' ERROR: ' . $message);
}
}
}

View File

@@ -0,0 +1,64 @@
<?php
namespace App\Console\Commands\PropertyWebMenuMapping;
use App\Core\Service\PropertyWebService;
use App\Exceptions\ApiErrorException;
use App\Models\PropertyWeb;
use App\Models\PropertyWebMenu;
use App\Models\PropertyWebMenuMapping;
use Illuminate\Console\Command;
use Exception;
use Illuminate\Support\Facades\Log;
class PropertyWebMenuMappingConsole extends Command
{
protected $signature = 'cron:property-web-menu-mapping';
protected $description = '';
public function __construct(){
parent::__construct();
}
public function handle()
{
try {
$this->info(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' Start');
$webMenus = PropertyWebMenu::all();
$webs = PropertyWeb::all();
$datas = [];
foreach ($webs as $key => $web){
foreach ($webMenus as $key1 => $menu){
$datas[$key][$key1]['property_id'] = $web->property_id;
$datas[$key][$key1]['property_web_id'] = $web->id;
$datas[$key][$key1]['property_web_menu_id'] = $menu->id;
$datas[$key][$key1]['order_number'] = $menu->order_number;
$datas[$key][$key1]['status'] = 1;
$datas[$key][$key1]['created_by'] = 1;
$datas[$key][$key1]['updated_by'] = 1;
$datas[$key][$key1]['created_at'] = 1;
$datas[$key][$key1]['updated_at'] = 1;
}
}
PropertyWebMenuMapping::insert(collect($datas)->flatten(1)->toArray());
$this->info(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' Finished');
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$this->error(date('Y-m-d H:i:s') . ' : ' . date('Y-m-d') . ' ERROR: ' . $message);
}
}
}

161
app/Console/Kernel.php Normal file
View File

@@ -0,0 +1,161 @@
<?php
namespace App\Console;
use App\Console\Commands\ApplicationLanguageFiles\ApplicationLanguageFiles;
use App\Console\Commands\ApplicationLanguageFiles\ApplicationLanguageBaseData;
use App\Console\Commands\ApplicationLanguageFiles\ApplicationFillTableLanguageKey;
use App\Console\Commands\ChannelManager\BestAvailableRateSyncService;
use App\Console\Commands\ChannelManager\MetaCancellationService;
use App\Console\Commands\ChannelManager\PropertyBookingSyncService;
use App\Console\Commands\ChannelManager\PropertyChannelSyncService;
use App\Console\Commands\ChannelManager\PropertyMetaRoomRatePriceService;
use App\Console\Commands\ChannelManager\PropertyMetaRoomRatePushService;
use App\Console\Commands\ChannelManager\PropertyMetaRoomRateService;
use App\Console\Commands\ChannelManager\RemovePaymentTokenService;
use App\Console\Commands\ChannelManager\ReselivaAvailRateUpdateService;
use App\Console\Commands\ChannelManager\ReservationPushService;
use App\Console\Commands\ChannelManager\ReservationPullService;
use App\Console\Commands\ChannelManager\RoomAvailabilityPushService;
use App\Console\Commands\CurrencyRates\CurrencyRatesService;
use App\Console\Commands\ChannelManager\RoomRatePushService;
use App\Console\Commands\Data\DashboardCacheService;
use App\Console\Commands\Data\HotelBedsList;
use App\Console\Commands\Data\WeatherService;
use App\Console\Commands\Google\GoogleReview;
use App\Console\Commands\Google\GoogleStaticMap;
use App\Console\Commands\Jobs\BookingCommissionService;
use App\Console\Commands\Jobs\BookingEngineSearchReportService;
use App\Console\Commands\Jobs\DataFetch;
use App\Console\Commands\Jobs\PriceComparisonService;
use App\Console\Commands\Jobs\PropertyCatalogService;
use App\Console\Commands\Jobs\PropertyInvoiceService;
use App\Console\Commands\Jobs\PropertySummaryService;
use App\Console\Commands\PropertyReviewService\PropertyReviewAnalyzeService;
use App\Console\Commands\PropertyReviewService\PropertyReviewScheduleService;
use App\Console\Commands\PropertyReviewService\PropertyReviewService;
use App\Console\Commands\Jobs\SummaryReportMail;
use App\Console\Commands\Jobs\SummaryReportMailSales;
use App\Console\Commands\PropertyTrialCheck\PropertyTrialCheck;
use App\Console\Commands\PropertyTrialCheck\PropertyTrialMail;
use App\Console\Commands\PropertyWebCheckDns\PropertyWebCheckDns;
use App\Console\Commands\Google\GoogleVisioLabel;
use App\Console\Commands\Jobs\MailJobs;
use App\Console\Commands\PropertyWebMenuMapping\PropertyWebMenuMappingConsole;
use Illuminate\Console\Scheduling\Schedule;
use Laravel\Lumen\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
GoogleVisioLabel::class,
MailJobs::class,
ApplicationLanguageFiles::class,
ApplicationLanguageBaseData::class,
ApplicationFillTableLanguageKey::class,
PropertyWebCheckDns::class,
CurrencyRatesService::class,
PropertyWebMenuMappingConsole::class,
RoomRatePushService::class,
RoomAvailabilityPushService::class,
ReservationPullService::class,
PropertyTrialCheck::class,
PropertyTrialMail::class,
HotelBedsList::class,
ReservationPushService::class,
SummaryReportMail::class,
PropertyChannelSyncService::class,
PropertyBookingSyncService::class,
BestAvailableRateSyncService::class,
RemovePaymentTokenService::class,
BookingEngineSearchReportService::class,
PropertyMetaRoomRateService::class,
PropertyMetaRoomRatePriceService::class,
PropertyMetaRoomRatePushService::class,
WeatherService::class,
BookingCommissionService::class,
DashboardCacheService::class,
GoogleReview::class,
SummaryReportMailSales::class,
GoogleStaticMap::class,
PriceComparisonService::class,
PropertyCatalogService::class,
PropertyInvoiceService::class,
PropertyReviewService::class,
PropertyReviewScheduleService::class,
PropertyReviewAnalyzeService::class,
DataFetch::class,
MetaCancellationService::class,
PropertySummaryService::class
//ReselivaAvailRateUpdateService::class
];
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
/*$schedule->command('cron:mail-jobs')
->withoutOverlapping()
->everyMinute()
->sendOutputTo(storage_path() . '/logs/cron-mail-jobs.log');*/
$schedule->command('cron:mail-jobs')->everyMinute();
$schedule->command('cron:currency-rates')
->withoutOverlapping()
->twiceDaily(2, 14)
//->everyMinute()
//->emailOutputTo('byumak@rezervasyon.com')
->sendOutputTo(storage_path() . '/logs/cron-currency-rates.log');
$schedule->command('cron:roomrate-push-service')->everyMinute();
$schedule->command('cron:roomavailability-push-service')->everyMinute();
$schedule->command('cron:reservation-pull-service')->everyMinute();
$schedule->command('cron:reservation-push-service')->everyMinute();
$schedule->command('cron:property-trial-check')->withoutOverlapping()->twiceDaily(9, 15);
$schedule->command('cron:property-trial-mail')->withoutOverlapping()->dailyAt('10:00');
//$schedule->command('queue:work')->everyMinute()->withoutOverlapping();
$schedule->command('queue:restart')->hourly()->withoutOverlapping();
$schedule->command('cron:summary-report-mail')->dailyAt('00:05');
$schedule->command('cron:summary-report-mail-sales')->dailyAt('09:00');
$schedule->command('cron:remove-payment-token-service')->withoutOverlapping()->dailyAt('02:00');
$schedule->command('cron:bookingengine-search-report-mail')->withoutOverlapping()->dailyAt('09:00');
$schedule->command('cron:propertymeta-roomrate-service')->withoutOverlapping()->dailyAt('03:00');
$schedule->command('cron:propertymeta-roomrateprice-service')->withoutOverlapping()->dailyAt('05:00');
$schedule->command('cron:propertymeta-roomratepush-service')->withoutOverlapping()->dailyAt('07:00');
//$schedule->command('cron:bar-sync-service')->withoutOverlapping()->cron('0 */2 * * *');
$schedule->command('cron:bar-sync-service')->cron('0 */2 * * *');
$schedule->command('cron:price-comparison-service')->withoutOverlapping()->weekly()->mondays()->at('02:00');
$schedule->command('cron:commission-service')->everyTenMinutes();
$schedule->command('cron:weather')->withoutOverlapping()->twiceDaily(2, 14);
$schedule->command('cron:dashboard-cache')->withoutOverlapping()->dailyAt('03:00');
$schedule->command('cron:google-static-map')->withoutOverlapping()->dailyAt('04:00');
$schedule->command('cron:google-review')->withoutOverlapping()->weekly()->mondays()->at('14:00');
$schedule->command('cron:property-invoice-service')->withoutOverlapping()->dailyAt('04:00');
$schedule->command('cron:property-summary-service')->withoutOverlapping()->dailyAt('04:30');
$schedule->command('cron:property-review-schedule-service')->withoutOverlapping()->dailyAt('05:00');
$schedule->command('cron:meta-cancellation-service')->withoutOverlapping()->dailyAt('05:30');
}
}

View File

@@ -0,0 +1,8 @@
<?php
namespace App\Core\Contracts;
interface MailInterface
{
public function process (array $params = null);
}

View File

@@ -0,0 +1,196 @@
<?php
namespace App\Core\Helper;
use Exception;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
class LanguageService
{
private static $currentLanguage = null;
private static $languageSupportList = null;
private static $languageSupportCacheName = "langSupportCache";
public static function getDefaultLang()
{
return config("languageSupport.defaultLanguage");
}
public static function getCurrentLang ( )
{
$language = self::$currentLanguage;
$language = $language ? $language : self::getDefaultLang();
return $language;
}
public static function isValidLanguage ( $language )
{
$validLanguages = self::getValidLanguages();
return in_array($language,$validLanguages);
}
public static function getCurrentLangPack($language = null)
{
$language = $language ? $language : self::getCurrentLang();
return config("language-pack-".$language);
}
public static function setCurrentLanguage($language)
{
$language = strtolower($language);
self::$currentLanguage = self::isValidLanguage($language) ? $language : config("languageSupport.defaultLanguage");
return self::$currentLanguage;
}
public static function getValidLanguages ( $except = null )
{
return collect(config("languageSupport.availableLanguages"))->flip()->except($except)->flip()->toArray();
}
public static function getAllLangPackages()
{
$langPackages = [];
$validSystemLanguages = self::getValidLanguages();
foreach ($validSystemLanguages as $perLanguage)
{
$langPackages[$perLanguage] = self::getCurrentLangPack($perLanguage);
}
return $langPackages;
}
public static function convertAllLanguageSettingsAndCache()
{
$cacheParam = [];
$wordIndexCounter = 0;
$allLangPackages = self::getAllLangPackages();
$systemDefaultLang = self::getDefaultLang();
foreach ($allLangPackages[$systemDefaultLang] as $perLangKey => $perLangWord)
{
$cacheParam[$wordIndexCounter]["md5"] = self::convertToMd5ForMultiLanguage($perLangWord);
foreach ($allLangPackages as $perLangPackKey => $perLangPack)
{
$cacheParam[$wordIndexCounter][$perLangPackKey] = $perLangPack[$wordIndexCounter];
}
$wordIndexCounter++;
}
$cacheParam = collect($cacheParam)->keyBy("md5")->toArray();
Cache::put(self::$languageSupportCacheName,$cacheParam,120);
return $cacheParam;
}
public static function getLanguageSupportList()
{
$cachedData = self::$languageSupportList;
if ( !$cachedData)
{
$cachedData = Cache::get(self::$languageSupportCacheName);
self::$languageSupportList = $cachedData;
}
$cachedData = $cachedData ? $cachedData : self::convertAllLanguageSettingsAndCache();
return $cachedData;
}
private static function makeSlugForMultiLanguage( $word )
{
$word = lowerCase($word);
preg_match_all("#[\pL\d+]+#iu",$word,$results);
$results = $results[0];
$converted = implode("",$results);
return $converted;
}
public static function convertToMd5ForMultiLanguage($word)
{
/*Clear The Parameters*/
$word = preg_replace('/\{\#\d+\}/',"",$word);
/**/
/*Clear From Html*/
$word = strip_tags($word);
/**/
$word = self::makeSlugForMultiLanguage($word);
return md5($word);
}
public static function findWordForLanguage($word,$lang,array $parameters = [])
{
$md5Key = self::convertToMd5ForMultiLanguage($word);
$langSupportList = self::getLanguageSupportList();
$converted = fillOnUndefined($langSupportList,$md5Key.".".$lang);
$converted = $converted ? $converted : fillOnUndefined($langSupportList,$md5Key.".".self::getDefaultLang());
$converted = $converted ? $converted : $word;
/*Inject Parameters*/
$parameters = reIndexArrayKeys($parameters,1);
foreach ($parameters as $perParameterKey => $perParameter)
{
$converted = preg_replace('/\{\#'.$perParameterKey.'\}/',$perParameter,$converted);
}
/**/
return $converted;
}
public static function lang ( $word,array $parameters = [],$lang = null )
{
$lang = $lang ? : self::$currentLanguage;
return self::findWordForLanguage($word,$lang,$parameters);
}
public static function langArrayStack ( array $langParamStack )
{
$result = [];
$validCases = ["lower","title","upper"];
foreach ($langParamStack as $perLangParam)
{
$word = castToString(fillOnUndefined($perLangParam,"word"));
$parameters = fillOnUndefined($perLangParam,"parameters",[]);
$lang = castToString(fillOnUndefined($perLangParam,"lang"));
$case = lowerCase(castToString(fillOnUndefined($perLangParam,"case")));
$case = in_array($case,$validCases) ? $case : null;
$caseFunction = $case ? camel_case("lang".$case."case") : "lang";
$result[] = self::$caseFunction($word,$parameters,$lang);
}
return $result;
}
public static function langArray ( array $words, $lang = null )
{
$result = [];
foreach ($words as $perWord)
{
$result[] = self::lang($perWord, [], $lang);
}
return $result;
}
public static function langLowerCase($word,array $parameters = [],$lang = null)
{
$lang = $lang ? : self::getCurrentLang();
$translated = self::lang($word, $parameters,$lang);
return $lang == "tr" ? lowerCase($translated) : mb_strtolower($translated);
}
public static function langTitleCase($word,array $parameters = [],$lang = null)
{
$lang = $lang ? : self::getCurrentLang();
$translated = self::lang($word, $parameters,$lang);
return $lang == "tr" ? uCase($translated) : mb_convert_case($translated,MB_CASE_TITLE);
}
public static function langUpperCase($word,array $parameters = [],$lang = null)
{
$lang = $lang ? : self::getCurrentLang();
$translated = self::lang($word, $parameters,$lang);
return $lang == "tr" ? upperCase($translated) : mb_strtoupper($translated);
}
}

View File

@@ -0,0 +1,570 @@
<?php
namespace App\Core\Helper;
use DateTime;
use Illuminate\Support\Facades\App;
class PhpHelper {
private static $days = [
'Pazartesi',
'Salı',
'Çarşamba',
'Perşembe',
'Cuma',
'Cumartesi',
'Pazar',
];
private static $months = [
'Ocak',
'Şubat',
'Mart',
'Nisan',
'Mayıs',
'Haziran',
'Temmuz',
'Ağustos',
'Eylül',
'Ekim',
'Kasım',
'Aralık',
];
private static $encryptionKey = 'd0a7e7997b6d5fcd55f4b5c32611b87cd923e88837b63bf2941ef819dc8ca282';
public static function json_decode($input) {
return json_decode($input);
}
public static function json_encode($input) {
return json_encode($input);
}
public static function pre($input) {
echo '<pre>';
print_r($input);
echo '</pre>';
}
/**
* Display the difference between two dates
* (30 years, 9 months, 25 days, 21 hours, 33 minutes, 3 seconds).
*
* @param string $start starting date
* @param string $end=false ending date
*
* @return string formatted date difference
*/
public static function dateDiff($start, $end = false) {$return = [];
try {
$start = new DateTime($start);
$end = new DateTime($end);
$form = $start->diff($end);
} catch (Exception $e) {
return $e->getMessage();
}
$display = ['y' => 'Yıl', 'm' => 'Ay', 'd' => 'Gün', 'h' => 'Saat', 'i' => 'Dakika', 's' => 'Saniye'];
foreach ($display as $key => $value) {
if ($form->$key > 0) {
$return[] = $form->$key . ' ' . $value;
}
}
return implode($return, ', ');
}
/**
* Display the day count between two dates
* (3 days).
*
* @param string $start starting date
* @param string $end=false ending date
*
* @return string day count
*/
public static function dayCount($end, $start) {
$return = [];
try {
$start = new DateTime($start);
$end = new DateTime($end);
$form = $start->diff($end);
} catch (Exception $e) {
return $e->getMessage();
}
return $form->days;
}
/**
* Display the day and month name
* (16 July).
*
* @param string $date date
*
* @return string formatted date
*/
public static function dayNumberAndMonthWord($date) {
return date('d', strtotime($date)) . ' ' . self::$months[date('m', strtotime($date)) - 1];
}
/**
* Display the month name
* (July).
*
* @param string $date date
*
* @return string formatted date
*/
public static function monthName($date) {
return self::$months[date('m', strtotime($date)) - 1];
}
/**
* Display the day name
* (Sunday).
*
* @param string $date date
*
* @return string formatted date
*/
public static function dayName($date) {
return self::$days[date('N', strtotime($date)) - 1];
}
/**
* Display the day number
* 01.
*
* @param string $date date
*
* @return string formatted date
*/
public static function dayNumber($date) {
return date('d', strtotime($date));
}
/**
* Display the human readable day
* 01.
*
* @param string $date date
*
* @return string formatted date
*/
public static function humanReadableDateWithDay($date) {
return date('d', strtotime($date)) . ' ' . self::$months[date('m', strtotime($date)) - 1] . ' ' . date('Y', strtotime($date)) . ', ' . self::dayName($date);
}
/**
* Display the human readable day
* 01.
*
* @param string $date date
*
* @return string formatted date
*/
public static function humanReadableDate($date) {
return date('d-m-Y H:i:s', strtotime($date));
}
public static function humanReadableDateWithoutClock($date) {
return date('d-m-Y', strtotime($date));
}
/**
* @param string $date date
*
* @return string formatted date
*/
public static function sqlDate($date) {
$date = date('Y-m-d', strtotime($date));
return $date;
}
public static function getMonth() {
return self::$months;
}
public static function isValidDate($date) {
if (!is_string($date)) {
return false;
}
$day = substr($date, 0, 2);
$mont = substr($date, 3, 2);
$year = substr($date, 6, 4);
return checkdate($mont, $day, $year);
}
public static function fillNullIfEmpty(&$variable) {
if (!isset($variable)) {
$variable = null;
}
return $variable;
}
public static function getWeekDays() {
$days = self::$days;
$result = array();
$counter = 1;
foreach ($days as $x) {
$result[$counter] = $x;
$counter++;
}
return $result;
}
public static function parseXmlToArray($xmlSource) {
try {
$xmlOut = simplexml_load_string($xmlSource, 'SimpleXMLElement', LIBXML_NOCDATA);
$arrayOut = json_decode(json_encode($xmlOut), true);
} catch (\Exception $e) {
$arrayOut = false;
}
return $arrayOut;
}
public static function encryptCodeNumber($string, $key) {
$key = is_null($key) ? self::$encryptionKey : $key;
$result = '';
for ($i = 0; $i < mb_strlen($string, "UTF-8"); $i++) {
$char = mb_substr($string, $i, 1, "UTF-8");
$keychar = mb_substr($key, ($i % mb_strlen($key, "UTF-8")) - 1, 1, "UTF-8");
$char = chr(ord($char) + ord($keychar));
$result.=$char;
}
$result = base64_encode($result);
$result = str_replace("=", "", $result);
return urlencode($result);
}
public static function decryptCodeNumber($string, $key) {
$key = is_null($key) ? self::$encryptionKey : $key;
$string = urldecode($string);
$eqcount = strlen($string) % 4;
if ($eqcount == 2)
$string . "==";
else if ($eqcount == 3)
$string . "=";
$result = '';
$string = base64_decode($string);
for ($i = 0; $i < mb_strlen($string); $i++) {
$char = mb_substr($string, $i, 1);
$keychar = mb_substr($key, ($i % mb_strlen($key)) - 1, 1);
$char = chr(ord($char) - ord($keychar));
$result.=$char;
}
return $result;
}
public static function generateRandomString($length = 5) {
$characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
public static function convertArrayToCsv (array $valueArray )
{
if ( !$valueArray )
{
return false;
}
$csvResult = "";
$valueArray = singleElementArray($valueArray);
/*Get The Column Names*/
$firstArray = reset($valueArray);
$csvResult.=implode(",",array_keys($firstArray))."\r\n";
foreach ($valueArray as $perArray)
{
$csvResult.=implode(",",$perArray)."\r\n";
}
return $csvResult;
}
private static function nextExcelColName ( $colName = null )
{
$primary = range("A","Z");
if ( !$colName)
{
return reset($primary);
}
if(last($primary) == $colName)
{
return reset($primary);
}
return $primary[array_search($colName,$primary)+1];
}
/* If $params[keyNames] is Empty Function Gonna Take All The Keys Of The Array */
public static function convertArrayToXls (array $valueArray,array $params = [] )
{
try
{
$excel = App::make('excel');
$params[ "fileName" ] = isset( $params[ "fileName" ] ) ? $params[ "fileName" ] : "xls_file";
$params[ "pagePrefix" ] = isset( $params[ "pagePrefix" ] ) ? $params[ "pagePrefix" ] : "Page";
$params[ "onlyTheseKeys" ] = isset( $params[ "onlyTheseKeys" ] ) ? $params[ "onlyTheseKeys" ] : [];
$params[ "keyNames" ] = isset( $params[ "keyNames" ] ) ? $params[ "keyNames" ] : [];
$result = $excel->create ( $params[ "fileName" ], function ( $excel ) use ( $valueArray, $params )
{
$excel->sheet ( $params[ "pagePrefix" ], function ( $sheet ) use ( $valueArray, $params)
{
$rowCounter = 1;
$sheet->setOrientation ( 'landscape' );
if ($params["keyNames"])
{
$colCounter = 0;
foreach ($params["keyNames"] as $perKey)
{
if ($params["onlyTheseKeys"] && !in_array($perKey,$params["onlyTheseKeys"]))
{
continue;
}
$sheet->setCellValueByColumnAndRow ( $colCounter, $rowCounter, $perKey );
$style = array(
'alignment' => array(
'horizontal' => "center",
)
);
$sheet->getDefaultStyle()->applyFromArray($style);
$colCounter++;
}
$rowCounter++;
}
foreach ($valueArray as $perValue)
{
$colCounter = 0;
foreach ($perValue as $perCol)
{
if ($params["onlyTheseKeys"] && !in_array($perKey,$params["onlyTheseKeys"]))
{
continue;
}
if (is_array($perCol))
{
$perCol = json_encode($perCol);
}
$sheet->setCellValueByColumnAndRow ( $colCounter, $rowCounter, $perCol );
$colCounter++;
}
$rowCounter++;
}
} );
});
return $result;
} catch ( Exception $e )
{
return null;
}
}
public static function singleElementArray ( $arrayElement,array $extraParams = null)
{
$isMultiArray = true;
if ( !is_array($arrayElement))
{
return [];
}
foreach ($arrayElement as $perItem)
{
if (gettype($perItem)!="array")
{
$isMultiArray = false;
break;
}
}
if(!$isMultiArray)
{
$isMultiArray = true;
foreach (array_keys ( $arrayElement ) as $perKey)
{
if (!is_numeric($perKey))
{
$isMultiArray = false;
break;
}
}
}
return $isMultiArray?$arrayElement:array($arrayElement);
}
public static function checkWizardMenu($wizardArray, $menuCode)
{
return array_filter($wizardArray, function ($key) use ($menuCode) {
return $key['menu_code'] == $menuCode ? true : false;
}, ARRAY_FILTER_USE_BOTH);
}
/*If its an array enter the index of the array to $index variable*/
public static function fillOnUndefined($variable,$index = null,$fillWith = null,$arrayDelimiter = ".")
{
if ( !$arrayDelimiter)
{
return null;
}
$index = trim($index,$arrayDelimiter);
if ( !$index && $index !== '0')
{
return false;
}
$indexes = explode($arrayDelimiter,$index);
$arrayDeep = $variable;
foreach ($indexes as $perIndex)
{
if ( !isset($arrayDeep[$perIndex]))
{
return $fillWith;
}
$arrayDeep = $arrayDeep[$perIndex];
}
return $arrayDeep;
}
public static function hexToBinary ( $hex )
{
if ( strlen($hex)<=0)
{
return null;
}
$str = "";
for($i=0;$i<strlen($hex);$i+=2)
$str .= chr(hexdec(substr($hex,$i,2)));
return $str;
}
public static function pickItemFromArray($index,array $targetArray)
{
try
{
$result = [ ];
foreach ($targetArray as $perIndex => $perValue)
{
if (isset($perValue[$index]))
{
$result[] = $perValue[$index];
}
}
return $result;
} catch ( Exception $e )
{
return [];
}
}
public static function pickNodeFromArray($index, $value, array $targetArray)
{
try {
$result = [];
foreach ($targetArray as $perIndex => $perValue) {
if (isset($perValue[$index]) && $perValue[$index] == $value) {
$result = $perValue;
break;
}
}
return $result;
} catch (Exception $e) {
return [];
}
}
public static function numberSortTurkish($number)
{
$returnString = '';
$numberValue = [
'inci' => [1,5,8,20,70,80],
'üncü' => [3,4,100],
'nci' => [2,7,50],
'ıncı' => [0,40,60,90],
'ncı' => [6],
'uncu' => [9,10,30]
];
if(strlen($number) < 4) {
if ($number % 10 == 0) {
$numberKey = $number;
} else $numberKey = substr($number, -1,1);
}
foreach ($numberValue as $orderKey => $numbers) {
if (array_search($numberKey, $numbers) !== false) {
$returnString = $orderKey;
}
}
return $returnString;
}
public static function now ( array $param = [] )
{
return date("Y-m-d H:i:s");
}
public static function todayDate ( array $param = [] )
{
return date("Y-m-d");
}
public static function moneyFormatWithTwoDecimals($money)
{
$money = str_replace(",","",$money);
return number_format($money,2,'.','');
}
public static function getXmlResponse ($view,$data)
{
$responseObj = App::make("Response");
return $responseObj::view($view,$data)->header('Content-Type', 'text/xml');
}
public static function preDie($args)
{
echo '<pre>';
print_r($args);
echo '</pre>';
die;
}
}

View File

@@ -0,0 +1,264 @@
<?php
if(!function_exists('config_path'))
{
/**
* Return the path to config files
* @param null $path
* @return string
*/
function config_path($path=null)
{
return app()->getConfigurationPath(rtrim($path, ".php"));
}
}
if(!function_exists('public_path'))
{
/**
* Return the path to public dir
* @param null $path
* @return string
*/
function public_path($path=null)
{
return rtrim(app()->basePath('public/'.$path), '/');
}
}
if(!function_exists('storage_path'))
{
/**
* Return the path to storage dir
* @param null $path
* @return string
*/
function storage_path($path=null)
{
return app()->storagePath($path);
}
}
if(!function_exists('database_path'))
{
/**
* Return the path to database dir
* @param null $path
* @return string
*/
function database_path($path=null)
{
return app()->databasePath($path);
}
}
if(!function_exists('resource_path'))
{
/**
* Return the path to resource dir
* @param null $path
* @return string
*/
function resource_path($path=null)
{
return app()->resourcePath($path);
}
}
if(!function_exists('lang_path'))
{
/**
* Return the path to lang dir
* @param null $str
* @return string
*/
function lang_path($path=null)
{
return app()->getLanguagePath($path);
}
}
if ( ! function_exists('asset'))
{
/**
* Generate an asset path for the application.
*
* @param string $path
* @param bool $secure
* @return string
*/
function asset($path, $secure = null)
{
return app('url')->asset($path, $secure);
}
}
if ( ! function_exists('elixir'))
{
/**
* Get the path to a versioned Elixir file.
*
* @param string $file
* @return string
*/
function elixir($file)
{
static $manifest = null;
if (is_null($manifest))
{
$manifest = json_decode(file_get_contents(public_path().'/build/rev-manifest.json'), true);
}
if (isset($manifest[$file]))
{
return '/build/'.$manifest[$file];
}
throw new InvalidArgumentException("File {$file} not defined in asset manifest.");
}
}
if ( ! function_exists('auth'))
{
/**
* Get the available auth instance.
*
* @return \Illuminate\Contracts\Auth\Guard
*/
function auth()
{
return app('Illuminate\Contracts\Auth\Guard');
}
}
if ( ! function_exists('bcrypt'))
{
/**
* Hash the given value.
*
* @param string $value
* @param array $options
* @return string
*/
function bcrypt($value, $options = array())
{
return app('hash')->make($value, $options);
}
}
if ( ! function_exists('redirect'))
{
/**
* Get an instance of the redirector.
*
* @param string|null $to
* @param int $status
* @param array $headers
* @param bool $secure
* @return \Illuminate\Routing\Redirector|\Illuminate\Http\RedirectResponse
*/
function redirect($to = null, $status = 302, $headers = array(), $secure = null)
{
if (is_null($to)) return app('redirect');
return app('redirect')->to($to, $status, $headers, $secure);
}
}
if ( ! function_exists('response'))
{
/**
* Return a new response from the application.
*
* @param string $content
* @param int $status
* @param array $headers
* @return \Symfony\Component\HttpFoundation\Response|\Illuminate\Contracts\Routing\ResponseFactory
*/
function response($content = '', $status = 200, array $headers = array())
{
$factory = app('Illuminate\Contracts\Routing\ResponseFactory');
if (func_num_args() === 0)
{
return $factory;
}
return $factory->make($content, $status, $headers);
}
}
if ( ! function_exists('secure_asset'))
{
/**
* Generate an asset path for the application.
*
* @param string $path
* @return string
*/
function secure_asset($path)
{
return asset($path, true);
}
}
if ( ! function_exists('secure_url'))
{
/**
* Generate a HTTPS url for the application.
*
* @param string $path
* @param mixed $parameters
* @return string
*/
function secure_url($path, $parameters = array())
{
return url($path, $parameters, true);
}
}
if ( ! function_exists('session'))
{
/**
* Get / set the specified session value.
*
* If an array is passed as the key, we will assume you want to set an array of values.
*
* @param array|string $key
* @param mixed $default
* @return mixed
*/
function session($key = null, $default = null)
{
if (is_null($key)) return app('session');
if (is_array($key)) return app('session')->put($key);
return app('session')->get($key, $default);
}
}
if ( ! function_exists('cookie'))
{
/**
* Create a new cookie instance.
*
* @param string $name
* @param string $value
* @param int $minutes
* @param string $path
* @param string $domain
* @param bool $secure
* @param bool $httpOnly
* @return \Symfony\Component\HttpFoundation\Cookie
*/
function cookie($name = null, $value = null, $minutes = 0, $path = null, $domain = null, $secure = false, $httpOnly = true)
{
$cookie = app('Illuminate\Contracts\Cookie\Factory');
if (is_null($name))
{
return $cookie;
}
return $cookie->make($name, $value, $minutes, $path, $domain, $secure, $httpOnly);
}
}

463
app/Core/Helper/helpers.php Normal file
View File

@@ -0,0 +1,463 @@
<?php
use App\Core\Helper\LanguageService;
use Illuminate\Container\Container;
use Illuminate\Support\Facades\App;
use Laravel\Lumen\Bus\PendingDispatch;
use Illuminate\Contracts\Bus\Dispatcher;
use Illuminate\Contracts\Debug\ExceptionHandler;
use Laravel\Lumen\Http\ResponseFactory;
use Symfony\Component\Debug\Exception\FatalThrowableError;
use Illuminate\Contracts\Broadcasting\Factory as BroadcastFactory;
use Illuminate\Support\Str;
function output($param)
{
$statusArr = [1 => "success", -1 => "exception", 0 => "error"];
$exceptionClassArr = ["exception" => "\Exception", "error" => "App\Exceptions\ApiErrorException"];
$statusCodeArr = [1 => 200, -1 => 500, 0 => 400];
$param["status"] = isset($param["status"]) ? $param["status"] : 1;
$status = isset($statusArr[$param["status"]]) ? $statusArr[$param["status"]] : "success";
$statusCode = isset($statusCodeArr[$param["status"]]) ? $statusCodeArr[$param["status"]] : 200;
$message = (isset($param['message']) ? $param['message'] : '');
$data = (isset($param['data']) ? $param['data'] : '');
$exceptionClass = isset($exceptionClassArr[$status]) ? new $exceptionClassArr[$status]($message) : null;
return ['status' => $status, 'message' => $message, 'data' => $data, 'statusCode' => $statusCode, "exceptionClass" => $exceptionClass];
}
function apiResponse($status = -1, $message = "", $data = [], $statusCode = null, $errorCode = null)
{
$genericMessage = "Bilinmeyen Bir Hata Oluştu";
$error = $status <= 0 ? true : false;
$statusCode = $statusCode ? $statusCode : 200;
$errorCode = $errorCode ? $errorCode : null;
//$statusCode = $error ? 500 : $statusCode;
$message = $status != -1 ? $message : $genericMessage;
$message = $message ? $message : null;
$data = $data && is_array($data) ? $data : [];
$responseData = [
"status" => $statusCode,
"error" => $error,
"errorCode" => $errorCode,
"message" => $message,
"data" => $data
];
/** ServiceLog **/
$serviceLogId = app('request')->serviceLogId;
$serviceLogRequestTime = app('request')->serviceLogRequestTime;
if (!empty($serviceLogId)) {
$updateServiceLog = [
'response' => json_encode($responseData),
'response_time' => microtime(true) - $serviceLogRequestTime,
'status' => 1
];
$serviceLog = App::make("App\Core\Service\ServiceLogService");
$serviceLog->update($serviceLogId, $updateServiceLog);
}
/** ServiceLog **/
return response()->json($responseData, $statusCode);
}
function fillOnUndefined($variable, $index = null, $fillWith = null, $arrayDelimiter = ".")
{
if (!$arrayDelimiter) {
return null;
}
if (!$index && $index !== '0' && $index !== 0) {
return false;
}
$indexes = explode($arrayDelimiter, $index);
$arrayDeep = $variable;
foreach ($indexes as $perIndex) {
if (!isset($arrayDeep[$perIndex])) {
return $fillWith;
}
$arrayDeep = $arrayDeep[$perIndex];
}
return $arrayDeep;
}
function fillOnUndefinedAndEmpty($variable, $index = null, $fillWith = null, $arrayDelimiter = ".")
{
if (!$arrayDelimiter) {
return null;
}
if (!$index && $index !== '' && $index !== '0' && $index !== 0) {
return false;
}
$indexes = explode($arrayDelimiter, $index);
$arrayDeep = $variable;
foreach ($indexes as $perIndex) {
if (!isset($arrayDeep[$perIndex]) || empty($arrayDeep[$perIndex])) {
return $fillWith;
}
$arrayDeep = $arrayDeep[$perIndex];
}
return $arrayDeep;
}
function createFolderAndSubFolder($structure, $path = __DIR__, &$createdPaths, $mode = 0777)
{
foreach ($structure as $folder => $subFolder) {
if (is_array($subFolder)) {
$newPath = "{$path}/{$folder}";
//$createdPaths[$newPath] = $newPath;
$createdPaths[] = $newPath;
if (!is_dir($newPath)) mkdir($newPath, $mode);
createFolderAndSubFolder($subFolder, $newPath, $createdPaths);
} else {
$newPath = "{$path}/{$subFolder}";
//$createdPaths[$newPath] = $newPath;
$createdPaths[] = $newPath;
if (!is_dir($newPath)) mkdir($newPath, $mode);
}
}
return $createdPaths;
}
function smartyModifierFileSize($size)
{
$size = max(0, (int)$size);
$units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
$power = $size > 0 ? floor(log($size, 1024)) : 0;
$convertSize = number_format($size / pow(1024, $power), 2, '.', ',');
$convertType = $units[$power];
return [$convertSize, $convertType];
}
function pickItemFromArray($index, array $targetArray)
{
try {
$result = [];
foreach ($targetArray as $perIndex => $perValue) {
if (isset($perValue[$index])) {
$result[] = $perValue[$index];
}
}
return $result;
} catch (Exception $e) {
return [];
}
}
function lang($word, array $parameters = [], $lang = null)
{
return LanguageService::lang($word, $parameters, $lang);
}
function getSystemLang()
{
return LanguageService::getCurrentLang();
}
function getSystemLangSession()
{
return session("sysLang");
}
function setSystemLangSession($language)
{
$validLanguages = LanguageService::getValidLanguages();
if (!in_array($language, $validLanguages)) {
throw new Exception("Invalid Language Selected language parameter : " . json_encode($language));
}
session()->set("sysLang", $language);
return $language;
}
function getSystemDefaultLang()
{
return LanguageService::getDefaultLang();
}
function getLanguageSupportList()
{
return LanguageService::getLanguageSupportList();
}
function upperCase($word, $charset = "UTF-8")
{
$word = str_replace("i", "İ", $word);
return mb_strtoupper($word, $charset);
}
function lowerCase($word, $charset = "UTF-8")
{
$word = str_replace("I", "ı", $word);
return mb_strtolower($word, $charset);
}
function uCase($word, $charset = "UTF-8")
{
$word = preg_replace("#(^\i)#", "İ", $word);
$word = preg_replace("#(^\ı)#", "I", $word);
return mb_convert_case($word, MB_CASE_TITLE, $charset);
}
function reIndexArrayKeys(array $targetArray, $startNo = 0)
{
if (!$targetArray) {
return [];
}
return array_combine(range($startNo, ($startNo - 1) + count($targetArray)), $targetArray);
}
function singleElementXMLArray($array = [])
{
return fillOnUndefined($array, 0) && is_array($array) ? $array : [$array];
}
function toArray($value): array
{
return is_array($value) ? $value : ($value !== null ? [$value] : []);
}
function singleElementArray($arrayElement, array $extraParams = null)
{
$isMultiArray = true;
if (!is_array($arrayElement)) {
return [];
}
foreach ($arrayElement as $perItem) {
if (gettype($perItem) != "array") {
$isMultiArray = false;
break;
}
}
if (!$isMultiArray) {
$isMultiArray = true;
foreach (array_keys($arrayElement) as $perKey) {
if (!is_numeric($perKey)) {
$isMultiArray = false;
break;
}
}
}
return $isMultiArray ? $arrayElement : array($arrayElement);
}
function generateRandomString($length = 5)
{
return \App\Core\Helper\PhpHelper::generateRandomString($length);
}
function humanReadableDate($date)
{
return date('d/m/Y', strtotime($date));
}
function language_key($title)
{
return Str::slug($title, $separator = '_', $language = 'en');
}
function getGuid()
{
$hash = md5(uniqid());
$guid = substr($hash, 0, 8) .
'-' .
substr($hash, 8, 4) .
'-' .
substr($hash, 12, 4) .
'-' .
substr($hash, 16, 4) .
'-' .
substr($hash, 20, 12);
return $guid;
}
function moneyDoubleFormat($money)
{
return number_format($money, 2, ',', '');
}
function moneyDoubleFormatDecimal($money)
{
return floatval(number_format($money, 2, '.', ''));
}
function moneyFourFormatDecimal($money)
{
return floatval(number_format($money, 4, '.', ''));
}
function getCodeGenerate($prefix = 'ENW')
{
return $prefix . date('ymd') . '-' . upperCase(generateRandomString(8));
}
function getPaymentGenerate($prefix = 'PYM')
{
$prefix = is_null($prefix) ? 'PYM' : $prefix;
return 'ENW' . $prefix . date('ymd') . '_' . upperCase(generateRandomString(8));
}
function getTicketCodeGenerate($prefix = 'TCK')
{
return $prefix . upperCase(generateRandomString(8));
}
function creditCardMask($cardNumber)
{
return substr($cardNumber, 0, 6) . '******' . substr($cardNumber, -4);
}
function occupancyCodeFormatted($occupancyCode)
{
$occupancyFormatted = [];
$adultCount = substr_count($occupancyCode, 'A');
if ($adultCount > 0) {
$occupancyFormatted[] = $adultCount . ' Adult';
}
$childCount = substr_count($occupancyCode, 'C');
if ($childCount > 0) {
$childAges = [];
$roomsChildArray = explode('C', $occupancyCode);
for ($i = 1; $i < count($roomsChildArray); $i++) {
if (!empty($roomsChildArray[$i]) || $roomsChildArray[$i] == 0) {
$childAges[] = $roomsChildArray[$i];
}
}
if (!empty($childAges)) {
$childAges = implode(', ', $childAges);
}
$occupancyFormatted[] = $childCount . ' Child' . (!empty($childAges) ? ' (' . $childAges . ')' : null);
}
if (!empty($occupancyFormatted)) {
$occupancyFormatted = implode(', ', $occupancyFormatted);
}
return $occupancyFormatted;
}
function occupancyCodeParser($occupancyCode)
{
$occupancy = [];
$occupancy['ADT'] = 0;
$occupancy['CHD'] = 0;
$occupancy['AGE'] = [];
$adultCount = substr_count($occupancyCode, 'A');
if ($adultCount > 0) {
$occupancy['ADT'] = $adultCount;
}
$childCount = substr_count($occupancyCode, 'C');
if ($childCount > 0) {
$childAges = [];
$roomsChildArray = explode('C', $occupancyCode);
for ($i = 1; $i < count($roomsChildArray); $i++) {
if (!empty($roomsChildArray[$i])) {
$childAges[] = $roomsChildArray[$i];
}
}
$occupancy['CHD'] = $childCount;
$occupancy['AGE'] = $childAges;
//$occupancyFormatted[] = $childCount . ' Child' . (!empty($childAges) ? ' (' . $childAges . ')' : null);
}
return $occupancy;
}
function occupancyGroup($maxAdult, $maxChild, $maxOccupancy, $excludeOccupancy = [])
{
$occupancyGroup = [];
//TODO: $excludeOccupancy
for ($i = 0; $i < $maxAdult; $i++) {
$occupancyCodeAdult = str_repeat('A', ($i + 1));
if (strlen($occupancyCodeAdult) > $maxOccupancy) {
break;
}
$occupancyGroup[] = $occupancyCodeAdult;
for ($j = 0; $j < $maxChild; $j++) {
$occupancyCodeChild = str_repeat('C', ($j + 1));
if (strlen($occupancyCodeChild) > $maxOccupancy) {
continue;
}
if (strlen($occupancyCodeAdult . $occupancyCodeChild) > $maxOccupancy) {
break;
}
$occupancyGroup[] = $occupancyCodeAdult . $occupancyCodeChild;
}
}
return $occupancyGroup;
}
function cancellationPolicyTextFormatted($isNonRefundable, $isFreeCancellation, $beforeArrivalDay, $type, $value, $currency, $languageCode = 'en')
{
$formattedText = null;
if (!$isFreeCancellation) {
if ($isNonRefundable) {
$formattedText = __('btn-irrevocable', [], $languageCode);
} else {
$formattedText = __('be-if_canceled_up_to_days', ['day' => $beforeArrivalDay], $languageCode) . ', ' . $value . ($type == 'PER' ? '%' : $currency) . ' ' . __('be-search-impose_penalty', [], $languageCode);
}
} else {
$formattedText = ($beforeArrivalDay > 0 ? __('be-up_to_days', ['day' => $beforeArrivalDay], $languageCode) : '') . ' ' . __('btn-free_cancellation', [], $languageCode);
}
return $formattedText;
}

View File

@@ -0,0 +1,60 @@
<?php
namespace App\Core\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class AffiliateRequestMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build ()
{
try
{
$params = $this->param;
$mailParams = $params['mailViewParams'] ;
$mailData = $params['mailData'] ;
$mailSenderAddress = Config::get('app.mailSenderAddress') ;
$mailTitle = $mailData['to']["name"]. ' | Affiliate Request Mail';
app('translator')->setLocale(fillOnUndefined($params['mailViewParams'],'language', 'en'));
/*echo view('emails.affiliateRequestMail', compact('mailParams', 'mailTitle'));
die();*/
return $this->from($mailSenderAddress, 'Extranetwork')
->view('emails.affiliateRequestMail', compact('mailParams', 'mailTitle'))
->to($mailData['to']["email"], $mailData['to']["name"])
->bcc($mailData['bcc'])
->subject($mailTitle)
->with(['message' => $this]);
}
catch ( Exception $e )
{
$message = $e->getFile()." ".$e->getLine()." ".$e->getMessage();
Log::error($message);
return output( ['status' => -1, 'message' => $e->getMessage()] );
}
}
}

View File

@@ -0,0 +1,13 @@
<?php
namespace App\Core\Mail;
class BaseMail
{
public function __construct ()
{
}
}

View File

@@ -0,0 +1,85 @@
<?php
namespace App\Core\Mail;
use App\Exceptions\ApiErrorException;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class BookingCancellationConfirmCodeMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build()
{
try {
$params = $this->param;
$mailSenderAddress = Config::get('app.mailSenderAddress');
$bookingService = App::make('App\Core\Service\BookingService');
$userService = App::make('App\Core\Service\UserService');
$requestData = [
'criteria' => [
['field' => 'booking_code', 'condition' => '=', 'value' => $params['bookingCode']]
],
'with' => ['bookingProperty.propertyBrand', 'bookingContact'],
'firstRow' => true
];
$bookingDetail = $bookingService->select($requestData);
if ($bookingDetail['status'] != 'success' || empty($bookingDetail['data'])) {
throw new ApiErrorException('Booking not found.');
}
$bookingDetail = $bookingDetail['data'];
$mailParams = [
'to' => $bookingDetail['booking_contact']['email'],
'toNameSurname' => $bookingDetail['booking_contact']['nameSurname'],
'bcc' => [],
'confirmCode' => $params['confirmCode'],
'bookingId' => fillOnUndefined($bookingDetail, 'id'),
'propertyId' => fillOnUndefined($bookingDetail, 'property_id'),
'bookingCode' => fillOnUndefined($bookingDetail, 'booking_code'),
'locale' => fillOnUndefined($bookingDetail['booking_contact'], 'language_code', 'en'),
];
/*echo view('emails.bookingCancellationConfirmCode', compact('mailParams'));
die();*/
$mailParams['bcc'][] = 'channel@extranetwork.com';
return $this->from($mailSenderAddress, 'Extranetwork')
->view('emails.bookingCancellationConfirmCode', compact('mailParams'))
->to($mailParams['to'], $mailParams['toNameSurname'])
->bcc($mailParams['bcc'])
->subject(__('api-mailing-cancellation_confirm_code-subject', ['bookingCode' => $mailParams['bookingCode']], $mailParams['locale']));
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
return output(['status' => -1, 'message' => $e->getMessage()]);
}
}
}

View File

@@ -0,0 +1,123 @@
<?php
namespace App\Core\Mail;
use App\Exceptions\ApiErrorException;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class BookingCancellationRequestMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build()
{
try {
$params = $this->param;
$mailSenderAddress = Config::get('app.mailSenderAddress');
$bookingService = App::make('App\Core\Service\BookingService');
$userService = App::make('App\Core\Service\UserService');
$requestData = [
'criteria' => [
['field' => 'booking_code', 'condition' => '=', 'value' => $params['bookingCode']]
],
'with' => [
'bookingPayment', 'bookingRoom.roomRateMapping.propertyRoom', 'bookingRoom.roomRateMapping.propertyRoomRate',
'bookingContact', 'bookingProperty.propertyBrand', 'bookingProperty.propertyExecutive', 'bookingProperty.propertyUser.user',
'bookingPropertyWeb', 'propertyBookingEngine', 'propertyBookingChannel'
],
'firstRow' => true
];
$bookingDetail = $bookingService->select($requestData);
if ($bookingDetail['status'] != 'success' || empty($bookingDetail['data'])) {
throw new ApiErrorException('Booking not found.');
}
$bookingDetail = $bookingDetail['data'];
//Language
$userData = $bookingDetail['booking_property']['property_user'];
$firstUserData = reset($userData);
$bookingLanguageCode = fillOnUndefined($firstUserData['user'], 'language', 'en');
//Mail Contact Data
$bcc = [];
foreach ($userData as $user) {
if ($user['user']['email'] != $firstUserData['user']['email']) {
$bcc[] = $user['user']['email'];
}
}
$reservationExecutives = [];
if (isset($bookingDetail['booking_property']['property_executive'])) {
$reservationExecutives = collect($bookingDetail['booking_property']['property_executive'])
->where('executive_type_id', '=', '7')
->values()->all();
}
foreach ($reservationExecutives as $reservationExecutive) {
$bcc[] = $reservationExecutive['email'];
}
$mailData = [
'to' => [
'name' => $bookingDetail['booking_property']['name'],
'email' => $firstUserData['user']['email']
]
];
$mailParams = [
'to' => $firstUserData['user']['email'],
'bcc' => $bcc,
'toNameSurname' => $bookingDetail['booking_property']['name'],
'bookingContactNameSurname' => $bookingDetail['booking_contact']['nameSurname'],
'bookingCode' => fillOnUndefined($bookingDetail, 'booking_code'),
'locale' => $bookingLanguageCode,
];
$mailParams['detailUrl'] = config('app.client_server').'/app/network/reservation/'.$bookingDetail['id'].'?propertyid='.$bookingDetail['property_id'];
/*echo view('emails.bookingCancellationRequest', compact('mailParams'));
die();*/
$mailParams['bcc'][] = 'channel@extranetwork.com';
return $this->from($mailSenderAddress, 'Extranetwork')
->view('emails.bookingCancellationRequest', compact('mailParams'))
->to($mailParams['to'], $mailParams['toNameSurname'])
->bcc($mailParams['bcc'])
->subject(__('api-mailing-cancellation_request-subject', ['bookingCode' => $mailParams['bookingCode']], $mailParams['locale']));
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
return output(['status' => -1, 'message' => $e->getMessage()]);
}
}
}

View File

@@ -0,0 +1,54 @@
<?php
namespace App\Core\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class BookingEngineSearchReportMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build()
{
try {
$params = $this->param;
$mailSenderAddress = Config::get('app.mailSenderAddress');
/*echo view('emails.bookingEngineSearchReportMail', compact('params'));
die();*/
$bcc = $params['propertyUserEmail'];
return $this->from($mailSenderAddress, 'Extranetwork')
->view('emails.bookingEngineSearchReportMail', compact('params'))
->to($mailSenderAddress, 'Extranetwork')
->bcc($bcc)
->subject($params['propertyName'].' - Günlük İşlem Raporu : '. $params['date']);
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
return output(['status' => -1, 'message' => $e->getMessage()]);
}
}
}

View File

@@ -0,0 +1,120 @@
<?php
namespace App\Core\Mail;
use App\Exceptions\ApiErrorException;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class BookingInvoiceUpdateMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build()
{
try {
$params = $this->param;
$bookingService = App::make("App\Core\Service\BookingService");
$bookingDetailParam = [
'criteria' => [
['field' => 'booking_code', 'condition' => '=', 'value' => $params['bookingCode']],
],
'with' => ['property.propertyBrand', 'property.propertyExecutive', 'property.propertyUser.user','property.propertyBookingEngineToken'],
'firstRow' => true
];
$bookingDetail = $bookingService->select($bookingDetailParam);
if ($bookingDetail['status'] != 'success') {
throw new ApiErrorException($bookingDetail['message']);
}
$bookingDetail = $bookingDetail['status'] == 'success' && !empty($bookingDetail['data']) ? $bookingDetail['data'] : null;
$property = $bookingDetail['property'];
//Mail Contact Data
$reservationExecutives = [];
if (isset($property['property_executive'])) {
$reservationExecutives = collect($property['property_executive'])
->where('executive_type_id', '=', '7')
->values()->all();
}
foreach ($reservationExecutives as $reservationExecutive) {
$bcc[] = $reservationExecutive['email'];
}
$bcc[] = "channel@extranetwork.com";
$userData = $property['property_user'];
$firstUserData = reset($userData);
foreach ($userData as $user) {
if ($user['user']['email'] != $firstUserData['user']['email']) {
$bcc[] = $user['user']['email'];
}
}
$mailData = [
'to' => [
'name' => $firstUserData['user']['nameSurname'],
'email' => $firstUserData['user']['email'],
],
'bcc' => $bcc
];
$locale = fillOnUndefined($firstUserData['user'], 'language', 'tr');
$mailSenderAddress = Config::get('app.mailSenderAddress');
app('translator')->setLocale($locale);
$mailParams = [
'propertyName' => $property['name'],
'bookingCode' => $params['bookingCode'],
'logo' => $property['property_brand']['logoUrl'],
'btnUrl' => config('app.bookingEngineUrl') . '/' . $property['property_booking_engine_token']['token'] . '/' . $locale . '/booking-detail/' . $params['bookingCode'],
];
/*echo view('emails.bookingInvoiceUpdateMail', compact('mailParams'));
die();*/
return $this->from($mailSenderAddress, 'Extranetwork - ' . $mailParams['propertyName'])
->view('emails.bookingInvoiceUpdateMail', compact('mailParams'))
->to($mailData['to']["email"], $mailData['to']["name"])
->bcc($mailData['bcc'])
->subject(__('api-mailing-booking-invoice_update-title', ['bookingCode' => $mailParams['bookingCode']]))
->with(['message' => $this]);
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
return output(['status' => -1, 'message' => $e->getMessage()]);
}
}
}

View File

@@ -0,0 +1,101 @@
<?php
namespace App\Core\Mail;
use App\Exceptions\ApiErrorException;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class BookingPaymentDataCodeMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build()
{
try {
$params = $this->param;
$mailSenderAddress = Config::get('app.mailSenderAddress');
$bookingService = App::make('App\Core\Service\BookingService');
$userService = App::make('App\Core\Service\UserService');
$requestData = [
'criteria' => [
['field' => 'id', 'condition' => '=', 'value' => $params['booking_id']]
],
//'with' => ['bookingProperty.propertyExecutive', 'bookingProperty.propertyBookingEngineToken', 'bookingProperty.propertyBrand', 'bookingContact', 'bookingChannel', 'bookingPayment', 'bookingPaymentType', 'bookingStatus'],
'firstRow' => true
];
$booking = $bookingService->select($requestData);
if ($booking['status'] != 'success' || empty($booking['data'])) {
throw new ApiErrorException(lang('Booking not found'));
}
$booking = $booking['data'];
$requestData = [
'criteria' => [
['field' => 'id', 'condition' => '=', 'value' => $params['user_id']]
],
'firstRow' => true
];
$user = $userService->select($requestData);
if ($user['status'] != 'success' || empty($user['data'])) {
throw new ApiErrorException(lang('User not found'));
}
$user = $user['data'];
$mailParams = [
'to' => $user['email'],
'toNameSurname' => $user['nameSurname'],
'bcc' => [],
'unlockCode' => $params['unlock_code'],
'bookingId' => fillOnUndefined($booking, 'id'),
'propertyId' => fillOnUndefined($booking, 'property_id'),
'bookingCode' => fillOnUndefined($booking, 'booking_code'),
'locale' => fillOnUndefined($user, 'language', 'en'),
];
/*echo view('emails.bookingPaymentDataCode', compact('mailParams'));
die();*/
$mailParams['bcc'][] = 'burhan@extranetwork.com';
return $this->from($mailSenderAddress, 'Extranetwork')
->view('emails.bookingPaymentDataCode', compact('mailParams'))
->to($mailParams['to'], $mailParams['toNameSurname'])
->bcc($mailParams['bcc'])
->subject(__('api-mailing-payment_data_code-subject',['bookingCode' => $mailParams['bookingCode']],$mailParams['locale']));
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
return output(['status' => -1, 'message' => $e->getMessage()]);
}
}
}

View File

@@ -0,0 +1,113 @@
<?php
namespace App\Core\Mail;
use App\Exceptions\ApiErrorException;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class BookingPropertyAddonUpdateMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build()
{
try {
$params = $this->param;
$propertyService = App::make("App\Core\Service\PropertyService");
$propertyParam = [
'criteria' => [
['field' => 'id', 'condition' => '=', 'value' => $params['propertyId']],
],
'with' => ['propertyBrand', 'propertyExecutive', 'propertyUser.user','propertyBookingEngineToken'],
'firstRow' => true
];
$property = $propertyService->select($propertyParam);
if ($property['status'] != 'success') {
throw new ApiErrorException($property['message']);
}
$property = $property['data'];
//Mail Contact Data
$reservationExecutives = [];
if (isset($property['property_executive'])) {
$reservationExecutives = collect($property['property_executive'])
->where('executive_type_id', '=', '7')
->values()->all();
}
foreach ($reservationExecutives as $reservationExecutive) {
$bcc[] = $reservationExecutive['email'];
}
$bcc[] = "channel@extranetwork.com";
$userData = $property['property_user'];
$firstUserData = reset($userData);
foreach ($userData as $user) {
if ($user['user']['email'] != $firstUserData['user']['email']) {
$bcc[] = $user['user']['email'];
}
}
$mailData = [
'to' => [
'name' => $firstUserData['user']['nameSurname'],
'email' => $firstUserData['user']['email'],
],
'bcc' => $bcc
];
$locale = fillOnUndefined($firstUserData['user'], 'language', 'tr');
$mailSenderAddress = Config::get('app.mailSenderAddress');
app('translator')->setLocale($locale);
$mailParams = [
'propertyName' => $property['name'],
'bookingCode' => $params['bookingCode'],
'addonLanguageKey' => $params['addonLanguageKey'],
'logo' => $property['property_brand']['logoUrl'],
'btnUrl' => config('app.bookingEngineUrl') . '/' . $property['property_booking_engine_token']['token'] . '/' . $locale . '/booking-detail/' . $params['bookingCode'],
];
return $this->from($mailSenderAddress, 'Extranetwork - ' . $mailParams['propertyName'])
->view('emails.bookingPropertyAddonUpdateMail', compact('mailParams'))
->to($mailData['to']["email"], $mailData['to']["name"])
->bcc($mailData['bcc'])
->subject(__('api-mailing-booking-addon_update-title', ['bookingCode' => $mailParams['bookingCode'], 'addonLanguageKey' => __($mailParams['addonLanguageKey'])]))
->with(['message' => $this]);
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
return output(['status' => -1, 'message' => $e->getMessage()]);
}
}
}

View File

@@ -0,0 +1,140 @@
<?php
namespace App\Core\Mail;
use App\Exceptions\ApiErrorException;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
use Exception;
class BookingTicketMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build()
{
try {
$params = $this->param;
$mailSenderAddress = Config::get('app.mailSenderAddress');
$bookingService = App::make('App\Core\Service\BookingService');
$requestData = [
'criteria' => [
['field' => 'id', 'condition' => '=', 'value' => $params['booking_id']]
],
'with' => ['bookingProperty.propertyExecutive', 'bookingProperty.propertyBookingEngineToken', 'bookingProperty.propertyBrand', 'bookingContact', 'bookingChannel', 'bookingPayment', 'bookingPaymentType', 'bookingStatus'],
'firstRow' => true
];
$booking = $bookingService->select($requestData);
if ($booking['status'] != 'success' || empty($booking['data'])) {
throw new ApiErrorException(lang('Booking not found'));
}
$booking = $booking['data'];
$locale = fillOnUndefined($params, 'locale', 'en');
if (!is_null($params['user'])) {
$locale = $booking['booking_contact']['language_code'];
}
app('translator')->setLocale($locale);
$propertyLogo = 'https://www.extranetwork.com/assets/img/logo/mini-logo.png';
if (isset($booking['booking_property']['property_brand']['logo_name'])) {
$propertyLogo = Config::get('app.imageUrl') . '/property-photos/' . $booking['booking_property']['id'] . "/logo/" . $booking['booking_property']['property_brand']['logo_name'] . '_250x250.' . $booking['booking_property']['property_brand']['logo_file_ext'];
}
$bookingContact = [
'mail' => $booking['booking_contact']['email'],
'nameSurname' => $booking['booking_contact']['nameSurname'],
];
if (!isset($booking['booking_property']['property_executive'])) {
throw new ApiErrorException(lang('Property Executive not found'));
}
$propertyExecutives = collect($booking['booking_property']['property_executive'])->where('status', 1)->where('executive_type_id', 7)->pluck('email')->toArray();
$params['subject'] = __('api-mailing-booking_ticket-subject', ['booking_code' => $booking['booking_code']]);//'Booking Ticket Message: ' . $booking['booking_code'];
$params['mailSenderName'] = 'Extranetwork - ' . $booking['booking_property']['name'];
if (!is_null($params['user'])) {
$mailParams = [
'to' => $bookingContact['mail'],
'toNameSurname' => $bookingContact['mail'],
'bcc' => [],
'title' => __('general-hi') . ', ' . $bookingContact['nameSurname'],
'logo' => $propertyLogo,
'message' => __('api-mailing-booking_ticket-message-user', ['booking_code' => $booking['booking_code']]),
'btnTitle' => __('api-mailing-booking_ticket-btn-message'),
'btnUrl' => config('app.bookingEngineUrl') . '/' . $booking['booking_property']['property_booking_engine_token']['token'] . '/' . $locale . '/booking-detail/' . $booking['booking_code'],
];
} else {
if (empty($propertyExecutives)) {
throw new ApiErrorException(lang('Property Executive not found'));
}
$mailParams = [
'to' => $propertyExecutives[0],
'toNameSurname' => null,
'bcc' => $propertyExecutives,
'title' => __('general-hi') . ',',
'logo' => $propertyLogo,
'message' => __('api-mailing-booking_ticket-message-enw-user', ['booking_code' => $booking['booking_code'], 'property_name' => $booking['booking_property']['name']]),
'btnTitle' => __('api-mailing-booking_ticket-btn-message'),
'btnUrl' => config('app.client_server') . '/app/network/reservation/' . $booking['id'].'?propertyid='.$booking['property_id'],
];
}
//$bcc[] = "sales@extranetwork.com";
$bcc = $mailParams['bcc'];
$bcc[] = "channel@extranetwork.com";
/*echo view('emails.bookingTicketMail', compact('mailParams'));
die();*/
return $this->from($mailSenderAddress, $params['mailSenderName'])
->view('emails.bookingTicketMail', compact('mailParams'))
->to($mailParams['to'], $mailParams['toNameSurname'])
->bcc($bcc)
->subject($params['subject']);
} catch (ApiErrorException $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
die();
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
die();
}
}
}

View File

@@ -0,0 +1,277 @@
<?php
namespace App\Core\Mail;
use App\Exceptions\ApiErrorException;
use Carbon\Carbon;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class CancelBookingMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build()
{
try {
$params = $this->param;
$propertyService = App::make("App\Core\Service\PropertyService");
$bookingService = App::make("App\Core\Service\BookingService");
$propertyBrandService = App::make("App\Core\Service\PropertyBrandService");
$bookingDetailParam = [
'criteria' => [
['field' => 'id', 'condition' => '=', 'value' => $params['booking_id']]
],
'with' => [
'bookingPayment', 'bookingRoom.roomRateMapping.propertyRoom','bookingRoom.roomRateMapping.propertyRoomRate',
'bookingContact','bookingProperty.propertyBrand', 'bookingProperty.propertyExecutive', 'bookingProperty.propertyUser.user',
'bookingPropertyWeb', 'propertyBookingEngine', 'propertyBookingChannel'
],
'firstRow' => true
];
$bookingData = $bookingService->select($bookingDetailParam);
$bookingData = $bookingData['data'];
$hostAddress = Config::get('app.bookingEngineUrl') . '/' . $bookingData['property_booking_engine']['token'] . '/' . $bookingData['booking_contact']['language_code'] . '/booking-detail/' . $bookingData['booking_code'];
$brandRequestData = ['property_id' => $bookingData['property_id']];
$getPropertyBrand = $propertyBrandService->getPropertyBrand($brandRequestData);
if ($getPropertyBrand['status'] != "success") {
throw new Exception($getPropertyBrand['message']);
}
$propertyBrand = $getPropertyBrand['data'];
$propertyBrandLogo = isset($propertyBrand['name'])
? Config::get('app.fileSystemDriver') . '/property-photos/' . $propertyBrand['property_id'] . "/logo/" . $propertyBrand['name'] . '_250x250.' . $propertyBrand['logo_file_ext']
: null;
$roomOrder = 1;
$bookingChannelRoom = [];
foreach ($bookingData['booking_room'] as $bookingRoom) {
if (!empty($bookingRoom['room_rate_mapping']['property_room'])) {
$bookingRoom['room_name'] = $bookingRoom['room_rate_mapping']['property_room']['name'];
}
if (!empty($bookingRoom['room_rate_mapping']['property_room_rate'])) {
$bookingRoom['room_rate_name'] = $bookingRoom['room_rate_mapping']['property_room_rate']['name'];
}
$extraParam = null;
if (!empty($bookingRoom['extra_param'])) {
$extraParamDecode = json_decode($bookingRoom['extra_param'], 1);
foreach ($extraParamDecode as $extraParamKey => $extraParamValue) {
$extraParamTitle = explode('_', $extraParamKey);
foreach ($extraParamTitle as $extraParamTitleKey => $extraParamTitleValue) {
$extraParamTitle[$extraParamTitleKey] = ucwords($extraParamTitleValue);
}
$extraParamTitle = implode(' ', $extraParamTitle);
$extraParam[$extraParamKey] = [
'title' => $extraParamTitle,
'value' => $extraParamValue,
];
}
}
$additionalFee = null;
if (!empty($bookingRoom['rate_detail'])) {
$rateDetail = json_decode($bookingRoom['rate_detail'], 1);
if(isset($rateDetail['taxes']) && $bookingData['channel_manager_id'] == 2) {
$additionalFee = $rateDetail['taxes'];
}
}
$bookingChannelRoom[] = [
'roomOrder' => $roomOrder,
'roomName' => $bookingRoom['room_name'],
'roomRateName' => $bookingRoom['room_rate_name'],
'occupancyCode' => $bookingRoom['occupancy_code'],
'occupancyText' => occupancyCodeFormatted($bookingRoom['occupancy_code']),
'amount' => $bookingRoom['amount'],
'discount_amount' => $bookingRoom['discount_amount'],
'total' => $bookingRoom['total'],
'currencyCode' => $bookingRoom['currency_code'],
'dailyAmount' => !empty($bookingRoom['daily_amount']) ? json_decode($bookingRoom['daily_amount'],1) : null,
'extraParam' => $extraParam,
'occupancyFormatted' => occupancyCodeFormatted($bookingRoom['occupancy_code']),
'additionalFee' => $additionalFee
];
//$bookingChannelRoom[] = $roomOrder . '. ' . $bookingRoom['room_name'] . ' - ' . $bookingRoom['room_rate_name'] . ' - ' . occupancyCodeFormatted($bookingRoom['occupancy_code']);
$roomOrder++;
}
$userData = $bookingData['booking_property']['property_user'];
$firstUserData = reset($userData);
if (in_array($bookingData['property_booking_channel']['channel_category_id'], [2,3])) {
$bookingLanguageCode = fillOnUndefined($bookingData['booking_contact'], 'language_code', 'en');
}else {
$bookingLanguageCode = fillOnUndefined($firstUserData['user'], 'language', 'en');
}
$bookingChannelPaymentType = __('property_booking_payment_type-pay_at_hotel',[],$bookingLanguageCode);
$bookingChannelPaymentSource = null;
if ($bookingData['booking_payment']['payment_type_code'] == 'CRD') {
$bookingChannelPaymentType = __('property_booking_payment_type-credit_card',[],$bookingLanguageCode);
if ($bookingData['booking_payment']['payment_source_code'] == 'OTA') {
$bookingChannelPaymentSource = __('enw-ota-credit_card',[],$bookingLanguageCode);
}
if ($bookingData['booking_payment']['payment_source_code'] == 'GST') {
$bookingChannelPaymentSource = __('enw-guest-credit_card',[],$bookingLanguageCode);
}
}
$creditCardInformation = null;
if (!is_null($bookingData['booking_payment']['extra_param'])) {
$paymentData = json_decode($bookingData['booking_payment']['extra_param'], 1);
if (isset($paymentData['attributes']['guarantee'])) {
$creditCardInformation['cardNumber'] = isset($paymentData['attributes']['guarantee']['card_number']) ? $paymentData['attributes']['guarantee']['card_number'] : null;
$creditCardInformation['cardHolderName'] = isset($paymentData['attributes']['guarantee']['cardholder_name']) ? $paymentData['attributes']['guarantee']['cardholder_name'] : null;
$creditCardInformation['expirationDate'] = isset($paymentData['attributes']['guarantee']['expiration_date']) ? $paymentData['attributes']['guarantee']['expiration_date'] : null;
$creditCardInformation['cvv'] = isset($paymentData['attributes']['guarantee']['cvv']) ? $paymentData['attributes']['guarantee']['cvv'] : null;
}
}
//Genius Member
$bookingContactExtraParam = null;
if(!empty($bookingData['booking_contact']['extra_param'])) {
$bookingContactExtraParam = json_decode($bookingData['booking_contact']['extra_param'],1);
}
$isBookingGenius = false;
if(isset($bookingContactExtraParam['is_genius']) && $bookingContactExtraParam['is_genius']) {
$isBookingGenius = true;
}
$mailParams = [
'bookingId' => $bookingData['id'],
'bookingCode' => $bookingData['booking_code'],
'propertyId' => $bookingData['booking_property']['id'],
'booking_code' => $bookingData['booking_code'],
'search_key' => $bookingData['search_key'],
'channel_token' => $bookingData['channel_token'],
'booking_engine_token' => $bookingData['booking_engine_token'],
'checkin_date' => Carbon::parse($bookingData['checkin_date'])->format('d.m.Y'),
'checkout_date' => Carbon::parse($bookingData['checkout_date'])->format('d.m.Y'),
'payment_type_code' => $bookingData['booking_payment']['payment_type_code'],
'payment_source_code' => $bookingData['booking_payment']['payment_source_code'],
'room_amount' => $bookingData['room_amount'],
'addon_amount' => $bookingData['addon_amount'],
'discount_amount' => $bookingData['discount_amount'],
'total' => $bookingData['total'],
'currency_code' => $bookingData['currency_code'],
'name_surname' => $bookingData['booking_contact']['nameSurname'],
'countryCode' => upperCase($bookingData['booking_contact']['country_code']),
'email' => $bookingData['booking_contact']['email'],
'property_name' => $bookingData['booking_property']['name'],
'url' => $hostAddress,
'logo' => $bookingData['booking_property']['property_brand']['logoUrl'],
'language_code' => $bookingData['booking_contact']['language_code'],
'bookingChannelId' => $bookingData['channel_id'],
'bookingChannelName' => fillOnUndefined($bookingData['property_booking_channel'], 'name'),
'bookingChannelCategoryId' => $bookingData['property_booking_channel']['channel_category_id'],
'bookingChannelCode' => $bookingData['channel_booking_code'],
'bookingChannelContactNameSurname' => $bookingData['booking_contact']['nameSurname'],
'bookingChannelContactEmail' => $bookingData['booking_contact']['email'],
'bookingChannelContactPhone' => $bookingData['booking_contact']['phone_number'],
'bookingChannelNote' => $bookingData['booking_contact']['note'],
'bookingChannelRoom' => $bookingChannelRoom,
'bookingChannelPaymentType' => $bookingChannelPaymentType,
'bookingChannelPaymentSource' => $bookingChannelPaymentSource,
'creditCardInformation' => $creditCardInformation,
'isBookingGenius' => $isBookingGenius
];
//Mail Contact Data
$reservationExecutives = [];
if (isset($bookingData['booking_property']['property_executive'])) {
$reservationExecutives = collect($bookingData['booking_property']['property_executive'])
->where('executive_type_id', '=', '7') // sadece rezervasyon yetkisi olanlar ...
->values()->all();
}
foreach ($reservationExecutives as $reservationExecutive) {
$bcc[] = $reservationExecutive['email'];
}
$bcc[] = "channel@extranetwork.com";
foreach ($userData as $user) {
if ($user['user']['email'] != $firstUserData['user']['email']) {
$bcc[] = $user['user']['email'];
}
}
//Booking Engine ve Offline Channel to Customer Info's
if (in_array($bookingData['property_booking_channel']['channel_category_id'], [2,3])) {
$mailData = [
'to' => [
'name' => $bookingData['booking_contact']['nameSurname'],
'email' => $bookingData['booking_contact']['email']
]
];
} else {
$mailData = [
'to' => [
'name' => $bookingData['booking_property']['name'],
'email' => $firstUserData['user']['email']
]
];
}
$mailData['bcc'] = $bcc;
$mailSenderAddress = Config::get('app.mailSenderAddress');
//app('translator')->setLocale(fillOnUndefined($firstUserData['user'], 'language', 'tr'));
app('translator')->setLocale($bookingLanguageCode);
$mailParams['showCreditCardUrl'] = null;
if(!empty($mailParams['creditCardInformation'])) {
$mailParams['showCreditCardUrl'] = Config::get('app.client_server').'/app/network/reservation/'.$mailParams['bookingId'].'?propertyid='.$mailParams['propertyId'];
}
/*echo view('emails.cancelBookingMail', compact('mailParams'));
die();*/
return $this->from($mailSenderAddress, 'Extranetwork - ' . $mailParams['property_name'])
->view('emails.cancelBookingMail', compact('mailParams'))
->to($mailData['to']["email"], $mailData['to']["name"])
->bcc($mailData['bcc'])
->subject(__('api-malling-booking-cancel_booking-title', ['channel' => $mailParams['bookingChannelName']]))
->with(['message' => $this]);
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
return output(['status' => -1, 'message' => $e->getMessage()]);
}
}
}

View File

@@ -0,0 +1,70 @@
<?php
namespace App\Core\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class ChannelManagerNotificationMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build()
{
try {
$params = $this->param;
$mailSenderAddress = Config::get('app.mailSenderAddress');
$propertyService = App::make('App\Core\Service\PropertyService');
$requestData = [
'criteria' => [
['field' => 'id', 'condition' => '=', 'value' => $params['propertyId']]
],
'with' => ['propertyUser.user'],
'firstRow' => true
];
$propertyDetail = $propertyService->select($requestData);
$propertyUser = [];
if($propertyDetail['status'] == 'success' && !empty($propertyDetail['data'])) {
$propertyUser = collect($propertyDetail['data']['property_user'])->where('status',1)->pluck('user.email')->toArray();
}
/*echo view('emails.channelManagerNotificationMail', compact('params'));
die();*/
return $this->from($mailSenderAddress, 'Extranetwork')
->view('emails.channelManagerNotificationMail', compact('params'))
->to('channel@extranetwork.com', 'Extranetwork Channel')
->bcc($propertyUser)
->subject('Channel Update Error: ' . $params['propertyName']);
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
return output(['status' => -1, 'message' => $e->getMessage()]);
}
}
}

View File

@@ -0,0 +1,58 @@
<?php
namespace App\Core\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class ContactFormMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build ()
{
try
{
$params = $this->param;
$mailParams = $params['mailViewParams'] ;
$mailData = $params['mailData'] ;
$mailSenderAddress = Config::get('app.mailSenderAddress') ;
$mailTitle = $mailData['to']["name"]. ' Contact Form (' . $mailParams['name']. ' '.$mailParams['surname']. ')' ;
app('translator')->setLocale('en');
return $this->from($mailSenderAddress, $mailParams['name']. ' '.$mailParams['surname'])
->view('emails.contactFormMail', compact('mailParams', 'mailTitle'))
->to($mailData['to']["email"], $mailData['to']["name"])
->bcc($mailData['bcc'])
->subject($mailTitle)
->with(['message' => $this]);
}
catch ( Exception $e )
{
$message = $e->getFile()." ".$e->getLine()." ".$e->getMessage();
Log::error($message);
return output( ['status' => -1, 'message' => $e->getMessage()] );
}
}
}

View File

@@ -0,0 +1,55 @@
<?php
namespace App\Core\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class DailyReportMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build()
{
try {
$params = $this->param;
$mailSenderAddress = Config::get('app.mailSenderAddress');
/*echo view('emails.dailyReportMail', compact('params'));
die();*/
$to = 'yoy@extranetwork.com';
$bcc[] = 'burhan@extranetwork.com';
return $this->from($mailSenderAddress, 'Extranetwork')
->view('emails.dailyReportMail', compact('params'))
->to($to, 'Extranetwork')
->bcc($bcc)
->subject('Extranetwork Summary Report - '. $params['daily']['period']);
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
return output(['status' => -1, 'message' => $e->getMessage()]);
}
}
}

View File

@@ -0,0 +1,58 @@
<?php
namespace App\Core\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class DailyReportMailSales extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build()
{
try {
$params = $this->param;
$mailSenderAddress = Config::get('app.mailSenderAddress');
/*echo view('emails.dailyReportMailSales', compact('params'));
die();*/
$to = $params['email'];
$bcc[] = 'yoy@extranetwork.com';
$bcc[] = 'burhan@extranetwork.com';
$bcc[] = 'cemile@extranetwork.com';
return $this->from($mailSenderAddress, 'Extranetwork')
->view('emails.dailyReportMailSales', compact('params'))
->to($to, 'Extranetwork')
->bcc($bcc)
->subject('Extranetwork Summary Report - '. $params['daily']['period'].' - '. $params['name']);
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
return output(['status' => -1, 'message' => $e->getMessage()]);
}
}
}

View File

@@ -0,0 +1,54 @@
<?php
namespace App\Core\Mail;
use Exception;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class EnwContactFormMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build ()
{
try
{
$params = $this->param;
$mailParams = $params['mailViewParams'] ;
$mailData = $params['mailData'] ;
$mailTitle = __('myweb-contact-contact_form-title');
app('translator')->setLocale($mailParams['language']);
return $this->view('emails.enwContactFormMail', compact('mailParams', 'mailTitle'))
->to($mailData['to']["email"], $mailData['to']["name"])
->bcc($mailData['bcc'])
->subject($mailTitle);
}
catch ( Exception $e )
{
$message = $e->getFile()." ".$e->getLine()." ".$e->getMessage();
Log::error($message);
return output( ['status' => -1, 'message' => $e->getMessage()] );
}
}
}

View File

@@ -0,0 +1,60 @@
<?php
namespace App\Core\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class InventoryActionMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build()
{
try {
$params = $this->param;
$mailSenderAddress = Config::get('app.mailSenderAddress');
app('translator')->setLocale(fillOnUndefined($params, 'locale', 'en'));
$params['title'] = $params['propertyName'] . ' - ' . __('enw-action-mail-title');
$params['channelContact'] = $params['channelContact'];
if(empty($params['channelContact'])) {
return false;
}
/*echo view('emails.inventoryActionMail', compact('params'));
die();*/
return $this->from($mailSenderAddress, 'Extranetwork - '.$params['propertyName'])
->view('emails.inventoryActionMail', compact('params'))
//->to($logMailAddress, 'Development Team')
->bcc($params['channelContact'])
->subject($params['title']);
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
return output(['status' => -1, 'message' => $e->getMessage()]);
}
}
}

View File

@@ -0,0 +1,60 @@
<?php
namespace App\Core\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class InventoryPdfLinkMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build()
{
try {
$params = $this->param;
$mailSenderAddress = Config::get('app.mailSenderAddress');
app('translator')->setLocale(fillOnUndefined($params, 'locale', 'en'));
$params['title'] = $params['propertyName'] . ' - ' . __('enw-inventory-mail-pdf-link');
$params['channelContact'] = $params['channelContact'];
if(empty($params['channelContact'])) {
return false;
}
/*echo view('emails.inventoryActionMail', compact('params'));
die();*/
return $this->from($mailSenderAddress, 'Extranetwork - '.$params['propertyName'])
->view('emails.inventoryPdfLinkMail', compact('params'))
//->to($logMailAddress, 'Development Team')
->bcc($params['channelContact'])
->subject($params['title']);
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
return output(['status' => -1, 'message' => $e->getMessage()]);
}
}
}

52
app/Core/Mail/LogMail.php Normal file
View File

@@ -0,0 +1,52 @@
<?php
namespace App\Core\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class LogMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 2;
public $timeout = 20;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build()
{
try {
$params = $this->param;
$logMailAddress = Config::get('app.logMailAddress');
$mailSenderAddress = Config::get('app.mailSenderAddress');
$params['title'] = 'ENW LOG - ' . $params['title'];
app('translator')->setLocale('tr');
return $this->from($mailSenderAddress, 'Development Team')
->view('emails.logMail', compact('params'))
->to($logMailAddress, 'Development Team')
//->bcc(['bd@extranetwork.com'])
->subject($params['title']);
} catch (\Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
return output(['status' => -1, 'message' => $e->getMessage()]);
}
}
}

View File

@@ -0,0 +1,64 @@
<?php
namespace App\Core\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class ManualPaymentMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build ()
{
try
{
$params = $this->param;
$mailParams = $params['mailViewParams'] ;
$mailData = $params['mailData'] ;
$mailSenderAddress = Config::get('app.mailSenderAddress') ;
app('translator')->setLocale($mailParams["language_code"]);
$description = __('api-manual_payment_mail-desc',[
'title' => $mailParams['process_title'] ,
'date' => $mailParams['date_time'],
'amount' => $mailParams['amount'],
'currency' => $mailParams['currency']
]);
return $this->from($mailSenderAddress, 'Extranetwork - '.$mailParams['property_name'])
->view('emails.manualPaymentMail', compact('mailParams', 'description'))
->to($mailData['to']["email"])
->bcc($mailData['bcc'])
->subject(__('api-manual_payment_mail-subject'))
->with(['message' => $this]);
}
catch ( Exception $e )
{
$message = $e->getFile()." ".$e->getLine()." ".$e->getMessage();
Log::error($message);
return output( ['status' => -1, 'message' => $e->getMessage()] );
}
}
}

View File

@@ -0,0 +1,264 @@
<?php
namespace App\Core\Mail;
use App\Core\Service\PropertyBrandService;
use App\Exceptions\ApiErrorException;
use Carbon\Carbon;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class ModifiedBookingMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build()
{
try {
$params = $this->param;
$propertyService = App::make("App\Core\Service\PropertyService");
$bookingService = App::make("App\Core\Service\BookingService");
$propertyBrandService = App::make("App\Core\Service\PropertyBrandService");
$bookingDetailParam = [
'criteria' => [
['field' => 'id', 'condition' => '=', 'value' => $params['booking_id']]
],
'with' => [
'bookingPayment', 'bookingRoom.roomRateMapping.propertyRoom','bookingRoom.roomRateMapping.propertyRoomRate',
'bookingContact','bookingProperty.propertyBrand', 'bookingProperty.propertyExecutive', 'bookingProperty.propertyUser.user',
'bookingPropertyWeb', 'propertyBookingEngine', 'propertyBookingChannel'
],
'firstRow' => true
];
$bookingData = $bookingService->select($bookingDetailParam);
$bookingData = $bookingData['data'];
$hostAddress = Config::get('app.bookingEngineUrl') . '/' . $bookingData['property_booking_engine']['token'] . '/' . $bookingData['booking_contact']['language_code'] . '/booking-detail/' . $bookingData['booking_code'];
$brandRequestData = ['property_id' => $bookingData['property_id']];
$getPropertyBrand = $propertyBrandService->getPropertyBrand($brandRequestData);
if ($getPropertyBrand['status'] != "success") {
throw new Exception($getPropertyBrand['message']);
}
$propertyBrand = $getPropertyBrand['data'];
$propertyBrandLogo = isset($propertyBrand['name'])
? Config::get('app.fileSystemDriver') . '/property-photos/' . $propertyBrand['property_id'] . "/logo/" . $propertyBrand['name'] . '_250x250.' . $propertyBrand['logo_file_ext']
: null;
$roomOrder = 1;
$bookingChannelRoom = [];
foreach ($bookingData['booking_room'] as $bookingRoom) {
if (!empty($bookingRoom['room_rate_mapping']['property_room'])) {
$bookingRoom['room_name'] = $bookingRoom['room_rate_mapping']['property_room']['name'];
}
if (!empty($bookingRoom['room_rate_mapping']['property_room_rate'])) {
$bookingRoom['room_rate_name'] = $bookingRoom['room_rate_mapping']['property_room_rate']['name'];
}
$extraParam = null;
if (!empty($bookingRoom['extra_param'])) {
$extraParamDecode = json_decode($bookingRoom['extra_param'], 1);
foreach ($extraParamDecode as $extraParamKey => $extraParamValue) {
$extraParamTitle = explode('_', $extraParamKey);
foreach ($extraParamTitle as $extraParamTitleKey => $extraParamTitleValue) {
$extraParamTitle[$extraParamTitleKey] = ucwords($extraParamTitleValue);
}
$extraParamTitle = implode(' ', $extraParamTitle);
$extraParam[$extraParamKey] = [
'title' => $extraParamTitle,
'value' => $extraParamValue,
];
}
}
$additionalFee = null;
if (!empty($bookingRoom['rate_detail'])) {
$rateDetail = json_decode($bookingRoom['rate_detail'], 1);
if(isset($rateDetail['taxes']) && $bookingData['channel_manager_id'] == 2) {
$additionalFee = $rateDetail['taxes'];
}
}
$bookingChannelRoom[] = [
'roomOrder' => $roomOrder,
'roomName' => $bookingRoom['room_name'],
'roomRateName' => $bookingRoom['room_rate_name'],
'occupancyCode' => $bookingRoom['occupancy_code'],
'occupancyText' => occupancyCodeFormatted($bookingRoom['occupancy_code']),
'amount' => $bookingRoom['amount'],
'discount_amount' => $bookingRoom['discount_amount'],
'total' => $bookingRoom['total'],
'currencyCode' => $bookingRoom['currency_code'],
'dailyAmount' => !empty($bookingRoom['daily_amount']) ? json_decode($bookingRoom['daily_amount'],1) : null,
'extraParam' => $extraParam,
'occupancyFormatted' => occupancyCodeFormatted($bookingRoom['occupancy_code']),
'additionalFee' => $additionalFee
];
//$bookingChannelRoom[] = $roomOrder . '. ' . $bookingRoom['room_name'] . ' - ' . $bookingRoom['room_rate_name'] . ' - ' . occupancyCodeFormatted($bookingRoom['occupancy_code']);
$roomOrder++;
}
$userData = $bookingData['booking_property']['property_user'];
$firstUserData = reset($userData);
$bookingLanguageCode = fillOnUndefined($firstUserData['user'], 'language', 'en');
$bookingChannelPaymentType = __('property_booking_payment_type-pay_at_hotel',[],$bookingLanguageCode);
$bookingChannelPaymentSource = null;
if ($bookingData['booking_payment']['payment_type_code'] == 'CRD') {
$bookingChannelPaymentType = __('property_booking_payment_type-credit_card',[],$bookingLanguageCode);
if ($bookingData['booking_payment']['payment_source_code'] == 'OTA') {
$bookingChannelPaymentSource = __('enw-ota-credit_card',[],$bookingLanguageCode);
}
if ($bookingData['booking_payment']['payment_source_code'] == 'GST') {
$bookingChannelPaymentSource = __('enw-guest-credit_card',[],$bookingLanguageCode);
}
}
$creditCardInformation = null;
if (!is_null($bookingData['booking_payment']['extra_param'])) {
$paymentData = json_decode($bookingData['booking_payment']['extra_param'], 1);
if (isset($paymentData['attributes']['guarantee'])) {
$creditCardInformation['cardNumber'] = isset($paymentData['attributes']['guarantee']['card_number']) ? $paymentData['attributes']['guarantee']['card_number'] : null;
$creditCardInformation['cardHolderName'] = isset($paymentData['attributes']['guarantee']['cardholder_name']) ? $paymentData['attributes']['guarantee']['cardholder_name'] : null;
$creditCardInformation['expirationDate'] = isset($paymentData['attributes']['guarantee']['expiration_date']) ? $paymentData['attributes']['guarantee']['expiration_date'] : null;
$creditCardInformation['cvv'] = isset($paymentData['attributes']['guarantee']['cvv']) ? $paymentData['attributes']['guarantee']['cvv'] : null;
}
}
//Genius Member
$bookingContactExtraParam = null;
if(!empty($bookingData['booking_contact']['extra_param'])) {
$bookingContactExtraParam = json_decode($bookingData['booking_contact']['extra_param'],1);
}
$isBookingGenius = false;
if(isset($bookingContactExtraParam['is_genius']) && $bookingContactExtraParam['is_genius']) {
$isBookingGenius = true;
}
$mailParams = [
'bookingId' => $bookingData['id'],
'bookingCode' => $bookingData['booking_code'],
'propertyId' => $bookingData['booking_property']['id'],
'booking_code' => $bookingData['booking_code'],
'search_key' => $bookingData['search_key'],
'channel_token' => $bookingData['channel_token'],
'booking_engine_token' => $bookingData['booking_engine_token'],
'checkin_date' => Carbon::parse($bookingData['checkin_date'])->format('d.m.Y'),
'checkout_date' => Carbon::parse($bookingData['checkout_date'])->format('d.m.Y'),
'payment_type_code' => $bookingData['booking_payment']['payment_type_code'],
'payment_source_code' => $bookingData['booking_payment']['payment_source_code'],
'room_amount' => $bookingData['room_amount'],
'addon_amount' => $bookingData['addon_amount'],
'discount_amount' => $bookingData['discount_amount'],
'total' => $bookingData['total'],
'currency_code' => $bookingData['currency_code'],
'name_surname' => $bookingData['booking_contact']['nameSurname'],
'countryCode' => upperCase($bookingData['booking_contact']['country_code']),
'email' => $bookingData['booking_contact']['email'],
'property_name' => $bookingData['booking_property']['name'],
'url' => $hostAddress,
'logo' => $bookingData['booking_property']['property_brand']['logoUrl'],
'language_code' => $bookingData['booking_contact']['language_code'],
'bookingChannelId' => $bookingData['channel_id'],
'bookingChannelName' => fillOnUndefined($bookingData['property_booking_channel'], 'name'),
'bookingChannelCategoryId' => $bookingData['property_booking_channel']['channel_category_id'],
'bookingChannelCode' => $bookingData['channel_booking_code'],
'bookingChannelContactNameSurname' => $bookingData['booking_contact']['nameSurname'],
'bookingChannelContactEmail' => $bookingData['booking_contact']['email'],
'bookingChannelContactPhone' => $bookingData['booking_contact']['phone_number'],
'bookingChannelNote' => $bookingData['booking_contact']['note'],
'bookingChannelRoom' => $bookingChannelRoom,
'bookingChannelPaymentType' => $bookingChannelPaymentType,
'bookingChannelPaymentSource' => $bookingChannelPaymentSource,
'creditCardInformation' => $creditCardInformation,
'isBookingGenius' => $isBookingGenius
];
//Mail Contact Data
$reservationExecutives = [];
if (isset($bookingData['booking_property']['property_executive'])) {
$reservationExecutives = collect($bookingData['booking_property']['property_executive'])
->where('executive_type_id', '=', '7') // sadece rezervasyon yetkisi olanlar ...
->values()->all();
}
foreach ($reservationExecutives as $reservationExecutive) {
$bcc[] = $reservationExecutive['email'];
}
$bcc[] = "channel@extranetwork.com";
foreach ($userData as $user) {
if ($user['user']['email'] != $firstUserData['user']['email']) {
$bcc[] = $user['user']['email'];
}
}
$mailData = [
'to' => [
'name' => $firstUserData['user']['nameSurname'],
'email' => $firstUserData['user']['email'],
],
'bcc' => $bcc
];
$mailSenderAddress = Config::get('app.mailSenderAddress');
//app('translator')->setLocale(fillOnUndefined($firstUserData['user'], 'language', 'tr'));
app('translator')->setLocale($bookingLanguageCode);
$mailParams['showCreditCardUrl'] = null;
if(!empty($mailParams['creditCardInformation'])) {
$mailParams['showCreditCardUrl'] = Config::get('app.client_server').'/app/network/reservation/'.$mailParams['bookingId'].'?propertyid='.$mailParams['propertyId'];
}
/*echo view('emails.modifiedBookingMail', compact('mailParams'));
die();*/
return $this->from($mailSenderAddress, 'Extranetwork - ' . $mailParams['property_name'])
->view('emails.modifiedBookingMail', compact('mailParams'))
->to($mailData['to']["email"], $mailData['to']["name"])
->bcc($mailData['bcc'])
->subject(__('api-mailing-booking-modified_booking-title', ['channel' => $mailParams['bookingChannelName']]))
->with(['message' => $this]);
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
return output(['status' => -1, 'message' => $e->getMessage()]);
}
}
}

View File

@@ -0,0 +1,68 @@
<?php
namespace App\Core\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class NewBookingMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build()
{
try {
$params = $this->param;
$mailParams = $params['mailViewParams'];
$mailData = $params['mailData'];
$mailSenderAddress = Config::get('app.mailSenderAddress');
app('translator')->setLocale($mailParams["language_code"]);
$bookingData = __('api-mailling-booking-desc', [
'booking_code' => $mailParams['booking_code'],
'property_name' => $mailParams['property_name'],
'checkin_date' => $mailParams['checkin_date'],
'checkout_date' => $mailParams['checkout_date']
]);
$mailSubject = __('api-malling-booking-new_booking_info-title');
if (isset($mailParams['bookingChannelCategoryId']) && $mailParams['bookingChannelCategoryId'] != 3) {
$mailSubject = $mailParams['bookingChannelName'] . ' - ' . $mailSubject;
}
/*echo view('emails.newBookingMail', compact('mailParams', 'bookingData'));
die();*/
return $this->from($mailSenderAddress, 'Extranetwork - ' . $mailParams['property_name'])
->view('emails.newBookingMail', compact('mailParams', 'bookingData'))
->to($mailData['to']["email"], $mailData['to']["name"])
->bcc($mailData['bcc'])
->subject('🛎️ '.$mailSubject)
->with(['message' => $this]);
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
return output(['status' => -1, 'message' => $e->getMessage()]);
}
}
}

View File

@@ -0,0 +1,106 @@
<?php
namespace App\Core\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class OfferAcceptMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build()
{
try {
$params = $this->param;
$propertyService = App::make("App\Core\Service\OfferService");
$requestParams = [
'offer_id' => fillOnUndefined($params, 'offer_id'),
'property_id' => fillOnUndefined($params, 'property_id'),
];
$offerDetail = $propertyService->findOffer($requestParams);
$offerDetail = fillOnUndefined($offerDetail, 'data');
app('translator')->setLocale($offerDetail["language"]);
$mailSenderAddress = Config::get('app.mailSenderAddress');
$mailParams['to'] = [];
$mailParams['to'] = $offerDetail['email'];
$mailParams['cc'] = [];
if (!empty($offerDetail['create_user'])) {
$mailParams['cc'][] = $offerDetail['create_user']['email'];
}
$mailParams['bcc'] = [];
$mailParams['bcc'][] = Config::get('app.logMailAddress');
$mailParams['property_name'] = $offerDetail['property']['name'];
$mailParams['url'] = Config::get('app.client_server').'/offer/'.$offerDetail['offer_code'];
$mailParams['paymentUrl'] = null;
if(isset($params['paymentUrl']) && !is_null($params['paymentUrl'])) {
$mailParams['paymentUrl'] = $params['paymentUrl'];
}
$description = [];
//$description[] = '<b>'.$offerDetail['property']['name'].'</b> tarafından oluşturulan <b>'.$offerDetail['ticket_code'].'</b> kodlu teklif onaylanmıştır.';
$description[] = __('api-mailing-offer_accept_mail-description', ['propertyName' => $offerDetail['property']['name'], 'code' => $offerDetail['ticket_code']]);
if(!is_null($offerDetail['payment_type_mapping_id']) && !empty($mailParams['paymentUrl'])) {
//$description[] = 'Teklife ait ödemenizi aşağıdaki <b>Ödeme Linki</b> üzerinden güvenle gerçekleştirebilirsiniz.';
$description[] = __('api-mailing-offer_accept_mail-payment');
}
$description = implode('<br><br>', $description);
$mailParams['logo'] = Config::get('app.webUrl').'/assets/img/logo/mini-logo.png';
if(isset($offerDetail['property_brand']['logoUrl'])) {
$mailParams['logo'] = $offerDetail['property_brand']['logoUrl'];
}
/*echo view('emails.offerAcceptMail', compact('mailParams', 'description'));
die();*/
return $this->from($mailSenderAddress, 'Extranetwork - ' . $mailParams['property_name'])
->view('emails.offerAcceptMail', compact('mailParams', 'description'))
->to($mailParams['to'])
->cc($mailParams['cc'])
->bcc($mailParams['bcc'])
->subject(__('api-mailing-offer_accept_mail-title', ['code' => $offerDetail['ticket_code']]))
->with(['message' => $this]);
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
return output(['status' => -1, 'message' => $e->getMessage()]);
}
}
}

View File

@@ -0,0 +1,91 @@
<?php
namespace App\Core\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class OfferPreConfirmCustomerMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build()
{
try {
$params = $this->param;
$propertyService = App::make("App\Core\Service\OfferService");
$requestParams = [
'offer_id' => fillOnUndefined($params, 'offer_id'),
'property_id' => fillOnUndefined($params, 'property_id'),
];
$offerDetail = $propertyService->findOffer($requestParams);
$offerDetail = fillOnUndefined($offerDetail, 'data');
app('translator')->setLocale($offerDetail["language"]);
$mailSenderAddress = Config::get('app.mailSenderAddress');
$mailParams['to'] = [];
$mailParams['to'] = $offerDetail['email'];
$mailParams['bcc'] = [];
$mailParams['bcc'][] = Config::get('app.logMailAddress');
$mailParams['property_name'] = $offerDetail['property']['name'];
$mailParams['url'] = Config::get('app.client_server').'/offer/'.$offerDetail['offer_code'];
$mailParams['logo'] = Config::get('app.webUrl').'/assets/img/logo/mini-logo.png';
if(isset($offerDetail['property_brand']['logoUrl'])) {
$mailParams['logo'] = $offerDetail['property_brand']['logoUrl'];
}
$description = [];
//$description[] = '<b>'.$offerDetail['property']['name'].'</b> tarafından oluşturulan <b>'.$offerDetail['ticket_code'].'</b> kodlu teklifi onayladınız.';
$description[] = __('api-mailing-offer_preconfirm_customer_mail-description-one', ['propertyName' => $offerDetail['property']['name'], 'code' => $offerDetail['ticket_code']]);
//$description[] = 'Onayınız tesisimize bildirilmiştir. Tesisin teklifi onaylaması beklenmektedir, onaya istinaden size dönüş yapılacaktır.';
$description[] = __('api-mailing-offer_preconfirm_customer_mail-description-two');
$description = implode('<br><br>', $description);
/*echo view('emails.offerPreConfirmCustomerMail', compact('mailParams', 'description'));
die();*/
return $this->from($mailSenderAddress, 'Extranetwork - ' . $mailParams['property_name'])
->view('emails.offerPreConfirmCustomerMail', compact('mailParams', 'description'))
->to($mailParams['to'])
->bcc($mailParams['bcc'])
//->subject($offerDetail['ticket_code'].' Kodlu Teklifiniz Tesis Onayı Bekliyor')
->subject(__('api-mailing-offer_preconfirm_customer_mail-title', ['code' => $offerDetail['ticket_code']]))
->with(['message' => $this]);
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
return output(['status' => -1, 'message' => $e->getMessage()]);
}
}
}

View File

@@ -0,0 +1,91 @@
<?php
namespace App\Core\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class OfferPreConfirmPropertyMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build()
{
try {
$params = $this->param;
$propertyService = App::make("App\Core\Service\OfferService");
$requestParams = [
'offer_id' => fillOnUndefined($params, 'offer_id'),
'property_id' => fillOnUndefined($params, 'property_id'),
];
$offerDetail = $propertyService->findOffer($requestParams);
$offerDetail = fillOnUndefined($offerDetail, 'data');
app('translator')->setLocale($offerDetail["language"]);
$mailSenderAddress = Config::get('app.mailSenderAddress');
$mailParams['to'] = [];
$mailParams['to'] = $offerDetail['create_user']['email'];
$mailParams['bcc'] = [];
$mailParams['bcc'][] = Config::get('app.logMailAddress');
$mailParams['property_name'] = $offerDetail['property']['name'];
$mailParams['url'] = Config::get('app.client_server').'/offer/'.$offerDetail['offer_code'];
$mailParams['logo'] = Config::get('app.webUrl').'/assets/img/logo/mini-logo.png';
if(isset($offerDetail['property_brand']['logoUrl'])) {
$mailParams['logo'] = $offerDetail['property_brand']['logoUrl'];
}
$description = [];
//$description[] = 'Misafir, <b>'.$offerDetail['ticket_code'].'</b> kodlu teklifi onaylamıştır.';
$description[] = __('api-mailing-offer_preconfirm_property_mail-description-one', ['code' => $offerDetail['ticket_code']]);
//$description[] = 'Teklif türü otel onaylı olduğu için, tesis onayı beklenmektedir. Tesis onayını Extranetwork üzerinden verebilirsiniz.';
$description[] = __('api-mailing-offer_preconfirm_property_mail-description-two');
$description = implode('<br><br>', $description);
/*echo view('emails.offerPreConfirmPropertyMail', compact('mailParams', 'description'));
die();*/
return $this->from($mailSenderAddress, 'Extranetwork - ' . $mailParams['property_name'])
->view('emails.offerPreConfirmPropertyMail', compact('mailParams', 'description'))
->to($mailParams['to'])
->bcc($mailParams['bcc'])
//->subject($offerDetail['ticket_code'].' Kodlu Teklif Misafir Onayı')
->subject(__('api-mailing-offer_preconfirm_property_mail-title', ['code' => $offerDetail['ticket_code']]))
->with(['message' => $this]);
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
return output(['status' => -1, 'message' => $e->getMessage()]);
}
}
}

View File

@@ -0,0 +1,86 @@
<?php
namespace App\Core\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class OfferSendMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build()
{
try {
$params = $this->param;
$propertyService = App::make("App\Core\Service\OfferService");
$requestParams = [
'offer_id' => fillOnUndefined($params, 'offer_id'),
'property_id' => fillOnUndefined($params, 'property_id'),
];
$offerDetail = $propertyService->findOffer($requestParams);
$offerDetail = fillOnUndefined($offerDetail, 'data');
app('translator')->setLocale($offerDetail["language"]);
$mailSenderAddress = Config::get('app.mailSenderAddress');
$mailParams['to'] = [];
$mailParams['to'] = $offerDetail['email'];
$mailParams['bcc'] = [];
$mailParams['bcc'][] = Config::get('app.logMailAddress');
$mailParams['property_name'] = $offerDetail['property']['name'];
$mailParams['url'] = Config::get('app.client_server').'/offer/'.$offerDetail['offer_code'];
$mailParams['logo'] = Config::get('app.webUrl').'/assets/img/logo/mini-logo.png';
if(isset($offerDetail['property_brand']['logoUrl'])) {
$mailParams['logo'] = $offerDetail['property_brand']['logoUrl'];
}
$description = [];
$description[] = __('api-mailing-offer_mail-description', ['propertyName' => $offerDetail['property']['name'], 'code' => $offerDetail['ticket_code']]);
$description = implode('<br><br>', $description);
/*echo view('emails.offerMail', compact('mailParams', 'description'));
die();*/
return $this->from($mailSenderAddress, 'Extranetwork - ' . $mailParams['property_name'])
->view('emails.offerMail', compact('mailParams', 'description'))
->to($mailParams['to'])
->bcc($mailParams['bcc'])
->subject(__('api-mailing-offer_mail-title', ['propertyName' => $offerDetail['property']['name'], 'code' => $offerDetail['ticket_code']]))
->with(['message' => $this]);
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
return output(['status' => -1, 'message' => $e->getMessage()]);
}
}
}

View File

@@ -0,0 +1,100 @@
<?php
namespace App\Core\Mail;
use App\Exceptions\ApiErrorException;
use App\Models\PropertyProductOffer;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class PropertyProductOfferMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build()
{
try {
$params = $this->param;
$propertyProductOffer = PropertyProductOffer::where('offer_key', $params['offerKey'])->first();
$propertyProductOffer = $propertyProductOffer ? $propertyProductOffer->toArray() : null;
if (!$propertyProductOffer) {
throw new ApiErrorException('The offer was not found');
}
$mailData = [
'to' => [
'name' => $propertyProductOffer['executive_name'],
'email' => $propertyProductOffer['executive_email'],
],
'bcc' => ['sales@extranetwork.com']
];
$mailData['cc'] = [];
if (isset($propertyProductOffer['account_manager_email'])) {
$mailData['cc'][] = $propertyProductOffer['account_manager_email'];
}
$mailSenderAddress = Config::get('app.mailSenderAddress');
$mailParams = [
'property_name' => $propertyProductOffer['property_name'],
'executive_name' => $propertyProductOffer['executive_name'],
'executive_email' => $propertyProductOffer['executive_email'],
'executive_phone' => $propertyProductOffer['executive_phone'],
'offer_expire_date' => $propertyProductOffer['offerExpireTimeFormatted'],
'logo' => 'https://www.extranetwork.com/assets/img/logo/mini-logo.png',
'btnUrl' => config('app.url') . '/property-product-offer/' . $propertyProductOffer['offer_key']
];
if ($propertyProductOffer['version'] == 'v2') {
$mailParams['btnUrl'] = config('app.webUrl') . '/property-product-offer/' . $propertyProductOffer['offer_key'];
}
/*echo view('emails.propertyProductOfferMail', compact('mailParams'));
die();*/
$subjectMail = 'Extranetwork ' . $mailParams['property_name'] . ' Fiyat Teklifi';
if (isset($propertyProductOffer['detailArray']['paket'])) {
$subjectMail = 'Extranetwork ' . $mailParams['property_name'] . ' - ' . $propertyProductOffer['detailArray']['paket'] . ' Fiyat Teklifi';
}
return $this->from($mailSenderAddress, 'Extranetwork')
->view('emails.propertyProductOfferMail', compact('mailParams'))
->to($mailData['to']['email'], $mailData['to']['name'])
->cc($mailData['cc'])
->bcc($mailData['bcc'])
->subject($subjectMail)
->with(['message' => $this]);
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
return output(['status' => -1, 'message' => $e->getMessage()]);
}
}
}

View File

@@ -0,0 +1,104 @@
<?php
namespace App\Core\Mail;
use App\Exceptions\ApiErrorException;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class TrialFirstMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build()
{
try {
$params = $this->param;
$mailSenderAddress = Config::get('app.mailSenderAddress');
$propertyService = App::make('App\Core\Service\PropertyService');
$propertySelectCriteria = [
'criteria' => [
['field' => 'id', 'condition' => '=', 'value' => $params['propertyId']],
],
'with' => ['userPropertyMapping.user'],
'firstRow' => true
];
$propertyData = $propertyService->select($propertySelectCriteria);
if($propertyData['status'] == 'success') {
$userPropertyMappingCollect = collect($propertyData['data']['user_property_mapping']);
$userPropertyMapping = $userPropertyMappingCollect->where('status',1)->where('user.status',1)->sortBy('id');
$userPropertyMapping = $userPropertyMapping ? $userPropertyMapping->toArray() : [];
$defaultUser = reset($userPropertyMapping);
$mailData['to'] = [
'email' => $defaultUser['user']['email'],
'nameSurname' => $defaultUser['user']['nameSurname'],
];
$mailData['bcc'] = [];
foreach ($userPropertyMapping as $user) {
//$mailData['bcc'][] = $user['user']['email'];
}
$mailData['bcc'] = 'channel@extranetwork.com';//TODO: Delete
$mailParams= [
'email' => $mailData['to']['email'],
'nameSurname' => $mailData['to']['nameSurname'],
'propertyName' => $propertyData['data']['name'],
];
$mailTitle = 'Rezervasyonlarını ikiye katlamaya hazır mısın? 🚀';
//app('translator')->setLocale('en');
//echo view('emails.reminder.trialFirstMail', compact('mailParams')); die();
return $this->from($mailSenderAddress, 'Extranetwork')
->view('emails.reminder.trialFirstMail', compact('mailParams'))
->to($mailData['to']['email'], $mailData['to']['nameSurname'])
->bcc($mailData['bcc'])
->subject($mailTitle)
->with(['message' => $this]);
}
} catch (ApiErrorException $e) {
return output(['status' => -1, 'message' => $e->getMessage()]);
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
return output(['status' => -1, 'message' => $e->getMessage()]);
}
}
}

View File

@@ -0,0 +1,104 @@
<?php
namespace App\Core\Mail;
use App\Exceptions\ApiErrorException;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class TrialSecondMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build()
{
try {
$params = $this->param;
$mailSenderAddress = Config::get('app.mailSenderAddress');
$propertyService = App::make('App\Core\Service\PropertyService');
$propertySelectCriteria = [
'criteria' => [
['field' => 'id', 'condition' => '=', 'value' => $params['propertyId']],
],
'with' => ['userPropertyMapping.user'],
'firstRow' => true
];
$propertyData = $propertyService->select($propertySelectCriteria);
if($propertyData['status'] == 'success') {
$userPropertyMappingCollect = collect($propertyData['data']['user_property_mapping']);
$userPropertyMapping = $userPropertyMappingCollect->where('status',1)->where('user.status',1)->sortBy('id');
$userPropertyMapping = $userPropertyMapping ? $userPropertyMapping->toArray() : [];
$defaultUser = reset($userPropertyMapping);
$mailData['to'] = [
'email' => $defaultUser['user']['email'],
'nameSurname' => $defaultUser['user']['nameSurname'],
];
$mailData['bcc'] = [];
foreach ($userPropertyMapping as $user) {
//$mailData['bcc'][] = $user['user']['email'];
}
$mailData['bcc'] = 'channel@extranetwork.com';//TODO: Delete
$mailParams= [
'email' => $mailData['to']['email'],
'nameSurname' => $mailData['to']['nameSurname'],
'propertyName' => $propertyData['data']['name'],
];
$mailTitle = 'Çok görünürlük, daha çok satış.😎';
//app('translator')->setLocale('en');
//echo view('emails.reminder.trialSecondMail', compact('mailParams')); die();
return $this->from($mailSenderAddress, 'Extranetwork')
->view('emails.reminder.trialSecondMail', compact('mailParams'))
->to($mailData['to']['email'], $mailData['to']['nameSurname'])
->bcc($mailData['bcc'])
->subject($mailTitle)
->with(['message' => $this]);
}
} catch (ApiErrorException $e) {
return output(['status' => -1, 'message' => $e->getMessage()]);
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
return output(['status' => -1, 'message' => $e->getMessage()]);
}
}
}

View File

@@ -0,0 +1,46 @@
<?php
namespace App\Core\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
class UserCreateMail extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build()
{
try {
$params = $this->param;
app('translator')->setLocale($params["language"]);
return $this->view('emails.createUserMail', compact('params'))
->to($params["email"], $params["name_surname"])
->subject(__('api-mailing-new_user_subject'));
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
return output(['status' => -1, 'message' => $e->getMessage()]);
}
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace App\Core\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
class UserForgotPassword extends Mailable
{
use Queueable, SerializesModels;
public $tries = 5;
public $timeout = 30;
protected $param;
public function __construct($param)
{
$this->param = $param;
}
public function build ()
{
try
{
$params = $this->param;
app('translator')->setLocale($params["language"]);
return $this->view('emails.userForgotPassword', compact('params'))
->to($params["email"], $params["name_surname"])
->subject(__('api-mailing-user_forgot_password_subject'))
->with(['message' => $this]);
}
catch ( Exception $e )
{
$message = $e->getFile()." ".$e->getLine()." ".$e->getMessage();
Log::error($message);
return output( ['status' => -1, 'message' => $e->getMessage()] );
}
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace App\Core\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Log ;
class WellcomeMail extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* @return void
*/
protected $param;
public function __construct($param)
{
$this->param = $param;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
$val = $this->param;
Log::debug($val);
return $this->view('emails.wellCome', compact('val'))
->to('ygundogdu@rezervasyon.com', 'yadican')
->bcc('ygundogdu@rezervasyon.com', 'Burhan YUMAK')
->bcc('ygundogdu@rezervasyon.com', 'Operasyon')
->subject("WellCome Mail");
}
}

View File

@@ -0,0 +1,224 @@
<?php
namespace App\Core\Payment\BankOfGeorgia;
use App\Exceptions\ApiErrorException;
use Auth;
use Carbon\Carbon;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Log;
use Exception;
class BankOfGeorgia
{
private $requestUrl;
private $clientId;
private $secretKey;
private $accessToken;
public function __construct($paymentInitializeParam)
{
$this->restClient = new Client();
$this->requestUrl = 'https://ipay.ge/opay/api/v1';
if ($paymentInitializeParam['env'] == 'test') {
$this->requestUrl = 'https://dev.ipay.ge/opay/api/v1/';
}
$this->clientId = $paymentInitializeParam['clientId'];
$this->secretKey = $paymentInitializeParam['secretKey'];
$getAccessToken = $this->getAccessToken();
$this->accessToken = $getAccessToken['status'] ? $getAccessToken['token'] : null;
}
private function makeRequest($method, $payloadData, $methodType = 'POST')
{
$response = ['status' => false, 'message' => ''];
try {
$requestParams['headers']['Content-Type'] = 'application/json';
$requestParams['headers']['Authorization'] = 'Bearer ' . $this->accessToken;
$requestParams['body'] = json_encode($payloadData);
$result = $this->restClient->request($methodType, $this->requestUrl . '/' . $method, $requestParams);
$getResponseBody = $result->getBody()->getContents();
$getResponseData = $getResponseBody ? json_decode($getResponseBody, 1) : [];
if (isset($getResponseData['error_code'])) {
$response['message'] = $getResponseData['status_description'];
$response['serviceResponse'] = $getResponseData;
} else {
$response = [
'status' => true,
'serviceResponse' => $getResponseData
];
}
} catch (ClientException $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::debug($message);
$response['message'] = $e->getMessage();
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::debug($message);
$response['message'] = $e->getMessage();
}
if (!$response['status']) {
Log::error($method);
Log::error($payloadData);
Log::error($response);
}
return $response;
}
private function getAccessToken()
{
$getTokenData = null;
$response = ['status' => false, 'message' => ''];
try {
$requestParams['headers']['Authorization'] = 'Basic ' . base64_encode($this->clientId . ':' . $this->secretKey);
$requestParams['headers']['Content-Type'] = 'application/x-www-form-urlencoded';
$requestParams['form_params']['grant_type'] = 'client_credentials';
$result = $this->restClient->request('POST', $this->requestUrl . '/oauth2/token', $requestParams);
$getResponseBody = $result->getBody()->getContents();
$getResponseData = $getResponseBody ? json_decode($getResponseBody, 1) : [];
if (isset($getResponseData['error_code'])) {
throw new ApiErrorException($getResponseData['error_message']);
}
$response['status'] = true;
$response['token'] = $getResponseData['access_token'];
} catch (ApiErrorException $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::debug($message);
$response['message'] = $e->getMessage();
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::debug($message);
$response['message'] = $e->getMessage();
}
return $response;
}
public function paymentInitialize($param)
{
$response = ['status' => false, 'message' => ''];
try {
$paymentInitializeParam = [
'intent' => 'CAPTURE',
'items' => [
[
'amount' => $param['amount'],
'description' => $param['orderCode'],
'quantity' => 1,
'product_id' => $param['orderCode'],
]
],
'locale' => 'en-US',
'shop_order_id' => $param['orderId'],
'redirect_url' => $param['paymentCheckUrl'],
'capture_method' => 'AUTOMATIC',
'purchase_units' => [
[
'amount' => [
'currency_code' => $param['currencyCode'],
'value' => $param['amount'],
]
]
]
];
$paymentInitialize = $this->makeRequest('checkout/orders', $paymentInitializeParam);
if (!$paymentInitialize['status']) {
throw new ApiErrorException($paymentInitialize['message']);
}
$response = [
'status' => true,
'data' => $paymentInitialize['serviceResponse']
];
} catch (ApiErrorException $e) {
$response = ['status' => false, 'message' => $e->getMessage()];
} catch (Exception $e) {
$response = ['status' => false, 'message' => $e->getMessage()];
Log::error($response);
}
return $response;
}
public function checkoutOrderInfo($orderId)
{
$response = ['status' => false, 'message' => ''];
try {
$method = 'checkout/orders/' . $orderId;
$payloadData = [];
$checkoutOrderInfoRequest = $this->makeRequest($method, $payloadData, 'GET');
if (!$checkoutOrderInfoRequest['status']) {
throw new ApiErrorException($checkoutOrderInfoRequest['message']);
}
$response = [
'status' => true,
'data' => $checkoutOrderInfoRequest['serviceResponse']
];
} catch (ApiErrorException $e) {
$response = ['status' => false, 'message' => $e->getMessage()];
} catch (Exception $e) {
$response = ['status' => false, 'message' => $e->getMessage()];
Log::error($response);
}
if (isset($checkoutOrderInfoRequest['serviceResponse'])) {
$response['serviceResponse'] = $checkoutOrderInfoRequest['serviceResponse'];
}
return $response;
}
}

View File

@@ -0,0 +1,239 @@
<?php
namespace App\Core\Payment\Esnekpos;
use App\Exceptions\ApiErrorException;
use App\Exceptions\ApplicationError;
use Auth;
use Carbon\Carbon;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\ServerException;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Log;
use Exception;
class Esnekpos
{
private $requestUrl;
public function __construct($paymentInitializeParam)
{
$this->restClient = new Client();
$this->requestUrl = 'https://posservice.esnekpos.com';
if ($paymentInitializeParam['env'] == 'test') {
$this->requestUrl = 'https://posservicetest.esnekpos.com';
}
$this->merchant = $paymentInitializeParam['merchant'];
$this->merchantKey = $paymentInitializeParam['merchantKey'];
$this->contactMail = $paymentInitializeParam['contactMail'];
$this->ipAddress = isset($paymentInitializeParam['ipAddress']) ? $paymentInitializeParam['ipAddress'] : '185.137.215.118';
$this->currencyMapping = [
'TRY' => 'TRY',
'USD' => 'USD',
'EUR' => 'EUR',
'GBP' => 'GBP',
];
}
private function makeRequest($method, $payloadData)
{
$response = ['status' => false, 'message' => ''];
try {
$requestParams['headers']['Content-Type'] = 'application/json';
$requestParams['body'] = json_encode($payloadData);
$result = $this->restClient->post($this->requestUrl . '/' . $method, $requestParams);
$getResponseBody = $result->getBody()->getContents();
$getResponseData = $getResponseBody ? json_decode($getResponseBody, 1) : [];
if ($getResponseData['STATUS'] == 'SUCCESS') {
$response = [
'status' => true,
'serviceResponse' => $getResponseData
];
} else {
throw new Exception($getResponseData['RETURN_MESSAGE']);
}
} catch (ClientException $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
$response['message'] = $message;
Log::debug($message);
} catch (ServerException | Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::debug($message);
$response['message'] = $e->getMessage();
}
if (!$response['status']) {
Log::error($method);
Log::error($payloadData);
Log::error($response);
}
if (isset($getResponseData)) {
$response['serviceResponse'] = $getResponseData;
}
return $response;
}
public function generateHashKey($total, $installment, $currency_code, $invoice_id)
{
$data = $total . '|' . $installment . '|' . $currency_code . '|' . $this->merchantKey . '|' . $invoice_id;
$iv = substr(sha1(mt_rand()), 0, 16);
$password = sha1($this->appSecret);
$salt = substr(sha1(mt_rand()), 0, 4);
$saltWithPassword = hash('sha256', $password . $salt);
$encrypted = openssl_encrypt("$data", 'aes-256-cbc', "$saltWithPassword", null, $iv);
$msg_encrypted_bundle = "$iv:$salt:$encrypted";
$msg_encrypted_bundle = str_replace('/', '__', $msg_encrypted_bundle);
return $msg_encrypted_bundle;
}
public function EYV3DPay($param)
{
$response = ['status' => false, 'message' => ''];
try {
$param['creditCard']['installment'] = $param['creditCard']['installment'] == 0 ? 1 : $param['creditCard']['installment'];
$items = [];
$items[] = [
'PRODUCT_ID' => $param['orderCode'],
'PRODUCT_NAME' => 'Booking',
'PRODUCT_CATEGORY' => 'Booking',
'PRODUCT_DESCRIPTION' => 'Booking',
'PRODUCT_AMOUNT' => $param['amount']
];
$method = 'api/pay/EYV3DPay';
$payloadData = [
'Config' => [
'MERCHANT' => $this->merchant,
'MERCHANT_KEY' => $this->merchantKey,
'BACK_URL' => $param['paymentCheckUrl'],
'PRICES_CURRENCY' => isset($this->currencyMapping[$param['currencyCode']]) ? $this->currencyMapping[$param['currencyCode']] : $param['currencyCode'],
'ORDER_REF_NUMBER' => $param['orderId'],
'ORDER_AMOUNT' => $param['amount'],
],
'CreditCard' => [
'CC_NUMBER' => $param['creditCard']['number'],
'EXP_MONTH' => $param['creditCard']['expiryMonth'],
'EXP_YEAR' => $param['creditCard']['expiryYear'],
'CC_CVV' => $param['creditCard']['cvv'],
'CC_OWNER' => $param['creditCard']['holderName'],
'INSTALLMENT_NUMBER' => $param['creditCard']['installment'],
],
'Customer' => [
'FIRST_NAME' => $param['orderId'],
'LAST_NAME' => $param['orderId'],
'MAIL' => $this->contactMail,
'PHONE' => '5555555555',
'CITY' => $param['orderId'],
'STATE' => $param['orderId'],
'ADDRESS' => $param['orderId'],
'CLIENT_IP' => $this->ipAddress,
],
'Product' => $items
];
$checkRequest = $this->makeRequest($method, $payloadData);
if (!$checkRequest['status']) {
throw new ApiErrorException($checkRequest['message']);
}
$response = [
'status' => true,
'data' => $checkRequest['serviceResponse']
];
} catch (ApiErrorException $e) {
$response = ['status' => false, 'message' => $e->getMessage()];
} catch (Exception $e) {
$response = ['status' => false, 'message' => $e->getMessage()];
Log::error($response);
}
return $response;
}
public function checkPaymentStatus($orderId)
{
$response = ['status' => false, 'message' => ''];
try {
$method = 'api/services/ProcessQuery';
$payloadData = [
'MERCHANT' => $this->merchant,
'MERCHANT_KEY' => $this->merchantKey,
'ORDER_REF_NUMBER' => $orderId,
];
$checkStatusRequest = $this->makeRequest($method, $payloadData);
if (!$checkStatusRequest['status']) {
throw new ApiErrorException($checkStatusRequest['message']);
}
if ($checkStatusRequest['serviceResponse']['STATUS'] != 'SUCCESS') {
throw new ApiErrorException($checkStatusRequest['message']);
}
$response = [
'status' => true,
'data' => $checkStatusRequest['serviceResponse']
];
} catch (ApiErrorException $e) {
$response = ['status' => false, 'message' => $e->getMessage()];
} catch (Exception $e) {
$response = ['status' => false, 'message' => $e->getMessage()];
Log::error($response);
}
if (isset($checkStatusRequest['serviceResponse'])) {
$response['serviceResponse'] = $checkStatusRequest['serviceResponse'];
}
return $response;
}
}

View File

@@ -0,0 +1,254 @@
<?php
namespace App\Core\Payment\HalkOde;
use App\Exceptions\ApiErrorException;
use App\Exceptions\ApplicationError;
use Auth;
use Carbon\Carbon;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Log;
use Exception;
class HalkOde
{
private $requestUrl;
public function __construct($paymentInitializeParam)
{
$this->restClient = new Client();
$this->requestUrl = 'https://app.halkode.com.tr/ccpayment';
if ($paymentInitializeParam['env'] == 'test') {
$this->requestUrl = 'https://test.halkode.com.tr/ccpayment';
}
$this->merchantId = $paymentInitializeParam['merchantId'];
$this->merchantKey = $paymentInitializeParam['merchantKey'];
$this->appKey = $paymentInitializeParam['appKey'];
$this->appSecret = $paymentInitializeParam['appSecret'];
$this->getAccessToken = $this->getAccessToken();
}
private function makeRequest($method, $payloadData)
{
$response = ['status' => false, 'message' => ''];
try {
$requestParams['headers']['Content-Type'] = 'application/json';
if ($method != 'api/token') {
$requestParams['headers']['Authorization'] = 'Bearer ' . $this->getAccessToken;
}
$requestParams['body'] = json_encode($payloadData);
$result = $this->restClient->post($this->requestUrl . '/' . $method, $requestParams);
$getResponseBody = $result->getBody()->getContents();
$getResponseData = $getResponseBody ? json_decode($getResponseBody, 1) : [];
if ($getResponseData['status_code'] == 100) {
$response = [
'status' => true,
'serviceResponse' => $getResponseData
];
} else {
$response['message'] = $getResponseData['status_description'];
$response['serviceResponse'] = $getResponseData;
}
} catch (ClientException $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::debug($message);
$response['message'] = $e->getMessage();
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::debug($message);
$response['message'] = $e->getMessage();
}
if (!$response['status']) {
Log::error($method);
Log::error($payloadData);
Log::error($response);
}
return $response;
}
private function getAccessToken()
{
$method = 'api/token';
$payloadData = [
'app_id' => $this->appKey,
'app_secret' => $this->appSecret,
];
$getTokenDataRequest = $this->makeRequest($method, $payloadData);
if ($getTokenDataRequest['status']) {
$getTokenData = $getTokenDataRequest['serviceResponse']['data']['token'];
}
return $getTokenData;
}
public function generateHashKey($total, $installment, $currency_code, $invoice_id)
{
$data = $total . '|' . $installment . '|' . $currency_code . '|' . $this->merchantKey . '|' . $invoice_id;
$iv = substr(sha1(mt_rand()), 0, 16);
$password = sha1($this->appSecret);
$salt = substr(sha1(mt_rand()), 0, 4);
$saltWithPassword = hash('sha256', $password . $salt);
$encrypted = openssl_encrypt("$data", 'aes-256-cbc', "$saltWithPassword", null, $iv);
$msg_encrypted_bundle = "$iv:$salt:$encrypted";
$msg_encrypted_bundle = str_replace('/', '__', $msg_encrypted_bundle);
return $msg_encrypted_bundle;
}
public function generateRefundHashKey($invoice_id, $merchant_key, $app_secret)
{
$data = $invoice_id . '|' . $merchant_key;
$iv = substr(sha1(mt_rand()), 0, 16);
$password = sha1($app_secret);
$salt = substr(sha1(mt_rand()), 0, 4);
$saltWithPassword = hash('sha256', $password . $salt);
$encrypted = openssl_encrypt(
$data, 'aes-256-cbc', "$saltWithPassword", null, $iv
);
$msg_encrypted_bundle = "$iv:$salt:$encrypted";
$hash_key = str_replace('/', '__', $msg_encrypted_bundle);
return $hash_key;
}
public function paySmart3D($param)
{
$response = ['status' => false, 'message' => ''];
try {
$param['creditCard']['installment'] = $param['creditCard']['installment'] == 0 ? 1 : $param['creditCard']['installment'];
$generateHashKey = $this->generateHashKey($param['amount'], $param['creditCard']['installment'], $param['currencyCode'], $param['orderId']);
$items = [];
$items[] = [
'name' => 'Booking',
'price' => $param['amount'],
'quantity' => 1,
'description' => $param['orderCode'],
];
$payment3dFormData['gateway'] = $this->requestUrl . '/api/paySmart3D';
$payment3dFormData['inputs'] = [
'currency_code' => $param['currencyCode'],
'installments_number' => $param['creditCard']['installment'],
'invoice_id' => $param['orderId'],
'invoice_description' => $param['orderCode'],
'total' => $param['amount'],
'merchant_key' => $this->merchantKey,
'items' => json_encode($items),
//'name' => $param['name'],
//'surname' => $param['surname'],
'hash_key' => $generateHashKey,
'return_url' => $param['paymentCheckUrl'],
'cancel_url' => $param['paymentCheckUrl'],
'cc_holder_name' => $param['creditCard']['holderName'],
'cc_no' => $param['creditCard']['number'],
'expiry_month' => $param['creditCard']['expiryMonth'],
'expiry_year' => $param['creditCard']['expiryYear'],
'cvv' => $param['creditCard']['cvv'],
'transaction_type' => 'Auth',
'is_comission_from_user' => '2',
'response_method' => 'GET',
];
$response = [
'status' => true,
'data' => $payment3dFormData
];
} catch (ApiErrorException $e) {
$response = ['status' => false, 'message' => $e->getMessage()];
} catch (Exception $e) {
$response = ['status' => false, 'message' => $e->getMessage()];
Log::error($response);
}
return $response;
}
public function checkPaymentStatus($orderId)
{
$response = ['status' => false, 'message' => ''];
try {
$generateHashKey = $this->generateRefundHashKey($orderId, $this->merchantKey, $this->appSecret);
$method = 'api/checkstatus';
$payloadData = [
'invoice_id' => $orderId,
'merchant_key' => $this->merchantKey,
'include_pending_status' => true,
'hash_key' => $generateHashKey
];
$checkstatusRequest = $this->makeRequest($method, $payloadData);
if (!$checkstatusRequest['status']) {
throw new ApiErrorException($checkstatusRequest['message']);
}
$response = [
'status' => true,
'data' => $checkstatusRequest['serviceResponse']
];
} catch (ApiErrorException $e) {
$response = ['status' => false, 'message' => $e->getMessage()];
} catch (Exception $e) {
$response = ['status' => false, 'message' => $e->getMessage()];
Log::error($response);
}
if (isset($checkstatusRequest['serviceResponse'])) {
$response['serviceResponse'] = $checkstatusRequest['serviceResponse'];
}
return $response;
}
}

View File

@@ -0,0 +1,241 @@
<?php
namespace App\Core\Payment\KuveytTurk;
use App\Exceptions\ApiErrorException;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\ServerException;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Request;
use Log;
use Exception;
class KuveytTurk
{
private $restClient;
private $customerId;
private $merchantId;
private $userName;
private $password;
private $currencyCodeMapping;
public function __construct
(
$paymentInitializeParam
)
{
$this->restClient = new Client();
$this->requestUrl = 'https://boa.kuveytturk.com.tr/sanalposservice/Home';
if ($paymentInitializeParam['env'] == 'test') {
$this->requestUrl = 'https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home';
}
$this->customerId = $paymentInitializeParam['customerId'];
$this->merchantId = $paymentInitializeParam['merchantId'];
$this->userName = $paymentInitializeParam['userName'];
$this->password = $paymentInitializeParam['password'];
$this->currencyCodeMapping = [
'TRY' => '0949',
'USD' => '0840',
'EUR' => '0978',
];
}
protected function post($param)
{
$getResponse = [];
$param['logDebug'] = fillOnUndefined($param, 'logDebug', false);
try {
$paymentRequest = $this->restClient->post($this->requestUrl . '/' . $param['method'], [
'headers' => [
'Content-Type' => 'application/xml; charset=UTF8',
],
'body' => $param['payload']
]);
$getResponseBody = $paymentRequest->getBody();
$getResponseXmlBase = $getResponseBody->getContents();
if (!$getResponseXmlBase) {
throw new ApiErrorException('Payment Initialize not processing.');
} else {
$response = [
'status' => true,
'data' => $getResponseXmlBase
];
}
if ($param['logDebug']) {
Log::debug(json_encode($param['param']));
Log::debug($param['param']);
Log::debug($getResponse);
}
} catch (ApiErrorException | Exception | ClientException | ServerException $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::debug($message);
$response['message'] = $e->getMessage();
}
return $response;
}
public function threeDModelPayGate($param = [])
{
try {
$hashData = null;
$param['amount'] = (int)(floatval($param['amount']) * 100);
$hashedPassword = base64_encode(sha1($this->password, "ISO-8859-9"));
$hashData = base64_encode(sha1($this->merchantId . $param['orderId'] . $param['amount'] . $param['paymentCheckUrl'] . $param['paymentCheckUrl'] . $this->userName . $hashedPassword, "ISO-8859-9"));
$requestParam['method'] = 'ThreeDModelPayGate';
$requestPayload = new \SimpleXMLElement('<KuveytTurkVPosMessage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"></KuveytTurkVPosMessage>');
$currencyCodeBank = isset($this->currencyCodeMapping[$param['currencyCode']]) ? $this->currencyCodeMapping[$param['currencyCode']] : '0949';
$requestPayload->addChild('APIVersion', '1.0.0');
$requestPayload->addChild('OkUrl', $param['paymentCheckUrl']);
$requestPayload->addChild('FailUrl', $param['paymentCheckUrl']);
$requestPayload->addChild('HashData', $hashData);
$requestPayload->addChild('MerchantId', $this->merchantId);
$requestPayload->addChild('CustomerId', $this->customerId);
$requestPayload->addChild('UserName', $this->userName);
$requestPayload->addChild('CardNumber', $param['creditCard']['number']);
$requestPayload->addChild('CardExpireDateYear', mb_substr($param['creditCard']['expiryYear'], 2, 2));
$requestPayload->addChild('CardExpireDateMonth', $param['creditCard']['expiryMonth']);
$requestPayload->addChild('CardCVV2', $param['creditCard']['cvv']);
$requestPayload->addChild('CardHolderName', $param['creditCard']['holderName']);
//$requestPayload->addChild('CardType', null);
$requestPayload->addChild('BatchID', 0);
$requestPayload->addChild('TransactionType', 'Sale');
$requestPayload->addChild('InstallmentCount', $param['creditCard']['installment']);
$requestPayload->addChild('Amount', $param['amount']);
$requestPayload->addChild('DisplayAmount', $param['amount']);
$requestPayload->addChild('CurrencyCode', $currencyCodeBank);
$requestPayload->addChild('MerchantOrderId', $param['orderId']);
$requestPayload->addChild('TransactionSecurity', 3);
$requestParam['payload'] = $requestPayload->asXML();
$paymentRequest = $this->post($requestParam);
if (!$paymentRequest['status']) {
throw new ApiErrorException($paymentRequest['message']);
}
$response = [
'status' => true,
'data' => $paymentRequest['data']
];
} catch (ApiErrorException | Exception $e) {
$response = ['status' => false, 'message' => $e->getMessage()];
}
if (isset($getResponseData)) {
$response['serviceResponse'] = $paymentRequest;
}
return $response;
}
public function checkPaymentStatus($paymentCode, $param = [])
{
$response = ['status' => false, 'message' => ''];
$requestContent = null;
$paymentRequest = [];
try {
$requestContent = urldecode($param["AuthenticationResponse"]);
$requestContent = json_decode(json_encode(simplexml_load_string($requestContent)), 1);
if ($requestContent['ResponseCode'] != "00") {
$errorMessage = $requestContent['ResponseCode'] . ': ' . $requestContent['ResponseMessage'];
$paymentRequest['serviceResponse'] = $requestContent;
throw new ApiErrorException($errorMessage);
}
$paymentCheckParam = [
'merchantOrderId' => isset($requestContent['VPosMessage']['MerchantOrderId']) ? $requestContent['VPosMessage']['MerchantOrderId'] : null,
'amount' => isset($requestContent['VPosMessage']['Amount']) ? $requestContent['VPosMessage']['Amount'] : null,
'md' => isset($requestContent['MD']) ? $requestContent['MD'] : null,
];
$hashData = null;
//$param['amount'] = (int)(floatval($param['amount']) * 100);
$hashedPassword = base64_encode(sha1($this->password, "ISO-8859-9"));
$hashData = base64_encode(sha1($this->merchantId . $paymentCheckParam['merchantOrderId'] . $paymentCheckParam['amount'] . $this->userName . $hashedPassword, "ISO-8859-9"));
$requestParam['method'] = 'ThreeDModelProvisionGate';
$requestPayload = new \SimpleXMLElement('<KuveytTurkVPosMessage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"></KuveytTurkVPosMessage>');
$requestPayload->addChild('APIVersion', '1.0.0');
$requestPayload->addChild('HashData', $hashData);
$requestPayload->addChild('MerchantId', $this->merchantId);
$requestPayload->addChild('CustomerId', $this->customerId);
$requestPayload->addChild('UserName', $this->userName);
$requestPayload->addChild('TransactionType', 'Sale');
$requestPayload->addChild('InstallmentCount', 1);
$requestPayload->addChild('CurrencyCode', '0949');
$requestPayload->addChild('Amount', $paymentCheckParam['amount']);
$requestPayload->addChild('MerchantOrderId', $paymentCheckParam['merchantOrderId']);
$requestPayload->addChild('TransactionSecurity', 3);
$kuveytTurkVPosAdditionalData = $requestPayload->addChild('KuveytTurkVPosAdditionalData');
$additionalData = $kuveytTurkVPosAdditionalData->addChild('AdditionalData');
$additionalData->addChild('Key', 'MD');
$additionalData->addChild('Data', $paymentCheckParam['md']);
$requestParam['payload'] = $requestPayload->asXML();
$paymentRequest = $this->post($requestParam);
if (!$paymentRequest['status']) {
throw new ApiErrorException($paymentRequest['message']);
}
$requestContent = simplexml_load_string($paymentRequest['data']);
$requestContent = json_decode(json_encode($requestContent), 1);
$paymentRequest['serviceResponse'] = $requestContent;
if ($requestContent['ResponseCode'] != "00") {
$errorMessage = $requestContent['ResponseCode'] . ': ' . $requestContent['ResponseMessage'];
throw new ApiErrorException($errorMessage);
}
$response = [
'status' => true,
'data' => $requestContent
];
} catch (ApiErrorException | Exception $e) {
$response = ['status' => false, 'message' => $e->getMessage()];
}
if (isset($paymentRequest['serviceResponse'])) {
$response['serviceResponse'] = $paymentRequest['serviceResponse'];
}
return $response;
}
}

View File

@@ -0,0 +1,176 @@
<?php
namespace App\Core\Payment\Moka;
use App\Exceptions\ApiErrorException;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Request;
use Log;
use Exception;
class Moka
{
private $restClient;
private $userName;
private $password;
private $dealerCode;
public function __construct
(
$paymentInitializeParam
)
{
$this->restClient = new Client();
$this->requestUrl = 'https://service.moka.com';
if ($paymentInitializeParam['env'] == 'test') {
$this->requestUrl = 'https://service.refmoka.com';
}
$this->userName = $paymentInitializeParam['userName'];
$this->password = $paymentInitializeParam['password'];
$this->dealerCode = $paymentInitializeParam['dealerCode'];
}
private function errorCodes($code)
{
$codes = [
md5('PaymentDealer.CheckPaymentDealerAuthentication.InvalidRequest') => 'Hatalı hash bilgisi',
md5('PaymentDealer.CheckPaymentDealerAuthentication.InvalidAccount') => 'Böyle bir bayi bulunamadı',
md5('PaymentDealer.CheckPaymentDealerAuthentication.VirtualPosNotFound') => 'Bu bayi için sanal pos tanımı yapılmamış',
md5('PaymentDealer.RequiredFields.AmountRequired') => 'Tutar girilmemiş',
md5('PaymentDealer.DoCapture.DealerNotAuthorized') => 'Ön provizyonu provizyona çevirmek için yetkiniz yok',
md5('PaymentDealer.DoDirectPayment3dRequest.CardTokenNotFound') => 'Tanımlı CardToken bulunamadı',
md5('PaymentDealer.CheckCardInfo.InvalidCardInfo') => 'Geçersiz Kart Bilgisi',
md5('PaymentDealer.DoDirectPayment3dRequest.VirtualPosNotAvailable') => 'Bu kredi kartı için ödeme desteklenmemektedir, lütfen farklı bir kart deneyiniz',
md5('PaymentDealer.CheckDealerPaymentLimits.DailyDealerLimitExceeded') => 'Bu kredi kartı için günlük kullanım limiti dolmuştur, lütfen farklı bir kart deneyiniz',
md5('PaymentDealer.DoDirectPayment3dRequest.ThisInstallmentNumberNotAvailableForDealer') => 'Bu taksit sayısı kullanılamaz',
md5('EX') => 'Beklenmeyen bir hata oluştu'
];
return fillOnUndefined($codes, md5($code), 'Bilinmeyen bir hata oluştu');
}
private function mokaServiceResponse($getResponse, $param)
{
$response = ['status' => false, 'message' => '', 'error' => '', 'data' => []];
if ($getResponse['ResultCode'] != 'Success') {
$response['message'] = $this->errorCodes($getResponse['ResultCode']);
//Log::error($getResponse);
} else {
$response = [
'status' => true,
'data' => $getResponse['Data']
];
}
return $response;
}
protected function post($param)
{
$getResponse = [];
$param['logDebug'] = fillOnUndefined($param, 'logDebug', false);
try {
$res = $this->restClient->post($this->requestUrl. $param['method'], [
'verify' => false,
'headers' => [
'Content-Type' => 'application/json',
],
'body' => json_encode($param['param'])
]);
$getResponseBody = $res->getBody();
$getResponse = json_decode($getResponseBody, true);
if ($param['logDebug']) {
Log::debug(json_encode($param['param']));
Log::debug($param['param']);
Log::debug($getResponse);
}
$getResponse = $this->mokaServiceResponse($getResponse, $param);
} catch (Exception $e) {
$message = $e->getFile() . ' ' . $e->getLine() . ' ' . $e->getMessage();
Log::error($message);
}
return $getResponse;
}
public function paymentDealerAuthentication()
{
return [
'DealerCode' => $this->dealerCode,
'Username' => $this->userName,
'Password' => $this->password,
'CheckKey' => hash('sha256', $this->dealerCode . 'MK' . $this->userName . 'PD' . $this->password)
];
}
public function DoDirectPaymentThreeD($param = [])
{
try {
$doDirectPaymentThreeD['method'] = '/PaymentDealer/DoDirectPaymentThreeD';
$doDirectPaymentThreeD['param']['PaymentDealerAuthentication'] = $this->paymentDealerAuthentication();
$doDirectPaymentThreeD['param']['PaymentDealerRequest'] = [
'CardHolderFullName' => fillOnUndefined($param, 'CardHolderFullName'),
'CardNumber' => fillOnUndefined($param, 'CardNumber', ''),
'ExpMonth' => fillOnUndefined($param, 'ExpMonth'),//12
'ExpYear' => fillOnUndefined($param, 'ExpYear'),//2022
'CvcNumber' => fillOnUndefined($param, 'CvcNumber'),
'CardToken' => fillOnUndefined($param, 'CardToken'),
'Amount' => fillOnUndefined($param, 'Amount'),//10.50
'Currency' => fillOnUndefined($param, 'Currency', 'TL'),
'InstallmentNumber' => fillOnUndefined($param, 'InstallmentNumber', 1),
'ClientIP' => fillOnUndefined($param, 'ClientIP', Request::ip()),
'OtherTrxCode' => fillOnUndefined($param, 'OtherTrxCode', ''),
'IsPreAuth' => fillOnUndefined($param, 'IsPreAuth', 1),
'Software' => fillOnUndefined($param, 'Software', ''),
'Description' => fillOnUndefined($param, 'Description', ''),
'RedirectUrl' => fillOnUndefined($param, 'RedirectUrl'),
];
$response = $this->post($doDirectPaymentThreeD);
} catch (Exception $e) {
$response = ['status' => false, 'message' => $e->getMessage()];
} catch (ApiErrorException $e) {
$response = ['status' => false, 'message' => $e->getMessage()];
}
return $response;
}
public function getPaymentDetail($param = [])
{
try {
$getPaymentList['method'] = '/PaymentDealer/GetDealerPaymentTrxDetailList';
$getPaymentList['param']['PaymentDealerAuthentication'] = $this->paymentDealerAuthentication();
$getPaymentList['param']['PaymentDealerRequest'] = [
'PaymentId' => fillOnUndefined($param, 'PaymentId', ''),
'OtherTrxCode' => fillOnUndefined($param, 'OtherTrxCode', ''),
];
$response = $this->post($getPaymentList);
} catch (Exception $e) {
$response = ['status' => false, 'message' => $e->getMessage()];
} catch (ApiErrorException $e) {
$response = ['status' => false, 'message' => $e->getMessage()];
}
return $response;
}
}

View File

@@ -0,0 +1,170 @@
<?php
namespace App\Core\Payment\Payriff;
use App\Exceptions\ApiErrorException;
use Auth;
use Carbon\Carbon;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Log;
use Exception;
class Payriff
{
private $requestUrl;
private $secretKey;
public function __construct($paymentInitializeParam)
{
$this->restClient = new Client();
$this->requestUrl = 'https://api.payriff.com/api/v3';
if ($paymentInitializeParam['env'] == 'test') {
$this->requestUrl = 'https://api.payriff.com/api/v3';
}
$this->secretKey = $paymentInitializeParam['secretKey'];
}
private function makeRequest($method, $payloadData, $methodType = 'POST')
{
$response = ['status' => false, 'message' => ''];
try {
$requestParams['headers']['Content-Type'] = 'application/json';
$requestParams['headers']['Authorization'] = $this->secretKey;
$requestParams['body'] = json_encode($payloadData);
$result = $this->restClient->request($methodType, $this->requestUrl . '/' . $method, $requestParams);
$getResponseBody = $result->getBody()->getContents();
$getResponseData = $getResponseBody ? json_decode($getResponseBody, 1) : [];
if ($getResponseData['code'] == '00000') {
$response = [
'status' => true,
'serviceResponse' => $getResponseData
];
} else {
$response['message'] = 'Redirect url not found.';
$response['serviceResponse'] = $getResponseData;
}
} catch (ClientException $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::debug($message);
$response['message'] = $e->getMessage();
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::debug($message);
$response['message'] = $e->getMessage();
}
if (!$response['status']) {
Log::error($method);
Log::error($payloadData);
Log::error($response);
}
return $response;
}
public function paymentInitialize($param)
{
$response = ['status' => false, 'message' => ''];
try {
$paymentInitializeParam = [
'amount' => $param['amount'],
'language' => 'EN',
'currency' => $param['currencyCode'],
'description' => $param['orderId'],
'callbackUrl' => $param['paymentCheckUrl'],
'cardSave' => false,
'operation' => 'PURCHASE',
'metadata' => [
'orderId' => $param['orderId'],
]
];
$paymentInitialize = $this->makeRequest('orders', $paymentInitializeParam);
if (!$paymentInitialize['status']) {
throw new ApiErrorException($paymentInitialize['message']);
}
$response = [
'status' => true,
'data' => $paymentInitialize['serviceResponse']
];
} catch (ApiErrorException $e) {
$response = ['status' => false, 'message' => $e->getMessage()];
} catch (Exception $e) {
$response = ['status' => false, 'message' => $e->getMessage()];
Log::error($response);
}
return $response;
}
public function orderInformation($orderId)
{
$response = ['status' => false, 'message' => ''];
try {
$method = 'orders/' . $orderId;
$payloadData = [];
$orderInformationRequest = $this->makeRequest($method, $payloadData, 'GET');
if (!$orderInformationRequest['status']) {
throw new ApiErrorException($orderInformationRequest['message']);
}
$response = [
'status' => true,
'data' => $orderInformationRequest['serviceResponse']
];
} catch (ApiErrorException $e) {
$response = ['status' => false, 'message' => $e->getMessage()];
} catch (Exception $e) {
$response = ['status' => false, 'message' => $e->getMessage()];
Log::error($response);
}
if (isset($orderInformationRequest['serviceResponse'])) {
$response['serviceResponse'] = $orderInformationRequest['serviceResponse'];
}
return $response;
}
}

View File

@@ -0,0 +1,701 @@
<?php
namespace App\Core\Payment\Pos;
use Carbon\Carbon;
use GPBMetadata\Google\Api\Log;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use App\Core\Payment\Pos\Exceptions\UnsupportedPaymentModelException;
use App\Core\Payment\Pos\Exceptions\UnsupportedTransactionTypeException;
use App\Core\Payment\Pos\PosHelpersTrait;
use Illuminate\Support\Facades\Hash;
use Symfony\Component\HttpFoundation\Request;
/**
* Class EstPos
* @package Mews\Pos
*/
class AkPos implements PosInterface
{
use PosHelpersTrait;
/**
* @const string
*/
public const NAME = 'AkPos';
/**
* API URL
*
* @var string
*/
public $url;
/**
* 3D Pay Gateway URL
*
* @var string
*/
public $gateway;
/**
* Response Codes
*
* @var array
*/
public $codes = [
'00' => 'approved',
'01' => 'bank_call',
'02' => 'bank_call',
'05' => 'reject',
'09' => 'try_again',
'12' => 'invalid_transaction',
'28' => 'reject',
'51' => 'insufficient_balance',
'54' => 'expired_card',
'57' => 'does_not_allow_card_holder',
'62' => 'restricted_card',
'77' => 'request_rejected',
'99' => 'general_error',
];
/**
* Transaction Types
*
* @var array
*/
public $types = [
'pay' => 'Auth',
'pre' => 'PreAuth',
'post' => 'PostAuth',
];
/**
* Currencies
*
* @var array
*/
public $currencies = [];
/**
* Transaction Type
*
* @var string
*/
public $type;
/**
* API Account
*
* @var array
*/
protected $account = [];
/**
* Order Details
*
* @var array
*/
protected $order = [];
/**
* Credit Card
*
* @var object
*/
protected $card;
/**
* Request
*
* @var Request
*/
protected $request;
/**
* Response Raw Data
*
* @var object
*/
protected $data;
/**
* Processed Response Data
*
* @var mixed
*/
public $response;
/**
* Configuration
*
* @var array
*/
protected $config = [];
/**
* Response Raw Data
*
* @var object
*/
protected $mbrId = 5;
/**
* EstPos constructor.
*
* @param array $config
* @param mixed $account
* @param array $currencies
*/
public function __construct($config, $account, array $currencies)
{
$this->config = $config;
$this->account = $account;
$this->currencies = $currencies;
$this->url = isset($this->config['urls'][$this->account->env]) ?
$this->config['urls'][$this->account->env] :
$this->config['urls']['production'];
$this->gateway = isset($this->config['urls']['gateway'][$this->account->env]) ?
$this->config['urls']['gateway'][$this->account->env] :
$this->config['urls']['gateway']['production'];
return $this;
}
/**
* Get ProcReturnCode
*
* @return string|null
*/
protected function getRandomNumberBase16()
{
$n = 128;
$characters = '0123456789ABCDEF';
$randomString = '';
for ($i = 0; $i < $n; $i++) {
$index = rand(0, strlen($characters) - 1);
$randomString .= $characters[$index];
}
return strtoupper($randomString);
}
/**
* Create Regular Payment XML
*
* @return string
*/
protected function createRegularPaymentXML()
{
$nodes = [
'CC5Request' => [
'Name' => $this->account->username,
'Password' => $this->account->password,
'ClientId' => $this->account->client_id,
'Type' => $this->type,
'IPAddress' => $this->order->ip,
'Email' => $this->order->email,
'OrderId' => $this->order->id,
'UserId' => isset($this->order->user_id) ? $this->order->user_id : null,
'Total' => $this->order->amount,
'Currency' => $this->order->currency,
'Taksit' => $this->order->installment,
'CardType' => isset($this->card->type) ? $this->card->type : null,
'Number' => $this->card->number,
'Expires' => $this->card->month . '/' . $this->card->year,
'Cvv2Val' => $this->card->cvv,
'Mode' => 'P',
'GroupId' => '',
'TransId' => '',
'BillTo' => [
'Name' => $this->order->name ? $this->order->name : null,
]
]
];
return $this->createXML($nodes, 'ISO-8859-9');
}
/**
* Create Regular Payment Post XML
*
* @return string
*/
protected function createRegularPostXML()
{
$nodes = [
'CC5Request' => [
'Name' => $this->account->username,
'Password' => $this->account->password,
'ClientId' => $this->account->client_id,
'Type' => $this->types[$this->order->transaction],
'OrderId' => $this->order->id,
]
];
return $this->createXML($nodes, 'ISO-8859-9');
}
/**
* Create 3D Payment XML
* @return string
*/
protected function create3DPaymentXML()
{
$nodes = [
'CC5Request' => [
'Name' => $this->account->username,
'Password' => $this->account->password,
'ClientId' => $this->account->client_id,
'Type' => $this->type,
'IPAddress' => $this->order->ip,
'Email' => $this->order->email,
'OrderId' => $this->order->id,
'UserId' => isset($this->order->user_id) ? $this->order->user_id : null,
'Total' => $this->order->amount,
'Currency' => $this->order->currency,
'Taksit' => $this->order->installment,
'Number' => $this->request->get('md'),
'Expires' => '',
'Cvv2Val' => '',
'PayerTxnId' => $this->request->get('xid'),
'PayerSecurityLevel' => $this->request->get('eci'),
'PayerAuthenticationCode' => $this->request->get('cavv'),
'CardholderPresentCode' => '13',
'Mode' => 'P',
'GroupId' => '',
'TransId' => '',
]
];
if ($this->order->name) {
$nodes['BillTo'] = [
'Name' => $this->order->name,
];
}
return $this->createXML($nodes, 'ISO-8859-9');
}
/**
* Get ProcReturnCode
*
* @return string|null
*/
protected function getProcReturnCode()
{
return isset($this->data->ProcReturnCode) ? (string)$this->data->ProcReturnCode : null;
}
/**
* Get Status Detail Text
*
* @return string|null
*/
protected function getStatusDetail()
{
$proc_return_code = $this->getProcReturnCode();
return $proc_return_code ? (isset($this->codes[$proc_return_code]) ? (string)$this->codes[$proc_return_code] : null) : null;
}
/**
* Create 3D Hash
*
* @return string
*/
public function create3DHash()
{
$hashItems = [];
$hashItems[] = mb_strtoupper($this->account->model);
$hashItems[] = $this->txnCode;
$hashItems[] = $this->account->merchant_safe_id;
$hashItems[] = $this->account->terminal_safe_id;
$hashItems[] = $this->order->id;
$hashItems[] = mb_strtoupper($this->order->lang);
$hashItems[] = $this->order->amount;
//$hashItems[] = $this->order->ccbRewardAmount;
//$hashItems[] = $this->order->pcbRewardAmount;
//$hashItems[] = $this->order->xcbRewardAmount;
$hashItems[] = $this->order->currency;
$hashItems[] = $this->order->installment;
$hashItems[] = $this->order->success_url;
$hashItems[] = $this->order->fail_url;
//$hashItems[] = $this->order->emailAddress;
//$hashItems[] = $this->order->subMerchantId;
$hashItems[] = $this->card->number;
$hashItems[] = $this->getCardExpDate();
$hashItems[] = $this->card->cvv;
$hashItems[] = $this->order->rand;
$hashItems[] = $this->order->requestDateTime;
//$hashItems[] = $this->order->b2bIdentityNumber;
$hashItemsString = implode('', $hashItems);
$hashItemsStringHashed = hash_hmac('sha512', $hashItemsString, $this->account->secret_key, true);
return base64_encode($hashItemsStringHashed);
}
/**
* Check 3D Hash
*
* @param array $data
* @return bool
*/
public function check3DHash($data)
{
$return = false;
$params = explode('+', $data['hashParams']);
$builder = '';
foreach ($params as $param) {
$builder .= $data[$param];
}
$hashItemsStringHashed = hash_hmac('sha512', $builder, $this->account->secret_key, true);
$hashItemsStringHashed = base64_encode($hashItemsStringHashed);
if ($data['hash'] == $hashItemsStringHashed) {
$return = true;
}
return $return;
}
/**
* Regular Payment
*
* @return $this
* @throws GuzzleException
*/
public function makeRegularPayment()
{
return false;
}
/**
* Make 3D Payment
*
* @return $this
* @throws GuzzleException
*/
public function make3DPayment()
{
return false;
}
/**
* Make 3D Pay Payment
*
* @return $this
*/
public function make3DPayPayment()
{
$this->request = Request::createFromGlobals();
$status = 'declined';
if ($this->check3DHash($this->request->request->all()) && (string)$this->request->get('responseCode') == 'VPS-0000') {
$status = 'approved';
}
$transaction_security = 'MPI fallback';
if ($status == 'approved') {
//if ($this->request->get('3DStatus') == '1') {
$transaction_security = 'Full 3D Secure';
// } elseif (in_array($this->request->get('3DStatus'), [2, 3, 4])) {
//$transaction_security = 'Half 3D Secure';
//}
}
$this->response = (object)[
'id' => (string)$this->request->get('authCode'),
'order_id' => (string)$this->request->get('orderId'),
'trans_id' => (string)$this->request->get('rrn'),
'response' => (string)$this->request->get('responseCode'),
'merchantSafeId' => (string)$this->request->get('merchantSafeId'),
'terminalSafeId' => (string)$this->request->get('terminalSafeId'),
'transaction_type' => $this->type,
'transaction' => (string)$this->request->get('rrn'),
'transaction_security' => $transaction_security,
'auth_code' => (string)$this->request->get('authCode'),
'host_ref_num' => (string)$this->request->get('rrn'),
'proc_return_code' => (string)$this->request->get('hostResponseCode'),
'code' => (string)$this->request->get('responseCode'),
'status' => $status,
'status_detail' => $this->getStatusDetail(),
'error_code' => (string)$this->request->get('responseCode') != 'VPS-0000' ? (string)$this->request->get('responseCode') : null,
'error_message' => (string)$this->request->get('responseCode') != 'VPS-0000' ? (string)$this->request->get('responseMessage') : null,
'md_status' => (string)$this->request->get('md_status'),
'hash' => (string)$this->request->get('hash'),
'rand' => null,
'hash_params' => (string)$this->request->get('hashParams'),
'hash_params_val' => (string)$this->request->get('hash'),
'amount' => (string)$this->request->get('amount'),
'md_error_message' => (string)$this->request->get('responseCode') != 'VPS-0000' ? (string)$this->request->get('responseMessage') : null,
'all' => $this->request->request->all()
];
return $this;
}
/**
* Get 3d Form Data
*
* @return array
*/
public function get3DFormData()
{
$data = [];
if ($this->order) {
$this->order->amount = number_format($this->order->amount, 2, '.', '');
$this->order->rand = $this->getRandomNumberBase16();
$this->order->requestDateTime = mb_substr(Carbon::now()->toISOString(), 0, 23);
$this->order->installment = $this->order->installment == 0 ? 1 : $this->order->installment;
$this->order->hash = $this->create3DHash();
$inputs = [
'paymentModel' => mb_strtoupper($this->account->model),
'txnCode' => $this->txnCode,
'merchantSafeId' => $this->account->merchant_safe_id,
'terminalSafeId' => $this->account->terminal_safe_id,
'orderId' => $this->order->id,
'lang' => mb_strtoupper($this->order->lang),
'amount' => $this->order->amount,
'currencyCode' => $this->order->currency,
'installCount' => $this->order->installment,
'okUrl' => $this->order->success_url,
'failUrl' => $this->order->fail_url,
'creditCard' => $this->card->number,
'expiredDate' => $this->getCardExpDate(),
'cvv' => $this->card->cvv,
'randomNumber' => $this->order->rand,
'requestDateTime' => $this->order->requestDateTime,
'hash' => $this->order->hash,
];
$data = [
'gateway' => $this->gateway,
'success_url' => $this->order->success_url,
'fail_url' => $this->order->fail_url,
'rand' => $this->order->rand,
'hash' => $this->order->hash,
'inputs' => $inputs,
];
//$formData = $data;
//echo view('threeDSecureForm', compact('formData'));die();
}
return $data;
}
/**
* Send contents to WebService
*
* @param $contents
* @return $this
* @throws GuzzleException
*/
public function send($contents)
{
$client = new Client();
$response = $client->request('POST', $this->url, [
'body' => $contents
]);
$this->data = $this->XMLStringToObject($response->getBody()->getContents());
return $this;
}
/**
* Prepare Order
*
* @param object $order
* @param object null $card
* @return mixed
* @throws UnsupportedTransactionTypeException
*/
public function prepare($order, $card = null)
{
$this->type = $this->types['pay'];
if (isset($order->transaction)) {
if (array_key_exists($order->transaction, $this->types)) {
$this->type = $this->types[$order->transaction];
} else {
throw new UnsupportedTransactionTypeException('Unsupported transaction type!');
}
}
$this->order = $order;
$this->card = $card;
$this->txnCode = 3000;
$this->order->installment = $this->order->installment == 0 ? 0 : $this->order->installment;
}
/**
* Make Payment
*
* @param object $card
* @return mixed
* @throws UnsupportedPaymentModelException
* @throws GuzzleException
*/
public function payment($card)
{
$this->card = $card;
$model = 'regular';
if (isset($this->account->model) && $this->account->model) {
$model = $this->account->model;
}
if ($model == 'regular') {
$this->makeRegularPayment();
} elseif ($model == '3d') {
$this->make3DPayment();
} elseif ($model == '3d_pay') {
$this->make3DPayPayment();
} else {
throw new UnsupportedPaymentModelException();
}
return $this;
}
/**
* Refund Order
*
* @param array $meta
* @return $this
* @throws GuzzleException
*/
public function refund(array $meta)
{
return false;
}
/**
* Cancel Order
*
* @param array $meta
* @return $this
* @throws GuzzleException
*/
public function cancel(array $meta)
{
return false;
}
/**
* Order Status
*
* @param array $meta
* @return $this
* @throws GuzzleException
*/
public function status(array $meta)
{
return false;
}
/**
* Order History
*
* @param array $meta
* @return $this
* @throws GuzzleException
*/
public function history(array $meta)
{
return false;
}
/**
* @return array
*/
public function getConfig()
{
return $this->config;
}
/**
* @return mixed
*/
public function getAccount()
{
return $this->account;
}
/**
* @return array
*/
public function getCurrencies()
{
return $this->currencies;
}
/**
* @return mixed
*/
public function getOrder()
{
return $this->order;
}
/**
* @return mixed
*/
public function getCard()
{
return $this->card;
}
/**
* @return string|null
*/
public function getCardCode()
{
$card_type = null;
if (isset($this->card->type)) {
if ($this->card->type == 'visa') {
$card_type = '0';
} elseif ($this->card->type == 'master') {
$card_type = '1';
} elseif ($this->card->type == '1' || $this->card->type == '2') {
$card_type = $this->card->type;
}
}
return $card_type;
}
protected function getCardExpDate()
{
$year = (string)substr($this->card->year, 2, 2);
$month = (string)substr($this->card->month, 0, 2);
return (string)$month . $year;
}
}

View File

@@ -0,0 +1,881 @@
<?php
namespace App\Core\Payment\Pos;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use App\Core\Payment\Pos\Exceptions\UnsupportedPaymentModelException;
use App\Core\Payment\Pos\Exceptions\UnsupportedTransactionTypeException;
use App\Core\Payment\Pos\PosHelpersTrait;
use Symfony\Component\HttpFoundation\Request;
/**
* Class EstPos
* @package Mews\Pos
*/
class EstPos implements PosInterface
{
use PosHelpersTrait;
/**
* @const string
*/
public const NAME = 'EstPos';
/**
* API URL
*
* @var string
*/
public $url;
/**
* 3D Pay Gateway URL
*
* @var string
*/
public $gateway;
/**
* Response Codes
*
* @var array
*/
public $codes = [
'00' => 'approved',
'01' => 'bank_call',
'02' => 'bank_call',
'05' => 'reject',
'09' => 'try_again',
'12' => 'invalid_transaction',
'28' => 'reject',
'51' => 'insufficient_balance',
'54' => 'expired_card',
'57' => 'does_not_allow_card_holder',
'62' => 'restricted_card',
'77' => 'request_rejected',
'99' => 'general_error',
];
/**
* Transaction Types
*
* @var array
*/
public $types = [
'pay' => 'Auth',
'pre' => 'PreAuth',
'post' => 'PostAuth',
];
/**
* Currencies
*
* @var array
*/
public $currencies = [];
/**
* Transaction Type
*
* @var string
*/
public $type;
/**
* API Account
*
* @var array
*/
protected $account = [];
/**
* Order Details
*
* @var array
*/
protected $order = [];
/**
* Credit Card
*
* @var object
*/
protected $card;
/**
* Request
*
* @var Request
*/
protected $request;
/**
* Response Raw Data
*
* @var object
*/
protected $data;
/**
* Processed Response Data
*
* @var mixed
*/
public $response;
/**
* Configuration
*
* @var array
*/
protected $config = [];
/**
* EstPos constructor.
*
* @param array $config
* @param mixed $account
* @param array $currencies
*/
public function __construct($config, $account, array $currencies)
{
$this->config = $config;
$this->account = $account;
$this->currencies = $currencies;
$this->url = isset($this->config['urls'][$this->account->env]) ?
$this->config['urls'][$this->account->env] :
$this->config['urls']['production'];
$this->gateway = isset($this->config['urls']['gateway'][$this->account->env]) ?
$this->config['urls']['gateway'][$this->account->env] :
$this->config['urls']['gateway']['production'];
return $this;
}
/**
* Create Regular Payment XML
*
* @return string
*/
protected function createRegularPaymentXML()
{
$nodes = [
'CC5Request' => [
'Name' => $this->account->username,
'Password' => $this->account->password,
'ClientId' => $this->account->client_id,
'Type' => $this->type,
'IPAddress' => $this->order->ip,
'Email' => $this->order->email,
'OrderId' => $this->order->id,
'UserId' => isset($this->order->user_id) ? $this->order->user_id : null,
'Total' => $this->order->amount,
'Currency' => $this->order->currency,
'Taksit' => $this->order->installment,
'CardType' => isset($this->card->type) ? $this->card->type : null,
'Number' => $this->card->number,
'Expires' => $this->card->month . '/' . $this->card->year,
'Cvv2Val' => $this->card->cvv,
'Mode' => 'P',
'GroupId' => '',
'TransId' => '',
'BillTo' => [
'Name' => $this->order->name ? $this->order->name : null,
]
]
];
return $this->createXML($nodes, 'ISO-8859-9');
}
/**
* Create Regular Payment Post XML
*
* @return string
*/
protected function createRegularPostXML()
{
$nodes = [
'CC5Request' => [
'Name' => $this->account->username,
'Password' => $this->account->password,
'ClientId' => $this->account->client_id,
'Type' => $this->types[$this->order->transaction],
'OrderId' => $this->order->id,
]
];
return $this->createXML($nodes, 'ISO-8859-9');
}
/**
* Create 3D Payment XML
* @return string
*/
protected function create3DPaymentXML()
{
$nodes = [
'CC5Request' => [
'Name' => $this->account->username,
'Password' => $this->account->password,
'ClientId' => $this->account->client_id,
'Type' => $this->type,
'IPAddress' => $this->order->ip,
'Email' => $this->order->email,
'OrderId' => $this->order->id,
'UserId' => isset($this->order->user_id) ? $this->order->user_id : null,
'Total' => $this->order->amount,
'Currency' => $this->order->currency,
'Taksit' => $this->order->installment,
'Number' => $this->request->get('md'),
'Expires' => '',
'Cvv2Val' => '',
'PayerTxnId' => $this->request->get('xid'),
'PayerSecurityLevel' => $this->request->get('eci'),
'PayerAuthenticationCode' => $this->request->get('cavv'),
'CardholderPresentCode' => '13',
'Mode' => 'P',
'GroupId' => '',
'TransId' => '',
]
];
if ($this->order->name) {
$nodes['BillTo'] = [
'Name' => $this->order->name,
];
}
return $this->createXML($nodes, 'ISO-8859-9');
}
/**
* Get ProcReturnCode
*
* @return string|null
*/
protected function getProcReturnCode()
{
return isset($this->data->ProcReturnCode) ? (string)$this->data->ProcReturnCode : null;
}
/**
* Get Status Detail Text
*
* @return string|null
*/
protected function getStatusDetail()
{
$proc_return_code = $this->getProcReturnCode();
return $proc_return_code ? (isset($this->codes[$proc_return_code]) ? (string)$this->codes[$proc_return_code] : null) : null;
}
/**
* Create 3D Hash
*
* @return string
*/
public function create3DHash()
{
$hash_str = '';
if ($this->account->model == '3d') {
$hash_str = $this->account->client_id . $this->order->id . $this->order->amount . $this->order->success_url . $this->order->fail_url . $this->order->rand . $this->account->store_key;
} elseif ($this->account->model == '3d_pay') {
$hash_str = $this->account->client_id . $this->order->id . $this->order->amount . $this->order->success_url . $this->order->fail_url . $this->type . $this->order->installment . $this->order->rand . $this->account->store_key;
}
return base64_encode(sha1($hash_str, true));
}
/**
* Check 3D Hash
*
* @param array $data
* @return bool
*/
public function check3DHash($data)
{
$hash_params = $data['HASHPARAMS'];
$hash_params_val = $data['HASHPARAMSVAL'];
$hash_param = $data['HASH'];
$params_val = '';
$hashparams_arr = explode(':', $hash_params);
foreach ($hashparams_arr as $value) {
if(!empty($value) && isset($data[$value])){
$params_val = $params_val . $data[$value];
}
}
$hash_val = $params_val . $this->account->store_key;
$hash = base64_encode(sha1($hash_val, true));
$return = false;
if ($hash_params && !($params_val != $hash_params_val || $hash_param != $hash)) {
$return = true;
}
return $return;
}
/**
* Regular Payment
*
* @return $this
* @throws GuzzleException
*/
public function makeRegularPayment()
{
$contents = '';
if (in_array($this->order->transaction, ['pay', 'pre'])) {
$contents = $this->createRegularPaymentXML();
} elseif ($this->order->transaction == 'post') {
$contents = $this->createRegularPostXML();
}
$this->send($contents);
$status = 'declined';
if ($this->getProcReturnCode() == '00') {
$status = 'approved';
}
$this->response = (object)[
'id' => isset($this->data->AuthCode) ? $this->printData($this->data->AuthCode) : null,
'order_id' => isset($this->data->OrderId) ? $this->printData($this->data->OrderId) : null,
'group_id' => isset($this->data->GroupId) ? $this->printData($this->data->GroupId) : null,
'trans_id' => isset($this->data->TransId) ? $this->printData($this->data->TransId) : null,
'response' => isset($this->data->Response) ? $this->printData($this->data->Response) : null,
'transaction_type' => $this->type,
'transaction' => $this->order->transaction,
'auth_code' => isset($this->data->AuthCode) ? $this->printData($this->data->AuthCode) : null,
'host_ref_num' => isset($this->data->HostRefNum) ? $this->printData($this->data->HostRefNum) : null,
'proc_return_code' => isset($this->data->ProcReturnCode) ? $this->printData($this->data->ProcReturnCode) : null,
'code' => isset($this->data->ProcReturnCode) ? $this->printData($this->data->ProcReturnCode) : null,
'status' => $status,
'status_detail' => $this->getStatusDetail(),
'error_code' => isset($this->data->Extra->ERRORCODE) ? $this->printData($this->data->Extra->ERRORCODE) : null,
'error_message' => isset($this->data->Extra->ERRORCODE) ? $this->printData($this->data->ErrMsg) : null,
'campaign_url' => null,
'extra' => isset($this->data->Extra) ? $this->data->Extra : null,
'all' => $this->data,
'original' => $this->data,
];
return $this;
}
/**
* Make 3D Payment
*
* @return $this
* @throws GuzzleException
*/
public function make3DPayment()
{
$this->request = Request::createFromGlobals();
$status = 'declined';
if ($this->check3DHash($this->request->request->all())) {
$contents = $this->create3DPaymentXML();
$this->send($contents);
}
$transaction_security = 'MPI fallback';
if ($this->getProcReturnCode() == '00') {
if ($this->request->get('mdStatus') == '1') {
$transaction_security = 'Full 3D Secure';
} elseif (in_array($this->request->get('mdStatus'), [2, 3, 4])) {
$transaction_security = 'Half 3D Secure';
}
$status = 'approved';
}
$this->response = (object)[
'id' => isset($this->data->AuthCode) ? $this->printData($this->data->AuthCode) : null,
'order_id' => isset($this->data->OrderId) ? $this->printData($this->data->OrderId) : null,
'group_id' => isset($this->data->GroupId) ? $this->printData($this->data->GroupId) : null,
'trans_id' => isset($this->data->TransId) ? $this->printData($this->data->TransId) : null,
'response' => isset($this->data->Response) ? $this->printData($this->data->Response) : null,
'transaction_type' => $this->type,
'transaction' => $this->order->transaction,
'transaction_security' => $transaction_security,
'auth_code' => isset($this->data->AuthCode) ? $this->printData($this->data->AuthCode) : null,
'host_ref_num' => isset($this->data->HostRefNum) ? $this->printData($this->data->HostRefNum) : null,
'proc_return_code' => isset($this->data->ProcReturnCode) ? $this->printData($this->data->ProcReturnCode) : null,
'code' => isset($this->data->ProcReturnCode) ? $this->printData($this->data->ProcReturnCode) : null,
'status' => $status,
'status_detail' => $this->getStatusDetail(),
'error_code' => isset($this->data->Extra->ERRORCODE) ? $this->printData($this->data->Extra->ERRORCODE) : null,
'error_message' => isset($this->data->Extra->ERRORCODE) ? $this->printData($this->data->ErrMsg) : null,
'md_status' => $this->request->get('mdStatus'),
'hash' => (string)$this->request->get('HASH'),
'rand' => (string)$this->request->get('rnd'),
'hash_params' => (string)$this->request->get('HASHPARAMS'),
'hash_params_val' => (string)$this->request->get('HASHPARAMSVAL'),
'masked_number' => (string)$this->request->get('maskedCreditCard'),
'month' => (string)$this->request->get('Ecom_Payment_Card_ExpDate_Month'),
'year' => (string)$this->request->get('Ecom_Payment_Card_ExpDate_Year'),
'amount' => (string)$this->request->get('amount'),
'currency' => (string)$this->request->get('currency'),
'tx_status' => (string)$this->request->get('txstatus'),
'eci' => (string)$this->request->get('eci'),
'cavv' => (string)$this->request->get('cavv'),
'xid' => (string)$this->request->get('xid'),
'md_error_message' => (string)$this->request->get('mdErrorMsg'),
'name' => (string)$this->request->get('firmaadi'),
'campaign_url' => null,
'email' => (string)$this->request->get('Email'),
'extra' => isset($this->data->Extra) ? $this->data->Extra : null,
'all' => $this->data,
'3d_all' => $this->request->request->all(),
];
return $this;
}
/**
* Make 3D Pay Payment
*
* @return $this
*/
public function make3DPayPayment()
{
$this->request = Request::createFromGlobals();
$status = 'declined';
if ($this->check3DHash($this->request->request->all()) && (string)$this->request->get('ProcReturnCode') == '00') {
if (in_array($this->request->get('mdStatus'), [1, 2, 3, 4])) {
$status = 'approved';
}
}
$transaction_security = 'MPI fallback';
if ($status == 'approved') {
if ($this->request->get('mdStatus') == '1') {
$transaction_security = 'Full 3D Secure';
} elseif (in_array($this->request->get('mdStatus'), [2, 3, 4])) {
$transaction_security = 'Half 3D Secure';
}
}
$this->response = (object)[
'id' => (string)$this->request->get('AuthCode'),
'trans_id' => (string)$this->request->get('TransId'),
'auth_code' => (string)$this->request->get('AuthCode'),
'host_ref_num' => (string)$this->request->get('HostRefNum'),
'response' => (string)$this->request->get('Response'),
'order_id' => (string)$this->request->get('oid'),
'transaction_type' => $this->type,
'transaction' => $this->order->transaction,
'transaction_security' => $transaction_security,
'code' => (string)$this->request->get('ProcReturnCode'),
'md_status' => $this->request->get('mdStatus'),
'status' => $status,
'status_detail' => isset($this->codes[$this->request->get('ProcReturnCode')]) ? (string)$this->request->get('ProcReturnCode') : null,
'hash' => (string)$this->request->get('HASH'),
'rand' => (string)$this->request->get('rnd'),
'hash_params' => (string)$this->request->get('HASHPARAMS'),
'hash_params_val' => (string)$this->request->get('HASHPARAMSVAL'),
'masked_number' => (string)$this->request->get('maskedCreditCard'),
'month' => (string)$this->request->get('Ecom_Payment_Card_ExpDate_Month'),
'year' => (string)$this->request->get('Ecom_Payment_Card_ExpDate_Year'),
'amount' => (string)$this->request->get('amount'),
'currency' => (string)$this->request->get('currency'),
'tx_status' => (string)$this->request->get('txstatus'),
'eci' => (string)$this->request->get('eci'),
'cavv' => (string)$this->request->get('cavv'),
'xid' => (string)$this->request->get('xid'),
'error_code' => (string)$this->request->get('ErrCode'),
'error_message' => (string)$this->request->get('ErrMsg'),
'md_error_message' => (string)$this->request->get('mdErrorMsg'),
'name' => (string)$this->request->get('firmaadi'),
'email' => (string)$this->request->get('Email'),
'campaign_url' => null,
'extra' => $this->request->get('Extra'),
'all' => $this->request->request->all(),
];
return $this;
}
/**
* Get 3d Form Data
*
* @return array
*/
public function get3DFormData()
{
$data = [];
if ($this->order) {
$this->order->hash = $this->create3DHash();
$inputs = [
'clientid' => $this->account->client_id,
'storetype' => $this->account->model,
'hash' => $this->order->hash,
'cardType' => $this->getCardCode(),
'pan' => $this->card->number,
'Ecom_Payment_Card_ExpDate_Month' => $this->card->month,
'Ecom_Payment_Card_ExpDate_Year' => $this->card->year,
'cv2' => $this->card->cvv,
'firmaadi' => $this->order->name,
'Email' => $this->order->email,
'amount' => $this->order->amount,
'oid' => $this->order->id,
'okUrl' => $this->order->success_url,
'failUrl' => $this->order->fail_url,
'rnd' => $this->order->rand,
'lang' => $this->order->lang,
'currency' => $this->order->currency,
];
if ($this->account->model == '3d_pay') {
$inputs = array_merge($inputs, [
'islemtipi' => $this->type,
'taksit' => $this->order->installment,
]);
}
$data = [
'gateway' => $this->gateway,
'success_url' => $this->order->success_url,
'fail_url' => $this->order->fail_url,
'rand' => $this->order->rand,
'hash' => $this->order->hash,
'inputs' => $inputs,
];
}
return $data;
}
/**
* Send contents to WebService
*
* @param $contents
* @return $this
* @throws GuzzleException
*/
public function send($contents)
{
$client = new Client();
$response = $client->request('POST', $this->url, [
'body' => $contents
]);
$this->data = $this->XMLStringToObject($response->getBody()->getContents());
return $this;
}
/**
* Prepare Order
*
* @param object $order
* @param object null $card
* @return mixed
* @throws UnsupportedTransactionTypeException
*/
public function prepare($order, $card = null)
{
$this->type = $this->types['pay'];
if (isset($order->transaction)) {
if (array_key_exists($order->transaction, $this->types)) {
$this->type = $this->types[$order->transaction];
} else {
throw new UnsupportedTransactionTypeException('Unsupported transaction type!');
}
}
$this->order = $order;
$this->card = $card;
}
/**
* Make Payment
*
* @param object $card
* @return mixed
* @throws UnsupportedPaymentModelException
* @throws GuzzleException
*/
public function payment($card)
{
$this->card = $card;
$model = 'regular';
if (isset($this->account->model) && $this->account->model) {
$model = $this->account->model;
}
if ($model == 'regular') {
$this->makeRegularPayment();
} elseif ($model == '3d') {
$this->make3DPayment();
} elseif ($model == '3d_pay') {
$this->make3DPayPayment();
} else {
throw new UnsupportedPaymentModelException();
}
return $this;
}
/**
* Refund Order
*
* @param array $meta
* @return $this
* @throws GuzzleException
*/
public function refund(array $meta)
{
$nodes = [
'CC5Request' => [
'Name' => $this->account->username,
'Password' => $this->account->password,
'ClientId' => $this->account->client_id,
'OrderId' => $meta['order_id'],
'Type' => 'Credit',
]
];
if ($meta['amount']) $nodes['Total'] = $meta['amount'];
$xml = $this->createXML($nodes, 'ISO-8859-9');
$this->send($xml);
$status = 'declined';
if ($this->getProcReturnCode() == '00') {
$status = 'approved';
}
$this->response = (object)[
'order_id' => isset($this->data->OrderId) ? $this->data->OrderId : null,
'group_id' => isset($this->data->GroupId) ? $this->data->GroupId : null,
'response' => isset($this->data->Response) ? $this->data->Response : null,
'auth_code' => isset($this->data->AuthCode) ? $this->data->AuthCode : null,
'host_ref_num' => isset($this->data->HostRefNum) ? $this->data->HostRefNum : null,
'proc_return_code' => isset($this->data->ProcReturnCode) ? $this->data->ProcReturnCode : null,
'trans_id' => isset($this->data->TransId) ? $this->data->TransId : null,
'error_code' => isset($this->data->Extra->ERRORCODE) ? $this->data->Extra->ERRORCODE : null,
'error_message' => isset($this->data->ErrMsg) ? $this->data->ErrMsg : null,
'status' => $status,
'status_detail' => $this->getStatusDetail(),
'all' => $this->data,
];
return $this;
}
/**
* Cancel Order
*
* @param array $meta
* @return $this
* @throws GuzzleException
*/
public function cancel(array $meta)
{
$xml = $this->createXML([
'CC5Request' => [
'Name' => $this->account->username,
'Password' => $this->account->password,
'ClientId' => $this->account->client_id,
'OrderId' => $meta['order_id'],
'Type' => 'Void',
]
], 'ISO-8859-9');
$this->send($xml);
$status = 'declined';
if ($this->getProcReturnCode() == '00') {
$status = 'approved';
}
$this->response = (object)[
'order_id' => isset($this->data->OrderId) ? $this->data->OrderId : null,
'group_id' => isset($this->data->GroupId) ? $this->data->GroupId : null,
'response' => isset($this->data->Response) ? $this->data->Response : null,
'auth_code' => isset($this->data->AuthCode) ? $this->data->AuthCode : null,
'host_ref_num' => isset($this->data->HostRefNum) ? $this->data->HostRefNum : null,
'proc_return_code' => isset($this->data->ProcReturnCode) ? $this->data->ProcReturnCode : null,
'trans_id' => isset($this->data->TransId) ? $this->data->TransId : null,
'error_code' => isset($this->data->Extra->ERRORCODE) ? $this->data->Extra->ERRORCODE : null,
'error_message' => isset($this->data->ErrMsg) ? $this->data->ErrMsg : null,
'status' => $status,
'status_detail' => $this->getStatusDetail(),
'all' => $this->data,
];
return $this;
}
/**
* Order Status
*
* @param array $meta
* @return $this
* @throws GuzzleException
*/
public function status(array $meta)
{
$xml = $this->createXML([
'CC5Request' => [
'Name' => $this->account->username,
'Password' => $this->account->password,
'ClientId' => $this->account->client_id,
'OrderId' => $meta['order_id'],
'Extra' => [
'ORDERSTATUS' => 'QUERY',
],
]
], 'ISO-8859-9');
$this->send($xml);
$status = 'declined';
if ($this->getProcReturnCode() == '00') {
$status = 'approved';
}
$first_amount = isset($this->data->Extra->ORIG_TRANS_AMT) ? $this->printData($this->data->Extra->ORIG_TRANS_AMT) : null;
$capture_amount = isset($this->data->Extra->CAPTURE_AMT) ? $this->printData($this->data->Extra->CAPTURE_AMT) : null;
$capture = $first_amount == $capture_amount ? true : false;
$this->response = (object)[
'order_id' => isset($this->data->OrderId) ? $this->printData($this->data->OrderId) : null,
'response' => isset($this->data->Response) ? $this->printData($this->data->Response) : null,
'proc_return_code' => isset($this->data->ProcReturnCode) ? $this->printData($this->data->ProcReturnCode) : null,
'trans_id' => isset($this->data->TransId) ? $this->printData($this->data->TransId) : null,
'error_message' => isset($this->data->ErrMsg) ? $this->printData($this->data->ErrMsg) : null,
'host_ref_num' => isset($this->data->Extra->HOST_REF_NUM) ? $this->printData($this->data->Extra->HOST_REF_NUM) : null,
'order_status' => isset($this->data->Extra->ORDERSTATUS) ? $this->printData($this->data->Extra->ORDERSTATUS) : null,
'process_type' => isset($this->data->Extra->CHARGE_TYPE_CD) ? $this->printData($this->data->Extra->CHARGE_TYPE_CD) : null,
'pan' => isset($this->data->Extra->PAN) ? $this->printData($this->data->Extra->PAN) : null,
'num_code' => isset($this->data->Extra->NUMCODE) ? $this->printData($this->data->Extra->NUMCODE) : null,
'first_amount' => $first_amount,
'capture_amount' => $capture_amount,
'status' => $status,
'status_detail' => $this->getStatusDetail(),
'capture' => $capture,
'all' => $this->data,
'xml' => $xml,
];
return $this;
}
/**
* Order History
*
* @param array $meta
* @return $this
* @throws GuzzleException
*/
public function history(array $meta)
{
$xml = $this->createXML([
'CC5Request' => [
'Name' => $this->account->username,
'Password' => $this->account->password,
'ClientId' => $this->account->client_id,
'OrderId' => $meta['order_id'],
'Extra' => [
'ORDERHISTORY' => 'QUERY',
],
]
], 'ISO-8859-9');
$this->send($xml);
$status = 'declined';
if ($this->getProcReturnCode() == '00') {
$status = 'approved';
}
$this->response = (object)[
'order_id' => isset($this->data->OrderId) ? $this->printData($this->data->OrderId) : null,
'response' => isset($this->data->Response) ? $this->printData($this->data->Response) : null,
'proc_return_code' => isset($this->data->ProcReturnCode) ? $this->printData($this->data->ProcReturnCode) : null,
'error_message' => isset($this->data->ErrMsg) ? $this->printData($this->data->ErrMsg) : null,
'num_code' => isset($this->data->Extra->NUMCODE) ? $this->printData($this->data->Extra->NUMCODE) : null,
'trans_count' => isset($this->data->Extra->TRXCOUNT) ? $this->printData($this->data->Extra->TRXCOUNT) : null,
'status' => $status,
'status_detail' => $this->getStatusDetail(),
'all' => $this->data,
'xml' => $xml,
];
return $this;
}
/**
* @return array
*/
public function getConfig()
{
return $this->config;
}
/**
* @return mixed
*/
public function getAccount()
{
return $this->account;
}
/**
* @return array
*/
public function getCurrencies()
{
return $this->currencies;
}
/**
* @return mixed
*/
public function getOrder()
{
return $this->order;
}
/**
* @return mixed
*/
public function getCard()
{
return $this->card;
}
/**
* @return string|null
*/
public function getCardCode()
{
$card_type = null;
if (isset($this->card->type)) {
if ($this->card->type == 'visa') {
$card_type = '1';
} elseif ($this->card->type == 'master') {
$card_type = '2';
}elseif($this->card->type == '1' || $this->card->type == '2'){
$card_type = $this->card->type;
}
}
return $card_type;
}
}

View File

@@ -0,0 +1,913 @@
<?php
namespace App\Core\Payment\Pos;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use App\Core\Payment\Pos\Exceptions\UnsupportedPaymentModelException;
use App\Core\Payment\Pos\Exceptions\UnsupportedTransactionTypeException;
use App\Core\Payment\Pos\PosHelpersTrait;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\Request;
/**
* Class EstPos
* @package Mews\Pos
*/
class EstPosV3 implements PosInterface
{
use PosHelpersTrait;
/**
* @const string
*/
public const NAME = 'EstPos';
/**
* API URL
*
* @var string
*/
public $url;
/**
* 3D Pay Gateway URL
*
* @var string
*/
public $gateway;
/**
* Response Codes
*
* @var array
*/
public $codes = [
'00' => 'approved',
'01' => 'bank_call',
'02' => 'bank_call',
'05' => 'reject',
'09' => 'try_again',
'12' => 'invalid_transaction',
'28' => 'reject',
'51' => 'insufficient_balance',
'54' => 'expired_card',
'57' => 'does_not_allow_card_holder',
'62' => 'restricted_card',
'77' => 'request_rejected',
'99' => 'general_error',
];
/**
* Transaction Types
*
* @var array
*/
public $types = [
'pay' => 'Auth',
'pre' => 'PreAuth',
'post' => 'PostAuth',
];
/**
* Currencies
*
* @var array
*/
public $currencies = [];
/**
* Transaction Type
*
* @var string
*/
public $type;
/**
* API Account
*
* @var array
*/
protected $account = [];
/**
* Order Details
*
* @var array
*/
protected $order = [];
/**
* Credit Card
*
* @var object
*/
protected $card;
/**
* Request
*
* @var Request
*/
protected $request;
/**
* Response Raw Data
*
* @var object
*/
protected $data;
/**
* Processed Response Data
*
* @var mixed
*/
public $response;
/**
* Configuration
*
* @var array
*/
protected $config = [];
/**
* EstPos constructor.
*
* @param array $config
* @param mixed $account
* @param array $currencies
*/
public function __construct($config, $account, array $currencies)
{
$this->config = $config;
$this->account = $account;
$this->currencies = $currencies;
$this->url = isset($this->config['urls'][$this->account->env]) ?
$this->config['urls'][$this->account->env] :
$this->config['urls']['production'];
$this->gateway = isset($this->config['urls']['gateway'][$this->account->env]) ?
$this->config['urls']['gateway'][$this->account->env] :
$this->config['urls']['gateway']['production'];
return $this;
}
/**
* Create Regular Payment XML
*
* @return string
*/
protected function createRegularPaymentXML()
{
$nodes = [
'CC5Request' => [
'Name' => $this->account->username,
'Password' => $this->account->password,
'ClientId' => $this->account->client_id,
'Type' => $this->type,
'IPAddress' => $this->order->ip,
'Email' => $this->order->email,
'OrderId' => $this->order->id,
'UserId' => isset($this->order->user_id) ? $this->order->user_id : null,
'Total' => $this->order->amount,
'Currency' => $this->order->currency,
'Taksit' => $this->order->installment,
'CardType' => isset($this->card->type) ? $this->card->type : null,
'Number' => $this->card->number,
'Expires' => $this->card->month . '/' . $this->card->year,
'Cvv2Val' => $this->card->cvv,
'Mode' => 'P',
'GroupId' => '',
'TransId' => '',
'BillTo' => [
'Name' => $this->order->name ? $this->order->name : null,
]
]
];
return $this->createXML($nodes, 'ISO-8859-9');
}
/**
* Create Regular Payment Post XML
*
* @return string
*/
protected function createRegularPostXML()
{
$nodes = [
'CC5Request' => [
'Name' => $this->account->username,
'Password' => $this->account->password,
'ClientId' => $this->account->client_id,
'Type' => $this->types[$this->order->transaction],
'OrderId' => $this->order->id,
]
];
return $this->createXML($nodes, 'ISO-8859-9');
}
/**
* Create 3D Payment XML
* @return string
*/
protected function create3DPaymentXML()
{
$nodes = [
'CC5Request' => [
'Name' => $this->account->username,
'Password' => $this->account->password,
'ClientId' => $this->account->client_id,
'Type' => $this->type,
'IPAddress' => $this->order->ip,
'Email' => $this->order->email,
'OrderId' => $this->order->id,
'UserId' => isset($this->order->user_id) ? $this->order->user_id : null,
'Total' => $this->order->amount,
'Currency' => $this->order->currency,
'Taksit' => $this->order->installment,
'Number' => $this->request->get('md'),
'Expires' => '',
'Cvv2Val' => '',
'PayerTxnId' => $this->request->get('xid'),
'PayerSecurityLevel' => $this->request->get('eci'),
'PayerAuthenticationCode' => $this->request->get('cavv'),
'CardholderPresentCode' => '13',
'Mode' => 'P',
'GroupId' => '',
'TransId' => '',
]
];
if ($this->order->name) {
$nodes['BillTo'] = [
'Name' => $this->order->name,
];
}
return $this->createXML($nodes, 'ISO-8859-9');
}
/**
* Get ProcReturnCode
*
* @return string|null
*/
protected function getProcReturnCode()
{
return isset($this->data->ProcReturnCode) ? (string)$this->data->ProcReturnCode : null;
}
/**
* Get Status Detail Text
*
* @return string|null
*/
protected function getStatusDetail()
{
$proc_return_code = $this->getProcReturnCode();
return $proc_return_code ? (isset($this->codes[$proc_return_code]) ? (string)$this->codes[$proc_return_code] : null) : null;
}
/**
* Create 3D Hash
*
* @return string
*/
public function create3DHash($inputs)
{
$hash3D = null;
$postParams = [];
foreach ($inputs as $key => $value){
array_push($postParams, $key);
}
natcasesort($postParams);
$hashval = "";
foreach ($postParams as $param){
$paramValue = $inputs[$param];
$escapedParamValue = str_replace("|", "\\|", str_replace("\\", "\\\\", $paramValue));
$lowerParam = strtolower($param);
if($lowerParam != "hash" && $lowerParam != "encoding" ) {
$hashval = $hashval . $escapedParamValue . "|";
}
}
$storeKey = $this->account->store_key;
$escapedStoreKey = str_replace("|", "\\|", str_replace("\\", "\\\\", $storeKey));
$hashval = $hashval . $escapedStoreKey;
$calculatedHashValue = hash('sha512', $hashval);
$hash3D = base64_encode (pack('H*',$calculatedHashValue));
return $hash3D;
}
/**
* Check 3D Hash
*
* @param array $data
* @return bool
*/
public function check3DHash($data)
{
$return = false;
Log::debug('LOG - 1');
Log::debug($data);
$postParams = [];
foreach ($data as $key => $value) {
array_push($postParams, $key);
}
natcasesort($postParams);
$hashval = "";
foreach ($postParams as $param) {
$paramValue = $data[$param];
$escapedParamValue = str_replace("|", "\\|", str_replace("\\", "\\\\", $paramValue));
$lowerParam = strtolower($param);
if ($lowerParam != "hash" && $lowerParam != "encoding") {
$hashval = $hashval . $escapedParamValue . "|";
}
}
$storeKey = $this->account->store_key;
$escapedStoreKey = str_replace("|", "\\|", str_replace("\\", "\\\\", $storeKey));
$hashval = $hashval . $escapedStoreKey;
$calculatedHashValue = hash('sha512', $hashval);
$actualHash = base64_encode(pack('H*', $calculatedHashValue));
$retrievedHash = fillOnUndefined($data,'HASH');
Log::debug('LOG - 2');
Log::debug($data);
if ($retrievedHash == $actualHash) {
$return = true;
}
return $return;
}
/**
* Regular Payment
*
* @return $this
* @throws GuzzleException
*/
public function makeRegularPayment()
{
$contents = '';
if (in_array($this->order->transaction, ['pay', 'pre'])) {
$contents = $this->createRegularPaymentXML();
} elseif ($this->order->transaction == 'post') {
$contents = $this->createRegularPostXML();
}
$this->send($contents);
$status = 'declined';
if ($this->getProcReturnCode() == '00') {
$status = 'approved';
}
$this->response = (object)[
'id' => isset($this->data->AuthCode) ? $this->printData($this->data->AuthCode) : null,
'order_id' => isset($this->data->OrderId) ? $this->printData($this->data->OrderId) : null,
'group_id' => isset($this->data->GroupId) ? $this->printData($this->data->GroupId) : null,
'trans_id' => isset($this->data->TransId) ? $this->printData($this->data->TransId) : null,
'response' => isset($this->data->Response) ? $this->printData($this->data->Response) : null,
'transaction_type' => $this->type,
'transaction' => $this->order->transaction,
'auth_code' => isset($this->data->AuthCode) ? $this->printData($this->data->AuthCode) : null,
'host_ref_num' => isset($this->data->HostRefNum) ? $this->printData($this->data->HostRefNum) : null,
'proc_return_code' => isset($this->data->ProcReturnCode) ? $this->printData($this->data->ProcReturnCode) : null,
'code' => isset($this->data->ProcReturnCode) ? $this->printData($this->data->ProcReturnCode) : null,
'status' => $status,
'status_detail' => $this->getStatusDetail(),
'error_code' => isset($this->data->Extra->ERRORCODE) ? $this->printData($this->data->Extra->ERRORCODE) : null,
'error_message' => isset($this->data->Extra->ERRORCODE) ? $this->printData($this->data->ErrMsg) : null,
'campaign_url' => null,
'extra' => isset($this->data->Extra) ? $this->data->Extra : null,
'all' => $this->data,
'original' => $this->data,
];
return $this;
}
/**
* Make 3D Payment
*
* @return $this
* @throws GuzzleException
*/
public function make3DPayment()
{
$this->request = Request::createFromGlobals();
$status = 'declined';
if ($this->check3DHash($this->request->request->all())) {
$contents = $this->create3DPaymentXML();
$this->send($contents);
}
$transaction_security = 'MPI fallback';
if ($this->getProcReturnCode() == '00') {
if ($this->request->get('mdStatus') == '1') {
$transaction_security = 'Full 3D Secure';
} elseif (in_array($this->request->get('mdStatus'), [2, 3, 4])) {
$transaction_security = 'Half 3D Secure';
}
$status = 'approved';
}
$this->response = (object)[
'id' => isset($this->data->AuthCode) ? $this->printData($this->data->AuthCode) : null,
'order_id' => isset($this->data->OrderId) ? $this->printData($this->data->OrderId) : null,
'group_id' => isset($this->data->GroupId) ? $this->printData($this->data->GroupId) : null,
'trans_id' => isset($this->data->TransId) ? $this->printData($this->data->TransId) : null,
'response' => isset($this->data->Response) ? $this->printData($this->data->Response) : null,
'transaction_type' => $this->type,
'transaction' => $this->order->transaction,
'transaction_security' => $transaction_security,
'auth_code' => isset($this->data->AuthCode) ? $this->printData($this->data->AuthCode) : null,
'host_ref_num' => isset($this->data->HostRefNum) ? $this->printData($this->data->HostRefNum) : null,
'proc_return_code' => isset($this->data->ProcReturnCode) ? $this->printData($this->data->ProcReturnCode) : null,
'code' => isset($this->data->ProcReturnCode) ? $this->printData($this->data->ProcReturnCode) : null,
'status' => $status,
'status_detail' => $this->getStatusDetail(),
'error_code' => isset($this->data->Extra->ERRORCODE) ? $this->printData($this->data->Extra->ERRORCODE) : null,
'error_message' => isset($this->data->Extra->ERRORCODE) ? $this->printData($this->data->ErrMsg) : null,
'md_status' => $this->request->get('mdStatus'),
'hash' => (string)$this->request->get('HASH'),
'rand' => (string)$this->request->get('rnd'),
'hash_params' => (string)$this->request->get('HASHPARAMS'),
'hash_params_val' => (string)$this->request->get('HASHPARAMSVAL'),
'masked_number' => (string)$this->request->get('maskedCreditCard'),
'month' => (string)$this->request->get('Ecom_Payment_Card_ExpDate_Month'),
'year' => (string)$this->request->get('Ecom_Payment_Card_ExpDate_Year'),
'amount' => (string)$this->request->get('amount'),
'currency' => (string)$this->request->get('currency'),
'tx_status' => (string)$this->request->get('txstatus'),
'eci' => (string)$this->request->get('eci'),
'cavv' => (string)$this->request->get('cavv'),
'xid' => (string)$this->request->get('xid'),
'md_error_message' => (string)$this->request->get('mdErrorMsg'),
'name' => (string)$this->request->get('firmaadi'),
'campaign_url' => null,
'email' => (string)$this->request->get('Email'),
'extra' => isset($this->data->Extra) ? $this->data->Extra : null,
'all' => $this->data,
'3d_all' => $this->request->request->all(),
];
return $this;
}
/**
* Make 3D Pay Payment
*
* @return $this
*/
public function make3DPayPayment()
{
$this->request = Request::createFromGlobals();
$status = 'declined';
if ($this->check3DHash($this->request->request->all()) && (string)$this->request->get('ProcReturnCode') == '00') {
if (in_array($this->request->get('mdStatus'), [1, 2, 3, 4])) {
$status = 'approved';
}
}
$transaction_security = 'MPI fallback';
if ($status == 'approved') {
if ($this->request->get('mdStatus') == '1') {
$transaction_security = 'Full 3D Secure';
} elseif (in_array($this->request->get('mdStatus'), [2, 3, 4])) {
$transaction_security = 'Half 3D Secure';
}
}
$this->response = (object)[
'id' => (string)$this->request->get('AuthCode'),
'trans_id' => (string)$this->request->get('TransId'),
'auth_code' => (string)$this->request->get('AuthCode'),
'host_ref_num' => (string)$this->request->get('HostRefNum'),
'response' => (string)$this->request->get('Response'),
'order_id' => (string)$this->request->get('oid'),
'transaction_type' => $this->type,
'transaction' => $this->order->transaction,
'transaction_security' => $transaction_security,
'code' => (string)$this->request->get('ProcReturnCode'),
'md_status' => $this->request->get('mdStatus'),
'status' => $status,
'status_detail' => isset($this->codes[$this->request->get('ProcReturnCode')]) ? (string)$this->request->get('ProcReturnCode') : null,
'hash' => (string)$this->request->get('HASH'),
'rand' => (string)$this->request->get('rnd'),
'masked_number' => (string)$this->request->get('maskedCreditCard'),
'month' => (string)$this->request->get('Ecom_Payment_Card_ExpDate_Month'),
'year' => (string)$this->request->get('Ecom_Payment_Card_ExpDate_Year'),
'amount' => (string)$this->request->get('amount'),
'currency' => (string)$this->request->get('currency'),
'hashAlgorithm' => (string)$this->request->get('hashAlgorithm'),
'xid' => (string)$this->request->get('xid'),
'error_code' => (string)$this->request->get('ErrCode'),
'error_message' => ($status != 'approved' && empty((string)$this->request->get('ErrMsg'))) ? (string)$this->request->get('mdErrorMsg') : (string)$this->request->get('ErrMsg'),
'md_error_message' => (string)$this->request->get('mdErrorMsg'),
'merchantName' => (string)$this->request->get('merchantName'),
'all' => $this->request->request->all(),
];
return $this;
}
/**
* Get 3d Form Data
*
* @return array
*/
public function get3DFormData()
{
$data = [];
if ($this->order) {
$inputs = [
'clientid' => $this->account->client_id,
'storetype' => $this->account->model,
'hashAlgorithm' => 'ver3',
'cardType' => $this->getCardCode(),
'pan' => $this->card->number,
'Ecom_Payment_Card_ExpDate_Month' => $this->card->month,
'Ecom_Payment_Card_ExpDate_Year' => $this->card->year,
'cv2' => $this->card->cvv,
//'firmaadi' => $this->order->name,
//'Email' => $this->order->email,
'amount' => $this->order->amount,
'oid' => $this->order->id,
'okUrl' => $this->order->success_url,
'failUrl' => $this->order->fail_url,
'callbackUrl' => null,
'rnd' => $this->order->rand,
'lang' => $this->order->lang,
'currency' => $this->order->currency,
'TranType' => 'Auth',
'Instalment' => $this->order->installment,
];
$inputs['HASH'] = $this->create3DHash($inputs);
$data = [
'gateway' => $this->gateway,
'success_url' => $this->order->success_url,
'fail_url' => $this->order->fail_url,
'rand' => $this->order->rand,
//'hash' => $this->order->hash,
'inputs' => $inputs,
];
}
return $data;
}
/**
* Send contents to WebService
*
* @param $contents
* @return $this
* @throws GuzzleException
*/
public function send($contents)
{
$client = new Client();
$response = $client->request('POST', $this->url, [
'body' => $contents
]);
$this->data = $this->XMLStringToObject($response->getBody()->getContents());
return $this;
}
/**
* Prepare Order
*
* @param object $order
* @param object null $card
* @return mixed
* @throws UnsupportedTransactionTypeException
*/
public function prepare($order, $card = null)
{
$this->type = $this->types['pay'];
if (isset($order->transaction)) {
if (array_key_exists($order->transaction, $this->types)) {
$this->type = $this->types[$order->transaction];
} else {
throw new UnsupportedTransactionTypeException('Unsupported transaction type!');
}
}
$this->order = $order;
$this->card = $card;
}
/**
* Make Payment
*
* @param object $card
* @return mixed
* @throws UnsupportedPaymentModelException
* @throws GuzzleException
*/
public function payment($card)
{
$this->card = $card;
$model = 'regular';
if (isset($this->account->model) && $this->account->model) {
$model = $this->account->model;
}
if ($model == 'regular') {
$this->makeRegularPayment();
} elseif ($model == '3d') {
$this->make3DPayment();
} elseif ($model == '3d_pay') {
$this->make3DPayPayment();
} else {
throw new UnsupportedPaymentModelException();
}
return $this;
}
/**
* Refund Order
*
* @param array $meta
* @return $this
* @throws GuzzleException
*/
public function refund(array $meta)
{
$nodes = [
'CC5Request' => [
'Name' => $this->account->username,
'Password' => $this->account->password,
'ClientId' => $this->account->client_id,
'OrderId' => $meta['order_id'],
'Type' => 'Credit',
]
];
if ($meta['amount']) $nodes['Total'] = $meta['amount'];
$xml = $this->createXML($nodes, 'ISO-8859-9');
$this->send($xml);
$status = 'declined';
if ($this->getProcReturnCode() == '00') {
$status = 'approved';
}
$this->response = (object)[
'order_id' => isset($this->data->OrderId) ? $this->data->OrderId : null,
'group_id' => isset($this->data->GroupId) ? $this->data->GroupId : null,
'response' => isset($this->data->Response) ? $this->data->Response : null,
'auth_code' => isset($this->data->AuthCode) ? $this->data->AuthCode : null,
'host_ref_num' => isset($this->data->HostRefNum) ? $this->data->HostRefNum : null,
'proc_return_code' => isset($this->data->ProcReturnCode) ? $this->data->ProcReturnCode : null,
'trans_id' => isset($this->data->TransId) ? $this->data->TransId : null,
'error_code' => isset($this->data->Extra->ERRORCODE) ? $this->data->Extra->ERRORCODE : null,
'error_message' => isset($this->data->ErrMsg) ? $this->data->ErrMsg : null,
'status' => $status,
'status_detail' => $this->getStatusDetail(),
'all' => $this->data,
];
return $this;
}
/**
* Cancel Order
*
* @param array $meta
* @return $this
* @throws GuzzleException
*/
public function cancel(array $meta)
{
$xml = $this->createXML([
'CC5Request' => [
'Name' => $this->account->username,
'Password' => $this->account->password,
'ClientId' => $this->account->client_id,
'OrderId' => $meta['order_id'],
'Type' => 'Void',
]
], 'ISO-8859-9');
$this->send($xml);
$status = 'declined';
if ($this->getProcReturnCode() == '00') {
$status = 'approved';
}
$this->response = (object)[
'order_id' => isset($this->data->OrderId) ? $this->data->OrderId : null,
'group_id' => isset($this->data->GroupId) ? $this->data->GroupId : null,
'response' => isset($this->data->Response) ? $this->data->Response : null,
'auth_code' => isset($this->data->AuthCode) ? $this->data->AuthCode : null,
'host_ref_num' => isset($this->data->HostRefNum) ? $this->data->HostRefNum : null,
'proc_return_code' => isset($this->data->ProcReturnCode) ? $this->data->ProcReturnCode : null,
'trans_id' => isset($this->data->TransId) ? $this->data->TransId : null,
'error_code' => isset($this->data->Extra->ERRORCODE) ? $this->data->Extra->ERRORCODE : null,
'error_message' => isset($this->data->ErrMsg) ? $this->data->ErrMsg : null,
'status' => $status,
'status_detail' => $this->getStatusDetail(),
'all' => $this->data,
];
return $this;
}
/**
* Order Status
*
* @param array $meta
* @return $this
* @throws GuzzleException
*/
public function status(array $meta)
{
$xml = $this->createXML([
'CC5Request' => [
'Name' => $this->account->username,
'Password' => $this->account->password,
'ClientId' => $this->account->client_id,
'OrderId' => $meta['order_id'],
'Extra' => [
'ORDERSTATUS' => 'QUERY',
],
]
], 'ISO-8859-9');
$this->send($xml);
$status = 'declined';
if ($this->getProcReturnCode() == '00') {
$status = 'approved';
}
$first_amount = isset($this->data->Extra->ORIG_TRANS_AMT) ? $this->printData($this->data->Extra->ORIG_TRANS_AMT) : null;
$capture_amount = isset($this->data->Extra->CAPTURE_AMT) ? $this->printData($this->data->Extra->CAPTURE_AMT) : null;
$capture = $first_amount == $capture_amount ? true : false;
$this->response = (object)[
'order_id' => isset($this->data->OrderId) ? $this->printData($this->data->OrderId) : null,
'response' => isset($this->data->Response) ? $this->printData($this->data->Response) : null,
'proc_return_code' => isset($this->data->ProcReturnCode) ? $this->printData($this->data->ProcReturnCode) : null,
'trans_id' => isset($this->data->TransId) ? $this->printData($this->data->TransId) : null,
'error_message' => isset($this->data->ErrMsg) ? $this->printData($this->data->ErrMsg) : null,
'host_ref_num' => isset($this->data->Extra->HOST_REF_NUM) ? $this->printData($this->data->Extra->HOST_REF_NUM) : null,
'order_status' => isset($this->data->Extra->ORDERSTATUS) ? $this->printData($this->data->Extra->ORDERSTATUS) : null,
'process_type' => isset($this->data->Extra->CHARGE_TYPE_CD) ? $this->printData($this->data->Extra->CHARGE_TYPE_CD) : null,
'pan' => isset($this->data->Extra->PAN) ? $this->printData($this->data->Extra->PAN) : null,
'num_code' => isset($this->data->Extra->NUMCODE) ? $this->printData($this->data->Extra->NUMCODE) : null,
'first_amount' => $first_amount,
'capture_amount' => $capture_amount,
'status' => $status,
'status_detail' => $this->getStatusDetail(),
'capture' => $capture,
'all' => $this->data,
'xml' => $xml,
];
return $this;
}
/**
* Order History
*
* @param array $meta
* @return $this
* @throws GuzzleException
*/
public function history(array $meta)
{
$xml = $this->createXML([
'CC5Request' => [
'Name' => $this->account->username,
'Password' => $this->account->password,
'ClientId' => $this->account->client_id,
'OrderId' => $meta['order_id'],
'Extra' => [
'ORDERHISTORY' => 'QUERY',
],
]
], 'ISO-8859-9');
$this->send($xml);
$status = 'declined';
if ($this->getProcReturnCode() == '00') {
$status = 'approved';
}
$this->response = (object)[
'order_id' => isset($this->data->OrderId) ? $this->printData($this->data->OrderId) : null,
'response' => isset($this->data->Response) ? $this->printData($this->data->Response) : null,
'proc_return_code' => isset($this->data->ProcReturnCode) ? $this->printData($this->data->ProcReturnCode) : null,
'error_message' => isset($this->data->ErrMsg) ? $this->printData($this->data->ErrMsg) : null,
'num_code' => isset($this->data->Extra->NUMCODE) ? $this->printData($this->data->Extra->NUMCODE) : null,
'trans_count' => isset($this->data->Extra->TRXCOUNT) ? $this->printData($this->data->Extra->TRXCOUNT) : null,
'status' => $status,
'status_detail' => $this->getStatusDetail(),
'all' => $this->data,
'xml' => $xml,
];
return $this;
}
/**
* @return array
*/
public function getConfig()
{
return $this->config;
}
/**
* @return mixed
*/
public function getAccount()
{
return $this->account;
}
/**
* @return array
*/
public function getCurrencies()
{
return $this->currencies;
}
/**
* @return mixed
*/
public function getOrder()
{
return $this->order;
}
/**
* @return mixed
*/
public function getCard()
{
return $this->card;
}
/**
* @return string|null
*/
public function getCardCode()
{
$card_type = null;
if (isset($this->card->type)) {
if ($this->card->type == 'visa') {
$card_type = '1';
} elseif ($this->card->type == 'master') {
$card_type = '2';
} elseif ($this->card->type == '1' || $this->card->type == '2') {
$card_type = $this->card->type;
}
}
return $card_type;
}
}

Some files were not shown because too many files have changed in this diff Show More