diff --git a/config/packages/catalyst_auth.yaml b/config/packages/catalyst_auth.yaml index 4a13e9e4..f4e5461a 100644 --- a/config/packages/catalyst_auth.yaml +++ b/config/packages/catalyst_auth.yaml @@ -618,6 +618,20 @@ catalyst_auth: - id: ownership_type.delete label: Delete + - id: service_offering + label: Service Offering Access + acls: + - id: service_offering.menu + label: Menu + - id: service_offering.list + label: List + - id: service_offering.add + label: Add + - id: service_offering.update + label: Update + - id: service_offering.delete + label: Delete + api: user_entity: "App\\Entity\\ApiUser" acl_data: @@ -876,4 +890,4 @@ catalyst_auth: - id: cust_api_v2.warranty.check label: Check Status - id: cust_api_v2.warranty.register - label: Register \ No newline at end of file + label: Register diff --git a/config/packages/catalyst_menu.yaml b/config/packages/catalyst_menu.yaml index 48947331..98bce994 100644 --- a/config/packages/catalyst_menu.yaml +++ b/config/packages/catalyst_menu.yaml @@ -279,4 +279,8 @@ catalyst_menu: - id: ownership_type_list acl: ownership_type.menu label: '[menu.database.ownershiptypes]' - parent: database \ No newline at end of file + parent: database + - id: service_offering_list + acl: service_offering.menu + label: '[menu.database.serviceofferings]' + parent: database diff --git a/config/routes/service_offering.yaml b/config/routes/service_offering.yaml new file mode 100644 index 00000000..4f87ca89 --- /dev/null +++ b/config/routes/service_offering.yaml @@ -0,0 +1,34 @@ +service_offering_list: + path: /service-offerings + controller: App\Controller\ServiceOfferingController::index + methods: [GET] + +service_offering_rows: + path: /service-offerings/rowdata + controller: App\Controller\ServiceOfferingController::datatableRows + methods: [POST] + +service_offering_add_form: + path: /service-offerings/newform + controller: App\Controller\ServiceOfferingController::addForm + methods: [GET] + +service_offering_add_submit: + path: /service-offerings + controller: App\Controller\ServiceOfferingController::addSubmit + methods: [POST] + +service_offering_update_form: + path: /service-offerings/{id} + controller: App\Controller\ServiceOfferingController::updateForm + methods: [GET] + +service_offering_update_submit: + path: /service-offerings/{id} + controller: App\Controller\ServiceOfferingController::updateSubmit + methods: [POST] + +service_offering_delete: + path: /service-offerings/{id} + controller: App\Controller\ServiceOfferingController::deleteSubmit + methods: [DELETE] diff --git a/src/Controller/APIController.php b/src/Controller/APIController.php index 444aa90a..64662057 100644 --- a/src/Controller/APIController.php +++ b/src/Controller/APIController.php @@ -1035,6 +1035,10 @@ class APIController extends Controller implements LoggedController // set if taxable $icrit->setIsTaxable(); + // set JO source + // old app doesn't have separate jumpstart + $icrit->setSource(TransactionOrigin::CALL); + // send to invoice generator $invoice = $ic->generateInvoice($icrit); $jo->setInvoice($invoice); @@ -1317,6 +1321,10 @@ class APIController extends Controller implements LoggedController // set taxable $icrit->setIsTaxable(true); + // set JO source + // old app doesn't have separate jumpstart + $icrit->setSource(TransactionOrigin::CALL); + // check trade-in // only allow motolite, other, none $trade_in = $req->request->get('trade_in'); @@ -2882,6 +2890,10 @@ class APIController extends Controller implements LoggedController // set taxable $icrit->setIsTaxable(true); + // set JO source + // old app doesn't have separate jumpstart + $icrit->setSource(TransactionOrigin::CALL); + // check promo $promo_id = $req->request->get('promo_id'); if (!empty($promo_id)) diff --git a/src/Controller/CustomerAppAPI/InvoiceController.php b/src/Controller/CustomerAppAPI/InvoiceController.php index a89f0950..379ccd32 100644 --- a/src/Controller/CustomerAppAPI/InvoiceController.php +++ b/src/Controller/CustomerAppAPI/InvoiceController.php @@ -8,6 +8,7 @@ use Catalyst\ApiBundle\Component\Response as ApiResponse; use App\Service\InvoiceGeneratorInterface; use App\Ramcar\InvoiceCriteria; use App\Ramcar\TradeInType; +use App\Ramcar\TransactionOrigin; use App\Entity\CustomerVehicle; use App\Entity\Promo; use App\Entity\Battery; @@ -101,6 +102,9 @@ class InvoiceController extends ApiController // set if taxable $icrit->setIsTaxable(); + // set JO source + $icrit->setSource(TransactionOrigin::MOBILE_APP); + // send to invoice generator $invoice = $ic->generateInvoice($icrit); diff --git a/src/Controller/CustomerAppAPI/JobOrderController.php b/src/Controller/CustomerAppAPI/JobOrderController.php index ae19f55f..07356ce2 100644 --- a/src/Controller/CustomerAppAPI/JobOrderController.php +++ b/src/Controller/CustomerAppAPI/JobOrderController.php @@ -682,6 +682,9 @@ class JobOrderController extends ApiController // set taxable $icrit->setIsTaxable(); + // set JO source + $icrit->setSource(TransactionOrigin::MOBILE_APP); + // send to invoice generator $invoice = $ic->generateInvoice($icrit); $jo->setInvoice($invoice); @@ -1087,6 +1090,9 @@ class JobOrderController extends ApiController // set taxable $icrit->setIsTaxable(); + // set JO source + $icrit->setSource(TransactionOrigin::MOBILE_APP); + $icrit->addEntry($batt, $trade_in, 1); // send to invoice generator diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index 30bc519c..121edd8f 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -7,6 +7,7 @@ use App\Ramcar\InvoiceCriteria; use App\Ramcar\CMBServiceType; use App\Ramcar\ServiceType; use App\Ramcar\JOCancelReasons; +use App\Ramcar\TransactionOrigin; use App\Entity\CustomerVehicle; use App\Entity\Promo; @@ -738,7 +739,8 @@ class JobOrderController extends Controller $criteria = new InvoiceCriteria(); $criteria->setServiceType($stype) ->setCustomerVehicle($cv) - ->setIsTaxable(); + ->setIsTaxable() + ->setSource(TransactionOrigin::CALL); /* diff --git a/src/Controller/ServiceOfferingController.php b/src/Controller/ServiceOfferingController.php new file mode 100644 index 00000000..66a447a7 --- /dev/null +++ b/src/Controller/ServiceOfferingController.php @@ -0,0 +1,252 @@ +render('service-offering/list.html.twig'); + } + + /** + * @IsGranted("service_offering.list") + */ + public function datatableRows(Request $req) + { + // get query builder + $qb = $this->getDoctrine() + ->getRepository(ServiceOffering::class) + ->createQueryBuilder('q'); + + // get datatable params + $datatable = $req->request->get('datatable'); + + // count total records + $tquery = $qb->select('COUNT(q)'); + $this->setQueryFilters($datatable, $tquery); + $total = $tquery->getQuery() + ->getSingleScalarResult(); + + // get current page number + $page = $datatable['pagination']['page'] ?? 1; + + $perpage = $datatable['pagination']['perpage']; + $offset = ($page - 1) * $perpage; + + // add metadata + $meta = [ + 'page' => $page, + 'perpage' => $perpage, + 'pages' => ceil($total / $perpage), + 'total' => $total, + 'sort' => 'asc', + 'field' => 'id' + ]; + + // build query + $query = $qb->select('q'); + $this->setQueryFilters($datatable, $query); + + // check if sorting is present, otherwise use default + if (isset($datatable['sort']['field']) && !empty($datatable['sort']['field'])) { + $order = $datatable['sort']['sort'] ?? 'asc'; + $query->orderBy('q.' . $datatable['sort']['field'], $order); + } else { + $query->orderBy('q.id', 'asc'); + } + + // get rows for this page + $obj_rows = $query->setFirstResult($offset) + ->setMaxResults($perpage) + ->getQuery() + ->getResult(); + + // process rows + $rows = []; + foreach ($obj_rows as $orow) { + // add row data + $row['id'] = $orow->getID(); + $row['name'] = $orow->getName(); + $row['fee'] = $orow->getFee(); + + // add row metadata + $row['meta'] = [ + 'update_url' => '', + 'delete_url' => '' + ]; + + // add crud urls + if ($this->isGranted('service_offering.update')) + $row['meta']['update_url'] = $this->generateUrl('service_offering_update_form', ['id' => $row['id']]); + if ($this->isGranted('service_offering.delete')) + $row['meta']['delete_url'] = $this->generateUrl('service_offering_delete', ['id' => $row['id']]); + + $rows[] = $row; + } + + // response + return $this->json([ + 'meta' => $meta, + 'data' => $rows + ]); + } + + /** + * @Menu(selected="service_offering.list") + * @IsGranted("service_offering.add") + */ + public function addForm() + { + $service_offering = new ServiceOffering(); + $params = [ + 'service_offering' => $service_offering, + 'mode' => 'create', + ]; + + // response + return $this->render('service-offering/form.html.twig', $params); + } + + /** + * @IsGranted("service_offering.add") + */ + public function addSubmit(Request $req, EntityManagerInterface $em, ValidatorInterface $validator) + { + $service_offering = new ServiceOffering(); + + $this->setObject($service_offering, $req); + + // validate + $errors = $validator->validate($service_offering); + + // initialize error list + $error_array = []; + + // add errors to list + foreach ($errors as $error) { + $error_array[$error->getPropertyPath()] = $error->getMessage(); + } + + // check if any errors were found + if (!empty($error_array)) { + // return validation failure response + return $this->json([ + 'success' => false, + 'errors' => $error_array + ], 422); + } + + // validated! save the entity + $em->persist($service_offering); + $em->flush(); + + // return successful response + return $this->json([ + 'success' => 'Changes have been saved!' + ]); + } + + /** + * @Menu(selected="service_offering_list") + * @ParamConverter("service_offering", class="App\Entity\ServiceOffering") + * @IsGranted("service_offering.update") + */ + public function updateForm($id, EntityManagerInterface $em, ServiceOffering $service_offering) + { + $params = []; + $params['service_offering'] = $service_offering; + $params['mode'] = 'update'; + + // response + return $this->render('service-offering/form.html.twig', $params); + } + + /** + * @ParamConverter("service_offering", class="App\Entity\ServiceOffering") + * @IsGranted("service_offering.update") + */ + public function updateSubmit(Request $req, EntityManagerInterface $em, ValidatorInterface $validator, ServiceOffering $service_offering) + { + $this->setObject($service_offering, $req); + + // validate + $errors = $validator->validate($service_offering); + + // initialize error list + $error_array = []; + + // add errors to list + foreach ($errors as $error) { + $error_array[$error->getPropertyPath()] = $error->getMessage(); + } + + // check if any errors were found + if (!empty($error_array)) { + // return validation failure response + return $this->json([ + 'success' => false, + 'errors' => $error_array + ], 422); + } + + // validated! save the entity + $em->flush(); + + // return successful response + return $this->json([ + 'success' => 'Changes have been saved!' + ]); + } + + /** + * @ParamConverter("service_offering", class="App\Entity\ServiceOffering") + * @IsGranted("service_offering.delete") + */ + public function deleteSubmit(EntityManagerInterface $em, ServiceOffering $service_offering) + { + // delete this object + $em->remove($service_offering); + $em->flush(); + + // response + $response = new Response(); + $response->setStatusCode(Response::HTTP_OK); + $response->send(); + } + + protected function setObject(ServiceOffering $obj, Request $req) + { + // set and save values + $obj->setName($req->request->get('name')) + ->setCode($req->request->get('code')) + ->setFee($req->request->get('fee')); + } + + protected function setQueryFilters($datatable, QueryBuilder $query) + { + if (isset($datatable['query']['data-rows-search']) && !empty($datatable['query']['data-rows-search'])) { + $query->where('q.name LIKE :filter') + ->setParameter('filter', '%' . $datatable['query']['data-rows-search'] . '%'); + } + } +} diff --git a/src/Controller/TAPI/JobOrderController.php b/src/Controller/TAPI/JobOrderController.php index a0a29b6b..83fb0a17 100644 --- a/src/Controller/TAPI/JobOrderController.php +++ b/src/Controller/TAPI/JobOrderController.php @@ -160,6 +160,9 @@ class JobOrderController extends ApiController // set taxable $icrit->setIsTaxable(); + // set JO source + $icrit->setSource(TransactionOrigin::THIRD_PARTY); + $icrit->addEntry($data['batt'], $data['trade_in_type'], 1); // send to invoice generator @@ -449,6 +452,12 @@ class JobOrderController extends ApiController $icrit->addEntry($data['battery'], $data['trade_in_type'], 1); + // set taxable + $icrit->setIsTaxable(); + + // set JO source + $icrit->setSource('third_party'); + // send to invoice generator $invoice = $ic->generateInvoice($icrit); diff --git a/src/Entity/ServiceOffering.php b/src/Entity/ServiceOffering.php new file mode 100644 index 00000000..3e8a935f --- /dev/null +++ b/src/Entity/ServiceOffering.php @@ -0,0 +1,81 @@ +id; + } + + public function setName($name) + { + $this->name = $name; + return $this; + } + + public function getName() + { + return $this->name; + } + + public function setCode($code) + { + $this->code = $code; + return $this; + } + + public function getCode() + { + return $this->code; + } + + public function setFee($fee) + { + $this->fee = $fee; + return $this; + } + + public function getFee() + { + return $this->fee; + } +} + diff --git a/src/InvoiceRule/BatteryReplacementWarranty.php b/src/InvoiceRule/BatteryReplacementWarranty.php index 8fbfe76c..ee1497b5 100644 --- a/src/InvoiceRule/BatteryReplacementWarranty.php +++ b/src/InvoiceRule/BatteryReplacementWarranty.php @@ -10,6 +10,7 @@ use App\Ramcar\ServiceType; use App\Ramcar\TradeInType; use App\Entity\Battery; +use App\Entity\ServiceOffering; class BatteryReplacementWarranty implements InvoiceRuleInterface { @@ -59,10 +60,16 @@ class BatteryReplacementWarranty implements InvoiceRuleInterface public function getServiceTypeFee() { - // TODO: we need to to put this somewhere like in .env - // so that if any chanages are to be made, we just edit the file - // instead of the code - return 0; + $code = 'battery_replacement_warranty_fee'; + + // find the service fee using the code + // if we can't find the fee, return 0 + $fee = $this->em->getRepository(ServiceOffering::class)->findOneBy(['code' => $code]); + + if ($fee == null) + return 0; + + return $fee->getFee(); } public function validatePromo($criteria, $promo_id) diff --git a/src/InvoiceRule/Fuel.php b/src/InvoiceRule/Fuel.php index 366ff0ad..f843e1c0 100644 --- a/src/InvoiceRule/Fuel.php +++ b/src/InvoiceRule/Fuel.php @@ -2,13 +2,25 @@ namespace App\InvoiceRule; +use Doctrine\ORM\EntityManagerInterface; + use App\InvoiceRuleInterface; use App\Ramcar\FuelType; use App\Ramcar\ServiceType; +use App\Entity\ServiceOffering; +use App\Entity\CustomerVehicle; + class Fuel implements InvoiceRuleInterface -{ +{ + protected $em; + + public function __construct(EntityManagerInterface $em) + { + $this->em = $em; + } + public function getID() { return 'fuel'; @@ -22,12 +34,9 @@ class Fuel implements InvoiceRuleInterface if ($stype == $this->getID()) { - // check if customer vehicle has a motolite battery $cv = $criteria->getCustomerVehicle(); - if ($cv->hasMotoliteBattery()) - $fee = 0; - else - $fee = $this->getServiceTypeFee(); + + $fee = $this->getServiceTypeFee($cv); $ftype = $cv->getFuelType(); @@ -82,29 +91,41 @@ class Fuel implements InvoiceRuleInterface return $items; } - public function getServiceTypeFee() - { - // TODO: we need to to put this somewhere like in .env - // so that if any changes are to be made, we just edit the file - // instead of the code - return 300; + public function getServiceTypeFee(CustomerVehicle $cv) + { + // check if customer vehicle has a motolite battery + // if yes, set the code to the motolite user service fee + if ($cv->hasMotoliteBattery()) + $code = 'motolite_user_service_fee'; + else + $code = 'fuel_service_fee'; + + // find the service fee using the code + // if we can't find the fee, return 0 + $fee = $this->em->getRepository(ServiceOffering::class)->findOneBy(['code' => $code]); + + if ($fee == null) + return 0; + + return $fee->getFee(); } public function getFuelFee($fuel_type) { - // TODO: we need to to put this somewhere like in .env - // so that if any changes are to be made, we just edit the file - // instead of the code + $code = ''; if ($fuel_type == FuelType::GAS) - { - // gas fuel fee - return 340; - } - else - { - // diesel fuel fee - return 300; - } + $code = 'fuel_gas_fee'; + if ($fuel_type == FuelType::DIESEL) + $code = 'fuel_diesel_fee'; + + // find the fuel fee for the specific fuel type using the code + // if we can't find the fee, return 0 + $fee = $this->em->getRepository(ServiceOffering::class)->findOneBy(['code' => $code]); + + if ($fee == null) + return 0; + + return $fee->getFee(); } public function validatePromo($criteria, $promo_id) diff --git a/src/InvoiceRule/Jumpstart.php b/src/InvoiceRule/Jumpstart.php index c8cdeb10..374ac93a 100644 --- a/src/InvoiceRule/Jumpstart.php +++ b/src/InvoiceRule/Jumpstart.php @@ -2,10 +2,23 @@ namespace App\InvoiceRule; +use Doctrine\ORM\EntityManagerInterface; + use App\InvoiceRuleInterface; +use App\Entity\ServiceOffering; + +use App\Ramcar\TransactionOrigin; + class Jumpstart implements InvoiceRuleInterface -{ +{ + protected $em; + + public function __construct(EntityManagerInterface $em) + { + $this->em = $em; + } + public function getID() { return 'jumpstart_troubleshoot'; @@ -14,12 +27,13 @@ class Jumpstart implements InvoiceRuleInterface public function compute($criteria, &$total) { $stype = $criteria->getServiceType(); + $source = $criteria->getSource(); $items = []; if ($stype == $this->getID()) { - $fee = $this->getServiceTypeFee(); + $fee = $this->getServiceTypeFee($source); // add the service fee to items $qty = 1; @@ -37,12 +51,23 @@ class Jumpstart implements InvoiceRuleInterface return $items; } - public function getServiceTypeFee() + public function getServiceTypeFee($source) { - // TODO: we need to to put this somewhere like in .env - // so that if any chanages are to be made, we just edit the file - // instead of the code - return 300; + // find the service fee for jumpstart using the code + // if we can't find the fee, return 0 + // jumpstart fee depends on the JO source. Jumpstart from app has a different fee + // we set the code to search for the default + $code = 'jumpstart_fee'; + + if ($source == TransactionOrigin::MOBILE_APP) + $code = 'jumpstart_fee_mobile_app'; + + $fee = $this->em->getRepository(ServiceOffering::class)->findOneBy(['code' => $code]); + + if ($fee == null) + return 0; + + return $fee->getFee(); } public function validatePromo($criteria, $promo_id) diff --git a/src/InvoiceRule/JumpstartWarranty.php b/src/InvoiceRule/JumpstartWarranty.php index 34a331e7..9423da44 100644 --- a/src/InvoiceRule/JumpstartWarranty.php +++ b/src/InvoiceRule/JumpstartWarranty.php @@ -2,10 +2,21 @@ namespace App\InvoiceRule; +use Doctrine\ORM\EntityManagerInterface; + use App\InvoiceRuleInterface; +use App\Entity\ServiceOffering; + class JumpstartWarranty implements InvoiceRuleInterface -{ +{ + protected $em; + + public function __construct(EntityManagerInterface $em) + { + $this->em = $em; + } + public function getID() { return 'jumpstart_warranty'; @@ -38,11 +49,17 @@ class JumpstartWarranty implements InvoiceRuleInterface } public function getServiceTypeFee() - { - // TODO: we need to to put this somewhere like in .env - // so that if any chanages are to be made, we just edit the file - // instead of the code - return 0; + { + $code = 'jumpstart_warranty_fee'; + + // find the service fee using the code + // if we can't find the fee, return 0 + $fee = $this->em->getRepository(ServiceOffering::class)->findOneBy(['code' => $code]); + + if ($fee == null) + return 0; + + return $fee->getFee(); } public function validatePromo($criteria, $promo_id) diff --git a/src/InvoiceRule/Overheat.php b/src/InvoiceRule/Overheat.php index 692e5e85..4c06bddb 100644 --- a/src/InvoiceRule/Overheat.php +++ b/src/InvoiceRule/Overheat.php @@ -2,12 +2,24 @@ namespace App\InvoiceRule; +use Doctrine\ORM\EntityManagerInterface; + use App\InvoiceRuleInterface; use App\Ramcar\ServiceType; +use App\Entity\ServiceOffering; +use App\Entity\CustomerVehicle; + class Overheat implements InvoiceRuleInterface -{ +{ + protected $em; + + public function __construct(EntityManagerInterface $em) + { + $this->em = $em; + } + public function getID() { return 'overheat'; @@ -22,12 +34,8 @@ class Overheat implements InvoiceRuleInterface if ($stype == $this->getID()) { - // check if customer vehicle has a motolite battery $cv = $criteria->getCustomerVehicle(); - if ($cv->hasMotoliteBattery()) - $fee = 0; - else - $fee = $this->getServiceTypeFee(); + $fee = $this->getServiceTypeFee($cv); // add the service fee to items $qty = 1; @@ -61,20 +69,37 @@ class Overheat implements InvoiceRuleInterface return $items; } - public function getServiceTypeFee() - { - // TODO: we need to to put this somewhere like in .env - // so that if any chanages are to be made, we just edit the file - // instead of the code - return 300; + public function getServiceTypeFee(CustomerVehicle $cv) + { + $code = 'overheat_fee'; + + // check if customer vehicle has a motolite battery + // if yes, set the code to the motolite user service fee + if ($cv->hasMotoliteBattery()) + $code = 'motolite_user_service_fee'; + + // find the service fee for overheat using the code + // if we can't find the fee, return 0 + $fee = $this->em->getRepository(ServiceOffering::class)->findOneBy(['code' => $code]); + + if ($fee == null) + return 0; + + return $fee->getFee(); } public function getCoolantFee() { - // TODO: we need to to put this somewhere like in .env - // so that if any chanages are to be made, we just edit the file - // instead of the code - return 1600; + $code = 'coolant_fee'; + + // find the service fee using the code + // if we can't find the fee, return 0 + $fee = $this->em->getRepository(ServiceOffering::class)->findOneBy($code); + + if ($fee == null) + return 0; + + return $fee->getFee(); } public function validatePromo($criteria, $promo_id) diff --git a/src/InvoiceRule/PostRecharged.php b/src/InvoiceRule/PostRecharged.php index 55549aa7..808f2340 100644 --- a/src/InvoiceRule/PostRecharged.php +++ b/src/InvoiceRule/PostRecharged.php @@ -2,10 +2,21 @@ namespace App\InvoiceRule; +use Doctrine\ORM\EntityManagerInterface; + use App\InvoiceRuleInterface; +use App\Entity\ServiceOffering; + class PostRecharged implements InvoiceRuleInterface -{ +{ + protected $em; + + public function __construct(EntityManagerInterface $em) + { + $this->em = $em; + } + public function getID() { return 'post_recharged'; @@ -38,11 +49,17 @@ class PostRecharged implements InvoiceRuleInterface } public function getServiceTypeFee() - { - // TODO: we need to to put this somewhere like in .env - // so that if any chanages are to be made, we just edit the file - // instead of the code - return 300; + { + $code = 'post_recharged_fee'; + + // find the service fee for post recharged using the code + // if we can't find the fee, return 0 + $fee = $this->em->getRepository(ServiceOffering::class)->findOneBy(['code' => $code]); + + if ($fee == null) + return 0; + + return $fee->getFee(); } public function validatePromo($criteria, $promo_id) diff --git a/src/InvoiceRule/PostReplacement.php b/src/InvoiceRule/PostReplacement.php index a64c0fce..aba6d9aa 100644 --- a/src/InvoiceRule/PostReplacement.php +++ b/src/InvoiceRule/PostReplacement.php @@ -2,10 +2,21 @@ namespace App\InvoiceRule; +use Doctrine\ORM\EntityManagerInterface; + use App\InvoiceRuleInterface; +use App\Entity\ServiceOffering; + class PostReplacement implements InvoiceRuleInterface -{ +{ + protected $em; + + public function __construct(EntityManagerInterface $em) + { + $this->em = $em; + } + public function getID() { return 'post_replacement'; @@ -37,11 +48,17 @@ class PostReplacement implements InvoiceRuleInterface } public function getServiceTypeFee() - { - // TODO: we need to to put this somewhere like in .env - // so that if any chanages are to be made, we just edit the file - // instead of the code - return 0; + { + $code = 'post_replacement_fee'; + + // find the service fee using the code + // if we can't find the fee, return 0 + $fee = $this->em->getRepository(ServiceOffering::class)->findOneBy(['code' => $code]); + + if ($fee == null) + return 0; + + return $fee->getFee(); } public function validatePromo($criteria, $promo_id) diff --git a/src/InvoiceRule/Tax.php b/src/InvoiceRule/Tax.php index 231c2d36..b1e6a600 100644 --- a/src/InvoiceRule/Tax.php +++ b/src/InvoiceRule/Tax.php @@ -2,12 +2,23 @@ namespace App\InvoiceRule; +use Doctrine\ORM\EntityManagerInterface; + use App\InvoiceRuleInterface; use App\Ramcar\ServiceType; +use App\Entity\ServiceOffering; + class Tax implements InvoiceRuleInterface { + protected $em; + + public function __construct(EntityManagerInterface $em) + { + $this->em = $em; + } + public function getID() { return 'tax'; @@ -101,10 +112,16 @@ class Tax implements InvoiceRuleInterface protected function getTaxRate() { - // TODO: we need to to put this somewhere like in .env - // so that if any chanages are to be made, we just edit the file - // instead of the code - return 0.12; + $code = 'tax'; + + // find the service fee using the code + // if we can't find the fee, return 0 + $fee = $this->em->getRepository(ServiceOffering::class)->findOneBy(['code' => $code]); + + if ($fee == null) + return 0; + + return $fee->getFee(); } } diff --git a/src/InvoiceRule/TireRepair.php b/src/InvoiceRule/TireRepair.php index 3ca00714..755c11bd 100644 --- a/src/InvoiceRule/TireRepair.php +++ b/src/InvoiceRule/TireRepair.php @@ -2,10 +2,22 @@ namespace App\InvoiceRule; +use Doctrine\ORM\EntityManagerInterface; + use App\InvoiceRuleInterface; +use App\Entity\ServiceOffering; +use App\Entity\CustomerVehicle; + class TireRepair implements InvoiceRuleInterface -{ +{ + protected $em; + + public function __construct(EntityManagerInterface $em) + { + $this->em = $em; + } + public function getID() { return 'tire'; @@ -19,12 +31,8 @@ class TireRepair implements InvoiceRuleInterface if ($stype == $this->getID()) { - // check if customer vehicle has a motolite battery $cv = $criteria->getCustomerVehicle(); - if ($cv->hasMotoliteBattery()) - $fee = 0; - else - $fee = $this->getServiceTypeFee(); + $fee = $this->getServiceTypeFee($cv); // add the service fee to items $qty = 1; @@ -42,12 +50,23 @@ class TireRepair implements InvoiceRuleInterface return $items; } - protected function getServiceTypeFee() - { - // TODO: we need to to put this somewhere like in .env - // so that if any chanages are to be made, we just edit the file - // instead of the code - return 300; + protected function getServiceTypeFee(CustomerVehicle $cv) + { + $code = 'tire_repair_fee'; + + // check if customer vehicle has a motolite battery + // if yes, set the code to the motolite user service fee + if ($cv->hasMotoliteBattery()) + $code = 'motolite_user_service_fee'; + + // find the service fee using the code + // if we can't find the fee, return 0 + $fee = $this->em->getRepository(ServiceOffering::class)->findOneBy(['code' => $code]); + + if ($fee == null) + return 0; + + return $fee->getFee(); } public function validatePromo($criteria, $promo_id) diff --git a/src/Ramcar/InvoiceCriteria.php b/src/Ramcar/InvoiceCriteria.php index 886d6024..b27395da 100644 --- a/src/Ramcar/InvoiceCriteria.php +++ b/src/Ramcar/InvoiceCriteria.php @@ -16,6 +16,7 @@ class InvoiceCriteria protected $discount; protected $service_charges; protected $flag_taxable; + protected $source; // use Ramcar's TransactionOrigin // entries are battery and trade-in combos protected $entries; @@ -30,6 +31,7 @@ class InvoiceCriteria $this->discount = 0; $this->service_charges = []; $this->flag_taxable = false; + $this->source = ''; } public function setServiceType($stype) @@ -166,4 +168,15 @@ class InvoiceCriteria return $this->flag_taxable; } + public function setSource($source) + { + $this->source = $source; + return $this; + } + + public function getSource() + { + return $this->source; + } + } diff --git a/src/Service/InvoiceGenerator/CMBInvoiceGenerator.php b/src/Service/InvoiceGenerator/CMBInvoiceGenerator.php index 534600fb..5dc86f8d 100644 --- a/src/Service/InvoiceGenerator/CMBInvoiceGenerator.php +++ b/src/Service/InvoiceGenerator/CMBInvoiceGenerator.php @@ -134,7 +134,7 @@ class CMBInvoiceGenerator implements InvoiceGeneratorInterface } // generate invoice criteria - public function generateInvoiceCriteria($jo, $discount, $invoice_items, &$error_array) + public function generateInvoiceCriteria($jo, $discount, $invoice_items, $source = null, &$error_array) { $em = $this->em; diff --git a/src/Service/InvoiceGenerator/ResqInvoiceGenerator.php b/src/Service/InvoiceGenerator/ResqInvoiceGenerator.php index d3a30762..3809133b 100644 --- a/src/Service/InvoiceGenerator/ResqInvoiceGenerator.php +++ b/src/Service/InvoiceGenerator/ResqInvoiceGenerator.php @@ -144,7 +144,7 @@ class ResqInvoiceGenerator implements InvoiceGeneratorInterface } // generate invoice criteria - public function generateInvoiceCriteria($jo, $promo_id, $invoice_items, &$error_array) + public function generateInvoiceCriteria($jo, $promo_id, $invoice_items, $source = null, &$error_array) { $em = $this->em; diff --git a/src/Service/InvoiceGeneratorInterface.php b/src/Service/InvoiceGeneratorInterface.php index 3e1c5f88..e2cb2cc3 100644 --- a/src/Service/InvoiceGeneratorInterface.php +++ b/src/Service/InvoiceGeneratorInterface.php @@ -13,7 +13,7 @@ interface InvoiceGeneratorInterface public function generateInvoice(InvoiceCriteria $criteria); // generate invoice criteria - public function generateInvoiceCriteria(JobOrder $jo, int $promo_id, array $invoice_items, array &$error_array); + public function generateInvoiceCriteria(JobOrder $jo, int $promo_id, array $invoice_items, $source, array &$error_array); // prepare draft for invoice public function generateDraftInvoice(InvoiceCriteria $criteria, int $promo_id, array $service_charges, array $items); diff --git a/src/Service/InvoiceManager.php b/src/Service/InvoiceManager.php index ce3caa7f..65fc3a43 100644 --- a/src/Service/InvoiceManager.php +++ b/src/Service/InvoiceManager.php @@ -44,21 +44,21 @@ class InvoiceManager implements InvoiceGeneratorInterface return [ new InvoiceRule\BatterySales($this->em), new InvoiceRule\BatteryReplacementWarranty($this->em), - new InvoiceRule\Jumpstart(), - new InvoiceRule\JumpstartWarranty(), - new InvoiceRule\PostRecharged(), - new InvoiceRule\PostReplacement(), - new InvoiceRule\Overheat(), - new InvoiceRule\Fuel(), - new InvoiceRule\TireRepair(), + new InvoiceRule\Jumpstart($this->em), + new InvoiceRule\JumpstartWarranty($this->em), + new InvoiceRule\PostRecharged($this->em), + new InvoiceRule\PostReplacement($this->em), + new InvoiceRule\Overheat($this->em), + new InvoiceRule\Fuel($this->em), + new InvoiceRule\TireRepair($this->em), new InvoiceRule\DiscountType($this->em), new InvoiceRule\TradeIn(), - new InvoiceRule\Tax(), + new InvoiceRule\Tax($this->em), ]; } // this is called when JO is submitted - public function generateInvoiceCriteria($jo, $promo_id, $invoice_items, &$error_array) + public function generateInvoiceCriteria($jo, $promo_id, $invoice_items, $source, &$error_array) { // instantiate the invoice criteria $criteria = new InvoiceCriteria(); @@ -70,6 +70,9 @@ class InvoiceManager implements InvoiceGeneratorInterface // would mean adding it as a parameter to the call, impacting all calls $criteria->setIsTaxable(); + // set JO source + $criteria->setSource($source); + foreach ($this->available_rules as $avail_rule) { $ierror = $avail_rule->validatePromo($criteria, $promo_id); @@ -185,6 +188,7 @@ class InvoiceManager implements InvoiceGeneratorInterface ]; // get what is in criteria + // NOTE: is this snippet still needed? if not, remove $stype = $criteria->getServiceType(); $entries = $criteria->getEntries(); $promos = $criteria->getPromos(); diff --git a/src/Service/JobOrderHandler/ResqJobOrderHandler.php b/src/Service/JobOrderHandler/ResqJobOrderHandler.php index 5b24ed48..3e86f434 100644 --- a/src/Service/JobOrderHandler/ResqJobOrderHandler.php +++ b/src/Service/JobOrderHandler/ResqJobOrderHandler.php @@ -562,7 +562,9 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface // check if invoice changed if ($invoice_change) { - $this->ic->generateInvoiceCriteria($jo, $promo_id, $invoice_items, $error_array); + $source = $jo->getSource(); + + $this->ic->generateInvoiceCriteria($jo, $promo_id, $invoice_items, $source, $error_array); } // validate @@ -792,7 +794,9 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface $invoice_change = $req->request->get('invoice_change', 0); if ($invoice_change) { - $this->ic->generateInvoiceCriteria($obj, $promo_id, $invoice_items, $error_array); + $source = $obj->getSource(); + + $this->ic->generateInvoiceCriteria($obj, $promo_id, $invoice_items, $source, $error_array); } // validate @@ -2137,7 +2141,10 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface // check if invoice changed if ($invoice_change) { - $this->ic->generateInvoiceCriteria($jo, $promo_id, $invoice_items, $error_array); + // NOTE: this is CMB code but for compilation purposes we need to add this + $source = $jo->getSource(); + + $this->ic->generateInvoiceCriteria($jo, $promo_id, $invoice_items, $source, $error_array); } // validate diff --git a/src/Service/RiderAPIHandler/ResqRiderAPIHandler.php b/src/Service/RiderAPIHandler/ResqRiderAPIHandler.php index 311d43fd..7a112913 100644 --- a/src/Service/RiderAPIHandler/ResqRiderAPIHandler.php +++ b/src/Service/RiderAPIHandler/ResqRiderAPIHandler.php @@ -16,6 +16,7 @@ use App\Ramcar\InvoiceStatus; use App\Ramcar\ModeOfPayment; use App\Ramcar\InvoiceCriteria; use App\Ramcar\WarrantySource; +use App\Ramcar\TransactionOrigin; use App\Service\RiderAPIHandlerInterface; use App\Service\RedisClientProvider; @@ -869,6 +870,10 @@ class ResqRiderAPIHandler implements RiderAPIHandlerInterface // set istaxable $crit->setIsTaxable(); + // set JO source + // set to anything other than mobile app + $icrit->setSource(TransactionOrigin::WALK_IN); + if ($promo != null) $crit->addPromo($promo); diff --git a/templates/service-offering/form.html.twig b/templates/service-offering/form.html.twig new file mode 100644 index 00000000..eb08bedc --- /dev/null +++ b/templates/service-offering/form.html.twig @@ -0,0 +1,151 @@ +{% extends 'base.html.twig' %} + +{% block body %} + +