Compare commits

...

46 commits

Author SHA1 Message Date
Korina Cordero
f89ddd73bf Fix issues found during testing of dispatch. #591 2021-07-21 10:12:27 +00:00
Korina Cordero
a28b7ec6d0 Modify setting of JO object. #591 2021-07-21 09:47:03 +00:00
Korina Cordero
5cfbb112a4 Refactor editing of job order. #591 2021-07-21 07:13:06 +00:00
Korina Cordero
64bf68e445 Fix bugs during testing customer tag removal. #591 2021-07-21 06:36:47 +00:00
Korina Cordero
e33b9eb719 Move customer tag removal to service. #591 2021-07-21 04:13:04 +00:00
Korina Cordero
19ec112bd2 Move JO event creation to job order service. #591 2021-07-19 10:08:38 +00:00
Korina Cordero
b0c04984ab Remove CMB code. #591 2021-07-15 08:54:26 +00:00
Korina Cordero
f067a6ddad Fix activateWarranty. #591 2021-07-15 07:59:32 +00:00
Korina Cordero
e162de9021 Add data to responses. #591 2021-07-15 07:13:38 +00:00
Korina Cordero
8c53b9ba75 Add data fields to responses where necessary. #591 2021-07-14 10:27:14 +00:00
Korina Cordero
deaad1dbc1 Add data fields to responses where necessary. #591 2021-07-14 09:41:11 +00:00
Korina Cordero
b040fe95a4 Modify WarrantyController. #591 2021-07-14 07:20:49 +00:00
Korina Cordero
2cdc51e878 Modify WarrantyController. #591 2021-07-13 09:15:06 +00:00
Korina Cordero
003b5f2aa1 Modify ScheduleOptionStatus. #591 2021-07-12 10:28:06 +00:00
Korina Cordero
d51e052a72 Modify getNearestHubAndSlots. #591 2021-07-12 10:22:06 +00:00
Korina Cordero
bfbd4d4045 Modify location support. #591 2021-07-12 09:44:46 +00:00
Korina Cordero
baaa832794 Modify getJOHIstory in JobOrderController . #591 2021-07-12 09:26:28 +00:00
Korina Cordero
3ebf6b6c96 Modify JobOrderController. Separate sending of MQTT events from creation of JO events. #591 2021-07-12 08:47:48 +00:00
Korina Cordero
f45f7fd411 Modify getEstimate. #591 2021-07-12 07:08:59 +00:00
Korina Cordero
518d5bb9d5 Break down newRequestJobOrder into smaller functions. #591 2021-07-12 06:26:25 +00:00
Korina Cordero
782a0493fc Break down requestJobOrder into smaller functions. #591 2021-07-12 04:25:14 +00:00
Korina Cordero
bfc2ee0890 Modify JobOrderController. #591 2021-07-09 11:00:57 +00:00
Korina Cordero
fb63fd80ac Modify RiderController. Fix calls to MobileAPIHandler. #591 2021-07-09 07:33:23 +00:00
Korina Cordero
8408c1e96a Modify PartnerController. #591 2021-07-09 03:07:41 +00:00
Korina Cordero
41f2002701 Modify PartnerController. #591 2021-07-06 09:26:13 +00:00
Korina Cordero
dbcf226682 Modify ServiceController. #591 2021-07-06 05:53:56 +00:00
Korina Cordero
cfbda4efe0 Modify BatteryController. #591 2021-07-06 05:43:13 +00:00
Korina Cordero
2ce5f05885 Modify PromoController. #591 2021-07-05 10:01:54 +00:00
Korina Cordero
cd48858b9d Modify CustomerVehicleController. #591 2021-07-05 09:52:26 +00:00
Korina Cordero
89a0acf380 Add service for mobile API common functions. Modify VehicleController. #591 2021-07-05 07:50:43 +00:00
Korina Cordero
6d42f1dcc5 Fix CustomerController for CAPI. #591 2021-07-01 10:29:45 +00:00
Korina Cordero
f998187e8e Modify confirmNumber and validateCode. #591 2021-07-01 09:28:25 +00:00
Korina Cordero
edaa514f57 Add index for capi user ID. Add checking if user already registered. #591 2021-07-01 08:26:36 +00:00
Korina Cordero
8fd9aed174 Merge branch 'master-fix' of gitlab.com:jankstudio/resq into 591-migrate-apicontroller 2021-07-01 07:32:35 +00:00
Korina Cordero
88c49582e2 Fix error response for register. #591 2021-06-30 08:27:07 +00:00
Korina Cordero
46907d41ae Merge branch 'master-fix' of gitlab.com:jankstudio/resq into 591-migrate-apicontroller 2021-06-29 07:21:18 +00:00
Korina Cordero
35b228ef0c Fix register for migration. #591 2021-06-28 04:49:00 +00:00
Korina Cordero
1d4a52bbf2 Add JobOrderController for JO mobile requests. #591 2021-06-25 08:24:03 +00:00
Korina Cordero
36ee7010d9 Merge branch 'master-fix' of gitlab.com:jankstudio/resq into 591-migrate-apicontroller 2021-06-25 06:05:06 +00:00
Korina Cordero
f0b562b0cb Add warranty controller. #591 2021-06-24 09:35:51 +00:00
Korina Cordero
fead12bcab Add controllers for battery, partner, promo, rider, and service. #591 2021-06-24 08:45:09 +00:00
Korina Cordero
ece60b177d Add controllers for vehicle and customer vehicle. #591 2021-06-24 07:47:56 +00:00
Korina Cordero
6c65faa517 Merge branch 'master-fix' of gitlab.com:jankstudio/resq into 591-migrate-apicontroller 2021-06-24 07:47:01 +00:00
Korina Cordero
69c221f78c Add controller for customer-related requests for mobile API. #591 2021-06-23 09:30:28 +00:00
Korina Cordero
2125f36e77 Add MobileUser entity. Add association between MobileUser and Customer. #591 2021-06-23 08:24:49 +00:00
Korina Cordero
642803217d Add new route file for resqapi. #591 2021-06-23 07:07:41 +00:00
28 changed files with 4603 additions and 1193 deletions

View file

@ -258,14 +258,6 @@ access_keys:
label: Edit
- id: joborder.cancel
label: Cancel
- id: jo_onestep.form
label: One-step Process
- id: jo_onestep.edit
label: One-step Process Edit
- id: jo_walkin.form
label: Walk-in
- id: jo_walkin.edit
label: Walk-in Edit
- id: jo_autoassign.test
label: Autoassign Test
- id: jo_hub.list

View file

@ -67,3 +67,107 @@ access_keys:
acls:
- id: dealer.list
label: List
- id: mobile_user
label: Mobile User Access
acls:
- id: mobile_user.register
label: Register Mobile User
- id: mobile_user.confirm.number
label: Confirm Number
- id: mobile_user.validate.code
label: Validate Code
- id: mobile_user.get.info
label: Get Customer Info
- id: mobile_user.update.info
label: Update Customer Info
- id: mobile_user.get.status
label: Get Status
- id: mobile_user.resend.code
label: Resend Code
- id: mobile_user.version.check
label: Version Check
- id: mobile_user.update.deviceid
label: Update Device ID
- id: mobile_user.privacy.settings
label: Privacy Settings
- id: mobile_vmanufacturer
label: Mobile Vehicle Manufacturer Access
acls:
- id: mobile_vmanufacturer.list
label: List Vehicle Manufacturers
- id: mobile_vehicle
label: Mobile Vehicle Make Access
acls:
- id: mobile_vehicle.list
label: List Vehicle Makes
- id: mobile_customer_vehicle
label: Mobile Customer Vehicle Access
acls:
- id: mobile_customer_vehicle.add
label: Add Mobile Customer Vehicle
- id: mobile_customer_vehicle.update
label: Update Mobile Customer Vehicle
- id: mobile_customer_vehicle.list
label: List Mobile Customer Vehicles
- id: mobile_promo
label: Mobile Promo Access
acls:
- id: mobile_promo.list
label: List Promos
- id: mobile_battery
label: Mobile Battery Access
acls:
- id: mobile_battery.list
label: List Compatible Batteries
- id: mobile_service
label: Mobile Service Access
acls:
- id: mobile_service.list
label: List Services
- id: mobile_partner
label: Mobile Partner Access
acls:
- id: mobile_partner.list
label: List Mobile Partners
- id: mobile_partner.info
label: Get Partner Info
- id: mobile_partner.review
label: Add Partner Review
- id: mobile_rider
label: Mobile Rider Access
acls:
- id: mobile_rider.status.get
label: Get Rider Status
- id: mobile_rider.rating.add
label: Add Rider Rating
- id: job_order
label: Mobile Job Order Access
acls:
- id: mobile_jo.request
label: Request Job Order
- id: mobile_jo.get.estimate
label: Get Estimate
- id: mobile_jo.get.ongoing
label: Get Ongoing Job Order
- id: mobile_jo.cancel
label: Cancel Job Order
- id: mobile_jo.get.history
label: Get Job Order History
- id: mobile_jo.get.invoice
label: Get Job Order Invoice
- id: mobile_jo.location.support
label: Check Location Support
- id: mobile_jo.nearest_hub.get
label: Get Nearest Hub and Slots
- id: mobile_jo.schedule_option.status
label: Schedule Option Status
- id: mobile_warranty
label: Mobile Warranty Access
acls:
- id: mobile_warranty.register.serial
label: Register Warranty Serial
- id: mobile_warranty.check
label: Check Warranty Serial
- id: mobile_warranty.activate
label: Activate Warranty

View file

@ -1,179 +0,0 @@
main_menu:
- id: home
acl: dashboard.menu
label: Dashboard
icon: flaticon-line-graph
- id: user
acl: user.menu
label: User
icon: flaticon-users
- id: user_list
acl: user.list
label: Users
parent: user
- id: role_list
acl: role.list
label: Roles
parent: user
- id: apiuser
acl: apiuser.menu
label: API User
icon: flaticon-users
- id: api_user_list
acl: apiuser.list
label: API Users
parent: apiuser
- id: api_role_list
acl: apirole.list
label: API Roles
parent: apiuser
- id: logistics
acl: logistics.menu
label: Logistics
icon: fa fa-truck
- id: rider_list
acl: rider.list
label: Riders
parent: logistics
- id: service_charge_list
acl: service_charge.list
label: Service Charges
parent: logistics
- id: battery
acl: battery.menu
label: Battery
icon: fa fa-battery-3
- id: battery_list
acl: battery.list
label: Batteries
parent: battery
- id: bmfg_list
acl: bmfg.list
label: Manufacturers
parent: battery
- id: bmodel_list
acl: bmodel.list
label: Models
parent: battery
- id: bsize_list
acl: bsize.list
label: Sizes
parent: battery
- id: promo_list
acl: promo.list
label: Promos
parent: battery
- id: vehicle
acl: vehicle.menu
label: Vehicle
icon: fa fa-car
- id: vehicle_list
acl: vehicle.list
label: Vehicles
parent: vehicle
- id: vmfg_list
acl: vmfg.list
label: Manufacturers
parent: vehicle
- id: location
acl: location.menu
label: Location
icon: fa fa-home
- id: outlet_list
acl: outlet.menu
label: Outlet
parent: location
- id: hub_list
acl: hub.menu
label: Hub
parent: location
- id: geofence_list
acl: geofence.menu
label: Geofence
parent: location
- id: joborder
acl: joborder.menu
label: Job Order
icon: flaticon-calendar-3
- id: jo_onestep_form
acl: jo_onestep.form
label: One-step Process
parent: joborder
- id: jo_walkin_form
acl: jo_walkin.form
label: Walk-in
parent: joborder
- id: jo_open
acl: jo_open.list
label: Open
parent: joborder
- id: jo_all
acl: jo_all.list
label: View All
parent: joborder
- id: support
acl: support.menu
label: Customer Support
icon: flaticon-support
- id: customer_list
acl: customer.list
label: Customers
parent: support
- id: ticket_list
acl: ticket.list
label: Tickets
parent: support
- id: general_search
acl: general.search
label: Search
parent: support
- id: warranty_search
acl: warranty.search
label: Customer Battery Search
parent: support
- id: privacy_policy_list
acl: privacy_policy.list
label: Privacy Policy
parent: support
- id: warranty_list
acl: warranty.list
label: Warranty
parent: support
- id: warranty_upload
acl: warranty.upload
label: Warranty Upload
parent: support
- id: static_content_list
acl: static_content.list
label: Static Content
parent: support
- id: service
acl: service.menu
label: Other Services
icon: flaticon-squares
- id: service_list
acl: service.list
label: Services
parent: service
- id: partner
acl: partner.menu
label: Partners
icon: flaticon-network
- id: partner_list
acl: partner.list
label: Partners
parent: partner
- id: review_list
acl: review.list
label: Reviews
parent: partner

View file

@ -1,235 +0,0 @@
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
map_default:
latitude: 14.6091
longitude: 121.0223
image_upload_directory: '%kernel.project_dir%/public/uploads'
job_order_refresh_interval: 300000
api_acl_file: 'api_acl.yaml'
api_access_key: 'api_access_keys'
app_acl_file: 'acl.yaml'
app_access_key: 'access_keys'
cvu_brand_id: "%env(CVU_BRAND_ID)%"
country_code: "%env(COUNTRY_CODE)%"
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
public: false # Allows optimizing the container by removing unused services; this also means
# fetching services directly from the container via $container->get() won't work.
# The best practice is to be explicit about your dependencies anyway.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{Entity,Migrations,Tests,Menu,Access}'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
resource: '../src/Controller'
tags: ['controller.service_arguments']
# add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones
App\Menu\Generator:
arguments:
$router: "@router.default"
$cache_dir: "%kernel.cache_dir%"
$config_dir: "%kernel.root_dir%/../config"
Catalyst\AuthBundle\Service\ACLGenerator:
arguments:
$router: "@router.default"
$cache_dir: "%kernel.cache_dir%"
$config_dir: "%kernel.root_dir%/../config"
$acl_file: "%app_acl_file%"
Catalyst\AuthBundle\Service\ACLVoter:
arguments:
$user_class: "App\\Entity\\User"
tags: ['security.voter']
Catalyst\AuthBundle\Service\UserChecker:
App\Service\FileUploader:
arguments:
$target_dir: '%image_upload_directory%'
App\Service\MapTools:
arguments:
$em: "@doctrine.orm.entity_manager"
$gmaps_api_key: "%env(GMAPS_API_KEY)%"
$cust_dist_limit: "%env(CUST_DISTANCE_LIMIT)%"
App\Service\RisingTideGateway:
arguments:
$em: "@doctrine.orm.entity_manager"
$user: "%env(RT_USER)%"
$pass: "%env(RT_PASS)%"
$usage_type: "%env(RT_USAGE_TYPE)%"
$shortcode: "%env(RT_SHORTCODE)%"
App\Service\MQTTClient:
arguments:
$redis_client: "@App\\Service\\RedisClientProvider"
$key: "mqtt_events"
App\Service\APNSClient:
arguments:
$redis_client: "@App\\Service\\RedisClientProvider"
App\Service\RedisClientProvider:
arguments:
$scheme: "%env(REDIS_CLIENT_SCHEME)%"
$host: "%env(REDIS_CLIENT_HOST)%"
$port: "%env(REDIS_CLIENT_PORT)%"
$password: "%env(REDIS_CLIENT_PASSWORD)%"
App\Service\GeofenceTracker:
arguments:
$geofence_flag: "%env(GEOFENCE_ENABLE)%"
App\Service\WarrantyHandler:
arguments:
$em: "@doctrine.orm.entity_manager"
App\Command\SetCustomerPrivacyPolicyCommand:
arguments:
$policy_promo: "%env(POLICY_PROMO)%"
$policy_third_party: "%env(POLICY_THIRD_PARTY)%"
$policy_mobile: "%env(POLICY_MOBILE)%"
App\Command\CreateCustomerFromWarrantyCommand:
arguments:
$cvu_mfg_id: "%env(CVU_MFG_ID)%"
$cvu_brand_id: "%env(CVU_BRAND_ID)%"
# rider tracker service
App\Service\RiderTracker:
arguments:
$redis_client: "@App\\Service\\RedisClientProvider"
Catalyst\APIBundle\Security\APIKeyUserProvider:
arguments:
$em: "@doctrine.orm.entity_manager"
Catalyst\APIBundle\Security\APIKeyAuthenticator:
arguments:
$em: "@doctrine.orm.entity_manager"
Catalyst\APIBundle\Command\UserCreateCommand:
arguments:
$em: "@doctrine.orm.entity_manager"
tags: ['console.command']
Catalyst\APIBundle\Command\TestCommand:
tags: ['console.command']
Catalyst\APIBundle\Command\TestAPICommand:
tags: ['console.command']
Catalyst\APIBundle\Access\Voter:
arguments:
$acl_gen: "@Catalyst\\APIBundle\\Access\\Generator"
$user_class: "Catalyst\\APIBundle\\Entity\\User"
tags: ['security.voter']
Catalyst\APIBundle\Access\Generator:
arguments:
$router: "@router.default"
$cache_dir: "%kernel.cache_dir%"
$config_dir: "%kernel.root_dir%/../config"
$acl_file: "%api_acl_file%"
Catalyst\MenuBundle\Menu\Generator:
arguments:
$router: "@router.default"
$cache_dir: "%kernel.cache_dir%"
$config_dir: "%kernel.root_dir%/../config"
Catalyst\MenuBundle\Listener\MenuAnnotationListener:
arguments:
$menu_name: "main_menu"
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
# invoice generator
App\Service\InvoiceGenerator\CMBInvoiceGenerator: ~
# invoice generator interface
App\Service\InvoiceGeneratorInterface: "@App\\Service\\InvoiceGenerator\\CMBInvoiceGenerator"
# job order generator
App\Service\JobOrderHandler\CMBJobOrderHandler:
arguments:
$country_code: "%env(COUNTRY_CODE)%"
#job order generator interface
App\Service\JobOrderHandlerInterface: "@App\\Service\\JobOrderHandler\\CMBJobOrderHandler"
# customer generator
App\Service\CustomerHandler\CMBCustomerHandler:
arguments:
$country_code: "%env(COUNTRY_CODE)%"
# customer generator interface
App\Service\CustomerHandlerInterface: "@App\\Service\\CustomerHandler\\CMBCustomerHandler"
# rider assignment
App\Service\RiderAssignmentHandler\CMBRiderAssignmentHandler: ~
# rider assignment interface
App\Service\RiderAssignmentHandlerInterface: "@App\\Service\\RiderAssignmentHandler\\CMBRiderAssignmentHandler"
# rider API service
App\Service\RiderAPIHandler\CMBRiderAPIHandler:
arguments:
$country_code: "%env(COUNTRY_CODE)%"
# rider API interface
App\Service\RiderAPIHandlerInterface: "@App\\Service\\RiderAPIHandler\\CMBRiderAPIHandler"
# map manager
#App\Service\GISManager\Bing: ~
App\Service\GISManager\OpenStreet: ~
#App\Service\GISManager\Google: ~
#App\Service\GISManagerInterface: "@App\\Service\\GISManager\\Bing"
App\Service\GISManagerInterface: "@App\\Service\\GISManager\\OpenStreet"
#App\Service\GISManagerInterface: "@App\\Service\\GISManager\\Google"
App\EventListener\JobOrderActiveCacheListener:
arguments:
$jo_cache: "@App\\Service\\JobOrderCache"
$mqtt: "@App\\Service\\MQTTClient"
tags:
- name: 'doctrine.orm.entity_listener'
event: 'postUpdate'
entity: 'App\Entity\JobOrder'
- name: 'doctrine.orm.entity_listener'
event: 'postRemove'
entity: 'App\Entity\JobOrder'
- name: 'doctrine.orm.entity_listener'
event: 'postPersist'
entity: 'App\Entity\JobOrder'
App\Service\JobOrderCache:
arguments:
$redis_prov: "@App\\Service\\RedisClientProvider"
$active_jo_key: "%env(LOCATION_JO_ACTIVE_KEY)%"
App\Service\RiderCache:
arguments:
$redis_prov: "@App\\Service\\RedisClientProvider"
$loc_key: "%env(LOCATION_RIDER_ACTIVE_KEY)%"
$status_key: "%env(STATUS_RIDER_KEY)%"
# API logging
App\EventSubscriber\LogSubscriber:
arguments:
$api_log_flag: "%env(API_LOGGING)%"

