diff --git a/.env.dist b/.env.dist index 509fee86..29a870ff 100644 --- a/.env.dist +++ b/.env.dist @@ -14,9 +14,15 @@ APP_SECRET=b344cd6cd151ae1d61403ed55806c5ce # For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db" # Configure your db driver and server_version in config/packages/doctrine.yaml DATABASE_URL=mysql://db_user:db_password@127.0.0.1:3306/db_name +LOGGING_DATABASE_URL=mysql://db_user:db_password@127.0.0.1:3306/db_logging ###< doctrine/doctrine-bundle ### GMAPS_API_KEY=insert_gmapsapikey_here +# influxdb +INFLUXDB_HOST=127.0.0.1 +INFLUXDB_PORT=8086 +INFLUXDB_DB=logging_db + # rising tide sms gateway RT_USER=rt_user RT_PASS=rt_pass diff --git a/composer.json b/composer.json index 7219d070..01f26a5e 100644 --- a/composer.json +++ b/composer.json @@ -14,6 +14,7 @@ "data-dog/audit-bundle": "^0.1.10", "edwinhoksberg/php-fcm": "^1.0", "guzzlehttp/guzzle": "^6.3", + "influxdb/influxdb-php": "^1.15", "predis/predis": "^1.1", "sensio/framework-extra-bundle": "^5.1", "setasign/fpdf": "^1.8", diff --git a/composer.lock b/composer.lock index 08ee90e0..d3656b7d 100644 --- a/composer.lock +++ b/composer.lock @@ -1,10 +1,10 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b101ecfbc1f6f2270f0e8ad326035b7e", + "content-hash": "cbde0e7f1fa49277c6196a3c677c3a51", "packages": [ { "name": "catalyst/auth-bundle", @@ -1836,6 +1836,67 @@ ], "time": "2019-07-01T23:21:34+00:00" }, + { + "name": "influxdb/influxdb-php", + "version": "1.15.0", + "source": { + "type": "git", + "url": "https://github.com/influxdata/influxdb-php.git", + "reference": "bf3415f81962e1ab8c939bc1a08a85f500bead35" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/influxdata/influxdb-php/zipball/bf3415f81962e1ab8c939bc1a08a85f500bead35", + "reference": "bf3415f81962e1ab8c939bc1a08a85f500bead35", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.0", + "php": "^5.5 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7" + }, + "suggest": { + "ext-curl": "Curl extension, needed for Curl driver", + "stefanotorresi/influxdb-php-async": "An asyncronous client for InfluxDB, implemented via ReactPHP." + }, + "type": "library", + "autoload": { + "psr-4": { + "InfluxDB\\": "src/InfluxDB" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gianluca Arbezzano", + "email": "gianarb92@gmail.com" + }, + { + "name": "Daniel Martinez", + "email": "danimartcas@hotmail.com" + }, + { + "name": "Stephen Hoogendijk", + "email": "stephen@tca0.nl" + } + ], + "description": "InfluxDB client library for PHP", + "keywords": [ + "client", + "influxdata", + "influxdb", + "influxdb class", + "influxdb client", + "influxdb library", + "time series" + ], + "time": "2019-05-30T00:15:14+00:00" + }, { "name": "jdorn/sql-formatter", "version": "v1.2.17", diff --git a/config/acl.yaml b/config/acl.yaml index bfd6c6cc..653fe458 100644 --- a/config/acl.yaml +++ b/config/acl.yaml @@ -21,6 +21,10 @@ access_keys: label: Super Admin Role - id: user.profile label: User Profile + - id: user.logs + label: User Logs + - id: user.change.history + label: User Change History - id: role label: Role Access acls: diff --git a/config/cmb.services.yaml b/config/cmb.services.yaml index 5f24e525..cd07558d 100644 --- a/config/cmb.services.yaml +++ b/config/cmb.services.yaml @@ -12,6 +12,7 @@ parameters: app_access_key: 'access_keys' cvu_brand_id: "%env(CVU_BRAND_ID)%" country_code: "%env(COUNTRY_CODE)%" + log_db: "%env(INFLUXDB_DB)%" services: # default configuration for services in *this* file @@ -202,6 +203,12 @@ services: #App\Service\GISManagerInterface: "@App\\Service\\GISManager\\Bing" App\Service\GISManagerInterface: "@App\\Service\\GISManager\\OpenStreet" #App\Service\GISManagerInterface: "@App\\Service\\GISManager\\Google" + + # influxdb + InfluxDB\Client: + arguments: ['%env(INFLUXDB_HOST)%', '%env(INFLUXDB_PORT)%'] + InfluxDB\Database: + arguments: ['%env(INFLUXDB_DB)%', "@InfluxDB\\Client"] App\EventListener\JobOrderActiveCacheListener: arguments: @@ -229,6 +236,28 @@ services: $loc_key: "%env(LOCATION_RIDER_ACTIVE_KEY)%" $status_key: "%env(STATUS_RIDER_KEY)%" + App\EventListener\JobOrderStatusListener: + arguments: + $wh: "@App\\Service\\WarrantyHandler" + tags: + - name: 'doctrine.orm.entity_listener' + event: 'postUpdate' + entity: 'App\Entity\JobOrder' + - name: 'doctrine.orm.entity_listener' + event: 'postPersist' + entity: 'App\Entity\JobOrder' + + App\EventListener\EntityListener: + arguments: + $token_storage: "@security.token_storage" + $log_db: "@InfluxDB\\Database" + $entities: ['App\Entity\User', 'App\Entity\Role', 'App\Entity\Partner'] + tags: + - name: 'doctrine.event_listener' + event: 'onFlush' + - name: 'doctrine.event_listener' + event: 'postPersist' + # API logging App\EventSubscriber\LogSubscriber: arguments: diff --git a/config/packages/doctrine.yaml b/config/packages/doctrine.yaml index c154fbc2..b1b6d947 100644 --- a/config/packages/doctrine.yaml +++ b/config/packages/doctrine.yaml @@ -19,7 +19,6 @@ doctrine: point: CrEOF\Spatial\DBAL\Types\Geometry\PointType polygon: CrEOF\Spatial\DBAL\Types\Geometry\PolygonType linestring: CrEOF\Spatial\DBAL\Types\Geometry\LineStringType - multipolygon: CrEOF\Spatial\DBAL\Types\Geometry\MultiPolygonType orm: auto_generate_proxy_classes: '%kernel.debug%' naming_strategy: doctrine.orm.naming_strategy.underscore diff --git a/config/resq.services.yaml b/config/resq.services.yaml index 284b7b73..1e7797b0 100644 --- a/config/resq.services.yaml +++ b/config/resq.services.yaml @@ -12,6 +12,7 @@ parameters: app_access_key: 'access_keys' cvu_brand_id: "%env(CVU_BRAND_ID)%" country_code: "%env(COUNTRY_CODE)%" + log_db: "%env(INFLUXDB_DB)%" services: # default configuration for services in *this* file @@ -201,7 +202,13 @@ services: #App\Service\GISManagerInterface: "@App\\Service\\GISManager\\Bing" App\Service\GISManagerInterface: "@App\\Service\\GISManager\\OpenStreet" #App\Service\GISManagerInterface: "@App\\Service\\GISManager\\Google" - + + # influxdb + InfluxDB\Client: + arguments: ['%env(INFLUXDB_HOST)%', '%env(INFLUXDB_PORT)%'] + InfluxDB\Database: + arguments: ['%env(INFLUXDB_DB)%', "@InfluxDB\\Client"] + App\EventListener\JobOrderActiveCacheListener: arguments: $jo_cache: "@App\\Service\\JobOrderCache" @@ -228,6 +235,28 @@ services: $loc_key: "%env(LOCATION_RIDER_ACTIVE_KEY)%" $status_key: "%env(STATUS_RIDER_KEY)%" + App\EventListener\JobOrderStatusListener: + arguments: + $wh: "@App\\Service\\WarrantyHandler" + tags: + - name: 'doctrine.orm.entity_listener' + event: 'postUpdate' + entity: 'App\Entity\JobOrder' + - name: 'doctrine.orm.entity_listener' + event: 'postPersist' + entity: 'App\Entity\JobOrder' + + App\EventListener\EntityListener: + arguments: + $token_storage: "@security.token_storage" + $log_db: "@InfluxDB\\Database" + $entities: ['App\Entity\User', 'App\Entity\Role', 'App\Entity\Partner'] + tags: + - name: 'doctrine.event_listener' + event: 'onFlush' + - name: 'doctrine.event_listener' + event: 'postPersist' + # inventory manager App\Service\InventoryManager: arguments: diff --git a/config/routes/user.yaml b/config/routes/user.yaml index 5b8dedbe..4b0bb93f 100644 --- a/config/routes/user.yaml +++ b/config/routes/user.yaml @@ -41,3 +41,23 @@ user_profile_submit: path: /profile controller: App\Controller\UserController::profileSubmit methods: [POST] + +user_view_logs_form: + path: /users/{id}/logs + controller: App\Controller\UserController::viewLogsForm + methods: [GET] + +user_view_logs: + path: /user/{id}/logs + controller: App\Controller\UserController::getAuditLogs + methods: [POST] + +user_view_change_history_form: + path: /users/{id}/change-history + controller: App\Controller\UserController::viewChangeHistoryForm + methods: [GET] + +user_view_change_history: + path: /user/{id}/change-history + controller: App\Controller\UserController::getChangeHistory + methods: [POST] diff --git a/config/services.yaml b/config/services.yaml index 284b7b73..fafcfdd8 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -12,6 +12,7 @@ parameters: app_access_key: 'access_keys' cvu_brand_id: "%env(CVU_BRAND_ID)%" country_code: "%env(COUNTRY_CODE)%" + log_db: "%env(INFLUXDB_DB)%" services: # default configuration for services in *this* file @@ -21,7 +22,7 @@ services: 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\: @@ -201,6 +202,12 @@ services: #App\Service\GISManagerInterface: "@App\\Service\\GISManager\\Bing" App\Service\GISManagerInterface: "@App\\Service\\GISManager\\OpenStreet" #App\Service\GISManagerInterface: "@App\\Service\\GISManager\\Google" + + # influxdb + InfluxDB\Client: + arguments: ['%env(INFLUXDB_HOST)%', '%env(INFLUXDB_PORT)%'] + InfluxDB\Database: + arguments: ['%env(INFLUXDB_DB)%', "@InfluxDB\\Client"] App\EventListener\JobOrderActiveCacheListener: arguments: @@ -228,6 +235,28 @@ services: $loc_key: "%env(LOCATION_RIDER_ACTIVE_KEY)%" $status_key: "%env(STATUS_RIDER_KEY)%" + App\EventListener\JobOrderStatusListener: + arguments: + $wh: "@App\\Service\\WarrantyHandler" + tags: + - name: 'doctrine.orm.entity_listener' + event: 'postUpdate' + entity: 'App\Entity\JobOrder' + - name: 'doctrine.orm.entity_listener' + event: 'postPersist' + entity: 'App\Entity\JobOrder' + + App\EventListener\EntityListener: + arguments: + $token_storage: "@security.token_storage" + $log_db: "@InfluxDB\\Database" + $entities: ['App\Entity\User', 'App\Entity\Role', 'App\Entity\Partner'] + tags: + - name: 'doctrine.event_listener' + event: 'onFlush' + - name: 'doctrine.event_listener' + event: 'postPersist' + # inventory manager App\Service\InventoryManager: arguments: diff --git a/src/Controller/UserController.php b/src/Controller/UserController.php index d9488e81..39422e9a 100644 --- a/src/Controller/UserController.php +++ b/src/Controller/UserController.php @@ -15,6 +15,8 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Catalyst\MenuBundle\Annotation\Menu; +use InfluxDB\Client; + class UserController extends Controller { /** @@ -484,4 +486,67 @@ class UserController extends Controller ]); } } + + /** + * @Menu(selected="user_list") + */ + public function viewLogsForm($id) + { + $this->denyAccessUnlessGranted('user.logs', null, 'No access.'); + + $params['id'] = $id; + + // response + return $this->render('user/audit.log.html.twig', $params); + } + + public function getAuditLogs(Client $client, $id) + { + // fetch database + $log_db = $this->getParameter('log_db'); + $database = $client->selectDB($log_db); + + // query will return a resultset object + $query_string = 'SELECT * FROM entity_log WHERE "user" = ' . $id; + $result = $database->query($query_string); + + // get the points from the resultset, which is an array + $points = $result->getPoints(); + + return $this->json([ + 'data' => $points, + ]); + } + + /** + * @Menu(selected="user_list") + */ + public function viewChangeHistoryForm($id) + { + $this->denyAccessUnlessGranted('user.change.history', null, 'No access.'); + + $params['id'] = $id; + + // response + return $this->render('user/change.history.log.html.twig', $params); + } + + public function getChangeHistory(Client $client, $id) + { + // fetch database + $log_db = $this->getParameter('log_db'); + $database = $client->selectDB($log_db); + + // query will return a resultset object + $query_string = 'SELECT * FROM entity_log WHERE entity_id = \'' . $id . '\''; + $result = $database->query($query_string); + + // get the points from the resultset, which is an array + $points = $result->getPoints(); + + return $this->json([ + 'data' => $points, + ]); + } + } diff --git a/src/Entity/AuditableEntity.php b/src/Entity/AuditableEntity.php new file mode 100644 index 00000000..f06e4cd8 --- /dev/null +++ b/src/Entity/AuditableEntity.php @@ -0,0 +1,8 @@ + $this->getID(), + 'name' => $this->getName(), + 'acl_attributes' => $this->getACLAttributes(), + ]; + + $fields = json_encode($field_array); + + return $fields; + } } diff --git a/src/Entity/User.php b/src/Entity/User.php index a57afb97..1ffe5228 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -16,7 +16,7 @@ use Serializable; * @UniqueEntity("username") * @UniqueEntity("email") */ -class User extends BaseUser implements Serializable +class User extends BaseUser implements Serializable, AuditableEntity { /** * @ORM\Id @@ -309,4 +309,24 @@ class User extends BaseUser implements Serializable { return $this->partners_created; } + + public function fieldDump() + { + // get all fields and their values into an array + $field_array = [ + 'id' => $this->getID(), + 'username' => $this->getUsername(), + 'password' => $this->getPassword(), + 'first_name' => $this->getFirstName(), + 'last_name' => $this->getLastName(), + 'email' => $this->getEmail(), + 'contact_number' => $this->getContactNumber(), + 'roles' => $this->getRoles(), + 'hubs' => $this->getHubs(), + ]; + + $fields = json_encode($field_array); + + return $fields; + } } diff --git a/src/EventListener/EntityListener.php b/src/EventListener/EntityListener.php new file mode 100644 index 00000000..0a4ee0f4 --- /dev/null +++ b/src/EventListener/EntityListener.php @@ -0,0 +1,194 @@ +token_storage = $token_storage; + $this->log_db = $log_db; + + // reconstruct entity array with class name as keys + // with values of true + foreach ($entities as $entity) + { + $this->entities[$entity] = true; + } + } + + public function postPersist(LifecycleEventArgs $args) + { + $object = $args->getObject(); + + $object_class = get_class($object); + + if (isset($this->entities[$object_class])) + { + if ($object instanceof AuditableEntity) + { + // get user id for logging + $user = $this->token_storage->getToken()->getUser(); + $user_id = $user->getID(); + + // get entity name + //$obj_class = preg_replace('/.*\\\\/', '', $object_class); + + // get fields of object + $fields = $object->fieldDump(); + + $this->writeToLogDB($object_class, $object->getID(), 'create', $fields, $user_id); + } + else + error_log($object_class . ' does not implement the AuditableEntity interface.'); + } + } + + public function onFlush(OnFlushEventArgs $args) + { + $em = $args->getEntityManager(); + + // get date time of event for logging + //$event_time = new DateTime(); + + // get user for logging + $user = $this->token_storage->getToken()->getUser(); + $user_id = $user->getID(); + + $field_changes = []; + + $unit_of_work = $em->getUnitOfWork(); + $created_entities = $unit_of_work->getScheduledEntityInsertions(); + $deleted_entities = $unit_of_work->getScheduledEntityDeletions(); + $updated_entities = $unit_of_work->getScheduledEntityUpdates(); + $updated_collections = $unit_of_work->getScheduledCollectionUpdates(); + $deleted_collections = $unit_of_work->getScheduledCollectionDeletions(); + + // get updated fields. This doesn't include lists of other entities. + foreach ($updated_entities as $updated_entity) + { + // check if entity is in list of entities to log + $entity_class = get_class($updated_entity); + if (isset($this->entities[$entity_class])) + { + if ($updated_entity instanceof AuditableEntity) + { + // get entity name + //$obj_class = preg_replace('/.*\\\\/', '', $entity_class); + + $changeset = $unit_of_work->getEntityChangeSet($updated_entity); + + $entity_fields = array_keys($changeset); + foreach ($entity_fields as $field) + { + $values = $changeset[$field]; + + $old_value = $values[0]; + $new_value = $values[1]; + + $field_changes[$field] = [ + 'old_value' => $values[0], + 'new_value' => $values[1], + ]; + } + + $fields = json_encode($field_changes); + + $this->writeToLogDB($entity_class, $updated_entity->getID(), 'update', $fields, $user_id); + } + else + error_log($entity_class . ' does not implement the AuditableEntity interface.'); + } + } + + // get deleted objects + foreach ($deleted_entities as $deleted_entity) + { + // check if entity is in list of entities to log + $entity_class = get_class($deleted_entity); + if (isset($this->entities[$entity_class])) + { + if ($deleted_entity instanceof AuditableEntity) + { + // get entity name + //$obj_class = preg_replace('/.*\\\\/', '', get_class($deleted_entity)); + + $deleted_id = $deleted_entity->getID(); + + // get fields of deleted entity + $fields = $deleted_entity->fieldDump(); + + $this->writeToLogDB($entity_class, $deleted_id, 'delete', $fields, $user_id); + } + else + error_log($entity_class . ' does not implement the AuditableEntity interface.'); + } + } + + // TODO: find a way to get the list of "old" items, compare with list of updated items + // so we can find out what was added/removed + /* + foreach ($updated_collections as $updated_collection) + { + error_log('in updated_collection snippet'); + + foreach ($updated_collection as $item) + { + if ($item instanceof Role) + { + error_log('updated_collection item ' . $item->getName()); + } + if ($item instanceof Hub) + { + error_log('updated_collection item ' . $item->getName()); + } + } + + } + + foreach ($deleted_collections as $deleted_collection) + { + error_log('in deleted_collection snippet'); + + foreach ($deleted_collection as $item) + { + if ($item instanceof Role) + { + error_log('deleted_collection item ' . $item->getName()); + } + if ($item instanceof Hub) + { + error_log('deleted_collection item ' . $item->getName()); + } + } + } */ + + } + + protected function writeToLogDB($entity_type, $entity_id, $action, $content, $user_id) + { + $new_point = new Point( + 'entity_log', // measurement + null, // measurement value + ['entity_type' => $entity_type, 'entity_id' => $entity_id], // measurement tags + ['action' => $action, 'content' => $content, 'user' => $user_id], // measurement fields + exec('date +%s%N') // timestamp in nanoseconds on Linux only + ); + + $this->log_db->writePoints([$new_point]); + } +} diff --git a/src/EventListener/JobOrderStatusListener.php b/src/EventListener/JobOrderStatusListener.php new file mode 100644 index 00000000..8c3c9f45 --- /dev/null +++ b/src/EventListener/JobOrderStatusListener.php @@ -0,0 +1,91 @@ +wh = $wh; + $this->jo_handler = $jo_handler; + } + + // when a JO is updated + public function postUpdate(JobOrder $jo, LifecycleEventArgs $args) + { + $status = $jo->getStatus(); + + if ($status == JOStatus::FULFILLED) + { + $this->createWarrantyFromJO($jo); + } + } + + // when a new job order comes in and status is already fulfilled + public function postPersist(JobOrder $jo, LifecycleEventArgs $args) + { + $status = $jo->getStatus(); + + if ($status == JOStatus::FULFILLED) + { + $this->createWarrantyFromJO($jo); + } + } + + protected function createWarrantyFromJO(JobOrder $jo) + { + // create warranty + if ($this->jo_handler->checkIfNewBattery($jo)) + { + $serial = null; + $warranty_class = $jo->getWarrantyClass(); + $first_name = $jo->getCustomer()->getFirstName(); + $last_name = $jo->getCustomer()->getLastName(); + $mobile_number = $jo->getCustomer()->getPhoneMobile(); + + // check if date fulfilled is null + if ($jo->getDateFulfill() == null) + $date_purchase = $jo->getDateCreate(); + else + $date_purchase = $jo->getDateFulfill(); + + // validate plate number + // $plate_number = $this->wh->cleanPlateNumber($jo->getCustomerVehicle()->getPlateNumber()); + $plate_number = Warranty::cleanPlateNumber($jo->getCustomerVehicle()->getPlateNumber()); + if ($plate_number != false) + { + $batt_list = array(); + $invoice = $jo->getInvoice(); + if (!empty($invoice)) + { + // get battery + $invoice_items = $invoice->getItems(); + foreach ($invoice_items as $item) + { + $battery = $item->getBattery(); + if ($battery != null) + { + $batt_list[] = $item->getBattery(); + } + } + } + + $this->wh->createWarranty($serial, $plate_number, $first_name, $last_name, $mobile_number, $batt_list, $date_purchase, $warranty_class); + } + } + } + +} diff --git a/src/Service/JobOrderHandler/CMBJobOrderHandler.php b/src/Service/JobOrderHandler/CMBJobOrderHandler.php index 862d431b..1bce48c3 100644 --- a/src/Service/JobOrderHandler/CMBJobOrderHandler.php +++ b/src/Service/JobOrderHandler/CMBJobOrderHandler.php @@ -24,7 +24,6 @@ use App\Entity\Hub; use App\Entity\Promo; use App\Entity\Rider; use App\Entity\JORejection; -use App\Entity\Warranty; use App\Entity\Customer; use App\Entity\ServiceCharge; @@ -44,7 +43,6 @@ use App\Service\InvoiceGeneratorInterface; use App\Service\JobOrderHandlerInterface; use App\Service\RiderAssignmentHandlerInterface; use App\Service\CustomerHandlerInterface; -use App\Service\WarrantyHandler; use App\Service\MQTTClient; use App\Service\APNSClient; use App\Service\MapTools; @@ -67,7 +65,6 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface protected $translator; protected $rah; protected $country_code; - protected $wh; protected $cust_handler; protected $template_hash; @@ -75,8 +72,7 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface public function __construct(Security $security, EntityManagerInterface $em, InvoiceGeneratorInterface $ic, ValidatorInterface $validator, TranslatorInterface $translator, RiderAssignmentHandlerInterface $rah, - string $country_code, WarrantyHandler $wh, - CustomerHandlerInterface $cust_handler) + string $country_code, CustomerHandlerInterface $cust_handler) { $this->em = $em; $this->ic = $ic; @@ -85,7 +81,6 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface $this->translator = $translator; $this->rah = $rah; $this->country_code = $country_code; - $this->wh = $wh; $this->cust_handler = $cust_handler; $this->loadTemplates(); @@ -977,6 +972,7 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface // call rider assignment handler's fulfillJobOrder $this->rah->fulfillJobOrder($obj, $image_url, $rider); + /* // create the warranty if new battery only if ($this->checkIfNewBattery($obj)) { @@ -1019,7 +1015,7 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface $this->wh->createWarranty($serial, $plate_number, $first_name, $last_name, $mobile_number, $batt_list, $date_purchase, $warranty_class); } - } + } */ // validated! save the entity $em->flush(); @@ -2658,7 +2654,7 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface $cust_vehicle->setWarrantyCode($req->request->get('warranty_code')); $em->persist($cust_vehicle); - + /* // create the warranty if new battery only if ($this->checkIfNewBattery($jo)) { @@ -2701,7 +2697,7 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface $this->wh->createWarranty($serial, $plate_number, $first_name, $last_name, $mobile_number, $batt_list, $date_purchase, $warranty_class); } - } + } */ $em->flush(); } diff --git a/src/Service/JobOrderHandler/ResqJobOrderHandler.php b/src/Service/JobOrderHandler/ResqJobOrderHandler.php index 585c6135..1a4b7e3f 100644 --- a/src/Service/JobOrderHandler/ResqJobOrderHandler.php +++ b/src/Service/JobOrderHandler/ResqJobOrderHandler.php @@ -23,7 +23,6 @@ use App\Entity\Hub; use App\Entity\Promo; use App\Entity\Rider; use App\Entity\JORejection; -use App\Entity\Warranty; use App\Entity\Customer; use App\Ramcar\InvoiceCriteria; @@ -41,7 +40,6 @@ use App\Ramcar\JORejectionReason; use App\Service\InvoiceGeneratorInterface; use App\Service\JobOrderHandlerInterface; use App\Service\RiderAssignmentHandlerInterface; -use App\Service\WarrantyHandler; use App\Service\MQTTClient; use App\Service\APNSClient; use App\Service\MapTools; @@ -64,14 +62,13 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface protected $translator; protected $rah; protected $country_code; - protected $wh; protected $template_hash; public function __construct(Security $security, EntityManagerInterface $em, InvoiceGeneratorInterface $ic, ValidatorInterface $validator, TranslatorInterface $translator, RiderAssignmentHandlerInterface $rah, - string $country_code, WarrantyHandler $wh) + string $country_code) { $this->em = $em; $this->ic = $ic; @@ -80,7 +77,6 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface $this->translator = $translator; $this->rah = $rah; $this->country_code = $country_code; - $this->wh = $wh; $this->loadTemplates(); } @@ -824,6 +820,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface // call rider assignment handler's fulfillJobOrder $this->rah->fulfillJobOrder($obj, $image_url, $rider); + /* // create the warranty if new battery only if ($this->checkIfNewBattery($obj)) { @@ -862,7 +859,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface $this->wh->createWarranty($serial, $plate_number, $first_name, $last_name, $mobile_number, $batt_list, $date_purchase, $warranty_class); } - } + } */ } } diff --git a/src/Service/RiderAPIHandler/CMBRiderAPIHandler.php b/src/Service/RiderAPIHandler/CMBRiderAPIHandler.php index 3c0236e1..32514afd 100644 --- a/src/Service/RiderAPIHandler/CMBRiderAPIHandler.php +++ b/src/Service/RiderAPIHandler/CMBRiderAPIHandler.php @@ -18,7 +18,6 @@ use App\Service\RiderAPIHandlerInterface; use App\Service\RedisClientProvider; use App\Service\RiderCache; use App\Service\MQTTClient; -use App\Service\WarrantyHandler; use App\Service\JobOrderHandlerInterface; use App\Service\InvoiceGeneratorInterface; @@ -30,7 +29,6 @@ use App\Entity\Promo; use App\Entity\Battery; use App\Entity\BatteryModel; use App\Entity\BatterySize; -use App\Entity\Warranty; use DateTime; @@ -42,7 +40,6 @@ class CMBRiderAPIHandler implements RiderAPIHandlerInterface protected $rcache; protected $country_code; protected $mclient; - protected $wh; protected $jo_handler; protected $ic; protected $session; @@ -50,8 +47,7 @@ class CMBRiderAPIHandler implements RiderAPIHandlerInterface public function __construct(EntityManagerInterface $em, RedisClientProvider $redis, EncoderFactoryInterface $ef, RiderCache $rcache, string $country_code, MQTTClient $mclient, - WarrantyHandler $wh, JobOrderHandlerInterface $jo_handler, - InvoiceGeneratorInterface $ic) + JobOrderHandlerInterface $jo_handler, InvoiceGeneratorInterface $ic) { $this->em = $em; $this->redis = $redis; @@ -59,7 +55,6 @@ class CMBRiderAPIHandler implements RiderAPIHandlerInterface $this->rcache = $rcache; $this->country_code = $country_code; $this->mclient = $mclient; - $this->wh = $wh; $this->jo_handler = $jo_handler; $this->ic = $ic; @@ -523,6 +518,7 @@ class CMBRiderAPIHandler implements RiderAPIHandlerInterface $this->em->flush(); + /* // create warranty if($this->jo_handler->checkIfNewBattery($jo)) { @@ -561,7 +557,7 @@ class CMBRiderAPIHandler implements RiderAPIHandlerInterface $this->wh->createWarranty($serial, $plate_number, $first_name, $last_name, $mobile_number, $batt_list, $date_purchase, $warranty_class); } - } + } */ // send mqtt event (fulfilled) $rider = $this->session->getRider(); diff --git a/src/Service/RiderAPIHandler/ResqRiderAPIHandler.php b/src/Service/RiderAPIHandler/ResqRiderAPIHandler.php index 3c3ede6c..23a5be47 100644 --- a/src/Service/RiderAPIHandler/ResqRiderAPIHandler.php +++ b/src/Service/RiderAPIHandler/ResqRiderAPIHandler.php @@ -18,7 +18,6 @@ use App\Service\RiderAPIHandlerInterface; use App\Service\RedisClientProvider; use App\Service\RiderCache; use App\Service\MQTTClient; -use App\Service\WarrantyHandler; use App\Service\JobOrderHandlerInterface; use App\Service\InvoiceGeneratorInterface; @@ -41,7 +40,6 @@ class ResqRiderAPIHandler implements RiderAPIHandlerInterface protected $rcache; protected $country_code; protected $mclient; - protected $wh; protected $jo_handler; protected $ic; protected $session; @@ -49,8 +47,7 @@ class ResqRiderAPIHandler implements RiderAPIHandlerInterface public function __construct(EntityManagerInterface $em, RedisClientProvider $redis, EncoderFactoryInterface $ef, RiderCache $rcache, string $country_code, MQTTClient $mclient, - WarrantyHandler $wh, JobOrderHandlerInterface $jo_handler, - InvoiceGeneratorInterface $ic) + JobOrderHandlerInterface $jo_handler, InvoiceGeneratorInterface $ic) { $this->em = $em; $this->redis = $redis; @@ -58,7 +55,6 @@ class ResqRiderAPIHandler implements RiderAPIHandlerInterface $this->rcache = $rcache; $this->country_code = $country_code; $this->mclient = $mclient; - $this->wh = $wh; $this->jo_handler = $jo_handler; $this->ic = $ic; @@ -525,6 +521,7 @@ class ResqRiderAPIHandler implements RiderAPIHandlerInterface $this->em->flush(); + /* // create warranty if($this->jo_handler->checkIfNewBattery($jo)) { @@ -559,7 +556,7 @@ class ResqRiderAPIHandler implements RiderAPIHandlerInterface } $this->wh->createWarranty($serial, $plate_number, $first_name, $last_name, $mobile_number, $batt_list, $date_purchase, $warranty_class); - } + } */ // send mqtt event (fulfilled) $rider = $this->session->getRider(); diff --git a/symfony.lock b/symfony.lock index 116ed675..1f800f3e 100644 --- a/symfony.lock +++ b/symfony.lock @@ -110,6 +110,9 @@ "guzzlehttp/psr7": { "version": "1.4.2" }, + "influxdb/influxdb-php": { + "version": "1.15.0" + }, "jdorn/sql-formatter": { "version": "v1.2.17" }, diff --git a/templates/user/audit.log.html.twig b/templates/user/audit.log.html.twig new file mode 100644 index 00000000..bd8f3655 --- /dev/null +++ b/templates/user/audit.log.html.twig @@ -0,0 +1,79 @@ +{% extends 'base.html.twig' %} + +{% block body %} + +
+
+
+

