From 4a9dc2a6b22992caa19035c5c52fb89f2473420c Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Tue, 6 Feb 2024 04:43:58 -0500 Subject: [PATCH 1/5] Add routes, controller, and template for trade in pricing. #789 --- config/packages/catalyst_auth.yaml | 5 + config/packages/catalyst_menu.yaml | 4 + config/routes/trade_in_pricing.yaml | 14 ++ src/Controller/TradeInPricingController.php | 72 ++++++++++ src/Entity/TradeInPrice.php | 117 ++++++++++++++++ templates/trade-in-pricing/form.html.twig | 143 ++++++++++++++++++++ 6 files changed, 355 insertions(+) create mode 100644 config/routes/trade_in_pricing.yaml create mode 100644 src/Controller/TradeInPricingController.php create mode 100644 src/Entity/TradeInPrice.php create mode 100644 templates/trade-in-pricing/form.html.twig diff --git a/config/packages/catalyst_auth.yaml b/config/packages/catalyst_auth.yaml index 9707fc93..fe6cb91f 100644 --- a/config/packages/catalyst_auth.yaml +++ b/config/packages/catalyst_auth.yaml @@ -672,6 +672,11 @@ catalyst_auth: acls: - id: item_pricing.update label: Update + - id: trade_in_pricing + label: Trade In Pricing + acls: + - id: trade_in_pricing.update + label: Update api: user_entity: "App\\Entity\\ApiUser" diff --git a/config/packages/catalyst_menu.yaml b/config/packages/catalyst_menu.yaml index 7972a414..19af068c 100644 --- a/config/packages/catalyst_menu.yaml +++ b/config/packages/catalyst_menu.yaml @@ -306,3 +306,7 @@ catalyst_menu: acl: item_pricing.update label: Item Pricing parent: item + - id: trade_in_pricing + acl: trade_in_pricing.update + label: Trade In Pricing + parent: item diff --git a/config/routes/trade_in_pricing.yaml b/config/routes/trade_in_pricing.yaml new file mode 100644 index 00000000..dbc52fb7 --- /dev/null +++ b/config/routes/trade_in_pricing.yaml @@ -0,0 +1,14 @@ +trade_in_pricing: + path: /trade-in-pricing + controller: App\Controller\TradeInPricingController::index + methods: [GET] + +trade_in_pricing_update: + path: /trade-in-pricing + controller: App\Controller\TradeInPricingController::formSubmit + methods: [POST] + +trade_in_pricing_prices: + path: /trade-in-pricing/{pt_id}/prices + controller: App\Controller\TradeInPricingController::tradeInPrices + methods: [GET] diff --git a/src/Controller/TradeInPricingController.php b/src/Controller/TradeInPricingController.php new file mode 100644 index 00000000..f9c0dcb4 --- /dev/null +++ b/src/Controller/TradeInPricingController.php @@ -0,0 +1,72 @@ +getRepository(PriceTier::class)->findAll(); + + // get all the items/battery sizes + $items = $this->getBatterySizes($em); + + // get the trade in types + + $params = [ + 'sets' => [ + 'price_tiers' => $price_tiers, + 'trade_in_types' => TradeInType::getCollection(), + ], + 'items' => $items, + ]; + + // TODO: fix display of prices according to trade in type selected + // need to set a default trade in type to display? check TradeInType::getCollection + return $this->render('trade-in-pricing/form.html.twig', $params); + } + + protected function getBatterySizes(EntityManagerInterface $em) + { + // get all battery sizes + $b_sizes = $em->getRepository(BatterySize::class)->findBy([], ['name' => 'asc']); + foreach ($b_sizes as $b_size) + { + $b_size_set[$b_size->getID()] = [ + 'name' => $b_size->getName(), + 'motolite_tiprice' => $b_size->getTIPriceMotolite(), + 'premium_tiprice' => $b_size->getTIPricePremium(), + 'other_tiprice' => $b_size->getTIPriceOther(), + ]; + } + + return [ + 'items' => $b_size_set, + ]; + } +} diff --git a/src/Entity/TradeInPrice.php b/src/Entity/TradeInPrice.php new file mode 100644 index 00000000..de5d1216 --- /dev/null +++ b/src/Entity/TradeInPrice.php @@ -0,0 +1,117 @@ +meta_info = []; + } + + public function getID() + { + return $this->id; + } + + public function setPriceTier(PriceTier $price_tier) + { + $this->price_tier = $price_tier; + return $this; + } + + public function getPriceTier() + { + return $this->price_tier; + } + + public function setItemType(ItemType $item_type) + { + $this->item_type = $item_type; + return $this; + } + + public function getItemType() + { + return $this->item_type; + } + + public function setItemID($item_id) + { + $this->item_id = $item_id; + return $this; + } + + public function getItemID() + { + return $this->item_id; + } + + public function addMetaInfo($id, $value) + { + $this->meta_info[$id] = $value; + return $this; + } + + public function deleteMetadataInfo($id) + { + unset($this->meta_info[$id]); + return $this; + } + + public function getMetaInfo($id) + { + // return null if we don't have it + if (!isset($this->meta_info[$id])) + return null; + + return $this->meta_info[$id]; + } + + public function getAllMetaInfo() + { + return $this->meta_info; + } +} diff --git a/templates/trade-in-pricing/form.html.twig b/templates/trade-in-pricing/form.html.twig new file mode 100644 index 00000000..77198fe2 --- /dev/null +++ b/templates/trade-in-pricing/form.html.twig @@ -0,0 +1,143 @@ +{% extends 'base.html.twig' %} + +{% block body %} + +
+
+
+