View file

@ -46,6 +46,14 @@ security:
provider: api_key_user_provider
user_checker: Catalyst\AuthBundle\Service\UserChecker
mobile_api:
pattern: ^\/resqapi\/
stateless: true
simple_preauth:
authenticator: Catalyst\APIBundle\Security\APIKeyAuthenticator
provider: api_key_user_provider
user_checker: Catalyst\AuthBundle\Service\UserChecker
main:
provider: user_provider
form_login:

View file

@ -176,26 +176,6 @@ jo_reject_hub:
controller: App\Controller\JobOrderController::rejectHubSubmit
methods: [POST]
jo_onestep_form:
path: /job-order/onestep
controller: App\Controller\JobOrderController::oneStepForm
methods: [GET]
jo_onestep_submit:
path: /job-order/onestep
controller: App\Controller\JobOrderController::oneStepSubmit
methods: [POST]
jo_onestep_edit_form:
path: /job-order/onestep/{id}/edit
controller: App\Controller\JobOrderController::oneStepEditForm
methods: [GET]
jo_onestep_edit_submit:
path: /job-order/onestep/{id}/edit
controller: App\Controller\JobOrderController::oneStepEditSubmit
methods: [POST]
jo_ajax_popup:
path: /job-order/{id}/popup
controller: App\Controller\JobOrderController::popupInfo
@ -206,26 +186,6 @@ jo_tracker:
controller: App\Controller\JobOrderController::tracker
methods: [GET]
jo_walkin_form:
path: /job-order/walk-in
controller: App\Controller\JobOrderController::walkInForm
methods: [GET]
jo_walkin_submit:
path: /job-order/walk-in
controller: App\Controller\JobOrderController::walkInSubmit
methods: [POST]
jo_walkin_edit_form:
path: /job-order/walk-in/{id}
controller: App\Controller\JobOrderController::walkInEditForm
methods: [GET]
jo_walkin_edit_submit:
path: /job-order/walk-in/{id}
controller: App\Controller\JobOrderController::walkInEditSubmit
methods: [POST]
jo_autoassign:
path: /job-order/autoassign
controller: App\Controller\JobOrderController::autoAssignForm

193
config/routes/resqapi.yaml Normal file
View file

@ -0,0 +1,193 @@
# resqapi aka mobile api
# customer/registration-related endpoints
resqapi_register:
path: /resqapi/register
controller: App\Controller\ResqAPI\CustomerController::register
methods: [POST]
resqapi_confirm:
path: /resqapi/number_confirm
controller: App\Controller\ResqAPI\CustomerController::confirmNumber
methods: [POST]
resqapi_validate:
path: /resqapi/code_validate
controller: App\Controller\ResqAPI\CustomerController::validateCode
methods: [POST]
resqapi_info_get:
path: /resqapi/info
controller: App\Controller\ResqAPI\CustomerController::getInfo
methods: [GET]
resqapi_info_update:
path: /resqapi/info
controller: App\Controller\ResqAPI\CustomerController::updateInfo
methods: [POST]
resqapi_status:
path: /resqapi/status
controller: App\Controller\ResqAPI\CustomerController::getStatus
methods: [GET]
resqapi_resend_code:
path: /resqapi/resend_code
controller: App\Controller\ResqAPI\CustomerController:resendCode
methods: [POST]
resqapi_version_check:
path: /resqapi/version_check
controller: App\Controller\ResqAPI\CustomerController::versionCheck
methods: [POST]
resqapi_device_id:
path: /resqapi/device_id
controller: App\Controller\ResqAPI\CustomerController:updateDeviceID
methods: [POST]
resqapi_privacy:
path: /resqapi/privacy
controller: App\Controller\ResqAPI\CustomerController:privacySettings
methods: [POST]
# vehicle manufacturer and vehicle endpoints
resqapi_vehicle_mfg_list:
path: /resqapi/vehicle/mfgs
controller: App\Controller\ResqAPI\VehicleController::listVehicleManufacturers
methods: [GET]
resqapi_vehicle_make_list:
path: /resqapi/vehicle/mfgs/{mfg_id}/makes
controller: App\Controller\ResqAPI\VehicleController::listVehicleMakes
methods: [GET]
# customer vehicle endpoints
resqapi_cust_vehicle_add:
path: /resqapi/vehicles
controller: App\Controller\ResqAPI\CustomerVehicleController::addVehicle
methods: [POST]
resqapi_cust_vehicle_update:
path: /resqapi/vehicles/{id}
controller: App\Controller\ResqAPI\CustomerVehicleController::updateVehicle
methods: [POST]
resqapi_cust_vehicle_list:
path: /resqapi/vehicles
controller: App\Controller\ResqAPI\CustomerVehicleController::listVehicles
methods: [GET]
# promo endpoints
resqapi_promo_list:
path: /resqapi/promos
controller: App\Controller\ResqAPI\PromoController::listPromos
methods: [GET]
# battery endpoints
resqapi_battery_list:
path: /resqapi/vehicles/{vid}/compatible_batteries
controller: App\Controller\ResqAPI\BatteryController::getCompatibleBatteries
methods: [GET]
# service endpoints
resqapi_service_list:
path: /resqapi/services
controller: App\Controller\ResqAPI\ServiceController:listServices
methods: [GET]
# partner endpoints
resqapi_partner_info:
path: /resqapi/partners/{pid}
controller: App\Controller\ResqAPI\PartnerController:getPartnerInformation
methods: [GET]
resqapi_partner:
path: /resqapi/partners
controller: App\Controller\ResqAPI\PartnerController:getClosestPartners
methods: [POST]
resqapi_partner_review:
path: /resqapi/partners/{pid}/review
controller: App\Controller\ResqAPI\PartnerController:reviewPartner
methods: [POST]
# rider endpoints
resq_rider_status:
path: /resqapi/rider
controller: App\Controller\ResqAPI\RiderController::getRiderStatus
methods: [GET]
resqapi_rider_rating_add:
path: /resqapi/rider_rating
controller: App\Controller\ResqAPI\RiderController::addRiderRating
methods: [POST]
# job order endpoints
resqapi_jo_request:
path: /resqapi/job_order
controller: App\Controller\ResqAPI\JobOrderController::requestJobOrder
methods: [POST]
resqapi_estimate:
path: /resqapi/estimate
controller: App\Controller\ResqAPI\JobOrderController::getEstimate
methods: [POST]
resqapi_ongoing:
path: /resqapi/job_order/ongoing
controller: App\Controller\ResqAPI\JobOrderController::getOngoing
methods: [GET]
resqapi_jo_cancel:
path: /resqapi/job_order/cancel
controller: App\Controller\ResqAPI\JobOrderController:cancelJobOrder
methods: [POST]
resqapi_jo_history:
path: /resqapi/job_order/history
controller: App\Controller\ResqAPI\JobOrderController:getJOHistory
methods: [GET]
resqapi_jo_invoice:
path: /resqapi/job_order/invoice
controller: App\Controller\ResqAPI\JobOrderController:getJOInvoice
methods: [GET]
resqapi_location_support:
path: /resqapi/location_support
controller: App\Controller\ResqAPI\JobOrderController:locationSupport
methods: [POST]
resqapi_nearest_hub_slots:
path: /resqapi/hub_slots
controller: App\Controller\ResqAPI\JobOrderController::getNearestHubAndSlots
methods: [POST]
resqapi_new_jo_request:
path: /resqapi/new_job_order
controller: App\Controller\ResqAPI\JobOrderController::newRequestJobOrder
methods: [POST]
resqapi_schedule_option_status:
path: /resqapi/schedule_option_status
controller: App\Controller\ResqAPI\JobOrderController::scheduleOptionStatus
methods: [GET]
# warranty endpoints
resqapi_activate_warranty:
path: /resqapi/activate_warranty
controller: App\Controller\ResqAPI\WarrantyController:activateWarranty
methods: [POST]
# paperless warranty / qr code
resqapi_warr_serial_check:
path: /resqapi/warranty/{serial}
controller: App\Controller\ResqAPI\WarrantyController::warrantyCheck
methods: [GET]
resqapi_warr_serial_register:
path: /resqapi/warranty/{serial}
controller: App\Controller\ResqAPI\WarrantyController::warrantyRegister
methods: [POST]

View file

@ -299,3 +299,15 @@ services:
App\Service\HubFilteringGeoChecker:
arguments:
$geofence_flag: "%env(HUB_GEOFENCE_ENABLE)%"
# mobile api handler
App\Service\MobileAPIHandler:
arguments:
$em: "@doctrine.orm.entity_manager"
# job order service
App\Service\JobOrderManager:
arguments:
$em: "@doctrine.orm.entity_manager"
$rah: "@App\\Service\\RiderAssignmentHandlerInterface"

View file

@ -182,9 +182,7 @@ class CustomerController extends Controller
public function getCustomerVehicles(Request $req, CustomerHandlerInterface $cust_handler)
{
if (!(($this->isGranted('jo_onestep.form')) ||
($this->isGranted('jo_walkin.form')) ||
($this->isGranted('jo_in.list'))))
if (!($this->isGranted('jo_in.list')))
{
$exception = $this->createAccessDeniedException('No access.');
throw $exception;

View file

@ -4,7 +4,6 @@ namespace App\Controller;
use App\Ramcar\JOStatus;
use App\Ramcar\InvoiceCriteria;
use App\Ramcar\CMBServiceType;
use App\Ramcar\ServiceType;
use App\Ramcar\JOCancelReasons;
@ -291,13 +290,11 @@ class JobOrderController extends Controller
$rows[$key]['meta']['reassign_rider_url'] = $this->generateUrl('jo_open_rider_form', ['id' => $jo_id]);
// $rows[$key]['meta']['edit_url'] = $this->generateUrl('jo_open_edit_form', ['id' => $jo_id]);
$rows[$key]['meta']['edit_url'] = $this->generateUrl($jo_handler->getEditRoute($jo_id, $tier_params['edit_route']), ['id' => $jo_id]);
$rows[$key]['meta']['onestep_edit_url'] = $this->generateUrl('jo_onestep_edit_form', ['id' => $jo_id]);
}
else
{
// $rows[$key]['meta']['update_url'] = $this->generateUrl($tier_params['edit_route'], ['id' => $jo_id]);
$rows[$key]['meta']['update_url'] = $this->generateUrl($jo_handler->getEditRoute($jo_id, $tier_params['edit_route']), ['id' => $jo_id]);
$rows[$key]['meta']['onestep_edit_url'] = $this->generateUrl('jo_onestep_edit_form', ['id' => $jo_id]);
$rows[$key]['meta']['pdf_url'] = $this->generateUrl('jo_pdf_form', ['id' => $jo_id]);
}
@ -853,95 +850,6 @@ class JobOrderController extends Controller
]);
}
/**
* @Menu(selected="jo_onestep_form")
*/
public function oneStepForm(EntityManagerInterface $em, JobOrderHandlerInterface $jo_handler, GISManagerInterface $gis)
{
$this->denyAccessUnlessGranted('jo_onestep.form', null, 'No access.');
$params = $jo_handler->initializeOneStepForm();
$params['submit_url'] = $this->generateUrl('jo_onestep_submit');
$params['return_url'] = $this->generateUrl('jo_onestep_form');
$params['map_js_file'] = $gis->getJSJOFile();
$params['vmfgs'] = $em->getRepository(VehicleManufacturer::class)->findAll();
$params['vmakes'] = $em->getRepository(Vehicle::class)->findAll();
$template = $params['template'];
// response
return $this->render($template, $params);
}
public function oneStepSubmit(Request $req, JobOrderHandlerInterface $jo_handler)
{
$this->denyAccessUnlessGranted('jo_onestep.form', null, 'No access.');
// initialize error list
$error_array = [];
$id = -1;
$error_array = $jo_handler->processOneStepJobOrder($req, $id);
// check if any errors were found
if (!empty($error_array)) {
// return validation failure response
return $this->json([
'success' => false,
'errors' => $error_array
], 422);
}
// return successful response
return $this->json([
'success' => 'Changes have been saved!'
]);
}
/**
* @Menu(selected="jo_onestep_edit_form")
*/
public function oneStepEditForm($id, EntityManagerInterface $em, JobOrderHandlerInterface $jo_handler,
GISManagerInterface $gis, MapTools $map_tools)
{
$this->denyAccessUnlessGranted('jo_onestep.edit', null, 'No access.');
$params = $jo_handler->initializeOneStepEditForm($id, $map_tools);
$params['submit_url'] = $this->generateUrl('jo_onestep_edit_submit', ['id' => $id]);
$params['return_url'] = $this->generateUrl('jo_open');
$params['map_js_file'] = $gis->getJSJOFile();
$params['vmfgs'] = $em->getRepository(VehicleManufacturer::class)->findAll();
$params['vmakes'] = $em->getRepository(Vehicle::class)->findAll();
$template = $params['template'];
// response
return $this->render($template, $params);
}
public function oneStepEditSubmit(Request $req, JobOrderHandlerInterface $jo_handler, $id)
{
$this->denyAccessUnlessGranted('jo_onestep.edit', null, 'No access.');
$error_array = [];
$error_array = $jo_handler->processOneStepJobOrder($req, $id);
// check if any errors were found
if (!empty($error_array)) {
// return validation failure response
return $this->json([
'success' => false,
'errors' => $error_array
], 422);
}
// return successful response
return $this->json([
'success' => 'Changes have been saved!'
]);
}
/**
* @ParamConverter("jo", class="App\Entity\JobOrder")
*/
@ -978,99 +886,12 @@ class JobOrderController extends Controller
$params['jo'] = $jo;
$params['rider'] = $rider;
$params['rider_pos'] = $rider_tracker->getRiderLocation($rider->getID());
$params['service_type'] = CMBServiceType::getName($jo->getServiceType());
$params['service_type'] = ServiceType::getName($jo->getServiceType());
$params['map_js_file'] = $gis_manager->getJSInitFile();
return $this->render('job-order/tracker.html.twig', $params);
}
/**
* @Menu(selected="jo_walkin_form")
*/
public function walkInForm(EntityManagerInterface $em, JobOrderHandlerInterface $jo_handler)
{
$this->denyAccessUnlessGranted('jo_walkin.form', null, 'No access.');
$params = $jo_handler->initializeWalkinForm();
$params['submit_url'] = $this->generateUrl('jo_walkin_submit');
$params['return_url'] = $this->generateUrl('jo_walkin_form');
$params['vmfgs'] = $em->getRepository(VehicleManufacturer::class)->findAll();
$params['vmakes'] = $em->getRepository(Vehicle::class)->findAll();
$params['hubs'] = $em->getRepository(Hub::class)->findAll();
$template = $params['template'];
// response
return $this->render($template, $params);
}
public function walkInSubmit(Request $req, JobOrderHandlerInterface $jo_handler)
{
$this->denyAccessUnlessGranted('jo_walkin.form', null, 'No access.');
// initialize error list
$error_array = [];
$id = -1;
$error_array = $jo_handler->processWalkinJobOrder($req, $id);
// check if any errors were found
if (!empty($error_array)) {
// return validation failure response
return $this->json([
'success' => false,
'errors' => $error_array
], 422);
}
// return successful response
return $this->json([
'success' => 'Changes have been saved!'
]);
}
/**
* @Menu(selected="jo_walkin_edit_form")
*/
public function walkInEditForm($id, EntityManagerInterface $em, JobOrderHandlerInterface $jo_handler)
{
$this->denyAccessUnlessGranted('jo_walkin.edit', null, 'No access.');
$params = $jo_handler->initializeWalkinEditForm($id);
$params['submit_url'] = $this->generateUrl('jo_walkin_edit_submit', ['id' => $id]);
$params['return_url'] = $this->generateUrl('jo_open');
$params['vmfgs'] = $em->getRepository(VehicleManufacturer::class)->findAll();
$params['vmakes'] = $em->getRepository(Vehicle::class)->findAll();
$params['hubs'] = $em->getRepository(Hub::class)->findAll();
$template = $params['template'];
// response
return $this->render($template, $params);
}
public function walkInEditSubmit(Request $req, JobOrderHandlerInterface $jo_handler, $id)
{
$this->denyAccessUnlessGranted('jo_walkin.edit', null, 'No access.');
$error_array = [];
$error_array = $jo_handler->processWalkinJobOrder($req, $id);
// check if any errors were found
if (!empty($error_array)) {
// return validation failure response
return $this->json([
'success' => false,
'errors' => $error_array
], 422);
}
// return successful response
return $this->json([
'success' => 'Changes have been saved!'
]);
}
/**
* @Menu(selected="jo_hub_view")
*/