Audit Logs

+
+
+
+ +
+ +
+
+
+
+ +
+ +
+
+
+
+
+{% endblock %} + +{% block scripts %} + +{% endblock %} + diff --git a/templates/user/change.history.log.html.twig b/templates/user/change.history.log.html.twig new file mode 100644 index 00000000..cf7ed1dc --- /dev/null +++ b/templates/user/change.history.log.html.twig @@ -0,0 +1,79 @@ +{% extends 'base.html.twig' %} + +{% block body %} + +
+
+
+

Audit Logs

+
+
+
+ +
+ +
+
+
+
+ +
+ +
+
+
+
+
+{% endblock %} + +{% block scripts %} + +{% endblock %} + diff --git a/templates/user/form.html.twig b/templates/user/form.html.twig index efa35dc4..05ea805f 100644 --- a/templates/user/form.html.twig +++ b/templates/user/form.html.twig @@ -57,6 +57,16 @@
Unique alias for this user +
+ {% if mode == 'update' %} + View Audit Logs + {% endif %} +
+
+ {% if mode == 'update' %} + View Change History + {% endif %} +
@@ -182,72 +192,73 @@ {% endblock %} {% block scripts %} - + // remove all error classes + function removeErrors() { + $(".form-control-danger").removeClass('form-control-danger'); + $("[data-field]").removeClass('has-danger'); + $(".form-control-feedback[data-field]").addClass('hide'); + } + }); + + {% endblock %}