Trade-In Pricing

+
+
+
+ +
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+ + + + + + + + + + {% for id, item in items.items %} + + + + + + {% endfor %} + +
IDNamePrice
{{ id }}{{ item.name }}
+
+ +
+
+
+
+
+
+
+
+{% endblock %} + +{% block scripts %} + +{% endblock %} -- 2.43.5 From 48058c858d77e0feb84ca587a1c5b019bde6c929 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Wed, 7 Feb 2024 04:27:45 -0500 Subject: [PATCH 2/5] Add page to display trade in prices. #789 --- src/Controller/TradeInPricingController.php | 89 ++++++++++++++++++--- src/Entity/PriceTier.php | 12 +++ src/Entity/TradeInPrice.php | 18 ----- templates/trade-in-pricing/form.html.twig | 27 +++---- 4 files changed, 104 insertions(+), 42 deletions(-) diff --git a/src/Controller/TradeInPricingController.php b/src/Controller/TradeInPricingController.php index f9c0dcb4..001d565b 100644 --- a/src/Controller/TradeInPricingController.php +++ b/src/Controller/TradeInPricingController.php @@ -31,37 +31,108 @@ class TradeInPricingController extends Controller public function index (EntityManagerInterface $em) { // get all the price tiers + // default price tier so battery sizes data should come from battery size + // not from price tier $price_tiers = $em->getRepository(PriceTier::class)->findAll(); // get all the items/battery sizes $items = $this->getBatterySizes($em); - // get the trade in types - $params = [ 'sets' => [ 'price_tiers' => $price_tiers, - 'trade_in_types' => TradeInType::getCollection(), ], 'items' => $items, ]; - // TODO: fix display of prices according to trade in type selected - // need to set a default trade in type to display? check TradeInType::getCollection return $this->render('trade-in-pricing/form.html.twig', $params); } + /** + * @IsGranted("trade_in_pricing.update") + */ + public function tradeInPrices(EntityManagerInterface $em, $pt_id, $ti_type) + { + $pt_prices = []; + + // check if default prices are needed + if ($pt_id != 0) + { + // get the price tier + $pt = $em->getRepository(PriceTier::class)->find($pt_id); + + // get the trade in prices under the price tier + $pt_trade_ins = $pt->getTradeInPrices(); + + foreach ($pt_trade_ins as $pt_trade_in) + { + $meta_info = $pt_trade_in->getAllMetaInfo(); + + error_log(print_r($meta_info, true)); + + $pt_prices[$pt_trade_in->getItemID()] = $meta_info; + } + } + + // get the prices from battery size + $bsizes = $em->getRepository(BatterySize::class)->findBy([], ['id' => 'asc']); + + $data_items = []; + foreach ($bsizes as $bsize) + { + $bsize_id = $bsize->getID(); + $name = $bsize->getName(); + + // get the default trade in prices + $motolite_tip = $bsize->getTIPriceMotolite(); + $premium_tip = $bsize->getTIPricePremium(); + $other_tip = $bsize->getTiPriceOther(); + + // check if tier has price for battery size + if (isset($pt_prices[$bsize_id])) + { + $meta_info = $pt_prices[$bsize_id]; + + $pt_motolite_tip = $meta_info['motolite']; + $pt_premium_tip = $meta_info['premium']; + $pt_other_tip = $meta_info['other']; + + // actual prices + $motolite_tip = number_format($pt_motolite_tip / 100, 2, '.', ''); + $premium_tip = number_format($pt_premium_tip / 100, 2, '.', ''); + $other_tip = number_format($pt_other_tip / 100, 2, '.', ''); + } + + $actual_motolite_tip = $motolite_tip; + $actual_premium_tip = $premium_tip; + $actual_other_tip = $other_tip; + + $data_items[] = [ + 'id' => $bsize_id, + 'name' => $name, + 'motolite_tip' => $actul_motolite_tip, + 'premium_tip' => $actual_premium_tip, + 'other_tip' => $actual_other_tip, + ]; + } + + // response + return new JsonResponse([ + 'items' => $data_items, + ]); + } + protected function getBatterySizes(EntityManagerInterface $em) { // get all battery sizes - $b_sizes = $em->getRepository(BatterySize::class)->findBy([], ['name' => 'asc']); + $b_sizes = $em->getRepository(BatterySize::class)->findBy([], ['id' => 'asc']); foreach ($b_sizes as $b_size) { $b_size_set[$b_size->getID()] = [ 'name' => $b_size->getName(), - 'motolite_tiprice' => $b_size->getTIPriceMotolite(), - 'premium_tiprice' => $b_size->getTIPricePremium(), - 'other_tiprice' => $b_size->getTIPriceOther(), + 'motolite_tip' => $b_size->getTIPriceMotolite(), + 'premium_tip' => $b_size->getTIPricePremium(), + 'other_tip' => $b_size->getTIPriceOther(), ]; } diff --git a/src/Entity/PriceTier.php b/src/Entity/PriceTier.php index 1e2599a5..c56cd0bb 100644 --- a/src/Entity/PriceTier.php +++ b/src/Entity/PriceTier.php @@ -38,10 +38,17 @@ class PriceTier */ protected $item_prices; + // trade in prices under a price tier + /** + * @ORM\OneToMany(targetEntity="TradeInPrice", mappedBy="price_tier") + */ + protected $trade_in_prices; + public function __construct() { $this->supported_areas = new ArrayCollection(); $this->items = new ArrayCollection(); + $this->trade_in_prices = new ArrayCollection(); } public function getID() @@ -85,4 +92,9 @@ class PriceTier return $this->item_prices; } + public function getTradeInPrices() + { + return $this->trade_in_prices; + } + } diff --git a/src/Entity/TradeInPrice.php b/src/Entity/TradeInPrice.php index de5d1216..26f31b47 100644 --- a/src/Entity/TradeInPrice.php +++ b/src/Entity/TradeInPrice.php @@ -26,13 +26,6 @@ class TradeInPrice */ protected $price_tier; - // item type - /** - * @ORM\ManyToOne(targetEntity="ItemType", inversedBy="items") - * @ORM\JoinColumn(name="item_type_id", referencedColumnName="id") - */ - protected $item_type; - // battery size id, loosely coupled /** * @ORM\Column(type="integer") @@ -67,17 +60,6 @@ class TradeInPrice return $this->price_tier; } - public function setItemType(ItemType $item_type) - { - $this->item_type = $item_type; - return $this; - } - - public function getItemType() - { - return $this->item_type; - } - public function setItemID($item_id) { $this->item_id = $item_id; diff --git a/templates/trade-in-pricing/form.html.twig b/templates/trade-in-pricing/form.html.twig index 77198fe2..fc878824 100644 --- a/templates/trade-in-pricing/form.html.twig +++ b/templates/trade-in-pricing/form.html.twig @@ -34,17 +34,6 @@ -
-
-
- -
-
-
@@ -57,7 +46,9 @@ ID Name - Price + Motolite + Premium + Other @@ -65,7 +56,15 @@ {{ id }} {{ item.name }} - + + + + + + + + + {% endfor %} @@ -89,7 +88,6 @@ initialize(); function initialize() { init_price_tier_dropdown(); - init_item_type_dropdown(); } function init_price_tier_dropdown() { @@ -128,7 +126,6 @@ function update_table(data) { item_html += ''; item_html += '' + item.id + ''; item_html += '' + item.name + ''; - item_html += '' + item.item_type + ''; item_html += ''; item_html += ''; item_html += ''; -- 2.43.5 From 59c65235b7bc52724061202246e4fc77de59b9ec Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Wed, 7 Feb 2024 04:31:13 -0500 Subject: [PATCH 3/5] Add saving of prices. #789 --- src/Controller/TradeInPricingController.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Controller/TradeInPricingController.php b/src/Controller/TradeInPricingController.php index 001d565b..3b81ed22 100644 --- a/src/Controller/TradeInPricingController.php +++ b/src/Controller/TradeInPricingController.php @@ -48,6 +48,15 @@ class TradeInPricingController extends Controller return $this->render('trade-in-pricing/form.html.twig', $params); } + /** + * @Menu(selected="trade_in_pricing") + * @IsGranted("trade_in_pricing.update") + */ + public function formSubmit(Request $req, EntityManagerInterface $em) + { + $pt_id = $req->request->get('price_tier_id'); + } + /** * @IsGranted("trade_in_pricing.update") */ -- 2.43.5 From 8804818828faab01de29230b8eb04afcf3ce7c83 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Wed, 7 Feb 2024 22:27:57 -0500 Subject: [PATCH 4/5] Fix issues found during testing of update of trade in prices. #789 --- src/Controller/TradeInPricingController.php | 66 ++++++++++++++++++++- templates/trade-in-pricing/form.html.twig | 8 ++- 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/src/Controller/TradeInPricingController.php b/src/Controller/TradeInPricingController.php index 3b81ed22..db9d08e6 100644 --- a/src/Controller/TradeInPricingController.php +++ b/src/Controller/TradeInPricingController.php @@ -55,12 +55,74 @@ class TradeInPricingController extends Controller public function formSubmit(Request $req, EntityManagerInterface $em) { $pt_id = $req->request->get('price_tier_id'); + + // get the trade in prices + $motolite_tips = $req->request->get('motolite_tip'); + $premium_tips = $req->request->get('premium_tip'); + $other_tips = $req->request->get('other_tip'); + + // get the battery sizes + $bsizes = $em->getRepository(BatterySize::class)->findBy([], ['id' => 'asc']); + + // on default price tier + if ($pt_id == 0) + { + // default price tier, update battery size trade in prices + // NOTE: battery size trade in prices are stored as decimal + foreach ($bsizes as $bsize) + { + $bsize_id = $bsize->getID(); + if (isset($motolite_tips[$bsize_id])) + $bsize->setTIPriceMotolite($motolite_tips[$bsize_id]); + + if (isset($premium_tips[$bsize_id])) + $bsize->setTIPricePremium($premium_tips[$bsize_id]); + + if (isset($other_tips[$bsize_id])) + $bsize->setTIPriceOther($other_tips[$bsize_id]); + } + } + else + { + // get the price tier + $price_tier = $em->getRepository(PriceTier::class)->find($pt_id); + + $pt_tips = $price_tier->getTradeInPrices(); + + // clear the tier's trade in prices + foreach ($pt_tips as $pt_tip) + { + $em->remove($pt_tip); + } + + // update the tier's trade in prices + foreach ($bsizes as $bsize) + { + $bsize_id = $bsize->getID(); + + $new_tip = new TradeInPrice(); + + $new_tip->setPriceTier($price_tier) + ->setItemID($bsize_id); + + $new_tip->addMetaInfo(TradeInType::MOTOLITE, $motolite_tips[$bsize_id] * 100); + $new_tip->addMetaInfo(TradeInType::PREMIUM, $premium_tips[$bsize_id] * 100); + $new_tip->addMetaInfo(TradeInType::OTHER, $other_tips[$bsize_id] * 100); + + // save + $em->persist($new_tip); + } + } + + $em->flush(); + + return $this->redirectToRoute('trade_in_pricing'); } /** * @IsGranted("trade_in_pricing.update") */ - public function tradeInPrices(EntityManagerInterface $em, $pt_id, $ti_type) + public function tradeInPrices(EntityManagerInterface $em, $pt_id) { $pt_prices = []; @@ -119,7 +181,7 @@ class TradeInPricingController extends Controller $data_items[] = [ 'id' => $bsize_id, 'name' => $name, - 'motolite_tip' => $actul_motolite_tip, + 'motolite_tip' => $actual_motolite_tip, 'premium_tip' => $actual_premium_tip, 'other_tip' => $actual_other_tip, ]; diff --git a/templates/trade-in-pricing/form.html.twig b/templates/trade-in-pricing/form.html.twig index fc878824..e45f6cd0 100644 --- a/templates/trade-in-pricing/form.html.twig +++ b/templates/trade-in-pricing/form.html.twig @@ -127,7 +127,13 @@ function update_table(data) { item_html += '' + item.id + ''; item_html += '' + item.name + ''; item_html += ''; - item_html += ''; + item_html += ''; + item_html += ''; + item_html += ''; + item_html += ''; + item_html += ''; + item_html += ''; + item_html += ''; item_html += ''; item_html += ''; } -- 2.43.5 From a0d9d1287ab8e0028b4460bdb1f4e26d5de3a901 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Thu, 8 Feb 2024 04:32:34 -0500 Subject: [PATCH 5/5] Modify trade-in invoice rule to use price tiers. #789 --- src/InvoiceRule/TradeIn.php | 39 ++++++++++++++++++++++++-------- src/Service/InvoiceManager.php | 2 +- src/Service/PriceTierManager.php | 36 +++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 11 deletions(-) diff --git a/src/InvoiceRule/TradeIn.php b/src/InvoiceRule/TradeIn.php index 8e3c6063..b7427b11 100644 --- a/src/InvoiceRule/TradeIn.php +++ b/src/InvoiceRule/TradeIn.php @@ -6,8 +6,17 @@ use App\InvoiceRuleInterface; use App\Ramcar\TradeInType; +use App\Service\PriceTierManager; + class TradeIn implements InvoiceRuleInterface { + protected $pt_manager; + + public function __construct(PriceTierManager $pt_manager) + { + $this->pt_manager = $pt_manager; + } + public function getID() { return 'trade-in'; @@ -17,10 +26,14 @@ class TradeIn implements InvoiceRuleInterface { $items = []; + $pt = $criteria->getPriceTier(); + // get the entries $entries = $criteria->getEntries(); foreach($entries as $entry) { + // TODO: this might need some changes once merged with the + // rider app changes $batt = $entry['battery']; $qty = $entry['qty']; $trade_in_type = null; @@ -30,7 +43,7 @@ class TradeIn implements InvoiceRuleInterface if ($trade_in_type != null) { - $ti_rate = $this->getTradeInRate($batt, $trade_in_type); + $ti_rate = $this->getTradeInRate($batt, $trade_in_type, $pt); $qty_ti = bcmul($ti_rate, $qty, 2); @@ -60,21 +73,27 @@ class TradeIn implements InvoiceRuleInterface return null; } - protected function getTradeInRate($battery, $trade_in_type) + protected function getTradeInRate($battery, $trade_in_type, $pt_id) { $size = $battery->getSize(); + $size_id = $size->getID(); - switch ($trade_in_type) + $tip = $this->pt_manager->getTradeInPrice($pt_id, $size_id, $trade_in_type); + + if ($tip == null) { - case TradeInType::MOTOLITE: - return $size->getTIPriceMotolite(); - case TradeInType::PREMIUM: - return $size->getTIPricePremium(); - case TradeInType::OTHER: - return $size->getTIPriceOther(); + switch ($trade_in_type) + { + case TradeInType::MOTOLITE: + return $size->getTIPriceMotolite(); + case TradeInType::PREMIUM: + return $size->getTIPricePremium(); + case TradeInType::OTHER: + return $size->getTIPriceOther(); + } } - return 0; + return $tip; } protected function getTitle($battery, $trade_in_type) diff --git a/src/Service/InvoiceManager.php b/src/Service/InvoiceManager.php index 8f655224..31868ba7 100644 --- a/src/Service/InvoiceManager.php +++ b/src/Service/InvoiceManager.php @@ -55,7 +55,7 @@ class InvoiceManager implements InvoiceGeneratorInterface new InvoiceRule\Fuel($this->em, $this->pt_manager), new InvoiceRule\TireRepair($this->em, $this->pt_manager), new InvoiceRule\DiscountType($this->em), - new InvoiceRule\TradeIn(), + new InvoiceRule\TradeIn($this->pt_manager), new InvoiceRule\Tax($this->em, $this->pt_manager), ]; } diff --git a/src/Service/PriceTierManager.php b/src/Service/PriceTierManager.php index 62d657f4..ae1b0125 100644 --- a/src/Service/PriceTierManager.php +++ b/src/Service/PriceTierManager.php @@ -7,6 +7,7 @@ use Doctrine\ORM\EntityManagerInterface; use CrEOF\Spatial\PHP\Types\Geometry\Point; use App\Entity\PriceTier; +use App\Entity\TradeInPrice; class PriceTierManager { @@ -51,6 +52,41 @@ class PriceTierManager return $actual_price; } + public function getTradeInPrice($pt_id, $battery_size_id, $trade_in_type) + { + // find the trade in price, given the price tier and battery size id + $db_conn = $this->em->getConnection(); + + $tip_sql = 'SELECT tip.meta_info AS metainfo + FROM trade_in_price tip + WHERE tip.price_tier_id = :pt_id + AND tip.item_id = :battery_size_id'; + + $tip_stmt = $db_conn->prepare($tip_sql); + $tip_stmt->bindValue('pt_id', $pt_id); + $tip_stmt->bindValue('battery_size_id', $battery_size_id); + + $tip_result = $tip_stmt->executeQuery(); + + $actual_tip = null; + + // go through the rows + while ($row = $tip_result->fetchAssociative()) + { + // get the price + $meta_info = $row['metainfo']; + $metadata = json_decode($meta_info, true); + if (isset($metadata[$trade_in_type])) + { + $tip = $metadata[$trade_in_type]; + + $actual_tip = number_format($tip / 100, 2, '.', ''); + } + } + + return $actual_tip; + } + public function getPriceTier(Point $coordinates) { $price_tier_id = 0; -- 2.43.5