View file

@ -0,0 +1,94 @@
<?php
namespace App\Controller\ResqAPI;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\ORM\Query;
use Doctrine\ORM\EntityManagerInterface;
use Catalyst\APIBundle\Controller\APIController;
use Catalyst\APIBundle\Response\APIResponse;
use App\Ramcar\APIResult;
use App\Entity\Vehicle;
use App\Service\MobileAPIHandler;
use Catalyst\APIBundle\Access\Generator as ACLGenerator;
class BatteryController extends APIController
{
protected $acl_gen;
public function __construct(ACLGenerator $acl_gen)
{
$this->acl_gen = $acl_gen;
}
public function getCompatibleBatteries(Request $req, $vid, EntityManagerInterface $em,
MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_battery.list', null, 'No access.');
// check required parameters
$required_params = [];
$msg = $this->checkRequiredParameters($req, $required_params);
if ($msg)
return new APIResponse(false, $msg);
// get capi user to link to mobile user
$user_id = $this->getUser()->getID();
// get mobile user
$mobile_user = $mah->findMobileUser($user_id);
if ($mobile_user == null)
return new APIResponse(false, 'No mobile user found.');
// get vehicle
$vehicle = $em->getRepository(Vehicle::class)->find($vid);
if ($vehicle == null)
return new APIResponse(false, 'Invalid vehicle');
// batteries
$batt_list = [];
$batts = $vehicle->getBatteries();
foreach ($batts as $batt)
{
// generate the url for image
$battery_image_url = $this->generateUrl('static_battery_image');
// TODO: Add warranty_tnv to battery information
$batt_list[] = [
'id' => $batt->getID(),
'mfg_id' => $batt->getManufacturer()->getID(),
'mfg_name' => $batt->getManufacturer()->getName(),
'model_id' => $batt->getModel()->getID(),
'model_name' => $batt->getModel()->getName(),
'size_id' => $batt->getSize()->getID(),
'size_name' => $batt->getSize()->getName(),
'price' => $batt->getSellingPrice(),
'wty_private' => $batt->getWarrantyPrivate(),
'wty_commercial' => $batt->getWarrantyCommercial(),
'image_url' => $mah->getBatteryImageURL($req, $batt, $battery_image_url),
];
}
// data
$data = [
'vehicle' => [
'id' => $vehicle->getID(),
'mfg_id' => $vehicle->getManufacturer()->getID(),
'mfg_name' => $vehicle->getManufacturer()->getName(),
'make' => $vehicle->getMake(),
'model_year_from' => $vehicle->getModelYearFrom(),
'model_year_to' => $vehicle->getModelYearTo(),
],
'batteries' => $batt_list,
];
return new APIResponse(true, 'Compatible batteries found', $data);
}
}

View file

@ -0,0 +1,615 @@
<?php
namespace App\Controller\ResqAPI;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Dotenv\Dotenv;
use Doctrine\ORM\Query;
use Doctrine\ORM\EntityManagerInterface;
use Catalyst\APIBundle\Controller\APIController;
use Catalyst\APIBundle\Response\APIResponse;
use App\Entity\MobileUser;
use App\Entity\Customer;
use App\Entity\PrivacyPolicy;
use App\Service\RisingTideGateway;
use App\Service\MobileAPIHandler;
use App\Ramcar\CustomerSource;
use Catalyst\APIBundle\Access\Generator as ACLGenerator;
use DateTime;
class CustomerController extends APIController
{
protected $acl_gen;
public function __construct(ACLGenerator $acl_gen)
{
$this->acl_gen = $acl_gen;
}
public function register(Request $req, EntityManagerInterface $em, MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_user.register', null, 'No access.');
// confirm parameters
$required_params = [
'phone_model',
'os_type',
'os_version',
'phone_id'
];
// check required parameters
$msg = $this->checkRequiredParameters($req, $required_params);
if ($msg)
return new APIResponse(false, $msg);
// get capi user to link to mobile user
$user_id = $this->getUser()->getID();
// check if capi user already has a mobile user
$mobile_user = $mah->findMobileUser($user_id);
if ($mobile_user != null)
return new APIResponse(false, 'User already registered');
// retry until we get a unique id
while (true)
{
try
{
// create mobile user
$mobile_user = new MobileUser();
$mobile_user->setPhoneModel($req->request->get('phone_model'))
->setOSType($req->request->get('os_type'))
->setOSVersion($req->request->get('os_version'))
->setPhoneID($req->request->get('phone_id'))
->setCapiUserId($user_id);
// reopen in case we get an exception
if (!$em->isOpen())
{
$em = $em->create(
$em->getConnection(),
$em->getConfiguration()
);
}
// save
$em->persist($mobile_user);
$em->flush();
}
catch (DBALException $e)
{
error_log($e->getMessage());
// delay one second and try again
sleep(1);
continue;
}
break;
}
// return data
// TODO: do we need to return the same names as before?
// right now, still using the old names so we use session_id name
$data = [
'session_id' => $mobile_user->getID(),
];
// response
return new APIResponse(true, 'Mobile user created.', $data);
}
public function confirmNumber(RisingTideGateway $rt, Request $req, EntityManagerInterface $em,
MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_user.confirm.number', null, 'No access.');
// check parameters
$required_params = [
'phone_number',
];
// check required parameters
$msg = $this->checkRequiredParameters($req, $required_params);
if ($msg)
return new APIResponse(false, $msg);
// get capi user to link to mobile user
$user_id = $this->getUser()->getID();
// get mobile user
$mobile_user = $mah->findMobileUser($user_id);
if ($mobile_user == null)
return new APIResponse(false, 'No mobile user found.');
// phone number
$phone_number = $req->request->get('phone_number');
// get otp_mode from .env
$dotenv = new Dotenv();
$dotenv->loadEnv(__DIR__.'/../../../.env');
$otp_mode = $_ENV['OTP_MODE'];
$data = [];
// check for hardcoded phone number for app store testing
if ($phone_number == '639221111111')
{
$code = '123456';
$mobile_user->setConfirmCode($code)
->setPhoneNumber($phone_number);
$em->flush();
return new APIResponse(true, 'Number confirmed.');
}
// check if otp_mode is test
if ($otp_mode == 'test')
{
$code = '123456';
$mobile_user->setConfirmCode($code)
->setPhoneNumber($phone_number);
$em->flush();
return new APIResponse(true, 'Number confirmed.');
}
// TODO: spam protection
// TODO: validate phone number
// generate code and save
$code = $this->generateConfirmCode();
$mobile_user->setConfirmCode($code)
->setPhoneNumber($phone_number);
$em->flush();
if ($otp_mode != 'test')
{
// send sms to number
$this->sendConfirmationCode($rt, $phone_number, $code);
}
// response
return new APIResponse(true, 'Number confirmed.');
}
public function validateCode(Request $req, EntityManagerInterface $em, MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_user.validate.code', null, 'No access.');
// check parameters
$required_params = [
'code',
];
// check required parameters
$msg = $this->checkRequiredParameters($req, $required_params);
if ($msg)
return new APIResponse(false, $msg);
// get capi user to link to mobile user
$user_id = $this->getUser()->getID();
// get mobile user
$mobile_user = $mah->findMobileUser($user_id);
if ($mobile_user == null)
return new APIResponse(false, 'No mobile user found.');
// code is wrong
$code = $req->request->get('code');
if ($mobile_user->getConfirmCode() != $code)
return new APIResponse(false, 'Wrong confirm code');
// set confirm date
$date = new DateTime();
$mobile_user->setDateConfirmed($date)
->setConfirmed();
// TODO: check if we have the number registered before and merge
$dupe_user = $this->findNumberMobileUser($mobile_user->getPhoneNumber(), $em);
if ($dupe_user != null)
{
$dupe_cust = $dupe_user->getCustomer();
$mobile_user->setCustomer($dupe_cust);
}
// TODO: check if mobile matches mobile of customer
// TODO: need to "clean" the mobile number. Mobile user stores the number with the area code prepended
// Customer stores the number without the area code
$customer = $this->findCustomerByNumber($mobile_user->getPhoneNumber(), $em);
if ($customer != null)
{
// TODO: if there is a dupe_sess, do we need to check if
// dupe_cust is the same as the customer we found?
$mobile_user->setCustomer($customer);
}
$em->flush();
// response
return new APIResponse(true, 'Code validated');
}
public function getInfo(Request $req, EntityManagerInterface $em, MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_user.get.info', null, 'No access.');
// get capi user to link to mobile user
$user_id = $this->getUser()->getID();
// get mobile user
$mobile_user = $mah->findMobileUser($user_id);
if ($mobile_user == null)
return new APIResponse(false, 'No mobile user found.');
// if no customer found
$cust = $mobile_user->getCustomer();
if ($cust == null)
{
$data = [
'first_name' => '',
'last_name' => '',
'priv_third_party' => (bool) false,
'priv_promo' => (bool) false,
];
return new APIResponse(true, 'No customer info found', $data);
}
// send back customer details
$data = [
'first_name' => $cust->getFirstName(),
'last_name' => $cust->getLastName(),
'priv_third_party' => (bool) $cust->getPrivacyThirdParty(),
'priv_promo' => (bool) $cust->getPrivacyPromo(),
];
return new APIResponse(true, 'Customer info found', $data);
}
public function updateInfo(Request $req, EntityManagerInterface $em, MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_user.update.info', null, 'No access.');
// check required parameters
$required_params = [
'first_name',
'last_name',
];
// check required parameters
$msg = $this->checkRequiredParameters($req, $required_params);
if ($msg)
return new APIResponse(false, $msg);
// get capi user to link to mobile user
$user_id = $this->getUser()->getID();
// get mobile user
$mobile_user = $mah->findMobileUser($user_id);
if ($mobile_user == null)
return new APIResponse(false, 'No mobile user found.');
$cust = $this->updateCustomerInfo($req, $em, $mobile_user);
// get privacy policy for mobile
$dotenv = new Dotenv();
$dotenv->loadEnv(__DIR__.'/../../../.env');
$policy_mobile_id = $_ENV['POLICY_MOBILE'];
$mobile_policy = $em->getRepository(PrivacyPolicy::class)->find($policy_mobile_id);
// set policy id
if ($mobile_policy != null)
{
$cust->setPrivacyPolicyMobile($mobile_policy);
}
$em->flush();
$data = [
'first_name' => $cust->getFirstName(),
'last_name' => $cust->getLastName(),
];
return new APIResponse(true, 'Customer info updated');
}
public function getStatus(Request $req, EntityManagerInterface $em, MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_user.get.status', null, 'No access.');
// get capi user to link to mobile user
$user_id = $this->getUser()->getID();
// get mobile user
$mobile_user = $mah->findMobileUser($user_id);
if ($mobile_user == null)
return new APIResponse(false, 'No mobile user found.');
// set data
$data = [];
if ($mobile_user->isConfirmed())
$data['status'] = 'confirmed';
else
$data['status'] = 'unconfirmed';
return new APIResponse(true, 'Customer status', $data);
}
public function resendCode(Request $req, RisingTideGateway $rt, EntityManagerInterface $em,
MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_user.resend.code', null, 'No access.');
// get capi user to link to mobile user
$user_id = $this->getUser()->getID();
// get mobile user
$mobile_user = $mah->findMobileUser($user_id);
if ($mobile_user == null)
return new APIResponse(false, 'No mobile user found.');
// already confirmed
if ($mobile_user->isConfirmed())
return new APIResponse(true, 'User is already confirmed');
// have sent code before
if ($mobile_session->getDateCodeSent() != null)
return new APIResponse(true, 'Can only send confirm code every 5 mins');
// TODO: send via sms
$phone_number = $mobile_user->getPhoneNumber();
$code = $mobile_user->getConfirmCode();
$this->sendConfirmationCode($rt, $phone_number, $code);
return new APIResponse(true, 'Code re-sent');
}
public function versionCheck(Request $req, EntityManagerInterface $em, MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_user.version.check', null, 'No access.');
$required_params = [
'version',
];
// check required parameters
$msg = $this->checkRequiredParameters($req, $required_params);
if ($msg)
return new APIResponse(false, $msg);
// get capi user to link to mobile user
$user_id = $this->getUser()->getID();
// get mobile user
$mobile_user = $mah->findMobileUser($user_id);
if ($mobile_user == null)
return new APIResponse(false, 'No mobile user found.');
$need_update = false;
$msg = 'Version is up to date.';
$api_version = $this->getParameter('api_version');
$app_version = $req->request->get('version');
$api_v = explode('.', $api_version);
$app_v = explode('.', $app_version);
if ($api_v[0] < $app_v[0])
return new APIResponse(false, 'Invalid application version: ' . $app_version);
if ($api_v[0] > $app_v[0])
{
$need_update = true;
$msg = 'Your version is outdated and needs an update to use the latest features RES-Q has to offer.';
}
$data = [
'need_update' => $need_update,
'message' => $msg,
];
return new APIResponse(true, 'Version checked', $data);
}
public function updateDeviceID(Request $req, EntityManagerInterface $em, MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_user.update.deviceid', null, 'No access.');
$required_params = [
'device_id',
];
// check required parameters
$msg = $this->checkRequiredParameters($req, $required_params);
if ($msg)
return new APIResponse(false, $msg);
// get capi user to link to mobile user
$user_id = $this->getUser()->getID();
// get mobile user
$mobile_user = $mah->findMobileUser($user_id);
if ($mobile_user == null)
return new APIResponse(false, 'No mobile user found.');
$device_id = $req->request->get('device_id');
$mobile_user->setDevicePushID($device_id);
$em->flush();
$data = [
'device_id' => $mobile_user->getDevicePushID(),
];
// response
return new APIResponse(true, 'Device ID updated', $data);
}
public function privacySettings(Request $req, EntityManagerInterface $em, MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_user.privacy.settings', null, 'No access.');
$required_params = [
'priv_third_party',
// 'priv_promo',
];
// check required parameters
$msg = $this->checkRequiredParameters($req, $required_params);
if ($msg)
return new APIResponse(false, $msg);
// get capi user to link to mobile user
$user_id = $this->getUser()->getID();
// get mobile user
$mobile_user = $mah->findMobileUser($user_id);
if ($mobile_user == null)
return new APIResponse(false, 'No mobile user found.');
// get customer
$cust = $mobile_user->getCustomer();
if ($cust == null)
return new APIResponse(false, 'No customer information found');
// set privacy settings
$priv_promo = $req->request->get('priv_promo', false);
$priv_third_party = $req->request->get('priv_third_party');
$cust->setPrivacyThirdParty($priv_third_party)
->setPrivacyPromo($priv_promo);
// get the policy ids from .env
$dotenv = new Dotenv();
$dotenv->loadEnv(__DIR__.'/../../../.env');
$policy_promo_id = $_ENV['POLICY_PROMO'];
$policy_third_party_id = $_ENV['POLICY_THIRD_PARTY'];
// check if privacy settings are true
// if true, set the private policy for the customer
if ($priv_promo)
{
// find the promo policy
$policy = $em->getRepository(PrivacyPolicy::class)->find($policy_promo_id);
// set policy id
if ($policy != null)
{
$cust->setPrivacyPolicyPromo($policy);
}
}
if ($priv_third_party)
{
// find the third party policy
$policy = $em->getRepository(PrivacyPolicy::class)->find($policy_third_party_id);
// set policy id
if ($policy != null)
{
$cust->setPrivacyPolicyThirdParty($policy);
}
}
$em->flush();
return new APIResponse(true, 'Privacy policy settings set');
}
// TODO: find session customer by phone number
protected function findNumberMobileUser($number, $em)
{
$query = $em->getRepository(MobileUser::class)->createQueryBuilder('s')
->where('s.phone_number = :number')
->andWhere('s.customer is not null')
->andWhere('s.confirm_flag = 1')
->setParameter('number', $number)
->setMaxResults(1)
->getQuery();
// we just need one
$res = $query->getOneOrNullResult();
return $res;
}
protected function findCustomerByNumber($number, $em)
{
$customers = $em->getRepository(Customer::class)->findBy(['phone_mobile' => $number]);
// find the customer with the most number of cars
$car_count = 0;
$cust = null;
foreach($customers as $customer)
{
error_log('no customer?');
$vehicles = $customer->getVehicles();
if (count($vehicles) > $car_count)
{
$car_count = count($vehicles);
// "save" customer object
$cust = $customer;
}
}
return $cust;
}
protected function updateCustomerInfo($req, $em, $mobile_user)
{
// create new customer if it's not there
$cust = $mobile_user->getCustomer();
if ($cust == null)
{
$cust = new Customer();
// set customer source
$cust->setCreateSource(CustomerSource::MOBILE);
$em->persist($cust);
$mobile_user->setCustomer($cust);
}
$cust->setFirstName($req->request->get('first_name'))
->setLastName($req->request->get('last_name'))
->setEmail($req->request->get('email', ''))
->setConfirmed($mobile_user->isConfirmed());
// update mobile phone of customer
$cust->setPhoneMobile(substr($mobile_user->getPhoneNumber(), 2));
return $cust;
}
protected function sendConfirmationCode(RisingTideGateway $rt, $phone_number, $code)
{
// send sms to number
$message = "Your Resq confirmation code is $code.";
$rt->sendSMS($phone_number, 'MOTOLITE', $message);
}
}

View file

@ -0,0 +1,251 @@
<?php
namespace App\Controller\ResqAPI;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\ORM\Query;
use Doctrine\ORM\EntityManagerInterface;
use Catalyst\APIBundle\Controller\APIController;
use Catalyst\APIBundle\Response\APIResponse;
use App\Entity\MobileUser;
use App\Entity\VehicleManufacturer;
use App\Entity\Vehicle;
use App\Entity\CustomerVehicle;
use App\Service\MobileAPIHandler;
use Catalyst\APIBundle\Access\Generator as ACLGenerator;
class CustomerVehicleController extends APIController
{
protected $acl_gen;
public function __construct(ACLGenerator $acl_gen)
{
$this->acl_gen = $acl_gen;
}
public function addVehicle(Request $req, EntityManagerInterface $em,
MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_customer_vehicle.add', null, 'No access.');
// check requirements
$msg = $this->checkVehicleRequirements($req);
if ($msg)
return new APIResponse(false, $msg);
// get capi user to link to mobile user
$user_id = $this->getUser()->getID();
// get mobile user
$mobile_user = $mah->findMobileUser($user_id);
if ($mobile_user == null)
return new APIResponse(false, 'No mobile user found.');
// customer vehicle
$cv = new CustomerVehicle();
$res = $this->setCustomerVehicleObject($mobile_user, $req, $cv, $em);
if (isset($res['cv_id']))
return new APIResponse(true, 'Customer vehicle added', $res);
else
return new APIResponse(false, $res);
}
public function updateVehicle(Request $req, $id, EntityManagerInterface $em,
MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_customer_vehicle.update', null, 'No access.');
// check requirements
$msg = $this->checkVehicleRequirements($req);
if ($msg)
return new APIResponse(false, $msg);
// get capi user to link to mobile user
$user_id = $this->getUser()->getID();
// get mobile user
$mobile_user = $mah->findMobileUser($user_id);
// get customer vehicle
$cv = $em->getRepository(CustomerVehicle::class)->find($id);
// check if it exists
if ($cv == null)
return new APIResponse(false, 'Vehicle does not exist');
// check if it's owned by customer
if ($cv->getCustomer()->getID() != $mobile_user->getCustomer()->getID())
return new APIResponse(false, 'Invalid vehicle');
$res = $this->setCustomerVehicleObject($mobile_user, $req, $cv, $em);
if (isset($res['cv_id']))
return new APIResponse(true, 'Customer vehicle updated', $res);
else
return new APIResponse(false, $res);
}
public function listVehicles(Request $req, EntityManagerInterface $em, MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_customer_vehicle.list', null, 'No access.');
// check required parameters
$required_params = [];
$msg = $this->checkRequiredParameters($req, $required_params);
if ($msg)
return new APIResponse(false, $msg);
// get capi user to link to mobile user
$user_id = $this->getUser()->getID();
// get mobile user
$mobile_user = $mah->findMobileUser($user_id);
if ($mobile_user == null)
return new APIResponse(false, 'No mobile user found.');
$cust = $mobile_user->getCustomer();
if ($cust == null)
return new APIResponse(false, 'No customer information found');
// vehicles
$cv_list = [];
$cvs = $cust->getVehicles();
foreach ($cvs as $cv)
{
$battery_id = null;
if ($cv->getCurrentBattery() != null)
$battery_id = $cv->getCurrentBattery()->getID();
$wty_ex = null;
if ($cv->getWarrantyExpiration() != null)
$wty_ex = $cv->getWarrantyExpiration()->format('Y-m-d');
$warranty = $mah->findWarranty($cv->getPlateNumber());
$cv_name = '';
if ($cv->getName() != null)
$cv_name = $cv->getName();
$cv_list[] = [
'cv_id' => $cv->getID(),
'mfg_id' => $cv->getVehicle()->getManufacturer()->getID(),
'make_id' => $cv->getVehicle()->getID(),
'name' => $cv_name,
'plate_num' => $cv->getPlateNumber(),
'model_year' => $cv->getModelYear(),
'color' => $cv->getColor(),
'condition' => $cv->getStatusCondition(),
'fuel_type' => $cv->getFuelType(),
'wty_code' => $cv->getWarrantyCode(),
'wty_expire' => $wty_ex,
'curr_batt_id' => $battery_id,
'is_motolite' => $cv->hasMotoliteBattery() ? 1 : 0,
'is_active' => $cv->isActive() ? 1 : 0,
'warranty' => $warranty,
];
}
// data
$data = [
'vehicles' => $cv_list
];
return new APIResponse(true, 'Customer vehicles listed', $data);
}
protected function checkVehicleRequirements(Request $req)
{
// check required parameters
$required_params = [
'make_id',
'name',
'plate_num',
'model_year',
'color',
'condition',
'fuel_type',
];
$msg = $this->checkRequiredParameters($req, $required_params);
// TODO: check valid plate number
// TODO: check valid fuel type (gas / diesel)
// TODO: check current battery id
// TODO: check condition (brand new / second-hand)
// TODO: check is_motolite and is_active (1 or 0)
// TODO: check warranty expiration date (YYYYMMDD)
// TODO: check model year coverage if it fits in between
return $msg;
}
protected function setCustomerVehicleObject(MobileUser $mobile_user, Request $req,
CustomerVehicle $cv, EntityManagerInterface $em)
{
$msg = '';
// check customer
$cust = $mobile_user->getCustomer();
if ($cust == null)
{
$msg = 'No customer information found';
return $msg;
}
// get vehicle
$vehicle = $em->getRepository(Vehicle::class)->find($req->request->get('make_id'));
if ($vehicle == null)
{
$msg = 'Invalid vehicle make id';
return $msg;
}
$cv->setCustomer($cust)
->setVehicle($vehicle)
->setName($req->request->get('name'))
->setPlateNumber($req->request->get('plate_num'))
->setModelYear($req->request->get('model_year'))
->setColor($req->request->get('color'))
->setFuelType($req->request->get('fuel_type'))
->setStatusCondition($req->request->get('condition'));
// set warranty code and expiration
// TODO: check warranty requirements
if (!empty($req->request->get('wty_code')))
$cv->setWarrantyCode($req->request->get('wty_code'));
if (!empty($req->request->get('wty_expire')))
$cv->setWarrantyExpiration(new DateTime($req->request->get('wty_expire')));
// TODO: get current battery
// is motolite
if ($req->request->get('is_motolite') == 0)
$cv->setHasMotoliteBattery(false);
else
$cv->setHasMotoliteBattery(true);
// is active
if ($req->request->get('is_active') == 0)
$cv->setActive(false);
else
$cv->setActive(true);
// save
$em->persist($cv);
$em->flush();
// data
$data = [
'cv_id' => $cv->getID()
];
return $data;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,200 @@
<?php
namespace App\Controller\ResqAPI;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\ORM\Query;
use Doctrine\ORM\EntityManagerInterface;
use Catalyst\APIBundle\Controller\APIController;
use Catalyst\APIBundle\Response\APIResponse;
use App\Entity\Partner;
use App\Entity\Review;
use App\Service\MobileAPIHandler;
use Catalyst\APIBundle\Access\Generator as ACLGenerator;
class PartnerController extends APIController
{
protected $acl_gen;
public function __construct(ACLGenerator $acl_gen)
{
$this->acl_gen = $acl_gen;
}
public function getClosestPartners(Request $req, EntityManagerInterface $em,
MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_partner.list', null, 'No access.');
// check required parameters
$required_params = [
'longitude',
'latitude',
'service_id',
'limit',
];
$msg = $this->checkRequiredParameters($req, $required_params);
if ($msg)
return new APIResponse(false, $msg);
// get capi user to link to mobile user
$user_id = $this->getUser()->getID();
// get mobile user
$mobile_user = $mah->findMobileUser($user_id);
if ($mobile_user == null)
return new APIResponse(false, 'No mobile user found.');
$long = $req->request->get('longitude');
$lat = $req->request->get('latitude');
$service_id = $req->request->get('service_id');
$limit = $req->request->get('limit');
// get partners within range
$query = $em->createQuery('SELECT p, st_distance(p.coordinates, point(:lng, :lat)) as dist FROM App\Entity\Partner p
JOIN App\Entity\Service s where s.id = :service_id ORDER BY dist')
->setParameter('lat', $lat)
->setParameter('lng', $long)
->setParameter('service_id', $service_id);
$query->setMaxResults($limit);
$result = $query->getResult();
$partners = [];
foreach($result as $row)
{
error_log($row[0]->getID());
$partners[] = [
'id' => $row[0]->getID(),
'name' => $row[0]->getName(),
'branch' => $row[0]->getBranch(),
'address' => $row[0]->getAddress(),
'contact_nums' => $row[0]->getContactNumbers(),
'time_open' => $row[0]->getTimeOpen()->format("g:i A"),
'time_close' => $row[0]->getTimeClose()->format("g:i A"),
'longitude' => $row[0]->getCoordinates()->getLongitude(),
'latitude' => $row[0]->getCoordinates()->getLatitude(),
'db_distance' => $row['dist'],
];
}
$data['partners'] = $partners;
return new APIResponse(true, 'Partners found', $data);
}
public function getPartnerInformation(Request $req, $pid, EntityManagerInterface $em,
MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_partner.info', null, 'No access.');
// check required parameters
$required_params = [];
$msg = $this->checkRequiredParameters($req, $required_params);
if ($msg)
return new APIResponse(false, $msg);
// get capi user to link to mobile user
$user_id = $this->getUser()->getID();
// get mobile user
$mobile_user = $mah->findMobileUser($user_id);
if ($mobile_user == null)
return new APIResponse(false, 'No mobile user found.');
// get partner
$partner = $em->getRepository(Partner::class)->findOneBy(['id' => $pid]);
if ($partner == null)
return new APIResponse(false, 'No partner found.');
// get reviews for partner
$reviews = $em->getRepository(Review::class)->findBy(['partner' => $partner]);
// get average rating for all reviews
$average_rating = 0;
if (!empty($reviews))
{
$rating = 0;
foreach($reviews as $review)
{
$rating = $rating + $review->getRating();
}
$average_rating = $rating / sizeof($reviews);
}
$data['partner'] = [
'id' => $partner->getID(),
'name' => $partner->getName(),
'branch' => $partner->getBranch(),
'address' => $partner->getAddress(),
'contact_nums' => $partner->getContactNumbers(),
'time_open' => $partner->getTimeOpen()->format("g:i A"),
'time_close' => $partner->getTimeClose()->format("g:i A"),
'longitude' => $partner->getCoordinates()->getLongitude(),
'latitude' => $partner->getCoordinates()->getLatitude(),
'average_rating' => $average_rating,
];
return new APIResponse(true, 'Partner information found', $data);
}
public function reviewPartner($pid, Request $req, EntityManagerInterface $em,
MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_partner.review', null, 'No access.');
$required_params = [
'rating',
'message',
];
$msg = $this->checkRequiredParameters($req, $required_params);
if ($msg)
return new APIResponse(false, $msg);
// get capi user to link to mobile user
$user_id = $this->getUser()->getID();
// get mobile user
$mobile_user = $mah->findMobileUser($user_id);
if ($mobile_user == null)
return new APIResponse(false, 'No mobile user found.');
$rating = $req->request->get('rating');
$msg = $req->request->get('message');
// TODO: check rating if 1 - 5
// check if partner exists
$partner = $em->getRepository(Partner::class)->find($pid);
if ($partner == null)
return new APIResponse(false, 'No partner found.');
$rev = new Review();
$rev->setRating($rating)
->setMessage($msg)
->setPartner($partner)
->setMobileUser($mobile_user);
// save to db
$em->persist($rev);
$em->flush();
$data = [
'rating' => $rev->getRating(),
'message' => $rev->getMessage(),
];
return new APIResponse(true, 'Review added', $data);
}
}

View file

@ -0,0 +1,39 @@
<?php
namespace App\Controller\ResqAPI;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\ORM\Query;
use Doctrine\ORM\EntityManagerInterface;
use Catalyst\APIBundle\Controller\APIController;
use Catalyst\APIBundle\Response\APIResponse;
use App\Entity\Promo;
use Catalyst\APIBundle\Access\Generator as ACLGenerator;
class PromoController extends APIController
{
protected $acl_gen;
public function __construct(ACLGenerator $acl_gen)
{
$this->acl_gen = $acl_gen;
}
public function listPromos(Request $req, EntityManagerInterface $em)
{
$this->denyAccessUnlessGranted('mobile_promo.list', null, 'No access.');
// check required parameters
$required_params = [];
$msg = $this->checkRequiredParameters($req, $required_params);
if ($msg)
return new APIResponse(false, $msg);
return new APIResponse(true, 'Promos listed');
}
}

View file

@ -0,0 +1,277 @@
<?php
namespace App\Controller\ResqAPI;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\ORM\Query;
use Doctrine\ORM\EntityManagerInterface;
use Catalyst\APIBundle\Controller\APIController;
use Catalyst\APIBundle\Response\APIResponse;
use App\Entity\Rider;
use App\Entity\JobOrder;
use App\Entity\RiderRating;
use App\Service\RiderTracker;
use App\Service\MobileAPIHandler;
use App\Ramcar\JOStatus;
use App\Ramcar\APIRiderStatus;
use Catalyst\APIBundle\Access\Generator as ACLGenerator;
class RiderController extends APIController
{
protected $acl_gen;
public function __construct(ACLGenerator $acl_gen)
{
$this->acl_gen = $acl_gen;
}
public function getRiderStatus(Request $req, RiderTracker $rt, EntityManagerInterface $em,
MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_rider.status.get', null, 'No access.');
$required_params = [];
$msg = $this->checkRequiredParameters($req, $required_params);
if ($msg)
return new APIResponse(false, $msg);
// get capi user to link to mobile user
$user_id = $this->getUser()->getID();
// get mobile user
$mobile_user = $mah->findMobileUser($user_id);
if ($mobile_user == null)
return new APIResponse(false, 'No mobile user found.');
// get customer
$cust = $mobile_user->getCustomer();
if ($cust == null)
return new APIResponse(false, 'No customer information found');
$ongoing_jos = $mah->getOngoingJobOrders($cust);
$data = [];
if (count($ongoing_jos) <= 0)
{
try
{
// check if the latest fulfilled jo they have needs rider rating
$query = $em->createQuery('select jo from App\Entity\JobOrder jo where jo.customer = :cust and jo.status = :status order by jo.date_fulfill desc');
$fulfill_jo = $query->setParameters([
'cust' => $cust,
'status' => JOStatus::FULFILLED,
])
->setMaxResults(1)
->getSingleResult();
}
catch (Exception $e)
{
// no pending
$data[] = [
'status' => APIRiderStatus::NO_PENDING_JO,
];
return new APIResponse(true, 'No pending job order', $data);
}
// we got a recently fulfilled job order
if ($fulfill_jo)
{
// check if the rider has been rated
if (!$fulfill_jo->hasRiderRating())
{
$dest = $fulfill_jo->getCoordinates();
$data[] = [
'jo_id' => $fulfill_jo->getID(),
'service_type' => $fulfill_jo->getServiceType(),
'destination' => [
'long' => $dest->getLongitude(),
'lat' => $dest->getLatitude(),
],
'delivery_address' => $fulfill_jo->getDeliveryAddress(),
'delivery_instructions' => $fulfill_jo->getDeliveryInstructions(),
];
$rider = $fulfill_jo->getRider();
// default image url
$url_prefix = $req->getSchemeAndHttpHost();
$image_url = $url_prefix . '/assets/images/user.gif';
if ($rider->getImageFile() != null)
$image_url = $url_prefix . '/uploads/' . $rider->getImageFile();
$data[] = [
'status' => APIRiderStatus::RIDER_RATING
];
// default rider location to hub
$data['rider'] = [
'id' => $rider->getID(),
'name' => $rider->getFullName(),
'plate_num' => $rider->getPlateNumber(),
'contact_num' => $rider->getContactNumber(),
'image_url' => $image_url,
];
return new APIResponse(true, 'Rider status found', $data);
}
}
// no pending
$data[] = [
'status' => APIRiderStatus::NO_PENDING_JO,
];
return new APIResponse(true, 'No pending job order', $data);
}
// get first jo that's pending
$jo = $ongoing_jos[0];
$dest = $jo->getCoordinates();
$data = [
'jo_id' => $jo->getID(),
'service_type' => $jo->getServiceType(),
'destination' => [
'long' => $dest->getLongitude(),
'lat' => $dest->getLatitude(),
],
'delivery_address' => $jo->getDeliveryAddress(),
'delivery_instructions' => $jo->getDeliveryInstructions(),
];
switch ($jo->getStatus())
{
case JOStatus::PENDING:
$data['status'] = APIRiderStatus::OUTLET_ASSIGN;
$res->setData($data);
return $res->getReturnResponse();
case JOStatus::RIDER_ASSIGN:
$data['status'] = APIRiderStatus::RIDER_ASSIGN;
$res->setData($data);
return $res->getReturnResponse();
case JOStatus::ASSIGNED:
case JOStatus::IN_TRANSIT:
case JOStatus::IN_PROGRESS:
$rider = $jo->getRider();
// get rider coordinates from redis
$coord = $rt->getRiderLocation($rider->getID());
// default image url
$url_prefix = $req->getSchemeAndHttpHost();
$image_url = $url_prefix . '/assets/images/user.gif';
if ($rider->getImageFile() != null)
$image_url = $url_prefix . '/uploads/' . $rider->getImageFile();
$data['status'] = APIRiderStatus::RIDER_PICK_UP;
// TODO: fix this to actual location of rider
// default rider location to hub
$data['rider'] = [
'id' => $rider->getID(),
'name' => $rider->getFullName(),
'plate_num' => $rider->getPlateNumber(),
'contact_num' => $rider->getContactNumber(),
'image_url' => $image_url,
'location' => [
'long' => $coord->getLongitude(),
'lat' => $coord->getLatitude()
]
];
return new APIResponse(true, 'Rider status found', $data);
}
return new APIResponse(true, 'Rider status found', $data);
}
public function addRiderRating(Request $req, EntityManagerInterface $em,
MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_rider.rating.add', null, 'No access.');
$required_params = [
'jo_id',
'rating',
];
$msg = $this->checkRequiredParameters($req, $required_params);
if ($msg)
return new APIResponse(false, $msg);
// get capi user to link to mobile user
$user_id = $this->getUser()->getID();
// get mobile user
$mobile_user = $mah->findMobileUser($user_id);
if ($mobile_user == null)
return new APIResponse(false, 'No mobile user found.');
// get customer
$cust = $mobile_user->getCustomer();
if ($cust == null)
return new APIResponse(false, 'No customer information found');
// get job order
$jo_id = $req->request->get('jo_id');
$jo = $em->getRepository(JobOrder::class)->find($jo_id);
if ($jo == null)
return new APIResponse(false, 'No job order found');
// get rider
$rider = $jo->getRider();
if ($rider == null)
return new APIResponse(false, 'No rider found');
// check that the customer owns the job order
$jo_cust = $jo->getCustomer();
if ($jo_cust->getID() != $cust->getID())
return new APIResponse(false, 'Job order was not initiated by customer;');
// TODO: check job order status, if it's complete
// add rider rating
$rating_num = $req->request->get('rating', -1);
// if rating is -1
if ($rating_num == -1)
{
$jo->setHasRiderRating();
$em->flush();
return new APIResponse(false, 'No rider rating', $data);
}
$rating = new RiderRating();
$rating->setRider($rider)
->setCustomer($cust)
->setJobOrder($jo)
->setRating($rating_num);
// rider rating comment
$comment = $req->request->get('comment');
if (!empty($comment))
$rating->setComment($comment);
// mark jo as rider rated already
$jo->setHasRiderRating();
$em->persist($rating);
$em->flush();
$data = [
'rating' => $rating->getRating(),
'comment' => $rating->getComment(),
];
// TODO: set average rating in rider entity
return new APIResponse(true, 'Rider rating added', $data);
}
}

View file

@ -0,0 +1,67 @@
<?php
namespace App\Controller\ResqAPI;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\ORM\Query;
use Doctrine\ORM\EntityManagerInterface;
use Catalyst\APIBundle\Controller\APIController;
use Catalyst\APIBundle\Response\APIResponse;
use App\Entity\Service;
use App\Service\MobileAPIHandler;
use Catalyst\APIBundle\Access\Generator as ACLGenerator;
class ServiceController extends APIController
{
protected $acl_gen;
public function __construct(ACLGenerator $acl_gen)
{
$this->acl_gen = $acl_gen;
}
public function listServices(Request $req, EntityManagerInterface $em,
MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_service.list', null, 'No access.');
// check required parameters
$required_params = [];
$msg = $this->checkRequiredParameters($req, $required_params);
if ($msg)
return new APIResponse(false, $msg);
// get capi user to link to mobile user
$user_id = $this->getUser()->getID();
// get mobile user
$mobile_user = $mah->findMobileUser($user_id);
if ($mobile_user == null)
return new APIResponse(false, 'No mobile user found.');
// services
$results = $em->getRepository(Service::class)->findAll();
if (empty($results))
return new APIResponse(false, 'No services available');
$services = [];
foreach ($results as $result)
{
$services[] = [
'id' => $result->getID(),
'name' => $result->getName(),
];
}
$data['services'] = $services;
return new APIResponse(true, 'Services found', $data);
}
}

View file

@ -0,0 +1,122 @@
<?php
namespace App\Controller\ResqAPI;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\ORM\Query;
use Doctrine\ORM\EntityManagerInterface;
use Catalyst\APIBundle\Controller\APIController;
use Catalyst\APIBundle\Response\APIResponse;
use App\Entity\VehicleManufacturer;
use App\Entity\Vehicle;
use App\Service\MobileAPIHandler;
use Catalyst\APIBundle\Access\Generator as ACLGenerator;
class VehicleController extends APIController
{
protected $acl_gen;
public function __construct(ACLGenerator $acl_gen)
{
$this->acl_gen = $acl_gen;
}
public function listVehicleManufacturers(Request $req, EntityManagerInterface $em,
MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_vmanufacturer.list', null, 'No access.');
// check required parameters
$required_params = [];
$msg = $this->checkRequiredParameters($req, $required_params);
if ($msg)
return new APIResponse(false, $msg);
// get capi user to link to mobile user
$user_id = $this->getUser()->getID();
// get mobile user
$mobile_user = $mah->findMobileUser($user_id);
if ($mobile_user == null)
return new APIResponse(false, 'No mobile user found.');
// get manufacturer list
$mfgs = $em->getRepository(VehicleManufacturer::class)->findBy(['flag_mobile' => true], ['name' => 'asc']);
$mfg_list = [];
foreach ($mfgs as $mfg)
{
$mfg_list[] = [
'id' => $mfg->getID(),
'name' => $mfg->getName(),
];
}
$data = [
'manufacturers' => $mfg_list
];
return new APIResponse(true, 'Vehicle manufacturers listed.', $data);
}
public function listVehicleMakes(Request $req, $mfg_id, EntityManagerInterface $em,
MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_vehicle.list', null, 'No access.');
// check required parameters
$required_params = [];
$msg = $this->checkRequiredParameters($req, $required_params);
if ($msg)
return new APIResponse(false, $msg);
// get capi user to link to mobile user
$user_id = $this->getUser()->getID();
// get mobile user
$mobile_user = $mah->findMobileUser($user_id);
if ($mobile_user == null)
return new APIResponse(false, 'No mobile user found.');
// get manufacturer
$mfg = $em->getRepository(VehicleManufacturer::class)->find($mfg_id);
if ($mfg == null)
return new APIResponse(false, 'Invalid vehicle manufacturer id');
// get makes
$vehicles = $em->getRepository(Vehicle::class)->findBy(
[
'flag_mobile' => true,
'manufacturer' => $mfg_id,
],
['make' => 'asc']
);
// $vehicles = $mfg->getVehicles();
$vlist = [];
foreach ($vehicles as $v)
{
$vlist[] = [
'id' => $v->getID(),
'make' => trim($v->getMake() . ' ' . $v->getModelYearFormatted(false)),
];
}
$data = [
'manufacturer' => [
'id' => $mfg->getID(),
'name' => $mfg->getName(),
],
'makes' => $vlist,
];
return new APIResponse(true, 'Vehicle makes listed.', $data);
}
}

View file

@ -0,0 +1,563 @@
<?php
namespace App\Controller\ResqAPI;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Doctrine\ORM\Query;
use Doctrine\ORM\EntityManagerInterface;
use Catalyst\APIBundle\Controller\APIController;
use Catalyst\APIBundle\Response\APIResponse;
use App\Ramcar\WarrantySource;
use App\Entity\Warranty;
use App\Entity\WarrantySerial;
use App\Entity\SAPBattery;
use App\Entity\CustomerVehicle;
use App\Service\RisingTideGateway;
use App\Service\WarrantyAPILogger;
use App\Service\MobileAPIHandler;
use Catalyst\APIBundle\Access\Generator as ACLGenerator;
use DateTime;
class WarrantyController extends APIController
{
protected $acl_gen;
public function __construct(ACLGenerator $acl_gen)
{
$this->acl_gen = $acl_gen;
}
public function warrantyRegister($serial, EntityManagerInterface $em, Request $req, KernelInterface $kernel, RisingTideGateway $rt,
TranslatorInterface $trans, WarrantyAPILogger $logger, MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_jo.request', null, 'No access.');
// check required parameters
$required_params = [
'first_name',
'last_name',
'plate_number',
'date_purchase',
];
// handle file uploads
$invoice = $req->files->get('invoice');
$warr_card = $req->files->get('warr_card');
// normalize serial
$serial = trim(strtoupper($serial));
// process picture uploads
$upload_dir = $kernel->getProjectDir() . '/public/warranty_uploads';
$inv_filename = $this->handlePictureUpload($invoice, $upload_dir, $serial, 'invoice');
$wcard_filename = $this->handlePictureUpload($warr_card, $upload_dir, $serial, 'wcard');
// get capi user to link to mobile user
$capi_user_id = $this->getUser()->getID();
// get mobile user
$mobile_user = $mah->findMobileUser($capi_user_id);
if ($mobile_user == null)
return new APIResponse(false, 'No mobile user found.');
$user_id = $mobile_user->getID();
// prepare logging data
$action = 'create';
$source = WarrantySource::MOBILE;
$log_data = [
'plate_number' => $req->request->get('plate_num'),
'first_name' => $req->request->get('first_name'),
'last_name' => $req->request->get('last_name'),
'date_purchase' => $req->request->get('date_purchase'),
];
$msg = $this->checkRequiredParameters($req, $required_params);
if ($msg)
{
$logger->logWarrantyInfo($log_data, $msg, $user_id, $action, $source);
return new APIResponse(false, $msg);
}
// update customer information
// $cust = $this->updateCustomerInfo($req, $em);
// update warranty
$data = [];
$msg = $this->updateWarranty($data, $em, $rt, $trans, $req, $serial, $inv_filename, $wcard_filename,
$logger, $log_data, $user_id, $action, $source, $mobile_user);
if ($msg != null)
return new APIResponse(false, $msg);
$em->flush();
return new APIResponse(true, 'Warranty registered', $data);
}
public function warrantyCheck($serial, EntityManagerInterface $em, Request $req, MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_warranty.check', null, 'No access.');
// check required parameters
$required_params = [];
$msg = $this->checkRequiredParameters($req, $required_params);
if ($msg)
return new APIResponse(false, $msg);
// get capi user to link to mobile user
$user_id = $this->getUser()->getID();
// get mobile user
$mobile_user = $mah->findMobileUser($user_id);
if ($mobile_user == null)
return new APIResponse(false, 'No mobile user found.');
// check if warranty serial is there
$warr_serial = $em->getRepository(WarrantySerial::class)->find($serial);
if ($warr_serial == null)
return new APIResponse(false, 'Invalid warranty serial code');
$warr = $em->getRepository(Warranty::class)->findOneBy(['serial' => $serial]);
$batt = null;
$is_registered = false;
$today = new DateTime();
// if we have a warranty entry for the serial already
if ($warr != null)
{
$warr_plate = $warr->getPlateNumber();
$is_registered = true;
$is_customer_warranty = false;
// check if the warranty is registered to a car owned by the customer
$cust = $mobile_user->getCustomer();
$is_customer_warranty = $this->checkCustomerPlateNumber($warr_plate, $cust);
// null mobile number should be blank string instead
if ($warr->getMobileNumber() == null)
$mobile_num = '';
else
$mobile_num = $warr->getMobileNumber();
$can_edit = $is_customer_warranty;
// if customer plate number matches the one registered on the warranty
if ($is_customer_warranty)
{
// purchase date of customer
if ($warr->getDatePurchaseCustomer() != null)
$date_purchase_cust = $warr->getDatePurchaseCustomer()->format('Y-m-d');
else
$date_purchase_cust = $today->format('Y-m-d');
// invoice
if ($warr->getFileInvoice() != null)
$invoice_url = $req->getSchemeAndHttpHost() . '/warranty_uploads/' . $warr->getFileInvoice();
else
$invoice_url = '';
// warranty card
if ($warr->getFileWarrantyCard() != null)
$warr_card_url = $req->getSchemeAndHttpHost() . '/warranty_uploads/' . $warr->getFileWarrantyCard();
else
$warr_card_url = '';
$customer = [
'first_name' => $warr->getFirstName() ?? '',
'last_name' => $warr->getLastName() ?? '',
'mobile_number' => $mobile_num,
'plate_number' => $warr_plate,
'email' => $warr->getEmail() ?? '',
'contact_num' => $warr->getContactNumber() ?? '',
'address' => $warr->getCustomerAddress() ?? '',
];
$other_data = [
'odometer' => (int) $warr->getOdometer() ?? 0,
'date_purchase' => $date_purchase_cust,
'invoice' => $invoice_url,
'warr_card' => $warr_card_url,
'dealer_name' => $warr->getDealerName() ?? '',
'dealer_address' => $warr->getDealerAddress() ?? '',
];
}
else
{
// hide customer information if customer is not the one registered
$customer = [
'first_name' => '',
'last_name' => '',
'mobile_number' => '',
'plate_number' => '',
'email' => '',
'contact_num' => '',
'address' => '',
];
$other_data = [
'odometer' => 0,
'date_purchase' => $today->format('Y-m-d'),
'invoice' => '',
'warr_card' => '',
'dealer_name' => '',
'dealer_address' => '',
];
}
}
else
{
$can_edit = true;
$customer = [
'first_name' => '',
'last_name' => '',
'mobile_number' => '',
'plate_number' => '',
'email' => '',
'contact_num' => '',
'address' => '',
];
$other_data = [
'odometer' => 0,
'date_purchase' => $today->format('Y-m-d'),
'invoice' => '',
'warr_card' => '',
'dealer_name' => '',
'dealer_address' => '',
];
}
$sku = $warr_serial->getSKU();
$batt = null;
$cat_name = '';
if ($sku != null)
$batt = $em->getRepository(SAPBattery::class)->find($sku);
else
{
// get the category name of the serial
$cat_name = $warr_serial->getMetaInfo('category_name');
}
// TODO: put this in a config file
$image_url = $req->getSchemeAndHttpHost() . '/battery/generic.png';
if ($batt != null)
{
$battery = [
'brand' => $batt->getBrand()->getName(),
'size' => $batt->getSize()->getName(),
'image_url' => $image_url,
];
}
else
{
$battery = [
'brand' => $cat_name,
'size' => '',
'image_url' => '',
];
}
// populate data
$data = [
'is_valid' => true,
'is_registered' => $is_registered,
'can_edit' => $can_edit,
'customer' => $customer,
'battery' => $battery,
'odometer' => $other_data['odometer'],
'invoice' => $other_data['invoice'],
'warr_card' => $other_data['warr_card'],
'date_purchase' => $other_data['date_purchase'],
'dealer_name' => $other_data['dealer_name'],
'dealer_address' => $other_data['dealer_address'],
'message' => [
'register_error' => 'Warranty serial code has already been registered.',
'edit_error' => 'Sorry, warranty is registered under another vehicle not in your list of vehicles.',
],
];
return new APIResponse(true, 'Warranty checked', $data);
}
public function activateWarranty(Request $req, EntityManagerInterface $em, MobileAPIHandler $mah)
{
$this->denyAccessUnlessGranted('mobile_warranty.activate', null, 'No access.');
$required_params = ['plate_number'];
$msg = $this->checkRequiredParameters($req, $required_params);
if ($msg)
return new APIResponse(false, $msg);
// get capi user to link to mobile user
$user_id = $this->getUser()->getID();
// get mobile user
$mobile_user = $mah->findMobileUser($user_id);
if ($mobile_user == null)
return new APIResponse(false, 'No mobile user found.');
$plate_number = $req->request->get('plate_number');
// find warranty using plate number
$warranty_results = $em->getRepository(Warranty::class)->findBy(['plate_number' => $plate_number],
['date_create' => 'desc']);
// check if warranty_results is empty
if (empty($warranty_results))
return new APIResponse(false, 'No warranty found for plate number');
// activate all entries
foreach ($warranty_results as $warranty)
{
$warranty->setActivated();
}
$em->flush();
$data = $this->generateWarrantyData($warranty);
return new APIResponse(true, 'Warranty activated', $data);
}
protected function handlePictureUpload($file, $target_dir, $serial, $name)
{
error_log("handling $name upload");
// no file sent
if ($file == null)
{
error_log('no file');
return null;
}
// create target dir if it doesn't exist
if (!file_exists($target_dir))
{
if (!mkdir($target_dir, 0744, true))
{
error_log('failed to create folder for warranty pictures');
return null;
}
}
// move file
$filename = $name . '.' . $file->getClientOriginalExtension();
$file->move($target_dir . '/' . $serial, $filename);
error_log("filename - $filename");
error_log($target_dir . '/' . $serial . '/' . $filename);
return $serial . '/' . $filename;
}
protected function updateWarranty(&$data, $em, $rt, $trans, $req, $serial, $inv_filename = null, $wcard_filename = null,
$logger, $log_data, $user_id, $action, $source, $mobile_user)
{
// get serial
$warr_serial = $em->getRepository(WarrantySerial::class)->find($serial);
if ($warr_serial == null)
{
$msg = 'Invalid warranty serial code.';
$logger->logWarrantyInfo($log_data, $msg, $user_id, $action, $source);
return $msg;
}
// check if warranty exists already
$warr = $em->getRepository(Warranty::class)->findOneBy(['serial' => $serial]);
// skip warranty if it already exists
if ($warr != null)
{
/*
// NOTE: we could not update in the old version
$res->setError(true)
->setErrorMessage('Warranty registration entry already exists.');
return $res;
*/
// check if warranty is registered to a serial owned by customer
$warr_plate = $warr->getPlateNumber();
$cust = $mobile_user->getCustomer();
$is_customer_warranty = $this->checkCustomerPlateNumber($warr_plate, $cust);
if (!$is_customer_warranty)
{
$msg = 'Warranty registered to a vehicle not in your list of vehicles.';
$logger->logWarrantyInfo($log_data, $msg, $user_id, $action, $source);
return $msg;
}
$sms_msg = $trans->trans('warranty_update_confirm');
}
else
{
$warr = new Warranty();
$sms_msg = $trans->trans('warranty_register_confirm');
// set warranty source
$warr->setCreateSource($source);
}
// get sap battery
$sku = $warr_serial->getSKU();
$sap_bty = null;
if ($sku != null)
{
$sap_bty = $em->getRepository(SAPBattery::class)->find($sku);
if ($sap_bty == null)
{
$msg = 'Could not find battery entry for warranty.';
$logger->logWarrantyInfo($log_data, $msg, $user_id, $action, $source);
return $msg;
}
}
// default date purchase to today
// NOTE: might need to change this later
$date_pur = new DateTime();
// get date purchase specified by customer
$date_pur_cust = DateTime::createFromFormat('Y-m-d', $req->request->get('date_purchase'));
if (!$date_pur_cust)
{
$msg = 'Invalid date format for date of purchase.';
$logger->logWarrantyInfo($log_data, $msg, $user_id, $action, $source);
return $msg;
}
$customer = $mobile_user->getCustomer();
if ($customer != null)
{
$warr->setCustomer($customer);
// get customer vehicles
$vehicle = $this->findCustomerVehicle($em, $customer, $req->request->get('plate_number'));
if ($vehicle != null)
$warr->setVehicle($vehicle);
}
// create or update warranty entry
$warr->setSerial($serial)
->setFirstName($req->request->get('first_name'))
->setLastName($req->request->get('last_name'))
->setEmail($req->request->get('email'))
->setPlateNumber($req->request->get('plate_number'))
// TODO: figure out how to compute date of purchase
->setDatePurchase($date_pur)
// TODO: set status
// ->setStatus()
// TODO: set battery model and size id
// ->setBatterySize()
// ->setBatteryModel()
->setSAPBattery($sap_bty)
->setMobileNumber(substr($mobile_user->getPhoneNumber(), 2))
->setActivated(true)
// files
->setFileInvoice($inv_filename)
->setFileWarrantyCard($wcard_filename)
// new fields
->setOdometer($req->request->get('odometer', 0))
->setDatePurchaseCustomer($date_pur_cust)
->setContactNumber($req->request->get('contact_num'))
->setCustomerAddress($req->request->get('cust_address'))
->setDealerName($req->request->get('dealer_name'))
->setDealerAddress($req->request->get('dealer_address'))
->setValidated(false);
// TODO: check for date purchase and date expire
$em->persist($warr);
// TODO: check if we need to do anything else
// TODO: put warranty data into data
$data = $this->generateWarrantyData($warr);
$logger->logWarrantyInfo($log_data, '', $user_id, $action, $source);
// send sms
error_log('sending sms to - ' . $mobile_user->getPhoneNumber());
$rt->sendSMS($mobile_user->getPhoneNumber(), 'MOTOLITE', $sms_msg);
}
protected function findCustomerVehicle($em, $customer, $plate_number)
{
$clean_plate = Warranty::cleanPlateNumber($plate_number);
if ($clean_plate)
{
// find the customer vehicle and get the vehicle
$cv = $em->getRepository(CustomerVehicle::class)->findOneBy(['plate_number' => $clean_plate, 'customer' => $customer]);
if ($cv != null)
{
$vehicle = $cv->getVehicle();
return $vehicle;
}
}
return null;
}
protected function checkCustomerPlateNumber($plate_number, $cust)
{
// strip spaces and make all caps
$plate_number = preg_replace('/\s+/', '', strtoupper($plate_number));
// if there's no customer linked to session
if ($cust != null)
{
// check all the customer vehicles
$cvs = $cust->getVehicles();
foreach ($cvs as $cv)
{
$cv_plate = preg_replace('/\s+/', '', strtoupper($cv->getPlateNumber()));
// did we find a match?
if ($cv_plate == $plate_number)
{
return true;
}
}
}
return false;
}
protected function generateWarrantyData($warranty)
{
$sap_bty_name = '';
if ($warranty->getSAPBAttery() != null)
$sap_bty_name = $warranty->getSAPBattery()->getID();
$data = [
'serial' => $warranty->getSerial(),
'first_name' => $warranty->getFirstName(),
'last_name' => $warranty->getLastName(),
'email' => $warranty->getEmail() ?? '',
'plate_number' => $warranty->getPlateNumber(),
'date_purchase' => $warranty->getDatePurchase()->format('Y-m-d'),
'sap_battery' => $sap_bty_name,
'mobile_number' => $warranty->getMobileNumber() ?? '',
'activated' => (boolean) $warranty->isActivated(),
'invoice_file' => $warranty->getFileInvoice() ?? '',
'warranty_card_file' => $warranty->getFileWarrantyCard() ?? '',
'odometer' => $warranty->getOdometer() ?? 0,
'date_purchase_customer' => $warranty->getDatePurchaseCustomer()->format('Y-m-d'),
'contact_number' => $warranty->getContactNumber() ?? '',
'customer_address' => $warranty->getCustomerAddress() ?? '',
'dealer_name' => $warranty->getDealerName() ?? '',
'dealer_address' => $warranty->getDealerAddress() ?? '',
'validated' => (boolean) $warranty->isValidated(),
];
return $data;
}
}

View file

@ -215,6 +215,12 @@ class Customer
*/
protected $customer_tags;
// mobile users linked to this customer
/**
* @ORM\OneToMany(targetEntity="MobileUser", mappedBy="customer")
*/
protected $mobile_users;
public function __construct()
{
$this->numbers = new ArrayCollection();
@ -222,6 +228,7 @@ class Customer
$this->vehicles = new ArrayCollection();
$this->job_orders = new ArrayCollection();
$this->customer_tags = new ArrayCollection();
$this->mobile_users = new ArrayCollection();
$this->customer_classification = CustomerClassification::REGULAR;
$this->customer_notes = '';
@ -656,4 +663,22 @@ class Customer
$this->customer_tags->removeElement($customer_tag);
$customer_tag->removeCustomer($this);
}
public function addMobileUser(MobileUser $mobile_user)
{
$this->mobile_users->add($mobile_user);
return $this;
}
public function clearMobileUsers()
{
$this->mobile_users->clear();
return $this;
}
public function getMobileUsers()
{
return $this->mobile_users;
}
}

277
src/Entity/MobileUser.php Normal file
View file

@ -0,0 +1,277 @@
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use DateTime;
/**
* @ORM\Entity
* @ORM\Table(
* name="mobile_user",
* indexes={@ORM\Index(name="capi_user_idx", columns={"capi_user_id"})}
* )
*/
class MobileUser
{
// unique id
/**
* @ORM\Id
* @ORM\Column(type="string", length=13)
*/
protected $id;
// phone model
/**
* @ORM\Column(type="string", length=50)
*/
protected $phone_model;
// operating system (android, ios, etc)
/**
* @ORM\Column(type="string", length=15)
*/
protected $os_type;
// os version
/**
* @ORM\Column(type="string", length=25)
*/
protected $os_version;
// device id or push id used by device
/**
* @ORM\Column(type="string", length=200, nullable=true)
*/
protected $device_push_id;
// phone id
/**
* @ORM\Column(type="string", length=50, nullable=true)
*/
protected $phone_id;
// link to customer
/**
* @ORM\ManyToOne(targetEntity="Customer", inversedBy="sessions")
* @ORM\JoinColumn(name="customer_id", referencedColumnName="id", nullable=true)
*/
protected $customer;
// phone number
/**
* @ORM\Column(type="string", length=12, nullable=true)
*/
protected $phone_number;
// confirm code that we send via SMS
/**
* @ORM\Column(type="string", length=6, nullable=true)
*/
protected $confirm_code;
// is confirmed?
/**
* @ORM\Column(type="boolean")
*/
protected $confirm_flag;
// date the session id was generated and sent to mobile app
/**
* @ORM\Column(type="datetime")
*/
protected $date_generated;
// date the phone number was confirmed
/**
* @ORM\Column(type="datetime", nullable=true)
*/
protected $date_confirmed;
// date and time that the confirmation code was last sent
/**
* @ORM\Column(type="datetime", nullable=true)
*/
protected $date_code_sent;
// reviews made by mobile user
/**
* @ORM\OneToMany(targetEntity="Review", mappedBy="mobile_user")
*/
protected $reviews;
// capi user id loosely associated to mobile user
/**
* @ORM\Column(type="integer", nullable=true)
*/
protected $capi_user_id;
public function __construct()
{
// default date generated to now
$this->id = $this->generateKeyID();
$this->date_generated = new DateTime();
$this->customer = null;
$this->confirm_flag = false;
$this->date_confirmed = null;
$this->date_code_sent = null;
$this->reviews = new ArrayCollection();
$this->capi_user_id = 0;
}
public function generateKeyID()
{
// use uniqid for now, since primary key dupes will trigger exceptions
return uniqid();
}
public function getID()
{
return $this->id;
}
public function setPhoneModel($model)
{
$this->phone_model = $model;
return $this;
}
public function getPhoneModel()
{
return $this->phone_model;
}
public function setOSType($type)
{
$this->os_type = $type;
return $this;
}
public function getOSType()
{
return $this->os_type;
}
public function setOSVersion($version)
{
$this->os_version = $version;
return $this;
}
public function getOSVersion()
{
return $this->os_version;
}
public function setPhoneID($id)
{
$this->phone_id = $id;
return $this;
}
public function getPhoneID()
{
return $this->phone_id;
}
public function setDevicePushID($id)
{
$this->device_push_id = $id;
return $this;
}
public function getDevicePushID()
{
return $this->device_push_id;
}
public function setCustomer(Customer $cust = null)
{
$this->customer = $cust;
return $this;
}
public function getCustomer()
{
return $this->customer;
}
public function getDateGenerated()
{
return $this->date_generated;
}
public function setPhoneNumber($num)
{
$this->phone_number = $num;
return $this;
}
public function getPhoneNumber()
{
return $this->phone_number;
}
public function setConfirmCode($code)
{
$this->confirm_code = $code;
return $this;
}
public function getConfirmCode()
{
return $this->confirm_code;
}
public function setConfirmed($flag = true)
{
$this->confirm_flag = $flag;
return $this;
}
public function isConfirmed()
{
return $this->confirm_flag;
}
public function setDateConfirmed(DateTime $date)
{
$this->date_confirmed = $date;
return $this;
}
public function getDateConfirmed()
{
return $this->date_confirmed;
}
public function setDateCodeSent(DateTime $date)
{
$this->date_code_sent = $date;
return $this;
}
public function getDateCodeSent()
{
return $this->date_code_sent;
}
public function getReviews()
{
return $this->reviews;
}
public function setCapiUserId($capi_user_id)
{
$this->capi_user_id = $capi_user_id;
}
public function getCapiUserId()
{
return $this->capi_user_id;
}
}

View file

@ -52,6 +52,13 @@ class Review
*/
protected $mobile_session;
// mobile user that sent review
/**
* @ORM\ManyToOne(targetEntity="MobileUser", inversedBy="reviews")
* @ORM\JoinColumn(name="mobile_user_id", referencedColumnName="id")
*/
protected $mobile_user;
public function __construct()
{
$this->date_create = new DateTime();
@ -114,4 +121,15 @@ class Review
return $this->mobile_session;
}
public function setMobileUser(MobileUser $mobile_user)
{
$this->mobile_user = $mobile_user;
return $this;
}
public function getMobileUser()
{
return $this->mobile_user;
}
}

View file

@ -123,7 +123,9 @@ class ResqInvoiceGenerator implements InvoiceGeneratorInterface
// get current user
$user = $this->security->getUser();
if ($user != null)
// check if user is User or APIUser
//if ($user != null)
if ($user instanceof User)
{
$invoice->setCreatedBy($user);
}

View file

@ -56,6 +56,7 @@ use App\Service\PromoLogger;
use App\Service\HubSelector;
use App\Service\HubDistributor;
use App\Service\HubFilteringGeoChecker;
use App\Service\JobOrderManager;
use CrEOF\Spatial\PHP\Types\Geometry\Point;
@ -80,6 +81,8 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
protected $promo_logger;
protected $hub_dist;
protected $hub_geofence;
protected $mclient;
protected $jo_manager;
protected $template_hash;
@ -87,7 +90,8 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
InvoiceGeneratorInterface $ic, ValidatorInterface $validator,
TranslatorInterface $translator, RiderAssignmentHandlerInterface $rah,
string $country_code, WarrantyHandler $wh, RisingTideGateway $rt,
PromoLogger $promo_logger, HubDistributor $hub_dist, HubFilteringGeoChecker $hub_geofence)
PromoLogger $promo_logger, HubDistributor $hub_dist, HubFilteringGeoChecker $hub_geofence,
MQTTClient $mclient, JobOrderManager $jo_manager)
{
$this->em = $em;
$this->ic = $ic;
@ -101,6 +105,8 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
$this->promo_logger = $promo_logger;
$this->hub_dist = $hub_dist;
$this->hub_geofence = $hub_geofence;
$this->mclient = $mclient;
$this->jo_manager = $jo_manager;
$this->loadTemplates();
}
@ -342,106 +348,15 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
->setDpaConsent($is_dpa_checked);
}
// check if lat and lng are provided
if (empty($req->request->get('coord_lng')) || empty($req->request->get('coord_lat'))) {
$error_array['coordinates'] = 'No map coordinates provided. Please click on a location on the map.';
}
// check if customer vehicle is set
if (empty($req->request->get('customer_vehicle'))) {
$error_array['customer_vehicle'] = 'No vehicle selected.';
} else {
// get customer vehicle
$cust_vehicle = $em->getRepository(CustomerVehicle::class)->find($req->request->get('customer_vehicle'));
if (empty($cust_vehicle)) {
$error_array['customer_vehicle'] = 'Invalid vehicle specified.';
}
}
// check if landmark is set
if (empty($req->request->get('landmark')))
$error_array['landmark'] = 'Landmark is required.';
// check if customer is not willing to wait
$will_wait = $req->request->get('flag_willing_to_wait');
$reason = '';
$more_reason = '';
if ($will_wait == WillingToWaitContent::NOT_WILLING_TO_WAIT)
// validate and set job order object
$jo_status = JOStatus::PENDING;
$this->validateJobOrder($req, $error_array, $jo_status);
if (empty($error_array))
{
// get the reason and text
$reason = $req->request->get('no_wait_reason');
$more_reason = $req->request->get('not_wait_notes');
}
$this->setJobOrderObject($req, $jo, $jo_status);
// check if service is battery sales
$stype = $req->request->get('service_type');
$no_trade_in_reason = '';
if ($stype == ServiceType::BATTERY_REPLACEMENT_NEW)
{
// check if trade in
$is_trade_in = $req->request->get('invoice_trade_in_type');
if (empty($is_trade_in))
{
$no_trade_in_reason = $req->request->get('no_trade_in_reason');
if (empty($no_trade_in_reason))
$error_array['no_trade_in_reason'] = 'No trade in reason required.';
}
}
// TODO: check status before saving since JO might already
// have a status that needs to be retained
if (empty($error_array)) {
// get current user
$user = $this->security->getUser();
// coordinates
$point = new Point($req->request->get('coord_lng'), $req->request->get('coord_lat'));
// set and save values
$jo->setDateSchedule(DateTime::createFromFormat("d M Y h:i A", $req->request->get('date_schedule_date') . " " . $req->request->get('date_schedule_time')))
->setCoordinates($point)
->setAdvanceOrder($req->request->get('flag_advance') ?? false)
->setServiceType($stype)
->setWarrantyClass($req->request->get('warranty_class'))
->setCustomer($cust_vehicle->getCustomer())
->setCustomerVehicle($cust_vehicle)
->setSource($req->request->get('source'))
->setStatus(JOStatus::PENDING)
->setDeliveryInstructions($req->request->get('delivery_instructions'))
->setTier1Notes($req->request->get('tier1_notes'))
->setTier2Notes($req->request->get('tier2_notes'))
->setDeliveryAddress($req->request->get('delivery_address'))
->setORName($req->request->get('or_name'))
->setPromoDetail($req->request->get('promo_detail'))
->setModeOfPayment($req->request->get('mode_of_payment'))
->setLandmark($req->request->get('landmark'))
->setWillWait($req->request->get('flag_willing_to_wait'))
->setReasonNotWait($reason)
->setNotWaitingNotes($more_reason)
->setNoTradeInReason($no_trade_in_reason);
// check if user is null, meaning call to create came from API
if ($user != null)
{
$jo->setCreatedBy($user);
}
// check if reference JO is set and validate
if (!empty($req->request->get('ref_jo'))) {
// get reference JO
$ref_jo = $em->getRepository(JobOrder::class)->find($req->request->get('ref_jo'));
if (empty($ref_jo)) {
$error_array['ref_jo'] = 'Invalid reference job order specified.';
} else {
$jo->setReferenceJO($ref_jo);
}
}
// call service to generate job order and invoice
// call service to generate invoice
$invoice_items = $req->request->get('invoice_items', []);
$promo_id = $req->request->get('invoice_promo');
$invoice_change = $req->request->get('invoice_change', 0);
@ -460,27 +375,21 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
$error_array[$error->getPropertyPath()] = $error->getMessage();
}
// check if errors are found
if (empty($error_array))
{
// validated, no error. save the job order and customer
$em->persist($jo);
$em->persist($customer);
// the event
$event = new JOEvent();
$event->setDateHappen(new DateTime())
->setTypeID(JOEventType::CREATE)
->setJobOrder($jo);
if ($user != null)
{
$event->setUser($user);
}
$em->persist($event);
$em->flush();
// check if any errors were found
if (!empty($error_array)) {
// return validation failure response
return $this->json([
'success' => false,
'errors' => $error_array
], 422);
}
$em->persist($jo);
$em->persist($customer);
$this->jo_manager->processJobOrderEvents($jo, JOEventType::CREATE);
$em->flush();
}
$data['error_array'] = $error_array;
@ -495,30 +404,12 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
// check service type
if ($jo->getServiceType() == ServiceType::BATTERY_REPLACEMENT_NEW)
{
$customer = $cust_vehicle->getCustomer();
// process customer tags
$customer_tags = $customer->getCustomerTagObjects();
if (!empty($customer_tags))
{
foreach ($customer_tags as $customer_tag)
{
if ($customer_tag->getID() == $jo->getInvoice()->getUsedCustomerTagId())
{
// remove associated entity
$customer->removeCustomerTag($customer_tag);
// log the availment of promo from customer
$created_by = $jo->getCreatedBy()->getUsername();
$cust_id = $jo->getCustomer()->getID();
$cust_fname = $jo->getCustomer()->getFirstName();
$cust_lname = $jo->getCustomer()->getLastName();
$jo_id = $jo->getID();
$invoice_id = $jo->getInvoice()->getID();
// TODO: check if we store total price of invoice or just the discounted amount
$amount = $jo->getInvoice()->getTotalPrice();
$this->promo_logger->logPromoInfo($created_by, $cust_id, $cust_fname, $cust_lname, $jo_id,
$invoice_id, $amount);
}
}
$username = $jo->getCreatedBy()->getUsername();
$this->jo_manager->removeCustomerTag($jo, $customer, $customer_tags, $username);
}
}
}
@ -541,69 +432,11 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
if (empty($obj))
throw $this->createNotFoundException('The item does not exist');
// check if lat and lng are provided
if (empty($req->request->get('coord_lng')) || empty($req->request->get('coord_lat'))) {
$error_array['coordinates'] = 'No map coordinates provided. Please click on a location on the map.';
}
// check if landmark is set
if (empty($req->request->get('landmark')))
$error_array['landmark'] = 'Landmark is required.';
// check if customer is not willing to wait
$will_wait = $req->request->get('flag_willing_to_wait');
$reason = '';
$more_reason = '';
if ($will_wait == WillingToWaitContent::NOT_WILLING_TO_WAIT)
// validate and set job order object
$this->validateJobOrder($req, $error_array, $obj->getStatus());
if (empty($error_array))
{
// get the reason and text
$reason = $req->request->get('no_wait_reason');
$more_reason = $req->request->get('not_wait_notes');
}
// check if service type is battery sales
$stype = $req->request->get('service_type');
$no_trade_in_reason = '';
if ($stype == ServiceType::BATTERY_REPLACEMENT_NEW)
{
// check if trade in
$is_trade_in = $req->request->get('invoice_trade_in_type');
if (empty($is_trade_in))
{
$no_trade_in_reason = $req->request->get('no_trade_in_reason');
if (empty($no_trade_in_reason))
$error_array['no_trade_in_reason'] = 'No trade in reason required.';
}
}
if (empty($error_array))
{
// get current user
$user = $this->security->getUser();
// coordinates
$point = new Point($req->request->get('coord_lng'), $req->request->get('coord_lat'));
// set and save values
$obj->setDateSchedule(DateTime::createFromFormat("d M Y h:i A", $req->request->get('date_schedule_date') . " " . $req->request->get('date_schedule_time')))
->setCoordinates($point)
->setAdvanceOrder($req->request->get('flag_advance') ?? false)
->setServiceType($stype)
->setWarrantyClass($req->request->get('warranty_class'))
->setSource($req->request->get('source'))
->setDeliveryInstructions($req->request->get('delivery_instructions'))
->setTier1Notes($req->request->get('tier1_notes'))
->setTier2Notes($req->request->get('tier2_notes'))
->setDeliveryAddress($req->request->get('delivery_address'))
->setORName($req->request->get('or_name'))
->setPromoDetail($req->request->get('promo_detail'))
->setModeOfPayment($req->request->get('mode_of_payment'))
->setLandmark($req->request->get('landmark'))
->setWillWait($req->request->get('flag_willing_to_wait'))
->setReasonNotWait($reason)
->setNotWaitingNotes($more_reason)
->setNoTradeInReason($no_trade_in_reason);
$this->setJobOrderObject($req, $obj, $obj->getStatus());
// did they change invoice?
$invoice_items = $req->request->get('invoice_items', []);
@ -631,20 +464,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
], 422);
}
// the event
$event = new JOEvent();
$event->setDateHappen(new DateTime())
->setTypeID(JOEventType::OPEN_EDIT)
->setJobOrder($obj);
error_log('open edit?');
if ($user != null)
{
$event->setUser($user);
}
$em->persist($event);
$this->jo_manager->processJobOrderEvents($obj, JOEventType::OPEN_EDIT);
// validated! save the entity
$em->flush();
@ -658,7 +478,6 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
}
return $data;
}
// dispatch job order
@ -668,7 +487,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
$em = $this->em;
$obj = $em->getRepository(JobOrder::class)->find($id);
$processor = $obj->getProcessedBy();
$user = $this->security->getUser();;
$user = $this->security->getUser();
// check if we're the one processing, return error otherwise
if ($processor == null)
@ -692,87 +511,24 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
// $error_array['dispatch'] = 'Could not dispatch. Job Order is not pending.';
}
// check if lat and lng are provided
if (empty($req->request->get('coord_lng')) || empty($req->request->get('coord_lat')))
{
$error_array['coordinates'] = 'No map coordinates provided. Please click on a location on the map.';
}
// validate
$jo_status = JOStatus::RIDER_ASSIGN;
$this->validateJobOrder($req, $error_array, $jo_status);
// check if hub is set
if (empty($req->request->get('hub')))
{
$error_array['hub'] = 'No hub selected.';
}
else
{
// get hub
$hub = $em->getRepository(Hub::class)->find($req->request->get('hub'));
if (empty($hub))
{
$error_array['hub'] = 'Invalid hub specified.';
}
}
// check facilitated type
$fac_type = $req->request->get('facilitated_type');
if (!empty($fac_type))
{
if (!FacilitatedType::validate($fac_type))
$fac_type = null;
}
else
$fac_type = null;
// check facilitated by
$fac_by_id = $req->request->get('facilitated_by');
$fac_by = null;
if (!empty($fac_by_id))
{
$fac_by = $em->getRepository(Hub::class)->find($fac_by_id);
if (empty($fac_by))
$fac_by = null;
}
// check if landmark is set
if (empty($req->request->get('landmark')))
$error_array['landmark'] = 'Landmark is required.';
// check if customer is not willing to wait
$will_wait = $req->request->get('flag_willing_to_wait');
$reason = '';
$more_reason = '';
if ($will_wait == WillingToWaitContent::NOT_WILLING_TO_WAIT)
{
// get the reason and text
$reason = $req->request->get('no_wait_reason');
$more_reason = $req->request->get('not_wait_notes');
}
if (empty($error_array))
{
// coordinates
$point = new Point($req->request->get('coord_lng'), $req->request->get('coord_lat'));
// set and save values
$obj->setDateSchedule(DateTime::createFromFormat("d M Y h:i A", $req->request->get('date_schedule_date') . " " . $req->request->get('date_schedule_time')))
->setCoordinates($point)
->setAdvanceOrder($req->request->get('flag_advance') ?? false)
->setServiceType($req->request->get('service_type'))
->setWarrantyClass($req->request->get('warranty_class'))
->setSource($req->request->get('source'))
->setStatus(JOStatus::RIDER_ASSIGN)
->setDeliveryInstructions($req->request->get('delivery_instructions'))
->setTier1Notes($req->request->get('tier1_notes'))
->setTier2Notes($req->request->get('tier2_notes'))
->setDeliveryAddress($req->request->get('delivery_address'))
->setFacilitatedType($fac_type)
->setFacilitatedBy($fac_by)
->setHub($hub)
->setLandmark($req->request->get('landmark'))
->setWillWait($req->request->get('flag_willing_to_wait'))
->setReasonNotWait($reason)
->setNotWaitingNotes($more_reason);
$this->setJobOrderObject($req, $obj, $jo_status);
// validate
$errors = $this->validator->validate($obj);
@ -781,22 +537,17 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
foreach ($errors as $error) {
$error_array[$error->getPropertyPath()] = $error->getMessage();
}
}
if (empty($error_array))
{
// the event
$event = new JOEvent();
$event->setDateHappen(new DateTime())
->setTypeID(JOEventType::HUB_ASSIGN)
->setJobOrder($obj);
if ($user != null)
{
$event->setUser($user);
// check if any errors were found
if (!empty($error_array)) {
// return validation failure response
return $this->json([
'success' => false,
'errors' => $error_array
], 422);
}
$em->persist($event);
$this->jo_manager->processJobOrderEvents($obj, JOEventType::HUB_ASSIGN);
// validated! save the entity
$em->flush();
@ -1517,157 +1268,6 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
}
// CMB code
public function processOneStepJobOrder(Request $req, $id)
{
// initialize error list
$error_array = [];
$em = $this->em;
$jo = $em->getRepository(JobOrder::class)->find($id);
if (empty($jo))
{
// new job order
$jo = new JobOrder();
}
// check if lat and lng are provided
if (empty($req->request->get('coord_lng')) || empty($req->request->get('coord_lat'))) {
$error_array['coordinates'] = 'No map coordinates provided. Please click on a location on the map.';
}
// check if customer vehicle is set
if (empty($req->request->get('customer_vehicle'))) {
$error_array['customer_vehicle'] = 'No vehicle selected.';
} else {
// get customer vehicle
$cust_vehicle = $em->getRepository(CustomerVehicle::class)->find($req->request->get('customer_vehicle'));
if (empty($cust_vehicle)) {
$error_array['customer_vehicle'] = 'Invalid vehicle specified.';
}
}
// check if hub AND rider is selected
if ((empty($req->request->get('hub_id'))) &&
(empty($req->request->get('rider_id')))) {
$error_array['hub'] = 'No hub selected.';
} else {
if (empty($req->request->get('rider_id'))) {
$error_array['rider'] = 'No rider selected.';
} else {
// get hub
$hub = $em->getRepository(Hub::class)->find($req->request->get('hub_id'));
if (empty($hub)) {
$error_array['hub'] = 'Invalid hub specified.';
} else {
// get rider
$rider = $em->getRepository(Rider::class)->find($req->request->get('rider_id'));
if (empty($rider)) {
$error_array['rider'] = 'Invalid rider specified.';
}
}
}
}
if (empty($error_array))
{
// get current user
$user = $this->security->getUser();
// coordinates
$point = new Point($req->request->get('coord_lng'), $req->request->get('coord_lat'));
$stype = $req->request->get('service_type');
// set and save values
$jo->setDateSchedule(DateTime::createFromFormat("d M Y h:i A", $req->request->get('date_schedule_date') . " " . $req->request->get('date_schedule_time')))
->setCoordinates($point)
->setAdvanceOrder($req->request->get('flag_advance') ?? false)
->setServiceType($stype)
->setWarrantyClass($req->request->get('warranty_class'))
->setCustomer($cust_vehicle->getCustomer())
->setCustomerVehicle($cust_vehicle)
->setSource($req->request->get('source'))
->setStatus(JOStatus::ASSIGNED)
->setDeliveryInstructions($req->request->get('delivery_instructions'))
->setTier1Notes($req->request->get('tier1_notes'))
->setTier2Notes($req->request->get('tier2_notes'))
->setDeliveryAddress($req->request->get('delivery_address'))
->setORName($req->request->get('or_name'))
->setPromoDetail($req->request->get('promo_detail'))
->setModeOfPayment($req->request->get('mode_of_payment'))
->setLandmark($req->request->get('landmark'))
->setHub($hub)
->setRider($rider);
// check if user is null, meaning call to create came from API
if ($user != null)
{
$jo->setCreatedBy($user);
}
// check if reference JO is set and validate
if (!empty($req->request->get('ref_jo'))) {
// get reference JO
$ref_jo = $em->getRepository(JobOrder::class)->find($req->request->get('ref_jo'));
if (empty($ref_jo)) {
$error_array['ref_jo'] = 'Invalid reference job order specified.';
} else {
$jo->setReferenceJO($ref_jo);
}
}
// call service to generate job order and invoice
$invoice_items = $req->request->get('invoice_items', []);
$promo_id = $req->request->get('invoice_promo');
$invoice_change = $req->request->get('invoice_change', 0);
// check if invoice changed
if ($invoice_change)
{
$this->ic->generateInvoiceCriteria($jo, $promo_id, $invoice_items, $error_array);
}
// validate
$errors = $this->validator->validate($jo);
// add errors to list
foreach ($errors as $error) {
$error_array[$error->getPropertyPath()] = $error->getMessage();
}
// check if errors are found
if (empty($error_array))
{
// validated, no error. save the job order
$em->persist($jo);
// the event
$event = new JOEvent();
$event->setDateHappen(new DateTime())
->setTypeID(JOEventType::CREATE)
->setJobOrder($jo);
if ($user != null)
{
$event->setUser($user);
}
$em->persist($event);
$em->flush();
}
}
return $error_array;
}
// initialize incoming job order form
public function initializeIncomingForm()
{
@ -1684,83 +1284,6 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
return $params;
}
// CMB code
public function initializeOneStepForm()
{
$params['obj'] = new JobOrder();
$params['mode'] = 'onestep';
$this->fillDropdownParameters($params);
$this->fillFormTags($params);
// get template to display
$params['template'] = $this->getTwigTemplate('jo_onestep');
// return params
return $params;
}
// CMB code
public function initializeOneStepEditForm($id, $map_tools)
{
$em = $this->em;
$obj = $em->getRepository(JobOrder::class)->find($id);
$params['obj'] = $obj;
$params['mode'] = 'onestep-edit';
$params['cvid'] = $obj->getCustomerVehicle()->getID();
$params['vid'] = $obj->getCustomerVehicle()->getVehicle()->getID();
$this->fillDropdownParameters($params);
$this->fillFormTags($params);
// get the hubs
// TODO: move this snippet to a function
$hubs = $map_tools->getClosestHubs($obj->getCoordinates(), 50, date("H:i:s"));
$params['hubs'] = [];
// format duration and distance into friendly time
foreach ($hubs as $hub) {
// duration
$seconds = $hub['duration'];
if (!empty($seconds) && $seconds > 0) {
$hours = floor($seconds / 3600);
$minutes = ceil(($seconds / 60) % 60);
$hub['duration'] = ($hours > 0 ? number_format($hours) . " hr" . ($hours > 1 ? "s" : '') . ($minutes > 0 ? ", " : '') : '') . ($minutes > 0 ? number_format($minutes) . " min" . ($minutes > 1 ? "s" : '') : '');
} else {
$hub['duration'] = false;
}
// distance
$meters = $hub['distance'];
if (!empty($meters) && $meters > 0) {
$hub['distance'] = round($meters / 1000) . " km";
} else {
$hub['distance'] = false;
}
// counters
$hub['rider_count'] = count($hub['hub']->getAvailableRiders());
$hub['jo_count'] = count($hub['hub']->getForAssignmentJobOrders());
// check for rejection
$hub['flag_rejected'] = false;
$hub_id = $hub['hub']->getID();
$params['hubs'][] = $hub;
}
// get template to display
$params['template'] = $this->getTwigTemplate('jo_onestep_edit_form');
return $params;
}
// initialize open edit job order form
public function initializeOpenEditForm($id)
{
@ -2916,17 +2439,6 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
$params['ftags']['invoice_edit'] = true;
$params['ftags']['preset_vehicle'] = true;
break;
case 'onestep':
$params['ftags']['vehicle_dropdown'] = true;
$params['ftags']['set_map_coordinate'] = false;
$params['ftags']['invoice_edit'] = true;
$params['ftags']['ticket_table'] = false;
$params['ftags']['cancel_button'] = false;
break;
case 'onestep-edit':
$params['ftags']['invoice_edit'] = true;
$params['ftags']['preset_vehicle'] = true;
break;
}
}
@ -3243,6 +2755,177 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
}
}
protected function validateJobOrder(Request $req, &$error_array, $jo_status)
{
// new job order
if ($jo_status == JOStatus::PENDING)
{
// check if service is battery sales
$stype = $req->request->get('service_type');
if ($stype == ServiceType::BATTERY_REPLACEMENT_NEW)
{
// check if trade in
$is_trade_in = $req->request->get('invoice_trade_in_type');
if (empty($is_trade_in))
{
if (empty($req->request->get('no_trade_in_reason')))
$error_array['no_trade_in_reason'] = 'No trade in reason required.';
}
}
// check if customer vehicle is set
if (empty($req->request->get('customer_vehicle')))
$error_array['customer_vehicle'] = 'No vehicle selected.';
else
{
// get customer vehicle
$cust_vehicle = $this->em->getRepository(CustomerVehicle::class)->find($req->request->get('customer_vehicle'));
if (empty($cust_vehicle))
$error_array['customer_vehicle'] = 'Invalid vehicle specified.';
}
// check if reference JO is set and validate
if (!empty($req->request->get('ref_jo')))
{
// get reference JO
$ref_jo = $em->getRepository(JobOrder::class)->find($req->request->get('ref_jo'));
if (empty($ref_jo))
$error_array['ref_jo'] = 'Invalid reference job order specified.';
}
}
// assign hub/dispatch job order
if ($jo_status == JOStatus::RIDER_ASSIGN)
{
// check if hub is set
if (empty($req->request->get('hub')))
$error_array['hub'] = 'No hub selected.';
else
{
// get hub
$hub = $this->em->getRepository(Hub::class)->find($req->request->get('hub'));
if (empty($hub))
$error_array['hub'] = 'Invalid hub specified.';
}
}
// check if lat and lng are provided
if (empty($req->request->get('coord_lng')) || empty($req->request->get('coord_lat')))
$error_array['coordinates'] = 'No map coordinates provided. Please click on a location on the map.';
// check if landmark is set
if (empty($req->request->get('landmark')))
$error_array['landmark'] = 'Landmark is required.';
}
protected function setJobOrderObject(Request $req, JobOrder $jo, $jo_status)
{
// new job order
if ($jo_status == JOStatus::PENDING)
{
// these are fields that are only set when new job order
// get customer vehicle
$cust_vehicle = $this->em->getRepository(CustomerVehicle::class)->find($req->request->get('customer_vehicle'));
$jo->setCustomer($cust_vehicle->getCustomer())
->setCustomerVehicle($cust_vehicle)
->setORName($req->request->get('or_name'))
->setPromoDetail($req->request->get('promo_detail'));
// get current user
$user = $this->security->getUser();
if ($user != null)
$jo->setCreatedBy($user);
// check if reference JO is set
if (!empty($req->request->get('ref_jo'))) {
// get reference JO
$ref_jo = $this->em->getRepository(JobOrder::class)->find($req->request->get('ref_jo'));
$jo->setReferenceJO($ref_jo);
}
}
// dispatch/assign hub
if ($jo_status == JOStatus::RIDER_ASSIGN)
{
// this means JO is in dispatch/assign hub
// for dispatch, set the hub and facilitated by and facilitated type
// check facilitated type
$fac_type = $req->request->get('facilitated_type');
if (!empty($fac_type))
{
if (!FacilitatedType::validate($fac_type))
$fac_type = null;
}
else
$fac_type = null;
// check facilitated by
$fac_by_id = $req->request->get('facilitated_by');
$fac_by = null;
if (!empty($fac_by_id))
{
$fac_by = $this->em->getRepository(Hub::class)->find($fac_by_id);
if (empty($fac_by))
$fac_by = null;
}
// get hub
$hub = $this->em->getRepository(Hub::class)->find($req->request->get('hub'));
$jo->setFacilitatedType($fac_type)
->setFacilitatedBy($fac_by)
->setHub($hub);
}
// check if customer is not willing to wait
$will_wait = $req->request->get('flag_willing_to_wait');
$reason = '';
$more_reason = '';
if ($will_wait == WillingToWaitContent::NOT_WILLING_TO_WAIT)
{
// get the reason and text
$reason = $req->request->get('no_wait_reason');
$more_reason = $req->request->get('not_wait_notes');
}
// check if service is battery sales
$stype = $req->request->get('service_type');
$no_trade_in_reason = '';
if ($stype == ServiceType::BATTERY_REPLACEMENT_NEW)
{
// check if trade in
$is_trade_in = $req->request->get('invoice_trade_in_type');
if (empty($is_trade_in))
$no_trade_in_reason = $req->request->get('no_trade_in_reason');
}
// coordinates
$point = new Point($req->request->get('coord_lng'), $req->request->get('coord_lat'));
// set and save values
$jo->setDateSchedule(DateTime::createFromFormat("d M Y h:i A", $req->request->get('date_schedule_date') . " " . $req->request->get('date_schedule_time')))
->setCoordinates($point)
->setAdvanceOrder($req->request->get('flag_advance') ?? false)
->setServiceType($stype)
->setWarrantyClass($req->request->get('warranty_class'))
->setSource($req->request->get('source'))
->setDeliveryInstructions($req->request->get('delivery_instructions'))
->setTier1Notes($req->request->get('tier1_notes'))
->setTier2Notes($req->request->get('tier2_notes'))
->setDeliveryAddress($req->request->get('delivery_address'))
->setModeOfPayment($req->request->get('mode_of_payment'))
->setLandmark($req->request->get('landmark'))
->setWillWait($req->request->get('flag_willing_to_wait'))
->setReasonNotWait($reason)
->setNotWaitingNotes($more_reason)
->setNoTradeInReason($no_trade_in_reason)
->setStatus($jo_status);
}
public function getEditRoute($jo_id, $tier)
{
if (empty($tier))

View file

@ -25,9 +25,6 @@ interface JobOrderHandlerInterface
// generate job order
public function generateJobOrder(Request $req, int $id);
// process one step job order
public function processOneStepJobOrder(Request $req, int $id);
// dispatch job order
public function dispatchJobOrder(Request $req, int $id, MQTTClient $mclient);
@ -82,12 +79,6 @@ interface JobOrderHandlerInterface
// initialize rider form
public function initializeRiderForm(int $id);
// initialize one step form
public function initializeOneStepForm();
// initialize one step edit form
public function initializeOneStepEditForm(int $id, MapTools $map_tools);
// generate pdf form for job order
public function generatePDFForm(Request $req, int $id, string $proj_path);

View file

@ -2,19 +2,38 @@
namespace App\Service;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Security;
use App\Entity\JobOrder;
use App\Entity\JOEvent;
use App\Entity\User;
use App\Entity\Customer;
use App\Ramcar\ServiceType;
use App\Ramcar\JOStatus;
use App\Ramcar\JOEventType;
use Doctrine\ORM\EntityManagerInterface;
use DateTime;
class JobOrderManager
{
protected $em;
protected $security;
protected $rah;
protected $mclient;
protected $promo_logger;
public function __construct(EntityManagerInterface $em)
public function __construct(EntityManagerInterface $em, Security $security,
RiderAssignmentHandlerInterface $rah, MQTTClient $mclient,
PromoLogger $promo_logger)
{
$this->em = $em;
$this->security = $security;
$this->rah = $rah;
$this->mclient = $mclient;
$this->promo_logger = $promo_logger;
}
public function fulfillJobOrder($jo_id)
@ -51,4 +70,98 @@ class JobOrderManager
$this->em->flush();
}
}
public function processJobOrderEvents(JobOrder $jo, $jo_event_type)
{
$em = $this->em;
// check for the jo event type
if ($jo_event_type == JOEventType::CREATE)
{
// add event log for JO
$event = new JOEvent();
$event->setDateHappen(new DateTime())
->setTypeID($jo_event_type)
->setJobOrder($jo);
$user = $this->security->getUser();
// check if user is User or APIUser
if ($user instanceof User)
$event->setUser($user);
$em->persist($event);
// check for JO status for additional events
// (1) when mobile app gets a new JO, finds a hub and assigns a rider
if ($jo->getStatus() == JOStatus::ASSIGNED)
{
// add event logs for hub and rider assignments
$hub_assign_event = new JOEvent();
$hub_assign_event->setDateHappen(new DateTime())
->setTypeID(JOEventType::HUB_ASSIGN)
->setJobOrder($jo);
$em->persist($hub_assign_event);
$rider_assign_event = new JOEvent();
$rider_assign_event->setDateHappen(new DateTime())
->setTypeID(JOEventType::RIDER_ASSIGN)
->setJobOrder($jo);
$em->persist($rider_assign_event);
}
// (2) when mobile app gets a new JO, finds a hub but no rider
if ($jo->getStatus() == JOStatus::RIDER_ASSIGN)
{
// add event logs for hub assignments
$hub_assign_event = new JOEvent();
$hub_assign_event->setDateHappen(new DateTime())
->setTypeID(JOEventType::HUB_ASSIGN)
->setJobOrder($jo);
$em->persist($hub_assign_event);
}
}
else
{
// TODO: check for other JO event types. See if all other event types have no special processing
// cancel, edit, dispatch are the same
// add event log for JO
$event = new JOEvent();
$event->setDateHappen(new DateTime())
->setTypeID($jo_event_type)
->setJobOrder($jo);
$user = $this->security->getUser();
// check if user is User or APIUser
if ($user instanceof User)
$event->setUser($user);
$em->persist($event);
}
}
public function removeCustomerTag(JobOrder $jo, Customer $customer, $customer_tags, $username)
{
foreach ($customer_tags as $customer_tag)
{
if ($customer_tag->getID() == $jo->getInvoice()->getUsedCustomerTagId())
{
// remove associated entity
$customer->removeCustomerTag($customer_tag);
// log the availment of promo from customer
$created_by = $username;
$cust_id = $jo->getCustomer()->getID();
$cust_fname = $jo->getCustomer()->getFirstName();
$cust_lname = $jo->getCustomer()->getLastName();
$jo_id = $jo->getID();
$invoice_id = $jo->getInvoice()->getID();
// TODO: check if we store total price of invoice or just the discounted amount
$amount = $jo->getInvoice()->getTotalPrice();
$this->promo_logger->logPromoInfo($created_by, $cust_id, $cust_fname, $cust_lname, $jo_id,
$invoice_id, $amount);
}
}
}
}

View file

@ -0,0 +1,110 @@
<?php
namespace App\Service;
use Doctrine\ORM\EntityManagerInterface;
use App\Entity\MobileUser;
use App\Entity\Warranty;
use App\Entity\JobOrder;
use App\Ramcar\JOStatus;
class MobileAPIHandler
{
protected $em;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
public function findMobileUser($user_id)
{
// get capi user to link to mobile user
$mobile_user = $this->em->getRepository(MobileUser::class)->findOneBy(['capi_user_id' => $user_id]);
return $mobile_user;
}
public function findWarranty($plate_number)
{
// NOTE: Modify the search for the latest warranty. This seems hacky.
// get latest warranty using plate number
$warranty_results = $this->em->getRepository(Warranty::class)->findBy(['plate_number' => $plate_number],
['date_create' => 'desc']);
$warr = [];
// check if warranty_results is empty
if (empty($warranty_results))
return $warr;
// get first entry
$warranty = current($warranty_results);
// check for null values for battery and date claim and date expire
$batt_model = '';
$batt_size = '';
$sap_batt = '';
$claim_date = '';
$expiry_date = '';
if (!(is_null($warranty->getBatteryModel()))) {
$batt_model = $warranty->getBatteryModel()->getName();
}
if (!(is_null($warranty->getBatterySize()))) {
$batt_size = $warranty->getBatterySize()->getName();
}
if (!(is_null($warranty->getSAPBattery()))) {
$sap_batt = $warranty->getSAPBattery()->getID();
}
if (!(is_null($warranty->getDateClaim()))) {
$claim_date = $warranty->getDateClaim()->format("d M Y");
}
if (!(is_null($warranty->getDateExpire()))) {
$expiry_date = $warranty->getDateExpire()->format("d M Y");
}
$warr[] = [
'id' => $warranty->getID(),
'serial' => $warranty->getSerial(),
'warranty_class' => $warranty->getWarrantyClass(),
'plate_number' => $warranty->getPlateNumber(),
'first_name' => $warranty->getFirstName(),
'last_name' => $warranty->getLastName(),
'mobile_number' => $warranty->getMobileNumber(),
'battery_model' => $batt_model,
'battery_size' => $batt_size,
'sap_battery' => $sap_batt,
'status' => $warranty->getStatus(),
'date_create' => $warranty->getDateCreate()->format("d M Y g:i A"),
'date_purchase' => $warranty->getDatePurchase()->format("d M Y"),
'date_expire' => $expiry_date,
'date_claim' => $claim_date,
'claim_from' => $warranty->getClaimedFrom(),
'is_activated' => $warranty->isActivated() ? 1 : 0,
];
return $warr;
}
public function getBatteryImageURL($req, $batt, $battery_image_url)
{
// TODO: workaround for now, we get static image of battery based on model name
$filename = trim(strtolower($batt->getModel()->getName())) . '_mobile.jpg';
$file_path = $req->getSchemeAndHttpHost() . $battery_image_url . '/' . $filename;
return $file_path;
}
public function getOngoingJobOrders($cust)
{
$ongoing_jos = $this->em->getRepository(JobOrder::class)->findBy([
'customer' => $cust,
'status' => [JOStatus::PENDING, JOStatus::RIDER_ASSIGN, JOStatus::IN_TRANSIT, JOStatus::ASSIGNED, JOStatus::IN_PROGRESS],
]);
return $ongoing_jos;
}
}