From 3b7bdd1d14f56c555caf234e8d8f0607013a8fc3 Mon Sep 17 00:00:00 2001 From: Hotlander Date: Wed, 17 Nov 2021 10:16:59 +0100 Subject: [PATCH] Squashed 'package/marello/' changes from 73c2e39ff5..d80705c83c d80705c83c Merge branch 'release/3.1' b7df2ced63 Merge commit '8ef804780109269a9d0078c99b98f46751d8b922' 9be5bc3877 Merge commit '1a6e4842329a1d135e43cd5092e0a40660ddb3fd' 0dcab9ced7 - updated dev.json/dev.locks - added missing translations - psr fixes - updated package-json's 9465afdc47 - fixed layout on payment popup on Invoice/Creditmemo 968dfcf75c - Added product unit as additional information to OrderItem on order create 29cd362aac - Uncommented previously commented for no obvious reason on the OrderItemType - Fixed translation on workflow e060f3794a - Added view page for inventory batches - added changes regarding navigation around inventory and inventory batches - updated layout on inventory batch pages 2d0aee8f24 - added manage batches inventory link on inventory level grid on inventory item view 9e68b871b3 - Fixed product name in datagrid for inventory item / balanced inventory level grid not being updated after changing the product's name 000dcf379c - Added taxIdentificationNumber below company number on invoice entity view 5a41136389 Merge branch 'bugfix/MAR10001-970-batch-allocation' into develop 6e84022f8d - Added small changes for batches; - added delivery date to batch form e78d01e15f - Fixed issue with selecting organization when creating products and purchase order debbd9f0db - fixed inventory batch condition that didn't add the correct amount for a batch to a packingslip a8317801d2 - Added organization to query for finding a specific sku for an organization 5f4f0254d3 - removed old query reference 83badc9bf2 bugfix/MAR10001-888-reports-per-organisation: - updated queries to cover organisation restriction 2bd300f915 - Added different calculation for total due on order view 287750fecb - Fixed issue with loading images during demo install - Fixed groupBy issues with products grid 4c6a058db5 - Changed to Autocomplete for Customers to FullNameSearchHandler instead of the default searchhandler to include fullname 1e1a5486e6 Merge branch 'develop' into feature/MAR10001-930 dbc8defaa3 - Added additional check to see which query needs to be running for updating tax_identification_number based on db driver ee01c68790 - added hasColumn() checks on fields that might already be added in previous version 1a3639e998 - changed conditional statement in checking wether the width needs to be applied to the logo of the pdf 31edb26d40 - Fixed idententation to match all others for actions.yml file - added additional css classes to make sure there is space between buttons of pdf and payment - added is_granted to pdf download button 01cf685ba1 - Added fix for query on postgresql where customer tax identification is copied to company tax identification 5ba6a0387a Merge branch 'develop' into feature/MAR10001-894 167914be40 Merge branch 'bugfix/MAR10001-0-apply-fixes' into develop 430ab3bb43 - Added minor fixes to purchase orders view and form dde294954d - Added possibility to update cost via marello-supplier-product-grid bd610c9fe6 Merge commit 'ffba2a1d74fe5713fd615d1fb3b6980a41cb9f31' into maintenance/3.0 dd1fc54c82 Merge commit 'f497f93ca471ade418553eea3289318a7c4bca23' into maintenance/3.0 193d3fea6f Merge commit '71530acca5abd305f2c328d3f74bb414c1b89844' into maintenance/3.0 3baa45e432 Merge commit '0bcb9bb847396efc745579839904136a8252ed58' into maintenance/3.0 668807adf4 Merge commit 'e779b8a1796d417078e3a9dfe89b0474e462caac' into maintenance/3.0 9a5de91019 Merge commit '4f68dc37da2773e1c4f6cee4e165f7a441154a90' into maintenance/3.0 91d136e4c4 Merge commit 'd34d82be891e77a23fd995c71dbfd92b8542ca00' into maintenance/3.0 206a89b737 Merge branch 'bugfix/MAR10001-0-add-additional-check-customer-address-in-order-create' into develop b383b8138d - Added additional info on runtime exception for Product create/update if no default name is given - Added additional check on loading customer address when creating an order and the primary address is empty 96d3c3da5f - Removed redundant variable provider, functionality is already included in Marello\Bundle\ProductBundle\Twig\Provider\ProductUnitVariablesProvider 497285847f - Added translations to Payments datagrid on Order and Invoice views that reflect the datagrid data afe10013b2 Merge branch 'develop' into feature/MAR10001-935 b80a45a604 Merge branch 'bugfix/MAR10001-0-purchaseorder-item-api' into develop 2a9faf61cd - added additional check before loading the purchase price in the Purchase Order Item 2b1ffd9160 Merge branch 'task/MAR10001-0-added-extended-view-support-for-saleschannel' into develop 40d84ffe1d - Added support to display extended fields on SalesChannel view & grid 3396437ff1 Merge branch 'bugfix/MAR10001-0-add-extended-entity-names-to-datagrids' into develop b943ecde6d - fixed issue with extended_entity_name in datagrid on the wrong spot in the configuration 4272c01b92 Merge branch 'bugfix/MAR10001-0-add-extended-entity-names-to-datagrids' into develop 8ea2cd21c2 - added extended entity names to datagrids - added additional filters to balanced inventory level datagrid f409304860 Merge branch 'feature/MAR10001-0-add-option-to-remove-product-from-website-only' 42f96be742 Merge branch 'bugfix/MAR10001-957-Company-validation-fails-on-update' into develop d4ffe67899 - Updated validation for company number as it was wrongly failing the validation when updating the company itself and not having another company using this number e9bdca05ad Merge branch 'bugfix/MAR10001-966-product-categories' into develop b80ea4d666 - updated product category grid on the category view to take the localized value of product name into account 52ea970fdc Merge branch 'bugfix/MAR10001-499-Filtering-SalesChannel' into develop 68a34c4f05 - Fixed issue with SalesChannels in colomn not being rendered in the Product grid - Fixed issue with SalesChannel filter in the Product grid e997c2938b Merge branch 'bugfix/MAR10001-0-fix-order-reference-filter' into develop 576d4b4f84 - changed type of OrderReference filter to string in order data grid to filter correctly (changed filter type from number to string) d455e77b8e Merge branch 'task/MAR10001-0-add-acl-config-to-tax-related-entities' into develop d47846ac55 - added default ACL config value for Tax Related entities 57e9233303 Merge branch 'task/MAR10001-0-layout-fixes' into develop 7f3d36c199 - fixed issue with rendering customer view where brackets where missing - added block identifiers in purchase order view to target blocks easier with event listeners - renamed duedate label to expected delivery date, due date field only has renamed labels for this - updated PO form view listener to add the WH delivery to the billing and shipping info block on the form - added general and additional ui section label translations in core bundle - updated validation for due date as it did get stuck when due date was in the past and validation for the whole PO was done c59a474ba0 Merge branch 'task/MAR10001-0-skip-configurables-magento-integration' into develop 69df3b84b5 - fix issue with trying to display data based on an entity that isn't available 635b95d3bd Merge branch 'task/MAR10001-0-skip-configurables-magento-integration' 78bff7f0ce - Added shipping method details to store additional information regarding the shipping method on the Marello Order 6a1f95564c Merge branch 'task/MAR10001-0-add-additional-dynamic-entity-fields' into develop cbc7d50021 - Added rendering for additional data block with dynamic entity fields 359e5f74ba Merge branch 'task/MAR10001-0-add-force-flush-option-to-inventory-level-record' into develop 3b49897071 - Added context option check for forceFlush in the inventorylevellogrecord b256f6567d Merge branch 'task/MAR10001-0-validation-fixes' into develop 6e8fc2bac8 - Updated validation groups for Order validation - Added SKU to the available inventory validation message d3b061686c Merge branch 'bugfix/MAR10001-0-calculation-packingslipitem-weight' into develop 10f5e5a917 - added additional data block on PackingSlip view - Updated weight calculation by multiplying it with the orderItem quantity in order to show the total weight for the row instead of the individual unit 298078c1fb Merge branch 'maintenance/3.0' 4d029e0a1d Merge branch 'bugfix/MAR10001-0-change-forbidden-exception' into develop 9d33c6381c - Added Symfony\Component\Security\Core\Exception\AccessDeniedException instead of Oro\Bundle\SecurityBundle\Exception\ForbiddenException in the ReturnController as this class has been removed - Added translation for exception for clarification dd4f67f6c9 Merge branch 'task/MAR10001-0-url-encode-magento-sku' into develop 76800e09e4 - remove enum field with OWNER_CUSTOM from form type in ReturnItem form as this will be managed by the platform itself - fix small issue with upgrade to 1_3_x versions for SalesBundle as it might already have a foreinkey relation which doesn't allow for the unique index removal 342c799e17 - added url encoding for SKU in requests to Magento as it might have slashes in the sku - removed validation from items in Marello order as it seems like the Count validation is not properly going of or validating the data correctly for some reason... 1ba0c3e52a multiple fixes 5ccbb54a33 multiple fixes 6f34f88cbf Merge branch 'maintenance/3.0' b48c0cc790 Merge commit '63f5e481b1b580ab73bcf6fd1d98fa0ba7595542' into maintenance/3.0 e19f59023c Merge branch 'maintenance/3.0' of https://github.com/marellocommerce/development-mono-repository into maintenance/3.0 817c626ab9 - added default weight to products to prevent issues with assigning WH's in Packingslips and issues with shipment creation for UPS - Added migration that will update the default weight for products that don't have a weight yet (null) 68db65f41d - added additional check on order view to make sure a customer exists on the order before trying to render properties of the customer 00cc1f1002 Merge branch 'maintenance/3.0' into develop 4f65e8c8fb MM-42: Test and fix functionality (#66) 92bfd1afaa MM-42: Test and fix functionality (#65) a8bacc7078 MM-40: Test and fix import order functionality (#63) 4817829be9 MM-38: Implement sync processors (#61) 019a1bf6b1 MM-35: Fix issue 'Removed special product price won't sync on Magento side' (#58) e03adedeaa Merge branch 'task/MAR10001-0-fix-productUnit-issue-email-template' into develop d7558a553b - added non proxy class of the Marello Product Unit as without this it can cause issues when the 'normal' class is used to send templates instead of the Proxy class of the product unit 8e3b617483 Merge branch 'task/MAR10001-0-fix-default-value-for-data-property-on-entities' into develop c81490c68e - Added default value for $data property as in most cases it will expect an array even if the data is not set on an Entity 172732b53d Merge branch 'task/MAR10001-0-added-product-unit-twig-variable-provider' into develop 314229d087 Merge branch 'task/MAR10001-0-fix-shipping-context' into develop 5396e6dc3d - updated email templates with name variable for ProductUnit - updated migration version for the application to load the new templates 3dedc0dcd4 - added ProductUnit variable provider for rendering the product unit in the email templates as this is an enum field which is behaving as an extended entity with a proxy class that wasn't allowed in the email templates d037f75e6c - Added the shipping origin based on WFA rules back for shipping methods that use the origin to determine shipping costs, the addres of the warehouse remains an estimation 9ea3dafb87 Merge branch 'task/MAR10001-0-fix-checking-wrong-field-for-available-inventory' into develop 7e8e448b99 - updated field to check for available inventory, it used the balanced inventory instead of the inventory qty which is the qty that is left from the balanced inventory 38d1fc24f1 - removed check that was going through the WFA rules that wasn't necessary for either Payment methods and Shipping methods on the Order creation 2421b27ff5 MAR10001-935: Payment updates 2 4e5e08104a - fixed renaming email templates for Order and Invoice notifications 737ea2f0be - Updated email templates with new style 5ec1a6a54e Merge branch 'task/MAR10001-0-fix-orocommerce-integration-with-updated-filter' into develop 21fea86fc7 - updated WorkflowstartListener test to check new behaviour of the OrderWorkflowStart 3e8649c6a0 - Fixed issue with WorkflowStartListener where only the last order id (which came in batches) was getting a workflow start 12028a44c2 Merge branch 'task/MAR10001-0-fix-orderitemstatus-dashboard-widget' into develop ebd3a4ee2f - Removed statuses that are NULL from the OrderItemStatus dashboard widget as they cannot be displayed correctly d4a4faec3e - added order status change for 'new' workflows in Marello 5f76351b57 Merge branch 'task/MAR10001-0-add-order-status' into develop a2edc86b63 - added Order status to Order which will serve as preparation for the next step in the Order Management - currently no critical parts are relying on the new Order status as of yet, it's also not visibile in the current implementation afba749090 Merge branch 'bugfix/MAR10001-0-fix-inventory-item-grid' into develop 1606b21a2f - renamed table alias as the datagrid was confused which one was the actual table and which one was the column of the ProductUnit in the InventoryItem grid a032ac46b9 - split the SalesBundle migrations as v1_3 was already released... 8f45f4f4da Merge commit '7d530c86aa0b89d4eb35d4c3572aa82061ee76fe' into maintenance/3.0 c55e72c5b9 Merge branch 'task/ZON20001-0-update-m2-bundle' into maintenance/3.0 2e3c05c2ab Merge commit 'e2af974edb72ae5923ecdf4dd34249e13ebf9f31' into maintenance/3.0 42ab5e4e49 Merge branch 'feature/MAR10001-0-add-quantity-of-unit-inventory-item' into develop e79f8ea1bd - renamed migrations to take newer versions of migrations into account on the develop branch 466e26f915 Merge branch 'feature/MAR10001-0-add-quantity-of-unit-inventory-item' into develop 616a370e64 - updated return notifications with ProductUnit on line items - added migration to update existing templates cd12386aa2 - updated email templates with Product Unit on the line items - Added migration to update email templates in existing installations 12edb4db24 - updated grids to include productUnit - updated PDF providers to include ProductUnit in PDF's - updated mappers either get the unit from the OrderItem or null e0560e386f - renamed unitOfMeasurement in InventoryItem to use the ProducUnit to keep it consistent in all entities having this relation - added ProductUnit to PackingSlipItem and InvoiceItem, InvoiceItem uses a different approach because it has a inheritance table and the EntityExtendBundle didn't really like this setup by adding an Extended field ddba1708e0 - updated test to check for the Unit Of Measurement being set on the OrderItem after the Order is saved e1f528d5a2 - Updated OrderItemProductUnitListener to first check the InventoryItem for a UnitOfMeasurement before going straight to the default, the previous logic for checking it's empty before assigning is still in place - Updated service definition of the OrderItemProductUnitListener to use the InventoryItemManager and get the necessary data from there instead of only using the DoctrineHelper c14755b41e - Added unitOfMeasurement to the InventoryItem view 67b17f04d3 - added unitOfMeasurement to InventoryItem grid with filters and sorters c1c8675b6d - Added unitOfMeasurement to InventoryItem - Updated tests for UoM - Added translations for inventory item UoM - Added default UoM when product is created (which is followed by creating and attaching the InventoryItem) 3362d3e39b Merge branch 'task/MAR10001-0-fix-unique-indexes-customer-addresses' into develop 724c55a6a4 - removed unique index on Customer primary/shipping address as it is a theoretical posibility that they are exactly the same address b74710116b Merge branch 'feature/magento2-integr' into task/ZON20001-0-update-m2-bundle 8700025844 Merge branch 'task/MAR10001-932-add-validation-to-Order-delivery-date' into develop 34f464d5e0 Merge branch 'task/MAR10001-0-price-alignment' into develop 95890e1169 Merge branch 'task/MAR10001-0-add-replenishment-field-to-variant-grid' into develop fdc275034e Merge branch 'task/MAR10001-0-add-replenishment-field-to-variant-grid' into maintenance/3.0 5a601552df Merge branch 'task/MAR10001-932-add-validation-to-Order-delivery-date' into maintenance/3.0 bd669d4e5c - Added the replenishment field to the variant grid for seeing continuation of the product d67deb0175 - fixed some price alignment, not specifically to the right, but at least in line with each others TH; - even though Oro's right aligment did work, it only worked with a 'crowed' table, as soon as only a few columns are in the grid, the whole things 'falls apart' and are not actually aligned to the right aaabab0bb2 - added validation message for DeliveryDate if date is not set in the future 8e7eaf7e1d - Added deliveryDate validation to make sure the date is set in the future and not in the past 3b22e634fa Merge branch 'bugfix/MAR10001-938-ghost-warehouse-after-switching-type' into develop cd34253b36 MM-29: Add functionality to map relation between website and sales_channel on the integration form (#54) e4636cbefc Merge branch 'bugfix/MAR10001-0-update-taxes-when-shipping-address-does-not-have-region-in-customer-address' into develop 86acde5686 Merge branch 'bugfix/MAR10001-941-po-recalculation-advised-products' into develop abb022df84 Merge branch 'bugfix/MAR10001-941-po-recalculation-advised-products' into maintenance/3.0 0bfbba2440 - updated condition to trigger the tax calculations for Order rows when creating an Order through the GUI - previously the calculation wouldn't trigger because the region was not set in the customer's shippingAddress 8af7a756af - fixed issue with recalculation not being triggered when items in the advised grid are either updated with an amount or quantity - added additional trigger / listener to trigger the recalculation in this collection 1e8ba0254c - updated explictly assigning of status for payments that have a source selected - fixed filtering related entities when updating a payment without a source assigned 764ded7fb5 - fixed unique constraints format...again :') de1cf1ddcf Merge branch 'bugfix/MAR10001-939-cannot-complete-replenishment-order' into develop a120078366 Merge commit 'c5697c673a4193f88c63e21e067f6b4142305400' c5697c673a Squashed 'applications/marello-application/' changes from 3a5a0ae59..ce3588041 9529d24ca5 Merge commit '0434749faa01bc372d0f6507d95e6c63b21d687a' into maintenance/3.0 d089cd443f - remove disabled code from SalesChannelType form type a4a6ba91b2 Merge branch 'feature/magento2-integr' into testmerge-magentoint b8e33d0c8f - removing BC break from order view regarding payments 2ab0e17cd5 - fixed issue with Migration where it was trying to create the order table on updating the application while it already exists - fixed issue with association name in the Enum field being inconsistent between the installer and the migration - Added additional enum options such as Box and Pallet c91a5a6ef2 MAR10001-931: Update Order and OrderItem entities with additional fields 49321bf5b1 Merge branch 'feature/MAR10001-931' into develop a598e0492f - fixed issue with Migration where it was trying to create the order table on updating the application while it already exists - fixed issue with association name in the Enum field being inconsistent between the installer and the migration - Added additional enum options such as Box and Pallet dae77eb2c2 Merge commit '2d726c233b9ee46e8df989abddab3e08d8d7a417' into maintenance/3.0 adce2c73eb - fixed issue with checking companyNumber on null while trying to render the PDF template b4aaca2a15 - fixed issue with check on Payment term when rendering the pdf once downloaded - Some cs fixes in the payment bundle department 05b90c397a - fix OrderExtension test to include the new twig functions 676420e632 Merge branch 'feature/MAR10001-920' into develop 7c21b23895 MAR10001-931: Update Order and OrderItem entities with additional fields 594e0cb6f4 Merge branch 'maintenance/3.0' into develop bde099601c - fixed issue with misquoting the columns on the unique constraint in the Company entity 9b975a725c Merge commit '171e747c96d54e8f0821d6c20507350aafa607d3' into maintenance/3.0 498af6f3de MAR10001-930: fixes for filtration on products grid b1dac57f09 MM-26: Test and stabilize product sync feature - Fixed issue with check connection on existing integration - Fixed issue with invalid transformations of pricing value triggers update prices on every save of product form 2b455f4c3e Merge branch 'maintenance/3.0' into develop 67af315d08 - removed commit reference in validation file 06abfd1d3f Merge branch 'maintenance/3.0' into develop 5bacf821b9 Merge commit 'eb90b8fcfaedb948656084d945666cfebbe15532' into maintenance/3.0 98738fb60e Merge branch 'feature/MAR10001-909' into develop f0c0ac9f5d - renamed Company code to Company number - added pdf translation - moved company number on the PDF 0d171513d8 MAR10001-909: Add Company ID to Company 2e94a890c3 - renamed Company code to Company number - added pdf translation - moved company number on the PDF c9ae8ff004 MM-25: Add logic for product prices and inventory synchronization (#50) c71fba9cfb Merge branch 'task/MAR10001-0-qol-fixes-orocommerce-bridge' into develop 32f24758d1 - fixed issue with installing by updating the OrderBundle Installer by updating the migration version to the correct version - fixed issue with shipping_method_reference setter on the Order entity, the setter needed to accept that it can be null e042a219a8 Merge branch 'task/MAR10001-0-qol-fixes-orocommerce-bridge' into develop d2dec90d1e - Added Shippingmethod reference as new field to the Order entity - Removed shippingmethod validation from the commerce validation group on the Order entity - added translation for shipping method reference - updated Order view layout to have all the source references (order reference, invoice reference and shippingmethod reference) in the same block and below the customer information 34bb0dd58f MAR10001-909: Add Company ID to Company e8489d2fb9 Merge branch 'maintenance/3.0' into develop 177f7c0781 MAR10001-909: Add Company ID to Company bf663180db Merge commit 'c3d7d6c1d492f690fe42956c139d0ead4c8a26cf' into maintenance/3.0 440aa90b1d Merge commit 'b065d549972a67f4a7ee98e2774243a9e2b80092' into maintenance/3.0 88e77d1529 - Removed replenishment enum field from InventoryItem form type as this has already been added through the DynamicFieldsExtension 9c8e8076ba Merge commit '39e05989e588eb7890665615fcc9b727f1c1f47e' into maintenance/3.0 4ac8519a49 Merge branch 'task/MAR10001-0-qol-fixes-orocommerce-bridge' into maintenance/3.0 bc363a6d7c - added missing validator translations regarding shipping method rules and configs 739457eee9 - updated validation regarding Customer, Company and Address - moved the validation to the correct bundles instead of having it all in the OrderBundle validation file 511b6e95ed MM-13: Implement initial products export (#49) 99bce0c3bd Merge commit '04ca95074be3a990fed20bc103c82c73a59c7ef7' into maintenance/3.0 27b7d0ba76 Merge branch 'task/MAR10001-0-qol-fixes-orocommerce-bridge' into develop 0f282598df - updated email SendProcessor to do not send emails or try to send emails when the recipients array is empty - updated validation groups for the Order entity to be able to save Orders without a Customer for the commerce group a24a263ce1 - updated data attribute of order to make sure when creating a new order via `new Order()` will have the data attribute as an array instead of null 9be493eebb - Updated OrderWorkflowStart event listener's service definition to inject doctrinehelper 05c200e5f6 - updated OrderWorkflowStart listener to use the doctrine helper from Oro to get the correct entity manager for the class instead of the event's entity manager e52f270e05 MAR10001-930: Cache seems to be invalidated quite frequently which results in pages being visited before increased loading times 29637429e6 - fixed issue with product duplication error when the action group registry is not a public service anymore, created a provider that injects said service and retrieving it via the provider that has been created as a public service dbd2f97b96 MM-23: Add logic to process changes in integration (#47) a9d817e4f2 - dropped unique index on integration ID on SalesChannel to allow a SalesChannelGroup with multiple SC's be connected to the integration - moved some fields around in the integration settings form - updated the OroCommerce integration event listener to take into account the integration is now linked to a SalesChannelGroup and not a single SalesChannel a0cbca0bad - removed required asterisk from Description on SalesChannel as this is not a required field 3c1a361456 - removed required asterisk from description as this is not required in the SCG 821b86b812 MAR10001-920: Payments Update 3b20f616b5 MM-22: Add logic to process changes in Sales Channel (#46) 0444679822 MAR10001-920: Payments Update dcc2fabbd7 MM-8: Add logic for tax class dictionary synchronization (#45) 679b16e1b4 MAR10001-920: Payments updates 8f5ab0ba92 MAR10001-920: Payments updates 640b21f1b1 Merge branch 'feature/MAR10001-911' into develop 7e5614fad8 - fix issue of search handler test where the actual search handler changed implementation slightly to let the unit test fail 73d2e6bb7f MM-6: Prepare logic for dictionary synchronization (#40) 0b932eced6 Merge commit 'fea3dea76b8b638d7f79d8b3708f785be7354814' into maintenance/3.0 a1fceaada0 Merge commit 'bde1161731d733d62102ae203244ae6f28810003' into maintenance/3.0 606a41d0a2 - fix issue of search handler test where the actual search handler changed implementation slightly to let the unit test fail e52e0f3e41 - fixed issue with updating the application from 3.0.x to 3.1 during issues updating indexes on columns that don't exist 6e88347657 - CS fixes aeb67039fd MAR10001-911: Update Product with SKU and organization unique index 4437b85ee7 Merge branch 'feature/MAR10001-791' into release/3.1 faf4093a73 Merge branch 'task/MAR10001-0-add-grid-view-labels' into develop 669afa36a2 - added entity_grid_all_view_label to all relevant entities on CE 32b5734247 MAR10001-911: added migrations 9e3545bc8c - updated pricing js views in order to be able to disable channelpricing without errors in the console 3aa0841106 - updated pricing js views in order to be able to disable channelpricing without errors in the console 685674d73a - added invoice type to the invoice/creditmemo view for clarification 9d2ae719b9 MM-4: Create Magento2 integration form - Added missed constraints 8e21fd8af5 - fixed issue with incorrect route names in the entity config of the AbstractInvoice entity which prevented users from using the entity management on Invoice related entities - fixed some of the confusing labels as creditmemo's were labled Invoice instead of Creditmemo 4bcba3217a - fixed functional of POcrons tests by updating the groupby clause in ProductRepository 80c43c3a94 MM-4: Create Magento2 integration form 5eb0c19071 - CS fixes - updated migrations to include indexes on tables that collide with a OroCommerce installation on PostGreSQL 59c349e61e - fixed InvoiceDownload functional test, name of pdf changed during changes made for creditmemo 67409dbf06 Merge branch 'maintenance/3.0' into feature/MAR10001-870 ee18f241b3 - updated creditmemo/invoice pdf's with company from the customer address instead of the Company from the customer itself - updated the address widget to include the company from the address to display on different views like Order, Invoice etc.. dff415a0b0 - added pdf template for creditmemo - added requesthandler for creditmemo pdf - updated translations for creditmemo pdf - added company to pdf's afc9de31d1 - added company to invoice view - moved company above the 'general' customer info on order view - added company to invoice pdf 1688dde2fc - removed `selectAll` from datagrids that were having issues with selecting rows only when having pgsql as db driver f656b27a94 Merge branch 'task/MAR10001-901-balanced-inventorylevels-disabled-products' into maintenance/3.0 2b1c222a8d - Updated (balanced) inventory grids to have most of the same columns in the same order as the Product grid - Added additional checks for disabled products before balancing and checking saleschannels that are actually assigned to the saleschannelgroups that will be available for balancing - Added additional listeners for rebalancing and resetting the balancedinventory levels when ProductStatus is changed and Saleschannels are assigned or removed from the product 7e3d730b3f - Fixed inventory levels on inventory item view when having PostgreSQL as db driver c697c71be1 Merge branch 'maintenance/3.0' into feature/MAR10001-870 9d776755be MAR10001-791: Marello Payments - fixed functional tests - fixed Invoice totalPaid, totalDue calculations c25ace73f3 Merge branch 'maintenance/3.0' into feature/MAR10001-791 1c252cd57f MAR10001-870: Creating the OroCommerce integration in Marello 3.0 is having issues with fetching the Attribute Family from OroCommerce e86e6ed294 - updated demo environment with oro 4.1.x - updated custom login page - removed deprecated ways of overriding templates f2f6e7a8d0 Merge branch 'release/3.0.1' into maintenance/3.0 973ae208d7 Merge commit '9f8826c1ed6098ac7a470b99f48436dc693e4026' into release/3.0.1 49b655159b Merge commit 'c8ab65a29b0a1894abb5d30a21f0d712a5db94ae' into release/3.0.1 eddf9768aa Merge commit '1994f4f34847af1a1fd1d9a973fed6d23564aeb8' into release/3.0.1 f1e2b9c6dd Merge commit '0cebbb868afa87ce24298ed4c9ddd449f456838b' into release/3.0.1 889dbf4c36 - Updated 'all time' query to include the start date and not only the date greater than the start date to include all orders 9e37a13263 - CS fixe 80cb2c6d70 Merge branch 'maintenance/3.0' into feature/MAR10001-867 8f9aba150e Merge commit '1994f4f34847af1a1fd1d9a973fed6d23564aeb8' into release/3.0.1 a0c3ea4f15 Merge commit '051c13f9a7cb31707f92cfcd8832c1bc83c6270c' into release/3.0.1 1d257e70a8 Merge commit '9c356b21a489b094195eda075a1b298a95a07813' into release/3.0.1 b3e08131b2 Merge commit '9586a6de30de76d1dacf6808b7c6e547aabb705a' into release/3.0.1 2d66315948 - added check to see if emails are already enabled by the user, otherwise the migration will fail because of it 2c96360025 - fixed issue with sending localized email notifications - fixed shipped order confirmation email template - fixed functional tests for sendProcessor d9471fb432 fixed failed repository e0acbed29c - CS fix - Added fix for existing attributes to configure them correctly to show them in attribute groups and retain the original data 1cc8c922c8 - moved the image of the product view to separate template file in order try to control the divs better 7d5fa0dbcb - switch createdAt and tags columns in product grid using the buildAfter event 7010c4b2ab - added inline editing for product status in product grid 07a07d458a - added inline edit for tags - added inline edit for sku - shuffled some columns around in the product grid - removed taxcode as default column d4ec778e79 - added Product tags in entity config - added migration to enable product tags for existing products fb1e74458a - Added email as activity to Marello Customer which allows to show emails being sent with the Customer as context in the customer view d44ec5ee16 - Added Additional data fields to Order entity - updated div's on the additional data of the product view 20dc7304f9 - updated migrations to deal with postgres update, works on mysql too 1ce83a7bd8 - removed annotations from Customer entity to prevent issues with update schema, when creating fields on entities, when running postgresql a03739881c - Added save and new buttons to SalesChannel and SalesChannelGroup create and update views 13ec79d24a - Added save and new buttons to Tax Jurisdictions, Tax Rates, Tax Rules and Tax Codes on both create and update views 8f7a61c724 merged maintenance/3.0 branch into 3.0-test 16268f1b60 fixed problem with schema update e3a455ee6d Merge branch 'feature/MAR10001-766' into feature/MAR10001-759 b2919ff4bc Merge branch 'feature/MAR10001-759' 02531ac825 made productName not audittable field 304eca194e MAR10001-867: Order statistics error when selecting 'All Time' as Date Range b61fefe5be Merge branch '3.0' into feature/MAR10001-791 f7d47e4683 MAR10001-791: Marello Payments a0a457bd4f - fixed issue with results of the query being used when filtering products through the grid and trying to assign them to saleschannels - added ability to split the message for bigger chunks of data instead of having a single message with a lot of product ids - restructured the code in order to use the entity repository of the products instead of relying on the cached query from the querybuilder - Fixed the main issue of the bug where we couldn't mass-assign products to SalesChannels because the query for the products grid evolved in such a query, which made hard to reset parts of the query for counting and not having to deal with the query cache once the results where fetched 062a9a134d - removed internal version in Marello EE - updated not merged translations - updated version number in EE Readme - updated dev dependencies in EE / CE applications - updated author name in packages's composer.json d992deb85d Merge branch 'develop' into test ccf2ad8602 Merge branch '3.0' into test 68f42ed7fc Merge commit '4531bc1f6d96c73cf6bd961956a99e01a0f6ce64' into test a9c51f6d9a Merge commit '2819c3c3081048e75dd1f381ed7719f52f1a4d62' into test 6c1b25d467 Merge commit '4487e16f32edab5591a323617e90704af2e73109' into test f41eaa1b3c Merge branch '3.0' into develop 501a3df713 - updated environments with :delegated parameter on docker env - added 'final' steps on workflows - removed deletion of old customer data in order to preserve possible extended fields and keep issues with old foreign keys at bay - updated UPGRADE file in order to specify additional step for Marello upgrade to 3.0 for smooth transition - updated README of EE in order to update the current requirements for Marello 3.0 applications 6cc04c42c0 - Added migration to include organization id on the purchase order item 06e994633c - changed path of Invoice template to MarelloInvoiceBundle:Pdf:invoice.html.twig instead of MarelloPdfBundle:Download:invoice.html.twig 3a6a510032 - removed .class parameters from service container and replaced it with the FQCNs 8109ecb47d - removed marello_product.entity.class parameter from service container and replaced it with the FQCN 7fc9dfaeda - removed marello_catalog.category.entity.class parameter from service container and replaced it with the FQCN d12c41ce2b - Merged improvements for PDF capabilities - Updated entities with SalesChannelAwareInterface who were already had a 'getSalesChannel()' method available - Renamed the ChannelAwareInterface to SalesChannelAwareInterface for clarity and consistency - Renamed the old SalesChannelAwareInterface to SalesChannelsAwareInterface to indicate the differences in interfaces, this one will have functions to add, remove and get multiple SalesChannels instead of a single SalesChannel d41e71cce2 - PSR2 CS fixes in PDF/InvoiceBundle 50df90b043 merged branch 3.0 into feature/MAR10001-849 d0e321148f MAR10001-849: PDF Bundle improvements 15034da774 - updated text-extended composer script to run a predefined phpcs.xml - updated packingslip datagrid to fix the issue with the warehouse filter and sorter - updated config yml files in order to fix the issue with API test failing 33e8f5c219 - Updated ProductAttributeControllerTest to test the index but not the actual creation of the attributes, during issues with creating multiple fields - Enabled index test of the ShippingMethodConfigRule of the ShippingMethodConfigsRuleControllerTest as we forgot to enable it after debugging issue with the failed test, also removed debugging logs bf0029c11e - Fixed issue with entity classes defined in the service container instead of using the FQCN b405a9a300 - updated unique keys for certain entities in order to have both the schema's and annotations in line with each other - updated delete operation tests to use the FQCN instead of a service container parameter as entity class 47ee1f552a - Added missing translation labels de3b70e663 - updated check if template is not null to be more strict in the EmailTemplateManager - updated SendProcessorTest with setting the correct exception when trying to find a localized template and there is no result 5a1454fdd6 - Updated unit tests to use and test the new underlying structure of resizing images df22a03877 - Fixed AvailableInventoryValidatorTest by using the correct constructor arguments during the removal of the setDispatcher method 7e3e808a15 - fixed OrderExtensionTest since the OrderItemStatuses have become enum's which are hard to mock during the nature of enums being extended entities, overcoming the issue by creating a stub class which will allow us to mock the class 3164afffe3 - updated unit test with the removal of the warehouse constructor argument for the InventoryItem as this has been removed as it was deprecated e7cb4250ae - Added phpcs.xml file for removing multiple arguments from commandline when running phpcs - updated dev.json to use new arguments when testing psr - fixed last CS of PSR2 since ORM data migrations are now being included in the config 97642d73db - 100% fixed PSR2 issues on the Marello CE edition, excluding the Tests/Migrations directories d6046389f1 - 65% done on PSR2 PHPCS fixes - updated command that will execute the PSR check to exclude migrations and test directories - [WIP]: add phpcs.xml to root directory for a more clean configuration instead of stuffing the command line with .... a895e7a888 Merge branch 'feature/MAR10001-847' into task/MAR10001-0-merge-fixing-price-columns 5cb399c081 - merged updated inventory batch layout and moved some widgets around - updated data migrations of shipping/payment integrations because of the removal of the entity parameter classes of Oro 82491d046c Merge branch 'feature/MAR10001-837' into 3.0 2b21958cfe MAR10001-847: Fix prices in product datagrid 4625f37bb6 - updated to platform 4.1.0 - fixed reference to non-existent parameter 'oro_note.entity.class' 63e0b0c0bb Merge branch 'feature/MAR10001-845' into 3.0 ce9d72a160 MAR10001-837: Inventory batch layout 43fc12dfba - Added schema installer for ServicePointBundle - Updated installer of invoice bundle during installation errors on Postgres - Reverted changes made on Product datagrid during not showing products on the product grid c88c25a6df MAR10001-845: Update WHG and SCG datagrids with the joins in a datagrid listener 6456a5a6f7 - updated navigation items by swapping facilities and servicepoints in the menu - removed the height of business hours override td table in favor of restoring the height in the workflow display in page titles where applicable - added quick product navigation to purchase order item grid 7f1cc1c91a Merge branch '3.0' of https://github.com/marellocommerce/development-mono-repository into 3.0 3b5d64f244 - removed empty line from services.yml 643f192900 Merge branch 'feature/MAR10001-842' into 3.0 3d84eb8fca - removed deprecations from different classes, some inf favor of constructor dependency injection - fixed default user&password for initializing db's in the docker container 442821802f Merge branch 'feature/MAR10001-776' into 3.0 df69a307ff Merge branch 'feature/MAR10001-776' into 3.0 8e581df3cd MAR10001-776: Inventory Batches - fixed bug in replenishment 0d9ee3bfd2 - preparations for release 90afec03be Merge branch 'feature/MAR10001-776' into 3.0 3b96c1ab97 - fixed issue with results of the query being used when filtering products through the grid and trying to assign them to saleschannels - added ability to split the message for bigger chunks of data instead of having a single message with a lot of product ids - restructured the code in order to use the entity repository of the products instead of relying on the cached query from the querybuilder - Fixed the main issue of the bug where we couldn't mass-assign products to SalesChannels because the query for the products grid evolved in such a query, which made hard to reset parts of the query for counting and not having to deal with the query cache once the results where fetched 82c3f40ac9 MAR10001-842: Issue when creating Order when Google Address Geocoding is enabled b6a01edcf0 - fixed issue with assigning saleschannel mass action where it wouldn't display the grid to select saleschannels to assign products to 98f43ba757 - fixed issue with foreign key update on inventory_item_id in the inventory_level_log table - added migration to update warehouseName on existing inventorylevelLogs 7c337e3746 MAR10001-776: Inventory Batches - InventoryBatches combined in replenishment orders f85becbb06 [WIP] - working on the migration from existing inventory level logs to the new data structure for it - fixing issue where the inventory level log is being removed as soon as an inventory level is deleted - added additional columns to the inventorylevellog in order to be able to have a history of movements for the whole inventory item - updated data grid in order to display the log based on different columns and identifiers - updated enterprise grid listener for displaying different column as warehouse label - added warehouseName as human readable reference of which inventory level it was a movement of - removed FK on inventory level in order to keep the inventorylevel log d9c7987cc6 - fixed AddressListener event which had typo's in the service definition which caused the address not being rendered in the Order datagrid 6e852b56fc - updated EmailTemplateManager with correct method call on the EmailTemplateRepository which was lost during merge f75dcb12fb - updated InventoryBatchCollection options to `allow_add` and ensure users are able to manually add batches - Added an add InventoryBatch button to the bottom of the InventoryBatchCollection 0db88c5cbb - fixed issue with InventoryManager and InventoryLevelFixture where they used to initialize an InventoryItem with a warehouse, which is not necessary anymore - Added action button for enabling Inventory Batches via a button instead of having a checkbox in the form 341bcf112b - Merge branch 'feature/MAR10001-776' into feature/update-to-rc3 - Removed deprecated property 'warehouse' from InventoryItem, constructor of InventoryItem and getters and setters for the property ed4a9260de MAR10001-776: Inventory Batches - created Inventory Balance trigger in order to update balanced inventory - added manual creation of InventoryBatch on the inventory batch update page b61114fe80 - updated applications (most used application variations) with new OroRequirements which require at least PHP 7.1.13 - updated dev.lock files with OroPlatform 4.1.0-rc4 and related packages (calendar, platform-enterprise etc.) - updated docker-compose files to include php 7.3.13 as version to build - updated .gitignore files to include the package.json - add package-lock.json files as this will be the locked npm package versions file - updated activity_list.provider tag to include FQCN for the activity e13e8a23cf - Moved 'old' customerAddressMap template and placeholder from CustomerBundle to generic addressMap in the AddressBundle for reusability - Removed old template and placeholder of customerAddressMap - Servicepoints map now uses placeholder from the AddressBundle instead of embedded implementation d3c9ffc21e MAR10001-776: Inventory Batches - updated Inventory Level import/export - added column 'enabled batch inventory' to inventory items grid afde76c67b Merge branch 'feature/CRH19001-18_Service-points' into feature/update-to-rc3 ff58c510e8 - updated invoice email attachment template to match the subject of the invoice notification email 0c624a7fee Merge branch 'feature/update-to-rc3' of https://github.com/marellocommerce/development-mono-repository into feature/update-to-rc3 2aea7fbc03 - updated SendEmailTemplateAttachmentAction with methods, properties and dependencies in order to make it work with 4.1-rc3 - updated template for invoice email to make it look like the original 7930e5350f - updated pdf labels and headers for invoice lines in pdf - added some css tweaks to pdf, smaller font size, line color changes - split the description in the invoice line item of pdf into productSku and productName and have separate columns for it in the pdf 8d081b5df7 - updated customer update view to correctly display name in the tab of the browser c201b18b07 - removed old bundle of Servicepoints, Servicepoints are now a separate package e7bebd421b - added service points as new package - added docker-compose file for service points application cd27da7f56 - fixed js component for purchase orders - fixed issue with showing currency symbol and prices 53bc5f4351 - fix controller - fix view d60ab65bd5 - fixed create return button on order view page after the status of items have been changed to enums instead of strings 99491f1076 - fixed order of import for multiple entity.js of purchase order 2fbe58179f - fixed missing nodeje module on purchase order multiple entities - fixed importing issue in the multiple entity of backbone 3c199c7d4b - reworked the multiple entities setup for purchase orders regarding js components de33b40003 - fixed typo in item view of purchase orders 1d17473b18 CRH19001-18; Change date formtype 5bd5f585b8 CRH19001-18; Refactor form handler for business hours overrides 283224e715 - expose additional js files for purchase order bundle - added some phpdoc to the LogoProvider - removed unnecessary dependency from LogoProvider in pdf bundle 93e0f7a301 CRH19001-18; Fix business hours overrides datagrid 05d3ee90cc - fixed issue with logo showing X as image when no image is found in the invoice - updated check, to check against the common parent of the Invoice & Creditmemo, the AbstractInvoice to make it work for both Invoice and Creditmemo 358bc16eb8 - fixed adding return items to return when creating it from the datagrid, status is now an enum and needs the id as identifier for checking the status instead of the object - make the the business rule mananager service public in order to use it in the process of authorizing the return items cea6de24e2 - fixed issue with wrong service definitions in the pdf bundle in order to download invoice pdf's - fixed service definition of saleschannel configuration form 603973a833 Merge branch 'feature/MAR10001-776' into feature/update-to-rc3 10cbe2cf78 - updated emailtemplate action to comply with php 7.2.x 55f2f27915 - make service public in order to use the service within symfony 4.4.x framework on other places 58ae37ab3b Merge branch 'feature/MAR10001-13_Create-pdfs' into feature/update-to-rc3 bf503d4350 Merge branch 'feature/MAR10001-742_Send-invoice-in-workflow' into feature/update-subscriptions-rc3 0b2acad22c merged branch 3.0 into feature/MAR10001-776 61cb213344 MAR10001-776: InventoryBatches 068d74d3df Merge branch 'feature/MAR10001-776' into feature/update-subscriptions-rc3 fe9ee212be Merge branch 'feature/MAR10001-805' into feature/update-subscriptions-rc3 e986b56fa9 - Fixed install issue of Subscription with attribute set not having an organization property anymore - Updated dev.lock files of all applications to RC3 9f96de829f CRH19001-18; Add business hours overrides 1442a7d762 - updated address js component to use the widgetmanager with the updated structure - updated address related views for Order, Supplier and Subscription e0d0dda2ac CRH19001-18; Manage collections of business hours in form handler 3f7c9317c5 CRH19001-18; Always show all days in form c6808d4d95 CRH19001-18; Fix validation c595b65716 - fix first part of the OrderReplenishment JS module - [WIP]: bug when deleting a single row and adding it back again, in which it is rendered but not in the collection of added products 7a03e31477 CRH19001-18; Rewrite business hours datastructure [WIP] 0ca22d1422 CRH19001-18; Rewrite business hours datastructure [WIP] 87cdbddbd1 CRH19001-18; Rewrite business hours datastructure [WIP] fa42383975 CRH19001-18; Update form view for business hours 500e23654d CRH1900-18; Fix validation 1a93d8f046 Merge branch 'feature/CRH19001-18_Service-points' of github.com:marellocommerce/development-mono-repository into feature/CRH19001-18_Service-points 403dedfa6c CRH19001-18; Updates to form theme 9b0fbd240f - updated all Marello CE bundles with the new format for webpack 08f29d3e82 CRH19001-18; Fix view page when no image selected 2ddc084de0 - updated Product related js components to comply with new webpack setup - Updated EmailTemplateManager for getting the localized email template were the old method has been removed 5dcaef4c7c - Updated application to Oro Platform 4.1-RC - Updated some components to comply with new webpack implementation of Oro Platform 4.1-rc 55389791d6 CRH19001-18; Add custom form theme for service point business hours 6c3e97f498 MAR10001-776: Inventory Batches - new comments fixed c55dd80ab4 CRH19001-18; Fix timezones of TimePeriod entities 915d6b6fc4 MAR10001-805: Error exporting inventory (and 'Download data template') - Error exporting inventory (and 'Download data template') - Change default text 'Oro' to 'Marello' in email Sender Name 39215f2e6a MAR10001-742; Add ability to add attachments to notifications from workflow action 43d599a5e1 MAR10001-742; Add ability to add attachments to notifications via SendProcessor e08240baac MAR10001-742; Add attachments to Notification 6c73a2673d MAR10001-742; Add v1_0 migration for NotificationBundle b5df9841fd MAR10001-742; Fix typo db986fead1 - reverted to old sticky note icon dddea172b6 - changed the sticky note text - reverted commmented line in phpunit.xml beb726cda6 - fixed the sticky note description and logo - updated help link on the question icon on the top 5938f580aa MAR10001-13; Add white background color to PDF template 00461a3d81 MAR10001-13; Add configuration button on sales channel view 373fac5383 CRH19001-18; Validate timeperiod validity 185587f5f9 CRH19001-18; Allow multiple timeperiods per day 5c269df542 MAR10001-774: Remove increase / decrease external warehouses option eae9820367 - CS fix aff92ca9cc Merge branch 'feature/MAR10001-765' into 3.0 cc8284f5b0 Merge branch '3.0' into feature/MAR10001-776 5d90b4d8bb MAR10001-802: WFA rule index is not rendering 3298d7fcda MAR10001-765: Update InventoryRebalance Command e0f6532d50 MAR10001-776: Inventory Batches - bug fixed d016d877d3 MAR10001-776: Inventory Batches - bug fixed 5bae55cf31 MAR10001-776: Inventory Batches - added inventoryBatch creation on PurchaseOrder complete - updated inventoryBatches allocation by q-ty for order 1fd2580e32 - Added more fixes regarding the changed DI in the Controller as the service locator is more limited than the 'normal' one - Aliased classes to service ids in order to get the subscribed services correctly in the Controller 9c398bc65a - Added OrderDashboardController as a service tagged with the container.service_subscriber in order to fix issues with private dependencies instead of using regular DI - Fixed issue with private service which provides data to a dashboard widget dccd932a01 Merge branch 'feature/MAR10001-770' into 3.0 c5c22bd721 Merge branch 'feature/MAR10001-775' into maintenance/2.2 2fec41981a Merge branch 'feature/MAR10001-775' into 3.0 fdb762cc77 Merge branch 'feature/MAR10001-769' into 3.0 1d9beba640 - updated dev.lock with Oro Platform beta 4.1 db50f7cc3e MAR10001-776: Inventory Batches - removed temp code 7a945dbd59 MAR10001-776: Inventory Batches f112a14e5c - added SymfonyRequirements to ee environment - [WIP]: updated assignSalesChannels.twig, still not able to mass assign saleschannels to products - updated order view to switch invoices and packingslip grids as it seems a more logical order for displaying the data - removed unnecessary divs which where messing up the css on some datagrids cdb282c591 - Fixed issue with deprecated dependency of OrderWarehousesProvider where the service definition was updated but not the class itself - Updated dev.lock file for Marello CE to include Oro 4.x - Added SymfonyRequirements to git as this is not being installed via composer anymore - Updated phpunit.xml.dist by removing incompatible notation of logging incomplete tests - Updated composer.json and dev.json files to include symfony require as extra to use symfony flex globally 6578d01bc4 Merge branch '3.0' into feature/MAR10001-770 c0ab2de3d6 fixed bug on order create page bd9ca3692f MAR10001-770: Order statistics widget: filter by SalesChannel d686c8bf67 - Added migration to include organization id on the purchase order item 24898c61be - Added data column to PurchaseOrder a86b2a0ed6 MAR10001-775: Product widget failed to load when creating order without selecting a SalesChannel first 4342e9cda5 MAR10001-766: OroCommerce Bridge 481d27f179 Merge branch 'develop' into feature/MAR10001-769 688913458a Merge branch 'feature/MAR10001-758' into develop d9e7dd5a18 Merge branch 'feature/MAR10001-758' into maintenance/2.2 3a6ceeebef - CS fixes 92cc9eafcb Merge commit 'e0648503de63b2c85be84b8221c1b6275f0abca1' into maintenance/2.2 3b0112bb93 Merge commit 'bfa4e9daabbc421ed429f987a971b58d80aad9a7' into maintenance/2.2 53a0e0fe76 - updated branch aliases 3069732a94 Merge commit '01a0d5ae6603999e572ad65466187b50d8cba388' into maintenance/2.2 6bb210c740 MAR10001-759: Update OroCommerce bridge for Marello 2.2 b405650589 - CS fixes - Changed php version back to 7.1 bfa8d0a010 CRH19001-18; Add API ed9ceec43d CRH19001-18; Add map to service point view page 07cf5faeed CRH19001-18; Add service point image to view b996811d8c CRH19001-18; Add EntityConfig 2796bc42ad CRH19001-18; Add ACL 7253212610 CRH19001-18; Add controllers and views 1ab4140c16 Merge commit '651d560e9524a8eb66e396696a20d8414c349ced' into bugfix/PR-GH59-fix-closing-bracket 85b581198e Merge commit 'f4ccf6e09bf029797d5590a52f1a26db5f9d4721' into maintenance/2.2 75543a6404 MAR10001-759: Update OroCommerce bridge for Marello 2.2 0a34a36913 MAR10001-758: ProductSupplierRelation deletion is not updating InventoryLevels af59a86f6c Merge branch 'develop' into feature/MAR10001-758 15e7c2de73 MAR10001-769: Show 'Cost' currency on de Product edit page bfcfe51dc3 CRH19001-18; Add Forms 566a8047eb CRH19001-18; Add validation 8f81e069ab CRH19001-18; Add translations 4f0f4472c1 CRH19001-18; Add data model 181ba0b28b CRH19001-18; Add ServicePointBundle 36491f5d88 - Changed column source on invoice and creditmemo items product sku and name d56c29a1f5 Merge branch 'feature/MAR10001-674' into develop 902777e475 - Disabled OrderOnDemand widget in Inventory view / update in order to prevent the usage of the unfinished feauture cd96ad2fcd Merge branch 'feature/MAR10001-674' into develop cb7397a38e Merge branch 'bugfix/MAR10001-764-stop-override-orderitem-status-when-already-set' into develop e21f585dcb - Added check to prevent overriding OrderItemStatus when already set on creation 10cfcd0c26 Merge branch 'bugfix/MAR10001-763-fix-inventory-level-import' into develop 71f17ce1d8 - Added additional check to verify there is a product to get the inventory item from when passed back to the import processor e9b8cb5546 - Added additional check to inventory level update strategy to check wether the product of the 'associated' inventory level exists before importing and throwing errors 075389df6a removed useless fields from oro_entity_config_field 968d3d9e36 fixed bug in Migrations versions ddab3fa39d fixed bug in Migrations versions f69acc4469 fixed bug in OrderBundle migration 703364dd86 merged branch develop into 3.0 f844a1ca2d Merge branch 'task/MAR10001-0-add-quick-navigation-in-views' into develop 61f30e140f Merge branch 'task/MAR10001-0-add-quick-navigation-in-views' into maintenance/2.1 4fd373a5b6 merge branch 3.0 into feature/MAR10001-730 92214326e6 merge branch 3.0 into feature/MAR10001-714 1b7c9737ca MAR10001-717: Update applications with Oro platform 4.0.0 - fixed bug in migrations in InventoryBundle related to renaming column from system to is_system f6ede87a76 Merge branch '3.0' into feature/MAR10001-725 01f560bbe7 Merge pull request #16 from marellocommerce/feature/MAR10001-751 89e25ec89b Merge branch '3.0' into feature/MAR10001-718 896f1bd97c Merge branch 'task/MAR10001-745-add-organization-ownership-to-child-entities' into develop d1fd8a090d - updated PurchaseOrderBundle schema versions to take the 'next' version of Marello (2.2) into account 8ad671de85 Merge branch 'task/MAR10001-745-add-organization-ownership-to-child-entities' into develop 82e0205502 - CS fix ee2489e990 - Added Organization ownership to PurchaseOrderItem - Added translation for Organization label on PurchaseOrderItem - Added migration to update current PurchaseOrderItem with Organization - Added migration to add column for ownership to PurchaseOrderItem table - Added translation for Organization label on ReturnItem baf6ce615b - Added translations for Return item and Refund item organization labels - Added Organization ownership to RefundItem - Added migrations to update current RefundItems with Organization - Added migrations to add ogranization colum to RefundItem table 4b2615016f - Added migration for updating existing InvoiceItems with Organization - Added migration for adding ownership to ReturnItems - Added migration for updating existing ReturnItems with Organization 30353c01c0 MAR10001-751: Rename columns to e81ccf1397 MAR10001-717: Update applications with Oro platform 4.0.0 - fixed bugs bbffc57fe2 MAR10001-717: Update applications with Oro platform 4.0.0 - fixed CustomerBundle - fixed PaymentTermBundle e4d8f4973e merge develop branch into feature/MAR10001-717 ' 016a88d9de - Added migration to update current credit/invoice items with organization based on the parent entity's organization 44bb82a11b MAR10001-758: ProductSupplierRelation deletion is not updating InventoryLevels 55caada862 - updated PackingSlipItem test to include organization - Added translation for PackingSlipItem organization e5abc43e6a - Added migrations for updating current OrderItems & PackingSlipItems to set the organization based of their parent entity - Added Ownership config to PackingSlipItem - Added migration to add the new organization column on PackingSlipItem c2e041aa3e - Added ownership field to Oro config d1b406c8d4 - Added organization ownership to InvoiceItems - Added translations for organization - Added migration to update schema with organization 19775441d0 - Added organization ownership to OrderItem for applying ACL when reports are created with the items e84fe56b4c - Added Organization ownership to Supplier entity - Added test to verify the organization is set when a new supplier is being created 8bc66364ae MAR10001-674: Order on demand - updated OOD validator - fixed bugs in order items statuses changing e7e7a14f35 - updated rendering of OrderNumber link and SalesChannel link on various views for quick navigation - added quick navigation link to customer on Invoice view 4859ab9d03 - Added product sku rendering link to RefundItem's datagrid for quick navigation 5d7eb3af80 - Added product SKU rendering link to ReturnItems grid for quick navigation 980ff3c964 - Added product sku rendering link to PackingSlip item grid for quick navigation 3090ea22fb - Added product sku link rendering to Invoice Item grid for quick navigation 4343ca21df - Added product sku link rendering to order item's product in order item datagrid 398f1459ec - Added quick navigation rendering link for product SKU's as macro and template for Twig templates - Added quick navigation product sku link to datagrids of Inventory related datagrids - Updated rendering product sku link in inventory view pages - Updated rendering product sku link in order's hero widget 9fcb639852 - Updated rendering of orderNumber in datagrid to check ACL access and handle rendering of both an id and object of order - Added rendering a view link to latest order grid in dashboard widget for quick navigation e392127544 - Added quick navigation for customer on Order View - Updated quick navigation for SalesChannel link on Order View 37433d1ec4 MAR10001-714: Payment methods 97059a43a3 Merge branch 'develop' into feature/MAR10001-742_Send-invoice-in-workflow 833db6fa4f MAR10001-742; Add tests 9c49ea3fcc MAR10001-742; Check if invoice workflow transition is set 391276bb71 MAR10001-742; Remove debug code a518151789 MAR10001-742; Add workflow actions to send invoice e-mail eb019896a8 MAR10001-742; Add translation 7a22819041 MAR10001-742; Add migration for invoice e-mail template 5197a78d51 MAR10001-742; Add IsSendEmailTransition workflow condition 95b51422f3 merged develop branch into feature/MAR10001-714 branch 45faee70c0 - Reverted changes that break BC, added comments where BC would break if we would keep the changes in the Interface - Added alternatives to provide same functionality but without BC breaks 9ab72e4522 Merge branch 'develop' into feature/MAR10001-674 c08ff89542 - CS fix -> fixed docblock e9c1caf2c3 Merge branch 'feature/MAR10001-739_Payment-term-invoice' into develop a02adf01bf Merge branch 'task/MAR10001-0-remove-unessary-rebalance-job-from-migration' into develop caeebb8554 - Added Migrations to update entity_config tables and entity_config_field tables to set auditable to false for InventoryLevel && BalancedInventoryLevel f12d8b32db Merge branch 'task/MAR10001-0-remove-unessary-rebalance-job-from-migration' into develop ad1f8e1077 Merge branch 'develop' into feature/MAR10001-742_Send-invoice-in-workflow 39649ac6d6 - removed the trigger of a rebalance when installing to reduce additional messages in queue - refactored the trigger of rebalancing when a SalesChannelGroups are created or deleted to only rebalance products linked to those SalesChannelGroups 94dc6b9304 - Added check to prevent sorting on null when no products have been found and linked to any warehouse when creating order and moving through the workflow 916fe29d7e MAR10001-742; Add e-mail settings about sending invoices 4c41e51514 MAR10001-739; Fix migration namespace 7663b85d5f - CS Fixes fb474fbb88 Merge branch 'feature/MAR10001-674' of https://github.com/marellocommerce/development-mono-repository into feature/MAR10001-674 a80caf8af5 MAR10001-674: Order on Demand - fixed warehouses calculations for order 58caaf643d - remove unused code from validator cfc1569d0c - Removed unused code - Added CS fixes where necessary 1514d992ff MAR10001-674: Order on Demand 81eeb78342 MAR10001-674: Order on Demand c0e4dfa344 - Updated dev.lock files - Updated oro platform to version 3.1.13 dd509f05db backmerged develop branch into feature/MAR10001-730 branch 5f8bc9bf89 MAR10001-730: Update CustomerBundle with Customer 88b1265062 MAR10001-742; Add workflow action to send email with attachment 0396909dab MAR10001-739; Add payment term to invoice view 092e4dd6db MAR10001-739; Calculate invoice due date 34f4b459ae MAR10001-739; Add payment term during invoice generation 931854b73a MAR10001-739; Add getCustomerPaymentTerm to PaymentTermProvider 574b4b5f94 MAR10001-739; Add payment term to invoice model d804c235f4 MAR10001-13; Add demo data for invoice configuration 3c39998425 Merge branch 'feature/MAR10001-744_Payment-term-for-Company' into develop 32a8e97f4a - Fixed typo in class name 63bcb3932d Merge branch 'feature/MAR10001-744_Payment-term-for-Company' into develop 0c260a20c3 - Small CS fixes; new line on end of file, formatting ano function over multiple lines 624ca71682 MAR10001-730: Move Customer e89cc46bdb MAR10001-13; Add functional test e9ac295074 MAR10001-13; Update TableSizeProviderTest de8e3d26d4 Merge commit '1fcaceed572eb29296aba81d50c4746ea44a9d0b' into maintenance/2.1 7984fc3e82 Merge branch 'bugfix/MAR10001-712-add-taxcode-remove-suppliers' into maintenance/2.1 c295d88b14 Merge branch 'bugfix/GH-PR9-update-ororequirements' into develop d8e50be874 Merge commit '73de19e5ff6867b2fb523997401df9d818e84235' into bugfix/GH-PR9-update-ororequirements 1379ec2829 - Added test to verify correct registration of cron command - updated code to include correct registration of cron command 88ca77277d MAR10001-13; PdfBundle unit tests 08a0633b9f MAR10001-13; Fix PDF bugs 9cdb3c040a - Updated tests to cover ProductRepository getPoItemCandidates - Updated inventory data fixture for tests to include data for InventoryItems - Added test for cron command to verify sending the notification for PO advise - Updated ProductData fixture to set a preferedsupplier on a product 448f70228d Merge branch 'feature/MAR10001-676-purchase-order-notification' of https://github.com/marellocommerce/development-mono-repository into feature/MAR10001-676-purchase-order-notification c154e4c36f - Added test to verify the working of the saving of the notification as activity target e62d2a80b7 - updated phpdocblock removing parameter that isn't there anymore c5299bf6c4 - updated query for including purchaseInventory when selecting purchaseOrderItemCandidates 243f6852cb - Updated SendProcessor to keep BC by having a setter and property for saving the notification as activity instead of adding a method parameter - Updated POACommand to set the property on the SendProcessor and use a constant as exit code a8ad8f7fc7 Merge branch 'develop' into feature/MAR10001-676-purchase-order-notification b860718e7d Merge branch 'develop' into feature/MAR10001-725 fc169ea485 Merge branch 'develop' into feature/MAR10001-676-purchase-order-notification ba67474dc0 MAR10001-13; Add PDF button to invoice view 163ff31db9 - changed Warehouse Location to Pick location - Updated migrations, tests and translations 37dabd1160 MAR10001-725: Update ProductBundle 28a8e09177 MAR10001-744; PaymentTerm API tests 65a730cbf2 Merge branch 'feature/MAR10001-735-add-second-workflow' into develop 829adf6dc3 - Added an Interface to have some constants for order workflow names - Updated tests being more clean without the much duplicated code b5e9a593c5 MAR10001-744; Adjust tests for Company PaymentTerm 970f8db73f MAR10001-744; Add PaymentTerm API ce5531f41a MAR10001-744; Add payment term to Company view and form 8240ad903e MAR10001-744; Add test for PaymentTermSelectType d66fb70060 MAR10001-744; Add PaymentTermSelectType 47bf1ef1da - Updated logic for moving default worfklows to pending when only one is active - Added test for logic to test scenario's where there is only a single one available, the entity not being eligible or when there is more than one available - Added tests to interact with default installation 40176c8574 MAR10001-744; Add payment term to Company model 675a7e6e82 - Added first version of the OrderWorkflowStartListener for when a single workflow is active on the order and start it automatically 8294ef69d8 - Fix inventory level tests for CE version 16472ec614 Merge branch 'task/MAR10001-0-fix-inventory-level-functional-tests' into develop 0157976993 - updated type hint for getWarehouseLocation() in InventoryLevel - Updated datagrid of inventory level to include warehouseLocation - Updated inventory level collection form to include warehouseLocation 8542e7742d - added warehouseLocation to inventory level form type 680ff8800c - Added Warehouselocation to InventoryLevel - Updated migrations to include warehouse location column - Added translation for new field warehouse location - Updated function/unit tests to test setting/getting and updating warehouse location 6f874d60d9 - Fix inventory level tests for CE version 914980b2ab - Fix inventory level tests for CE version a0e022fd2e - added currency of root entity(Invoice) for formatting correctly in PDF's 2cd0baa461 Merge branch 'feature/MAR10001-701_Payment-term' into develop c7206c8ed0 - Fixed check in PaymentTermDeletePermissionProvider to take into account a null result from the PaymentTermProvider - Fixed PaymentTermControllerTest to count the result of the loaded fixture and verify 'results' ae53673066 - Show inventory level collection when empty for CE version a84466c0e9 - Adding PaymentTerm demo data - Updated payment term provider to check wether the id from the config exists before querying on the repository 128b5c7dd9 - CS fixes aeb405cb23 Merge commit '88a66e97085d3973c1f3ab5688d657f589675912' into feature/MAR10001-674 abf67f2a04 Merge commit 'c5439ea9dcce676be7d610bd46086d4843c58fad' into feature/MAR10001-674 2972b70974 Merge commit '22b754da8f9fb0b396a651fd3f9a1a84ad4a6e61' into feature/MAR10001-13_Create-pdfs d6269fc8ce Merge commit '9fa49926a0e01508f988164f88559744622be764' into feature/MAR10001-701_Payment-term a38dcb394e MAR10001-718: Refactor LocaleBundle - backmerged develop branch 94f2d72431 MAR10001-717: Update applications with Oro platform 4.0.0 ad348b7530 MAR10001-718: Refactor LocaleBundle cbecd42a23 - updated workflow #2 for switching shipping and invoicing steps in order workflow - updated translation for workflow #2 - updated configuration for workflow #1 to be able to handle more than 1 workflow on a single entity - disabled workflow #2 by default b45f85caf6 MAR10001-717: Update applications with Oro platform 4.0.0 92389121ac Merge branch 'develop' of https://github.com/marellocommerce/development-mono-repository into develop e1769e9ffc - removed unused code - todo add additional customer controller tests for create/update 617db295e2 - removed commented code 320802d081 - fixed testCompanyUpdateRemoveCustomers test now calling correct method for customer to assert - removed an assertion from testCompanyUpdateRemoveCustomers because assumption of the assertion was wrong fbde6ffe7c - CS Fixes - Updated Company controller test to test saving a company without customers assigned - Fixed Customer entity to allow the company to be empty - Added Company name and view link to Order view 641d2e0b4c - CS fixes 07694aa1ce Merge commit '11f7d8417a07b4a65cd787387c0e10cc56870352' into feature/MAR10001-692 2be35ef41d - removed suppliers from product grid - added missing taxcode to product grid c857054177 Merge branch 'bugfix/MAR10001-711-images-load-slower-than-marello-20' into maintenance/2.1 163456716d - added addditional migration to update product images with `acl_protected` false in Entity config to change the caching directory of images - updated installer to include the `acl_protected` entity config by default in Product Image attachments ff6afc3b5a - updated OrderView datagrid layouts to resemble the 'original' style from Oro 8ef8047801 Merge commit 'ce6c5c85565cf4ba66d2942b1c1aa34c3c389a33' into release/2.1 de9d4c47b4 Merge commit 'ce6c5c85565cf4ba66d2942b1c1aa34c3c389a33' into release/2.1 1a6e484232 - updated branch aliases eec150b3c8 - updated branch aliases 980c1ff750 Merge commit '7139917230723d97b9b8c99e27dcd5c3f7d2e8e1' into release/2.1 1557581997 Merge commit '7139917230723d97b9b8c99e27dcd5c3f7d2e8e1' into release/2.1 7a60f4801b - prepared composer.json files for release 357aa47e70 - Added twig file extension to deal with image id being fetched as a result in the product grid and getting the correct image during PostgreSQL having issue with an object in the result - Fixed subscription controller test to include cancelBeforeDuration field since it is not nullable 1534d71d1f - added back sorters in to two datagrids for invoices and packingslips bb1f6da3c8 - updated translations - updated updated orderitem status Dropshipped to Dropshipping - updated datagrids with removal of exports and some sorters 32f5ac18da - removed todo comment 942b3ac1b3 - Removed inventory check when subscription product is in the order and the OrderItem status is being updated 6b5f3192af - removed external warehouse inventory from AvailableInventoryProvider in order to not confuse users, external warehouse inventory should be taken into account in the inventory balancer b18dc9eb14 - changed show form when empty boolean on inventorylevel collection in order to prevent confusion for users 9bd1490c73 - updated code for checking bc breaks 9e27b773c7 - Fixed some classes in order to keep BC for upcoming release - Added some comment in which we couldn't keep BC (OrmFilterExtension) 061f842b30 - fix constructor argument in order to keep BC for 2.1 release 1898c7674f - fix constructor argument in order to keep BC for 2.1 release 2d24b8a400 - CS Fixes - updated the check for updating existing email templates migration bff8ed6cc0 Merge commit '5bb4981c46c7990c597fb4344a600bcb969981c5' into feature/MAR10001-676 8e7b24f1ec - Updated translation for Order Item status report f3ee26fd2b - Update InventoryItem view and update page for more consistency between the pages 508e306de2 - Added check for Back/Pre-order quantities where the MaxInventoryQty is null - Updated test to check the new order count in DB after if the maxQty is set for back/pre-order 0d3f077862 - Updated tests for checking whether more than 1 product type has been registered in the application af99300131 - Added tooltips for back/pre-order form fields - removed the 'relations' between purchase order and the backorder datetime field - updated translation labels for consistency - removed configuration for enabling / disabling usage of PO and datetime of backorder - added feature to set the pre-order allowed field to false and pre order datetime to null when PO has received items - added feature to set backorder datetime to null when PO has received items 17c85aa1ce Merge branch 'develop' into feature/MAR10001-485-subscriptions c03a1d1b23 - CS fixes - Updated dev.lock f08f3ba42f - CS fix 82eff3b7a6 Merge branch 'develop' into feature/MAR10001-485-subscriptions 09150b621a Merge commit '5f12bd20893426c155ce26461eb08b0dc2da5297' into feature/MAR10001-670 2675326390 - Changed name of the placeholder data twig function for clarification - Added additional tests for checking the functions of the Additional data Placeholder Provider feature 7810b27874 - removed references of subscription bundle in Marello CE core - added the ability add additional placeholder data to render blocks - added additional placeholder data to orders, purcahse orders, suppliers, products and salesChannels f0a79a1bec - Updated send processor test to include coverage for sending correctly rendered emails 2efcb450e9 - Added additional test for testing when the email template cannot be found - Changed the type, content and subject to be send to the emailNotificationSender in order to prevent sending notifications without proper rendering fbc89a82c9 - CS fixes - Fixed CreateProduct test in ProductController test to take the attribute family into account when creating new products 2db9b9c96a Merge commit 'b1ef79ca49e261313c5007056254a522cc673dee' into feature/MAR10001-485-subscriptions f85d647ea0 Merge commit 'e5280b59fd2f4e57a38bc08bb62f43344bae4ef0' into feature/MAR10001-485-subscriptions 75bf8c07ab Merge branch 'bugfix/MAR10001-0-fix-email-template-tags' into feature/MAR10001-485-subscriptions 5bc7613548 - added fixes for non escaped twig tags in replenishment and return emails 41d3b570e8 - update migration namespace since it's not an oro migration but a Marello one; just clarification no bugfix 227b098549 - fix email tags for Purhcase Order email templates 8dc07387fa - Added Migration to Order & Purchase Order bundles to update email template tags to make sure the custom tags are not being removed 1984ce316f - fixed subscription view translation keys - Changed ownership of product attributes to Custom to allow attribute sets be created without the subscription attributes in it (system attributes are required to be added to all attribute families) efbc60e7a6 - added documentation for registering product types - fixed some phpDocs in Subscription entity to include correct return types a67cc41a7e Merge branch 'feature/MAR10001-485-subscriptions' of https://github.com/marellocommerce/development-mono-repository into feature/MAR10001-485-subscriptions 2d91077b66 Merge branch 'develop' into feature/MAR10001-485-subscriptions 30ccc7a9b4 - Merge commit '22a02abd2e26d568767c7824dba7970017871107' into feature/MAR10001-499 9f22ddd42f - Fix installing demo data with default product type 4a125df84e Merge branch 'feature/MAR10001-0-fix-is-managed-inventory-level' into feature/MAR10001-485-subscriptions 5ec23e1c59 - fixed issue with managedInventory interfering with updating inventoryLevels and or going from managed to unmanaged 7e421308cf - revert mark as skipped functional test of ProductController 2703f95f17 - CS fixes - Updated test-extended script in dev.json to test PSR in correct directory - Mark ProductCreate test as skipped because of failure with subscription extension enabled ceaa7ee8bc Merge commit 'd616475ea6c833b33481537e80d73a114b76df94' into feature/MAR10001-485-subscriptions 0955caf4f8 - remove setting datetime for pre-orders when purchase order is created 56286a89d4 - PSR2 fixes - Remove unused constant from config - Unified translations for Backorders and Pre-orders 05169bd5f1 Merge commit 'b55e936f3c6428ae97c2f440cd8df8e00e3a9127' into feature/MAR10001-377 6b9e312b6c Merge branch 'feature/MAR10001-604' into develop 94bfebcb84 - Fix PSR2 cs fixes 60f21670a5 Merge commit '4b5ec7e8d02e9b7e079e43d024f18dc3a92a9c7d' into development 248bb21439 Merge commit '40a4d43559a871bd237a9a91e61f6bb33f6db69e' into feature/MAR10001-604 2fb751999e - added composer.lock - added dev.lock - updated branch alias in marello package composer.json 087a810477 Add 'applications/marello-application-ee/' from commit 'd13f2b41e079dff4eee99f8874928459658daaff' REVERT: 73c2e39ff5 - Added minor fixes to purchase orders view and form REVERT: 7b00a7d73c - Added possibility to update cost via marello-supplier-product-grid REVERT: c0e9f673c7 Merge commit 'ffba2a1d74fe5713fd615d1fb3b6980a41cb9f31' into maintenance/3.0 REVERT: 1591559098 Merge commit 'f497f93ca471ade418553eea3289318a7c4bca23' into maintenance/3.0 REVERT: 9a16f4759c Merge commit '71530acca5abd305f2c328d3f74bb414c1b89844' into maintenance/3.0 REVERT: 26a030ac69 Merge commit '0bcb9bb847396efc745579839904136a8252ed58' into maintenance/3.0 REVERT: cf8c669f62 Merge commit 'e779b8a1796d417078e3a9dfe89b0474e462caac' into maintenance/3.0 REVERT: dcc89ded95 Merge commit '4f68dc37da2773e1c4f6cee4e165f7a441154a90' into maintenance/3.0 REVERT: 746d1e3655 - Added additional info on runtime exception for Product create/update if no default name is given - Added additional check on loading customer address when creating an order and the primary address is empty git-subtree-dir: package/marello git-subtree-split: d80705c83cf6471e2764ba7dde0c84c184dc431b --- composer.json | 2 +- .../Bundle/CatalogBundle/Entity/Category.php | 6 +- .../Entity/Repository/CategoryRepository.php | 16 + .../Datagrid/CategoriesDatagridListener.php | 162 ----- .../Schema/MarelloCatalogBundleInstaller.php | 4 +- .../Schema/v1_2/MarelloCatalogBundle.php | 31 + .../Resources/config/services.yml | 14 +- .../Resources/config/validation.yml | 2 +- .../Datagrid/Property/categories.html.twig | 3 - .../CatalogBundle/Twig/CategoryExtension.php | 68 ++ .../Autocomplete/CompanyCustomerHandler.php | 4 +- .../Bundle/CustomerBundle/Entity/Company.php | 34 + .../Bundle/CustomerBundle/Entity/Customer.php | 34 - .../CustomerBundle/Form/Type/CompanyType.php | 6 +- .../CustomerBundle/Form/Type/CustomerType.php | 3 - .../Schema/MarelloCustomerBundleInstaller.php | 4 +- .../v1_5/MarelloCustomerBundlePart1.php | 59 ++ .../v1_5/MarelloCustomerBundlePart2.php | 33 + .../Resources/config/services.yml | 2 +- .../Resources/config/validation.yml | 2 +- .../Resources/translations/messages.en.yml | 2 +- .../Resources/translations/pdf.en.yml | 1 + .../Resources/views/Company/update.html.twig | 1 + .../Resources/views/Company/view.html.twig | 1 + .../Resources/views/Customer/update.html.twig | 1 - .../Api/responses/cget_companies_list.yml | 3 + .../Api/responses/cget_customer_list.yml | 10 - .../Api/responses/get_company_by_id.yml | 1 + .../Api/responses/get_customer_by_email.yml | 1 - .../Api/responses/get_customer_by_id.yml | 1 - .../ParentCompanySearchHandlerTest.php | 4 - .../Extension/Totals/OrmTotalsExtension.php | 93 +++ .../Resources/config/services.yml | 13 +- .../Data/Demo/ORM/LoadProductData.php | 4 +- .../Data/Demo/ORM/LoadProductImageData.php | 16 +- .../MarelloFilterExtension.php | 26 + .../FilterBundle/Filter/ChoiceLikeFilter.php | 52 ++ .../Resources/config/services.yml | 9 + .../Controller/InventoryLevelController.php | 19 + .../InventoryBundle/Entity/InventoryBatch.php | 3 - .../Entity/InventoryLevelLogRecord.php | 4 +- .../Datagrid/InventoryLevelGridListener.php | 68 ++ .../Form/Type/InventoryBatchType.php | 7 + .../Strategy/InventoryLevelUpdateStrategy.php | 8 +- .../MarelloInventoryBundleInstaller.php | 7 + .../UpdateInventoryLevelLogForeignKey.php | 41 ++ .../Resources/config/eventlistener.yml | 7 + .../Resources/config/oro/datagrids.yml | 82 ++- .../Resources/public/css/scss/main.scss | 10 +- .../Resources/translations/messages.en.yml | 8 +- .../Resources/views/Form/fields.html.twig | 17 +- .../Datagrid/manageBatches.html.twig | 5 + .../InventoryLevel/batchesView.html.twig | 85 +++ .../InventoryLevel/manageBatches.html.twig | 18 +- .../Controller/InventoryControllerTest.php | 4 + .../InvoiceBundle/Entity/AbstractInvoice.php | 205 ++++-- .../Repository/AbstractInvoiceRepository.php | 24 + .../Form/Type/InvoiceSelectType.php | 33 + .../Schema/MarelloInvoiceBundleInstaller.php | 42 +- .../v2_0/MarelloInvoiceBundleAddColumns.php | 75 +++ .../v2_0/MarelloInvoiceBundleAddQuery.php | 26 + .../MarelloInvoiceBundleRemoveColumns.php | 37 ++ .../Schema/v2_0/PaymentsCreationQuery.php | 66 ++ .../Pdf/Logo/InvoiceLogoPathProvider.php | 12 + .../InvoiceLogoRenderParameterProvider.php | 5 +- .../Provider/InvoicePaidAmountProvider.php | 18 + .../Resources/config/oro/actions.yml | 89 +++ .../Resources/config/oro/datagrids.yml | 17 +- .../Resources/config/services.yml | 18 +- .../Resources/translations/messages.en.yml | 24 +- .../Resources/translations/pdf.en.yml | 1 + .../Resources/views/Invoice/view.html.twig | 44 +- .../Resources/views/Pdf/creditmemo.html.twig | 4 + .../Resources/views/Pdf/invoice.html.twig | 10 +- .../Api/responses/cget_creditmemo_list.yml | 4 - .../cget_creditmemo_list_by_order.yml | 2 - .../Api/responses/cget_invoice_list.yml | 8 - .../responses/cget_invoice_list_by_order.yml | 2 - .../Api/responses/get_creditmemo_by_id.yml | 2 - .../get_creditmemo_by_invoiceNumber.yml | 2 - .../Api/responses/get_invoice_by_id.yml | 2 - .../get_invoice_by_invoiceNumber.yml | 2 - ...InvoiceLogoRenderParameterProviderTest.php | 2 +- .../Pdf/Table/InvoiceTableProviderTest.php | 2 - .../InvoiceBundle/Twig/InvoiceExtension.php | 65 ++ .../Resources/public/css/scss/main.scss | 2 +- .../MarelloNotificationBundleInstaller.php | 4 +- .../Schema/v1_2/MarelloNotificationBundle.php | 34 + .../Controller/OrderController.php | 1 - .../Bundle/OrderBundle/Entity/Order.php | 67 -- .../Doctrine/OrderWorkflowStartListener.php | 4 +- .../Form/Type/OrderItemCollectionType.php | 2 +- .../OrderBundle/Form/Type/OrderItemType.php | 24 +- .../Form/Type/OrderTotalPaidType.php | 93 +++ .../Schema/MarelloOrderBundleInstaller.php | 4 +- .../Schema/v3_1/MarelloOrderBundle.php | 29 + .../Schema/v3_1_1/MarelloOrderBundle.php | 73 ++ .../MarelloOrderBundle.php | 7 +- .../Model/WorkflowNameProviderInterface.php | 6 +- .../OrderBundle/Resources/config/form.yml | 8 + .../OrderBundle/Resources/config/oro/api.yml | 5 + .../Resources/config/oro/datagrids.yml | 2 +- .../Resources/config/oro/workflows.yml | 629 ++++++++++++++++++ .../OrderBundle/Resources/doc/api/order.md | 2 - .../Resources/public/css/scss/style.scss | 32 +- .../public/js/app/views/order-item-view.js | 10 +- .../Resources/translations/messages.en.yml | 3 +- .../Resources/translations/workflows.en.yml | 128 +++- .../Resources/views/Form/fields.html.twig | 21 +- .../Resources/views/Order/view.html.twig | 47 +- .../order_create_with_existing_customer.yml | 2 - .../order_create_with_new_customer.yml | 27 +- .../Api/responses/cget_order_list.yml | 100 ++- .../Api/responses/get_order_by_id.yml | 10 +- .../responses/get_order_by_orderNumber.yml | 10 +- .../Controller/OrderOnDemandWorkflowTest.php | 17 +- .../Functional/DataFixtures/LoadOrderData.php | 5 +- .../OrderWorkflowStartListenerTest.php | 8 +- .../Tests/Unit/Entity/OrderTest.php | 2 - .../Tests/Unit/Twig/OrderExtensionTest.php | 6 +- .../OrderBundle/Twig/OrderExtension.php | 61 +- .../Mapper/OrderToPackingSlipMapper.php | 2 +- .../Mapper/OrderToPackingSlipMapperTest.php | 6 +- .../Handler/AddPaymentActionHandler.php | 104 +++ .../Controller/PaymentAjaxController.php | 66 ++ .../Controller/PaymentController.php | 116 ++++ .../PaymentMethodsConfigsRuleController.php | 14 +- .../Bundle/PaymentBundle/Entity/Payment.php | 356 ++++++++++ .../EventListener/PaymentCreationListener.php | 103 +++ .../Form/Handler/PaymentCreateHandler.php | 88 +++ .../Form/Handler/PaymentUpdateHandler.php | 81 +++ .../Form/Type/PaymentCreateType.php | 210 ++++++ .../Form/Type/PaymentUpdateType.php | 215 ++++++ .../Data/ORM/LoadPaymentStatusData.php | 41 ++ .../Schema/MarelloPaymentBundleInstaller.php | 102 ++- .../Schema/v1_0/MarelloPaymentBundle.php | 18 +- .../Schema/v2_0/MarelloPaymentBundle.php | 97 +++ .../PaymentBundle/Model/ExtendPayment.php | 10 + ...AvailableCurrenciesFormChangesProvider.php | 56 ++ ...lablePaymentMethodsFormChangesProvider.php | 108 +++ .../Resources/config/jsmodules.yml | 5 +- .../Resources/config/oro/datagrids.yml | 163 +++++ .../Resources/config/oro/navigation.yml | 11 + .../Resources/config/oro/routing.yml | 10 + .../Resources/config/services.yml | 84 +++ .../Resources/config/validation.yml | 5 + .../Resources/public/css/scss/style.scss | 7 + .../js/app/views/payment-method-view.js | 90 +++ .../js/app/views/payment-source-view.js | 51 ++ .../public/js/app/views/total-paid-view.js | 98 +++ .../Resources/translations/messages.en.yml | 25 +- .../Resources/translations/validators.en.yml | 2 + .../views/Action/payment_popup.html.twig | 22 + .../Form/paymentMethodSelector.html.twig | 1 + .../paymentMethodWithOptions.html.twig | 8 + .../paymentMethodWithoutOptions.html.twig | 4 + .../Resources/views/Payment/create.html.twig | 96 +++ .../Resources/views/Payment/index.html.twig | 13 + .../Resources/views/Payment/update.html.twig | 91 +++ .../Resources/views/Payment/view.html.twig | 74 +++ .../Validator/Constraints/PaymentStatus.php | 27 + .../Validator/Constraints/TotalPaid.php | 27 + .../Validator/PaymentStatusValidator.php | 37 ++ .../Validator/TotalPaidValidator.php | 38 ++ .../Provider/PaymentTermProvider.php | 11 + .../Resources/config/services.yml | 9 + .../Twig/PaymentTermExtension.php | 71 ++ .../DependencyInjection/Configuration.php | 2 + .../config/oro/system_configuration.yml | 10 +- .../Resources/translations/messages.en.yml | 3 + .../Resources/views/Download/util.html.twig | 2 +- .../ChannelPricesDatagridListener.php | 215 ++---- .../Datagrid/PricesDatagridListener.php | 231 +++---- .../Resources/config/services.yml | 8 +- .../Property/defaultChannelPrices.html.twig | 9 +- .../Datagrid/Property/defaultPrices.html.twig | 9 +- .../Datagrid/Property/msrpPrices.html.twig | 9 +- .../Property/specialChannelPrices.html.twig | 9 +- .../Datagrid/Property/specialPrices.html.twig | 9 +- .../AssembledChannelPriceListJsonApiTest.php | 5 +- .../Controller/ProductController.php | 54 +- .../Entity/Builder/ProductFamilyBuilder.php | 107 +++ .../Bundle/ProductBundle/Entity/Product.php | 123 +++- .../Entity/Repository/ProductRepository.php | 22 +- .../Datagrid/AbstractProductsGridListener.php | 55 ++ .../Datagrid/ProductGridListener.php | 3 +- .../ORM/AssignAttributesToDefaultFamily.php | 117 ---- .../ORM/LoadDefaultAttributeFamilyData.php | 102 --- .../Data/ORM/LoadDefaultProductFamilyData.php | 62 ++ .../ORM/UpdateExistingAttributesConfig.php | 2 +- ...ateExistingProductsWithAttributeFamily.php | 5 +- ...ateExistingProductsWithCategoriesCodes.php | 41 ++ ...pdateExistingProductsWithChannelsCodes.php | 41 ++ .../Schema/MarelloProductBundleInstaller.php | 6 +- .../Schema/v1_11/MarelloProductBundle.php | 31 + .../Schema/v1_12/MarelloProductBundle.php | 28 + .../Provider/OrderItemProductUnitProvider.php | 72 ++ .../Provider/ProductTaxCodeProvider.php | 3 +- .../Resources/config/oro/actions.yml | 2 +- .../Resources/config/oro/api.yml | 4 + .../Resources/config/oro/datagrids.yml | 36 + .../Resources/config/services.yml | 18 +- .../Resources/config/validation.yml | 2 +- .../Resources/translations/messages.en.yml | 2 + .../Datagrid/Property/categories.html.twig | 6 + .../Datagrid/Property/channels.html.twig | 6 + .../views/Product/createStepTwo.html.twig | 7 +- .../Controller/ProductControllerTest.php | 4 +- .../DataFixtures/LoadProductData.php | 4 +- .../Tests/Functional/Entity/ProductTest.php | 4 +- .../ProductBundle/Twig/ProductExtension.php | 33 +- .../Controller/PurchaseOrderController.php | 9 +- .../Type/PurchaseOrderCreateStepTwoType.php | 13 +- .../Resources/translations/messages.en.yml | 1 + .../PurchaseOrder/createStepTwo.html.twig | 7 +- .../PurchaseOrderControllerTest.php | 2 +- .../Resources/config/oro/navigation.yml | 2 - .../Resources/views/Refund/update.html.twig | 1 - .../Resources/views/Refund/view.html.twig | 2 - .../Controller/RefundControllerTest.php | 5 +- .../Resources/config/oro/datagrids.yml | 18 +- .../Controller/ReturnController.php | 3 +- .../Repository/SalesChannelRepository.php | 14 + .../SalesBundle/Entity/SalesChannel.php | 58 ++ .../SalesChannelsDatagridListener.php | 172 ----- .../SalesBundle/Resources/config/services.yml | 8 - .../Resources/translations/messages.en.yml | 1 + .../Datagrid/Property/channels.html.twig | 7 - .../Tests/Unit/Twig/SalesExtensionTest.php | 41 ++ .../SalesBundle/Twig/SalesExtension.php | 19 + .../Datagrid/TaxCodeDatagridListener.php | 2 +- 231 files changed, 6700 insertions(+), 1530 deletions(-) delete mode 100644 src/Marello/Bundle/CatalogBundle/EventListener/Datagrid/CategoriesDatagridListener.php create mode 100644 src/Marello/Bundle/CatalogBundle/Migrations/Schema/v1_2/MarelloCatalogBundle.php delete mode 100644 src/Marello/Bundle/CatalogBundle/Resources/views/Datagrid/Property/categories.html.twig create mode 100644 src/Marello/Bundle/CatalogBundle/Twig/CategoryExtension.php create mode 100644 src/Marello/Bundle/CustomerBundle/Migrations/Schema/v1_5/MarelloCustomerBundlePart1.php create mode 100644 src/Marello/Bundle/CustomerBundle/Migrations/Schema/v1_5/MarelloCustomerBundlePart2.php create mode 100644 src/Marello/Bundle/DataGridBundle/Extension/Totals/OrmTotalsExtension.php create mode 100644 src/Marello/Bundle/FilterBundle/DependencyInjection/MarelloFilterExtension.php create mode 100644 src/Marello/Bundle/FilterBundle/Filter/ChoiceLikeFilter.php create mode 100644 src/Marello/Bundle/FilterBundle/Resources/config/services.yml create mode 100644 src/Marello/Bundle/InventoryBundle/EventListener/Datagrid/InventoryLevelGridListener.php create mode 100644 src/Marello/Bundle/InventoryBundle/Migrations/Schema/v2_5/UpdateInventoryLevelLogForeignKey.php create mode 100644 src/Marello/Bundle/InventoryBundle/Resources/views/Inventory/Datagrid/manageBatches.html.twig create mode 100644 src/Marello/Bundle/InventoryBundle/Resources/views/InventoryLevel/batchesView.html.twig create mode 100644 src/Marello/Bundle/InvoiceBundle/Entity/Repository/AbstractInvoiceRepository.php create mode 100644 src/Marello/Bundle/InvoiceBundle/Form/Type/InvoiceSelectType.php create mode 100644 src/Marello/Bundle/InvoiceBundle/Migrations/Schema/v2_0/MarelloInvoiceBundleAddColumns.php create mode 100644 src/Marello/Bundle/InvoiceBundle/Migrations/Schema/v2_0/MarelloInvoiceBundleAddQuery.php create mode 100644 src/Marello/Bundle/InvoiceBundle/Migrations/Schema/v2_0/MarelloInvoiceBundleRemoveColumns.php create mode 100644 src/Marello/Bundle/InvoiceBundle/Migrations/Schema/v2_0/PaymentsCreationQuery.php create mode 100644 src/Marello/Bundle/InvoiceBundle/Provider/InvoicePaidAmountProvider.php create mode 100644 src/Marello/Bundle/InvoiceBundle/Resources/config/oro/actions.yml create mode 100644 src/Marello/Bundle/InvoiceBundle/Twig/InvoiceExtension.php create mode 100644 src/Marello/Bundle/NotificationBundle/Migrations/Schema/v1_2/MarelloNotificationBundle.php create mode 100644 src/Marello/Bundle/OrderBundle/Form/Type/OrderTotalPaidType.php create mode 100644 src/Marello/Bundle/OrderBundle/Migrations/Schema/v3_1/MarelloOrderBundle.php create mode 100644 src/Marello/Bundle/OrderBundle/Migrations/Schema/v3_1_1/MarelloOrderBundle.php rename src/Marello/Bundle/OrderBundle/Migrations/Schema/{v1_13_1 => v3_1_2}/MarelloOrderBundle.php (77%) create mode 100644 src/Marello/Bundle/PaymentBundle/Action/Handler/AddPaymentActionHandler.php create mode 100644 src/Marello/Bundle/PaymentBundle/Controller/PaymentAjaxController.php create mode 100644 src/Marello/Bundle/PaymentBundle/Controller/PaymentController.php create mode 100644 src/Marello/Bundle/PaymentBundle/Entity/Payment.php create mode 100644 src/Marello/Bundle/PaymentBundle/EventListener/PaymentCreationListener.php create mode 100644 src/Marello/Bundle/PaymentBundle/Form/Handler/PaymentCreateHandler.php create mode 100644 src/Marello/Bundle/PaymentBundle/Form/Handler/PaymentUpdateHandler.php create mode 100644 src/Marello/Bundle/PaymentBundle/Form/Type/PaymentCreateType.php create mode 100644 src/Marello/Bundle/PaymentBundle/Form/Type/PaymentUpdateType.php create mode 100644 src/Marello/Bundle/PaymentBundle/Migrations/Data/ORM/LoadPaymentStatusData.php create mode 100644 src/Marello/Bundle/PaymentBundle/Migrations/Schema/v2_0/MarelloPaymentBundle.php create mode 100644 src/Marello/Bundle/PaymentBundle/Model/ExtendPayment.php create mode 100644 src/Marello/Bundle/PaymentBundle/Provider/FormChanges/AvailableCurrenciesFormChangesProvider.php create mode 100644 src/Marello/Bundle/PaymentBundle/Provider/FormChanges/AvailablePaymentMethodsFormChangesProvider.php create mode 100755 src/Marello/Bundle/PaymentBundle/Resources/public/js/app/views/payment-method-view.js create mode 100755 src/Marello/Bundle/PaymentBundle/Resources/public/js/app/views/payment-source-view.js create mode 100755 src/Marello/Bundle/PaymentBundle/Resources/public/js/app/views/total-paid-view.js create mode 100644 src/Marello/Bundle/PaymentBundle/Resources/views/Action/payment_popup.html.twig create mode 100755 src/Marello/Bundle/PaymentBundle/Resources/views/Form/paymentMethodSelector.html.twig create mode 100644 src/Marello/Bundle/PaymentBundle/Resources/views/Payment/Datagrid/paymentMethodWithOptions.html.twig create mode 100644 src/Marello/Bundle/PaymentBundle/Resources/views/Payment/Datagrid/paymentMethodWithoutOptions.html.twig create mode 100644 src/Marello/Bundle/PaymentBundle/Resources/views/Payment/create.html.twig create mode 100644 src/Marello/Bundle/PaymentBundle/Resources/views/Payment/index.html.twig create mode 100644 src/Marello/Bundle/PaymentBundle/Resources/views/Payment/update.html.twig create mode 100644 src/Marello/Bundle/PaymentBundle/Resources/views/Payment/view.html.twig create mode 100644 src/Marello/Bundle/PaymentBundle/Validator/Constraints/PaymentStatus.php create mode 100644 src/Marello/Bundle/PaymentBundle/Validator/Constraints/TotalPaid.php create mode 100644 src/Marello/Bundle/PaymentBundle/Validator/PaymentStatusValidator.php create mode 100644 src/Marello/Bundle/PaymentBundle/Validator/TotalPaidValidator.php create mode 100755 src/Marello/Bundle/PaymentTermBundle/Twig/PaymentTermExtension.php create mode 100644 src/Marello/Bundle/ProductBundle/Entity/Builder/ProductFamilyBuilder.php create mode 100644 src/Marello/Bundle/ProductBundle/EventListener/Datagrid/AbstractProductsGridListener.php delete mode 100644 src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/AssignAttributesToDefaultFamily.php delete mode 100644 src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/LoadDefaultAttributeFamilyData.php create mode 100644 src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/LoadDefaultProductFamilyData.php create mode 100644 src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/UpdateExistingProductsWithCategoriesCodes.php create mode 100644 src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/UpdateExistingProductsWithChannelsCodes.php create mode 100644 src/Marello/Bundle/ProductBundle/Migrations/Schema/v1_11/MarelloProductBundle.php create mode 100644 src/Marello/Bundle/ProductBundle/Migrations/Schema/v1_12/MarelloProductBundle.php create mode 100644 src/Marello/Bundle/ProductBundle/Provider/OrderItemProductUnitProvider.php create mode 100644 src/Marello/Bundle/ProductBundle/Resources/views/Product/Datagrid/Property/categories.html.twig create mode 100644 src/Marello/Bundle/ProductBundle/Resources/views/Product/Datagrid/Property/channels.html.twig delete mode 100644 src/Marello/Bundle/SalesBundle/EventListener/Datagrid/SalesChannelsDatagridListener.php delete mode 100644 src/Marello/Bundle/SalesBundle/Resources/views/SalesChannel/Datagrid/Property/channels.html.twig diff --git a/composer.json b/composer.json index d57ff137c..e82f6c984 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,7 @@ "prefer-stable": true, "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { diff --git a/src/Marello/Bundle/CatalogBundle/Entity/Category.php b/src/Marello/Bundle/CatalogBundle/Entity/Category.php index 4a0744fe6..9c6be361a 100755 --- a/src/Marello/Bundle/CatalogBundle/Entity/Category.php +++ b/src/Marello/Bundle/CatalogBundle/Entity/Category.php @@ -17,8 +17,8 @@ * @ORM\Table(name="marello_catalog_category", * uniqueConstraints={ * @ORM\UniqueConstraint( - * name="marello_catalog_category_codeidx", - * columns={"code"} + * name="marello_catalog_category_codeorgidx", + * columns={"code", "organization_id"} * ) * } * ) @@ -218,6 +218,7 @@ public function addProduct(Product $product) { if (!$this->hasProduct($product)) { $this->products->add($product); + $product->addCategoryCode($this->getCode()); } return $this; @@ -230,6 +231,7 @@ public function addProduct(Product $product) public function removeProduct(Product $product) { if ($this->hasProduct($product)) { + $product->removeCategory($this); $this->products->removeElement($product); } diff --git a/src/Marello/Bundle/CatalogBundle/Entity/Repository/CategoryRepository.php b/src/Marello/Bundle/CatalogBundle/Entity/Repository/CategoryRepository.php index 584198873..743501e59 100644 --- a/src/Marello/Bundle/CatalogBundle/Entity/Repository/CategoryRepository.php +++ b/src/Marello/Bundle/CatalogBundle/Entity/Repository/CategoryRepository.php @@ -3,6 +3,9 @@ namespace Marello\Bundle\CatalogBundle\Entity\Repository; use Doctrine\ORM\EntityRepository; +use Marello\Bundle\CatalogBundle\Entity\Category; +use Marello\Bundle\ProductBundle\Entity\Product; +use Marello\Bundle\SalesBundle\Entity\SalesChannel; use Oro\Bundle\SecurityBundle\ORM\Walker\AclHelper; class CategoryRepository extends EntityRepository @@ -33,4 +36,17 @@ public function findExcludedCategoriesIds(array $relatedCategoriesIds) return $this->aclHelper->apply($qb)->getArrayResult(); } + + /** + * @param Product $product + * @return Category[] + */ + public function findByProduct(Product $product) + { + $qb = $this->createQueryBuilder('c') + ->where(':product MEMBER OF c.products') + ->setParameters(['product' => $product]); + + return $qb->getQuery()->getResult(); + } } diff --git a/src/Marello/Bundle/CatalogBundle/EventListener/Datagrid/CategoriesDatagridListener.php b/src/Marello/Bundle/CatalogBundle/EventListener/Datagrid/CategoriesDatagridListener.php deleted file mode 100644 index 60b5231d3..000000000 --- a/src/Marello/Bundle/CatalogBundle/EventListener/Datagrid/CategoriesDatagridListener.php +++ /dev/null @@ -1,162 +0,0 @@ -relatedEntityClass = $relatedEntityClass; - $this->categoriesChoicesProvider = $categoriesChoicesProvider; - - $this->expressionBuilder = new Expr(); - } - - /** - * @param BuildBefore $event - */ - public function onBuildBefore(BuildBefore $event) - { - $config = $event->getConfig(); - - $this->addSelect($config); - $this->addJoin($config); - $this->addColumn($config); - $this->addSorter($config); - $this->addFilter($config); - } - - /** - * @param DatagridConfiguration $configuration - * @return string - * @throws \InvalidArgumentException when a root entity not found in the grid - */ - protected function getAlias(DatagridConfiguration $configuration) - { - $rootAlias = $configuration->getOrmQuery()->getRootAlias(); - if (!$rootAlias) { - throw new \InvalidArgumentException( - sprintf( - 'A root entity is missing for grid "%s"', - $configuration->getName() - ) - ); - } - - return $rootAlias; - } - - /** - * @return string - */ - protected function getColumnLabel() - { - return 'marello.catalog.category.entity_plural_label'; - } - - /** - * @return string - */ - protected function getDataName() - { - return self::DATA_NAME; - } - - /** - * @return string - */ - protected function getJoinAlias() - { - return self::JOIN_ALIAS; - } - - /** - * @param DatagridConfiguration $config - */ - protected function addSelect(DatagridConfiguration $config) - { - $config->getOrmQuery()->addSelect( - sprintf('count(%s.code) AS categoriesCount', $this->getJoinAlias()) - ); - } - - /** - * @param DatagridConfiguration $config - */ - protected function addJoin(DatagridConfiguration $config) - { - $config->getOrmQuery()->addLeftJoin( - $this->getAlias($config).'.categories', - $this->getJoinAlias() - ); - } - - /** - * @param DatagridConfiguration $config - */ - protected function addColumn(DatagridConfiguration $config) - { - $config->offsetSetByPath(sprintf('[columns][%s]', $this->getDataName()), [ - 'label' => $this->getColumnLabel(), - 'type' => 'twig', - 'frontend_type' => 'html', - 'template' => 'MarelloCatalogBundle:Datagrid/Property:categories.html.twig', - 'renderable' => false - ]); - } - - /** - * @param DatagridConfiguration $config - */ - protected function addSorter(DatagridConfiguration $config) - { - $config->offsetSetByPath( - sprintf('[sorters][columns][%s]', $this->getDataName()), - ['data_name' => 'categoriesCount'] - ); - } - - /** - * @param DatagridConfiguration $config - */ - protected function addFilter(DatagridConfiguration $config) - { - $config->offsetSetByPath( - sprintf('[filters][columns][%s]', $this->getDataName()), - [ - 'type' => 'choice', - 'data_name' => $this->getJoinAlias() . '.code', - 'enabled' => false, - 'options' => [ - 'field_options' => [ - 'multiple' => true, - 'choices' => $this->categoriesChoicesProvider->getCategories() - ] - ] - ] - ); - } -} diff --git a/src/Marello/Bundle/CatalogBundle/Migrations/Schema/MarelloCatalogBundleInstaller.php b/src/Marello/Bundle/CatalogBundle/Migrations/Schema/MarelloCatalogBundleInstaller.php index f6f33fa38..bf35ef7fe 100755 --- a/src/Marello/Bundle/CatalogBundle/Migrations/Schema/MarelloCatalogBundleInstaller.php +++ b/src/Marello/Bundle/CatalogBundle/Migrations/Schema/MarelloCatalogBundleInstaller.php @@ -20,7 +20,7 @@ class MarelloCatalogBundleInstaller implements Installation, ActivityExtensionAw */ public function getMigrationVersion() { - return 'v1_1_1'; + return 'v1_2'; } /** @@ -61,7 +61,7 @@ protected function createCatalogCategoryTable(Schema $schema) $table->addColumn('updated_at', 'datetime', ['notnull' => false]); $table->addColumn('organization_id', 'integer', ['notnull' => false]); $table->setPrimaryKey(['id']); - $table->addUniqueIndex(['code'], 'marello_catalog_category_codeidx'); + $table->addUniqueIndex(['code', 'organization_id'], 'marello_catalog_category_codeorgidx'); $this->activityExtension->addActivityAssociation($schema, 'oro_note', 'marello_catalog_category'); } diff --git a/src/Marello/Bundle/CatalogBundle/Migrations/Schema/v1_2/MarelloCatalogBundle.php b/src/Marello/Bundle/CatalogBundle/Migrations/Schema/v1_2/MarelloCatalogBundle.php new file mode 100644 index 000000000..5e5ad41a9 --- /dev/null +++ b/src/Marello/Bundle/CatalogBundle/Migrations/Schema/v1_2/MarelloCatalogBundle.php @@ -0,0 +1,31 @@ +changeMarelloCatalogCategoryUniqueIndex($schema); + } + + /** + * @param Schema $schema + */ + protected function changeMarelloCatalogCategoryUniqueIndex(Schema $schema) + { + $table = $schema->getTable('marello_catalog_category'); + $table->dropIndex('marello_catalog_category_codeidx'); + $table->addUniqueIndex(['code', 'organization_id'], 'marello_catalog_category_codeorgidx'); + } +} diff --git a/src/Marello/Bundle/CatalogBundle/Resources/config/services.yml b/src/Marello/Bundle/CatalogBundle/Resources/config/services.yml index a4ccf54b1..910595b99 100644 --- a/src/Marello/Bundle/CatalogBundle/Resources/config/services.yml +++ b/src/Marello/Bundle/CatalogBundle/Resources/config/services.yml @@ -20,14 +20,6 @@ services: - '@request_stack' - '@doctrine.orm.entity_manager' - marello_catalog.event_listener.datagrid.products_grid: - class: 'Marello\Bundle\CatalogBundle\EventListener\Datagrid\CategoriesDatagridListener' - arguments: - - 'Marello\Bundle\ProductBundle\Entity\Product' - - '@marello_catalog.provider.categories_choices' - tags: - - { name: kernel.event_listener, event: oro_datagrid.datagrid.build.before.marello-products-grid, method: onBuildBefore } - marello_catalog.listener.datagrid.category_products_column_listener: class: 'Marello\Bundle\CatalogBundle\EventListener\Datagrid\CategoryProductsColumnListener' arguments: @@ -57,3 +49,9 @@ services: calls: - [setAclHelper, ['@oro_security.acl_helper']] + marello_catalog.twig.category_extension: + class: 'Marello\Bundle\CatalogBundle\Twig\CategoryExtension' + arguments: + - '@doctrine' + tags: + - { name: twig.extension } diff --git a/src/Marello/Bundle/CatalogBundle/Resources/config/validation.yml b/src/Marello/Bundle/CatalogBundle/Resources/config/validation.yml index 03f724875..dc7b04ecf 100644 --- a/src/Marello/Bundle/CatalogBundle/Resources/config/validation.yml +++ b/src/Marello/Bundle/CatalogBundle/Resources/config/validation.yml @@ -1,7 +1,7 @@ Marello\Bundle\CatalogBundle\Entity\Category: constraints: - Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity: - fields: code + fields: [code, organization] message: 'marello.catalog.category.messages.error.code' properties: name: diff --git a/src/Marello/Bundle/CatalogBundle/Resources/views/Datagrid/Property/categories.html.twig b/src/Marello/Bundle/CatalogBundle/Resources/views/Datagrid/Property/categories.html.twig deleted file mode 100644 index 873179a78..000000000 --- a/src/Marello/Bundle/CatalogBundle/Resources/views/Datagrid/Property/categories.html.twig +++ /dev/null @@ -1,3 +0,0 @@ -{% for index, category in record.getValue('categories') %} - {{ category|trans }}
-{% endfor %} \ No newline at end of file diff --git a/src/Marello/Bundle/CatalogBundle/Twig/CategoryExtension.php b/src/Marello/Bundle/CatalogBundle/Twig/CategoryExtension.php new file mode 100644 index 000000000..18ad25617 --- /dev/null +++ b/src/Marello/Bundle/CatalogBundle/Twig/CategoryExtension.php @@ -0,0 +1,68 @@ +doctrine = $doctrine; + } + + /** + * Returns the name of the extension. + * + * @return string The extension name + */ + public function getName() + { + return self::NAME; + } + + /** + * Returns a list of functions to add to the existing list. + * + * @return array An array of functions + */ + public function getFunctions() + { + return [ + new TwigFunction( + 'marello_get_category_name_by_code', + [$this, 'getCategoryNameByCode'] + ) + ]; + } + + /** + * @param string $code + * @return string + */ + public function getCategoryNameByCode($code) + { + $category = $this->doctrine + ->getManagerForClass(Category::class) + ->getRepository(Category::class) + ->findOneBy(['code' => $code]); + if ($category) { + return $category->getName(); + } + + return $code; + } +} diff --git a/src/Marello/Bundle/CustomerBundle/Autocomplete/CompanyCustomerHandler.php b/src/Marello/Bundle/CustomerBundle/Autocomplete/CompanyCustomerHandler.php index 597fd2278..eae8e8371 100644 --- a/src/Marello/Bundle/CustomerBundle/Autocomplete/CompanyCustomerHandler.php +++ b/src/Marello/Bundle/CustomerBundle/Autocomplete/CompanyCustomerHandler.php @@ -3,10 +3,10 @@ namespace Marello\Bundle\CustomerBundle\Autocomplete; use Marello\Bundle\CustomerBundle\Entity\Company; -use Oro\Bundle\FormBundle\Autocomplete\SearchHandler; +use Oro\Bundle\FormBundle\Autocomplete\FullNameSearchHandler; use Doctrine\ORM\QueryBuilder; -class CompanyCustomerHandler extends SearchHandler +class CompanyCustomerHandler extends FullNameSearchHandler { /** * {@inheritdoc} diff --git a/src/Marello/Bundle/CustomerBundle/Entity/Company.php b/src/Marello/Bundle/CustomerBundle/Entity/Company.php index 991b960ff..56a09eb19 100644 --- a/src/Marello/Bundle/CustomerBundle/Entity/Company.php +++ b/src/Marello/Bundle/CustomerBundle/Entity/Company.php @@ -203,6 +203,20 @@ class Company extends ExtendCompany implements OrganizationAwareInterface **/ protected $customers; + /** + * @ORM\Column(name="tax_identification_number", type="string", nullable=true) + * @ConfigField( + * defaultValues={ + * "dataaudit"={ + * "auditable"=true + * } + * } + * ) + * + * @var string + */ + protected $taxIdentificationNumber; + /** * Constructor */ @@ -451,4 +465,24 @@ protected function hasCustomer(Customer $customer) { return $this->customers->contains($customer); } + + /** + * @return string + */ + public function getTaxIdentificationNumber() + { + return $this->taxIdentificationNumber; + } + + /** + * @param string $taxIdentificationNumber + * + * @return $this + */ + public function setTaxIdentificationNumber($taxIdentificationNumber) + { + $this->taxIdentificationNumber = $taxIdentificationNumber; + + return $this; + } } diff --git a/src/Marello/Bundle/CustomerBundle/Entity/Customer.php b/src/Marello/Bundle/CustomerBundle/Entity/Customer.php index f2df2fba5..67b8f24aa 100644 --- a/src/Marello/Bundle/CustomerBundle/Entity/Customer.php +++ b/src/Marello/Bundle/CustomerBundle/Entity/Customer.php @@ -92,20 +92,6 @@ class Customer extends ExtendCustomer implements */ protected $shippingAddress; - /** - * @ORM\Column(name="tax_identification_number", type="string", nullable=true) - * @Oro\ConfigField( - * defaultValues={ - * "dataaudit"={ - * "auditable"=true - * } - * } - * ) - * - * @var string - */ - protected $taxIdentificationNumber; - /** * @ORM\OneToMany( * targetEntity="Marello\Bundle\AddressBundle\Entity\MarelloAddress", @@ -266,26 +252,6 @@ public function getShippingAddress() return $this->shippingAddress; } - /** - * @return string - */ - public function getTaxIdentificationNumber() - { - return $this->taxIdentificationNumber; - } - - /** - * @param string $taxIdentificationNumber - * - * @return $this - */ - public function setTaxIdentificationNumber($taxIdentificationNumber) - { - $this->taxIdentificationNumber = $taxIdentificationNumber; - - return $this; - } - /** * @return Company */ diff --git a/src/Marello/Bundle/CustomerBundle/Form/Type/CompanyType.php b/src/Marello/Bundle/CustomerBundle/Form/Type/CompanyType.php index 87a4d20ac..63a062450 100644 --- a/src/Marello/Bundle/CustomerBundle/Form/Type/CompanyType.php +++ b/src/Marello/Bundle/CustomerBundle/Form/Type/CompanyType.php @@ -12,8 +12,6 @@ use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormEvent; -use Symfony\Component\Form\FormEvents; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; @@ -58,6 +56,10 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'label' => 'marello.customer.company.payment_term.label', 'required' => false, ]) + ->add('taxIdentificationNumber', TextType::class, [ + 'label' => 'marello.customer.company.tax_identification_number.label', + 'required' => false, + ]) ->add( 'appendCustomers', EntityIdentifierType::class, diff --git a/src/Marello/Bundle/CustomerBundle/Form/Type/CustomerType.php b/src/Marello/Bundle/CustomerBundle/Form/Type/CustomerType.php index b11a96c58..d1cb8c38d 100644 --- a/src/Marello/Bundle/CustomerBundle/Form/Type/CustomerType.php +++ b/src/Marello/Bundle/CustomerBundle/Form/Type/CustomerType.php @@ -42,9 +42,6 @@ public function buildForm(FormBuilderInterface $builder, array $options) ->add('email', EmailType::class, [ 'required' => true ]) - ->add('taxIdentificationNumber', TextType::class, [ - 'required' => false, - ]) ->add('primaryAddress', AddressType::class, [ 'required' => false, ]) diff --git a/src/Marello/Bundle/CustomerBundle/Migrations/Schema/MarelloCustomerBundleInstaller.php b/src/Marello/Bundle/CustomerBundle/Migrations/Schema/MarelloCustomerBundleInstaller.php index 41620e1fd..7cd0ce8db 100644 --- a/src/Marello/Bundle/CustomerBundle/Migrations/Schema/MarelloCustomerBundleInstaller.php +++ b/src/Marello/Bundle/CustomerBundle/Migrations/Schema/MarelloCustomerBundleInstaller.php @@ -34,7 +34,7 @@ class MarelloCustomerBundleInstaller implements */ public function getMigrationVersion() { - return 'v1_4_1'; + return 'v1_5'; } /** @@ -65,6 +65,7 @@ protected function createMarelloCompanyTable(Schema $schema) $table->addColumn('name', 'string', ['length' => 255]); $table->addColumn('company_number', 'string', ['length' => 255, 'notnull' => false]); $table->addColumn('payment_term_id', 'integer', ['notnull' => false]); + $table->addColumn('tax_identification_number', 'string', ['notnull' => false, 'length' => 255]); $table->addColumn('parent_id', 'integer', ['notnull' => false]); $table->addColumn('organization_id', 'integer', ['notnull' => false]); $table->addColumn('created_at', 'datetime'); @@ -103,7 +104,6 @@ protected function createMarelloCustomerTable(Schema $schema) $table->addColumn('last_name', 'string', ['length' => 255]); $table->addColumn('name_suffix', 'string', ['notnull' => false, 'length' => 255]); $table->addColumn('email', 'text', []); - $table->addColumn('tax_identification_number', 'string', ['notnull' => false, 'length' => 255]); $table->addColumn('company_id', 'integer', ['notnull' => false]); $table->setPrimaryKey(['id']); $table->addIndex(['organization_id']); diff --git a/src/Marello/Bundle/CustomerBundle/Migrations/Schema/v1_5/MarelloCustomerBundlePart1.php b/src/Marello/Bundle/CustomerBundle/Migrations/Schema/v1_5/MarelloCustomerBundlePart1.php new file mode 100644 index 000000000..904ebafe4 --- /dev/null +++ b/src/Marello/Bundle/CustomerBundle/Migrations/Schema/v1_5/MarelloCustomerBundlePart1.php @@ -0,0 +1,59 @@ +getTable(MarelloCustomerBundleInstaller::MARELLO_COMPANY_TABLE); + $table->addColumn('tax_identification_number', 'string', ['notnull' => false, 'length' => 255]); + if ($this->connection->getDriver()->getName() === DatabaseDriverInterface::DRIVER_POSTGRESQL) { + $sql = <<addPostQuery($sql); + } + + /** + * {@inheritdoc} + */ + public function setConnection(Connection $connection) + { + $this->connection = $connection; + } + +} diff --git a/src/Marello/Bundle/CustomerBundle/Migrations/Schema/v1_5/MarelloCustomerBundlePart2.php b/src/Marello/Bundle/CustomerBundle/Migrations/Schema/v1_5/MarelloCustomerBundlePart2.php new file mode 100644 index 000000000..3f2fb834e --- /dev/null +++ b/src/Marello/Bundle/CustomerBundle/Migrations/Schema/v1_5/MarelloCustomerBundlePart2.php @@ -0,0 +1,33 @@ +getTable(MarelloCustomerBundleInstaller::MARELLO_CUSTOMER_TABLE); + $table->dropColumn('tax_identification_number'); + } +} diff --git a/src/Marello/Bundle/CustomerBundle/Resources/config/services.yml b/src/Marello/Bundle/CustomerBundle/Resources/config/services.yml index bf043f992..de3a7c476 100644 --- a/src/Marello/Bundle/CustomerBundle/Resources/config/services.yml +++ b/src/Marello/Bundle/CustomerBundle/Resources/config/services.yml @@ -44,7 +44,7 @@ services: marello_customer.form.autocomplete.company_customer.search_handler: class: 'Marello\Bundle\CustomerBundle\Autocomplete\CompanyCustomerHandler' - parent: oro_form.autocomplete.search_handler + parent: oro_form.autocomplete.full_name.search_handler arguments: - 'Marello\Bundle\CustomerBundle\Entity\Customer' - ['namePrefix', 'firstName', 'middleName', 'lastName', 'nameSuffix'] diff --git a/src/Marello/Bundle/CustomerBundle/Resources/config/validation.yml b/src/Marello/Bundle/CustomerBundle/Resources/config/validation.yml index f193a3d9b..9bc7c6904 100644 --- a/src/Marello/Bundle/CustomerBundle/Resources/config/validation.yml +++ b/src/Marello/Bundle/CustomerBundle/Resources/config/validation.yml @@ -15,4 +15,4 @@ Marello\Bundle\CustomerBundle\Entity\Company: message: 'marello.customer.company.number.message' properties: name: - - NotBlank: ~ \ No newline at end of file + - NotBlank: ~ diff --git a/src/Marello/Bundle/CustomerBundle/Resources/translations/messages.en.yml b/src/Marello/Bundle/CustomerBundle/Resources/translations/messages.en.yml index bffdb9031..57e808fb5 100644 --- a/src/Marello/Bundle/CustomerBundle/Resources/translations/messages.en.yml +++ b/src/Marello/Bundle/CustomerBundle/Resources/translations/messages.en.yml @@ -7,7 +7,6 @@ marello: organization.label: 'Organization' primary_address.label: 'Primary Address' shipping_address.label: 'Shipping Address' - tax_identification_number.label: 'Tax Identification Number' addresses.label: 'Addresses' email.label: 'Primary Email' emails.label: 'Email Addresses' @@ -35,6 +34,7 @@ marello: customers.label: 'Customers' organization.label: 'Organization' payment_term.label: 'Payment Term' + tax_identification_number.label: 'Tax Identification Number' form: choose: 'Choose a company...' diff --git a/src/Marello/Bundle/CustomerBundle/Resources/translations/pdf.en.yml b/src/Marello/Bundle/CustomerBundle/Resources/translations/pdf.en.yml index da88d9569..44fa83ae6 100644 --- a/src/Marello/Bundle/CustomerBundle/Resources/translations/pdf.en.yml +++ b/src/Marello/Bundle/CustomerBundle/Resources/translations/pdf.en.yml @@ -3,3 +3,4 @@ marello: company: pdf: company_number.label: "Company Number" + tax_identification_number.label: 'Tax Identification Number' \ No newline at end of file diff --git a/src/Marello/Bundle/CustomerBundle/Resources/views/Company/update.html.twig b/src/Marello/Bundle/CustomerBundle/Resources/views/Company/update.html.twig index 360527cdc..0222c29df 100644 --- a/src/Marello/Bundle/CustomerBundle/Resources/views/Company/update.html.twig +++ b/src/Marello/Bundle/CustomerBundle/Resources/views/Company/update.html.twig @@ -54,6 +54,7 @@ form_row(form.companyNumber), form_row(form.parent), form_row(form.paymentTerm), + form_row(form.taxIdentificationNumber), form_widget(form.appendCustomers, {'id': 'appendCustomers'}), form_widget(form.removeCustomers, {'id': 'removeCustomers'}), ] diff --git a/src/Marello/Bundle/CustomerBundle/Resources/views/Company/view.html.twig b/src/Marello/Bundle/CustomerBundle/Resources/views/Company/view.html.twig index c7f2e79b1..5dd7494bf 100644 --- a/src/Marello/Bundle/CustomerBundle/Resources/views/Company/view.html.twig +++ b/src/Marello/Bundle/CustomerBundle/Resources/views/Company/view.html.twig @@ -35,6 +35,7 @@ {% if entity.paymentTerm %} {{ UI.renderProperty('marello.customer.company.payment_term.label'|trans, entity.paymentTerm.labels|localized_value) }} {% endif %} + {{ UI.renderProperty('marello.customer.company.tax_identification_number.label'|trans, entity.taxIdentificationNumber ? entity.taxIdentificationNumber : 'N/A') }} {{ entityConfig.renderDynamicFields(entity) }} diff --git a/src/Marello/Bundle/CustomerBundle/Resources/views/Customer/update.html.twig b/src/Marello/Bundle/CustomerBundle/Resources/views/Customer/update.html.twig index 6f2925943..d7826acec 100644 --- a/src/Marello/Bundle/CustomerBundle/Resources/views/Customer/update.html.twig +++ b/src/Marello/Bundle/CustomerBundle/Resources/views/Customer/update.html.twig @@ -49,7 +49,6 @@ form_row(form.lastName), form_row(form.nameSuffix), form_row(form.email), - form_row(form.taxIdentificationNumber), ] }] }] %} diff --git a/src/Marello/Bundle/CustomerBundle/Tests/Functional/Api/responses/cget_companies_list.yml b/src/Marello/Bundle/CustomerBundle/Tests/Functional/Api/responses/cget_companies_list.yml index 8e5ffd244..a25e947aa 100644 --- a/src/Marello/Bundle/CustomerBundle/Tests/Functional/Api/responses/cget_companies_list.yml +++ b/src/Marello/Bundle/CustomerBundle/Tests/Functional/Api/responses/cget_companies_list.yml @@ -4,6 +4,7 @@ data: id: 'id)>' attributes: name: company1 + taxIdentificationNumber: null relationships: customers: data: @@ -22,6 +23,7 @@ data: id: 'id)>' attributes: name: company2 + taxIdentificationNumber: null relationships: paymentTerm: data: @@ -44,6 +46,7 @@ data: id: 'id)>' attributes: name: company3 + taxIdentificationNumber: null relationships: customers: data: diff --git a/src/Marello/Bundle/CustomerBundle/Tests/Functional/Api/responses/cget_customer_list.yml b/src/Marello/Bundle/CustomerBundle/Tests/Functional/Api/responses/cget_customer_list.yml index 3901a01b4..13a853953 100644 --- a/src/Marello/Bundle/CustomerBundle/Tests/Functional/Api/responses/cget_customer_list.yml +++ b/src/Marello/Bundle/CustomerBundle/Tests/Functional/Api/responses/cget_customer_list.yml @@ -3,7 +3,6 @@ data: type: marellocustomers id: 'id)>' attributes: - taxIdentificationNumber: null namePrefix: null firstName: Marilyn middleName: null @@ -30,7 +29,6 @@ data: type: marellocustomers id: 'id)>' attributes: - taxIdentificationNumber: null namePrefix: null firstName: James middleName: null @@ -57,7 +55,6 @@ data: type: marellocustomers id: 'id)>' attributes: - taxIdentificationNumber: null namePrefix: null firstName: Randy middleName: null @@ -84,7 +81,6 @@ data: type: marellocustomers id: 'id)>' attributes: - taxIdentificationNumber: null namePrefix: null firstName: Priscilla middleName: null @@ -111,7 +107,6 @@ data: type: marellocustomers id: 'id)>' attributes: - taxIdentificationNumber: null namePrefix: null firstName: May middleName: null @@ -138,7 +133,6 @@ data: type: marellocustomers id: 'id)>' attributes: - taxIdentificationNumber: null namePrefix: null firstName: Catherine middleName: null @@ -165,7 +159,6 @@ data: type: marellocustomers id: 'id)>' attributes: - taxIdentificationNumber: null namePrefix: null firstName: Richard middleName: null @@ -192,7 +185,6 @@ data: type: marellocustomers id: 'id)>' attributes: - taxIdentificationNumber: null namePrefix: null firstName: Edward middleName: null @@ -219,7 +211,6 @@ data: type: marellocustomers id: 'id)>' attributes: - taxIdentificationNumber: null namePrefix: null firstName: Kelly middleName: null @@ -246,7 +237,6 @@ data: type: marellocustomers id: 'id)>' attributes: - taxIdentificationNumber: null namePrefix: null firstName: Roberta middleName: null diff --git a/src/Marello/Bundle/CustomerBundle/Tests/Functional/Api/responses/get_company_by_id.yml b/src/Marello/Bundle/CustomerBundle/Tests/Functional/Api/responses/get_company_by_id.yml index 7ed038fe3..4754171e1 100644 --- a/src/Marello/Bundle/CustomerBundle/Tests/Functional/Api/responses/get_company_by_id.yml +++ b/src/Marello/Bundle/CustomerBundle/Tests/Functional/Api/responses/get_company_by_id.yml @@ -3,6 +3,7 @@ data: id: 'id)>' attributes: name: company1 + taxIdentificationNumber: null relationships: customers: data: diff --git a/src/Marello/Bundle/CustomerBundle/Tests/Functional/Api/responses/get_customer_by_email.yml b/src/Marello/Bundle/CustomerBundle/Tests/Functional/Api/responses/get_customer_by_email.yml index a73d6952b..02bc3d8e1 100644 --- a/src/Marello/Bundle/CustomerBundle/Tests/Functional/Api/responses/get_customer_by_email.yml +++ b/src/Marello/Bundle/CustomerBundle/Tests/Functional/Api/responses/get_customer_by_email.yml @@ -3,7 +3,6 @@ data: type: marellocustomers id: 'id)>' attributes: - taxIdentificationNumber: null namePrefix: null firstName: James middleName: null diff --git a/src/Marello/Bundle/CustomerBundle/Tests/Functional/Api/responses/get_customer_by_id.yml b/src/Marello/Bundle/CustomerBundle/Tests/Functional/Api/responses/get_customer_by_id.yml index fe9805cb6..44b291a12 100644 --- a/src/Marello/Bundle/CustomerBundle/Tests/Functional/Api/responses/get_customer_by_id.yml +++ b/src/Marello/Bundle/CustomerBundle/Tests/Functional/Api/responses/get_customer_by_id.yml @@ -2,7 +2,6 @@ data: type: marellocustomers id: 'id)>' attributes: - taxIdentificationNumber: null namePrefix: null firstName: James middleName: null diff --git a/src/Marello/Bundle/CustomerBundle/Tests/Unit/Autocomplete/ParentCompanySearchHandlerTest.php b/src/Marello/Bundle/CustomerBundle/Tests/Unit/Autocomplete/ParentCompanySearchHandlerTest.php index 6aef4d9ee..4e94db197 100644 --- a/src/Marello/Bundle/CustomerBundle/Tests/Unit/Autocomplete/ParentCompanySearchHandlerTest.php +++ b/src/Marello/Bundle/CustomerBundle/Tests/Unit/Autocomplete/ParentCompanySearchHandlerTest.php @@ -337,10 +337,6 @@ protected function assertSearchCall( $queryBuilder->expects($this->once()) ->method('getQuery') ->will($this->returnValue($query)); - $this->aclHelper->expects($this->once()) - ->method('apply') - ->with($query) - ->will($this->returnValue($query)); $this->entityRepository ->expects($this->any()) ->method('createQueryBuilder') diff --git a/src/Marello/Bundle/DataGridBundle/Extension/Totals/OrmTotalsExtension.php b/src/Marello/Bundle/DataGridBundle/Extension/Totals/OrmTotalsExtension.php new file mode 100644 index 000000000..2aae85c53 --- /dev/null +++ b/src/Marello/Bundle/DataGridBundle/Extension/Totals/OrmTotalsExtension.php @@ -0,0 +1,93 @@ + $total) { + $column = []; + if (isset($data[$field])) { + $totalValue = $data[$field]; + if (isset($total[Configuration::TOTALS_DIVISOR_KEY])) { + $divisor = (int) $total[Configuration::TOTALS_DIVISOR_KEY]; + if ($divisor != 0) { + $totalValue = $totalValue / $divisor; + } + } + if (isset($total[Configuration::TOTALS_FORMATTER_KEY])) { + if ($total[Configuration::TOTALS_FORMATTER_KEY] === 'currency' && isset($data['currency'])) { + $totalValue = $this->applyFrontendFormatting( + [$totalValue, $data['currency']], + $total[Configuration::TOTALS_FORMATTER_KEY] + ); + } else { + $totalValue = $this->applyFrontendFormatting( + $totalValue, + $total[Configuration::TOTALS_FORMATTER_KEY] + ); + } + } + $column['total'] = $totalValue; + } + if (isset($total[Configuration::TOTALS_LABEL_KEY])) { + $column[Configuration::TOTALS_LABEL_KEY] = + $this->translator->trans($total[Configuration::TOTALS_LABEL_KEY]); + } + $columns[$field] = $column; + }; + + return ['columns' => $columns]; + } + + /** + * {@inheritDoc} + */ + protected function applyFrontendFormatting($val = null, $formatter = null) + { + if (null === $formatter) { + return $val; + } + + switch ($formatter) { + case PropertyInterface::TYPE_DATE: + $val = $this->dateTimeFormatter->formatDate($val); + break; + case PropertyInterface::TYPE_DATETIME: + $val = $this->dateTimeFormatter->format($val); + break; + case PropertyInterface::TYPE_TIME: + $val = $this->dateTimeFormatter->formatTime($val); + break; + case PropertyInterface::TYPE_DECIMAL: + $val = $this->numberFormatter->formatDecimal($val); + break; + case PropertyInterface::TYPE_INTEGER: + $val = $this->numberFormatter->formatDecimal($val); + break; + case PropertyInterface::TYPE_PERCENT: + $val = $this->numberFormatter->formatPercent($val); + break; + case PropertyInterface::TYPE_CURRENCY: + $val = is_array($val) ? + $this->numberFormatter->formatCurrency($val[0], $val[1]) : + $this->numberFormatter->formatCurrency($val); + break; + } + + return $val; + } +} diff --git a/src/Marello/Bundle/DataGridBundle/Resources/config/services.yml b/src/Marello/Bundle/DataGridBundle/Resources/config/services.yml index 9ca7fb00c..d0b491e69 100644 --- a/src/Marello/Bundle/DataGridBundle/Resources/config/services.yml +++ b/src/Marello/Bundle/DataGridBundle/Resources/config/services.yml @@ -6,4 +6,15 @@ services: class: 'Marello\Bundle\DataGridBundle\EventListener\Datagrid\RowSelectionSelectAllListener' tags: - { name: kernel.event_listener, event: oro_datagrid.datagrid.build.after, method: onBuildAfter, priority: 250 } - - { name: kernel.event_listener, event: oro_datagrid.orm_datasource.result.after, method: onResultAfter } \ No newline at end of file + - { name: kernel.event_listener, event: oro_datagrid.orm_datasource.result.after, method: onResultAfter } + + marello_datagrid.extension.totals: + class: 'Marello\Bundle\DataGridBundle\Extension\Totals\OrmTotalsExtension' + decorates: oro_datagrid.extension.totals + arguments: + - '@translator' + - '@oro_locale.formatter.number' + - '@oro_locale.formatter.date_time' + - '@oro_security.acl_helper' + tags: + - { name: oro_datagrid.extension } diff --git a/src/Marello/Bundle/DemoDataBundle/Migrations/Data/Demo/ORM/LoadProductData.php b/src/Marello/Bundle/DemoDataBundle/Migrations/Data/Demo/ORM/LoadProductData.php index b6bfa942b..575d87d3f 100644 --- a/src/Marello/Bundle/DemoDataBundle/Migrations/Data/Demo/ORM/LoadProductData.php +++ b/src/Marello/Bundle/DemoDataBundle/Migrations/Data/Demo/ORM/LoadProductData.php @@ -5,8 +5,8 @@ use Doctrine\Common\DataFixtures\AbstractFixture; use Doctrine\Common\DataFixtures\DependentFixtureInterface; use Doctrine\Common\Persistence\ObjectManager; +use Marello\Bundle\ProductBundle\Entity\Builder\ProductFamilyBuilder; use Marello\Bundle\ProductBundle\Entity\Product; -use Marello\Bundle\ProductBundle\Migrations\Data\ORM\LoadDefaultAttributeFamilyData; use Marello\Bundle\SalesBundle\Entity\SalesChannel; use Oro\Bundle\EntityConfigBundle\Attribute\Entity\AttributeFamily; use Oro\Bundle\LocaleBundle\Entity\LocalizedFallbackValue; @@ -127,7 +127,7 @@ private function createProduct(array $data) /** @var AttributeFamily $attributeFamily */ $attributeFamily = $this->manager ->getRepository(AttributeFamily::class) - ->findOneByCode(LoadDefaultAttributeFamilyData::DEFAULT_FAMILY_CODE); + ->findOneByCode(ProductFamilyBuilder::DEFAULT_FAMILY_CODE); $product->setAttributeFamily($attributeFamily); return $product; diff --git a/src/Marello/Bundle/DemoDataBundle/Migrations/Data/Demo/ORM/LoadProductImageData.php b/src/Marello/Bundle/DemoDataBundle/Migrations/Data/Demo/ORM/LoadProductImageData.php index 72ab3ecf7..90b62718c 100644 --- a/src/Marello/Bundle/DemoDataBundle/Migrations/Data/Demo/ORM/LoadProductImageData.php +++ b/src/Marello/Bundle/DemoDataBundle/Migrations/Data/Demo/ORM/LoadProductImageData.php @@ -79,7 +79,7 @@ public function loadProductImages() } /** - * @param $sku + * @param $sku * @return null */ protected function getProductImage($sku) @@ -87,13 +87,15 @@ protected function getProductImage($sku) try { $imagePath = $this->getImagePath($sku); $fileManager = $this->container->get('oro_attachment.file_manager'); - $image = $fileManager->createFileEntity($imagePath); - if ($image) { - $this->manager->persist($image); - $image->setOwner($this->adminUser); - } + if ($imagePath) { + $image = $fileManager->createFileEntity($imagePath); + if ($image) { + $this->manager->persist($image); + $image->setOwner($this->adminUser); + } - return $image; + return $image; + } } catch (\Exception $e) { //image not found } diff --git a/src/Marello/Bundle/FilterBundle/DependencyInjection/MarelloFilterExtension.php b/src/Marello/Bundle/FilterBundle/DependencyInjection/MarelloFilterExtension.php new file mode 100644 index 000000000..34a3ea6b7 --- /dev/null +++ b/src/Marello/Bundle/FilterBundle/DependencyInjection/MarelloFilterExtension.php @@ -0,0 +1,26 @@ +load('services.yml'); + } +} diff --git a/src/Marello/Bundle/FilterBundle/Filter/ChoiceLikeFilter.php b/src/Marello/Bundle/FilterBundle/Filter/ChoiceLikeFilter.php new file mode 100644 index 000000000..4238cd266 --- /dev/null +++ b/src/Marello/Bundle/FilterBundle/Filter/ChoiceLikeFilter.php @@ -0,0 +1,52 @@ +getQueryBuilder(); + $parameter = $qb->getParameter($parameterName); + $value = $parameter->getValue(); + if (is_array($value)) { + $comparisonExpressions = []; + foreach ($value as $key => $valueItem) { + if ($key !== 0) { + $parameterName = sprintf('%s%d', $parameterName, $key); + } + $qb->setParameter($parameterName, '%|' . $valueItem . '|%'); + switch ($comparisonType) { + case ChoiceFilterType::TYPE_NOT_CONTAINS: + $comparisonExpressions[] = $ds->expr()->notLike($fieldName, $parameterName, true); + break; + default: + $comparisonExpressions[] = $ds->expr()->like($fieldName, $parameterName, true); + } + } + + return call_user_func_array([$ds->expr(), 'andX'], $comparisonExpressions); + } else { + switch ($comparisonType) { + case ChoiceFilterType::TYPE_NOT_CONTAINS: + return $ds->expr()->notLike($fieldName, $parameterName, true); + default: + return $ds->expr()->like($fieldName, $parameterName, true); + } + } + } +} diff --git a/src/Marello/Bundle/FilterBundle/Resources/config/services.yml b/src/Marello/Bundle/FilterBundle/Resources/config/services.yml new file mode 100644 index 000000000..74f91ae18 --- /dev/null +++ b/src/Marello/Bundle/FilterBundle/Resources/config/services.yml @@ -0,0 +1,9 @@ +services: + marello_filter.choice_like_filter: + class: Marello\Bundle\FilterBundle\Filter\ChoiceLikeFilter + public: false + arguments: + - '@form.factory' + - '@oro_filter.filter_utility' + tags: + - { name: oro_filter.extension.orm_filter.filter, type: choice_like } diff --git a/src/Marello/Bundle/InventoryBundle/Controller/InventoryLevelController.php b/src/Marello/Bundle/InventoryBundle/Controller/InventoryLevelController.php index e9c4c3428..7b08946c7 100644 --- a/src/Marello/Bundle/InventoryBundle/Controller/InventoryLevelController.php +++ b/src/Marello/Bundle/InventoryBundle/Controller/InventoryLevelController.php @@ -115,4 +115,23 @@ public function manageBatchesAction(InventoryLevel $inventoryLevel, Request $req $request ); } + + /** + * @Route( + * path="/manage-batches/view/{id}", + * requirements={"id"="\d+"}, + * name="marello_inventory_inventorylevel_batches_view" + * ) + * @Template("MarelloInventoryBundle:InventoryLevel:batchesView.html.twig") + * + * @param InventoryLevel $inventoryLevel + * + * @return array + */ + public function viewAction(InventoryLevel $inventoryLevel) + { + return [ + 'entity' => $inventoryLevel + ]; + } } diff --git a/src/Marello/Bundle/InventoryBundle/Entity/InventoryBatch.php b/src/Marello/Bundle/InventoryBundle/Entity/InventoryBatch.php index 3968d7f2c..dccf9f59c 100644 --- a/src/Marello/Bundle/InventoryBundle/Entity/InventoryBatch.php +++ b/src/Marello/Bundle/InventoryBundle/Entity/InventoryBatch.php @@ -14,9 +14,6 @@ /** * @ORM\Entity() * @Oro\Config( - * routeView="marello_inventory_batch_view", - * routeName="marello_inventory_batch_index", - * routeCreate="marello_inventory_batch_create", * defaultValues={ * "entity"={ * "icon"="fa-cubes" diff --git a/src/Marello/Bundle/InventoryBundle/Entity/InventoryLevelLogRecord.php b/src/Marello/Bundle/InventoryBundle/Entity/InventoryLevelLogRecord.php index da464135b..a710028a8 100644 --- a/src/Marello/Bundle/InventoryBundle/Entity/InventoryLevelLogRecord.php +++ b/src/Marello/Bundle/InventoryBundle/Entity/InventoryLevelLogRecord.php @@ -38,7 +38,7 @@ class InventoryLevelLogRecord /** * @ORM\ManyToOne(targetEntity="Marello\Bundle\InventoryBundle\Entity\InventoryLevel") - * @ORM\JoinColumn(name="inventory_level_id", referencedColumnName="id") + * @ORM\JoinColumn(name="inventory_level_id", referencedColumnName="id", onDelete="SET NULL") * @Oro\ConfigField( * defaultValues={ * "entity"={ @@ -57,7 +57,7 @@ class InventoryLevelLogRecord /** * @ORM\ManyToOne(targetEntity="Marello\Bundle\InventoryBundle\Entity\InventoryItem", * cascade={"persist", "remove"}) - * @ORM\JoinColumn(name="inventory_item_id", referencedColumnName="id", onDelete="CASCADE") + * @ORM\JoinColumn(name="inventory_item_id", referencedColumnName="id", onDelete="CASCADE", nullable=false) * @Oro\ConfigField( * defaultValues={ * "entity"={ diff --git a/src/Marello/Bundle/InventoryBundle/EventListener/Datagrid/InventoryLevelGridListener.php b/src/Marello/Bundle/InventoryBundle/EventListener/Datagrid/InventoryLevelGridListener.php new file mode 100644 index 000000000..36c4b6c13 --- /dev/null +++ b/src/Marello/Bundle/InventoryBundle/EventListener/Datagrid/InventoryLevelGridListener.php @@ -0,0 +1,68 @@ +doctrineHelper = $helper; + } + + /** + * @param BuildBefore $event + */ + public function onBuildBefore(BuildBefore $event) + { + $inventoryItemId = $this->getParameter($event->getDatagrid(), 'inventoryItemId'); + /** @var InventoryItem $inventoryItem */ + $inventoryItem = $this->doctrineHelper + ->getEntityRepositoryForClass(InventoryItem::class) + ->find($inventoryItemId); + if ($inventoryItem->isEnableBatchInventory()) { + $config = $event->getConfig(); + $columns = $config->offsetGetByPath('[columns]'); + $columns = array_merge( + $columns, + [ + 'manageBatches' => [ + 'label' => 'marello.inventory.inventorylevel.grid.batches.label', + 'type' => 'twig', + 'frontend_type' => 'html', + 'template' => 'MarelloInventoryBundle:Inventory/Datagrid:manageBatches.html.twig', + ] + ] + ); + $config->offsetSetByPath('[columns]', $columns); + } + } + + /** + * @param DatagridInterface $datagrid + * @param string $parameterName + * @return mixed + */ + protected function getParameter(DatagridInterface $datagrid, $parameterName) + { + $value = $datagrid->getParameters()->get($parameterName); + + if ($value === null) { + throw new \LogicException(sprintf('Parameter "%s" must be set', $parameterName)); + } + + return $value; + } +} diff --git a/src/Marello/Bundle/InventoryBundle/Form/Type/InventoryBatchType.php b/src/Marello/Bundle/InventoryBundle/Form/Type/InventoryBatchType.php index 8e3419cc0..c98608e50 100644 --- a/src/Marello/Bundle/InventoryBundle/Form/Type/InventoryBatchType.php +++ b/src/Marello/Bundle/InventoryBundle/Form/Type/InventoryBatchType.php @@ -76,6 +76,13 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'disabled' => true ] ) + ->add( + 'deliveryDate', + OroDateType::class, + [ + 'required' => false + ] + ) ->add( 'purchasePrice', NumberType::class, diff --git a/src/Marello/Bundle/InventoryBundle/ImportExport/Strategy/InventoryLevelUpdateStrategy.php b/src/Marello/Bundle/InventoryBundle/ImportExport/Strategy/InventoryLevelUpdateStrategy.php index e440ea43d..c09621acc 100644 --- a/src/Marello/Bundle/InventoryBundle/ImportExport/Strategy/InventoryLevelUpdateStrategy.php +++ b/src/Marello/Bundle/InventoryBundle/ImportExport/Strategy/InventoryLevelUpdateStrategy.php @@ -253,7 +253,13 @@ protected function findInventoryBatch(InventoryBatch $entity) protected function getProduct($entity) { return $this->databaseHelper - ->findOneBy(Product::class, ['sku' => $entity->getInventoryItem()->getProduct()->getSku()]); + ->findOneBy( + Product::class, + [ + 'sku' => $entity->getInventoryItem()->getProduct()->getSku(), + 'organization' => $entity->getOrganization() + ] + ); } /** diff --git a/src/Marello/Bundle/InventoryBundle/Migrations/Schema/MarelloInventoryBundleInstaller.php b/src/Marello/Bundle/InventoryBundle/Migrations/Schema/MarelloInventoryBundleInstaller.php index 554d7b846..818dbce7e 100644 --- a/src/Marello/Bundle/InventoryBundle/Migrations/Schema/MarelloInventoryBundleInstaller.php +++ b/src/Marello/Bundle/InventoryBundle/Migrations/Schema/MarelloInventoryBundleInstaller.php @@ -178,6 +178,7 @@ protected function createMarelloInventoryInventoryLogLevelTable(Schema $schema) $table->addColumn('warehouse_name', 'string', ['notnull' => true, 'length' => 255]); $table->setPrimaryKey(['id']); $table->addIndex(['inventory_item_id']); + $table->addIndex(['inventory_level_id']); $table->addIndex(['user_id'], 'IDX_32D13BA4F675F31B', []); } @@ -374,6 +375,12 @@ protected function addMarelloInventoryInventoryLevelLogForeignKeys(Schema $schem ['id'], ['onDelete' => 'CASCADE', 'onUpdate' => null] ); + $table->addForeignKeyConstraint( + $schema->getTable('marello_inventory_level'), + ['inventory_level_id'], + ['id'], + ['onDelete' => 'SET NULL', 'onUpdate' => null] + ); $table->addForeignKeyConstraint( $schema->getTable('oro_user'), ['user_id'], diff --git a/src/Marello/Bundle/InventoryBundle/Migrations/Schema/v2_5/UpdateInventoryLevelLogForeignKey.php b/src/Marello/Bundle/InventoryBundle/Migrations/Schema/v2_5/UpdateInventoryLevelLogForeignKey.php new file mode 100644 index 000000000..e74871fc2 --- /dev/null +++ b/src/Marello/Bundle/InventoryBundle/Migrations/Schema/v2_5/UpdateInventoryLevelLogForeignKey.php @@ -0,0 +1,41 @@ +updateInventoryLevelLogForeignKeyConstraint($schema, $queries); + } + + /** + * {@inheritdoc} + * @param Schema $schema + * @param QueryBag $queries + * @throws \Doctrine\DBAL\Schema\SchemaException + */ + protected function updateInventoryLevelLogForeignKeyConstraint(Schema $schema, $queries) + { + $table = $schema->getTable(self::INVENTORY_LEVEL_LOG_TABLE_NAME); + $table->addIndex(['inventory_level_id']); + $table->addForeignKeyConstraint( + $schema->getTable(self::INVENTORY_LEVEL_TABLE_NAME), + ['inventory_level_id'], + ['id'], + ['onDelete' => 'SET NULL', 'onUpdate' => null] + ); + } +} diff --git a/src/Marello/Bundle/InventoryBundle/Resources/config/eventlistener.yml b/src/Marello/Bundle/InventoryBundle/Resources/config/eventlistener.yml index 494fbd959..81f28de56 100644 --- a/src/Marello/Bundle/InventoryBundle/Resources/config/eventlistener.yml +++ b/src/Marello/Bundle/InventoryBundle/Resources/config/eventlistener.yml @@ -99,3 +99,10 @@ services: - { name: doctrine.orm.entity_listener, entity: 'Marello\Bundle\InventoryBundle\Entity\InventoryItem', event: postPersist } - { name: doctrine.orm.entity_listener, entity: 'Marello\Bundle\InventoryBundle\Entity\InventoryItem', event: preUpdate } - { name: doctrine.event_listener, event: postFlush } + + marello_inventory.event_listener.datagrid.inventory_level_grid: + class: 'Marello\Bundle\InventoryBundle\EventListener\Datagrid\InventoryLevelGridListener' + arguments: + - '@oro_entity.doctrine_helper' + tags: + - { name: kernel.event_listener, event: oro_datagrid.datagrid.build.before.marello-inventory-levels, method: onBuildBefore } \ No newline at end of file diff --git a/src/Marello/Bundle/InventoryBundle/Resources/config/oro/datagrids.yml b/src/Marello/Bundle/InventoryBundle/Resources/config/oro/datagrids.yml index 89595beae..50548077f 100644 --- a/src/Marello/Bundle/InventoryBundle/Resources/config/oro/datagrids.yml +++ b/src/Marello/Bundle/InventoryBundle/Resources/config/oro/datagrids.yml @@ -6,7 +6,6 @@ datagrids: query: select: - i.id - - p.denormalizedDefaultName as productName - p.sku as productSku - i.enableBatchInventory as enableBatchInventory - pu.name as productUnit @@ -30,8 +29,6 @@ datagrids: template: MarelloProductBundle:Product/Datagrid:productSku.html.twig productName: label: marello.product.names.label - frontend_type: string - data_name: productName productUnit: label: marello.inventory.inventoryitem.product_unit.label frontend_type: string @@ -55,7 +52,7 @@ datagrids: sorters: columns: productSku: { data_name: p.sku } - productName: { data_name: p.denormalizedDefaultName } + productName: { data_name: productName } productUnit: { data_name: productUnit } enableBatchInventory: { data_name: enableBatchInventory } inventoryQty: { data_name: inventoryQty } @@ -70,7 +67,7 @@ datagrids: data_name: p.sku productName: type: string - data_name: p.denormalizedDefaultName + data_name: productName productUnit: type: enum data_name: productUnit @@ -92,6 +89,9 @@ datagrids: filter_by_having: true properties: id: ~ + productName: + type: localized_value + data_name: p.names inventory_view_link: type: url route: marello_inventory_inventory_view @@ -211,6 +211,7 @@ datagrids: - il.updatedAt - wht.label as warehouseTypeLabel - wh.label as warehouse + - wh.code as warehouseCode - COALESCE(il.inventory, 0) AS inventoryQty - COALESCE(il.allocatedInventory, 0) AS allocatedInventoryQty - COALESCE(il.inventory - il.allocatedInventory, 0) AS virtualInventoryQty @@ -223,19 +224,23 @@ datagrids: where: and: - IDENTITY(il.inventoryItem) = :inventoryItemId - groupBy: il.id, wh.label, wht.label + groupBy: il.id, wh.code, wh.label, wht.label bind_parameters: inventoryItemId: inventoryItemId columns: warehouse: label: marello.inventory.inventorylevel.warehouse.label frontend_type: string + warehouseCode: + label: marello.inventory.inventorylevel.grid.warehouse_code.label + frontend_type: string pickLocation: label: marello.inventory.inventorylevel.pick_location.label frontend_type: string warehouseTypeLabel: label: marello.inventory.warehousetype.entity_label frontend_type: string + renderable: false inventoryQty: label: marello.inventory.inventorylevel.inventory.label frontend_type: number @@ -248,9 +253,18 @@ datagrids: label: marello.inventory.inventorylevel.virtual_inventory.label frontend_type: number data_name: virtualInventoryQty - updatedAt: - label: oro.ui.updated_at - frontend_type: datetime + filters: + columns: + warehouse: + type: string + data_name: warehouse + warehouseCode: + type: string + data_name: warehouseCode + warehouseTypeLabel: + type: string + data_name: warehouseTypeLabel + enabled: false marello-balanced-inventory-levels-grid: extended_entity_name: Marello\Bundle\InventoryBundle\Entity\BalancedInventoryLevel @@ -259,7 +273,6 @@ datagrids: query: select: - balancedInventoryLevel - - p.denormalizedDefaultName as productName - p.sku as productSku - scg.name as salesChannelGroupName from: @@ -277,8 +290,6 @@ datagrids: template: MarelloProductBundle:Product/Datagrid:productSku.html.twig productName: label: marello.product.names.label - frontend_type: string - data_name: productName inventoryQty: label: marello.inventory.balancedinventorylevel.inventory.label frontend_type: integer @@ -346,3 +357,50 @@ datagrids: data_name: balancedInventoryLevel.reservedInventory default: productName: 'DESC' + properties: + productName: + type: localized_value + data_name: p.names + + marello-inventory-batches: + extended_entity_name: Marello\Bundle\InventoryBundle\Entity\InventoryBatch + source: + type: orm + query: + select: + - ib + from: + - { table: MarelloInventoryBundle:InventoryBatch, alias: ib } + where: + and: + - IDENTITY(ib.inventoryLevel) = :inventoryLevelId + bind_parameters: + inventoryLevelId: inventoryLevelId + columns: + batchNumber: + label: marello.inventory.inventorybatch.batch_number.label + frontend_type: string + data_name: batchNumber + quantity: + label: marello.inventory.inventorybatch.quantity.label + frontend_type: integer + data_name: quantity + receivedDate: + label: marello.inventory.inventorybatch.date_received.label + frontend_type: datetime + data_name: deliveryDate + expirationDate: + label: marello.inventory.inventorybatch.expiration_date.label + frontend_type: datetime + data_name: expirationDate + purchasePrice: + label: marello.inventory.inventorybatch.purchase_price.label + frontend_type: currency + data_name: purchasePrice + options: + export: false + mass_actions: ~ + toolbarOptions: + hide: true + pagination: + hide: true \ No newline at end of file diff --git a/src/Marello/Bundle/InventoryBundle/Resources/public/css/scss/main.scss b/src/Marello/Bundle/InventoryBundle/Resources/public/css/scss/main.scss index 0f2612614..0c0477af9 100644 --- a/src/Marello/Bundle/InventoryBundle/Resources/public/css/scss/main.scss +++ b/src/Marello/Bundle/InventoryBundle/Resources/public/css/scss/main.scss @@ -16,7 +16,7 @@ .inventorylevel-warehouse { .select2-container { - width: 190px; + width: 300px; .select2-choice { .select2-arrow { @@ -30,7 +30,7 @@ } } -.inventorylevel-adjustment { +.inventorylevel-adjustment, .inventorybatch-adjustment { .selector { width: 100px !important; @@ -48,6 +48,12 @@ } } +.inventorybatch-delivery-date, .inventorybatch-purchase-price, .inventorybatch-expiration-date { + input[type=text] { + width: 100px !important; + } +} + // Font Awesome .fa-caret-down:before { content: "\f0d7"; diff --git a/src/Marello/Bundle/InventoryBundle/Resources/translations/messages.en.yml b/src/Marello/Bundle/InventoryBundle/Resources/translations/messages.en.yml index cdf44347d..0eebca7b5 100644 --- a/src/Marello/Bundle/InventoryBundle/Resources/translations/messages.en.yml +++ b/src/Marello/Bundle/InventoryBundle/Resources/translations/messages.en.yml @@ -108,6 +108,11 @@ marello: pick_location.label: Pick Location inventory_batches.label: Inventory Batches + grid: + warehouse_code.label: Warehouse Code + batches.label: Batches + view_batches.label: View Batches + form: manage_batches.label: Manage Batches @@ -120,11 +125,12 @@ marello: batch_reference.label: Batch Reference purchase_reference.label: Purchase Reference quantity.label: Quantity - delivery_date.label: Delivery Date + date_received.label: Date Received expiration_date.label: Expiration Date purchase_price.label: Purchase Price total_price.label: Total Price organization.label: Organization + delivery_date.label: Delivery Date inventorylevellogrecord: id.label: Id diff --git a/src/Marello/Bundle/InventoryBundle/Resources/views/Form/fields.html.twig b/src/Marello/Bundle/InventoryBundle/Resources/views/Form/fields.html.twig index 47124c3be..613f4e6d7 100644 --- a/src/Marello/Bundle/InventoryBundle/Resources/views/Form/fields.html.twig +++ b/src/Marello/Bundle/InventoryBundle/Resources/views/Form/fields.html.twig @@ -108,7 +108,7 @@ -
+
@@ -118,14 +118,20 @@ {{ form_errors(form.adjustmentQuantity) }}
- -
+ +
+ {{ form_widget(form.deliveryDate) }} +
+ {{ form_errors(form.deliveryDate) }} + + +
{{ form_widget(form.purchasePrice) }}
{{ form_errors(form.purchasePrice) }} - -
+ +
{{ form_widget(form.expirationDate) }}
{{ form_errors(form.expirationDate) }} @@ -172,6 +178,7 @@ {{ 'marello.inventory.inventorybatch.batch_number.label'|trans }} {{ 'marello.inventory.inventorybatch.quantity.label'|trans }} {{ 'marello.inventory.model.warehouse.adjustment.label'|trans }} + {{ 'marello.inventory.inventorybatch.date_received.label'|trans }} {{ 'marello.inventory.inventorybatch.purchase_price.label'|trans }} {{ 'marello.inventory.inventorybatch.expiration_date.label'|trans }} diff --git a/src/Marello/Bundle/InventoryBundle/Resources/views/Inventory/Datagrid/manageBatches.html.twig b/src/Marello/Bundle/InventoryBundle/Resources/views/Inventory/Datagrid/manageBatches.html.twig new file mode 100644 index 000000000..06e005d81 --- /dev/null +++ b/src/Marello/Bundle/InventoryBundle/Resources/views/Inventory/Datagrid/manageBatches.html.twig @@ -0,0 +1,5 @@ + diff --git a/src/Marello/Bundle/InventoryBundle/Resources/views/InventoryLevel/batchesView.html.twig b/src/Marello/Bundle/InventoryBundle/Resources/views/InventoryLevel/batchesView.html.twig new file mode 100644 index 000000000..541749a3f --- /dev/null +++ b/src/Marello/Bundle/InventoryBundle/Resources/views/InventoryLevel/batchesView.html.twig @@ -0,0 +1,85 @@ +{% extends 'OroUIBundle:actions:view.html.twig' %} +{% import 'OroUIBundle::macros.html.twig' as UI %} +{% import 'OroDataGridBundle::macros.html.twig' as dataGrid %} + +{% block navButtons %} + {{ UI.cancelButton(path('marello_inventory_inventory_view', { 'id': entity.inventoryItem.id }), 'Back'|trans) }} + {% if is_granted('EDIT', entity) %} + {{ UI.editButton({ + 'path' : path('marello_inventory_inventorylevel_manage_batches', { id: entity.id }), + 'entity_label': 'marello.inventory.inventorybatch.entity_label'|trans + }) }} + {% endif %} +{% endblock navButtons %} + +{% block pageHeader %} + {% set breadcrumbs = { + 'entity': form.vars.value, + 'indexPath': path('marello_inventory_inventory_index'), + 'indexLabel': 'marello.inventory.label'|trans, + 'entityTitle': 'marello.inventory.inventorybatch.entity_plural_label'|trans, + 'additional': [{ + 'indexPath': path('marello_inventory_inventory_view', {'id': entity.inventoryItem.id}), + 'indexLabel': entity.inventoryItem.product.sku + }] + } %} + {{ parent() }} +{% endblock pageHeader %} + +{% block content_data %} + {% set id = 'marello-inventory-batches-view' %} + {% set generalSubblocks = [] %} + + {% set productInformationWidget %} +
+
+
+
+ {{ oro_widget_render({ + 'widgetType': 'block', + 'url': path('marello_inventory_widget_info', {id: entity.inventoryItem.id}), + 'title': 'marello.product.product_information'|trans + }) }} +
+
+
+
+ {% endset %} + {% set generalSubblocks = generalSubblocks|merge([{'data' : [productInformationWidget] }]) %} + + {% set inventoryLevelInformationWidget %} +
+
+
+ {{ 'marello.inventory.information.label'|trans }} +
+ {{ UI.renderProperty('marello.inventory.inventorylevel.warehouse.label'|trans, entity.warehouse.label) }} + {{ UI.renderProperty('marello.inventory.inventorylevel.pick_location.label'|trans, entity.picklocation) }} + {{ UI.renderProperty('marello.inventory.inventorylevel.inventory.label'|trans, entity.inventoryQty) }} +
+
+ {% endset %} + {% set generalSubblocks = generalSubblocks|merge([{'data' : [inventoryLevelInformationWidget]}]) %} + + {% set dataBlocks = [ + { + 'title': 'General Information'|trans, + 'class': 'active', + 'subblocks': generalSubblocks + } + ] %} + + {% set dataBlocks = dataBlocks|merge([{ + 'title' : 'marello.inventory.inventorybatch.entity_plural_label'|trans, + 'subblocks': [{ + 'title' : null, + 'data' : [ + dataGrid.renderGrid('marello-inventory-batches', {'inventoryLevelId': entity.id}) + ] + }] + }]) + %} + + {% set data = { 'dataBlocks': dataBlocks } %} + {{ parent() }} +{% endblock content_data %} diff --git a/src/Marello/Bundle/InventoryBundle/Resources/views/InventoryLevel/manageBatches.html.twig b/src/Marello/Bundle/InventoryBundle/Resources/views/InventoryLevel/manageBatches.html.twig index f7afc52be..d61285fe2 100644 --- a/src/Marello/Bundle/InventoryBundle/Resources/views/InventoryLevel/manageBatches.html.twig +++ b/src/Marello/Bundle/InventoryBundle/Resources/views/InventoryLevel/manageBatches.html.twig @@ -9,8 +9,8 @@ {% if entity.id and is_granted('marello_inventory_inventory_update') %} {% set html = '' %} {% set html = UI.saveAndCloseButton({ - 'route': 'marello_inventory_inventory_update', - 'params': {'id': entity.inventoryItem.id} + 'route': 'marello_inventory_inventorylevel_batches_view', + 'params': {'id': entity.id} }) %} {% set html = html ~ UI.saveAndStayButton({ 'route': 'marello_inventory_inventorylevel_manage_batches', @@ -26,10 +26,10 @@ 'entity': form.vars.value, 'indexPath': path('marello_inventory_inventory_index'), 'indexLabel': 'marello.inventory.label'|trans, - 'entityTitle': 'marello.inventory.inventorybatch.entity_plural_label'|trans ~ ' - ' ~ entity.inventoryItem.product.sku, + 'entityTitle': 'marello.inventory.inventorybatch.entity_plural_label'|trans, 'additional': [{ 'indexPath': path('marello_inventory_inventory_update', {'id': entity.inventoryItem.id}), - 'indexLabel': 'marello.inventory.inventorylevel.entity_plural_label'|trans, + 'indexLabel': entity.inventoryItem.product.sku }] } %} {{ parent() }} @@ -55,15 +55,6 @@ {% endset %} {% set generalSubblocks = generalSubblocks|merge([{'data' : [productInformationWidget] }]) %} - {% set totalsWidget %} -
-
- {% placeholder marello_inventory_levels_totals with {'entity' : entity.inventoryItem} %} -
-
- {% endset %} - {% set generalSubblocks = generalSubblocks|merge([{'data' : [totalsWidget] }]) %} - {% set inventoryLevelInformationWidget %}
@@ -72,6 +63,7 @@
{{ UI.renderProperty('marello.inventory.inventorylevel.warehouse.label'|trans, entity.warehouse.label) }} {{ UI.renderProperty('marello.inventory.inventorylevel.pick_location.label'|trans, entity.picklocation) }} + {{ UI.renderProperty('marello.inventory.inventorylevel.inventory.label'|trans, entity.inventoryQty) }}
{% endset %} diff --git a/src/Marello/Bundle/InventoryBundle/Tests/Functional/Controller/InventoryControllerTest.php b/src/Marello/Bundle/InventoryBundle/Tests/Functional/Controller/InventoryControllerTest.php index 7a42ef1d5..7bb70b357 100644 --- a/src/Marello/Bundle/InventoryBundle/Tests/Functional/Controller/InventoryControllerTest.php +++ b/src/Marello/Bundle/InventoryBundle/Tests/Functional/Controller/InventoryControllerTest.php @@ -14,6 +14,10 @@ use Marello\Bundle\InventoryBundle\Tests\Functional\DataFixtures\LoadInventoryData; use Marello\Bundle\PricingBundle\Tests\Functional\DataFixtures\LoadProductChannelPricingData; +/** + * @dbIsolationPerTest + * @nestTransactionsWithSavepoints + */ class InventoryControllerTest extends WebTestCase { /** diff --git a/src/Marello/Bundle/InvoiceBundle/Entity/AbstractInvoice.php b/src/Marello/Bundle/InvoiceBundle/Entity/AbstractInvoice.php index 02883a604..e9b3dfdcc 100644 --- a/src/Marello/Bundle/InvoiceBundle/Entity/AbstractInvoice.php +++ b/src/Marello/Bundle/InvoiceBundle/Entity/AbstractInvoice.php @@ -6,6 +6,7 @@ use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; +use Marello\Bundle\PaymentBundle\Entity\Payment; use Oro\Bundle\AddressBundle\Entity\AbstractAddress; use Oro\Bundle\EntityConfigBundle\Metadata\Annotation as Oro; use Oro\Bundle\OrganizationBundle\Entity\OrganizationAwareInterface; @@ -23,7 +24,7 @@ use Marello\Bundle\SalesBundle\Model\SalesChannelAwareInterface; /** - * @ORM\Entity + * @ORM\Entity(repositoryClass="Marello\Bundle\InvoiceBundle\Entity\Repository\AbstractInvoiceRepository") * @ORM\InheritanceType("SINGLE_TABLE") * @ORM\DiscriminatorColumn(name="type", type="string") * @ORM\DiscriminatorMap({"invoice" = "Invoice", "creditmemo" = "Creditmemo"}) @@ -172,33 +173,6 @@ abstract class AbstractInvoice implements */ protected $paymentMethod; - /** - * @var string - * @ORM\Column(name="payment_reference", type="string", length=255, nullable=true) - * @Oro\ConfigField( - * defaultValues={ - * "dataaudit"={ - * "auditable"=true - * } - * } - * ) - */ - protected $paymentReference; - - /** - * @var string - * - * @ORM\Column(name="payment_details", type="text", nullable=true) - * @Oro\ConfigField( - * defaultValues={ - * "dataaudit"={ - * "auditable"=true - * } - * } - * ) - */ - protected $paymentDetails; - /** * @var string * @@ -302,6 +276,30 @@ abstract class AbstractInvoice implements */ protected $items; + /** + * @var Collection|Payment[] + * + * @ORM\ManyToMany(targetEntity="Marello\Bundle\PaymentBundle\Entity\Payment", cascade={"persist"}) + * @ORM\JoinTable(name="marello_invoice_payments", + * joinColumns={@ORM\JoinColumn(name="invoice_id", referencedColumnName="id", onDelete="CASCADE")}, + * inverseJoinColumns={ + * @ORM\JoinColumn(name="payment_id", referencedColumnName="id", unique=true, onDelete="CASCADE") + * } + * ) + * @ORM\OrderBy({"id" = "ASC"}) + * @Oro\ConfigField( + * defaultValues={ + * "email"={ + * "available_in_template"=true + * }, + * "dataaudit"={ + * "auditable"=true + * } + * } + * ) + */ + protected $payments; + /** * @var int * @@ -372,6 +370,34 @@ abstract class AbstractInvoice implements */ protected $shippingAmountExclTax; + /** + * @var int + * + * @ORM\Column(name="total_due", type="money", nullable=true) + * @Oro\ConfigField( + * defaultValues={ + * "dataaudit"={ + * "auditable"=true + * } + * } + * ) + */ + protected $totalDue = 0; + + /** + * @var int + * + * @ORM\Column(name="total_paid", type="money", nullable=true) + * @Oro\ConfigField( + * defaultValues={ + * "dataaudit"={ + * "auditable"=true + * } + * } + * ) + */ + protected $totalPaid = 0; + /** * @param AbstractAddress|null $billingAddress * @param AbstractAddress|null $shippingAddress @@ -381,6 +407,7 @@ public function __construct( AbstractAddress $shippingAddress = null ) { $this->items = new ArrayCollection(); + $this->payments = new ArrayCollection(); $this->billingAddress = $billingAddress; $this->shippingAddress = $shippingAddress; } @@ -526,44 +553,6 @@ public function setPaymentMethod($paymentMethod) return $this; } - /** - * @return string - */ - public function getPaymentReference() - { - return $this->paymentReference; - } - - /** - * @param string $paymentReference - * @return AbstractInvoice - */ - public function setPaymentReference($paymentReference) - { - $this->paymentReference = $paymentReference; - - return $this; - } - - /** - * @return string - */ - public function getPaymentDetails() - { - return $this->paymentDetails; - } - - /** - * @param string $paymentDetails - * @return AbstractInvoice - */ - public function setPaymentDetails($paymentDetails) - { - $this->paymentDetails = $paymentDetails; - - return $this; - } - /** * @return string */ @@ -734,6 +723,52 @@ public function removeItem(AbstractInvoiceItem $item) return $this; } + /** + * @return Collection|Payment[] + */ + public function getPayments() + { + return $this->payments; + } + + /** + * @param Payment $payment + * + * @return $this + */ + public function addPayment(Payment $payment) + { + if (!$this->payments->contains($payment)) { + $this->payments->add($payment); + $totalPaid = $this->getTotalPaid() ? : 0; + $grandTotal = $this->getGrandTotal() ? : 0; + + $this->setTotalPaid($payment->getTotalPaid() + $totalPaid); + $this->setTotalDue($grandTotal - $this->getTotalPaid()); + } + + return $this; + } + + /** + * @param Payment $payment + * + * @return $this + */ + public function removePayment(Payment $payment) + { + if ($this->payments->contains($payment)) { + $this->payments->removeElement($payment); + $totalPaid = $this->getTotalPaid() ? : 0; + $grandTotal = $this->getGrandTotal() ? : 0; + + $this->setTotalPaid($totalPaid - $payment->getTotalPaid()); + $this->setTotalDue($grandTotal - $this->getTotalPaid()); + } + + return $this; + } + /** * @return int */ @@ -839,6 +874,44 @@ public function setDerivedProperty($id) } } + /** + * @return float + */ + public function getTotalDue() + { + return $this->totalDue; + } + + /** + * @param float $totalDue + * @return $this + */ + public function setTotalDue($totalDue) + { + $this->totalDue = $totalDue; + + return $this; + } + + /** + * @return float + */ + public function getTotalPaid() + { + return $this->totalPaid; + } + + /** + * @param float $totalPaid + * @return $this + */ + public function setTotalPaid($totalPaid) + { + $this->totalPaid = $totalPaid; + + return $this; + } + /** * @return string */ diff --git a/src/Marello/Bundle/InvoiceBundle/Entity/Repository/AbstractInvoiceRepository.php b/src/Marello/Bundle/InvoiceBundle/Entity/Repository/AbstractInvoiceRepository.php new file mode 100644 index 000000000..1e0a25123 --- /dev/null +++ b/src/Marello/Bundle/InvoiceBundle/Entity/Repository/AbstractInvoiceRepository.php @@ -0,0 +1,24 @@ +createQueryBuilder('i'); + $qb + ->where( + $qb->expr()->isMemberOf(':payment', 'i.payments') + ) + ->setParameter('payment', $payment->getId()); + + return $qb->getQuery()->getOneOrNullResult(); + } +} diff --git a/src/Marello/Bundle/InvoiceBundle/Form/Type/InvoiceSelectType.php b/src/Marello/Bundle/InvoiceBundle/Form/Type/InvoiceSelectType.php new file mode 100644 index 000000000..5b8748d2a --- /dev/null +++ b/src/Marello/Bundle/InvoiceBundle/Form/Type/InvoiceSelectType.php @@ -0,0 +1,33 @@ +setDefaults([ + 'class' => AbstractInvoice::class, + 'choice_label' => function (AbstractInvoice $invoice) { + return sprintf('%s: %s', $invoice->getInvoiceType(), $invoice->getInvoiceNumber()); + }, + ]); + } + + public function getParent() + { + return EntityType::class; + } + + public function getBlockPrefix() + { + return self::BLOCK_PREFIX; + } +} diff --git a/src/Marello/Bundle/InvoiceBundle/Migrations/Schema/MarelloInvoiceBundleInstaller.php b/src/Marello/Bundle/InvoiceBundle/Migrations/Schema/MarelloInvoiceBundleInstaller.php index 3791ebb6b..f769f9384 100644 --- a/src/Marello/Bundle/InvoiceBundle/Migrations/Schema/MarelloInvoiceBundleInstaller.php +++ b/src/Marello/Bundle/InvoiceBundle/Migrations/Schema/MarelloInvoiceBundleInstaller.php @@ -29,10 +29,12 @@ public function up(Schema $schema, QueryBag $queries) /** Tables generation **/ $this->createMarelloInvoiceInvoiceTable($schema); $this->createMarelloInvoiceInvoiceItemTable($schema); + $this->createMarelloInvoicePaymentsTable($schema); /** Foreign keys generation **/ $this->addMarelloInvoiceInvoiceForeignKeys($schema); $this->addMarelloInvoiceInvoiceItemForeignKeys($schema); + $this->addMarelloInvoicePaymentsForeignKeys($schema); } /** @@ -51,8 +53,6 @@ protected function createMarelloInvoiceInvoiceTable(Schema $schema) $table->addColumn('invoiced_at', 'datetime', ['notnull' => false]); $table->addColumn('invoice_due_date', 'datetime', ['notnull' => false]); $table->addColumn('payment_method', 'string', ['notnull' => false, 'length' => 255]); - $table->addColumn('payment_reference', 'string', ['notnull' => false, 'length' => 255]); - $table->addColumn('payment_details', 'text', ['notnull' => false]); $table->addColumn('shipping_method', 'string', ['notnull' => false, 'length' => 255]); $table->addColumn('shipping_method_type', 'string', ['notnull' => false, 'length' => 255]); $table->addColumn('order_id', 'integer', ['notnull' => true]); @@ -66,6 +66,8 @@ protected function createMarelloInvoiceInvoiceTable(Schema $schema) $table->addColumn('subtotal', 'money', ['precision' => 19, 'scale' => 4, 'comment' => '(DC2Type:money)']); $table->addColumn('total_tax', 'money', ['precision' => 19, 'scale' => 4, 'comment' => '(DC2Type:money)']); $table->addColumn('grand_total', 'money', ['precision' => 19, 'scale' => 4, 'comment' => '(DC2Type:money)']); + $table->addColumn('total_due', 'money', ['notnull' => false, 'precision' => 19, 'scale' => 4, 'comment' => '(DC2Type:money)']); + $table->addColumn('total_paid', 'money', ['notnull' => false, 'precision' => 19, 'scale' => 4, 'comment' => '(DC2Type:money)']); $table->addColumn( 'shipping_amount_incl_tax', 'money', @@ -139,7 +141,21 @@ protected function createMarelloInvoiceInvoiceItemTable(Schema $schema) $table->setPrimaryKey(['id']); } - + + /** + * Create marello_invoice_invoice_item table + * + * @param Schema $schema + */ + protected function createMarelloInvoicePaymentsTable(Schema $schema) + { + $table = $schema->createTable('marello_invoice_payments'); + $table->addColumn('invoice_id', 'integer', ['notnull' => true]); + $table->addColumn('payment_id', 'integer', ['notnull' => true]); + $table->addUniqueIndex(['payment_id'], null); + $table->setPrimaryKey(['invoice_id', 'payment_id']); + } + /** * Add marello_invoice_invoice foreign keys. * @@ -219,4 +235,24 @@ protected function addMarelloInvoiceInvoiceItemForeignKeys(Schema $schema) ['onDelete' => 'SET NULL', 'onUpdate' => null] ); } + + /** + * @param Schema $schema + */ + protected function addMarelloInvoicePaymentsForeignKeys(Schema $schema) + { + $table = $schema->getTable('marello_invoice_payments'); + $table->addForeignKeyConstraint( + $schema->getTable('marello_invoice_invoice'), + ['invoice_id'], + ['id'], + ['onDelete' => 'CASCADE', 'onUpdate' => null] + ); + $table->addForeignKeyConstraint( + $schema->getTable('marello_payment_payment'), + ['payment_id'], + ['id'], + ['onDelete' => 'CASCADE', 'onUpdate' => null] + ); + } } diff --git a/src/Marello/Bundle/InvoiceBundle/Migrations/Schema/v2_0/MarelloInvoiceBundleAddColumns.php b/src/Marello/Bundle/InvoiceBundle/Migrations/Schema/v2_0/MarelloInvoiceBundleAddColumns.php new file mode 100644 index 000000000..967919d74 --- /dev/null +++ b/src/Marello/Bundle/InvoiceBundle/Migrations/Schema/v2_0/MarelloInvoiceBundleAddColumns.php @@ -0,0 +1,75 @@ +updateInvoiceTable($schema); + if (!$schema->hasTable('marello_invoice_payments')) { + $this->createMarelloInvoicePaymentsTable($schema); + $this->addMarelloInvoicePaymentsForeignKeys($schema); + } + } + + /** + * @param Schema $schema + */ + public function updateInvoiceTable(Schema $schema) + { + $table = $schema->getTable('marello_invoice_invoice'); + $table->addColumn('total_due', 'money', ['notnull' => false, 'precision' => 19, 'scale' => 4, 'comment' => '(DC2Type:money)']); + $table->addColumn('total_paid', 'money', ['notnull' => false, 'precision' => 19, 'scale' => 4, 'comment' => '(DC2Type:money)']); + } + + /** + * Create marello_invoice_invoice_item table + * + * @param Schema $schema + */ + protected function createMarelloInvoicePaymentsTable(Schema $schema) + { + $table = $schema->createTable('marello_invoice_payments'); + $table->addColumn('invoice_id', 'integer', ['notnull' => true]); + $table->addColumn('payment_id', 'integer', ['notnull' => true]); + $table->addUniqueIndex(['payment_id'], null); + $table->setPrimaryKey(['invoice_id', 'payment_id']); + } + + /** + * @param Schema $schema + */ + protected function addMarelloInvoicePaymentsForeignKeys(Schema $schema) + { + $table = $schema->getTable('marello_invoice_payments'); + $table->addForeignKeyConstraint( + $schema->getTable('marello_invoice_invoice'), + ['invoice_id'], + ['id'], + ['onDelete' => 'CASCADE', 'onUpdate' => null] + ); + $table->addForeignKeyConstraint( + $schema->getTable('marello_payment_payment'), + ['payment_id'], + ['id'], + ['onDelete' => 'CASCADE', 'onUpdate' => null] + ); + } +} diff --git a/src/Marello/Bundle/InvoiceBundle/Migrations/Schema/v2_0/MarelloInvoiceBundleAddQuery.php b/src/Marello/Bundle/InvoiceBundle/Migrations/Schema/v2_0/MarelloInvoiceBundleAddQuery.php new file mode 100644 index 000000000..d670dd174 --- /dev/null +++ b/src/Marello/Bundle/InvoiceBundle/Migrations/Schema/v2_0/MarelloInvoiceBundleAddQuery.php @@ -0,0 +1,26 @@ +addQuery(new PaymentsCreationQuery()); + } +} diff --git a/src/Marello/Bundle/InvoiceBundle/Migrations/Schema/v2_0/MarelloInvoiceBundleRemoveColumns.php b/src/Marello/Bundle/InvoiceBundle/Migrations/Schema/v2_0/MarelloInvoiceBundleRemoveColumns.php new file mode 100644 index 000000000..de17a5ed8 --- /dev/null +++ b/src/Marello/Bundle/InvoiceBundle/Migrations/Schema/v2_0/MarelloInvoiceBundleRemoveColumns.php @@ -0,0 +1,37 @@ +updateInvoiceTable($schema); + } + + /** + * @param Schema $schema + */ + public function updateInvoiceTable(Schema $schema) + { + $table = $schema->getTable('marello_invoice_invoice'); + $table->dropColumn('payment_reference'); + $table->dropColumn('payment_details'); + } +} diff --git a/src/Marello/Bundle/InvoiceBundle/Migrations/Schema/v2_0/PaymentsCreationQuery.php b/src/Marello/Bundle/InvoiceBundle/Migrations/Schema/v2_0/PaymentsCreationQuery.php new file mode 100644 index 000000000..b1678a010 --- /dev/null +++ b/src/Marello/Bundle/InvoiceBundle/Migrations/Schema/v2_0/PaymentsCreationQuery.php @@ -0,0 +1,66 @@ +createPayments($logger, true); + + return $logger->getMessages(); + } + + /** + * {@inheritdoc} + */ + public function execute(LoggerInterface $logger) + { + $this->createPayments($logger); + } + + /** + * @param LoggerInterface $logger + * @param bool $dryRun + */ + protected function createPayments(LoggerInterface $logger, $dryRun = false) + { + $invoices = $this->loadInvoices($logger); + foreach ($invoices as $invoice) { + $query = " +INSERT INTO marello_payment_payment +(payment_method, payment_reference, payment_details, total_paid, organization_id, payment_date, created_at) +VALUES +('" . $invoice['payment_method'] . "', '" . $invoice['payment_reference'] . "', '" .$invoice['payment_details'] . "', '" . $invoice['grand_total'] . "', '" . $invoice['organization_id'] . "', '" . $invoice['created_at'] . "', '" . $invoice['created_at'] . "')"; + $this->logQuery($logger, $query); + if (!$dryRun) { + $this->connection->executeQuery($query); + + $paymentId = $this->connection->lastInsertId(); + $query2 = "INSERT INTO marello_invoice_payments (invoice_id, payment_id) VALUES ('" . $invoice['id'] . "', '" . $paymentId . "')"; + $this->connection->executeQuery($query2); + } + } + } + + /** + * @param LoggerInterface $logger + * + * @return array + */ + protected function loadInvoices(LoggerInterface $logger) + { + $sql = 'SELECT id, payment_method, payment_reference, payment_details, grand_total, organization_id, created_at FROM marello_invoice_invoice'; + $this->logQuery($logger, $sql); + + return $this->connection->fetchAll($sql); + } +} diff --git a/src/Marello/Bundle/InvoiceBundle/Pdf/Logo/InvoiceLogoPathProvider.php b/src/Marello/Bundle/InvoiceBundle/Pdf/Logo/InvoiceLogoPathProvider.php index f0008fb5a..7fc99035e 100644 --- a/src/Marello/Bundle/InvoiceBundle/Pdf/Logo/InvoiceLogoPathProvider.php +++ b/src/Marello/Bundle/InvoiceBundle/Pdf/Logo/InvoiceLogoPathProvider.php @@ -58,6 +58,17 @@ public function getInvoiceLogo(SalesChannel $salesChannel, $absolute = false) return $path; } + /** + * @param SalesChannel $salesChannel + * @return mixed + */ + public function getInvoiceLogoWidth(SalesChannel $salesChannel) + { + $key = sprintf('%s.%s', Configuration::CONFIG_NAME, Configuration::CONFIG_KEY_LOGO_WIDTH); + + return $this->configManager->get($key, false, false, $salesChannel); + } + /** * @param SalesChannel $salesChannel * @return mixed @@ -69,6 +80,7 @@ protected function getInvoiceLogoId(SalesChannel $salesChannel) return $this->configManager->get($key, false, false, $salesChannel); } + /** * @param $id * @return object|null diff --git a/src/Marello/Bundle/InvoiceBundle/Pdf/Logo/InvoiceLogoRenderParameterProvider.php b/src/Marello/Bundle/InvoiceBundle/Pdf/Logo/InvoiceLogoRenderParameterProvider.php index a5e30e5fd..592f5736d 100644 --- a/src/Marello/Bundle/InvoiceBundle/Pdf/Logo/InvoiceLogoRenderParameterProvider.php +++ b/src/Marello/Bundle/InvoiceBundle/Pdf/Logo/InvoiceLogoRenderParameterProvider.php @@ -30,6 +30,9 @@ public function getParams($entity, array $options) $salesChannel = $options[self::OPTION_KEY]; } - return ['logo' => $this->logoProvider->getInvoiceLogo($salesChannel, true)]; + return [ + 'logo' => $this->logoProvider->getInvoiceLogo($salesChannel, true), + 'logo_width' => $this->logoProvider->getInvoiceLogoWidth($salesChannel), + ]; } } diff --git a/src/Marello/Bundle/InvoiceBundle/Provider/InvoicePaidAmountProvider.php b/src/Marello/Bundle/InvoiceBundle/Provider/InvoicePaidAmountProvider.php new file mode 100644 index 000000000..9f04cdc34 --- /dev/null +++ b/src/Marello/Bundle/InvoiceBundle/Provider/InvoicePaidAmountProvider.php @@ -0,0 +1,18 @@ +getPayments() as $payment) { + $amount += $payment->getTotalPaid(); + } + + return $amount; + } +} diff --git a/src/Marello/Bundle/InvoiceBundle/Resources/config/oro/actions.yml b/src/Marello/Bundle/InvoiceBundle/Resources/config/oro/actions.yml new file mode 100644 index 000000000..59d941be7 --- /dev/null +++ b/src/Marello/Bundle/InvoiceBundle/Resources/config/oro/actions.yml @@ -0,0 +1,89 @@ +operations: + marello_payment_add: + label: marello.payment.button.add_payment.label + applications: [default] + acl_resource: [EDIT, $.data] + order: 20 + routes: + - marello_invoice_invoice_view + attributes: + invoice_paid_amount: + label: marello.payment.total_paid.label + type: float + payment_method: + label: marello.payment.payment_method.label + type: string + payment_date: + label: marello.payment.payment_date.label + type: object + options: + class: \DateTime + payment_reference: + label: marello.payment.payment_reference.label + type: string + payment_details: + label: marello.payment.payment_details.label + type: string + total_paid: + label: marello.payment.total_paid.label + type: object + options: + class: Oro\Bundle\CurrencyBundle\Entity\Price + action_result: + label: 'result' + type: array + form_options: + attribute_fields: + payment_method: + form_type: Marello\Bundle\PaymentBundle\Form\Type\PaymentMethodSelectType + options: + required: true + constraints: + - NotBlank: ~ + payment_date: + form_type: Oro\Bundle\FormBundle\Form\Type\OroDateTimeType + options: + required: true + constraints: + - NotBlank: ~ + - DateTime: ~ + payment_reference: + form_type: Symfony\Component\Form\Extension\Core\Type\TextType + options: + required: true + constraints: + - NotBlank: ~ + payment_details: + form_type: Symfony\Component\Form\Extension\Core\Type\TextType + options: + required: true + constraints: + - NotBlank: ~ + total_paid: + form_type: Marello\Bundle\OrderBundle\Form\Type\OrderTotalPaidType + options: + required: true + currency: $.data.currency + frontend_options: + options: + width: 2000 + show_dialog: true + template: MarelloPaymentBundle:Action:payment_popup.html.twig + preactions: + - '@call_service_method': + service: marello_invoice.provider.invoice_paid_amount + method: getPaidAmount + method_parameters: [$.data] + attribute: $.invoice_paid_amount + preconditions: + '@and': + - '@less': [$.invoice_paid_amount, $.data.grandTotal] + actions: + - '@call_service_method': + service: marello_payment.action.handler.add_payment + method: handleAction + method_parameters: [$.data, $.payment_method, $.payment_date, $.payment_reference, $.payment_details, $.total_paid.value] + attribute: $.action_result + - '@flash_message': + message: $.action_result.message + type: $.action_result.type diff --git a/src/Marello/Bundle/InvoiceBundle/Resources/config/oro/datagrids.yml b/src/Marello/Bundle/InvoiceBundle/Resources/config/oro/datagrids.yml index a2f3717a0..ef230af46 100644 --- a/src/Marello/Bundle/InvoiceBundle/Resources/config/oro/datagrids.yml +++ b/src/Marello/Bundle/InvoiceBundle/Resources/config/oro/datagrids.yml @@ -38,10 +38,21 @@ datagrids: method: formatCurrency context_resolver: Marello\Bundle\DataGridBundle\Grid\FormatterContextResolver::getResolverCurrencyClosure align: right + totalPaid: + label: marello.invoice.total_paid.label + type: localized_number + method: formatCurrency + context_resolver: Marello\Bundle\DataGridBundle\Grid\FormatterContextResolver::getResolverCurrencyClosure + align: right + totalDue: + label: marello.invoice.total_due.label + type: localized_number + method: formatCurrency + context_resolver: Marello\Bundle\DataGridBundle\Grid\FormatterContextResolver::getResolverCurrencyClosure + align: right invoicedAt: frontend_type: datetime label: marello.invoice.invoiced_at.label - renderable: false createdAt: label: oro.ui.created_at frontend_type: datetime @@ -62,6 +73,10 @@ datagrids: data_name: billingName grandTotal: data_name: i.grandTotal + totalPaid: + data_name: i.totalPaid + totalDue: + data_name: i.totalDue invoicedAt: data_name: i.purchaseDate createdAt: diff --git a/src/Marello/Bundle/InvoiceBundle/Resources/config/services.yml b/src/Marello/Bundle/InvoiceBundle/Resources/config/services.yml index 849ff0d47..410c3f69c 100644 --- a/src/Marello/Bundle/InvoiceBundle/Resources/config/services.yml +++ b/src/Marello/Bundle/InvoiceBundle/Resources/config/services.yml @@ -60,6 +60,10 @@ services: tags: - { name: kernel.event_listener, event: oro_datagrid.datagrid.build.before.marello-invoices-base-grid, method: onBuildBefore } + marello_invoice.provider.invoice_paid_amount: + class: 'Marello\Bundle\InvoiceBundle\Provider\InvoicePaidAmountProvider' + public: true + marello_invoice.provider.invoice_type_choices: class: 'Marello\Bundle\InvoiceBundle\Provider\InvoiceTypeChoicesProvider' public: true @@ -122,4 +126,16 @@ services: arguments: - '@marello_invoice.pdf.provider.table_size' tags: - - { name: marello_pdf.document_table_provider } \ No newline at end of file + - { name: marello_pdf.document_table_provider } + + marello_invoice.form_type.invoice_select: + class: 'Marello\Bundle\InvoiceBundle\Form\Type\InvoiceSelectType' + tags: + - { name: form.type } + + marello_invoice.twig.invoice_extension: + class: 'Marello\Bundle\InvoiceBundle\Twig\InvoiceExtension' + arguments: + - '@doctrine' + tags: + - { name: twig.extension } diff --git a/src/Marello/Bundle/InvoiceBundle/Resources/translations/messages.en.yml b/src/Marello/Bundle/InvoiceBundle/Resources/translations/messages.en.yml index 27b5910a4..5d89cd675 100644 --- a/src/Marello/Bundle/InvoiceBundle/Resources/translations/messages.en.yml +++ b/src/Marello/Bundle/InvoiceBundle/Resources/translations/messages.en.yml @@ -13,9 +13,10 @@ marello: name.label: Ship to Name invoiced_at.label: Invoiced At invoice_due_date.label: Invoice Due Date + payments.label: Payments + total_due.label: Total Due + total_paid.label: Total Paid payment_method.label: Payment Method - payment_reference.label: Payment Reference - payment_details.label: Payment Details payment_term.label: Payment Term shipping_method.label: Shipping Method shipping_method_type.label: Shipping Method Type @@ -52,9 +53,10 @@ marello: name.label: Ship to Name invoiced_at.label: Invoiced At invoice_due_date.label: Invoice Due Date + payments.label: Payments + total_due.label: Total Due + total_paid.label: Total Paid payment_method.label: Payment Method - payment_reference.label: Payment Reference - payment_details.label: Payment Details shipping_method.label: Shipping Method shipping_method_type.label: Shipping Method Type order.label: Order @@ -75,7 +77,7 @@ marello: datablock: general: General - billing_and_payment: Billing & Payment + billing_address: Billing Address delivery: Delivery invoice_items: Invoice Items creditmemo_items: Credit Memo Items @@ -85,6 +87,7 @@ marello: customer_information: Customer Information invoice_totals: Invoice Totals creditmemo_totals: Credit Memo Totals + payments: Payments invoiceitem: id.label: Id @@ -106,10 +109,10 @@ marello: creditmemoitem: id.label: Id - entity_label: Creditmemo Item - entity_plural_label: Creditmemo Items + entity_label: Credit Memo Item + entity_plural_label: Credit Memo Items entity_grid_all_view_label: All %entity_plural_label% - invoice.label: Creditmemo + invoice.label: Invoice quantity.label: Quantity price.label: Price product.label: Product @@ -136,9 +139,10 @@ marello: name.label: Ship to Name invoiced_at.label: Invoiced At invoice_due_date.label: Invoice Due Date + payments.label: Payments + total_due.label: Total Due + total_paid.label: Total Paid payment_method.label: Payment Method - payment_reference.label: Payment Reference - payment_details.label: Payment Details shipping_method.label: Shipping Method shipping_method_type.label: Shipping Method Type order.label: Order diff --git a/src/Marello/Bundle/InvoiceBundle/Resources/translations/pdf.en.yml b/src/Marello/Bundle/InvoiceBundle/Resources/translations/pdf.en.yml index 51491d074..0b1b0fe0f 100644 --- a/src/Marello/Bundle/InvoiceBundle/Resources/translations/pdf.en.yml +++ b/src/Marello/Bundle/InvoiceBundle/Resources/translations/pdf.en.yml @@ -4,6 +4,7 @@ marello: invoice_date.label: "Invoice date" invoice_number.label: "Invoice number" debtor_number.label: "Debtor number" + payment_term.label: "Payment term" subtotal.label: "Subtotal" total.label: "Total" page_number.label: "Page %pageNumber% of %totalPages%" diff --git a/src/Marello/Bundle/InvoiceBundle/Resources/views/Invoice/view.html.twig b/src/Marello/Bundle/InvoiceBundle/Resources/views/Invoice/view.html.twig index 4799e021a..4b5a1a40b 100644 --- a/src/Marello/Bundle/InvoiceBundle/Resources/views/Invoice/view.html.twig +++ b/src/Marello/Bundle/InvoiceBundle/Resources/views/Invoice/view.html.twig @@ -16,9 +16,13 @@ {% endblock pageHeader %} {% block navButtons %} - - {{ 'marello.invoice.pdf.download.label'|trans }} - + {% if is_granted('VIEW', entity) %} + + {% endif %} {% endblock %} {% block content_data %} @@ -57,6 +61,10 @@ {{ UI.renderProperty('marello.invoice.shipping_amount_incl_tax.label'|trans, entity.shippingAmountInclTax|oro_format_currency({'currency':entity.currency})) }} {{ UI.renderProperty('marello.invoice.total_tax.label'|trans, entity.totalTax|oro_format_currency({'currency':entity.currency})) }} {{ UI.renderProperty('marello.invoice.grand_total.label'|trans, entity.grandTotal|oro_format_currency({'currency':entity.currency})) }} + {{ UI.renderProperty('marello.invoice.total_paid.label'|trans, entity.totalPaid|oro_format_currency({'currency':entity.currency})) }} + {{ UI.renderProperty('marello.invoice.total_due.label'|trans, entity.totalDue|oro_format_currency({'currency':entity.currency})) }} +
+
{% endset %} @@ -78,6 +86,9 @@ {% if entity.customer.company.companyNumber %} {{ UI.renderProperty('marello.customer.company.company_number.label'|trans, entity.customer.company.companyNumber) }} {% endif %} + {% if entity.customer.company.taxIdentificationNumber %} + {{ UI.renderProperty('marello.customer.company.tax_identification_number.label'|trans, entity.customer.company.taxIdentificationNumber) }} + {% endif %} {% endif %} {{ UI.renderHtmlProperty( 'marello.customer.entity_label'|trans, @@ -91,28 +102,24 @@ {% endset %} {% set generalSubblocks = generalSubblocks|merge([{'data' : [customerInformation] }]) %} - {% set paymentSubblocks = [] %} + {% set billingSubblocks = [] %} {% set billingAddressBlock %} {{ oro_widget_render({ 'widgetType': 'block', 'url': path('marello_order_order_address', {id: entity.billingAddress.id, typeId: 1}), }) }} {% endset %} - {% set paymentSubblocks = paymentSubblocks|merge([{'data' : [billingAddressBlock] }]) %} + {% set billingSubblocks = billingSubblocks|merge([{'data' : [billingAddressBlock] }]) %} - {% set paymentWidget %} + {% set emptyWidget %}
- {{ UI.renderProperty('marello.invoice.payment_method.label'|trans, entity.paymentMethod) }} - {{ UI.renderProperty('marello.invoice.payment_reference.label'|trans, entity.paymentReference) }} - {{ UI.renderHtmlProperty('marello.invoice.payment_details.label'|trans, entity.paymentDetails|nl2br) }} - {{ UI.renderProperty('marello.invoice.payment_term.label'|trans, (entity.paymentTerm is not empty ? entity.paymentTerm.labels|localized_value : 'N/A')|trans) }}
{% endset %} - {% set paymentSubblocks = paymentSubblocks|merge([{'data' : [paymentWidget] }]) %} + {% set billingSubblocks = billingSubblocks|merge([{'data' : [emptyWidget] }]) %} {% set shippingSubblocks = [] %} {% set shippingAddressBlock %} @@ -146,6 +153,10 @@ {% endset %} + {% set payments %} + {{ dataGrid.renderGrid('marello-invoice-payments-grid', {'invoiceId': entity.id}) }} + {% endset %} + {% set dataBlocks = [ { 'title': 'marello.invoice.datablock.general'|trans, @@ -153,9 +164,9 @@ 'subblocks': generalSubblocks }, { - 'title': 'marello.invoice.datablock.billing_and_payment'|trans, + 'title': 'marello.invoice.datablock.billing_address'|trans, 'class': 'active', - 'subblocks': paymentSubblocks + 'subblocks': billingSubblocks }, { 'title': 'marello.invoice.datablock.delivery'|trans, @@ -168,6 +179,13 @@ 'subblocks': [ { 'data' : [items] } ] + }, + { + 'title': 'marello.invoice.datablock.payments'|trans, + 'class': 'active', + 'subblocks': [ + { 'data' : [payments] } + ] } ] %} diff --git a/src/Marello/Bundle/InvoiceBundle/Resources/views/Pdf/creditmemo.html.twig b/src/Marello/Bundle/InvoiceBundle/Resources/views/Pdf/creditmemo.html.twig index c36265499..0a31984d3 100644 --- a/src/Marello/Bundle/InvoiceBundle/Resources/views/Pdf/creditmemo.html.twig +++ b/src/Marello/Bundle/InvoiceBundle/Resources/views/Pdf/creditmemo.html.twig @@ -249,6 +249,10 @@
{{ 'marello.customer.company.pdf.company_number.label'|trans({}, 'pdf', language) }}:
{{ entity.customer.company.companyNumber }}
{% endif %} + {% if entity.customer.company and entity.customer.company.taxIdentificationNumber %} +
{{ 'marello.customer.company.pdf.tax_identification_number.label'|trans({}, 'pdf', language) }}:
+
{{ entity.customer.company.taxIdentificationNumber }}
+ {% endif %} diff --git a/src/Marello/Bundle/InvoiceBundle/Resources/views/Pdf/invoice.html.twig b/src/Marello/Bundle/InvoiceBundle/Resources/views/Pdf/invoice.html.twig index 915b1f83c..c38722281 100644 --- a/src/Marello/Bundle/InvoiceBundle/Resources/views/Pdf/invoice.html.twig +++ b/src/Marello/Bundle/InvoiceBundle/Resources/views/Pdf/invoice.html.twig @@ -237,7 +237,7 @@ {{ address.postalCode }} {{ address.city }}
{{ ('country.' ~ address.country.iso2code)|trans({}, 'entities', language) }}

- + {% set paymentTerm = marello_get_payment_term_for_customer(entity.customer) %} {# Invoice details #}
@@ -249,6 +249,14 @@
{{ 'marello.customer.company.pdf.company_number.label'|trans({}, 'pdf', language) }}:
{{ entity.customer.company.companyNumber }}
{% endif %} + {% if entity.customer.company and entity.customer.company.taxIdentificationNumber %} +
{{ 'marello.customer.company.pdf.tax_identification_number.label'|trans({}, 'pdf', language) }}:
+
{{ entity.customer.company.taxIdentificationNumber }}
+ {% endif %} + {% if paymentTerm %} +
{{ 'marello.pdf.invoice.payment_term.label'|trans({}, 'pdf', language) }}:
+
{{ 'marello.payment_term.ui.payment_term.term_days'|trans({'%days%': paymentTerm.term }) }}
+ {% endif %}
diff --git a/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/cget_creditmemo_list.yml b/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/cget_creditmemo_list.yml index 4f5457203..36ac54310 100644 --- a/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/cget_creditmemo_list.yml +++ b/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/cget_creditmemo_list.yml @@ -7,8 +7,6 @@ data: invoicedAt: '@marello_creditmemo_0->invoicedAt->format("Y-m-d\TH:i:s\Z")' invoiceDueDate: null paymentMethod: 'Credit Card' - paymentReference: null - paymentDetails: 'American Express refnr. 371449635398431' shippingMethod: null shippingMethodType: null currency: USD @@ -56,8 +54,6 @@ data: invoicedAt: '@marello_creditmemo_1->invoicedAt->format("Y-m-d\TH:i:s\Z")' invoiceDueDate: null paymentMethod: Paypal - paymentReference: null - paymentDetails: null shippingMethod: null shippingMethodType: null currency: GBP diff --git a/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/cget_creditmemo_list_by_order.yml b/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/cget_creditmemo_list_by_order.yml index 148b9ccfd..4f4a3d80d 100644 --- a/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/cget_creditmemo_list_by_order.yml +++ b/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/cget_creditmemo_list_by_order.yml @@ -7,8 +7,6 @@ data: invoicedAt: '@marello_creditmemo_1->invoicedAt->format("Y-m-d\TH:i:s\Z")' invoiceDueDate: null paymentMethod: Paypal - paymentReference: null - paymentDetails: null shippingMethod: null shippingMethodType: null currency: GBP diff --git a/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/cget_invoice_list.yml b/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/cget_invoice_list.yml index 9057e501b..249e13be3 100644 --- a/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/cget_invoice_list.yml +++ b/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/cget_invoice_list.yml @@ -7,8 +7,6 @@ data: invoicedAt: '@marello_invoice_0->invoicedAt->format("Y-m-d\TH:i:s\Z")' invoiceDueDate: null paymentMethod: 'Credit Card' - paymentReference: null - paymentDetails: 'American Express refnr. 371449635398431' shippingMethod: null shippingMethodType: null currency: USD @@ -56,8 +54,6 @@ data: invoicedAt: '@marello_invoice_1->invoicedAt->format("Y-m-d\TH:i:s\Z")' invoiceDueDate: null paymentMethod: Paypal - paymentReference: null - paymentDetails: null shippingMethod: null shippingMethodType: null currency: GBP @@ -114,8 +110,6 @@ data: invoicedAt: '@marello_invoice_2->invoicedAt->format("Y-m-d\TH:i:s\Z")' invoiceDueDate: null paymentMethod: 'Credit Card' - paymentReference: null - paymentDetails: 'American Express refnr. 371449635398431' shippingMethod: null shippingMethodType: null currency: USD @@ -169,8 +163,6 @@ data: invoicedAt: '@marello_invoice_3->invoicedAt->format("Y-m-d\TH:i:s\Z")' invoiceDueDate: null paymentMethod: Paypal - paymentReference: null - paymentDetails: null shippingMethod: null shippingMethodType: null currency: GBP diff --git a/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/cget_invoice_list_by_order.yml b/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/cget_invoice_list_by_order.yml index 82650d8b6..49a6c6df0 100644 --- a/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/cget_invoice_list_by_order.yml +++ b/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/cget_invoice_list_by_order.yml @@ -7,8 +7,6 @@ data: invoicedAt: '@marello_invoice_2->invoicedAt->format("Y-m-d\TH:i:s\Z")' invoiceDueDate: null paymentMethod: 'Credit Card' - paymentReference: null - paymentDetails: 'American Express refnr. 371449635398431' shippingMethod: null shippingMethodType: null currency: USD diff --git a/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/get_creditmemo_by_id.yml b/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/get_creditmemo_by_id.yml index 850783795..ba6c76ba4 100644 --- a/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/get_creditmemo_by_id.yml +++ b/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/get_creditmemo_by_id.yml @@ -6,8 +6,6 @@ data: invoicedAt: '@marello_creditmemo_0->invoicedAt->format("Y-m-d\TH:i:s\Z")' invoiceDueDate: null paymentMethod: 'Credit Card' - paymentReference: null - paymentDetails: 'American Express refnr. 371449635398431' shippingMethod: null shippingMethodType: null currency: USD diff --git a/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/get_creditmemo_by_invoiceNumber.yml b/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/get_creditmemo_by_invoiceNumber.yml index 66e18c5f3..115352ced 100644 --- a/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/get_creditmemo_by_invoiceNumber.yml +++ b/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/get_creditmemo_by_invoiceNumber.yml @@ -6,8 +6,6 @@ data: invoicedAt: '@marello_creditmemo_1->invoicedAt->format("Y-m-d\TH:i:s\Z")' invoiceDueDate: null paymentMethod: Paypal - paymentReference: null - paymentDetails: null shippingMethod: null shippingMethodType: null currency: GBP diff --git a/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/get_invoice_by_id.yml b/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/get_invoice_by_id.yml index 66efd1b98..2fde1b2ee 100644 --- a/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/get_invoice_by_id.yml +++ b/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/get_invoice_by_id.yml @@ -6,8 +6,6 @@ data: invoicedAt: '@marello_invoice_1->invoicedAt->format("Y-m-d\TH:i:s\Z")' invoiceDueDate: null paymentMethod: Paypal - paymentReference: null - paymentDetails: null shippingMethod: null shippingMethodType: null currency: GBP diff --git a/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/get_invoice_by_invoiceNumber.yml b/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/get_invoice_by_invoiceNumber.yml index 66efd1b98..2fde1b2ee 100644 --- a/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/get_invoice_by_invoiceNumber.yml +++ b/src/Marello/Bundle/InvoiceBundle/Tests/Functional/Api/responses/get_invoice_by_invoiceNumber.yml @@ -6,8 +6,6 @@ data: invoicedAt: '@marello_invoice_1->invoicedAt->format("Y-m-d\TH:i:s\Z")' invoiceDueDate: null paymentMethod: Paypal - paymentReference: null - paymentDetails: null shippingMethod: null shippingMethodType: null currency: GBP diff --git a/src/Marello/Bundle/InvoiceBundle/Tests/Unit/Pdf/Logo/InvoiceLogoRenderParameterProviderTest.php b/src/Marello/Bundle/InvoiceBundle/Tests/Unit/Pdf/Logo/InvoiceLogoRenderParameterProviderTest.php index 2f87a0170..7ad7ae5d4 100644 --- a/src/Marello/Bundle/InvoiceBundle/Tests/Unit/Pdf/Logo/InvoiceLogoRenderParameterProviderTest.php +++ b/src/Marello/Bundle/InvoiceBundle/Tests/Unit/Pdf/Logo/InvoiceLogoRenderParameterProviderTest.php @@ -69,7 +69,7 @@ public function testGetParams($entity, $options, $salesChannel, $logoPath) ->willReturn($logoPath) ; - $this->assertEquals(['logo' => $logoPath], $this->provider->getParams($entity, $options)); + $this->assertEquals(['logo' => $logoPath, 'logo_width' => null], $this->provider->getParams($entity, $options)); } public function getParamsProvider() diff --git a/src/Marello/Bundle/InvoiceBundle/Tests/Unit/Pdf/Table/InvoiceTableProviderTest.php b/src/Marello/Bundle/InvoiceBundle/Tests/Unit/Pdf/Table/InvoiceTableProviderTest.php index 952b4f938..20b565b2c 100644 --- a/src/Marello/Bundle/InvoiceBundle/Tests/Unit/Pdf/Table/InvoiceTableProviderTest.php +++ b/src/Marello/Bundle/InvoiceBundle/Tests/Unit/Pdf/Table/InvoiceTableProviderTest.php @@ -126,8 +126,6 @@ public function testGetTables( 'invoicedAt' => new \DateTime('2019-01-01 12:34:56'), 'invoiceDueDate' => new \DateTime('2019-01-02 23:45:01'), 'paymentMethod' => 'payment method', - 'paymentReference' => 'payment reference', - 'paymentDetails' => 'payment details', 'shippingMethod' => 'shipping method', 'shippingMethodType' => 'shipping', 'status' => 'open', diff --git a/src/Marello/Bundle/InvoiceBundle/Twig/InvoiceExtension.php b/src/Marello/Bundle/InvoiceBundle/Twig/InvoiceExtension.php new file mode 100644 index 000000000..80eb03499 --- /dev/null +++ b/src/Marello/Bundle/InvoiceBundle/Twig/InvoiceExtension.php @@ -0,0 +1,65 @@ +doctrine = $doctrine; + } + + /** + * Returns the name of the extension. + * + * @return string The extension name + */ + public function getName() + { + return self::NAME; + } + + /** + * Returns a list of functions to add to the existing list. + * + * @return array An array of functions + */ + public function getFunctions() + { + return [ + new TwigFunction( + 'marello_get_payment_source', + [$this, 'getPaymentSource'] + ) + ]; + } + + /** + * {@inheritdoc} + * @param Payment $payment + * @return AbstractInvoice + */ + public function getPaymentSource(Payment $payment) + { + return $this->doctrine + ->getManagerForClass(AbstractInvoice::class) + ->getRepository(AbstractInvoice::class) + ->findOneByPayment($payment); + } +} diff --git a/src/Marello/Bundle/LayoutBundle/Resources/public/css/scss/main.scss b/src/Marello/Bundle/LayoutBundle/Resources/public/css/scss/main.scss index c807e4367..10b739996 100644 --- a/src/Marello/Bundle/LayoutBundle/Resources/public/css/scss/main.scss +++ b/src/Marello/Bundle/LayoutBundle/Resources/public/css/scss/main.scss @@ -42,7 +42,7 @@ } .marello-line-item-related-field { - margin: 5px 0 0 5px; + margin: 0 0 0 5px; float:left; } diff --git a/src/Marello/Bundle/NotificationBundle/Migrations/Schema/MarelloNotificationBundleInstaller.php b/src/Marello/Bundle/NotificationBundle/Migrations/Schema/MarelloNotificationBundleInstaller.php index 6656c66b8..03897227d 100644 --- a/src/Marello/Bundle/NotificationBundle/Migrations/Schema/MarelloNotificationBundleInstaller.php +++ b/src/Marello/Bundle/NotificationBundle/Migrations/Schema/MarelloNotificationBundleInstaller.php @@ -17,7 +17,7 @@ class MarelloNotificationBundleInstaller implements Installation */ public function getMigrationVersion() { - return 'v1_1'; + return 'v1_2'; } /** @@ -103,7 +103,7 @@ protected function addAttachmentForeignKeys(Schema $schema) ['id'] ); $table->addForeignKeyConstraint( - $schema->getTable('oro_attachment_file'), + $schema->getTable('oro_attachment'), ['attachment_id'], ['id'] ); diff --git a/src/Marello/Bundle/NotificationBundle/Migrations/Schema/v1_2/MarelloNotificationBundle.php b/src/Marello/Bundle/NotificationBundle/Migrations/Schema/v1_2/MarelloNotificationBundle.php new file mode 100644 index 000000000..45bbc31c9 --- /dev/null +++ b/src/Marello/Bundle/NotificationBundle/Migrations/Schema/v1_2/MarelloNotificationBundle.php @@ -0,0 +1,34 @@ +updateAttachmentForeignKeys($schema); + } + + /** + * Add foreign keys. + * + * @param Schema $schema + */ + protected function updateAttachmentForeignKeys(Schema $schema) + { + $table = $schema->getTable('marello_notification_attach'); + $table->removeForeignKey('FK_70347799464E68B'); + $table->addForeignKeyConstraint( + $schema->getTable('oro_attachment'), + ['attachment_id'], + ['id'] + ); + } +} diff --git a/src/Marello/Bundle/OrderBundle/Controller/OrderController.php b/src/Marello/Bundle/OrderBundle/Controller/OrderController.php index 34c0fa5cf..674b18b4e 100644 --- a/src/Marello/Bundle/OrderBundle/Controller/OrderController.php +++ b/src/Marello/Bundle/OrderBundle/Controller/OrderController.php @@ -13,7 +13,6 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\Routing\Annotation\Route; class OrderController extends AbstractController diff --git a/src/Marello/Bundle/OrderBundle/Entity/Order.php b/src/Marello/Bundle/OrderBundle/Entity/Order.php index c30d6e340..e806c952d 100644 --- a/src/Marello/Bundle/OrderBundle/Entity/Order.php +++ b/src/Marello/Bundle/OrderBundle/Entity/Order.php @@ -223,33 +223,6 @@ class Order extends ExtendOrder implements */ protected $paymentMethodOptions; - /** - * @var string - * @ORM\Column(name="payment_reference", type="string", length=255, nullable=true) - * @Oro\ConfigField( - * defaultValues={ - * "dataaudit"={ - * "auditable"=true - * } - * } - * ) - */ - protected $paymentReference; - - /** - * @var string - * - * @ORM\Column(name="payment_details", type="text", nullable=true) - * @Oro\ConfigField( - * defaultValues={ - * "dataaudit"={ - * "auditable"=true - * } - * } - * ) - */ - protected $paymentDetails; - /** * @var double * @@ -925,26 +898,6 @@ public function setPaymentMethodOptions(array $paymentMethodOptions) return $this; } - /** - * @return string - */ - public function getPaymentDetails() - { - return $this->paymentDetails; - } - - /** - * @param string $paymentDetails - * - * @return $this - */ - public function setPaymentDetails($paymentDetails) - { - $this->paymentDetails = $paymentDetails; - - return $this; - } - /** * @return string */ @@ -1041,26 +994,6 @@ public function setInvoicedAt($invoicedAt) return $this; } - /** - * @return string - */ - public function getPaymentReference() - { - return $this->paymentReference; - } - - /** - * @param string $paymentReference - * - * @return $this - */ - public function setPaymentReference($paymentReference) - { - $this->paymentReference = $paymentReference; - - return $this; - } - /** * @param int $id */ diff --git a/src/Marello/Bundle/OrderBundle/EventListener/Doctrine/OrderWorkflowStartListener.php b/src/Marello/Bundle/OrderBundle/EventListener/Doctrine/OrderWorkflowStartListener.php index 079ebaaab..a2edecb6f 100644 --- a/src/Marello/Bundle/OrderBundle/EventListener/Doctrine/OrderWorkflowStartListener.php +++ b/src/Marello/Bundle/OrderBundle/EventListener/Doctrine/OrderWorkflowStartListener.php @@ -97,7 +97,9 @@ protected function getDefaultWorkflowNames(): array { return [ WorkflowNameProviderInterface::ORDER_WORKFLOW_1, - WorkflowNameProviderInterface::ORDER_WORKFLOW_2 + WorkflowNameProviderInterface::ORDER_WORKFLOW_2, + WorkflowNameProviderInterface::ORDER_DEPRECATED_WORKFLOW_1, + WorkflowNameProviderInterface::ORDER_DEPRECATED_WORKFLOW_2 ]; } diff --git a/src/Marello/Bundle/OrderBundle/Form/Type/OrderItemCollectionType.php b/src/Marello/Bundle/OrderBundle/Form/Type/OrderItemCollectionType.php index 707425eb5..82921b3e3 100644 --- a/src/Marello/Bundle/OrderBundle/Form/Type/OrderItemCollectionType.php +++ b/src/Marello/Bundle/OrderBundle/Form/Type/OrderItemCollectionType.php @@ -27,7 +27,7 @@ public function configureOptions(OptionsResolver $resolver) $resolver->setDefaults([ 'entry_type' => OrderItemType::class, 'show_form_when_empty' => false, - 'error_bubbling' => false, + 'error_bubbling' => true, 'constraints' => [new Valid()], 'prototype_name' => '__nameorderitem__', 'prototype' => true, diff --git a/src/Marello/Bundle/OrderBundle/Form/Type/OrderItemType.php b/src/Marello/Bundle/OrderBundle/Form/Type/OrderItemType.php index 38dfcab61..603bb8af5 100644 --- a/src/Marello/Bundle/OrderBundle/Form/Type/OrderItemType.php +++ b/src/Marello/Bundle/OrderBundle/Form/Type/OrderItemType.php @@ -47,39 +47,45 @@ public function buildForm(FormBuilderInterface $builder, array $options) ->add('product', ProductSalesChannelAwareSelectType::class, [ 'required' => true, 'label' => 'marello.product.entity_label', - 'create_enabled' => false, + 'create_enabled' => false ]) ->add('quantity', NumberType::class, [ - 'data' => 1, - ])->add('availableInventory', NumberType::class, [ + 'data' => 1 + ]) + ->add('availableInventory', NumberType::class, [ 'mapped' => false, 'attr' => [ - 'readonly' => true, + 'readonly' => true + ] + ]) + ->add('productUnit', TextType::class, [ + 'attr' => [ + 'readonly' => true ] ]) ->add('price', TextType::class, [ 'attr' => [ - 'readonly' => true, + 'readonly' => true ] ]) ->add('tax', TextType::class, [ 'attr' => [ - 'readonly' => true, + 'readonly' => true ] ]) ->add('taxCode', TextType::class, [ 'attr' => [ - 'readonly' => true, + 'readonly' => true ] ]) ->add('rowTotalExclTax', TextType::class, [ 'attr' => [ - 'readonly' => true, + 'readonly' => true ] ]) ->add('rowTotalInclTax', TextType::class, [ 'attr' => [ - 'readonly' => true, + 'readonly' => true ] ]) ; diff --git a/src/Marello/Bundle/OrderBundle/Form/Type/OrderTotalPaidType.php b/src/Marello/Bundle/OrderBundle/Form/Type/OrderTotalPaidType.php new file mode 100644 index 000000000..ed29022d6 --- /dev/null +++ b/src/Marello/Bundle/OrderBundle/Form/Type/OrderTotalPaidType.php @@ -0,0 +1,93 @@ +localeSettings = $localeSettings; + $this->currencyListProvider = $currencyListProvider; + } + + /** + * @param FormBuilderInterface $builder + * @param array $options + */ + public function buildForm(FormBuilderInterface $builder, array $options) + { + $currencyChoices = []; + if (isset($options['currency']) && $options['currency'] !== null) { + $currencyChoices[$this->localeSettings->getCurrencySymbolByCurrency($options['currency'])] = + $options['currency']; + } else { + foreach ($this->currencyListProvider->getCurrencyList() as $currency) { + $currencyChoices[$this->localeSettings->getCurrencySymbolByCurrency($currency)] = + $currency; + } + } + + $builder + ->add( + 'value', + NumberType::class, + [ + 'grouping' => true, + 'required' => true, + 'constraints' => new NotNull + ] + ) + ->add( + 'currency', + ChoiceType::class, + [ + 'choices' => $currencyChoices + ] + ); + } + + /** + * {@inheritdoc} + */ + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + 'data_class' => Price::class, + 'currency' => null + ]); + } + + /** + * {@inheritdoc} + */ + public function getBlockPrefix() + { + return self::BLOCK_PREFIX; + } +} diff --git a/src/Marello/Bundle/OrderBundle/Migrations/Schema/MarelloOrderBundleInstaller.php b/src/Marello/Bundle/OrderBundle/Migrations/Schema/MarelloOrderBundleInstaller.php index 0678baba2..362535355 100644 --- a/src/Marello/Bundle/OrderBundle/Migrations/Schema/MarelloOrderBundleInstaller.php +++ b/src/Marello/Bundle/OrderBundle/Migrations/Schema/MarelloOrderBundleInstaller.php @@ -46,7 +46,7 @@ class MarelloOrderBundleInstaller implements */ public function getMigrationVersion() { - return 'v1_13_2'; + return 'v3_1_2'; } /** @@ -92,8 +92,6 @@ protected function createMarelloOrderOrderTable(Schema $schema) 'notnull' => false, 'comment' => '(DC2Type:json_array)' ] ); - $table->addColumn('payment_reference', 'string', ['notnull' => false, 'length' => 255]); - $table->addColumn('payment_details', 'text', ['notnull' => false]); $table->addColumn('data', 'json_array', ['notnull' => false, 'comment' => '(DC2Type:json_array)']); $table->addColumn( 'shipping_amount_incl_tax', diff --git a/src/Marello/Bundle/OrderBundle/Migrations/Schema/v3_1/MarelloOrderBundle.php b/src/Marello/Bundle/OrderBundle/Migrations/Schema/v3_1/MarelloOrderBundle.php new file mode 100644 index 000000000..18caf1371 --- /dev/null +++ b/src/Marello/Bundle/OrderBundle/Migrations/Schema/v3_1/MarelloOrderBundle.php @@ -0,0 +1,29 @@ +updateOrderTable($schema); + } + + /** + * @param Schema $schema + */ + public function updateOrderTable(Schema $schema) + { + $table = $schema->getTable('marello_order_order'); + $table->dropColumn('payment_reference'); + $table->dropColumn('payment_details'); + } +} diff --git a/src/Marello/Bundle/OrderBundle/Migrations/Schema/v3_1_1/MarelloOrderBundle.php b/src/Marello/Bundle/OrderBundle/Migrations/Schema/v3_1_1/MarelloOrderBundle.php new file mode 100644 index 000000000..92b31b802 --- /dev/null +++ b/src/Marello/Bundle/OrderBundle/Migrations/Schema/v3_1_1/MarelloOrderBundle.php @@ -0,0 +1,73 @@ +updateOrderTable($schema); + $this->updateOrderItemTable($schema); + } + + private function updateOrderTable(Schema $schema) + { + $table = $schema->getTable('marello_order_order'); + if (!$table->hasColumn('delivery_date')) { + $table->addColumn('delivery_date', 'datetime', ['notnull' => false]); + } + if (!$table->hasColumn('order_note')) { + $table->addColumn('order_note', 'text', ['notnull' => false]); + } + if (!$table->hasColumn('po_number')) { + $table->addColumn('po_number', 'string', ['length' => 255, 'notnull' => false]); + } + } + + private function updateOrderItemTable(Schema $schema) + { + $tableName = $this->extendExtension->getNameGenerator()->generateEnumTableName('marello_product_unit'); + // enum table is already available and created... + if ($schema->hasTable($tableName)) { + return; + } + + $table = $schema->getTable('marello_order_order_item'); + $this->extendExtension->addEnumField( + $schema, + $table, + 'productUnit', + 'marello_product_unit', + false, + false, + [ + 'extend' => ['owner' => ExtendScope::OWNER_SYSTEM], + ] + ); + } + + /** + * Sets the ExtendExtension + * + * @param ExtendExtension $extendExtension + */ + public function setExtendExtension(ExtendExtension $extendExtension) + { + $this->extendExtension = $extendExtension; + } +} diff --git a/src/Marello/Bundle/OrderBundle/Migrations/Schema/v1_13_1/MarelloOrderBundle.php b/src/Marello/Bundle/OrderBundle/Migrations/Schema/v3_1_2/MarelloOrderBundle.php similarity index 77% rename from src/Marello/Bundle/OrderBundle/Migrations/Schema/v1_13_1/MarelloOrderBundle.php rename to src/Marello/Bundle/OrderBundle/Migrations/Schema/v3_1_2/MarelloOrderBundle.php index 69560bd4b..d64955a37 100644 --- a/src/Marello/Bundle/OrderBundle/Migrations/Schema/v1_13_1/MarelloOrderBundle.php +++ b/src/Marello/Bundle/OrderBundle/Migrations/Schema/v3_1_2/MarelloOrderBundle.php @@ -1,6 +1,6 @@ getTable('marello_order_order'); - $table->addColumn('locale_id', 'string', ['notnull' => false, 'length' => 255]); - + if (!$table->hasColumn('locale_id')) { + $table->addColumn('locale_id', 'string', ['notnull' => false, 'length' => 255]); + } $queries->addQuery( new UpdateEntityConfigFieldValueQuery( Order::class, diff --git a/src/Marello/Bundle/OrderBundle/Model/WorkflowNameProviderInterface.php b/src/Marello/Bundle/OrderBundle/Model/WorkflowNameProviderInterface.php index e951aef0e..79c2d1389 100644 --- a/src/Marello/Bundle/OrderBundle/Model/WorkflowNameProviderInterface.php +++ b/src/Marello/Bundle/OrderBundle/Model/WorkflowNameProviderInterface.php @@ -4,6 +4,8 @@ interface WorkflowNameProviderInterface { - const ORDER_WORKFLOW_1 = 'marello_order_b2c_workflow_1'; - const ORDER_WORKFLOW_2 = 'marello_order_b2c_workflow_2'; + const ORDER_DEPRECATED_WORKFLOW_1 = 'marello_order_b2c_workflow_1'; + const ORDER_DEPRECATED_WORKFLOW_2 = 'marello_order_b2c_workflow_2'; + const ORDER_WORKFLOW_1 = 'marello_order_b2c_new_workflow_1'; + const ORDER_WORKFLOW_2 = 'marello_order_b2c_new_workflow_2'; } diff --git a/src/Marello/Bundle/OrderBundle/Resources/config/form.yml b/src/Marello/Bundle/OrderBundle/Resources/config/form.yml index 9058b368e..17718fbe8 100644 --- a/src/Marello/Bundle/OrderBundle/Resources/config/form.yml +++ b/src/Marello/Bundle/OrderBundle/Resources/config/form.yml @@ -6,6 +6,14 @@ services: tags: - { name: form.type } + marello_order.form.type.total_paid: + class: Marello\Bundle\OrderBundle\Form\Type\OrderTotalPaidType + arguments: + - '@oro_locale.settings' + - '@oro_currency.config.currency' + tags: + - { name: form.type } + marello_order.form.type.order_update: class: Marello\Bundle\OrderBundle\Form\Type\OrderUpdateType tags: diff --git a/src/Marello/Bundle/OrderBundle/Resources/config/oro/api.yml b/src/Marello/Bundle/OrderBundle/Resources/config/oro/api.yml index 0e33250c1..3e69395ac 100644 --- a/src/Marello/Bundle/OrderBundle/Resources/config/oro/api.yml +++ b/src/Marello/Bundle/OrderBundle/Resources/config/oro/api.yml @@ -60,6 +60,11 @@ api: allow_array: true property_path: order description: 'Filter by order ID' + status_id: + data_type: string + allow_array: true + property_path: status_id + description: 'Filter by status' actions: delete: false delete_list: false diff --git a/src/Marello/Bundle/OrderBundle/Resources/config/oro/datagrids.yml b/src/Marello/Bundle/OrderBundle/Resources/config/oro/datagrids.yml index 677da9169..39c1a5d0c 100644 --- a/src/Marello/Bundle/OrderBundle/Resources/config/oro/datagrids.yml +++ b/src/Marello/Bundle/OrderBundle/Resources/config/oro/datagrids.yml @@ -471,7 +471,7 @@ datagrids: from: - { table: MarelloOrderBundle:OrderItem, alias: oi } join: - left: + inner: - { join: oi.order, alias: o } columns: productSku: diff --git a/src/Marello/Bundle/OrderBundle/Resources/config/oro/workflows.yml b/src/Marello/Bundle/OrderBundle/Resources/config/oro/workflows.yml index ce650eb67..7fe3385f8 100644 --- a/src/Marello/Bundle/OrderBundle/Resources/config/oro/workflows.yml +++ b/src/Marello/Bundle/OrderBundle/Resources/config/oro/workflows.yml @@ -621,3 +621,632 @@ workflows: parameters_mapping: order: $order current_transition: payment_reminder + + marello_order_b2c_new_workflow_1: + entity: Marello\Bundle\OrderBundle\Entity\Order + entity_attribute: order + exclusive_record_groups: [order_b2c] + priority: 5 + defaults: + active: true + + attributes: + payment_reference: + type: string + payment_details: + type: string + total_paid: + type: object + options: + class: Oro\Bundle\CurrencyBundle\Entity\Price + invoiced_at: + type: object + options: + class: \DateTime + note: + type: string + update_balanced_inventory: + type: boolean + steps: + pending: + allowed_transitions: + - invoice + - hold_pending + - cancel + cancelled: + allowed_transitions: [] + pending_on_hold: + allowed_transitions: + - un_hold_pending + invoice_on_hold: + allowed_transitions: + - un_hold_invoice + paid: + allowed_transitions: + - prepare_shipping + invoice: + allowed_transitions: + - hold_invoice + - payment_reminder + - payment_received + pick_and_pack: + allowed_transitions: + - ship + shipped: + allowed_transitions: [] + + transitions: + pending: + step_to: pending + is_start: true + transition_definition: pending_definition + cancel: + step_to: cancelled + transition_definition: cancel_definition + hold_pending: + step_to: pending_on_hold + transition_definition: hold_definition + form_options: + attribute_fields: + note: + form_type: Symfony\Component\Form\Extension\Core\Type\TextareaType + options: + required: false + un_hold_pending: + step_to: pending + transition_definition: un_hold_definition + hold_invoice: + step_to: invoice_on_hold + transition_definition: hold_definition + form_options: + attribute_fields: + note: + form_type: Symfony\Component\Form\Extension\Core\Type\TextareaType + options: + required: false + un_hold_invoice: + step_to: invoice + transition_definition: un_hold_definition + invoice: + step_to: invoice + transition_definition: invoice_definition + form_options: + attribute_fields: + invoiced_at: + form_type: Oro\Bundle\FormBundle\Form\Type\OroDateTimeType + options: + required: true + constraints: + - NotBlank: ~ + - DateTime: ~ + payment_received: + step_to: paid + transition_definition: payment_received_definition + form_options: + attribute_fields: + payment_reference: + form_type: Symfony\Component\Form\Extension\Core\Type\TextType + options: + required: true + constraints: + - NotBlank: ~ + payment_details: + form_type: Symfony\Component\Form\Extension\Core\Type\TextType + options: + required: true + constraints: + - NotBlank: ~ + total_paid: + form_type: Marello\Bundle\OrderBundle\Form\Type\OrderTotalPaidType + options: + required: true + currency: $order.currency + ship: + step_to: shipped + transition_definition: ship_definition + prepare_shipping: + step_to: pick_and_pack + transition_definition: prepare_shipping_definition + payment_reminder: + step_to: invoice + transition_definition: payment_reminder_definition + + transition_definitions: + pending_definition: + actions: + - '@assign_value': + - [$update_balanced_inventory, true] + post_actions: + - '@run_action_group': + action_group: send_order_invoice_email + parameters_mapping: + order: $order + current_transition: pending + - '@run_action_group': + action_group: marello_order_status_change + parameters_mapping: + order: $order + status: 'pending' + cancel_definition: + conditions: + '@and': + - '@sales_channel_has_valid_integration': + salesChannel: $order.salesChannel + actions: + - '@extendable': + events: [extendable_action.order_cancel] + post_actions: + - '@marello_cancel_order': + update_balanced_inventory: $update_balanced_inventory + - '@marello_notification_send': + entity: $order + recipient: $order.customer + template: marello_order_cancelled + - '@run_action_group': + action_group: send_order_invoice_email + parameters_mapping: + order: $order + current_transition: cancel + - '@run_action_group': + action_group: marello_order_status_change + parameters_mapping: + order: $order + status: 'cancelled' + hold_definition: + actions: + - '@tree': + conditions: + '@not_empty': $note + actions: + - '@create_note': + message: $note + target_entity: $order + - '@assign_value': [$note, ~] + post_actions: + - '@run_action_group': + action_group: send_order_invoice_email + parameters_mapping: + order: $order + current_transition: hold + - '@run_action_group': + action_group: marello_order_status_change + parameters_mapping: + order: $order + status: 'hold' + un_hold_definition: + post_actions: + - '@run_action_group': + action_group: send_order_invoice_email + parameters_mapping: + order: $order + current_transition: un_hold + - '@run_action_group': + action_group: marello_order_status_change + parameters_mapping: + order: $order + status: 'processing' + invoice_definition: + conditions: + '@and': + - '@sales_channel_has_valid_integration': + salesChannel: $order.salesChannel + post_actions: + - '@assign_value': + attribute: $order.invoicedAt + value: $invoiced_at + - '@marello_notification_send': + entity: $order + recipient: $order.customer + template: marello_order_invoiced + - '@extendable': + events: [extendable_action.order_invoiced] + - '@run_action_group': + action_group: send_order_invoice_email + parameters_mapping: + order: $order + current_transition: invoice + - '@run_action_group': + action_group: marello_order_status_change + parameters_mapping: + order: $order + status: 'invoiced' + payment_received_definition: + conditions: + '@and': + - '@sales_channel_has_valid_integration': + salesChannel: $order.salesChannel + post_actions: + - '@extendable': + events: [extendable_action.order_paid] + - '@run_action_group': + action_group: send_order_invoice_email + parameters_mapping: + order: $order + current_transition: payment_received + - '@run_action_group': + action_group: marello_order_status_change + parameters_mapping: + order: $order + status: 'paid' + prepare_shipping_definition: + conditions: + '@and': + - '@not_empty': $order.shippingMethod + - '@not_empty': $order.shippingAddress.country + - '@not_empty': $order.shippingAddress.postalCode + - '@not_empty': $order.shippingAddress.city + - '@not_empty': $order.shippingAddress.street + post_actions: + - '@call_service_method': + service: marello_order.factory.shipping_context + method: create + method_parameters: [$order] + attribute: $.result.orderShippingContext + - '@marello_shipment_create': + context: $.result.orderShippingContext + method: $order.shippingMethod + methodType: $order.shippingMethodType + - '@extendable': + events: [extendable_action.create_packingslip] + - '@marello_pick_pack_order': ~ + - '@marello_notification_send': + entity: $order + recipient: $order.customer + template: marello_order_shipping_prepared + - '@run_action_group': + action_group: send_order_invoice_email + parameters_mapping: + order: $order + current_transition: prepare_shipping + - '@run_action_group': + action_group: marello_order_status_change + parameters_mapping: + order: $order + status: 'pick_and_pack' + ship_definition: + conditions: + '@and': + - '@not_empty': $order.shippingAddress.country + - '@not_empty': $order.shippingAddress.postalCode + - '@not_empty': $order.shippingAddress.city + - '@not_empty': $order.shippingAddress.street + - '@sales_channel_has_valid_integration': + salesChannel: $order.salesChannel + post_actions: + - '@extendable': + events: [extendable_action.order_ship] + - '@marello_ship_order': ~ + - '@marello_notification_send': + entity: $order + recipient: $order.customer + template: marello_order_shipped_confirmation + - '@extendable': + events: [extendable_action.order_shipped] + - '@run_action_group': + action_group: send_order_invoice_email + parameters_mapping: + order: $order + current_transition: ship + - '@run_action_group': + action_group: marello_order_status_change + parameters_mapping: + order: $order + status: 'shipped' + payment_reminder_definition: + post_actions: + - '@marello_notification_send': + entity: $order + recipient: $order.customer + template: marello_order_payment_reminder + - '@flash_message': + message: 'Reminder has been sent.' + - '@run_action_group': + action_group: send_order_invoice_email + parameters_mapping: + order: $order + current_transition: payment_reminder + + marello_order_b2c_new_workflow_2: + entity: Marello\Bundle\OrderBundle\Entity\Order + entity_attribute: order + priority: 8 + exclusive_record_groups: [order_b2c] + attributes: + payment_reference: + type: string + payment_details: + type: string + total_paid: + type: object + options: + class: Oro\Bundle\CurrencyBundle\Entity\Price + invoiced_at: + type: object + options: + class: \DateTime + note: + type: string + steps: + pending: + allowed_transitions: + - invoice + invoice: + allowed_transitions: + - prepare_shipping + pick_and_pack: + allowed_transitions: + - ship + shipped: + allowed_transitions: + - payment_received + cancelled: + allowed_transitions: [] + pending_on_hold: + allowed_transitions: + - un_hold_pending + invoice_on_hold: + allowed_transitions: + - un_hold_invoice + paid: + allowed_transitions: [] + transitions: + pending: + step_to: pending + is_start: true + transition_definition: pending_definition + cancel: + step_to: cancelled + transition_definition: cancel_definition + hold_pending: + step_to: pending_on_hold + transition_definition: hold_definition + form_options: + attribute_fields: + note: + form_type: Symfony\Component\Form\Extension\Core\Type\TextAreaType + options: + required: false + un_hold_pending: + step_to: pending + transition_definition: un_hold_definition + hold_invoice: + step_to: invoice_on_hold + transition_definition: hold_definition + form_options: + attribute_fields: + note: + form_type: Symfony\Component\Form\Extension\Core\Type\TextAreaType + options: + required: false + un_hold_invoice: + step_to: invoice + transition_definition: un_hold_definition + invoice: + step_to: invoice + transition_definition: invoice_definition + form_options: + attribute_fields: + invoiced_at: + form_type: Oro\Bundle\FormBundle\Form\Type\OroDateTimeType + options: + required: true + constraints: + - NotBlank: ~ + - DateTime: ~ + payment_received: + step_to: paid + transition_definition: payment_received_definition + form_options: + attribute_fields: + payment_reference: + form_type: Symfony\Component\Form\Extension\Core\Type\TextType + options: + required: true + constraints: + - NotBlank: ~ + payment_details: + form_type: Symfony\Component\Form\Extension\Core\Type\TextType + options: + required: true + constraints: + - NotBlank: ~ + total_paid: + form_type: Marello\Bundle\OrderBundle\Form\Type\OrderTotalPaidType + options: + required: true + currency: $order.currency + ship: + step_to: shipped + transition_definition: ship_definition + prepare_shipping: + step_to: pick_and_pack + transition_definition: prepare_shipping_definition + payment_reminder: + step_to: pending + transition_definition: payment_reminder_definition + + transition_definitions: + pending_definition: + post_actions: + - '@run_action_group': + action_group: send_order_invoice_email + parameters_mapping: + order: $order + current_transition: pending + - '@run_action_group': + action_group: marello_order_status_change + parameters_mapping: + order: $order + status: 'pending' + cancel_definition: + conditions: + '@and': + - '@sales_channel_has_valid_integration': + salesChannel: $order.salesChannel + actions: + - '@extendable': + events: [extendable_action.order_cancel] + post_actions: + - '@marello_cancel_order': ~ + - '@marello_notification_send': + entity: $order + recipient: $order.customer + template: marello_order_cancelled + - '@run_action_group': + action_group: send_order_invoice_email + parameters_mapping: + order: $order + current_transition: cancel + - '@run_action_group': + action_group: marello_order_status_change + parameters_mapping: + order: $order + status: 'cancelled' + hold_definition: + post_actions: + - '@run_action_group': + action_group: send_order_invoice_email + parameters_mapping: + order: $order + current_transition: hold + - '@run_action_group': + action_group: marello_order_status_change + parameters_mapping: + order: $order + status: 'hold' + un_hold_definition: + post_actions: + - '@run_action_group': + action_group: send_order_invoice_email + parameters_mapping: + order: $order + current_transition: un_hold + - '@run_action_group': + action_group: marello_order_status_change + parameters_mapping: + order: $order + status: 'processing' + invoice_definition: + conditions: + '@and': + - '@sales_channel_has_valid_integration': + salesChannel: $order.salesChannel + post_actions: + - '@assign_value': + attribute: $order.invoicedAt + value: $invoiced_at + - '@marello_notification_send': + entity: $order + recipient: $order.customer + template: marello_order_invoiced + - '@extendable': + events: [extendable_action.order_invoiced] + - '@run_action_group': + action_group: send_order_invoice_email + parameters_mapping: + order: $order + current_transition: invoice + - '@run_action_group': + action_group: marello_order_status_change + parameters_mapping: + order: $order + status: 'invoiced' + payment_received_definition: + conditions: + '@and': + - '@sales_channel_has_valid_integration': + salesChannel: $order.salesChannel + post_actions: + - '@marello_notification_send': + entity: $order + recipient: $order.customer + template: marello_order_invoiced + - '@extendable': + events: [extendable_action.order_paid] + - '@run_action_group': + action_group: send_order_invoice_email + parameters_mapping: + order: $order + current_transition: payment_received + - '@run_action_group': + action_group: marello_order_status_change + parameters_mapping: + order: $order + status: 'paid' + prepare_shipping_definition: + conditions: + '@and': + - '@not_empty': $order.shippingMethod + - '@not_empty': $order.shippingAddress.country + - '@not_empty': $order.shippingAddress.postalCode + - '@not_empty': $order.shippingAddress.city + - '@not_empty': $order.shippingAddress.street + post_actions: + - '@call_service_method': + service: marello_order.factory.shipping_context + method: create + method_parameters: [$order] + attribute: $.result.orderShippingContext + - '@marello_shipment_create': + context: $.result.orderShippingContext + method: $order.shippingMethod + methodType: $order.shippingMethodType + - '@extendable': + events: [extendable_action.create_packingslip] + - '@marello_pick_pack_order': ~ + - '@marello_notification_send': + entity: $order + recipient: $order.customer + template: marello_order_shipping_prepared + - '@run_action_group': + action_group: send_order_invoice_email + parameters_mapping: + order: $order + current_transition: prepare_shipping + - '@run_action_group': + action_group: marello_order_status_change + parameters_mapping: + order: $order + status: 'pick_and_pack' + ship_definition: + conditions: + '@and': + - '@not_empty': $order.shippingAddress.country + - '@not_empty': $order.shippingAddress.postalCode + - '@not_empty': $order.shippingAddress.city + - '@not_empty': $order.shippingAddress.street + - '@sales_channel_has_valid_integration': + salesChannel: $order.salesChannel + post_actions: + - '@extendable': + events: [extendable_action.order_ship] + - '@marello_ship_order': ~ + - '@marello_notification_send': + entity: $order + recipient: $order.customer + template: marello_order_shipped_confirmation + - '@extendable': + events: [extendable_action.order_shipped] + - '@run_action_group': + action_group: send_order_invoice_email + parameters_mapping: + order: $order + current_transition: ship + - '@run_action_group': + action_group: marello_order_status_change + parameters_mapping: + order: $order + status: 'shipped' + payment_reminder_definition: + post_actions: + - '@marello_notification_send': + entity: $order + recipient: $order.customer + template: marello_order_payment_reminder + - '@flash_message': + message: 'Reminder has been sent.' + - '@run_action_group': + action_group: send_order_invoice_email + parameters_mapping: + order: $order + current_transition: payment_reminder diff --git a/src/Marello/Bundle/OrderBundle/Resources/doc/api/order.md b/src/Marello/Bundle/OrderBundle/Resources/doc/api/order.md index 70cf8ada3..b536a295c 100644 --- a/src/Marello/Bundle/OrderBundle/Resources/doc/api/order.md +++ b/src/Marello/Bundle/OrderBundle/Resources/doc/api/order.md @@ -44,8 +44,6 @@ Example without address: "grandTotal": "60.5000", "currency": "EUR", "paymentMethod": null, - "paymentReference": null, - "paymentDetails": null, "shippingAmountInclTax": "10.0000", "shippingAmountExclTax": "10.0000", "shippingMethod": null, diff --git a/src/Marello/Bundle/OrderBundle/Resources/public/css/scss/style.scss b/src/Marello/Bundle/OrderBundle/Resources/public/css/scss/style.scss index cd5f123a2..097ad83e5 100644 --- a/src/Marello/Bundle/OrderBundle/Resources/public/css/scss/style.scss +++ b/src/Marello/Bundle/OrderBundle/Resources/public/css/scss/style.scss @@ -29,46 +29,26 @@ width: 315px; } -.order-line-item-quantity { +.order-line-item-tax-code, +.order-line-item-product-unit { width: 243px; input[type="text"] { width:80px; - text-align:right; - float: left; - } -} - -.order-line-item-price { - line-height: 2.3; - width: 243px; - - input[type="text"] { - width:80px; - text-align:right; - padding-left: 17px; - float: left; - } -} - -.order-line-item-tax { - width: 243px; - - input[type="text"] { - width:80px; - text-align:right; - padding-left: 17px; + text-align:left; float: left; } } +.order-line-item-tax, +.order-line-item-price, +.order-line-item-quantity, .order-line-item-total-price { width: 243px; input[type="text"] { width:80px; text-align:right; - padding-left: 17px; float: left; } } diff --git a/src/Marello/Bundle/OrderBundle/Resources/public/js/app/views/order-item-view.js b/src/Marello/Bundle/OrderBundle/Resources/public/js/app/views/order-item-view.js index c4445671e..46e8549eb 100644 --- a/src/Marello/Bundle/OrderBundle/Resources/public/js/app/views/order-item-view.js +++ b/src/Marello/Bundle/OrderBundle/Resources/public/js/app/views/order-item-view.js @@ -92,6 +92,7 @@ define(function(require) { this.fieldsByName.price.val($priceValue); this.fieldsByName.taxCode.val(this.getTaxCode()); + this.fieldsByName.productUnit.val(this.getProductUnit()); this.setRowTotals(); this.setAvailableInventory(); @@ -124,6 +125,13 @@ define(function(require) { return !_.isEmpty(this.data['row_totals'][this.getRowItemIdentifier()]) ? this.data['row_totals'][this.getRowItemIdentifier()] : null; }, + /** + * @returns {Array|Null} + */ + getProductUnit: function() { + return !_.isEmpty(this.data['product_unit']) ? this.data['product_unit'].unit : null; + }, + /** * @returns {Array|Null} */ @@ -152,7 +160,7 @@ define(function(require) { setAvailableInventory: function() { if (this.getProductInventory() === null) { - return + return; } this.fieldsByName.availableInventory.val(this.getProductInventory()); diff --git a/src/Marello/Bundle/OrderBundle/Resources/translations/messages.en.yml b/src/Marello/Bundle/OrderBundle/Resources/translations/messages.en.yml index ec1d8a3fd..52320c3b1 100644 --- a/src/Marello/Bundle/OrderBundle/Resources/translations/messages.en.yml +++ b/src/Marello/Bundle/OrderBundle/Resources/translations/messages.en.yml @@ -59,7 +59,7 @@ marello: edit_action: Edit Address datablock: general: General - billing_and_payment: Billing & Payment + billing_address: Billing Address delivery: Delivery order_items: Order Items activity: Activity @@ -68,6 +68,7 @@ marello: order_totals: Order Totals packing_slips: Packing Slips invoices: Invoices + payments: Payments source_references_information: Source References optional: Optional # OrderItem entity diff --git a/src/Marello/Bundle/OrderBundle/Resources/translations/workflows.en.yml b/src/Marello/Bundle/OrderBundle/Resources/translations/workflows.en.yml index e765e3040..fef518cfa 100644 --- a/src/Marello/Bundle/OrderBundle/Resources/translations/workflows.en.yml +++ b/src/Marello/Bundle/OrderBundle/Resources/translations/workflows.en.yml @@ -1,7 +1,7 @@ oro: workflow: marello_order_b2c_workflow_1: - label: 'Order B2C Workflow #1' + label: 'Order B2C Workflow #1(Deprecated)' attribute: payment_reference: label: 'Payment Reference' @@ -23,7 +23,7 @@ oro: invoice: label: 'Invoiced' paid: - label: 'Order Payed' + label: 'Order Paid' credit: label: 'Closed' pick_and_pack: @@ -57,7 +57,7 @@ oro: label: 'Payment Reminder' marello_order_b2c_workflow_2: - label: 'Order B2C Workflow #2' + label: 'Order B2C Workflow #2(Deprecated)' attribute: payment_reference: label: 'Payment Reference' @@ -79,7 +79,7 @@ oro: invoice: label: 'Complete' paid: - label: 'Order Payed' + label: 'Order Paid' credit: label: 'Closed' pick_and_pack: @@ -115,3 +115,123 @@ oro: label: 'Prepare Shipping' payment_reminder: label: 'Payment Reminder' + + marello_order_b2c_new_workflow_1: + label: 'Order B2C Workflow #1' + attribute: + payment_reference: + label: 'Payment Reference' + payment_details: + label: 'Payment Details' + total_paid: + label: 'Paid Amount' + invoiced_at: + label: 'Invoiced At' + note: + label: 'Note' + step: + pending: + label: 'Pending Order' + cancelled: + label: 'Cancelled' + pending_on_hold: + label: 'On Hold' + invoice_on_hold: + label: 'On Hold' + invoice: + label: 'Invoiced' + paid: + label: 'Order Paid' + credit: + label: 'Closed' + pick_and_pack: + label: 'Pick and Pack' + shipped: + label: 'Complete' + transition: + pending: + label: 'Pending' + cancel: + label: 'Cancel' + hold_pending: + label: 'Hold' + un_hold_pending: + label: 'Un-Hold' + hold_invoice: + label: 'Hold' + un_hold_invoice: + label: 'Un-Hold' + invoice: + label: 'Invoice' + payment_received: + label: 'Payment Received' + ship: + label: 'Ship' + credit: + label: 'Credit' + prepare_shipping: + label: 'Prepare Shipping' + payment_reminder: + label: 'Payment Reminder' + + marello_order_b2c_new_workflow_2: + label: 'Order B2C Workflow #2' + attribute: + payment_reference: + label: 'Payment Reference' + payment_details: + label: 'Payment Details' + total_paid: + label: 'Paid Amount' + invoiced_at: + label: 'Invoiced At' + note: + label: 'Note' + step: + pending: + label: 'Pending Order' + cancelled: + label: 'Cancelled' + pending_on_hold: + label: 'On Hold' + invoice_on_hold: + label: 'On Hold' + invoice: + label: 'Invoiced' + paid: + label: 'Complete' + credit: + label: 'Closed' + pick_and_pack: + label: 'Pick and Pack' + shipped: + label: 'Shipped' + transition: + pending: + label: 'Pending' + cancel: + label: 'Cancel' + hold_pending: + label: 'Hold' + un_hold_pending: + label: 'Un-Hold' + hold_invoice: + label: 'Hold' + un_hold_invoice: + label: 'Un-Hold' + hold_shipped: + label: 'Hold' + un_hold_shipped: + label: 'Un-Hold' + invoice: + label: 'Invoice' + payment_received: + label: 'Payment Received' + ship: + label: 'Ship' + credit: + label: 'Credit' + prepare_shipping: + label: 'Prepare Shipping' + payment_reminder: + label: 'Payment Reminder' \ No newline at end of file diff --git a/src/Marello/Bundle/OrderBundle/Resources/views/Form/fields.html.twig b/src/Marello/Bundle/OrderBundle/Resources/views/Form/fields.html.twig index e25fc6a96..d5907e7a4 100644 --- a/src/Marello/Bundle/OrderBundle/Resources/views/Form/fields.html.twig +++ b/src/Marello/Bundle/OrderBundle/Resources/views/Form/fields.html.twig @@ -17,6 +17,12 @@ {{ form_errors(form.availableInventory) }} + +
+ {{ form_widget(form.productUnit) }} +
+ {{ form_errors(form.productUnit) }} +
{{ form_widget(form.price) }} @@ -29,7 +35,7 @@
{{ form_errors(form.tax) }} - +
{{ form_widget(form.taxCode) }}
@@ -109,6 +115,7 @@ {{ 'marello.product.entity_label'|trans }} {{ 'marello.order.orderitem.quantity.label'|trans }} {{ 'marello.order.orderitem.inventory.label'|trans }} + {{ 'marello.order.orderitem.product_unit.label'|trans }} {{ marello_pricing_vat_aware_label('marello.order.orderitem.price.per_unit.label'|trans) }} {{ 'marello.order.orderitem.tax.label'|trans }} {{ 'marello.order.orderitem.tax_code.label'|trans }} @@ -162,3 +169,15 @@ {{ form_rest(form) }} {% endif %} {% endblock %} + +{% block marello_order_total_paid_widget %} +
+
+ {{ form_widget(form.value) }} + {{ form_widget(form.currency) }} + {{ form_errors(form.value) }} + {{ form_errors(form.currency) }} +
+
+{% endblock %} + diff --git a/src/Marello/Bundle/OrderBundle/Resources/views/Order/view.html.twig b/src/Marello/Bundle/OrderBundle/Resources/views/Order/view.html.twig index 00d4fad59..7a6370dfb 100644 --- a/src/Marello/Bundle/OrderBundle/Resources/views/Order/view.html.twig +++ b/src/Marello/Bundle/OrderBundle/Resources/views/Order/view.html.twig @@ -104,6 +104,8 @@ {{ UI.renderProperty('marello.order.total_tax.label'|trans, entity.totalTax|oro_format_currency({'currency':entity.currency})) }} {{ UI.renderProperty('marello.order.discount_amount.label'|trans, entity.discountAmount|oro_format_currency({'currency':entity.currency})) }} {{ UI.renderProperty('marello.order.grand_total.label'|trans, entity.grandTotal|oro_format_currency({'currency':entity.currency})) }} + {{ UI.renderProperty('marello.invoice.total_paid.label'|trans, marello_get_order_total_paid(entity)|oro_format_currency({'currency':entity.currency})) }} + {{ UI.renderProperty('marello.invoice.total_due.label'|trans, marello_get_order_total_due(entity)|oro_format_currency({'currency':entity.currency})) }} {{ UI.renderProperty('marello.order.coupon_code.label'|trans, entity.couponCode) }} @@ -111,42 +113,24 @@ {% endset %} {% set generalSubblocks = generalSubblocks|merge([{'data' : [totalsWidget] }]) %} - {% set paymentSubblocks = [] %} + {% set billingSubblocks = [] %} {% set billingAddressWidget %} {{ oro_widget_render({ 'widgetType': 'block', 'url': path('marello_order_order_address', {id: entity.billingAddress.id, typeId: 1}), }) }} {% endset %} - {% set paymentSubblocks = paymentSubblocks|merge([{'data' : [billingAddressWidget] }]) %} + {% set billingSubblocks = billingSubblocks|merge([{'data' : [billingAddressWidget] }]) %} - {% set paymentWidget %} + {% set emptyWidget %}
- {{ UI.renderProperty('marello.order.invoiced_at.label'|trans, entity.invoicedAt|oro_format_datetime) }} - {{ UI.renderProperty('marello.order.invoice_reference.label'|trans, entity.invoiceReference) }} -
- -
-
- {% include marello_payment_method_config_template(entity.paymentMethod) with { - 'currency': null, - 'methodData': { - 'identifier': entity.paymentMethod, - 'options': entity.paymentMethodOptions, - } - } %} -
-
-
- {{ UI.renderProperty('marello.order.payment_reference.label'|trans, entity.paymentReference) }} - {{ UI.renderHtmlProperty('marello.order.payment_details.label'|trans, entity.paymentDetails|nl2br) }}
{% endset %} - {% set paymentSubblocks = paymentSubblocks|merge([{'data' : [paymentWidget] }]) %} + {% set billingSubblocks = billingSubblocks|merge([{'data' : [emptyWidget] }]) %} {% set shippingSubblocks = [] %} {% set shippingAddressWidget %} @@ -182,6 +166,10 @@ {{ dataGrid.renderGrid('marello-order-invoices-grid', {'orderId': entity.id}) }} {% endset %} + {% set payments %} + {{ dataGrid.renderGrid('marello-order-payments-grid', {'orderId': entity.id}) }} + {% endset %} + {% set optionalWidget %}
@@ -201,9 +189,9 @@ 'subblocks': generalSubblocks }, { - 'title': 'marello.order.datablock.billing_and_payment'|trans, + 'title': 'marello.order.datablock.billing_address'|trans, 'class': 'active', - 'subblocks': paymentSubblocks + 'subblocks': billingSubblocks }, { 'title': 'marello.order.datablock.delivery'|trans, @@ -221,8 +209,15 @@ 'title': 'marello.order.datablock.invoices'|trans, 'class': 'active', 'subblocks': [ - { 'data' : [invoices] } - ] + { 'data' : [invoices] } + ] + }, + { + 'title': 'marello.order.datablock.payments'|trans, + 'class': 'active', + 'subblocks': [ + { 'data' : [payments] } + ] }, { 'title': 'marello.order.datablock.packing_slips'|trans, diff --git a/src/Marello/Bundle/OrderBundle/Tests/Functional/Api/requests/order_create_with_existing_customer.yml b/src/Marello/Bundle/OrderBundle/Tests/Functional/Api/requests/order_create_with_existing_customer.yml index 66e901df3..c05c9714d 100644 --- a/src/Marello/Bundle/OrderBundle/Tests/Functional/Api/requests/order_create_with_existing_customer.yml +++ b/src/Marello/Bundle/OrderBundle/Tests/Functional/Api/requests/order_create_with_existing_customer.yml @@ -8,8 +8,6 @@ data: grandTotal: 101 currency: 'USD' paymentMethod: 'payment_term_1' - paymentReference: null - paymentDetails: null shippingAmountInclTax: null shippingAmountExclTax: null shippingMethod: 'manual_shipping_1' diff --git a/src/Marello/Bundle/OrderBundle/Tests/Functional/Api/requests/order_create_with_new_customer.yml b/src/Marello/Bundle/OrderBundle/Tests/Functional/Api/requests/order_create_with_new_customer.yml index 9b2b771ad..8f93aa5b7 100644 --- a/src/Marello/Bundle/OrderBundle/Tests/Functional/Api/requests/order_create_with_new_customer.yml +++ b/src/Marello/Bundle/OrderBundle/Tests/Functional/Api/requests/order_create_with_new_customer.yml @@ -19,7 +19,7 @@ data: data: - type: marelloorderitems - id: 'items->first()->id)>' + id: '8da4d8e7-6b25-4c5c-8075-nh3fpu9sca3htc3v' customer: data: type: marellocustomers @@ -35,4 +35,27 @@ included: attributes: firstName: 'test' lastName: 'user' - email: 'new_customer@example.com' \ No newline at end of file + email: 'new_customer@example.com' + - + type: marelloorderitems + id: '8da4d8e7-6b25-4c5c-8075-nh3fpu9sca3htc3v' + attributes: + quantity: 10 + productName: 'name)>' + price: 0 + originalPriceInclTax: 0 + originalPriceExclTax: 0 + purchasePriceIncl: 0 + tax: 0 + taxPercent: 0.21 + rowTotalInclTax: 180.00 + rowTotalExclTax: 180.00 + relationships: + product: + data: + type: marelloproducts + id: 'sku)>' + taxCode: + data: + type: marellotaxcodes + id: 'TAX_HIGH' \ No newline at end of file diff --git a/src/Marello/Bundle/OrderBundle/Tests/Functional/Api/responses/cget_order_list.yml b/src/Marello/Bundle/OrderBundle/Tests/Functional/Api/responses/cget_order_list.yml index 9fb62c1a1..b5404d927 100644 --- a/src/Marello/Bundle/OrderBundle/Tests/Functional/Api/responses/cget_order_list.yml +++ b/src/Marello/Bundle/OrderBundle/Tests/Functional/Api/responses/cget_order_list.yml @@ -11,8 +11,6 @@ data: grandTotal: '280.0000' currency: USD paymentMethod: 'Credit Card' - paymentReference: null - paymentDetails: 'American Express refnr. 371449635398431' shippingAmountInclTax: '0.0000' shippingAmountExclTax: '0.0000' shippingMethod: null @@ -26,10 +24,10 @@ data: salesChannelName: channel2 purchaseDate: '@marello_order_0->purchaseDate->format("Y-m-d\TH:i:s\Z")' data: null - workflowItem: - currentStep: - name: pending - label: 'Pending Order' + #workflowItem: + # currentStep: + # name: pending + # label: 'Pending Order' relationships: items: data: @@ -72,8 +70,6 @@ data: grandTotal: '1511.0000' currency: GBP paymentMethod: Paypal - paymentReference: null - paymentDetails: null shippingAmountInclTax: '10.0000' shippingAmountExclTax: '10.0000' shippingMethod: null @@ -87,10 +83,10 @@ data: salesChannelName: channel3 purchaseDate: '@marello_order_1->purchaseDate->format("Y-m-d\TH:i:s\Z")' data: null - workflowItem: - currentStep: - name: pending - label: 'Pending Order' + #workflowItem: + # currentStep: + # name: pending + # label: 'Pending Order' relationships: items: data: @@ -142,8 +138,6 @@ data: grandTotal: '1110.0000' currency: USD paymentMethod: 'Credit Card' - paymentReference: null - paymentDetails: 'American Express refnr. 371449635398431' shippingAmountInclTax: '0.0000' shippingAmountExclTax: '0.0000' shippingMethod: null @@ -157,10 +151,10 @@ data: salesChannelName: channel2 purchaseDate: '@marello_order_2->purchaseDate->format("Y-m-d\TH:i:s\Z")' data: null - workflowItem: - currentStep: - name: pending - label: 'Pending Order' + #workflowItem: + # currentStep: + # name: pending + # label: 'Pending Order' relationships: items: data: @@ -209,8 +203,6 @@ data: grandTotal: '2030.0000' currency: GBP paymentMethod: Paypal - paymentReference: null - paymentDetails: null shippingAmountInclTax: '0.0000' shippingAmountExclTax: '0.0000' shippingMethod: null @@ -224,10 +216,10 @@ data: salesChannelName: channel3 purchaseDate: '@marello_order_3->purchaseDate->format("Y-m-d\TH:i:s\Z")' data: null - workflowItem: - currentStep: - name: pending - label: 'Pending Order' + #workflowItem: + # currentStep: + # name: pending + # label: 'Pending Order' relationships: items: data: @@ -279,8 +271,6 @@ data: grandTotal: '455.0000' currency: GBP paymentMethod: 'Credit Card' - paymentReference: null - paymentDetails: 'Visa refnr. 4012888888881881' shippingAmountInclTax: '5.0000' shippingAmountExclTax: '5.0000' shippingMethod: null @@ -294,10 +284,10 @@ data: salesChannelName: channel3 purchaseDate: '@marello_order_4->purchaseDate->format("Y-m-d\TH:i:s\Z")' data: null - workflowItem: - currentStep: - name: pending - label: 'Pending Order' + #workflowItem: + # currentStep: + # name: pending + # label: 'Pending Order' relationships: items: data: @@ -340,8 +330,6 @@ data: grandTotal: '920.2500' currency: GBP paymentMethod: Paypal - paymentReference: null - paymentDetails: null shippingAmountInclTax: '0.0000' shippingAmountExclTax: '0.0000' shippingMethod: null @@ -355,10 +343,10 @@ data: salesChannelName: channel3 purchaseDate: '@marello_order_5->purchaseDate->format("Y-m-d\TH:i:s\Z")' data: null - workflowItem: - currentStep: - name: pending - label: 'Pending Order' + #workflowItem: + # currentStep: + # name: pending + # label: 'Pending Order' relationships: items: data: @@ -404,8 +392,6 @@ data: grandTotal: '1595.0000' currency: GBP paymentMethod: Paypal - paymentReference: null - paymentDetails: null shippingAmountInclTax: '5.0000' shippingAmountExclTax: '5.0000' shippingMethod: null @@ -419,10 +405,10 @@ data: salesChannelName: channel3 purchaseDate: '@marello_order_6->purchaseDate->format("Y-m-d\TH:i:s\Z")' data: null - workflowItem: - currentStep: - name: pending - label: 'Pending Order' + #workflowItem: + # currentStep: + # name: pending + # label: 'Pending Order' relationships: items: data: @@ -474,8 +460,6 @@ data: grandTotal: '635.0000' currency: USD paymentMethod: 'Credit Card' - paymentReference: null - paymentDetails: 'Visa refnr. 4012888888881881' shippingAmountInclTax: '5.0000' shippingAmountExclTax: '5.0000' shippingMethod: null @@ -489,10 +473,10 @@ data: salesChannelName: channel2 purchaseDate: '@marello_order_7->purchaseDate->format("Y-m-d\TH:i:s\Z")' data: null - workflowItem: - currentStep: - name: pending - label: 'Pending Order' + #workflowItem: + # currentStep: + # name: pending + # label: 'Pending Order' relationships: items: data: @@ -535,8 +519,6 @@ data: grandTotal: '430.0000' currency: USD paymentMethod: 'Credit Card' - paymentReference: null - paymentDetails: 'Visa refnr. 4012888888881881' shippingAmountInclTax: '5.0000' shippingAmountExclTax: '5.0000' shippingMethod: null @@ -550,10 +532,10 @@ data: salesChannelName: channel2 purchaseDate: '@marello_order_8->purchaseDate->format("Y-m-d\TH:i:s\Z")' data: null - workflowItem: - currentStep: - name: pending - label: 'Pending Order' + #workflowItem: + # currentStep: + # name: pending + # label: 'Pending Order' relationships: items: data: @@ -599,8 +581,6 @@ data: grandTotal: '0.0000' currency: EUR paymentMethod: 'Credit Card' - paymentReference: null - paymentDetails: 'Master Card refnr. 5105105105105100' shippingAmountInclTax: '10.0000' shippingAmountExclTax: '10.0000' shippingMethod: null @@ -614,10 +594,10 @@ data: salesChannelName: channel1 purchaseDate: '@marello_order_9->purchaseDate->format("Y-m-d\TH:i:s\Z")' data: null - workflowItem: - currentStep: - name: pending - label: 'Pending Order' + #workflowItem: + # currentStep: + # name: pending + # label: 'Pending Order' relationships: items: data: diff --git a/src/Marello/Bundle/OrderBundle/Tests/Functional/Api/responses/get_order_by_id.yml b/src/Marello/Bundle/OrderBundle/Tests/Functional/Api/responses/get_order_by_id.yml index 2fa1f090e..58d628478 100644 --- a/src/Marello/Bundle/OrderBundle/Tests/Functional/Api/responses/get_order_by_id.yml +++ b/src/Marello/Bundle/OrderBundle/Tests/Functional/Api/responses/get_order_by_id.yml @@ -10,8 +10,6 @@ data: grandTotal: '1511.0000' currency: GBP paymentMethod: Paypal - paymentReference: null - paymentDetails: null shippingAmountInclTax: '10.0000' shippingAmountExclTax: '10.0000' shippingMethod: null @@ -25,10 +23,10 @@ data: salesChannelName: channel3 purchaseDate: '@marello_order_1->purchaseDate->format("Y-m-d\TH:i:s\Z")' data: null - workflowItem: - currentStep: - name: pending - label: 'Pending Order' + #workflowItem: + # currentStep: + # name: pending + # label: 'Pending Order' relationships: items: data: diff --git a/src/Marello/Bundle/OrderBundle/Tests/Functional/Api/responses/get_order_by_orderNumber.yml b/src/Marello/Bundle/OrderBundle/Tests/Functional/Api/responses/get_order_by_orderNumber.yml index 2fa1f090e..58d628478 100644 --- a/src/Marello/Bundle/OrderBundle/Tests/Functional/Api/responses/get_order_by_orderNumber.yml +++ b/src/Marello/Bundle/OrderBundle/Tests/Functional/Api/responses/get_order_by_orderNumber.yml @@ -10,8 +10,6 @@ data: grandTotal: '1511.0000' currency: GBP paymentMethod: Paypal - paymentReference: null - paymentDetails: null shippingAmountInclTax: '10.0000' shippingAmountExclTax: '10.0000' shippingMethod: null @@ -25,10 +23,10 @@ data: salesChannelName: channel3 purchaseDate: '@marello_order_1->purchaseDate->format("Y-m-d\TH:i:s\Z")' data: null - workflowItem: - currentStep: - name: pending - label: 'Pending Order' + #workflowItem: + # currentStep: + # name: pending + # label: 'Pending Order' relationships: items: data: diff --git a/src/Marello/Bundle/OrderBundle/Tests/Functional/Controller/OrderOnDemandWorkflowTest.php b/src/Marello/Bundle/OrderBundle/Tests/Functional/Controller/OrderOnDemandWorkflowTest.php index c2d6b56c2..ee1b53ed0 100644 --- a/src/Marello/Bundle/OrderBundle/Tests/Functional/Controller/OrderOnDemandWorkflowTest.php +++ b/src/Marello/Bundle/OrderBundle/Tests/Functional/Controller/OrderOnDemandWorkflowTest.php @@ -24,6 +24,9 @@ use Symfony\Component\DomCrawler\Form; use Symfony\Component\HttpFoundation\Response; +/** + * @dbIsolationPerTest + */ class OrderOnDemandWorkflowTest extends WebTestCase { public function setUp() @@ -142,9 +145,19 @@ public function testWorkflow() $this->assertEmpty($beforePackingSlips); $workflowManager = $this->getContainer()->get('oro_workflow.manager'); - $orderWorkflowItem = $workflowManager->getWorkflowItem($order, 'marello_order_b2c_workflow_1'); - $workflowManager->transit($orderWorkflowItem, 'payment_received'); + $orderWorkflowItem = $workflowManager->getWorkflowItem($order, 'marello_order_b2c_new_workflow_1'); + if (!$orderWorkflowItem) { + $orderWorkflowItem = $workflowManager + ->startWorkflow('marello_order_b2c_new_workflow_1', $order, 'pending'); + } $workflowManager->transit($orderWorkflowItem, 'invoice'); + $data = $orderWorkflowItem->getData(); + $data + ->set('payment_reference', 'payment_reference') + ->set('payment_details', 'payment_details') + ->set('total_paid', 100); + $orderWorkflowItem->setData($data); + $workflowManager->transit($orderWorkflowItem, 'payment_received'); $workflowManager->transit($orderWorkflowItem, 'prepare_shipping'); $workflowManager->transit($orderWorkflowItem, 'ship'); diff --git a/src/Marello/Bundle/OrderBundle/Tests/Functional/DataFixtures/LoadOrderData.php b/src/Marello/Bundle/OrderBundle/Tests/Functional/DataFixtures/LoadOrderData.php index ff483b75c..f457039a8 100644 --- a/src/Marello/Bundle/OrderBundle/Tests/Functional/DataFixtures/LoadOrderData.php +++ b/src/Marello/Bundle/OrderBundle/Tests/Functional/DataFixtures/LoadOrderData.php @@ -232,9 +232,6 @@ protected function createOrder($row, Organization $organization) } $orderEntity->setPaymentMethod($row['payment_method']); - if ($row['payment_details'] !== 'NULL') { - $orderEntity->setPaymentDetails($row['payment_details']); - } $orderEntity->setShippingAmountExclTax($row['shipping_amount']); $orderEntity->setShippingAmountInclTax($row['shipping_amount']); @@ -254,7 +251,7 @@ protected function createOrderItem($row, Organization $organization) /** @var Product $product */ $product = $this->manager ->getRepository('MarelloProductBundle:Product') - ->findOneBy(['sku' => $row['sku']]); + ->findOneBy(['sku' => $row['sku'], 'organization' => $organization]); $itemEntity = new OrderItem(); $itemEntity->setProduct($product); diff --git a/src/Marello/Bundle/OrderBundle/Tests/Functional/EventListener/Doctrine/OrderWorkflowStartListenerTest.php b/src/Marello/Bundle/OrderBundle/Tests/Functional/EventListener/Doctrine/OrderWorkflowStartListenerTest.php index be407c0b2..9d982abf9 100644 --- a/src/Marello/Bundle/OrderBundle/Tests/Functional/EventListener/Doctrine/OrderWorkflowStartListenerTest.php +++ b/src/Marello/Bundle/OrderBundle/Tests/Functional/EventListener/Doctrine/OrderWorkflowStartListenerTest.php @@ -53,7 +53,7 @@ public function testOrderHasSingleWorkflowStartedByDefault() $workflowManager = $this->getContainer()->get('oro_workflow.manager'); $workflowItems = $workflowManager->getWorkflowItemsByEntity($order); - self::assertCount(1, $workflowItems); + self::assertCount(0, $workflowItems); } /** @@ -67,10 +67,10 @@ public function testWorkflowStartedIsDefaultWorkflow() $workflowManager = $this->getContainer()->get('oro_workflow.manager'); $workflowItems = $workflowManager->getWorkflowItemsByEntity($order); - self::assertCount(1, $workflowItems); + self::assertCount(0, $workflowItems); /** @var WorkflowItem $workflowItem */ - $workflowItem = array_shift($workflowItems); - self::assertEquals(WorkflowNameProviderInterface::ORDER_WORKFLOW_1, $workflowItem->getWorkflowName()); + //$workflowItem = array_shift($workflowItems); + //self::assertEquals(WorkflowNameProviderInterface::ORDER_WORKFLOW_1, $workflowItem->getWorkflowName()); } /** diff --git a/src/Marello/Bundle/OrderBundle/Tests/Unit/Entity/OrderTest.php b/src/Marello/Bundle/OrderBundle/Tests/Unit/Entity/OrderTest.php index 22227c963..8664df8e3 100644 --- a/src/Marello/Bundle/OrderBundle/Tests/Unit/Entity/OrderTest.php +++ b/src/Marello/Bundle/OrderBundle/Tests/Unit/Entity/OrderTest.php @@ -30,8 +30,6 @@ public function testAccessors() ['grandTotal', 42], ['currency', 'some string'], ['paymentMethod', 'some string'], - ['paymentReference', 'some string'], - ['paymentDetails', 'some string'], ['shippingAmountInclTax', 'some string'], ['shippingAmountExclTax', 'some string'], ['shippingMethod', 3.1415926], diff --git a/src/Marello/Bundle/OrderBundle/Tests/Unit/Twig/OrderExtensionTest.php b/src/Marello/Bundle/OrderBundle/Tests/Unit/Twig/OrderExtensionTest.php index 67d17df54..6b6a719e6 100644 --- a/src/Marello/Bundle/OrderBundle/Tests/Unit/Twig/OrderExtensionTest.php +++ b/src/Marello/Bundle/OrderBundle/Tests/Unit/Twig/OrderExtensionTest.php @@ -64,13 +64,15 @@ public function testNameIsCorrectlySetAndReturnedFromConstant() public function testGetFunctionsAreRegisteredInExtension() { $functions = $this->extension->getFunctions(); - $this->assertCount(4, $functions); + $this->assertCount(6, $functions); $expectedFunctions = array( 'marello_order_can_return', 'marello_order_item_shipped', 'marello_get_order_item_status', - 'marello_get_order_items_for_notification' + 'marello_get_order_items_for_notification', + 'marello_get_order_total_paid', + 'marello_get_order_total_due' ); /** @var \Twig_SimpleFunction $function */ diff --git a/src/Marello/Bundle/OrderBundle/Twig/OrderExtension.php b/src/Marello/Bundle/OrderBundle/Twig/OrderExtension.php index 4f0a2bcce..0022f2150 100644 --- a/src/Marello/Bundle/OrderBundle/Twig/OrderExtension.php +++ b/src/Marello/Bundle/OrderBundle/Twig/OrderExtension.php @@ -3,6 +3,7 @@ namespace Marello\Bundle\OrderBundle\Twig; use Doctrine\Bundle\DoctrineBundle\Registry; +use Marello\Bundle\InvoiceBundle\Entity\AbstractInvoice; use Marello\Bundle\OrderBundle\Entity\Order; use Marello\Bundle\OrderBundle\Entity\OrderItem; use Marello\Bundle\OrderBundle\Migrations\Data\ORM\LoadOrderItemStatusData; @@ -15,12 +16,21 @@ class OrderExtension extends AbstractExtension { const NAME = 'marello_order'; - /** @var Registry $doctrine */ + /** + * @var Registry + */ private $doctrine; - /** @var ShippingPreparedOrderItemsForNotificationProvider $orderItemsForNotificationProvider*/ + /** + * @var ShippingPreparedOrderItemsForNotificationProvider + */ private $orderItemsForNotificationProvider; + /** + * @var array + */ + private $orderInvoices; + /** * Returns the name of the extension. * @@ -54,6 +64,14 @@ public function getFunctions() new TwigFunction( 'marello_get_order_items_for_notification', [$this->orderItemsForNotificationProvider, 'getItems'] + ), + new TwigFunction( + 'marello_get_order_total_paid', + [$this, 'getOrderTotalPaid'] + ), + new TwigFunction( + 'marello_get_order_total_due', + [$this, 'getOrderTotalDue'] ) ]; } @@ -143,4 +161,43 @@ public function setItemsForNotificationProvider( return $this; } + + /** + * @param Order $order + * @return AbstractInvoice[] + */ + private function getOrderInvoices(Order $order) + { + if (!isset($this->orderInvoices[$order->getId()])) { + $this->orderInvoices[$order->getId()] = $this->doctrine + ->getManagerForClass(AbstractInvoice::class) + ->getRepository(AbstractInvoice::class) + ->findBy(['order' => $order]); + } + + return $this->orderInvoices[$order->getId()]; + } + + /** + * @param Order $order + * @return float|int + */ + public function getOrderTotalPaid(Order $order) + { + $orderInvoices = $this->getOrderInvoices($order); + $totalPaid = 0.0; + foreach ($orderInvoices as $invoice) { + $totalPaid += $invoice->getTotalPaid(); + } + + return $totalPaid; + } + /** + * @param Order $order + * @return float|int + */ + public function getOrderTotalDue(Order $order) + { + return ($order->getGrandTotal() - $this->getOrderTotalPaid($order)); + } } diff --git a/src/Marello/Bundle/PackingBundle/Mapper/OrderToPackingSlipMapper.php b/src/Marello/Bundle/PackingBundle/Mapper/OrderToPackingSlipMapper.php index da18b686e..c3c937bd6 100644 --- a/src/Marello/Bundle/PackingBundle/Mapper/OrderToPackingSlipMapper.php +++ b/src/Marello/Bundle/PackingBundle/Mapper/OrderToPackingSlipMapper.php @@ -108,7 +108,7 @@ protected function mapItem(OrderItem $orderItem, Warehouse $warehouse) if ($inventoryBatch->getQuantity() >= $quantity) { $data[$inventoryBatch->getBatchNumber()] = $quantity; break; - } elseif ($batchQty = $inventoryBatch->getQuantity() > 0) { + } elseif (($batchQty = $inventoryBatch->getQuantity()) > 0) { $data[$inventoryBatch->getBatchNumber()] = $batchQty; $quantity = $quantity - $batchQty; } diff --git a/src/Marello/Bundle/PackingBundle/Tests/Unit/Mapper/OrderToPackingSlipMapperTest.php b/src/Marello/Bundle/PackingBundle/Tests/Unit/Mapper/OrderToPackingSlipMapperTest.php index 8e03942fb..25e592a8f 100644 --- a/src/Marello/Bundle/PackingBundle/Tests/Unit/Mapper/OrderToPackingSlipMapperTest.php +++ b/src/Marello/Bundle/PackingBundle/Tests/Unit/Mapper/OrderToPackingSlipMapperTest.php @@ -122,19 +122,19 @@ public function testMap() 'product' => $product1, 'inventoryBatches' => ['000001' => 5], 'quantity' => $orderItem1->getQuantity(), - 'weight' => $product1->getWeight() + 'weight' => ($orderItem1->getQuantity() * $product1->getWeight()) ]), $this->getEntity(PackingSlipItem::class, [ 'orderItem' => $orderItem2, 'product' => $product2, 'quantity' => $orderItem2->getQuantity(), - 'weight' => $product2->getWeight() + 'weight' => ($orderItem2->getQuantity() * $product2->getWeight()) ]), $this->getEntity(PackingSlipItem::class, [ 'orderItem' => $orderItem3, 'product' => $product3, 'quantity' => $orderItem3->getQuantity(), - 'weight' => $product3->getWeight() + 'weight' => ($orderItem3->getQuantity() * $product3->getWeight()) ]), ]; diff --git a/src/Marello/Bundle/PaymentBundle/Action/Handler/AddPaymentActionHandler.php b/src/Marello/Bundle/PaymentBundle/Action/Handler/AddPaymentActionHandler.php new file mode 100644 index 000000000..0eaeb3d16 --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Action/Handler/AddPaymentActionHandler.php @@ -0,0 +1,104 @@ +entityManager = $entityManager; + $this->invoicePaidAmountProvider = $invoicePaidAmountProvider; + } + + /** + * @param AbstractInvoice $entity + * @param string $paymentMethod + * @param \DateTime $paymentDate + * @param string $paymentReference + * @param string $paymentDetails + * @param float $paidTotal + * @return array + */ + public function handleAction( + AbstractInvoice $entity, + $paymentMethod, + \DateTime $paymentDate, + $paymentReference, + $paymentDetails, + $paidTotal + ) { + $paidTotalBefore = $this->invoicePaidAmountProvider->getPaidAmount($entity); + $paidTotalAfter = $paidTotalBefore + $paidTotal; + if ($paidTotalAfter > $entity->getGrandTotal()) { + return [ + 'type' => 'error', + 'message' => 'marello.payment.message.add_payment.error.paid_total_exceed' + ]; + } + $payment = new Payment(); + $payment + ->setPaymentMethod($paymentMethod) + ->setPaymentDate($paymentDate) + ->setPaymentReference($paymentReference) + ->setPaymentDetails($paymentDetails) + ->setTotalPaid($paidTotal) + ->setCurrency($entity->getCurrency()) + ->setStatus($this->findStatusByName(LoadPaymentStatusData::ASSIGNED)) + ->setOrganization($entity->getOrganization()); + $order = $entity->getOrder(); + if ($order && $paymentMethod === $order->getPaymentMethod()) { + $payment->setPaymentMethodOptions($order->getPaymentMethodOptions()); + } + $entity->addPayment($payment); + $this->entityManager->persist($entity); + $this->entityManager->flush(); + + return [ + 'type' => 'success', + 'message' => 'marello.payment.message.add_payment.success' + ]; + } + + /** + * @param string $name + * @return null|object + */ + private function findStatusByName($name) + { + $statusClass = ExtendHelper::buildEnumValueClassName( + LoadPaymentStatusData::PAYMENT_STATUS_ENUM_CLASS + ); + $status = $this->entityManager + ->getRepository($statusClass) + ->find($name); + + if ($status) { + return $status; + } + + return null; + } +} diff --git a/src/Marello/Bundle/PaymentBundle/Controller/PaymentAjaxController.php b/src/Marello/Bundle/PaymentBundle/Controller/PaymentAjaxController.php new file mode 100644 index 000000000..daf0a1f30 --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Controller/PaymentAjaxController.php @@ -0,0 +1,66 @@ +getType($payment); + $submittedData = $request->get($form->getName()); + + $form->submit($submittedData); + + $context = new FormChangeContext( + [ + FormChangeContext::FORM_FIELD => $form, + FormChangeContext::SUBMITTED_DATA_FIELD => $submittedData, + FormChangeContext::RESULT_FIELD => [], + ] + ); + + $formChangesProvider = $this->get('marello_layout.provider.form_changes_data.composite'); + $formChangesProvider + ->setRequiredDataClass(Payment::class) + ->setRequiredFields($request->get('updateFields', [])) + ->processFormChanges($context); + + return new JsonResponse($context->getResult()); + } + + /** + * @param Payment $payment + * @return FormInterface + */ + protected function getType(Payment $payment) + { + return $this->createForm(PaymentCreateType::class, $payment); + } +} diff --git a/src/Marello/Bundle/PaymentBundle/Controller/PaymentController.php b/src/Marello/Bundle/PaymentBundle/Controller/PaymentController.php new file mode 100644 index 000000000..34d4ee58f --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Controller/PaymentController.php @@ -0,0 +1,116 @@ + Payment::class + ]; + } + + /** + * @Route(path="/view/{id}", name="marello_payment_view", requirements={"id"="\d+"}) + * @Template("MarelloPaymentBundle:Payment:view.html.twig") + * @Acl( + * id="marello_payment_view", + * type="entity", + * class="MarelloPaymentBundle:Payment", + * permission="VIEW" + * ) + * + * @param Payment $payment + * + * @return array + */ + public function viewAction(Payment $payment) + { + return [ + 'entity' => $payment, + ]; + } + + /** + * @Route(path="/create", name="marello_payment_create") + * @Template("MarelloPaymentBundle:Payment:create.html.twig") + * @Acl( + * id="marello_payment_create", + * type="entity", + * permission="CREATE", + * class="MarelloPaymentBundle:Payment" + * ) + * @param Request $request + * + * @return array + */ + public function createAction(Request $request) + { + return $this->update($request); + } + + /** + * @Route(path="/update/{id}", name="marello_payment_update", requirements={"id"="\d+"}) + * @Template("MarelloPaymentBundle:Payment:update.html.twig") + * @Acl( + * id="marello_payment_update", + * type="entity", + * permission="EDIT", + * class="MarelloPaymentBundle:Payment" + * ) + * @param Request $request + * @param Payment $entity + * + * @return array + */ + public function updateAction(Request $request, Payment $entity) + { + return $this->update($request, $entity); + } + + /** + * @param Request $request + * @param Payment|null $entity + * @return array|RedirectResponse + */ + protected function update(Request $request, Payment $entity = null) + { + if ($entity === null) { + $entity = new Payment(); + $handler = $this->get('marello_payment.form.handler.payment_create'); + } else { + $handler = $this->get('marello_payment.form.handler.payment_update'); + } + + if ($handler->process($entity)) { + $this->get('session')->getFlashBag()->add( + 'success', + $this->get('translator')->trans('marello.payment_term.ui.payment_term.saved.message') + ); + + return $this->get('oro_ui.router')->redirect($entity); + } + + return [ + 'entity' => $entity, + 'form' => $handler->getFormView(), + ]; + } +} diff --git a/src/Marello/Bundle/PaymentBundle/Controller/PaymentMethodsConfigsRuleController.php b/src/Marello/Bundle/PaymentBundle/Controller/PaymentMethodsConfigsRuleController.php index 8be34b42e..5c4e27580 100644 --- a/src/Marello/Bundle/PaymentBundle/Controller/PaymentMethodsConfigsRuleController.php +++ b/src/Marello/Bundle/PaymentBundle/Controller/PaymentMethodsConfigsRuleController.php @@ -2,18 +2,18 @@ namespace Marello\Bundle\PaymentBundle\Controller; -use Oro\Bundle\DataGridBundle\Extension\MassAction\MassActionDispatcher; use Marello\Bundle\PaymentBundle\Entity\PaymentMethodsConfigsRule; use Marello\Bundle\PaymentBundle\Form\Handler\PaymentMethodsConfigsRuleHandler; use Marello\Bundle\PaymentBundle\Form\Type\PaymentMethodsConfigsRuleType; +use Oro\Bundle\DataGridBundle\Extension\MassAction\MassActionDispatcher; use Oro\Bundle\SecurityBundle\Annotation\Acl; use Oro\Bundle\SecurityBundle\Annotation\AclAncestor; use Oro\Bundle\SecurityBundle\Annotation\CsrfProtection; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Routing\Annotation\Route; /** * Payment Methods Configs Rule Controller @@ -21,7 +21,7 @@ class PaymentMethodsConfigsRuleController extends AbstractController { /** - * @Route("/", name="marello_payment_methods_configs_rule_index") + * @Route(path="/", name="marello_payment_methods_configs_rule_index") * @Template("MarelloPaymentBundle:PaymentMethodsConfigsRule:index.html.twig") * @AclAncestor("marello_payment_methods_configs_rule_view") * @@ -35,7 +35,7 @@ public function indexAction() } /** - * @Route("/create", name="marello_payment_methods_configs_rule_create") + * @Route(path="/create", name="marello_payment_methods_configs_rule_create") * @Template("MarelloPaymentBundle:PaymentMethodsConfigsRule:update.html.twig") * @Acl( * id="marello_payment_methods_configs_rule_create", @@ -53,7 +53,7 @@ public function createAction(Request $request) } /** - * @Route("/view/{id}", name="marello_payment_methods_configs_rule_view", requirements={"id"="\d+"}) + * @Route(path="/view/{id}", name="marello_payment_methods_configs_rule_view", requirements={"id"="\d+"}) * @Template("MarelloPaymentBundle:PaymentMethodsConfigsRule:view.html.twig") * @Acl( * id="marello_payment_methods_configs_rule_view", @@ -74,7 +74,7 @@ public function viewAction(PaymentMethodsConfigsRule $paymentMethodsConfigsRule) } /** - * @Route("/update/{id}", name="marello_payment_methods_configs_rule_update", requirements={"id"="\d+"}) + * @Route(path="/update/{id}", name="marello_payment_methods_configs_rule_update", requirements={"id"="\d+"}) * @Template("MarelloPaymentBundle:PaymentMethodsConfigsRule:update.html.twig") * @Acl( * id="marello_payment_methods_configs_rule_update", @@ -122,7 +122,7 @@ protected function update(PaymentMethodsConfigsRule $entity, Request $request) } /** - * @Route("/{gridName}/massAction/{actionName}", name="marello_payment_methods_configs_massaction") + * @Route(path="/{gridName}/massAction/{actionName}", name="marello_payment_methods_configs_massaction") * @Acl( * id="marello_payment_methods_configs_update", * type="entity", diff --git a/src/Marello/Bundle/PaymentBundle/Entity/Payment.php b/src/Marello/Bundle/PaymentBundle/Entity/Payment.php new file mode 100644 index 000000000..7b78e1b93 --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Entity/Payment.php @@ -0,0 +1,356 @@ +id) { + $this->id = null; + } + } + + /** + * @return int + */ + public function getId() + { + return $this->id; + } + + /** + * @return AbstractInvoice|null + */ + public function getPaymentSource() + { + return $this->paymentSource; + } + + /** + * @param AbstractInvoice|null $paymentSource + * @return $this + */ + public function setPaymentSource(AbstractInvoice $paymentSource = null) + { + $this->paymentSource = $paymentSource; + + return $this; + } + + /** + * @return int + */ + public function getTotalPaid() + { + return $this->totalPaid; + } + + /** + * @param int $totalPaid + * + * @return $this + */ + public function setTotalPaid($totalPaid) + { + $this->totalPaid = $totalPaid; + + return $this; + } + + /** + * @return string + */ + public function getPaymentMethod() + { + return $this->paymentMethod; + } + + /** + * @param string $paymentMethod + * + * @return $this + */ + public function setPaymentMethod($paymentMethod) + { + $this->paymentMethod = $paymentMethod; + + return $this; + } + + /** + * @return array + */ + public function getPaymentMethodOptions() + { + return $this->paymentMethodOptions; + } + + /** + * @param array $paymentMethodOptions + * @return $this + */ + public function setPaymentMethodOptions(array $paymentMethodOptions) + { + $this->paymentMethodOptions = $paymentMethodOptions; + + return $this; + } + + /** + * @return string + */ + public function getPaymentDetails() + { + return $this->paymentDetails; + } + + /** + * @param string $paymentDetails + * + * @return $this + */ + public function setPaymentDetails($paymentDetails) + { + $this->paymentDetails = $paymentDetails; + + return $this; + } + + /** + * @return string + */ + public function getPaymentReference() + { + return $this->paymentReference; + } + + /** + * @param string $paymentReference + * + * @return $this + */ + public function setPaymentReference($paymentReference) + { + $this->paymentReference = $paymentReference; + + return $this; + } + + /** + * @return \DateTime + */ + public function getPaymentDate() + { + return $this->paymentDate ? : $this->createdAt; + } + + /** + * @param \DateTime|null $paymentDate + * @return $this + */ + public function setPaymentDate(\DateTime $paymentDate = null) + { + $this->paymentDate = $paymentDate; + + return $this; + } + + /** + * @return string + */ + public function getCurrency() + { + return $this->currency; + } + + /** + * @param string $currency + * + * @return $this + */ + public function setCurrency($currency) + { + $this->currency = $currency; + + return $this; + } + + /** + * @return \Extend\Entity\EV_Marello_Payment_Status + */ + public function getStatus() + { + return $this->status; + } + + /** + * @param string $status + * @return $this + */ + public function setStatus($status) + { + $this->status = $status; + + return $this; + } +} diff --git a/src/Marello/Bundle/PaymentBundle/EventListener/PaymentCreationListener.php b/src/Marello/Bundle/PaymentBundle/EventListener/PaymentCreationListener.php new file mode 100644 index 000000000..0e1681945 --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/EventListener/PaymentCreationListener.php @@ -0,0 +1,103 @@ +doctrineHelper = $doctrineHelper; + } + + /** + * @param ExtendableActionEvent $event + */ + public function onOrderPaid(ExtendableActionEvent $event) + { + if (!$this->isCorrectOrderContext($event->getContext())) { + return; + } + $data = $event->getContext()->getData(); + /** @var Order $entity */ + $entity = $data->get('order'); + $entityManager = $this->doctrineHelper->getEntityManagerForClass(Invoice::class); + /** @var Invoice $invoice */ + $invoice = $entityManager + ->getRepository(Invoice::class) + ->findOneBy(['order' => $entity]); + if ($invoice) { + $totalPaid = $data->get('total_paid'); + if ($totalPaid instanceof Price) { + $totalPaid = $totalPaid->getValue(); + } + $payment = new Payment(); + $payment + ->setPaymentMethod($entity->getPaymentMethod()) + ->setPaymentMethodOptions($entity->getPaymentMethodOptions()) + ->setPaymentReference($data->get('payment_reference')) + ->setPaymentDetails($data->get('payment_details')) + ->setTotalPaid($totalPaid) + ->setCurrency($entity->getCurrency() ? : $invoice->getCurrency()) + ->setPaymentDate(new \DateTime('now', new \DateTimeZone('UTC'))) + ->setOrganization($entity->getOrganization()) + ->setStatus($this->findStatusByName(LoadPaymentStatusData::ASSIGNED)); + + $invoice->addPayment($payment); + $entityManager->persist($invoice); + $entityManager->flush(); + } + } + + /** + * @param mixed $context + * @return bool + */ + protected function isCorrectOrderContext($context) + { + return ($context instanceof WorkflowItem + && $context->getData() instanceof WorkflowData + && $context->getData()->has('order') + && $context->getData()->get('order') instanceof Order + ); + } + + /** + * @param string $name + * @return null|object + */ + private function findStatusByName($name) + { + $statusClass = ExtendHelper::buildEnumValueClassName( + LoadPaymentStatusData::PAYMENT_STATUS_ENUM_CLASS + ); + $status = $this->doctrineHelper + ->getEntityManagerForClass($statusClass) + ->getRepository($statusClass) + ->find($name); + + if ($status) { + return $status; + } + + return null; + } +} diff --git a/src/Marello/Bundle/PaymentBundle/Form/Handler/PaymentCreateHandler.php b/src/Marello/Bundle/PaymentBundle/Form/Handler/PaymentCreateHandler.php new file mode 100644 index 000000000..9f7b28d49 --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Form/Handler/PaymentCreateHandler.php @@ -0,0 +1,88 @@ +form = $form; + $this->request = $requestStack->getCurrentRequest(); + $this->manager = $manager; + } + + /** + * @param Payment $entity + * + * @return bool True on successful processing, false otherwise + */ + public function process(Payment $entity) + { + $this->form->setData($entity); + + if (in_array($this->request->getMethod(), ['POST', 'PUT'])) { + $this->submitPostPutRequest($this->form, $this->request); + if ($this->form->isValid()) { + $this->onSuccess($entity); + + return true; + } + } + + return false; + } + + /** + * @param Payment $entity + */ + protected function onSuccess(Payment $entity) + { + $this->manager->persist($entity); + $this->manager->flush(); + $paymentSource = $this->form->get('paymentSource')->getData(); + if ($paymentSource instanceof AbstractInvoice) { + $paymentSource->addPayment($entity); + $this->manager->persist($paymentSource); + $this->manager->flush(); + } + } + + /** + * Returns form instance + * + * @return FormView + */ + public function getFormView() + { + return $this->form->createView(); + } +} diff --git a/src/Marello/Bundle/PaymentBundle/Form/Handler/PaymentUpdateHandler.php b/src/Marello/Bundle/PaymentBundle/Form/Handler/PaymentUpdateHandler.php new file mode 100644 index 000000000..dd4684e75 --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Form/Handler/PaymentUpdateHandler.php @@ -0,0 +1,81 @@ +form = $form; + $this->request = $requestStack->getCurrentRequest(); + $this->manager = $manager; + } + + /** + * @param Payment $entity + * + * @return bool True on successful processing, false otherwise + */ + public function process(Payment $entity) + { + $this->form->setData($entity); + + if (in_array($this->request->getMethod(), ['POST', 'PUT'])) { + $this->submitPostPutRequest($this->form, $this->request); + if ($this->form->isValid()) { + $this->onSuccess($entity); + + return true; + } + } + + return false; + } + + /** + * @param Payment $entity + */ + protected function onSuccess(Payment $entity) + { + $this->manager->persist($entity); + $this->manager->flush(); + } + + /** + * Returns form instance + * + * @return FormView + */ + public function getFormView() + { + return $this->form->createView(); + } +} diff --git a/src/Marello/Bundle/PaymentBundle/Form/Type/PaymentCreateType.php b/src/Marello/Bundle/PaymentBundle/Form/Type/PaymentCreateType.php new file mode 100644 index 000000000..08a91e5f3 --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Form/Type/PaymentCreateType.php @@ -0,0 +1,210 @@ +registry = $registry; + $this->paymentMethodChoicesProvider = $paymentMethodChoicesProvider; + } + + + /** + * {@inheritdoc} + */ + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder + ->add( + 'paymentSource', + InvoiceSelectType::class, + [ + 'label' => 'marello.payment.payment_source.label', + 'required' => false, + 'placeholder' => 'Choose Related Entity', + 'empty_data' => null, + 'query_builder' => function (AbstractInvoiceRepository $repository) { + return $repository->createQueryBuilder('invoice') + ->where('invoice.totalPaid < invoice.grandTotal'); + }, + ] + ) + ->add( + 'paymentMethod', + PaymentMethodSelectType::class, + [ + 'label' => 'marello.payment.payment_method.label', + 'required' => true, + 'constraints' => new NotNull, + ] + ) + ->add( + 'paymentDate', + OroDateTimeType::class, + [ + 'label' => 'marello.payment.payment_date.label', + 'required' => true, + ] + ) + ->add( + 'paymentReference', + TextType::class, + [ + 'label' => 'marello.payment.payment_reference.label', + 'required' => false + ] + ) + ->add( + 'paymentDetails', + TextType::class, + [ + 'label' => 'marello.payment.payment_details.label', + 'required' => false + ] + ) + ->add( + 'totalPaid', + OrderTotalPaidType::class, + [ + 'label' => 'marello.payment.total_paid.label', + 'required' => true, + 'mapped' => false + ] + ) + ->add( + 'currency', + HiddenType::class + ); + $builder->addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event) { + $form = $event->getForm(); + $paymentSource = $form->get('paymentSource')->getData(); + if ($paymentSource instanceof AbstractInvoice) { + $sourcePaymentMethod = $paymentSource->getPaymentMethod(); + if ($sourcePaymentMethod) { + $allPaymentMethods = $this->paymentMethodChoicesProvider->getMethods(); + $choices = [$allPaymentMethods[$sourcePaymentMethod] => $sourcePaymentMethod]; + $form->remove('paymentMethod'); + $form->add( + 'paymentMethod', + PaymentMethodSelectType::class, + [ + 'label' => 'marello.payment.payment_method.label', + 'required' => true, + 'choices' => $choices, + 'constraints' => new NotNull, + ] + ); + } + if ($paymentSource->getCurrency()) { + $form->remove('totalPaid'); + $form->add( + 'totalPaid', + OrderTotalPaidType::class, + [ + 'label' => 'marello.payment.total_paid.label', + 'required' => true, + 'mapped' => false, + 'currency' => $paymentSource->getCurrency() + ] + ); + } + } + }); + $builder->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) { + $payment = $event->getData(); + if ($payment instanceof Payment) { + $form = $event->getForm(); + $totalPaid = $form->get('totalPaid')->getData(); + if ($totalPaid instanceof Price) { + $payment + ->setTotalPaid($totalPaid->getValue()) + ->setCurrency($totalPaid->getCurrency()); + } + $paymentSource = $form->get('paymentSource')->getData(); + if (!$paymentSource) { + $payment->setStatus($this->getStatus(LoadPaymentStatusData::UNASSIGNED)); + } else { + $payment->setStatus($this->getStatus(LoadPaymentStatusData::ASSIGNED)); + } + } + $event->setData($payment); + }); + } + + /** + * {@inheritdoc} + */ + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + 'data_class' => Payment::class, + 'constraints' => [new Valid()] + ]); + } + + /** + * {@inheritdoc} + */ + public function getBlockPrefix() + { + return self::BLOCK_PREFIX; + } + + /** + * @param string $name + * @return null|object + */ + private function getStatus($name) + { + $statusClass = ExtendHelper::buildEnumValueClassName(LoadPaymentStatusData::PAYMENT_STATUS_ENUM_CLASS); + $status = $this->registry + ->getManagerForClass($statusClass) + ->getRepository($statusClass) + ->find($name); + + if ($status) { + return $status; + } + + return null; + } +} diff --git a/src/Marello/Bundle/PaymentBundle/Form/Type/PaymentUpdateType.php b/src/Marello/Bundle/PaymentBundle/Form/Type/PaymentUpdateType.php new file mode 100644 index 000000000..60509ec1e --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Form/Type/PaymentUpdateType.php @@ -0,0 +1,215 @@ +registry = $registry; + } + + /** + * {@inheritdoc} + */ + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder + ->add( + 'status', + EnumSelectType::class, + [ + 'label' => 'marello.payment.status.label', + 'enum_code' => 'marello_paymnt_status', + 'configs' => ['allowClear' => false] + ] + ) + ->add( + 'paymentSource', + InvoiceSelectType::class, + [ + 'label' => 'marello.payment.payment_source.label', + 'required' => true, + 'placeholder' => 'Choose Related Entity', + 'empty_data' => null + ] + ) + ->add( + 'paymentReference', + TextType::class, + [ + 'label' => 'marello.payment.payment_reference.label', + 'required' => false + ] + ) + ->add( + 'paymentDetails', + TextType::class, + [ + 'label' => 'marello.payment.payment_details.label', + 'required' => false + ] + ); + $builder->addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event) { + /** @var Payment $payment */ + $payment = $event->getData(); + if ($payment) { + $form = $event->getForm(); + if ($payment->getStatus() && $payment->getStatus()->getId() == LoadPaymentStatusData::ASSIGNED) { + $form->remove('status'); + $form->add( + 'status', + EnumSelectType::class, + [ + 'label' => 'marello.payment.status.label', + 'disabled' => true, + 'enum_code' => 'marello_paymnt_status', + 'configs' => ['allowClear' => false] + ] + ); + $form->remove('paymentSource'); + $form->add( + 'paymentSource', + InvoiceSelectType::class, + [ + 'label' => 'marello.payment.payment_source.label', + 'required' => true, + 'mapped' => false, + 'disabled' => true, + 'placeholder' => 'Choose Related Entity', + 'empty_data' => null, + ] + ); + } else { + $currency = $payment->getCurrency(); + $form->remove('paymentSource'); + $form->add( + 'paymentSource', + InvoiceSelectType::class, + [ + 'label' => 'marello.payment.payment_source.label', + 'required' => true, + 'mapped' => false, + 'placeholder' => 'Choose Related Entity', + 'empty_data' => null, + 'query_builder' => function (AbstractInvoiceRepository $repository) use ($currency) { + return $repository->createQueryBuilder('invoice') + ->where('invoice.currency = :currency') + ->andWhere('invoice.totalPaid < invoice.grandTotal') + ->setParameter('currency', $currency); + }, + ] + ); + } + $source = $this->registry + ->getManagerForClass(AbstractInvoice::class) + ->getRepository(AbstractInvoice::class) + ->findOneByPayment($payment); + if ($source) { + $form->get('paymentSource')->setData($source); + } + } + }); + $builder->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) { + /** @var Payment $payment */ + $payment = $event->getData(); + $form = $event->getForm(); + $source = $form->get('paymentSource')->getData(); + if ($source instanceof AbstractInvoice) { + $payment->setPaymentSource($source); + } + if ($source) { + $payment->setStatus($this->getStatus(LoadPaymentStatusData::ASSIGNED)); + } + + $event->setData($payment); + }); + $builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) { + /** @var Payment $payment */ + $payment = $event->getData(); + if ($payment) { + $form = $event->getForm(); + $newSource = $form->get('paymentSource')->getData(); + $oldSource = $this->registry + ->getManagerForClass(AbstractInvoice::class) + ->getRepository(AbstractInvoice::class) + ->findOneByPayment($payment); + if ($newSource !== $oldSource) { + $em = $this->registry->getManagerForClass(AbstractInvoice::class); + if ($oldSource) { + $oldSource->removePayment($payment); + $em->persist($oldSource); + $em->flush(); + } + $newSource->addPayment($payment); + $em->persist($newSource); + $em->flush(); + } + } + }); + } + + /** + * {@inheritdoc} + */ + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + 'data_class' => Payment::class, + 'constraints' => [new Valid()] + ]); + } + + /** + * {@inheritdoc} + */ + public function getBlockPrefix() + { + return self::BLOCK_PREFIX; + } + + /** + * @param string $name + * @return null|object + */ + private function getStatus($name) + { + $statusClass = ExtendHelper::buildEnumValueClassName(LoadPaymentStatusData::PAYMENT_STATUS_ENUM_CLASS); + $status = $this->registry + ->getManagerForClass($statusClass) + ->getRepository($statusClass) + ->find($name); + + if ($status) { + return $status; + } + + return null; + } +} diff --git a/src/Marello/Bundle/PaymentBundle/Migrations/Data/ORM/LoadPaymentStatusData.php b/src/Marello/Bundle/PaymentBundle/Migrations/Data/ORM/LoadPaymentStatusData.php new file mode 100644 index 000000000..e6000b5d4 --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Migrations/Data/ORM/LoadPaymentStatusData.php @@ -0,0 +1,41 @@ + true, + 'Unassigned' => false, + ]; + + /** + * @param ObjectManager $manager + */ + public function load(ObjectManager $manager) + { + $className = ExtendHelper::buildEnumValueClassName(self::PAYMENT_STATUS_ENUM_CLASS); + + /** @var EnumValueRepository $enumRepo */ + $enumRepo = $manager->getRepository($className); + + $priority = 1; + foreach ($this->data as $name => $isDefault) { + $enumOption = $enumRepo->createEnumValue($name, $priority++, $isDefault); + $manager->persist($enumOption); + } + + $manager->flush(); + } +} diff --git a/src/Marello/Bundle/PaymentBundle/Migrations/Schema/MarelloPaymentBundleInstaller.php b/src/Marello/Bundle/PaymentBundle/Migrations/Schema/MarelloPaymentBundleInstaller.php index b82aee0bd..c5cc4c0a0 100644 --- a/src/Marello/Bundle/PaymentBundle/Migrations/Schema/MarelloPaymentBundleInstaller.php +++ b/src/Marello/Bundle/PaymentBundle/Migrations/Schema/MarelloPaymentBundleInstaller.php @@ -5,25 +5,36 @@ use Doctrine\DBAL\Schema\Schema; use Oro\Bundle\ActivityBundle\Migration\Extension\ActivityExtension; use Oro\Bundle\ActivityBundle\Migration\Extension\ActivityExtensionAwareInterface; +use Oro\Bundle\EntityExtendBundle\EntityConfig\ExtendScope; +use Oro\Bundle\EntityExtendBundle\Migration\Extension\ExtendExtension; +use Oro\Bundle\EntityExtendBundle\Migration\Extension\ExtendExtensionAwareInterface; use Oro\Bundle\MigrationBundle\Migration\Installation; use Oro\Bundle\MigrationBundle\Migration\QueryBag; /** * @SuppressWarnings(PHPMD.TooManyMethods) */ -class MarelloPaymentBundleInstaller implements Installation, ActivityExtensionAwareInterface +class MarelloPaymentBundleInstaller implements + Installation, + ActivityExtensionAwareInterface, + ExtendExtensionAwareInterface { /** * @var ActivityExtension */ protected $activityExtension; + /** + * @var ExtendExtension + */ + protected $extendExtension; + /** * {@inheritdoc} */ public function getMigrationVersion() { - return 'v1_0'; + return 'v2_0'; } /** @@ -31,15 +42,58 @@ public function getMigrationVersion() */ public function up(Schema $schema, QueryBag $queries) { + $this->createMarelloPaymentPaymentTable($schema); $this->createMarelloPaymentMethodConfigTable($schema); $this->createMarelloPaymentMethodsConfigsRuleTable($schema); $this->createMarelloPaymentMethodsConfigsRuleDestinationTable($schema); $this->createMarelloPaymentMethodsConfigsRuleDestinationPostalCodeTable($schema); - $this->addOroPaymentMethodConfigForeignKeys($schema); - $this->addOroPaymentMethodsConfigsRuleForeignKeys($schema); - $this->addOroPaymentMethodsConfigsRuleDestinationForeignKeys($schema); - $this->addOroPaymentMethodsConfigsRuleDestinationPostalCodeForeignKeys($schema); + $this->addMarelloPaymentPaymentForeignKeys($schema); + $this->addMarelloPaymentMethodConfigForeignKeys($schema); + $this->addMarelloPaymentMethodConfigForeignKeys($schema); + $this->addMarelloPaymentMethodsConfigsRuleForeignKeys($schema); + $this->addMarelloPaymentMethodsConfigsRuleDestinationForeignKeys($schema); + $this->addMarelloPaymentMethodsConfigsRuleDestinationPostalCodeForeignKeys($schema); + } + + /** + * Create marello_payment_payment table + * + * @param Schema $schema + */ + protected function createMarelloPaymentPaymentTable(Schema $schema) + { + $table = $schema->createTable('marello_payment_payment'); + $table->addColumn('id', 'integer', ['autoincrement' => true]); + $table->addColumn('organization_id', 'integer', ['notnull' => false]); + $table->addColumn('payment_method', 'string', ['notnull' => false, 'length' => 255]); + $table->addColumn( + 'payment_method_options', + 'json_array', + [ + 'notnull' => false, 'comment' => '(DC2Type:json_array)' + ] + ); + $table->addColumn('payment_reference', 'string', ['notnull' => false, 'length' => 255]); + $table->addColumn('payment_details', 'text', ['notnull' => false]); + $table->addColumn('total_paid', 'money', ['precision' => 19, 'scale' => 4, 'comment' => '(DC2Type:money)']); + $table->addColumn('payment_date', 'datetime', ['notnull' => false, 'comment' => '(DC2Type:datetime)']); + $table->addColumn('currency', 'string', ['notnull' => false, 'length' => 10]); + $table->addColumn('created_at', 'datetime'); + $table->addColumn('updated_at', 'datetime', ['notnull' => false]); + $this->extendExtension->addEnumField( + $schema, + $table, + 'status', + 'marello_paymnt_status', + false, + false, + [ + 'extend' => ['owner' => ExtendScope::OWNER_SYSTEM], + ] + ); + $table->setPrimaryKey(['id']); + $table->addIndex(['organization_id']); } /** @@ -107,13 +161,29 @@ protected function createMarelloPaymentMethodsConfigsRuleDestinationPostalCodeTa $table->addColumn('name', 'text', []); $table->setPrimaryKey(['id']); } - + + /** + * Add marello_payment_payment foreign keys. + * + * @param Schema $schema + */ + protected function addMarelloPaymentPaymentForeignKeys(Schema $schema) + { + $table = $schema->getTable('marello_payment_payment'); + $table->addForeignKeyConstraint( + $schema->getTable('oro_organization'), + ['organization_id'], + ['id'], + ['onDelete' => 'SET NULL', 'onUpdate' => null] + ); + } + /** * Add marello_payment_method_config foreign keys. * * @param Schema $schema */ - protected function addOroPaymentMethodConfigForeignKeys(Schema $schema) + protected function addMarelloPaymentMethodConfigForeignKeys(Schema $schema) { $table = $schema->getTable('marello_payment_method_config'); $table->addForeignKeyConstraint( @@ -129,7 +199,7 @@ protected function addOroPaymentMethodConfigForeignKeys(Schema $schema) * * @param Schema $schema */ - protected function addOroPaymentMethodsConfigsRuleForeignKeys(Schema $schema) + protected function addMarelloPaymentMethodsConfigsRuleForeignKeys(Schema $schema) { $table = $schema->getTable('marello_payment_mtds_cfgs_rl'); $table->addForeignKeyConstraint( @@ -152,7 +222,7 @@ protected function addOroPaymentMethodsConfigsRuleForeignKeys(Schema $schema) * * @param Schema $schema */ - protected function addOroPaymentMethodsConfigsRuleDestinationForeignKeys(Schema $schema) + protected function addMarelloPaymentMethodsConfigsRuleDestinationForeignKeys(Schema $schema) { $table = $schema->getTable('marello_payment_mtds_cfgs_rl_d'); $table->addForeignKeyConstraint( @@ -180,7 +250,7 @@ protected function addOroPaymentMethodsConfigsRuleDestinationForeignKeys(Schema * * @param Schema $schema */ - protected function addOroPaymentMethodsConfigsRuleDestinationPostalCodeForeignKeys(Schema $schema) + protected function addMarelloPaymentMethodsConfigsRuleDestinationPostalCodeForeignKeys(Schema $schema) { $table = $schema->getTable('marello_pmnt_mtdscfgsrl_dst_pc'); $table->addForeignKeyConstraint( @@ -200,4 +270,14 @@ public function setActivityExtension(ActivityExtension $activityExtension) { $this->activityExtension = $activityExtension; } + + /** + * Sets the ExtendExtension + * + * @param ExtendExtension $extendExtension + */ + public function setExtendExtension(ExtendExtension $extendExtension) + { + $this->extendExtension = $extendExtension; + } } diff --git a/src/Marello/Bundle/PaymentBundle/Migrations/Schema/v1_0/MarelloPaymentBundle.php b/src/Marello/Bundle/PaymentBundle/Migrations/Schema/v1_0/MarelloPaymentBundle.php index 4442fe6ad..a1428d450 100644 --- a/src/Marello/Bundle/PaymentBundle/Migrations/Schema/v1_0/MarelloPaymentBundle.php +++ b/src/Marello/Bundle/PaymentBundle/Migrations/Schema/v1_0/MarelloPaymentBundle.php @@ -11,7 +11,7 @@ /** * @SuppressWarnings(PHPMD.TooManyMethods) */ -class MarelloPaymentBundleInstaller implements Migration, ActivityExtensionAwareInterface +class MarelloPaymentBundle implements Migration, ActivityExtensionAwareInterface { /** * @var ActivityExtension @@ -28,10 +28,10 @@ public function up(Schema $schema, QueryBag $queries) $this->createMarelloPaymentMethodsConfigsRuleDestinationTable($schema); $this->createMarelloPaymentMethodsConfigsRuleDestinationPostalCodeTable($schema); - $this->addOroPaymentMethodConfigForeignKeys($schema); - $this->addOroPaymentMethodsConfigsRuleForeignKeys($schema); - $this->addOroPaymentMethodsConfigsRuleDestinationForeignKeys($schema); - $this->addOroPaymentMethodsConfigsRuleDestinationPostalCodeForeignKeys($schema); + $this->addMarelloPaymentMethodConfigForeignKeys($schema); + $this->addMarelloPaymentMethodsConfigsRuleForeignKeys($schema); + $this->addMarelloPaymentMethodsConfigsRuleDestinationForeignKeys($schema); + $this->addMarelloPaymentMethodsConfigsRuleDestinationPostalCodeForeignKeys($schema); } /** @@ -105,7 +105,7 @@ protected function createMarelloPaymentMethodsConfigsRuleDestinationPostalCodeTa * * @param Schema $schema */ - protected function addOroPaymentMethodConfigForeignKeys(Schema $schema) + protected function addMarelloPaymentMethodConfigForeignKeys(Schema $schema) { $table = $schema->getTable('marello_payment_method_config'); $table->addForeignKeyConstraint( @@ -121,7 +121,7 @@ protected function addOroPaymentMethodConfigForeignKeys(Schema $schema) * * @param Schema $schema */ - protected function addOroPaymentMethodsConfigsRuleForeignKeys(Schema $schema) + protected function addMarelloPaymentMethodsConfigsRuleForeignKeys(Schema $schema) { $table = $schema->getTable('marello_payment_mtds_cfgs_rl'); $table->addForeignKeyConstraint( @@ -144,7 +144,7 @@ protected function addOroPaymentMethodsConfigsRuleForeignKeys(Schema $schema) * * @param Schema $schema */ - protected function addOroPaymentMethodsConfigsRuleDestinationForeignKeys(Schema $schema) + protected function addMarelloPaymentMethodsConfigsRuleDestinationForeignKeys(Schema $schema) { $table = $schema->getTable('marello_payment_mtds_cfgs_rl_d'); $table->addForeignKeyConstraint( @@ -172,7 +172,7 @@ protected function addOroPaymentMethodsConfigsRuleDestinationForeignKeys(Schema * * @param Schema $schema */ - protected function addOroPaymentMethodsConfigsRuleDestinationPostalCodeForeignKeys(Schema $schema) + protected function addMarelloPaymentMethodsConfigsRuleDestinationPostalCodeForeignKeys(Schema $schema) { $table = $schema->getTable('marello_pmnt_mtdscfgsrl_dst_pc'); $table->addForeignKeyConstraint( diff --git a/src/Marello/Bundle/PaymentBundle/Migrations/Schema/v2_0/MarelloPaymentBundle.php b/src/Marello/Bundle/PaymentBundle/Migrations/Schema/v2_0/MarelloPaymentBundle.php new file mode 100644 index 000000000..37c9f97fa --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Migrations/Schema/v2_0/MarelloPaymentBundle.php @@ -0,0 +1,97 @@ +createMarelloPaymentPaymentTable($schema); + + $this->addMarelloPaymentPaymentForeignKeys($schema); + } + + /** + * Create marello_payment_payment table + * + * @param Schema $schema + */ + protected function createMarelloPaymentPaymentTable(Schema $schema) + { + $table = $schema->createTable('marello_payment_payment'); + $table->addColumn('id', 'integer', ['autoincrement' => true]); + $table->addColumn('organization_id', 'integer', ['notnull' => false]); + $table->addColumn('payment_method', 'string', ['notnull' => false, 'length' => 255]); + $table->addColumn( + 'payment_method_options', + 'json_array', + [ + 'notnull' => false, 'comment' => '(DC2Type:json_array)' + ] + ); + $table->addColumn('payment_reference', 'string', ['notnull' => false, 'length' => 255]); + $table->addColumn('payment_details', 'text', ['notnull' => false]); + $table->addColumn('total_paid', 'money', ['precision' => 19, 'scale' => 4, 'comment' => '(DC2Type:money)']); + $table->addColumn('payment_date', 'datetime', ['notnull' => false, 'comment' => '(DC2Type:datetime)']); + $table->addColumn('currency', 'string', ['notnull' => false, 'length' => 10]); + $table->addColumn('created_at', 'datetime'); + $table->addColumn('updated_at', 'datetime', ['notnull' => false]); + $this->extendExtension->addEnumField( + $schema, + $table, + 'status', + 'marello_paymnt_status', + false, + false, + [ + 'extend' => ['owner' => ExtendScope::OWNER_SYSTEM], + ] + ); + $table->setPrimaryKey(['id']); + $table->addIndex(['organization_id']); + } + + /** + * Add marello_payment_payment foreign keys. + * + * @param Schema $schema + */ + protected function addMarelloPaymentPaymentForeignKeys(Schema $schema) + { + $table = $schema->getTable('marello_payment_payment'); + $table->addForeignKeyConstraint( + $schema->getTable('oro_organization'), + ['organization_id'], + ['id'], + ['onDelete' => 'SET NULL', 'onUpdate' => null] + ); + } + + /** + * Sets the ExtendExtension + * + * @param ExtendExtension $extendExtension + */ + public function setExtendExtension(ExtendExtension $extendExtension) + { + $this->extendExtension = $extendExtension; + } +} diff --git a/src/Marello/Bundle/PaymentBundle/Model/ExtendPayment.php b/src/Marello/Bundle/PaymentBundle/Model/ExtendPayment.php new file mode 100644 index 000000000..6383964d9 --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Model/ExtendPayment.php @@ -0,0 +1,10 @@ +localeSettings = $localeSettings; + $this->currencyListProvider = $currencyListProvider; + } + + /** + * @inheritDoc + */ + public function processFormChanges(FormChangeContextInterface $context) + { + $form = $context->getForm(); + $invoice = $form->get('paymentSource')->getData(); + $result = $context->getResult(); + $currencyChoices = []; + if ($invoice instanceof AbstractInvoice) { + $currencyChoices[$this->localeSettings->getCurrencySymbolByCurrency($invoice->getCurrency())] = + $invoice->getCurrency(); + } else { + foreach ($this->currencyListProvider->getCurrencyList() as $currency) { + $currencyChoices[$this->localeSettings->getCurrencySymbolByCurrency($currency)] = + $currency; + } + } + $result[self::FIELD] = $currencyChoices; + $context->setResult($result); + } +} diff --git a/src/Marello/Bundle/PaymentBundle/Provider/FormChanges/AvailablePaymentMethodsFormChangesProvider.php b/src/Marello/Bundle/PaymentBundle/Provider/FormChanges/AvailablePaymentMethodsFormChangesProvider.php new file mode 100644 index 000000000..cd3f52dbf --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Provider/FormChanges/AvailablePaymentMethodsFormChangesProvider.php @@ -0,0 +1,108 @@ +templatingEngine = $templatingEngine; + $this->formFactory = $formFactory; + $this->paymentMethodChoicesProvider = $paymentMethodChoicesProvider; + } + + /** + * {@inheritdoc} + */ + public function processFormChanges(FormChangeContextInterface $context) + { + $form = $context->getForm(); + if ($form->has('paymentMethod')) { + $paymentFormName = $form->getName(); + $paymentSource = $form->get('paymentSource')->getData(); + if ($paymentSource instanceof AbstractInvoice) { + $sourcePaymentMethod = $paymentSource->getPaymentMethod(); + if ($sourcePaymentMethod) { + $allPaymentMethods = $this->paymentMethodChoicesProvider->getMethods(); + $choices = [$allPaymentMethods[$sourcePaymentMethod] => $sourcePaymentMethod]; + $form = $this->formFactory + ->createNamedBuilder($paymentFormName) + ->add( + 'paymentMethod', + PaymentMethodSelectType::class, + [ + 'label' => 'marello.payment.payment_method.label', + 'required' => true, + 'choices' => $choices, + 'constraints' => new NotNull, + ] + ) + ->getForm(); + } + } else { + $form = $this->formFactory + ->createNamedBuilder($paymentFormName) + ->add( + 'paymentMethod', + PaymentMethodSelectType::class, + [ + 'label' => 'marello.payment.payment_method.label', + 'required' => true, + 'constraints' => new NotNull, + ] + ) + ->getForm(); + } + + $result = $context->getResult(); + $result[self::FIELD] = $this->renderForm($form->createView()); + $context->setResult($result); + } + } + + /** + * @param FormView $formView + * @return string + */ + protected function renderForm(FormView $formView) + { + return $this + ->templatingEngine + ->render('MarelloPaymentBundle:Form:paymentMethodSelector.html.twig', ['form' => $formView]); + } +} diff --git a/src/Marello/Bundle/PaymentBundle/Resources/config/jsmodules.yml b/src/Marello/Bundle/PaymentBundle/Resources/config/jsmodules.yml index 93452c960..fbf99e521 100644 --- a/src/Marello/Bundle/PaymentBundle/Resources/config/jsmodules.yml +++ b/src/Marello/Bundle/PaymentBundle/Resources/config/jsmodules.yml @@ -1,3 +1,6 @@ dynamic-imports: marellopayment: - - marellopayment/js/app/views/payment-rule-method-view \ No newline at end of file + - marellopayment/js/app/views/payment-rule-method-view + - marellopayment/js/app/views/payment-method-view + - marellopayment/js/app/views/payment-source-view + - marellopayment/js/app/views/total-paid-view \ No newline at end of file diff --git a/src/Marello/Bundle/PaymentBundle/Resources/config/oro/datagrids.yml b/src/Marello/Bundle/PaymentBundle/Resources/config/oro/datagrids.yml index 84a10c2fb..faab6b0f0 100644 --- a/src/Marello/Bundle/PaymentBundle/Resources/config/oro/datagrids.yml +++ b/src/Marello/Bundle/PaymentBundle/Resources/config/oro/datagrids.yml @@ -106,3 +106,166 @@ datagrids: icon: close entity_name: 'Marello\Bundle\PaymentBundle\Entity\PaymentMethodsConfigsRule' data_identifier: payment_methods_configs_rule.id + + marello-payments-base-grid: + source: + type: orm + query: + select: + - p.id + - p.paymentMethod + - p.paymentMethodOptions + - p.paymentReference + - p.paymentDetails + - p.paymentDate + - p.totalPaid + - p.createdAt + - p.updatedAt + - p.currency + - s.name AS status + columns: + status: + label: marello.payment.status.label + frontend_type: string + data_name: status + paymentMethod: + label: marello.payment.payment_method.label + type: twig + frontend_type: html + template: MarelloPaymentBundle:Payment/Datagrid:paymentMethodWithoutOptions.html.twig + paymentReference: + label: marello.payment.payment_reference.label + frontend_type: string + paymentDetails: + label: marello.payment.payment_details.label + frontend_type: string + paymentDate: + frontend_type: datetime + label: marello.payment.payment_date.label + createdAt: + label: oro.ui.created_at + frontend_type: datetime + updatedAt: + label: oro.ui.updated_at + frontend_type: datetime + totalPaid: + label: marello.payment.total_paid.label + type: localized_number + method: formatCurrency + context_resolver: Marello\Bundle\DataGridBundle\Grid\FormatterContextResolver::getResolverCurrencyClosure + align: right + sorters: + columns: + status: + data_name: s.name + paymentMethod: + data_name: p.paymentMethod + paymentReference: + data_name: p.paymentReference + paymentDetails: + data_name: p.paymentDetails + totalPaid: + data_name: p.totalPaid + paymentDate: + data_name: p.paymentDate + createdAt: + data_name: p.createdAt + updatedAt: + data_name: p.updatedAt + default: + createdAt: 'DESC' + filters: + columns: + status: + type: string + data_name: s.name + paymentMethod: + type: string + data_name: p.paymentMethod + paymentReference: + type: string + data_name: p.paymentReference + paymentDetails: + type: string + data_name: p.paymentDetails + totalPaid: + type: number + data_name: p.totalPaid + properties: + id: ~ + view_link: + type: url + route: marello_payment_view + params: [ id ] + update_link: + type: url + route: marello_payment_update + params: [ id ] + actions: + view: + type: navigate + label: oro.grid.action.view + link: view_link + icon: eye + acl_recource: marello_payment_view + rowAction: true + update: + type: navigate + label: oro.grid.action.update + icon: edit + link: update_link + acl_resource: marello_payment_update + + marello-payments-grid: + extends: marello-payments-base-grid + source: + type: orm + query: + from: + - { table: MarelloPaymentBundle:Payment, alias: p } + join: + inner: + - { join: p.status, alias: s } + + marello-order-payments-grid: + extends: marello-payments-base-grid + source: + type: orm + query: + from: + - { table: MarelloInvoiceBundle:AbstractInvoice, alias: i } + join: + inner: + - { join: i.payments, alias: p } + - { join: p.status, alias: s } + - { join: i.order, alias: o } + where: + and: + - o.id = :orderId + bind_parameters: + - orderId + options: + entityHint: marello.payment.entity_plural_label + gridViews: + allLabel: marello.payment.entity_plural_label + + marello-invoice-payments-grid: + extends: marello-payments-base-grid + source: + type: orm + query: + from: + - { table: MarelloInvoiceBundle:AbstractInvoice, alias: i } + join: + inner: + - { join: i.payments, alias: p } + - { join: p.status, alias: s } + where: + and: + - i.id = :invoiceId + bind_parameters: + - invoiceId + options: + entityHint: marello.payment.entity_plural_label + gridViews: + allLabel: marello.payment.entity_plural_label \ No newline at end of file diff --git a/src/Marello/Bundle/PaymentBundle/Resources/config/oro/navigation.yml b/src/Marello/Bundle/PaymentBundle/Resources/config/oro/navigation.yml index 1d398ce07..ca400e9db 100644 --- a/src/Marello/Bundle/PaymentBundle/Resources/config/oro/navigation.yml +++ b/src/Marello/Bundle/PaymentBundle/Resources/config/oro/navigation.yml @@ -1,6 +1,13 @@ navigation: menu_config: items: + marello_payments: + label: 'marello.payment.entity_plural_label' + route: 'marello_payment_index' + extras: + routes: ['marello_payment_*'] + position: 45 + marello_payment_rules: label: 'marello.payment.menu.paymentmethodsconfigsrule.label' route: 'marello_payment_methods_configs_rule_index' @@ -18,6 +25,9 @@ navigation: tree: application_menu: children: + sales_tab: + children: + marello_payments: ~ system_tab: children: marello_payment_rules: ~ @@ -26,6 +36,7 @@ navigation: shortcut_marello_payment_rules: ~ titles: + marello_payment_index: 'marello.payment.entity_plural_label' marello_payment_methods_configs_rule_index: ~ marello_payment_methods_configs_rule_view: '%label%' marello_payment_methods_configs_rule_update: 'Payment Rule %id% - Edit' diff --git a/src/Marello/Bundle/PaymentBundle/Resources/config/oro/routing.yml b/src/Marello/Bundle/PaymentBundle/Resources/config/oro/routing.yml index 05cfefb5c..9bef6599e 100644 --- a/src/Marello/Bundle/PaymentBundle/Resources/config/oro/routing.yml +++ b/src/Marello/Bundle/PaymentBundle/Resources/config/oro/routing.yml @@ -1,3 +1,13 @@ +marello_payment: + resource: "@MarelloPaymentBundle/Controller/PaymentController.php" + type: annotation + prefix: /marello/payment + +marello_payment_ajax: + resource: "@MarelloPaymentBundle/Controller/PaymentAjaxController.php" + type: annotation + prefix: /marello/payment + marello_payment_methods_configs_rule: resource: "@MarelloPaymentBundle/Controller/PaymentMethodsConfigsRuleController.php" type: annotation diff --git a/src/Marello/Bundle/PaymentBundle/Resources/config/services.yml b/src/Marello/Bundle/PaymentBundle/Resources/config/services.yml index 676361ab8..1f8547ede 100644 --- a/src/Marello/Bundle/PaymentBundle/Resources/config/services.yml +++ b/src/Marello/Bundle/PaymentBundle/Resources/config/services.yml @@ -22,6 +22,49 @@ services: - '@request_stack' - '@doctrine.orm.entity_manager' + marello_payment.form.type.payment_create: + class: 'Marello\Bundle\PaymentBundle\Form\Type\PaymentCreateType' + arguments: + - '@doctrine' + - '@marello_payment.provider.basic_payment_methods_choices' + tags: + - { name: form.type } + + marello_payment.form.payment_create: + class: 'Symfony\Component\Form\Form' + factory: ['@form.factory', 'create'] + arguments: + - 'Marello\Bundle\PaymentBundle\Form\Type\PaymentCreateType' + + marello_payment.form.handler.payment_create: + class: 'Marello\Bundle\PaymentBundle\Form\Handler\PaymentCreateHandler' + public: true + arguments: + - '@marello_payment.form.payment_create' + - '@request_stack' + - '@doctrine.orm.entity_manager' + + marello_payment.form.type.payment_update: + class: 'Marello\Bundle\PaymentBundle\Form\Type\PaymentUpdateType' + arguments: + - '@doctrine' + tags: + - { name: form.type } + + marello_payment.form.payment_update: + class: 'Symfony\Component\Form\Form' + factory: ['@form.factory', 'create'] + arguments: + - 'Marello\Bundle\PaymentBundle\Form\Type\PaymentUpdateType' + + marello_payment.form.handler.payment_update: + class: 'Marello\Bundle\PaymentBundle\Form\Handler\PaymentUpdateHandler' + public: true + arguments: + - '@marello_payment.form.payment_update' + - '@request_stack' + - '@doctrine.orm.entity_manager' + marello_payment.datagrid.payment_rule_actions_visibility_provider: parent: marello_rule.action.visibility_provider public: true @@ -94,6 +137,13 @@ services: tags: - { name: kernel.event_listener, event: marello_payment.method_renaming, method: onMethodRename} + marello_orderpayment.event_listener.payment_creation: + class: 'Marello\Bundle\PaymentBundle\EventListener\PaymentCreationListener' + arguments: + - '@oro_entity.doctrine_helper' + tags: + - { name: kernel.event_listener, event: extendable_action.order_paid, method: onOrderPaid } + marello_payment.method.event.dispatcher.method_removal: class: 'Marello\Bundle\PaymentBundle\Method\Event\BasicMethodRemovalEventDispatcher' public: false @@ -193,6 +243,13 @@ services: - '@marello_payment.repository.payment_methods_configs_rule' - '@marello_payment.payment_method.composite_provider' + marello_payment.action.handler.add_payment: + class: 'Marello\Bundle\PaymentBundle\Action\Handler\AddPaymentActionHandler' + public: true + arguments: + - '@doctrine.orm.entity_manager' + - '@marello_invoice.provider.invoice_paid_amount' + marello_payment.action.handler.payment_methods_configs_rule.enable_status: class: 'Marello\Bundle\PaymentBundle\Action\Handler\PaymentMethodsConfigsRuleToggleStatusActionHandler' public: true @@ -246,3 +303,30 @@ services: - '%marello_payment.rule_grid_route_name%' - '%marello_payment.rule_grid_name%' - '@oro_datagrid.helper.route' + + marello_payment.provider.form_changes.available_currencies: + class: 'Marello\Bundle\PaymentBundle\Provider\FormChanges\AvailableCurrenciesFormChangesProvider' + arguments: + - '@oro_locale.settings' + - '@oro_currency.config.currency' + tags: + - { name: marello.form_changes_data_provider, class: 'Marello\Bundle\PaymentBundle\Entity\Payment', type: currencies, priority: 45 } + + marello_payment.provider.form_changes.available_payment_methods: + class: 'Marello\Bundle\PaymentBundle\Provider\FormChanges\AvailablePaymentMethodsFormChangesProvider' + arguments: + - '@templating' + - '@form.factory' + - '@marello_payment.provider.basic_payment_methods_choices' + tags: + - { name: marello.form_changes_data_provider, class: 'Marello\Bundle\PaymentBundle\Entity\Payment', type: paymentMethods, priority: 45 } + + marello_payment.validator.payment_status: + class: 'Marello\Bundle\PaymentBundle\Validator\PaymentStatusValidator' + tags: + - { name: validator.constraint_validator, alias: marello_payment.payment_status_validator } + + marello_payment.validator.total_paid: + class: 'Marello\Bundle\PaymentBundle\Validator\TotalPaidValidator' + tags: + - { name: validator.constraint_validator, alias: marello_payment.total_paid_validator } diff --git a/src/Marello/Bundle/PaymentBundle/Resources/config/validation.yml b/src/Marello/Bundle/PaymentBundle/Resources/config/validation.yml index 44f612feb..18ac20bb6 100644 --- a/src/Marello/Bundle/PaymentBundle/Resources/config/validation.yml +++ b/src/Marello/Bundle/PaymentBundle/Resources/config/validation.yml @@ -25,3 +25,8 @@ Marello\Bundle\PaymentBundle\Entity\PaymentMethodConfig: properties: method: - NotBlank: ~ + +Marello\Bundle\PaymentBundle\Entity\Payment: + constraints: + - Marello\Bundle\PaymentBundle\Validator\Constraints\PaymentStatus: ~ + - Marello\Bundle\PaymentBundle\Validator\Constraints\TotalPaid: ~ \ No newline at end of file diff --git a/src/Marello/Bundle/PaymentBundle/Resources/public/css/scss/style.scss b/src/Marello/Bundle/PaymentBundle/Resources/public/css/scss/style.scss index 688715028..efd6aa20f 100755 --- a/src/Marello/Bundle/PaymentBundle/Resources/public/css/scss/style.scss +++ b/src/Marello/Bundle/PaymentBundle/Resources/public/css/scss/style.scss @@ -48,3 +48,10 @@ .marello-payment-rule-add-method-select { display: inline-block; } + +.marello-payment-update-property-label { + max-width: 180px; + color: #545456; + margin-right: 12px; +} + diff --git a/src/Marello/Bundle/PaymentBundle/Resources/public/js/app/views/payment-method-view.js b/src/Marello/Bundle/PaymentBundle/Resources/public/js/app/views/payment-method-view.js new file mode 100755 index 000000000..3fe27fe45 --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Resources/public/js/app/views/payment-method-view.js @@ -0,0 +1,90 @@ +define(function(require) { + 'use strict'; + + const $ = require('jquery'); + const _ = require('underscore'); + const mediator = require('oroui/js/mediator'); + const LoadingMaskView = require('oroui/js/app/views/loading-mask-view'); + const BaseView = require('oroui/js/app/views/base/view'); + + /** + * @export marelloorder/js/app/views/order-totals-view + * @extends oroui.app.views.base.View + * @class marelloorder.app.views.OrderTotalsView + */ + const PaymentMethodView = BaseView.extend({ + /** + * @property {LoadingMaskView} + */ + loadingMaskView: null, + + /** + * @inheritDoc + */ + initialize: function(options) { + this.options = _.defaults(options || {}, this.options); + + this.loadingMaskView = new LoadingMaskView({container: this.$el}); + + mediator.on('payment:form-changes:trigger', this.loadingStart, this); + mediator.on('payment:form-changes:load', this.updatePaymentMethods, this); + mediator.on('payment:form-changes:load:after', this.loadingEnd, this); + }, + + /** + * @param {Object} data + */ + updatePaymentMethods: function(data) { + var paymentMethodsHtml = data['paymentMethods'] || null; + if (!paymentMethodsHtml) { + this.loadingEnd(); + return; + } + + this.render(paymentMethodsHtml); + }, + + /** + * Show loading view + */ + loadingStart: function(e) { + if (e.updateFields !== undefined && _.contains(e.updateFields, "paymentMethods") !== true) { + return; + } + this.loadingMaskView.show(); + }, + + /** + * Hide loading view + */ + loadingEnd: function() { + this.loadingMaskView.hide(); + }, + + /** + * Render + * + * @param {String} paymentMethodHtml + */ + render: function(paymentMethodHtml) { + $("div[data-ftid='marello_payment_create_paymentMethod']").replaceWith(paymentMethodHtml); + }, + + /** + * @inheritDoc + */ + dispose: function() { + if (this.disposed) { + return; + } + + mediator.off('payment:form-changes:trigger', this.loadingStart, this); + mediator.off('payment:form-changes:load', this.updatePaymentMethods, this); + mediator.off('payment:form-changes:load:after', this.loadingEnd, this); + + PaymentMethodView.__super__.dispose.call(this); + } + }); + + return PaymentMethodView; +}); diff --git a/src/Marello/Bundle/PaymentBundle/Resources/public/js/app/views/payment-source-view.js b/src/Marello/Bundle/PaymentBundle/Resources/public/js/app/views/payment-source-view.js new file mode 100755 index 000000000..75867494e --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Resources/public/js/app/views/payment-source-view.js @@ -0,0 +1,51 @@ +define(function(require) { + 'use strict'; + + const $ = require('jquery'); + const _ = require('underscore'); + const mediator = require('oroui/js/mediator'); + const BaseView = require('oroui/js/app/views/base/view'); + + /** + * @export marelloorder/js/app/views/order-discount-view + * @extends oroui.app.views.base.View + * @class marelloorder.app.views.OrderDiscountView + */ + const OrderDiscountView = BaseView.extend({ + /** + * @property {Object} + */ + options: {}, + + /** + * @property {jQuery} + */ + $field: null, + + /** + * @inheritDoc + */ + initialize: function(options) { + this.options = $.extend(true, {}, this.options, options || {}); + + this.$field = this.$el.find(':input[data-ftid]'); + $(this.$field).on('change', function() { + mediator.trigger('payment:form-changes:trigger', {updateFields: ['paymentMethods', 'currencies']}); + }); + $(this.$field).trigger('change'); + }, + + /** + * @inheritDoc + */ + dispose: function() { + if (this.disposed) { + return; + } + + OrderDiscountView.__super__.dispose.call(this); + } + }); + + return OrderDiscountView; +}); diff --git a/src/Marello/Bundle/PaymentBundle/Resources/public/js/app/views/total-paid-view.js b/src/Marello/Bundle/PaymentBundle/Resources/public/js/app/views/total-paid-view.js new file mode 100755 index 000000000..d4bf44e33 --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Resources/public/js/app/views/total-paid-view.js @@ -0,0 +1,98 @@ +define(function(require) { + 'use strict'; + + const $ = require('jquery'); + const _ = require('underscore'); + const mediator = require('oroui/js/mediator'); + const LoadingMaskView = require('oroui/js/app/views/loading-mask-view'); + const BaseView = require('oroui/js/app/views/base/view'); + + /** + * @export marelloorder/js/app/views/order-totals-view + * @extends oroui.app.views.base.View + * @class marelloorder.app.views.OrderTotalsView + */ + const TotalPaidCurrenciesView = BaseView.extend({ + /** + * @property {LoadingMaskView} + */ + loadingMaskView: null, + + /** + * @inheritDoc + */ + initialize: function(options) { + this.options = _.defaults(options || {}, this.options); + + this.loadingMaskView = new LoadingMaskView({container: this.$el}); + + mediator.on('payment:form-changes:trigger', this.loadingStart, this); + mediator.on('payment:form-changes:load', this.updateCurrencies, this); + mediator.on('payment:form-changes:load:after', this.loadingEnd, this); + }, + + /** + * @param {Object} data + */ + updateCurrencies: function(data) { + var currencies = data['currencies'] || null; + if (!currencies) { + this.loadingEnd(); + return; + } + + this.render(currencies); + }, + + /** + * Show loading view + */ + loadingStart: function(e) { + if (e.updateFields !== undefined && _.contains(e.updateFields, "currencies") !== true) { + return; + } + this.loadingMaskView.show(); + }, + + /** + * Hide loading view + */ + loadingEnd: function() { + this.loadingMaskView.hide(); + }, + + /** + * Render + * + * @param {Object} currencies + */ + render: function(currencies) { + var selector = $("select[name='marello_payment_create[totalPaid][currency]']"); + selector.empty(); + $.each(currencies, function(text, value) { + var option = $("") + .attr("value", value) + .text(text); + selector.append(option); + }); + selector.trigger('change'); + }, + + /** + * @inheritDoc + */ + dispose: function() { + if (this.disposed) { + return; + } + + mediator.off('payment:form-changes:trigger', this.loadingStart, this); + mediator.off('payment:form-changes:load', this.updateCurrencies, this); + mediator.off('payment:form-changes:load:after', this.loadingEnd, this); + + TotalPaidCurrenciesView.__super__.dispose.call(this); + } + }); + + return TotalPaidCurrenciesView; +}); diff --git a/src/Marello/Bundle/PaymentBundle/Resources/translations/messages.en.yml b/src/Marello/Bundle/PaymentBundle/Resources/translations/messages.en.yml index 7a4ae474d..a6bddbcbc 100644 --- a/src/Marello/Bundle/PaymentBundle/Resources/translations/messages.en.yml +++ b/src/Marello/Bundle/PaymentBundle/Resources/translations/messages.en.yml @@ -1,5 +1,23 @@ marello: payment: + entity_label: Payment + entity_plural_label: Payments + entity_grid_all_view_label: All %entity_plural_label% + id.label: Id + organization.label: Organization + payment_method.label: Payment Method + payment_method_options.label: Payment Method Options + payment_reference.label: Payment Reference + payment_details.label: Payment Details + payment_source.label: Related Entity + payment_date.label: Payment Date + total_paid.label: Total Paid + currency.label: Currency + status.label: Status + + button: + add_payment.label: Add Payment + menu: payments.label: Payments paymentmethodsconfigsrule.description: Payment Rules @@ -70,6 +88,10 @@ marello: message: error: 'General error. We were unable to process action.' + add_payment: + success: 'Payment was successfuly added' + error: + paid_total_exceed: "Total Paid amount of all Payments can't exceed Invoice grandTotal amount" paymentmethodconfig: entity_label: Payment Method Config @@ -148,7 +170,8 @@ marello: pending.label: Pending sections: - general: 'General Information' + general: 'General' + additional: 'Additional' destination: 'Destinations' paymentrule_configurations: no_methods.message: 'Please enable at least one payment integration.' diff --git a/src/Marello/Bundle/PaymentBundle/Resources/translations/validators.en.yml b/src/Marello/Bundle/PaymentBundle/Resources/translations/validators.en.yml index 4a433c817..27bb946d6 100644 --- a/src/Marello/Bundle/PaymentBundle/Resources/translations/validators.en.yml +++ b/src/Marello/Bundle/PaymentBundle/Resources/translations/validators.en.yml @@ -4,3 +4,5 @@ marello: paymentrule: type.config.count.message: 'You must select at least {{ limit }} payment method type|You must select at least {{ limit }} payment method types' method.config.count.message: 'You must select at least {{ limit }} payment method|You must select at least {{ limit }} payment methods' + status.message: 'Only payments with related entity can have status "Assigned" and only payments without related entity can have status "Unassigned"' + total_paid.message: "Total Paid can't be higher related entity's Total Due" \ No newline at end of file diff --git a/src/Marello/Bundle/PaymentBundle/Resources/views/Action/payment_popup.html.twig b/src/Marello/Bundle/PaymentBundle/Resources/views/Action/payment_popup.html.twig new file mode 100644 index 000000000..af5ef2e24 --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Resources/views/Action/payment_popup.html.twig @@ -0,0 +1,22 @@ +{% extends 'OroActionBundle:Operation:form.html.twig' %} + +{% block form %} + {% set buttonOptions = operation.definition.buttonOptions %} +
+ {{ form_start(form, {'action': app.request.uri, 'attr': {'id': form.vars.id, 'data-collect': 'true', 'class': 'form-dialog'}}) }} +
+ {{ form_row(form.payment_method) }} + {{ form_row(form.payment_date) }} + {{ form_row(form.payment_reference) }} + {{ form_row(form.payment_details) }} + {{ form_row(form.total_paid) }} +
+
+ + +
+ {{ form_rest(form) }} + {{ form_end(form) }} + {{ oro_form_js_validation(form) }} +
+{% endblock %} diff --git a/src/Marello/Bundle/PaymentBundle/Resources/views/Form/paymentMethodSelector.html.twig b/src/Marello/Bundle/PaymentBundle/Resources/views/Form/paymentMethodSelector.html.twig new file mode 100755 index 000000000..6968a36de --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Resources/views/Form/paymentMethodSelector.html.twig @@ -0,0 +1 @@ +{{ form_widget(form.paymentMethod) }} diff --git a/src/Marello/Bundle/PaymentBundle/Resources/views/Payment/Datagrid/paymentMethodWithOptions.html.twig b/src/Marello/Bundle/PaymentBundle/Resources/views/Payment/Datagrid/paymentMethodWithOptions.html.twig new file mode 100644 index 000000000..e73786090 --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Resources/views/Payment/Datagrid/paymentMethodWithOptions.html.twig @@ -0,0 +1,8 @@ +{% spaceless %} + {% set identifier = record.getValue('paymentMethod') %} + {% set options = record.getValue('paymentMethodOptions') %} + {{ marello_get_payment_method_label(identifier)|trans }}
+ {% for name, value in options %} + {{ name ~ ': ' ~ value }}
+ {% endfor %} +{% endspaceless %} diff --git a/src/Marello/Bundle/PaymentBundle/Resources/views/Payment/Datagrid/paymentMethodWithoutOptions.html.twig b/src/Marello/Bundle/PaymentBundle/Resources/views/Payment/Datagrid/paymentMethodWithoutOptions.html.twig new file mode 100644 index 000000000..06197dfec --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Resources/views/Payment/Datagrid/paymentMethodWithoutOptions.html.twig @@ -0,0 +1,4 @@ +{% spaceless %} + {% set identifier = record.getValue('paymentMethod') %} + {{ marello_get_payment_method_label(identifier)|trans }} +{% endspaceless %} diff --git a/src/Marello/Bundle/PaymentBundle/Resources/views/Payment/create.html.twig b/src/Marello/Bundle/PaymentBundle/Resources/views/Payment/create.html.twig new file mode 100644 index 000000000..956b93214 --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Resources/views/Payment/create.html.twig @@ -0,0 +1,96 @@ +{% extends 'OroUIBundle:actions:update.html.twig' %} +{% import 'OroUIBundle::macros.html.twig' as UI %} +{% import 'OroDataGridBundle::macros.html.twig' as dataGrid %} +{% form_theme form with 'OroFormBundle:Form:fields.html.twig' %} +{% set formAction = path('marello_payment_create') %} + +{% block navButtons %} + {{ UI.cancelButton(path('marello_payment_index')) }} + {% set html = UI.saveAndCloseButton({ + 'route': 'marello_payment_index' + }) %} + {{ UI.dropdownSaveButton({ 'html': html }) }} +{% endblock navButtons %} + +{% block pageHeader %} + {% set title = 'oro.ui.create_entity'|trans({'%entityName%': 'marello.payment.entity_label'|trans}) %} + {% include 'OroUIBundle::page_title_block.html.twig' with { title: title } %} +{% endblock pageHeader %} + +{% set pageComponent = { + module: 'marellolayout/js/app/components/form-changes-component', + options: { + route: 'marello_payment_form_changes', + prefix: 'payment', + routeParams: {id: entity.id|default(0)} + } +} %} + +{% block content_data %} + {% set id = 'marello-payment-create' %} + {% set generalSubblocks = [] %} + {% set generalInformation %} +
+
+
+
+
+ {{ form_row(form.paymentSource) }} +
+
+ {{ form_row(form.paymentMethod) }} +
+ {{ form_row(form.paymentDate) }} + {{ form_row(form.paymentReference) }} + {{ form_row(form.paymentDetails) }} +
+ {{ form_row(form.totalPaid) }} +
+
+
+
+
+ {% endset %} + {% set generalSubblocks = generalSubblocks|merge([{'data' : [generalInformation] }]) %} + + + {% set dataBlocks = [{ + 'title': 'marello.payment.sections.general'|trans, + 'class': 'active', + 'subblocks': generalSubblocks + } + ] %} + + {% set additionalData = [] %} + {% for child in form.children if child.vars.extra_field is defined and child.vars.extra_field %} + {% set additionalData = additionalData|merge([form_row(child)]) %} + {% endfor %} + + {% if additionalData is not empty %} + {% set dataBlocks = dataBlocks|merge([{ + 'title' : 'marello.payment.sections.additional'|trans, + 'subblocks': [{ + 'title' : null, + 'useSpan': false, + 'data' : [ + additionalData + ] + }] + }]) %} + {% endif %} + + {% set data = { + 'formErrors': form_errors(form)? form_errors(form) : null, + 'dataBlocks': dataBlocks, + } %} + {{ parent() }} +{% endblock content_data %} diff --git a/src/Marello/Bundle/PaymentBundle/Resources/views/Payment/index.html.twig b/src/Marello/Bundle/PaymentBundle/Resources/views/Payment/index.html.twig new file mode 100644 index 000000000..fa3ded544 --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Resources/views/Payment/index.html.twig @@ -0,0 +1,13 @@ +{% extends 'OroUIBundle:actions:index.html.twig' %} +{% import 'OroUIBundle::macros.html.twig' as UI %} +{% set gridName = 'marello-payments-grid' %} +{% set pageTitle = 'marello.payment.entity_plural_label'|trans %} + +{% block navButtons %} + {% if is_granted('marello_payment_create') %} + {{ UI.addButton({ + 'path': path('marello_payment_create'), + 'entity_label': 'marello.payment.entity_label'|trans + }) }} + {% endif %} +{% endblock %} \ No newline at end of file diff --git a/src/Marello/Bundle/PaymentBundle/Resources/views/Payment/update.html.twig b/src/Marello/Bundle/PaymentBundle/Resources/views/Payment/update.html.twig new file mode 100644 index 000000000..54aea7fc7 --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Resources/views/Payment/update.html.twig @@ -0,0 +1,91 @@ +{% extends 'OroUIBundle:actions:update.html.twig' %} +{% import 'OroUIBundle::macros.html.twig' as UI %} +{% import 'OroDataGridBundle::macros.html.twig' as dataGrid %} +{% form_theme form with 'OroFormBundle:Form:fields.html.twig' %} +{% set formAction = path('marello_payment_update', { 'id': form.vars.value.id }) %} + +{% block navButtons %} + {{ parent() }} + + {{ UI.cancelButton(path('marello_payment_index')) }} + {% if is_granted('marello_payment_update') %} + {% set html = '' %} + {% if is_granted('marello_payment_view') %} + {% set html = UI.saveAndCloseButton({ + 'route': 'marello_payment_view', + 'params': {'id': '$id'} + }) %} + {% endif %} + {% set html = html ~ UI.saveAndStayButton({ + 'route': 'marello_payment_update', + 'params': {'id': '$id'} + }) %} + + {{ UI.dropdownSaveButton({'html': html}) }} + {% endif %} +{% endblock navButtons %} + +{% block pageHeader %} + {% set breadcrumbs = { + 'entity': form.vars.value, + 'indexPath': path('marello_payment_index'), + 'indexLabel': 'marello.payment.entity_plural_label'|trans, + 'entityTitle': entity.id + } %} + {{ parent() }} +{% endblock pageHeader %} + +{% block content_data %} + {% set id = 'marello-payment-update' %} + {% set paymentMethod = marello_get_payment_method_label(entity.paymentMethod)|trans %} + {% for name, value in entity.paymentMethodOptions %} + {% if name == 'term' %} + {% set value = 'marello.payment_term.ui.payment_term.term_days'|trans({'%days%': value }) %} + {% set name = 'Term' %} + {% elseif name == 'code' %} + {% set value = marello_get_payment_term_label_for_code(value) %} + {% set name = 'Label' %} + {% endif %} + {% set paymentMethod = paymentMethod ~ '
' ~ name ~ ': ' ~ value %} + {% endfor %} + {% set dataBlocks = [{ + 'title': 'marello.payment.sections.general'|trans, + 'class': 'active', + 'subblocks': [{ + 'title': '', + 'data': [ + form_row(form.status), + form_row(form.paymentSource), + UI.renderHtmlProperty('marello.payment.payment_method.label'|trans, paymentMethod, null, null, {termClass: 'marello-payment-update-property-label'}), + form_row(form.paymentReference), + form_row(form.paymentDetails), + UI.renderProperty('marello.payment.total_paid.label'|trans, entity.totalPaid|oro_format_currency({'currency':entity.currency}), null, null, {termClass: 'marello-payment-update-property-label'}), + UI.renderProperty('marello.payment.payment_date.label'|trans, entity.paymentDate|date, null, null, {termClass: 'marello-payment-update-property-label'}) + ] + }]} + ] %} + + {% set additionalData = [] %} + {% for child in form.children if child.vars.extra_field is defined and child.vars.extra_field %} + {% set additionalData = additionalData|merge([form_row(child)]) %} + {% endfor %} + + {% if additionalData is not empty %} + {% set dataBlocks = dataBlocks|merge([{ + 'title' : 'marello.payment.sections.additional'|trans, + 'subblocks': [{ + 'title' : null, + 'useSpan': false, + 'data' : [ + additionalData + ] + }] + }]) %} + {% endif %} + + {% set data = { + 'formErrors': form_errors(form)? form_errors(form) : null, + 'dataBlocks': dataBlocks, + } %} + {{ parent() }} +{% endblock content_data %} diff --git a/src/Marello/Bundle/PaymentBundle/Resources/views/Payment/view.html.twig b/src/Marello/Bundle/PaymentBundle/Resources/views/Payment/view.html.twig new file mode 100644 index 000000000..838e49826 --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Resources/views/Payment/view.html.twig @@ -0,0 +1,74 @@ +{% extends 'OroUIBundle:actions:view.html.twig' %} +{% import 'OroUIBundle::macros.html.twig' as UI %} + +{% block navButtons %} + {% if is_granted('marello_payment_update') %} + {{ UI.editButton({ + 'path' : path('marello_payment_update', { id: entity.id }), + 'entity_label': 'marello.payment.entity_label'|trans + }) }} + {% endif %} +{% endblock navButtons %} + +{% block pageHeader %} + {% set breadcrumbs = { + 'entity': entity, + 'indexPath': path('marello_payment_index'), + 'indexLabel': 'marello.payment.entity_plural_label'|trans, + 'entityTitle': entity.id + } %} + {{ parent() }} +{% endblock pageHeader %} + +{% block content_data %} + {% set id = 'marello-payment-view' %} + {% set paymentMethod = marello_get_payment_method_label(entity.paymentMethod)|trans %} + {% for name, value in entity.paymentMethodOptions %} + {% if name == 'term' %} + {% set value = 'marello.payment_term.ui.payment_term.term_days'|trans({'%days%': value }) %} + {% set name = 'Term' %} + {% elseif name == 'code' %} + {% set value = marello_get_payment_term_label_for_code(value) %} + {% set name = 'Label' %} + {% endif %} + {% set paymentMethod = paymentMethod ~ '
' ~ name ~ ': ' ~ value %} + {% endfor %} + {% set paymentSource = marello_get_payment_source(entity) %} + {% set data %} +
+
+
+ {{ UI.renderProperty('marello.payment.status.label'|trans, entity.status) }} + {% if paymentSource is not empty %} + {{ UI.renderHtmlProperty( + 'marello.payment.payment_source.label'|trans, + UI.entityViewLink(paymentSource, paymentSource.invoiceType ~ ': ' ~ paymentSource.invoiceNumber, 'marello_invoice_invoice_view') + )}} + {% else %} + {{ UI.renderHtmlProperty( + 'marello.payment.payment_source.label'|trans, + 'N/A' + )}} + {% endif %} + {{ UI.renderHtmlProperty('marello.payment.payment_method.label'|trans, paymentMethod) }} + {{ UI.renderProperty('marello.payment.payment_reference.label'|trans, entity.paymentReference) }} + {{ UI.renderProperty('marello.payment.payment_details.label'|trans, entity.paymentDetails) }} + {{ UI.renderProperty('marello.payment.total_paid.label'|trans, entity.totalPaid|oro_format_currency({'currency':entity.currency})) }} + {{ UI.renderProperty('marello.payment.payment_date.label'|trans, entity.paymentDate|date) }} +
+
+
+ {% endset %} + {% set dataBlocks = [ + { + 'title': 'General'|trans, + 'class': 'active', + 'subblocks': [ + { 'data' : [data] } + ] + } + ] %} + + {% set data = { 'dataBlocks': dataBlocks } %} + {{ parent() }} +{% endblock content_data %} diff --git a/src/Marello/Bundle/PaymentBundle/Validator/Constraints/PaymentStatus.php b/src/Marello/Bundle/PaymentBundle/Validator/Constraints/PaymentStatus.php new file mode 100644 index 000000000..26eca402c --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Validator/Constraints/PaymentStatus.php @@ -0,0 +1,27 @@ +getPaymentSource(); + $status = $entity->getStatus()->getId(); + if ((!$paymentSource && $status === LoadPaymentStatusData::ASSIGNED) || + ($paymentSource && $status === LoadPaymentStatusData::UNASSIGNED) + ) { + $this->context->buildViolation($constraint->message) + ->atPath('status') + ->addViolation(); + } + } + } +} diff --git a/src/Marello/Bundle/PaymentBundle/Validator/TotalPaidValidator.php b/src/Marello/Bundle/PaymentBundle/Validator/TotalPaidValidator.php new file mode 100644 index 000000000..ae9f55675 --- /dev/null +++ b/src/Marello/Bundle/PaymentBundle/Validator/TotalPaidValidator.php @@ -0,0 +1,38 @@ +getPaymentSource(); + if ($paymentSource) { + $totalPaid = $entity->getTotalPaid(); + $totalDue = $paymentSource->getTotalDue(); + if ($totalPaid > $totalDue) { + $this->context->buildViolation($constraint->message) + ->atPath('totalPaid') + ->addViolation(); + } + } + } + } +} diff --git a/src/Marello/Bundle/PaymentTermBundle/Provider/PaymentTermProvider.php b/src/Marello/Bundle/PaymentTermBundle/Provider/PaymentTermProvider.php index 569fb149d..512cd30b7 100644 --- a/src/Marello/Bundle/PaymentTermBundle/Provider/PaymentTermProvider.php +++ b/src/Marello/Bundle/PaymentTermBundle/Provider/PaymentTermProvider.php @@ -81,4 +81,15 @@ public function getPaymentTerms() { return $this->doctrineHelper->getEntityRepositoryForClass(PaymentTerm::class)->findAll(); } + + /** + * @param string $code + * @return PaymentTerm|null + */ + public function getPaymentTerm($code) + { + return $this->doctrineHelper + ->getEntityRepositoryForClass(PaymentTerm::class) + ->findOneBy(['code' => $code]); + } } diff --git a/src/Marello/Bundle/PaymentTermBundle/Resources/config/services.yml b/src/Marello/Bundle/PaymentTermBundle/Resources/config/services.yml index f6a0a5c2c..9b8523bc1 100644 --- a/src/Marello/Bundle/PaymentTermBundle/Resources/config/services.yml +++ b/src/Marello/Bundle/PaymentTermBundle/Resources/config/services.yml @@ -66,3 +66,12 @@ services: - '@marello_payment_term.provider.payment_term' tags: - { name: kernel.event_listener, event: marello_payment.applicable_payment_method_view, method: onApplicablePaymentMethodView } + + marello_payment_term.twig.payment_term_extension: + class: 'Marello\Bundle\PaymentTermBundle\Twig\PaymentTermExtension' + public: false + arguments: + - '@marello_payment_term.provider.payment_term' + - '@oro_locale.helper.localization' + tags: + - { name: twig.extension } diff --git a/src/Marello/Bundle/PaymentTermBundle/Twig/PaymentTermExtension.php b/src/Marello/Bundle/PaymentTermBundle/Twig/PaymentTermExtension.php new file mode 100755 index 000000000..d712bcb07 --- /dev/null +++ b/src/Marello/Bundle/PaymentTermBundle/Twig/PaymentTermExtension.php @@ -0,0 +1,71 @@ +paymentTermProvider = $paymentTermProvider; + $this->localizationHelper = $localizationHelper; + } + + + /** + * {@inheritdoc} + */ + public function getName() + { + return static::NAME; + } + + /** + * @return array + */ + public function getFunctions() + { + return [ + new TwigFunction( + 'marello_get_payment_term_label_for_code', + [$this, 'getPaymentTermLabelForCode'] + ), + new TwigFunction( + 'marello_get_payment_term_for_customer', + [$this->paymentTermProvider, 'getCustomerPaymentTerm'] + ) + ]; + } + + /** + * @param string $code + * @return string + */ + public function getPaymentTermLabelForCode($code) + { + $paymentTerm = $this->paymentTermProvider->getPaymentTerm($code); + if ($paymentTerm) { + return $this->localizationHelper->getLocalizedValue($paymentTerm->getLabels())->getString(); + } + } +} diff --git a/src/Marello/Bundle/PdfBundle/DependencyInjection/Configuration.php b/src/Marello/Bundle/PdfBundle/DependencyInjection/Configuration.php index 06d825b73..ce5c6eac7 100644 --- a/src/Marello/Bundle/PdfBundle/DependencyInjection/Configuration.php +++ b/src/Marello/Bundle/PdfBundle/DependencyInjection/Configuration.php @@ -22,6 +22,7 @@ class Configuration implements ConfigurationInterface const CONFIG_KEY_COMPANY_ADDRESS = 'company_address'; const CONFIG_KEY_COMPANY_EMAIL = 'company_email'; const CONFIG_KEY_LOGO = 'logo'; + const CONFIG_KEY_LOGO_WIDTH = 'logo_width'; const CONFIG_KEY_COMPANY_PHONE = 'company_phone'; const CONFIG_KEY_COMPANY_BANK = 'company_bank'; const CONFIG_KEY_COMPANY_COC = 'company_coc'; @@ -47,6 +48,7 @@ public function getConfigTreeBuilder() self::CONFIG_KEY_COMPANY_ADDRESS => ['value' => null], self::CONFIG_KEY_COMPANY_EMAIL => ['value' => null], self::CONFIG_KEY_LOGO => ['value' => null], + self::CONFIG_KEY_LOGO_WIDTH => ['value' => null], self::CONFIG_KEY_COMPANY_PHONE => ['value' => null], self::CONFIG_KEY_COMPANY_BANK => ['value' => null], self::CONFIG_KEY_COMPANY_COC => ['value' => null], diff --git a/src/Marello/Bundle/PdfBundle/Resources/config/oro/system_configuration.yml b/src/Marello/Bundle/PdfBundle/Resources/config/oro/system_configuration.yml index 9e3dd41bb..80853d463 100644 --- a/src/Marello/Bundle/PdfBundle/Resources/config/oro/system_configuration.yml +++ b/src/Marello/Bundle/PdfBundle/Resources/config/oro/system_configuration.yml @@ -55,6 +55,13 @@ system_configuration: fileConstraints: - Image: ~ + marello_pdf.logo_width: + data_type: number + type: 'Symfony\Component\Form\Extension\Core\Type\NumberType' + options: + label: marello.pdf.config.fields.logo_width.label + tooltip: marello.pdf.config.fields.logo_width.tooltip + marello_pdf.company_address: data_type: string type: 'Symfony\Component\Form\Extension\Core\Type\TextareaType' @@ -98,7 +105,7 @@ system_configuration: options: label: marello.pdf.config.fields.email_workflow_transition.label tooltip: marello.pdf.config.fields.email_workflow_transition.tooltip - workflow: marello_order_b2c_workflow_1 + workflow: marello_order_b2c_new_workflow_1 required: false placeholder: marello.pdf.config.fields.email_workflow_transition.placeholder @@ -144,6 +151,7 @@ system_configuration: children: - marello_pdf.localization - marello_pdf.logo + - marello_pdf.logo_width - marello_pdf.company_address - marello_pdf.company_email - marello_pdf.company_phone diff --git a/src/Marello/Bundle/PdfBundle/Resources/translations/messages.en.yml b/src/Marello/Bundle/PdfBundle/Resources/translations/messages.en.yml index 05916891c..5ca19599b 100644 --- a/src/Marello/Bundle/PdfBundle/Resources/translations/messages.en.yml +++ b/src/Marello/Bundle/PdfBundle/Resources/translations/messages.en.yml @@ -19,6 +19,9 @@ marello: logo: label: "Company logo" tooltip: "Upload a logo that will be displayed on top of your PDF document(image/jpeg, image/png, image/gif, image/svg)." + logo_width: + label: "Company logo width" + tooltip: "Enter logo width in pixels here." company_address: label: "Company address" tooltip: "Enter company address information here, including the company name and country." diff --git a/src/Marello/Bundle/PdfBundle/Resources/views/Download/util.html.twig b/src/Marello/Bundle/PdfBundle/Resources/views/Download/util.html.twig index ea8473d4e..646ec610c 100644 --- a/src/Marello/Bundle/PdfBundle/Resources/views/Download/util.html.twig +++ b/src/Marello/Bundle/PdfBundle/Resources/views/Download/util.html.twig @@ -2,7 +2,7 @@
diff --git a/src/Marello/Bundle/PricingBundle/EventListener/Datagrid/ChannelPricesDatagridListener.php b/src/Marello/Bundle/PricingBundle/EventListener/Datagrid/ChannelPricesDatagridListener.php index d3445f71b..03d1a3179 100644 --- a/src/Marello/Bundle/PricingBundle/EventListener/Datagrid/ChannelPricesDatagridListener.php +++ b/src/Marello/Bundle/PricingBundle/EventListener/Datagrid/ChannelPricesDatagridListener.php @@ -2,136 +2,38 @@ namespace Marello\Bundle\PricingBundle\EventListener\Datagrid; -use Doctrine\ORM\Query\Expr; -use Oro\Bundle\DataGridBundle\Datagrid\Common\DatagridConfiguration; +use Marello\Bundle\PricingBundle\Entity\AssembledChannelPriceList; +use Oro\Bundle\DataGridBundle\Datasource\ResultRecord; use Oro\Bundle\DataGridBundle\Event\BuildBefore; +use Oro\Bundle\DataGridBundle\Event\OrmResultAfter; +use Oro\Bundle\EntityBundle\ORM\DoctrineHelper; class ChannelPricesDatagridListener { - const DATA_NAME = 'channelPrices'; - const JOIN_ALIAS = 'cpr'; - const CHANNEL_DATA_NAME = 'channel'; - const CHANNEL_JOIN_ALIAS = 'ch'; - const DEFAULT_DATA_NAME = 'defaultPrice'; - const DEFAULT_JOIN_ALIAS = 'defcpr'; - const SPECIAL_DATA_NAME = 'specialPrice'; - const SPECIAL_JOIN_ALIAS = 'spcpr'; - - /** @var string */ - protected $relatedEntityClass; - - /** @var Expr */ - protected $expressionBuilder; - - /** - * @param string $relatedEntityClass - */ - public function __construct( - $relatedEntityClass - ) { - $this->relatedEntityClass = $relatedEntityClass; - - $this->expressionBuilder = new Expr(); - } - - /** - * @param BuildBefore $event - */ - public function onBuildBefore(BuildBefore $event) - { - $config = $event->getConfig(); - - $this->addSelect($config); - $this->addJoin($config); - $this->addColumn($config); - $this->addSorter($config); - $this->addFilter($config); - } - - /** - * @param DatagridConfiguration $configuration - * @return string - * @throws \InvalidArgumentException when a root entity not found in the grid - */ - protected function getAlias(DatagridConfiguration $configuration) - { - $rootAlias = $configuration->getOrmQuery()->getRootAlias(); - if (!$rootAlias) { - throw new \InvalidArgumentException( - sprintf( - 'A root entity is missing for grid "%s"', - $configuration->getName() - ) - ); - } - - return $rootAlias; - } - - /** - * @return string - */ - protected function getDataName() - { - return self::DATA_NAME; - } + const DEFAULT_PRICES_COLUMN = 'defaultChannelPrices'; + const SPECIAL_PRICES_COLUMN = 'specialChannelPrices'; /** - * @return string + * @var DoctrineHelper */ - protected function getJoinAlias() - { - return self::JOIN_ALIAS; - } + protected $doctrineHelper; /** - * @param DatagridConfiguration $config + * @param DoctrineHelper $doctrineHelper */ - protected function addSelect(DatagridConfiguration $config) + public function __construct(DoctrineHelper $doctrineHelper) { - $ormQuery = $config->getOrmQuery(); - $ormQuery - ->addSelect( - sprintf( - 'GROUP_CONCAT( - DISTINCT CONCAT_WS(\'|\', %1$s.name, %2$s.value, %2$s.currency) SEPARATOR \';\' - ) as defaultChannelPrices', - self::CHANNEL_JOIN_ALIAS, - self::DEFAULT_JOIN_ALIAS - ) - ) - ->addSelect( - sprintf( - 'GROUP_CONCAT( - DISTINCT CONCAT_WS(\'|\', %1$s.name, %2$s.value, %2$s.currency) SEPARATOR \';\' - ) as specialChannelPrices', - self::CHANNEL_JOIN_ALIAS, - self::SPECIAL_JOIN_ALIAS - ) - ) - ->addSelect(sprintf('sum(%s.value) as defaultChannelPricesSum', self::DEFAULT_JOIN_ALIAS)) - ->addSelect(sprintf('sum(%s.value) as specialChannelPricesSum', self::SPECIAL_JOIN_ALIAS)); + $this->doctrineHelper = $doctrineHelper; } /** - * @param DatagridConfiguration $config + * @param BuildBefore $event */ - protected function addJoin(DatagridConfiguration $config) + public function onBuildBefore(BuildBefore $event) { - $ormQuery = $config->getOrmQuery(); - $ormQuery - ->addLeftJoin(sprintf('%s.%s', $this->getAlias($config), self::DATA_NAME), $this->getJoinAlias()) - ->addLeftJoin(sprintf('%s.%s', $this->getJoinAlias(), self::CHANNEL_DATA_NAME), self::CHANNEL_JOIN_ALIAS) - ->addLeftJoin(sprintf('%s.%s', $this->getJoinAlias(), self::DEFAULT_DATA_NAME), self::DEFAULT_JOIN_ALIAS) - ->addLeftJoin(sprintf('%s.%s', $this->getJoinAlias(), self::SPECIAL_DATA_NAME), self::SPECIAL_JOIN_ALIAS); - } + $config = $event->getConfig(); - /** - * @param DatagridConfiguration $config - */ - protected function addColumn(DatagridConfiguration $config) - { - $config->offsetSetByPath(sprintf('[columns][%s]', 'defaultChannelPrices'), [ + $config->offsetSetByPath(sprintf('[columns][%s]', self::DEFAULT_PRICES_COLUMN), [ 'label' => 'marello.pricing.assembledchannelpricelist.default_price.plural_label', 'type' => 'twig', 'frontend_type' => 'html', @@ -139,7 +41,7 @@ protected function addColumn(DatagridConfiguration $config) 'renderable' => false, 'align' => 'right' ]); - $config->offsetSetByPath(sprintf('[columns][%s]', 'specialChannelPrices'), [ + $config->offsetSetByPath(sprintf('[columns][%s]', self::SPECIAL_PRICES_COLUMN), [ 'label' => 'marello.pricing.assembledchannelpricelist.special_price.plural_label', 'type' => 'twig', 'frontend_type' => 'html', @@ -150,41 +52,68 @@ protected function addColumn(DatagridConfiguration $config) } /** - * @param DatagridConfiguration $config + * @param OrmResultAfter $event */ - protected function addSorter(DatagridConfiguration $config) + public function onResultAfter(OrmResultAfter $event) { - $config - ->offsetSetByPath( - sprintf('[sorters][columns][%s]', 'defaultChannelPrices'), - ['data_name' => 'defaultChannelPricesSum'] - ) - ->offsetSetByPath( - sprintf('[sorters][columns][%s]', 'specialChannelPrices'), - ['data_name' => 'specialChannelPricesSum'] - ); + /** @var ResultRecord[] $records */ + $records = $event->getRecords(); + + $productIds = array_map( + function (ResultRecord $record) { + return $record->getValue('id'); + }, + $records + ); + + $this->addProductPrices($productIds, $records); } /** - * @param DatagridConfiguration $config + * @param array $productIds + * @param array|ResultRecord[] $records */ - protected function addFilter(DatagridConfiguration $config) + protected function addProductPrices(array $productIds, array $records) { - $config->offsetSetByPath( - sprintf('[filters][columns][%s]', 'defaultChannelPrices'), - [ - 'type' => 'number', - 'data_name' => self::DEFAULT_JOIN_ALIAS . '.value', - 'enabled' => false, - ] - ); - $config->offsetSetByPath( - sprintf('[filters][columns][%s]', 'specialChannelPrices'), - [ - 'type' => 'number', - 'data_name' => self::SPECIAL_JOIN_ALIAS . '.value', - 'enabled' => false, - ] - ); + $groupedPrices = $this->getPrices($productIds); + + foreach ($records as $record) { + $priceLists = []; + $productId = $record->getValue('id'); + + if (array_key_exists($productId, $groupedPrices)) { + /** @var AssembledChannelPriceList[] $priceLists */ + $priceLists = $groupedPrices[$productId]; + } + $data = []; + foreach ($priceLists as $priceList) { + if ($priceList->getDefaultPrice()) { + $data[self::DEFAULT_PRICES_COLUMN][] = $priceList->getDefaultPrice(); + } + if ($priceList->getSpecialPrice()) { + $data[self::SPECIAL_PRICES_COLUMN][] = $priceList->getSpecialPrice(); + } + } + + $record->addData($data); + } + } + + /** + * @param array $productIds + * @return array + */ + protected function getPrices(array $productIds) + { + $prices = $this->doctrineHelper + ->getEntityRepository(AssembledChannelPriceList::class) + ->findBy(['product' => $productIds]); + + $result = []; + foreach ($prices as $price) { + $result[$price->getProduct()->getId()][] = $price; + } + + return $result; } } diff --git a/src/Marello/Bundle/PricingBundle/EventListener/Datagrid/PricesDatagridListener.php b/src/Marello/Bundle/PricingBundle/EventListener/Datagrid/PricesDatagridListener.php index 0a0fa4b17..176db9b8f 100644 --- a/src/Marello/Bundle/PricingBundle/EventListener/Datagrid/PricesDatagridListener.php +++ b/src/Marello/Bundle/PricingBundle/EventListener/Datagrid/PricesDatagridListener.php @@ -2,143 +2,39 @@ namespace Marello\Bundle\PricingBundle\EventListener\Datagrid; -use Doctrine\ORM\Query\Expr; -use Oro\Bundle\DataGridBundle\Datagrid\Common\DatagridConfiguration; +use Marello\Bundle\PricingBundle\Entity\AssembledPriceList; +use Oro\Bundle\DataGridBundle\Datasource\ResultRecord; use Oro\Bundle\DataGridBundle\Event\BuildBefore; +use Oro\Bundle\DataGridBundle\Event\OrmResultAfter; +use Oro\Bundle\EntityBundle\ORM\DoctrineHelper; class PricesDatagridListener { - const DATA_NAME = 'prices'; - const JOIN_ALIAS = 'pr'; - const DEFAULT_DATA_NAME = 'defaultPrice'; - const DEFAULT_JOIN_ALIAS = 'defpr'; - const SPECIAL_DATA_NAME = 'specialPrice'; - const SPECIAL_JOIN_ALIAS = 'sppr'; - const MSRP_DATA_NAME = 'msrpPrice'; - const MSRP_JOIN_ALIAS = 'mspr'; - - /** @var string */ - protected $relatedEntityClass; - - /** @var Expr */ - protected $expressionBuilder; - - /** - * @param string $relatedEntityClass - */ - public function __construct( - $relatedEntityClass - ) { - $this->relatedEntityClass = $relatedEntityClass; - - $this->expressionBuilder = new Expr(); - } - - /** - * @param BuildBefore $event - */ - public function onBuildBefore(BuildBefore $event) - { - $config = $event->getConfig(); - - $this->addSelect($config); - $this->addJoin($config); - $this->addColumn($config); - $this->addSorter($config); - $this->addFilter($config); - } + const DEFAULT_PRICES_COLUMN = 'defaultPrices'; + const SPECIAL_PRICES_COLUMN = 'specialPrices'; + const MSRP_PRICES_COLUMN = 'msrpPrices'; /** - * @param DatagridConfiguration $configuration - * @return string - * @throws \InvalidArgumentException when a root entity not found in the grid + * @var DoctrineHelper */ - protected function getAlias(DatagridConfiguration $configuration) - { - $rootAlias = $configuration->getOrmQuery()->getRootAlias(); - if (!$rootAlias) { - throw new \InvalidArgumentException( - sprintf( - 'A root entity is missing for grid "%s"', - $configuration->getName() - ) - ); - } - - return $rootAlias; - } + protected $doctrineHelper; /** - * @return string + * @param DoctrineHelper $doctrineHelper */ - protected function getDataName() + public function __construct(DoctrineHelper $doctrineHelper) { - return self::DATA_NAME; + $this->doctrineHelper = $doctrineHelper; } /** - * @return string - */ - protected function getJoinAlias() - { - return self::JOIN_ALIAS; - } - - /** - * @param DatagridConfiguration $config - */ - protected function addSelect(DatagridConfiguration $config) - { - $ormQuery = $config->getOrmQuery(); - $ormQuery - ->addSelect( - sprintf( - 'GROUP_CONCAT( - DISTINCT CONCAT_WS(\'|\', %1$s.value, %1$s.currency) SEPARATOR \';\' - ) as defaultPrices', - self::DEFAULT_JOIN_ALIAS - ) - ) - ->addSelect( - sprintf( - 'GROUP_CONCAT( - DISTINCT CONCAT_WS(\'|\', %1$s.value, %1$s.currency) SEPARATOR \';\' - ) as specialPrices', - self::SPECIAL_JOIN_ALIAS - ) - ) - ->addSelect( - sprintf( - 'GROUP_CONCAT( - DISTINCT CONCAT_WS(\'|\', %1$s.value, %1$s.currency) SEPARATOR \';\' - ) as msrpPrices', - self::MSRP_JOIN_ALIAS - ) - ) - ->addSelect(sprintf('SUM(%s.value) as defaultPricesSum', self::DEFAULT_JOIN_ALIAS)) - ->addSelect(sprintf('SUM(%s.value) as specialPricesSum', self::SPECIAL_JOIN_ALIAS)) - ->addSelect(sprintf('SUM(%s.value) as msrpPricesSum', self::MSRP_JOIN_ALIAS)); - } - - /** - * @param DatagridConfiguration $config + * @param BuildBefore $event */ - protected function addJoin(DatagridConfiguration $config) + public function onBuildBefore(BuildBefore $event) { - $ormQuery = $config->getOrmQuery(); - $ormQuery - ->addLeftJoin(sprintf('%s.%s', $this->getAlias($config), self::DATA_NAME), $this->getJoinAlias()) - ->addLeftJoin(sprintf('%s.%s', $this->getJoinAlias(), self::DEFAULT_DATA_NAME), self::DEFAULT_JOIN_ALIAS) - ->addLeftJoin(sprintf('%s.%s', $this->getJoinAlias(), self::SPECIAL_DATA_NAME), self::SPECIAL_JOIN_ALIAS) - ->addLeftJoin(sprintf('%s.%s', $this->getJoinAlias(), self::MSRP_DATA_NAME), self::MSRP_JOIN_ALIAS); - } + $config = $event->getConfig(); - /** - * @param DatagridConfiguration $config - */ - protected function addColumn(DatagridConfiguration $config) - { - $config->offsetSetByPath(sprintf('[columns][%s]', 'defaultPrices'), [ + $config->offsetSetByPath(sprintf('[columns][%s]', self::DEFAULT_PRICES_COLUMN), [ 'label' => 'marello.pricing.assembledpricelist.default_price.plural_label', 'type' => 'twig', 'frontend_type' => 'html', @@ -146,7 +42,7 @@ protected function addColumn(DatagridConfiguration $config) 'renderable' => false, 'align' => 'right' ]); - $config->offsetSetByPath(sprintf('[columns][%s]', 'specialPrices'), [ + $config->offsetSetByPath(sprintf('[columns][%s]', self::SPECIAL_PRICES_COLUMN), [ 'label' => 'marello.pricing.assembledpricelist.special_price.plural_label', 'type' => 'twig', 'frontend_type' => 'html', @@ -154,7 +50,7 @@ protected function addColumn(DatagridConfiguration $config) 'renderable' => false, 'align' => 'right' ]); - $config->offsetSetByPath(sprintf('[columns][%s]', 'msrpPrices'), [ + $config->offsetSetByPath(sprintf('[columns][%s]', self::MSRP_PRICES_COLUMN), [ 'label' => 'marello.pricing.assembledpricelist.msrp_price.plural_label', 'type' => 'twig', 'frontend_type' => 'html', @@ -165,44 +61,71 @@ protected function addColumn(DatagridConfiguration $config) } /** - * @param DatagridConfiguration $config + * @param OrmResultAfter $event */ - protected function addSorter(DatagridConfiguration $config) + public function onResultAfter(OrmResultAfter $event) { - $config - ->offsetSetByPath(sprintf('[sorters][columns][%s]', 'defaultPrices'), ['data_name' => 'defaultPricesSum']) - ->offsetSetByPath(sprintf('[sorters][columns][%s]', 'specialPrices'), ['data_name' => 'specialPricesSum']) - ->offsetSetByPath(sprintf('[sorters][columns][%s]', 'msrpPrices'), ['data_name' => 'msrpPricesSum']); + /** @var ResultRecord[] $records */ + $records = $event->getRecords(); + + $productIds = array_map( + function (ResultRecord $record) { + return $record->getValue('id'); + }, + $records + ); + + $this->addProductPrices($productIds, $records); } /** - * @param DatagridConfiguration $config + * @param array $productIds + * @param array|ResultRecord[] $records */ - protected function addFilter(DatagridConfiguration $config) + protected function addProductPrices(array $productIds, array $records) { - $config->offsetSetByPath( - sprintf('[filters][columns][%s]', 'defaultPrices'), - [ - 'type' => 'number', - 'data_name' => self::DEFAULT_JOIN_ALIAS . '.value', - 'enabled' => false, - ] - ); - $config->offsetSetByPath( - sprintf('[filters][columns][%s]', 'specialPrices'), - [ - 'type' => 'number', - 'data_name' => self::SPECIAL_JOIN_ALIAS . '.value', - 'enabled' => false, - ] - ); - $config->offsetSetByPath( - sprintf('[filters][columns][%s]', 'msrpPrices'), - [ - 'type' => 'number', - 'data_name' => self::MSRP_JOIN_ALIAS . '.value', - 'enabled' => false, - ] - ); + $groupedPrices = $this->getPrices($productIds); + + foreach ($records as $record) { + $priceLists = []; + $productId = $record->getValue('id'); + + if (array_key_exists($productId, $groupedPrices)) { + /** @var AssembledPriceList[] $priceLists */ + $priceLists = $groupedPrices[$productId]; + } + $data = []; + foreach ($priceLists as $priceList) { + if ($priceList->getDefaultPrice()) { + $data[self::DEFAULT_PRICES_COLUMN][] = $priceList->getDefaultPrice(); + } + if ($priceList->getSpecialPrice()) { + $data[self::SPECIAL_PRICES_COLUMN][] = $priceList->getSpecialPrice(); + } + if ($priceList->getMsrpPrice()) { + $data[self::MSRP_PRICES_COLUMN][] = $priceList->getMsrpPrice(); + } + } + + $record->addData($data); + } + } + + /** + * @param array $productIds + * @return array + */ + protected function getPrices(array $productIds) + { + $prices = $this->doctrineHelper + ->getEntityRepository(AssembledPriceList::class) + ->findBy(['product' => $productIds]); + + $result = []; + foreach ($prices as $price) { + $result[$price->getProduct()->getId()][] = $price; + } + + return $result; } } diff --git a/src/Marello/Bundle/PricingBundle/Resources/config/services.yml b/src/Marello/Bundle/PricingBundle/Resources/config/services.yml index 3fd6760df..6bfed6d6e 100644 --- a/src/Marello/Bundle/PricingBundle/Resources/config/services.yml +++ b/src/Marello/Bundle/PricingBundle/Resources/config/services.yml @@ -69,13 +69,15 @@ services: marello_productprice.pricing.listener.datagrid.products_grid.prices: class: 'Marello\Bundle\PricingBundle\EventListener\Datagrid\PricesDatagridListener' arguments: - - 'Marello\Bundle\ProductBundle\Entity\Product' + - '@oro_entity.doctrine_helper' tags: - { name: kernel.event_listener, event: oro_datagrid.datagrid.build.before.marello-products-grid, method: onBuildBefore } + - { name: kernel.event_listener, event: oro_datagrid.orm_datasource.result.after.marello-products-grid, method: onResultAfter } marello_productprice.pricing.listener.datagrid.products_grid.channel_prices: class: 'Marello\Bundle\PricingBundle\EventListener\Datagrid\ChannelPricesDatagridListener' arguments: - - 'Marello\Bundle\ProductBundle\Entity\Product' + - '@oro_entity.doctrine_helper' tags: - - { name: kernel.event_listener, event: oro_datagrid.datagrid.build.before.marello-products-grid, method: onBuildBefore } \ No newline at end of file + - { name: kernel.event_listener, event: oro_datagrid.datagrid.build.before.marello-products-grid, method: onBuildBefore } + - { name: kernel.event_listener, event: oro_datagrid.orm_datasource.result.after.marello-products-grid, method: onResultAfter } \ No newline at end of file diff --git a/src/Marello/Bundle/PricingBundle/Resources/views/Datagrid/Property/defaultChannelPrices.html.twig b/src/Marello/Bundle/PricingBundle/Resources/views/Datagrid/Property/defaultChannelPrices.html.twig index 63a2d5436..3875a5c33 100644 --- a/src/Marello/Bundle/PricingBundle/Resources/views/Datagrid/Property/defaultChannelPrices.html.twig +++ b/src/Marello/Bundle/PricingBundle/Resources/views/Datagrid/Property/defaultChannelPrices.html.twig @@ -1,7 +1,4 @@ -{% set prices = record.getValue('defaultChannelPrices')|split(';') %} -{% for index, valueSet in prices %} - {% set values = valueSet|split('|') %} - {% if values|length == 3 %} - {{ values[0] }}: {{ values[1]|oro_format_currency({'currency': values[2]}) }}
- {% endif %} +{% set prices = record.getValue('defaultChannelPrices') %} +{% for index, price in prices %} + {{ price.channel.name ~ ': ' ~ price.value|oro_format_currency({'currency': price.currency}) }}
{% endfor %} diff --git a/src/Marello/Bundle/PricingBundle/Resources/views/Datagrid/Property/defaultPrices.html.twig b/src/Marello/Bundle/PricingBundle/Resources/views/Datagrid/Property/defaultPrices.html.twig index cac4859ba..bf7a5312e 100644 --- a/src/Marello/Bundle/PricingBundle/Resources/views/Datagrid/Property/defaultPrices.html.twig +++ b/src/Marello/Bundle/PricingBundle/Resources/views/Datagrid/Property/defaultPrices.html.twig @@ -1,7 +1,4 @@ -{% set prices = record.getValue('defaultPrices')|split(';') %} -{% for index, valueSet in prices %} - {% set values = valueSet|split('|') %} - {% if values|length == 2 %} - {{ values[0]|oro_format_currency({'currency': values[1]}) }}
- {% endif %} +{% set prices = record.getValue('defaultPrices') %} +{% for index, price in prices %} + {{ price.value|oro_format_currency({'currency': price.currency}) }}
{% endfor %} \ No newline at end of file diff --git a/src/Marello/Bundle/PricingBundle/Resources/views/Datagrid/Property/msrpPrices.html.twig b/src/Marello/Bundle/PricingBundle/Resources/views/Datagrid/Property/msrpPrices.html.twig index c2bd44916..ed6ace409 100644 --- a/src/Marello/Bundle/PricingBundle/Resources/views/Datagrid/Property/msrpPrices.html.twig +++ b/src/Marello/Bundle/PricingBundle/Resources/views/Datagrid/Property/msrpPrices.html.twig @@ -1,7 +1,4 @@ -{% set prices = record.getValue('msrpPrices')|split(';') %} -{% for index, valueSet in prices %} - {% set values = valueSet|split('|') %} - {% if values|length == 2 %} - {{ values[0]|oro_format_currency({'currency': values[1]}) }}
- {% endif %} +{% set prices = record.getValue('msrpPrices') %} +{% for index, price in prices %} + {{ price.value|oro_format_currency({'currency': price.currency}) }}
{% endfor %} \ No newline at end of file diff --git a/src/Marello/Bundle/PricingBundle/Resources/views/Datagrid/Property/specialChannelPrices.html.twig b/src/Marello/Bundle/PricingBundle/Resources/views/Datagrid/Property/specialChannelPrices.html.twig index b625f13de..2fe08e90a 100644 --- a/src/Marello/Bundle/PricingBundle/Resources/views/Datagrid/Property/specialChannelPrices.html.twig +++ b/src/Marello/Bundle/PricingBundle/Resources/views/Datagrid/Property/specialChannelPrices.html.twig @@ -1,7 +1,4 @@ -{% set prices = record.getValue('specialChannelPrices')|split(';') %} -{% for index, valueSet in prices %} - {% set values = valueSet|split('|') %} - {% if values|length == 3 %} - {{ values[0] }}: {{ values[1]|oro_format_currency({'currency': values[2]}) }}
- {% endif %} +{% set prices = record.getValue('specialChannelPrices') %} +{% for index, price in prices %} + {{ price.channel.name ~ ': ' ~ price.value|oro_format_currency({'currency': price.currency}) }}
{% endfor %} \ No newline at end of file diff --git a/src/Marello/Bundle/PricingBundle/Resources/views/Datagrid/Property/specialPrices.html.twig b/src/Marello/Bundle/PricingBundle/Resources/views/Datagrid/Property/specialPrices.html.twig index 7791957fb..dea509bf7 100644 --- a/src/Marello/Bundle/PricingBundle/Resources/views/Datagrid/Property/specialPrices.html.twig +++ b/src/Marello/Bundle/PricingBundle/Resources/views/Datagrid/Property/specialPrices.html.twig @@ -1,7 +1,4 @@ -{% set prices = record.getValue('specialPrices')|split(';') %} -{% for index, valueSet in prices %} - {% set values = valueSet|split('|') %} - {% if values|length == 2 %} - {{ values[0]|oro_format_currency({'currency': values[1]}) }}
- {% endif %} +{% set prices = record.getValue('specialPrices') %} +{% for index, price in prices %} + {{ price.value|oro_format_currency({'currency': price.currency}) }}
{% endfor %} \ No newline at end of file diff --git a/src/Marello/Bundle/PricingBundle/Tests/Functional/Api/AssembledChannelPriceListJsonApiTest.php b/src/Marello/Bundle/PricingBundle/Tests/Functional/Api/AssembledChannelPriceListJsonApiTest.php index 049a05343..5553ab726 100644 --- a/src/Marello/Bundle/PricingBundle/Tests/Functional/Api/AssembledChannelPriceListJsonApiTest.php +++ b/src/Marello/Bundle/PricingBundle/Tests/Functional/Api/AssembledChannelPriceListJsonApiTest.php @@ -11,7 +11,10 @@ use Marello\Bundle\SalesBundle\Tests\Functional\DataFixtures\LoadSalesData; use Marello\Bundle\ProductBundle\Tests\Functional\DataFixtures\LoadProductData; use Marello\Bundle\PricingBundle\Tests\Functional\DataFixtures\LoadProductChannelPricingData; - +/** + * @dbIsolationPerTest + * @nestTransactionsWithSavepoints + */ class AssembledChannelPriceListJsonApiTest extends RestJsonApiTestCase { const TESTING_ENTITY = 'marelloassembledchannelpricelists'; diff --git a/src/Marello/Bundle/ProductBundle/Controller/ProductController.php b/src/Marello/Bundle/ProductBundle/Controller/ProductController.php index dc70dc63c..c43412f3f 100644 --- a/src/Marello/Bundle/ProductBundle/Controller/ProductController.php +++ b/src/Marello/Bundle/ProductBundle/Controller/ProductController.php @@ -59,22 +59,25 @@ public function createAction(Request $request) */ protected function createStepOne(Request $request) { - $form = $this->createForm(ProductStepOneType::class); + $form = $this->createForm(ProductStepOneType::class, new Product()); $handler = new ProductCreateStepOneHandler($form, $request); - $productTypesProvider = $this->get('marello_product.provider.product_types'); - $em = $this->get('doctrine.orm.entity_manager'); - /** @var AttributeFamily $attributeFamily */ - $attributeFamilies = $em - ->getRepository(AttributeFamily::class) - ->findBy(['entityClass' => Product::class]); + $queryParams = $request->query->all(); + if ($handler->process()) { - return $this->forward('MarelloProductBundle:Product:createStepTwo'); + return $this->forward('MarelloProductBundle:Product:createStepTwo', [], $queryParams); } - if (count($productTypesProvider->getProductTypes()) <= 1 && count($attributeFamilies) <= 1) { + + $productTypesProvider = $this->get('marello_product.provider.product_types'); + $em = $this->get('oro_entity.doctrine_helper'); + /** @var AttributeFamily $attributeFamily */ + $countAttributeFamilies = $em + ->getEntityRepositoryForClass(AttributeFamily::class) + ->countFamiliesByEntityClass(Product::class); + if (count($productTypesProvider->getProductTypes()) <= 1 && $countAttributeFamilies <= 1) { $request->setMethod('POST'); $request->request->set('input_action', 'marello_product_create'); $request->request->set('single_product_type', true); - return $this->forward('MarelloProductBundle:Product:createStepTwo'); + return $this->forward('MarelloProductBundle:Product:createStepTwo', [], $queryParams); } return [ @@ -109,27 +112,34 @@ public function createStepTwoAction(Request $request) protected function createStepTwo(Request $request, Product $product) { if ($request->get('input_action') === 'marello_product_create') { - $formStepOne = $this->createForm(ProductStepOneType::class, $product); - $em = $this->get('doctrine.orm.entity_manager'); + $form = $this->createForm(ProductStepOneType::class, $product); + $queryParams = $request->query->all(); + $form->handleRequest($request); + $formData = $form->all(); + if ($request->get('single_product_type')) { - $type = Product::DEFAULT_PRODUCT_TYPE; + $em = $this->get('oro_entity.doctrine_helper'); + /** @var AttributeFamily $attributeFamily */ $attributeFamily = $em - ->getRepository(AttributeFamily::class) + ->getEntityRepositoryForClass(AttributeFamily::class) ->findOneBy(['entityClass' => Product::class]); - } else { - $formStepOne->handleRequest($request); - $type = $formStepOne->get('type')->getData(); - $attributeFamily = $formStepOne->get('attributeFamily')->getData(); + $product->setType(Product::DEFAULT_PRODUCT_TYPE); + $product->setAttributeFamily($attributeFamily); } - $product->setType($type); - $product->setAttributeFamily($attributeFamily); - $form = $this->createForm(ProductType::class, $product); + if (!empty($formData)) { + $form = $this->createForm(ProductType::class, $product); + foreach ($formData as $key => $item) { + $data = $item->getData(); + $form->get($key)->setData($data); + } + } return [ 'form' => $form->createView(), 'entity' => $product, - 'isWidgetContext' => (bool)$request->get('_wid', false) + 'isWidgetContext' => (bool)$request->get('_wid', false), + 'queryParams' => $queryParams ]; } diff --git a/src/Marello/Bundle/ProductBundle/Entity/Builder/ProductFamilyBuilder.php b/src/Marello/Bundle/ProductBundle/Entity/Builder/ProductFamilyBuilder.php new file mode 100644 index 000000000..842694727 --- /dev/null +++ b/src/Marello/Bundle/ProductBundle/Entity/Builder/ProductFamilyBuilder.php @@ -0,0 +1,107 @@ + 'General', + 'groupCode' => 'general', + 'attributes' => [ + 'sku', + 'names', + 'channels', + 'status', + 'prices', + 'channelPrices', + 'taxCode', + 'salesChannelTaxCodes', + 'weight', + 'manufacturingCode', + 'warranty', + 'suppliers', + 'categories', + 'image', + ], + 'groupVisibility' => true, + ] + ]; + + /** @var TranslatorInterface */ + private $translator; + + /** @var AttributeGroupManager */ + private $attributeGroupManager; + + /** @var AttributeFamily */ + private $family; + + /** + * @param TranslatorInterface $translator + * @param AttributeGroupManager $attributeGroupManager + */ + public function __construct(TranslatorInterface $translator, AttributeGroupManager $attributeGroupManager) + { + $this->translator = $translator; + $this->attributeGroupManager = $attributeGroupManager; + } + + /** + * @param Organization $organization + * @return $this + */ + public function createDefaultFamily(Organization $organization) + { + $this->family = new AttributeFamily(); + $this->family->setCode(self::DEFAULT_FAMILY_CODE); + $this->family->setEntityClass(Product::class); + $this->family->setOwner($organization); + $this->family->setDefaultLabel( + $this->translator->trans('oro.entityconfig.attribute.entity.attributefamily.default.label') + ); + + return $this; + } + + /** + * @return $this + */ + public function addDefaultAttributeGroups() + { + if (!$this->family instanceof AttributeFamily) { + throw new \LogicException( + sprintf('Attribute groups can only be added to an instance of %s.', AttributeFamily::class) + ); + } + $attributeGroups = $this->attributeGroupManager->createGroupsWithAttributes( + Product::class, + self::$groups + ); + foreach ($attributeGroups as $attributeGroup) { + $this->family->addAttributeGroup($attributeGroup); + } + + return $this; + } + + /** + * @return AttributeFamily|null + */ + public function getFamily(): ?AttributeFamily + { + return $this->family; + } +} diff --git a/src/Marello/Bundle/ProductBundle/Entity/Product.php b/src/Marello/Bundle/ProductBundle/Entity/Product.php index 835ec31a3..cb1c63408 100644 --- a/src/Marello/Bundle/ProductBundle/Entity/Product.php +++ b/src/Marello/Bundle/ProductBundle/Entity/Product.php @@ -35,8 +35,8 @@ * }, * uniqueConstraints={ * @ORM\UniqueConstraint( - * name="marello_product_product_skuidx", - * columns={"sku"} + * name="marello_product_product_skuorgidx", + * columns={"sku","organization_id"} * ) * } * ) @@ -362,9 +362,9 @@ class Product extends ExtendProduct implements /** * @var ArrayCollection - * unidirectional many-to-many * @ORM\ManyToMany(targetEntity="Marello\Bundle\SalesBundle\Entity\SalesChannel", - * fetch="EAGER" + * inversedBy="products", + * fetch="EAGER" * ) * @ORM\JoinTable(name="marello_product_saleschannel") * @Oro\ConfigField( @@ -386,6 +386,23 @@ class Product extends ExtendProduct implements */ protected $channels; + /** + * @var string + * + * @ORM\Column(name="channels_codes", type="text", nullable=true) + * @Oro\ConfigField( + * defaultValues={ + * "dataaudit"={ + * "auditable"=true + * }, + * "importexport"={ + * "excluded"=true + * } + * } + * ) + */ + protected $channelsCodes; + /** * @var Variant * @@ -546,7 +563,7 @@ class Product extends ExtendProduct implements /** * @var ArrayCollection|Category[] * - * @ORM\ManyToMany(targetEntity="Marello\Bundle\CatalogBundle\Entity\Category", mappedBy="products") + * @ORM\ManyToMany(targetEntity="Marello\Bundle\CatalogBundle\Entity\Category", mappedBy="products", fetch="EAGER") * @Oro\ConfigField( * defaultValues={ * "dataaudit"={ @@ -566,6 +583,23 @@ class Product extends ExtendProduct implements */ protected $categories; + /** + * @var string + * + * @ORM\Column(name="categories_codes", type="text", nullable=true) + * @Oro\ConfigField( + * defaultValues={ + * "dataaudit"={ + * "auditable"=true + * }, + * "importexport"={ + * "excluded"=true + * } + * } + * ) + */ + protected $categoriesCodes; + /** * @var AttributeFamily * @@ -916,6 +950,33 @@ public function addChannel(SalesChannel $channel) { if (!$this->channels->contains($channel)) { $this->channels->add($channel); + $this->addChannelCode($channel->getCode()); + } + + return $this; + } + + /** + * @param string $code + * @return $this + */ + public function addChannelCode($code) + { + if (strpos($this->channelsCodes, '|') === false) { + $channelsCodes = []; + } else { + $channelsCodes = $this->channelsCodes; + if (substr($channelsCodes, 0, 1) === '|') { + $channelsCodes = substr($channelsCodes, 1); + } + if (substr($channelsCodes, -1, 1) === '|') { + $channelsCodes = substr($channelsCodes, 0, -1); + } + $channelsCodes = explode("|", $channelsCodes); + } + if (!in_array($code, $channelsCodes)) { + $channelsCodes[] = $code; + $this->channelsCodes = sprintf('|%s|', implode('|', $channelsCodes)); } return $this; @@ -949,6 +1010,16 @@ public function removeChannel(SalesChannel $channel) { if ($this->channels->contains($channel)) { $this->channels->removeElement($channel); + $channelsCodes = $this->channelsCodes; + if (substr($channelsCodes, 0, 1) === '|') { + $channelsCodes = substr($channelsCodes, 1); + } + if (substr($channelsCodes, -1, 1) === '|') { + $channelsCodes = substr($channelsCodes, 0, -1); + } + $channelsCodes = explode("|", $channelsCodes); + $channelsCodes = array_diff([$channelsCodes], [$channel->getCode()]); + $this->channelsCodes = sprintf('|%s|', implode('|', $channelsCodes)); } return $this; @@ -1280,7 +1351,36 @@ public function addCategory(Category $category) { if (!$this->hasCategory($category)) { $this->categories->add($category); - $category->addProduct($this); + if (!$category->hasProduct($this)) { + $category->addProduct($this); + } + $this->addCategoryCode($category->getCode()); + } + + return $this; + } + + /** + * @param string $code + * @return $this + */ + public function addCategoryCode($code) + { + if (strpos($this->categoriesCodes, '|') === false) { + $categoriesCodes = []; + } else { + $categoriesCodes = $this->categoriesCodes; + if (substr($categoriesCodes, 0, 1) === '|') { + $categoriesCodes = substr($categoriesCodes, 1); + } + if (substr($categoriesCodes, -1, 1) === '|') { + $categoriesCodes = substr($categoriesCodes, 0, -1); + } + $categoriesCodes = explode("|", $categoriesCodes); + } + if (!in_array($code, $categoriesCodes)) { + $categoriesCodes[] = $code; + $this->categoriesCodes = sprintf('|%s|', implode('|', $categoriesCodes)); } return $this; @@ -1295,10 +1395,21 @@ public function removeCategory(Category $category) if ($this->hasCategory($category)) { $this->categories->removeElement($category); $category->removeProduct($this); + $categoriesCodes = $this->categoriesCodes; + if (substr($categoriesCodes, 0, 1) === '|') { + $categoriesCodes = substr($categoriesCodes, 1); + } + if (substr($categoriesCodes, -1, 1) === '|') { + $categoriesCodes = substr($categoriesCodes, 0, -1); + } + $categoriesCodes = explode("|", $categoriesCodes); + $categoriesCodes = array_diff([$categoriesCodes], [$category->getCode()]); + $this->categoriesCodes = sprintf('|%s|', implode('|', $categoriesCodes)); } return $this; } + /** * @param Category $category diff --git a/src/Marello/Bundle/ProductBundle/Entity/Repository/ProductRepository.php b/src/Marello/Bundle/ProductBundle/Entity/Repository/ProductRepository.php index fdcf6b0e2..1d1b7ecff 100644 --- a/src/Marello/Bundle/ProductBundle/Entity/Repository/ProductRepository.php +++ b/src/Marello/Bundle/ProductBundle/Entity/Repository/ProductRepository.php @@ -6,6 +6,7 @@ use Marello\Bundle\ProductBundle\Entity\Product; use Marello\Bundle\SalesBundle\Entity\SalesChannel; +use Oro\Bundle\OrganizationBundle\Entity\Organization; use Oro\Bundle\SecurityBundle\ORM\Walker\AclHelper; class ProductRepository extends EntityRepository @@ -133,17 +134,24 @@ public function findBySalesChannel($salesChannel, array $productIds) } /** - * @param string $sku - * - * @return null|Product + * @param $sku + * @param Organization|null $organization + * @return int|mixed|string|null + * @throws \Doctrine\ORM\NonUniqueResultException */ - public function findOneBySku($sku) + public function findOneBySku($sku, Organization $organization = null) { $queryBuilder = $this->createQueryBuilder('product'); $queryBuilder->andWhere('UPPER(product.sku) = :sku') ->setParameter('sku', strtoupper($sku)); + if ($organization) { + $queryBuilder + ->andWhere('product.organization = :organization') + ->setParameter('organization', $organization); + } + return $this->aclHelper->apply($queryBuilder->getQuery())->getOneOrNullResult(); } @@ -200,8 +208,8 @@ public function getPurchaseOrderItemsCandidates() ->select( 'sup.name AS supplier, p.sku, - (i.desiredInventory - COALESCE(SUM(l.inventory - l.allocatedInventory), 0)) AS orderAmount, - i.purchaseInventory' + SUM(i.desiredInventory - COALESCE((l.inventory - l.allocatedInventory), 0)) AS orderAmount, + SUM(i.purchaseInventory) AS purchaseInventory' ) ->innerJoin('p.preferredSupplier', 'sup') ->innerJoin('p.status', 's') @@ -210,7 +218,7 @@ public function getPurchaseOrderItemsCandidates() ->where("sup.name <> ''") ->andWhere("s.name = 'enabled'") ->andWhere("i.replenishment = 'never_out_of_stock'") - ->groupBy('p.sku, sup.name, i.desiredInventory, i.purchaseInventory') + ->groupBy('sup.name, p.sku, i.desiredInventory, i.purchaseInventory') ->having('SUM(l.inventory - l.allocatedInventory) < i.purchaseInventory'); return $this->aclHelper->apply($qb->getQuery())->getResult(); diff --git a/src/Marello/Bundle/ProductBundle/EventListener/Datagrid/AbstractProductsGridListener.php b/src/Marello/Bundle/ProductBundle/EventListener/Datagrid/AbstractProductsGridListener.php new file mode 100644 index 000000000..cff24ada7 --- /dev/null +++ b/src/Marello/Bundle/ProductBundle/EventListener/Datagrid/AbstractProductsGridListener.php @@ -0,0 +1,55 @@ +doctrineHelper = $doctrineHelper; + } + + /** + * @param OrmResultAfter $event + */ + public function onResultAfter(OrmResultAfter $event) + { + /** @var ResultRecord[] $records */ + $records = $event->getRecords(); + $firstRecord = $records[0]; + if (!$firstRecord->getValue('product')) { + $productIds = array_map( + function (ResultRecord $record) { + return $record->getValue('id'); + }, + $records + ); + /** @var Product[] $products */ + $products = $this->doctrineHelper + ->getEntityRepository(Product::class) + ->findBy(['id' => $productIds]); + foreach ($records as $record) { + foreach ($products as $product) { + $productId = $record->getValue('id'); + if ($productId == $product->getId()) { + $record->addData(['product' => $product]); + break; + } + } + } + } + } +} diff --git a/src/Marello/Bundle/ProductBundle/EventListener/Datagrid/ProductGridListener.php b/src/Marello/Bundle/ProductBundle/EventListener/Datagrid/ProductGridListener.php index a88b2150f..0824c9c26 100644 --- a/src/Marello/Bundle/ProductBundle/EventListener/Datagrid/ProductGridListener.php +++ b/src/Marello/Bundle/ProductBundle/EventListener/Datagrid/ProductGridListener.php @@ -29,7 +29,8 @@ public function onBuildBefore(BuildBefore $event) ->addSelect('i.id as image') ->addSelect('(CASE WHEN p.image IS NOT NULL THEN true ELSE false END) as hasImage') ->addSelect('IDENTITY(p.status) as status') - ->addLeftJoin('p.image', 'i'); + ->addLeftJoin('p.image', 'i') + ->addGroupBy('i.id'); $columns = $config->offsetGetByPath('[columns]'); $columns = array_merge( [ diff --git a/src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/AssignAttributesToDefaultFamily.php b/src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/AssignAttributesToDefaultFamily.php deleted file mode 100644 index 74b9a76ec..000000000 --- a/src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/AssignAttributesToDefaultFamily.php +++ /dev/null @@ -1,117 +0,0 @@ - [ - 'searchable' => true, - 'filterable' => true, - 'filter_by' => 'exact_value', - 'sortable' => true, - ], - 'names' => [ - 'searchable' => true, - 'filterable' => true, - 'filter_by' => 'exact_value', - 'sortable' => true, - ], - 'channels' => [ - 'visible' => true - ], - 'status' => [ - 'visible' => true - ], - 'prices' => [ - 'visible' => true - ], - 'channelPrices' => [ - 'visible' => true - ], - 'taxCode' => [ - 'visible' => true - ], - 'salesChannelTaxCodes' => [ - 'visible' => true - ], - 'weight' => [ - 'visible' => true - ], - 'manufacturingCode' => [ - 'visible' => true - ], - 'warranty' => [ - 'visible' => true - ], - 'suppliers' => [ - 'visible' => true - ], - 'categories' => [ - 'visible' => true - ], - 'image' => [ - 'visible' => true - ], - ]; - - /** - * {@inheritdoc} - */ - public function load(ObjectManager $manager) - { - $this->updateProductAttributes(self::ATTRIBUTES); - $this->addGroup($manager); - } - - /** - * @param ObjectManager $manager - */ - private function addGroup(ObjectManager $manager) - { - $attributeFamilyRepository = $manager->getRepository(AttributeFamily::class); - - $defaultFamily = - $attributeFamilyRepository->findOneBy([ - 'code' => LoadDefaultAttributeFamilyData::DEFAULT_FAMILY_CODE - ]); - - $attributeGroup = $defaultFamily->getAttributeGroup(LoadDefaultAttributeFamilyData::GENERAL_GROUP_CODE); - - $configManager = $this->getConfigManager(); - foreach (self::ATTRIBUTES as $attribute => $data) { - $fieldConfigModel = $configManager->getConfigFieldModel(Product::class, $attribute); - $attributeGroupRelation = new AttributeGroupRelation(); - $attributeGroupRelation->setEntityConfigFieldId($fieldConfigModel->getId()); - $attributeGroup->addAttributeRelation($attributeGroupRelation); - } - - $manager->persist($attributeGroup); - $manager->flush(); - } - - /** - * @inheritdoc - */ - public function getDependencies() - { - return [ - LoadDefaultAttributeFamilyData::class - ]; - } -} diff --git a/src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/LoadDefaultAttributeFamilyData.php b/src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/LoadDefaultAttributeFamilyData.php deleted file mode 100644 index 7b45dfebf..000000000 --- a/src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/LoadDefaultAttributeFamilyData.php +++ /dev/null @@ -1,102 +0,0 @@ - self::GENERAL_GROUP_LABEL, - 'groupCode' => self::GENERAL_GROUP_CODE, - 'attributes' => [], - 'groupVisibility' => false - ] - ]; - - /** - * {@inheritdoc} - */ - public function getDependencies() - { - return [ - LoadAdminUserData::class - ]; - } - - /** - * @param ObjectManager $manager - */ - public function load(ObjectManager $manager) - { - $organization = $this->getOrganization($manager); - $attributeFamily = new AttributeFamily(); - $attributeFamily->setCode(self::DEFAULT_FAMILY_CODE); - $attributeFamily->setEntityClass(Product::class); - $attributeFamily->addLabel((new LocalizedFallbackValue())->setString('Default')); - $attributeFamily->setOwner($organization); - - $this->setReference(self::DEFAULT_FAMILY_CODE, $attributeFamily); - - $this->addGroupsWithAttributesToFamily($this->data, $attributeFamily, $manager); - } - - /** - * @param ObjectManager $manager - * - * @return Organization|object - */ - private function getOrganization(ObjectManager $manager) - { - if ($this->hasReference(LoadOrganizationAndBusinessUnitData::REFERENCE_DEFAULT_ORGANIZATION)) { - return $this->getReference(LoadOrganizationAndBusinessUnitData::REFERENCE_DEFAULT_ORGANIZATION); - } else { - return $manager - ->getRepository('OroOrganizationBundle:Organization') - ->getFirst(); - } - } - - /** - * - * @param array $groupsData - * @param AttributeFamily $attributeFamily - * @param ObjectManager $manager - */ - protected function addGroupsWithAttributesToFamily( - array $groupsData, - AttributeFamily $attributeFamily, - ObjectManager $manager - ) { - foreach ($groupsData as $groupData) { - $attributeGroup = new AttributeGroup(); - $attributeGroup->addLabel((new LocalizedFallbackValue())->setString($groupData['groupLabel'])); - $attributeGroup->setIsVisible($groupData['groupVisibility']); - $attributeGroup->setCode($groupData['groupCode']); - $attributeFamily->addAttributeGroup($attributeGroup); - } - - $manager->persist($attributeFamily); - $manager->flush(); - } -} diff --git a/src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/LoadDefaultProductFamilyData.php b/src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/LoadDefaultProductFamilyData.php new file mode 100644 index 000000000..3b97ccabf --- /dev/null +++ b/src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/LoadDefaultProductFamilyData.php @@ -0,0 +1,62 @@ +getOrganization($manager); + if ($organization) { + /** @var ProductFamilyBuilder $productFamilyBuilder */ + $productFamilyBuilder = $this->container->get('marello_product.entity.builder.product_family'); + $defaultProductFamily = $productFamilyBuilder + ->createDefaultFamily($organization) + ->addDefaultAttributeGroups() + ->getFamily(); + + $manager->persist($defaultProductFamily); + $manager->flush(); + } + } + + + /** + * @param ObjectManager $manager + * + * @return Organization|null + */ + private function getOrganization(ObjectManager $manager) + { + $queryBuilder = $manager->getRepository(Organization::class) + ->createQueryBuilder('org'); + + $organizations = $queryBuilder + ->leftJoin(AttributeFamily::class, 'family', Join::WITH, 'org.id = family.owner') + ->where($queryBuilder->expr()->isNull('family.owner')) + ->getQuery() + ->getResult(); + if (!empty($organizations)) { + return reset($organizations); + } else { + return null; + } + } +} diff --git a/src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/UpdateExistingAttributesConfig.php b/src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/UpdateExistingAttributesConfig.php index f0dd5008b..90bc7bfb3 100644 --- a/src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/UpdateExistingAttributesConfig.php +++ b/src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/UpdateExistingAttributesConfig.php @@ -76,7 +76,7 @@ public function load(ObjectManager $manager) public function getDependencies() { return [ - LoadDefaultAttributeFamilyData::class + LoadDefaultProductFamilyData::class ]; } } diff --git a/src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/UpdateExistingProductsWithAttributeFamily.php b/src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/UpdateExistingProductsWithAttributeFamily.php index 6b7f27b5c..4c23d8880 100644 --- a/src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/UpdateExistingProductsWithAttributeFamily.php +++ b/src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/UpdateExistingProductsWithAttributeFamily.php @@ -6,6 +6,7 @@ use Doctrine\Common\DataFixtures\DependentFixtureInterface; use Doctrine\Common\Persistence\ObjectManager; +use Marello\Bundle\ProductBundle\Entity\Builder\ProductFamilyBuilder; use Oro\Bundle\EntityConfigBundle\Attribute\Entity\AttributeFamily; use Marello\Bundle\ProductBundle\Entity\Product; @@ -21,7 +22,7 @@ class UpdateExistingProductsWithAttributeFamily extends AbstractFixture implemen public function getDependencies() { return [ - LoadDefaultAttributeFamilyData::class + LoadDefaultProductFamilyData::class ]; } @@ -39,7 +40,7 @@ public function load(ObjectManager $manager) } /** @var AttributeFamily $attributeFamily */ - $attributeFamily = $this->getReference(LoadDefaultAttributeFamilyData::DEFAULT_FAMILY_CODE); + $attributeFamily = $this->getReference(ProductFamilyBuilder::DEFAULT_FAMILY_CODE); foreach ($products as $product) { $product->setAttributeFamily($attributeFamily); $manager->persist($product); diff --git a/src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/UpdateExistingProductsWithCategoriesCodes.php b/src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/UpdateExistingProductsWithCategoriesCodes.php new file mode 100644 index 000000000..78f89789b --- /dev/null +++ b/src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/UpdateExistingProductsWithCategoriesCodes.php @@ -0,0 +1,41 @@ +getRepository(Product::class) + ->findBy(['categoriesCodes' => null]); + + if (count($products) === 0) { + return; + } + foreach ($products as $product) { + foreach ($product->getCategories() as $category) { + $product->addCategoryCode($category->getCode()); + } + $manager->persist($product); + } + + $manager->flush(); + } +} diff --git a/src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/UpdateExistingProductsWithChannelsCodes.php b/src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/UpdateExistingProductsWithChannelsCodes.php new file mode 100644 index 000000000..056f9b59a --- /dev/null +++ b/src/Marello/Bundle/ProductBundle/Migrations/Data/ORM/UpdateExistingProductsWithChannelsCodes.php @@ -0,0 +1,41 @@ +getRepository(Product::class) + ->findBy(['channelsCodes' => null]); + + if (count($products) === 0) { + return; + } + foreach ($products as $product) { + foreach ($product->getChannels() as $channel) { + $product->addChannelCode($channel->getCode()); + } + $manager->persist($product); + } + + $manager->flush(); + } +} diff --git a/src/Marello/Bundle/ProductBundle/Migrations/Schema/MarelloProductBundleInstaller.php b/src/Marello/Bundle/ProductBundle/Migrations/Schema/MarelloProductBundleInstaller.php index 6d8ebccd3..7cc96291f 100644 --- a/src/Marello/Bundle/ProductBundle/Migrations/Schema/MarelloProductBundleInstaller.php +++ b/src/Marello/Bundle/ProductBundle/Migrations/Schema/MarelloProductBundleInstaller.php @@ -29,7 +29,7 @@ class MarelloProductBundleInstaller implements */ public function getMigrationVersion() { - return 'v1_10'; + return 'v1_12'; } /** @@ -83,8 +83,10 @@ protected function createMarelloProductProductTable(Schema $schema) $table->addColumn('warranty', 'integer', ['notnull' => false]); $table->addColumn('preferred_supplier_id', 'integer', ['notnull' => false]); $table->addColumn('tax_code_id', 'integer', ['notnull' => false]); + $table->addColumn('channels_codes', 'text', ['notnull' => false, 'comment' => '(DC2Type:text)']); + $table->addColumn('categories_codes', 'text', ['notnull' => false, 'comment' => '(DC2Type:text)']); $table->setPrimaryKey(['id']); - $table->addUniqueIndex(['sku'], 'marello_product_product_skuidx'); + $table->addUniqueIndex(['sku', 'organization_id'], 'marello_product_product_skuorgidx'); $table->addIndex(['created_at'], 'idx_marello_product_created_at', []); $table->addIndex(['updated_at'], 'idx_marello_product_updated_at', []); $table->addIndex(['product_status'], 'IDX_25845B8D197C24B8', []); diff --git a/src/Marello/Bundle/ProductBundle/Migrations/Schema/v1_11/MarelloProductBundle.php b/src/Marello/Bundle/ProductBundle/Migrations/Schema/v1_11/MarelloProductBundle.php new file mode 100644 index 000000000..a8d6d4504 --- /dev/null +++ b/src/Marello/Bundle/ProductBundle/Migrations/Schema/v1_11/MarelloProductBundle.php @@ -0,0 +1,31 @@ +changeMarelloProductProductUniqueIndex($schema); + } + + /** + * @param Schema $schema + */ + protected function changeMarelloProductProductUniqueIndex(Schema $schema) + { + $table = $schema->getTable('marello_product_product'); + $table->dropIndex('marello_product_product_skuidx'); + $table->addUniqueIndex(['sku', 'organization_id'], 'marello_product_product_skuorgidx'); + } +} diff --git a/src/Marello/Bundle/ProductBundle/Migrations/Schema/v1_12/MarelloProductBundle.php b/src/Marello/Bundle/ProductBundle/Migrations/Schema/v1_12/MarelloProductBundle.php new file mode 100644 index 000000000..6dea87861 --- /dev/null +++ b/src/Marello/Bundle/ProductBundle/Migrations/Schema/v1_12/MarelloProductBundle.php @@ -0,0 +1,28 @@ +updateMarelloProductProductTable($schema); + } + + /** + * @param Schema $schema + */ + protected function updateMarelloProductProductTable(Schema $schema) + { + $table = $schema->getTable('marello_product_product'); + $table->addColumn('channels_codes', 'text', ['notnull' => false, 'comment' => '(DC2Type:text)']); + $table->addColumn('categories_codes', 'text', ['notnull' => false, 'comment' => '(DC2Type:text)']); + } +} diff --git a/src/Marello/Bundle/ProductBundle/Provider/OrderItemProductUnitProvider.php b/src/Marello/Bundle/ProductBundle/Provider/OrderItemProductUnitProvider.php new file mode 100644 index 000000000..b2908a502 --- /dev/null +++ b/src/Marello/Bundle/ProductBundle/Provider/OrderItemProductUnitProvider.php @@ -0,0 +1,72 @@ +doctrineHelper = $doctrineHelper; + } + + /** + * {@inheritdoc} + */ + public function processFormChanges(FormChangeContextInterface $context) + { + $submittedData = $context->getSubmittedData(); + $order = $context->getForm()->getData(); + if ($order instanceof Order) { + $salesChannel = $order->getSalesChannel(); + } else { + return; + } + $productIds = []; + foreach ($submittedData[self::ITEMS_FIELD] as $item) { + $productIds[] = (int)$item['product']; + } + $data = []; + /** @var Product[] $products */ + $products = $this->getRepository()->findBySalesChannel($salesChannel->getId(), $productIds); + foreach ($products as $product) { + /** @var InventoryItem $inventoryItem */ + $inventoryItem = $product->getInventoryItems()->first(); + $unit = $inventoryItem->getProductUnit(); + if ($unit) { + $data[sprintf('%s%s', self::IDENTIFIER_PREFIX, $product->getId())] = [ + 'unit' => $unit->getName() + ]; + } + } + if (!empty($data)) { + $result = $context->getResult(); + $result[self::ITEMS_FIELD]['product_unit'] = $data; + $context->setResult($result); + } + } + + /** + * @return ProductRepository + */ + protected function getRepository() + { + return $this->doctrineHelper->getEntityRepositoryForClass(Product::class); + } +} diff --git a/src/Marello/Bundle/ProductBundle/Provider/ProductTaxCodeProvider.php b/src/Marello/Bundle/ProductBundle/Provider/ProductTaxCodeProvider.php index 427555bdd..affd97dc9 100644 --- a/src/Marello/Bundle/ProductBundle/Provider/ProductTaxCodeProvider.php +++ b/src/Marello/Bundle/ProductBundle/Provider/ProductTaxCodeProvider.php @@ -49,8 +49,7 @@ public function processFormChanges(FormChangeContextInterface $context) if ($taxCode) { $data[sprintf('%s%s', self::IDENTIFIER_PREFIX, $product->getId())] = [ 'id' => $taxCode->getId(), - 'code' => $taxCode->getCode(), - + 'code' => $taxCode->getCode() ]; } } diff --git a/src/Marello/Bundle/ProductBundle/Resources/config/oro/actions.yml b/src/Marello/Bundle/ProductBundle/Resources/config/oro/actions.yml index 0dd0ca1bb..0a8d70b86 100755 --- a/src/Marello/Bundle/ProductBundle/Resources/config/oro/actions.yml +++ b/src/Marello/Bundle/ProductBundle/Resources/config/oro/actions.yml @@ -55,7 +55,7 @@ operations: method_parameters: [$.data] attribute: $.inventoryitem - '@redirect': - route: marello_inventory_inventory_update + route: marello_inventory_inventory_view route_parameters: id: $.inventoryitem.id action_groups: diff --git a/src/Marello/Bundle/ProductBundle/Resources/config/oro/api.yml b/src/Marello/Bundle/ProductBundle/Resources/config/oro/api.yml index 6a966356c..64e61ab02 100644 --- a/src/Marello/Bundle/ProductBundle/Resources/config/oro/api.yml +++ b/src/Marello/Bundle/ProductBundle/Resources/config/oro/api.yml @@ -19,6 +19,10 @@ api: property_path: taxCode productstatus: property_path: status + channelsCodes: + exclude: true + categoriesCodes: + exclude: true createdAt: exclude: true updatedAt: diff --git a/src/Marello/Bundle/ProductBundle/Resources/config/oro/datagrids.yml b/src/Marello/Bundle/ProductBundle/Resources/config/oro/datagrids.yml index c42e53019..f48122ff2 100644 --- a/src/Marello/Bundle/ProductBundle/Resources/config/oro/datagrids.yml +++ b/src/Marello/Bundle/ProductBundle/Resources/config/oro/datagrids.yml @@ -13,6 +13,8 @@ datagrids: - p.type - p.weight - p.manufacturingCode + - p.channelsCodes + - p.categoriesCodes - p.createdAt - p.updatedAt from: @@ -31,6 +33,22 @@ datagrids: frontend_type: string inline_editing: enable: false + channels: + label: marello.product.channels.label + type: twig + frontend_type: html + template: MarelloProductBundle:Product/Datagrid/Property:channels.html.twig + renderable: false + inline_editing: + enable: false + categories: + label: marello.product.categories.label + type: twig + frontend_type: html + template: MarelloProductBundle:Product/Datagrid/Property:categories.html.twig + renderable: false + inline_editing: + enable: false manufacturingCode: label: marello.product.manufacturing_code.label frontend_type: string @@ -69,6 +87,8 @@ datagrids: sku: { data_name: p.sku } name: { data_name: name } weight: { data_name: p.weight } + channels: { data_name: p.channelsCodes } + categories: { data_name: p.categoriesCodes } createdAt: { data_name: p.createdAt } updatedAt: { data_name: p.updatedAt } default: @@ -88,6 +108,22 @@ datagrids: data_name: p.manufacturingCode type: string enabled: false + channels: + data_name: p.channelsCodes + type: choice_like + options: + field_options: + multiple: true + choices: '@marello_sales.provider.basic_sales_channels_choices->getChannels()' + enabled: false + categories: + data_name: p.categoriesCodes + type: choice_like + options: + field_options: + multiple: true + choices: '@marello_catalog.provider.categories_choices->getCategories()' + enabled: false weight: data_name: p.weight type: number diff --git a/src/Marello/Bundle/ProductBundle/Resources/config/services.yml b/src/Marello/Bundle/ProductBundle/Resources/config/services.yml index 836153d56..64600bd44 100644 --- a/src/Marello/Bundle/ProductBundle/Resources/config/services.yml +++ b/src/Marello/Bundle/ProductBundle/Resources/config/services.yml @@ -39,6 +39,7 @@ services: - '@marello_catalog.provider.categories_ids' calls: - ['setOroEntityDoctrineHelper', ['@oro_entity.doctrine_helper']] + - ['setTokenAccessor', ['@oro_security.token_accessor']] tags: - { name: twig.extension } @@ -107,6 +108,14 @@ services: tags: - { name: marello_order.order_item_data_provider, type: tax_code, priority: 20 } + marello_product.provider.order_item_product_unit_provider: + class: Marello\Bundle\ProductBundle\Provider\OrderItemProductUnitProvider + arguments: + - '@oro_entity.doctrine_helper' + tags: + - { name: marello_order.order_item_data_provider, type: product_unit, priority: 25 } + + marello_product.repository.product: class: 'Marello\Bundle\ProductBundle\Entity\Repository\ProductRepository' parent: oro_entity.abstract_repository @@ -216,8 +225,15 @@ services: tags: - { name: doctrine.event_listener, event: onFlush } + marello_product.entity.builder.product_family: + class: Marello\Bundle\ProductBundle\Entity\Builder\ProductFamilyBuilder + arguments: + - '@translator' + - '@oro_entity_config.manager.attribute_group_manager' + public: true + marello_product.provider.action_group_registry: public: true class: Marello\Bundle\ProductBundle\Provider\ActionGroupRegistryProvider arguments: - - '@oro_action.action_group_registry' \ No newline at end of file + - '@oro_action.action_group_registry' diff --git a/src/Marello/Bundle/ProductBundle/Resources/config/validation.yml b/src/Marello/Bundle/ProductBundle/Resources/config/validation.yml index 31ad2a288..67457f47f 100644 --- a/src/Marello/Bundle/ProductBundle/Resources/config/validation.yml +++ b/src/Marello/Bundle/ProductBundle/Resources/config/validation.yml @@ -2,7 +2,7 @@ Marello\Bundle\ProductBundle\Entity\Product: constraints: - Marello\Bundle\ProductBundle\Validator\Constraints\ProductSupplierRelationsDropship: ~ - Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity: - fields: sku + fields: [sku, organization] message: 'marello.product.messages.error.sku' properties: names: diff --git a/src/Marello/Bundle/ProductBundle/Resources/translations/messages.en.yml b/src/Marello/Bundle/ProductBundle/Resources/translations/messages.en.yml index cb137af73..0d22b6c23 100644 --- a/src/Marello/Bundle/ProductBundle/Resources/translations/messages.en.yml +++ b/src/Marello/Bundle/ProductBundle/Resources/translations/messages.en.yml @@ -28,6 +28,8 @@ marello: categories.label: Categories suppliers.label: Suppliers attribute_family.label: Attribute Family + channels_codes.label: Channel codes + categories_codes.label: Category codes variant: label: Variant entity_label: Variant diff --git a/src/Marello/Bundle/ProductBundle/Resources/views/Product/Datagrid/Property/categories.html.twig b/src/Marello/Bundle/ProductBundle/Resources/views/Product/Datagrid/Property/categories.html.twig new file mode 100644 index 000000000..a8a7ac820 --- /dev/null +++ b/src/Marello/Bundle/ProductBundle/Resources/views/Product/Datagrid/Property/categories.html.twig @@ -0,0 +1,6 @@ +{% set codes = record.getValue('categoriesCodes')|split('|') %} +{% for index, code in codes %} + {% if index > 0 %} + {{ marello_get_category_name_by_code(code) }}
+ {% endif %} +{% endfor %} \ No newline at end of file diff --git a/src/Marello/Bundle/ProductBundle/Resources/views/Product/Datagrid/Property/channels.html.twig b/src/Marello/Bundle/ProductBundle/Resources/views/Product/Datagrid/Property/channels.html.twig new file mode 100644 index 000000000..446f552ea --- /dev/null +++ b/src/Marello/Bundle/ProductBundle/Resources/views/Product/Datagrid/Property/channels.html.twig @@ -0,0 +1,6 @@ +{% set codes = record.getValue('channelsCodes')|split('|') %} +{% for index, code in codes %} + {% if index > 0 %} + {{ marello_get_sales_channel_name_by_code(code) }}
+ {% endif %} +{% endfor %} \ No newline at end of file diff --git a/src/Marello/Bundle/ProductBundle/Resources/views/Product/createStepTwo.html.twig b/src/Marello/Bundle/ProductBundle/Resources/views/Product/createStepTwo.html.twig index 22dc56023..1b8c9a072 100644 --- a/src/Marello/Bundle/ProductBundle/Resources/views/Product/createStepTwo.html.twig +++ b/src/Marello/Bundle/ProductBundle/Resources/views/Product/createStepTwo.html.twig @@ -6,12 +6,17 @@ {% set gridName = 'marello-product-saleschannel-extended-grid' %} {% set entity = form.vars.value %} -{% set formAction = path('marello_product_create_step_two') %} {% if entity.id %} {% oro_title_set({params : {"%name%": entity.name } }) %} {% endif %} +{% if queryParams is defined %} + {% set formAction = path('marello_product_create_step_two', queryParams) %} +{% else %} + {% set formAction = path('marello_product_create_step_two') %} +{% endif %} + {% block pageHeader %} {% if entity.id %} {% set breadcrumbs = { diff --git a/src/Marello/Bundle/ProductBundle/Tests/Functional/Controller/ProductControllerTest.php b/src/Marello/Bundle/ProductBundle/Tests/Functional/Controller/ProductControllerTest.php index 5e0534475..fd998c19f 100644 --- a/src/Marello/Bundle/ProductBundle/Tests/Functional/Controller/ProductControllerTest.php +++ b/src/Marello/Bundle/ProductBundle/Tests/Functional/Controller/ProductControllerTest.php @@ -2,8 +2,8 @@ namespace Marello\Bundle\ProductBundle\Tests\Functional\Controller; +use Marello\Bundle\ProductBundle\Entity\Builder\ProductFamilyBuilder; use Marello\Bundle\ProductBundle\Entity\Product; -use Marello\Bundle\ProductBundle\Migrations\Data\ORM\LoadDefaultAttributeFamilyData; use Marello\Bundle\ProductBundle\Provider\ProductTypesProvider; use Marello\Bundle\ProductBundle\Tests\Functional\DataFixtures\LoadProductData; use Marello\Bundle\SalesBundle\Tests\Functional\DataFixtures\LoadSalesData; @@ -57,7 +57,7 @@ public function testCreateProduct() /** @var AttributeFamily $attributeFamily */ $attributeFamily = $em ->getRepository(AttributeFamily::class) - ->findOneBy(['code' => LoadDefaultAttributeFamilyData::DEFAULT_FAMILY_CODE]); + ->findOneBy(['code' => ProductFamilyBuilder::DEFAULT_FAMILY_CODE]); $form = $crawler->selectButton('Continue')->form(); $formValues = $form->getPhpValues(); $formValues['input_action'] = 'marello_product_create'; diff --git a/src/Marello/Bundle/ProductBundle/Tests/Functional/DataFixtures/LoadProductData.php b/src/Marello/Bundle/ProductBundle/Tests/Functional/DataFixtures/LoadProductData.php index 6adc549f4..fb7976a5e 100644 --- a/src/Marello/Bundle/ProductBundle/Tests/Functional/DataFixtures/LoadProductData.php +++ b/src/Marello/Bundle/ProductBundle/Tests/Functional/DataFixtures/LoadProductData.php @@ -9,8 +9,8 @@ use Marello\Bundle\PricingBundle\Entity\AssembledPriceList; use Marello\Bundle\PricingBundle\Entity\PriceType; use Marello\Bundle\PricingBundle\Model\PriceTypeInterface; +use Marello\Bundle\ProductBundle\Entity\Builder\ProductFamilyBuilder; use Marello\Bundle\ProductBundle\Entity\Product; -use Marello\Bundle\ProductBundle\Migrations\Data\ORM\LoadDefaultAttributeFamilyData; use Marello\Bundle\SupplierBundle\Entity\Supplier; use Marello\Bundle\SalesBundle\Entity\SalesChannel; use Marello\Bundle\PricingBundle\Entity\ProductPrice; @@ -243,7 +243,7 @@ private function createProduct(array $data) $defaultAttributeFamily = $this->manager ->getRepository(AttributeFamily::class) - ->findOneBy(['code' => LoadDefaultAttributeFamilyData::DEFAULT_FAMILY_CODE]); + ->findOneBy(['code' => ProductFamilyBuilder::DEFAULT_FAMILY_CODE]); $product->setAttributeFamily($defaultAttributeFamily); $currencies = $this->addSalesChannels($product, $data); diff --git a/src/Marello/Bundle/ProductBundle/Tests/Functional/Entity/ProductTest.php b/src/Marello/Bundle/ProductBundle/Tests/Functional/Entity/ProductTest.php index ca7925aae..e73d7b4c8 100644 --- a/src/Marello/Bundle/ProductBundle/Tests/Functional/Entity/ProductTest.php +++ b/src/Marello/Bundle/ProductBundle/Tests/Functional/Entity/ProductTest.php @@ -2,7 +2,7 @@ namespace Marello\Bundle\ProductBundle\Tests\Functional\Entity; -use Marello\Bundle\ProductBundle\Migrations\Data\ORM\LoadDefaultAttributeFamilyData; +use Marello\Bundle\ProductBundle\Entity\Builder\ProductFamilyBuilder; use Oro\Bundle\EntityConfigBundle\Config\AttributeConfigHelper; use Oro\Bundle\TestFrameworkBundle\Test\WebTestCase; @@ -39,7 +39,7 @@ public function testProductIsAssignedDefaultAttributeFamily() /** @var Product $product */ $product = $this->getReference(LoadProductData::PRODUCT_1_REF); static::assertSame( - LoadDefaultAttributeFamilyData::DEFAULT_FAMILY_CODE, + ProductFamilyBuilder::DEFAULT_FAMILY_CODE, $product->getAttributeFamily()->getCode() ); } diff --git a/src/Marello/Bundle/ProductBundle/Twig/ProductExtension.php b/src/Marello/Bundle/ProductBundle/Twig/ProductExtension.php index f07ae8e2c..0c9d831ec 100644 --- a/src/Marello/Bundle/ProductBundle/Twig/ProductExtension.php +++ b/src/Marello/Bundle/ProductBundle/Twig/ProductExtension.php @@ -7,6 +7,8 @@ use Marello\Bundle\ProductBundle\Entity\Repository\ProductRepository; use Marello\Bundle\SalesBundle\Provider\ChannelProvider; use Oro\Bundle\EntityBundle\ORM\DoctrineHelper; +use Oro\Bundle\OrganizationBundle\Entity\Organization; +use Oro\Bundle\SecurityBundle\Authentication\TokenAccessorInterface; use Twig\Extension\AbstractExtension; use Twig\TwigFunction; @@ -14,21 +16,18 @@ class ProductExtension extends AbstractExtension { const NAME = 'marello_product'; - /** - * @var ChannelProvider - */ + /** @var ChannelProvider $channelProvider */ protected $channelProvider; - /** - * @var CategoriesIdsProvider - */ + /** @var CategoriesIdsProvider $categoriesIdsProvider */ protected $categoriesIdsProvider; - /** - * @var DoctrineHelper - */ + /** @var DoctrineHelper $doctrineHelper */ private $doctrineHelper; + /** @var TokenAccessorInterface $tokenAccessor */ + private $tokenAccessor; + /** * @param ChannelProvider $channelProvider * @param CategoriesIdsProvider $categoriesIdsProvider @@ -101,9 +100,15 @@ public function getProductBySku($sku) if (!$this->doctrineHelper || !$sku) { return null; } + + $organization = null; + if ($this->tokenAccessor) { + $organization = $this->tokenAccessor->getOrganization(); + } + /** @var ProductRepository $productRepository */ $productRepository = $this->doctrineHelper->getEntityRepository(Product::class); - return $productRepository->findOneBySku($sku); + return $productRepository->findOneBySku($sku, $organization); } /** @@ -113,4 +118,12 @@ public function setOroEntityDoctrineHelper(DoctrineHelper $doctrineHelper) { $this->doctrineHelper = $doctrineHelper; } + + /** + * @param TokenAccessorInterface $tokenAccessor + */ + public function setTokenAccessor(TokenAccessorInterface $tokenAccessor) + { + $this->tokenAccessor = $tokenAccessor; + } } diff --git a/src/Marello/Bundle/PurchaseOrderBundle/Controller/PurchaseOrderController.php b/src/Marello/Bundle/PurchaseOrderBundle/Controller/PurchaseOrderController.php index a15c6e4fa..8aa6cfa7f 100644 --- a/src/Marello/Bundle/PurchaseOrderBundle/Controller/PurchaseOrderController.php +++ b/src/Marello/Bundle/PurchaseOrderBundle/Controller/PurchaseOrderController.php @@ -123,11 +123,12 @@ public function createStepTwoAction(Request $request) */ protected function createStepOne(Request $request) { - $form = $this->createForm(PurchaseOrderCreateStepOneType::class); + $form = $this->createForm(PurchaseOrderCreateStepOneType::class, new PurchaseOrder()); $handler = new PurchaseOrderCreateStepOneHandler($form, $request); + $queryParams = $request->query->all(); if ($handler->process()) { - return $this->forward('MarelloPurchaseOrderBundle:PurchaseOrder:createStepTwo'); + return $this->forward('MarelloPurchaseOrderBundle:PurchaseOrder:createStepTwo', [], $queryParams); } return ['form' => $form->createView()]; @@ -142,6 +143,7 @@ protected function createStepTwo(Request $request, PurchaseOrder $purchaseOrder) { if ($request->request->get('input_action') === 'marello_purchaseorder_purchaseorder_create') { $form = $this->createForm(PurchaseOrderCreateStepOneType::class, $purchaseOrder); + $queryParams = $request->query->all(); $form->handleRequest($request); $formData = $form->all(); @@ -155,7 +157,8 @@ protected function createStepTwo(Request $request, PurchaseOrder $purchaseOrder) return [ 'form' => $form->createView(), - 'entity' => $purchaseOrder + 'entity' => $purchaseOrder, + 'queryParams' => $queryParams ]; } diff --git a/src/Marello/Bundle/PurchaseOrderBundle/Form/Type/PurchaseOrderCreateStepTwoType.php b/src/Marello/Bundle/PurchaseOrderBundle/Form/Type/PurchaseOrderCreateStepTwoType.php index 1bb787813..4acfe2291 100644 --- a/src/Marello/Bundle/PurchaseOrderBundle/Form/Type/PurchaseOrderCreateStepTwoType.php +++ b/src/Marello/Bundle/PurchaseOrderBundle/Form/Type/PurchaseOrderCreateStepTwoType.php @@ -62,11 +62,14 @@ public function buildForm(FormBuilderInterface $builder, array $options) [ 'required' => false, 'label' => 'marello.purchaseorder.expected_delivery_date.label', - 'constraints' => [ new GreaterThan( - [ - 'value' => 'today', - 'message' => 'marello.purchaseorder.expected_delivery_date.messages.error.greater_than_date' - ]) + 'constraints' => [ + new GreaterThan( + [ + 'value' => 'today', + 'message' + => 'marello.purchaseorder.expected_delivery_date.messages.error.greater_than_date' + ] + ) ] ] ) diff --git a/src/Marello/Bundle/PurchaseOrderBundle/Resources/translations/messages.en.yml b/src/Marello/Bundle/PurchaseOrderBundle/Resources/translations/messages.en.yml index 35f91e975..81ca529c6 100644 --- a/src/Marello/Bundle/PurchaseOrderBundle/Resources/translations/messages.en.yml +++ b/src/Marello/Bundle/PurchaseOrderBundle/Resources/translations/messages.en.yml @@ -26,6 +26,7 @@ marello: billing_and_shipping.label: Billing & Delivery Info shipping_address.label: Shipping Address data.label: Data + due_date.label: Due Date ui: continue: Continue sections: diff --git a/src/Marello/Bundle/PurchaseOrderBundle/Resources/views/PurchaseOrder/createStepTwo.html.twig b/src/Marello/Bundle/PurchaseOrderBundle/Resources/views/PurchaseOrder/createStepTwo.html.twig index 86646151d..cb4fd08e7 100644 --- a/src/Marello/Bundle/PurchaseOrderBundle/Resources/views/PurchaseOrder/createStepTwo.html.twig +++ b/src/Marello/Bundle/PurchaseOrderBundle/Resources/views/PurchaseOrder/createStepTwo.html.twig @@ -3,7 +3,12 @@ {% oro_title_set({params : {"%sku%": entity.sku|default('N/A'|trans) , "%name%": (entity.id ? entity.defaultName.string : '')|default('N/A'|trans) } }) %} -{% set formAction = path('marello_purchaseorder_purchaseorder_create_step_two') %} +{% if queryParams is defined %} + {% set formAction = path('marello_purchaseorder_purchaseorder_create_step_two', queryParams) %} +{% else %} + {% set formAction = path('marello_purchaseorder_purchaseorder_create_step_two') %} +{% endif %} + {% block navButtons %} {{ parent() }} diff --git a/src/Marello/Bundle/PurchaseOrderBundle/Tests/Functional/Controller/PurchaseOrderControllerTest.php b/src/Marello/Bundle/PurchaseOrderBundle/Tests/Functional/Controller/PurchaseOrderControllerTest.php index e7bf67fa9..eb922b022 100644 --- a/src/Marello/Bundle/PurchaseOrderBundle/Tests/Functional/Controller/PurchaseOrderControllerTest.php +++ b/src/Marello/Bundle/PurchaseOrderBundle/Tests/Functional/Controller/PurchaseOrderControllerTest.php @@ -374,7 +374,7 @@ public function testErrorDueDateCreateAction() $this->assertHtmlResponseStatusCodeEquals($result, Response::HTTP_OK); $html = $crawler->html(); - $this->assertContains('Due date must be greater than', $html); + $this->assertContains('Expected Delivery date must be greater than today', $html); } /** diff --git a/src/Marello/Bundle/RefundBundle/Resources/config/oro/navigation.yml b/src/Marello/Bundle/RefundBundle/Resources/config/oro/navigation.yml index 6721068c6..a5fdc5baf 100644 --- a/src/Marello/Bundle/RefundBundle/Resources/config/oro/navigation.yml +++ b/src/Marello/Bundle/RefundBundle/Resources/config/oro/navigation.yml @@ -7,8 +7,6 @@ navigation: extras: routes: ['marello_refund_*'] position: 40 - - tree: application_menu: children: diff --git a/src/Marello/Bundle/RefundBundle/Resources/views/Refund/update.html.twig b/src/Marello/Bundle/RefundBundle/Resources/views/Refund/update.html.twig index 41c656777..a40a067ee 100644 --- a/src/Marello/Bundle/RefundBundle/Resources/views/Refund/update.html.twig +++ b/src/Marello/Bundle/RefundBundle/Resources/views/Refund/update.html.twig @@ -65,7 +65,6 @@ {{ UI.renderProperty('oro.ui.created_at'|trans, entity.createdAt|date) }} {{ UI.renderProperty('oro.ui.updated_at'|trans, entity.updatedAt|date) }} {{ UI.renderProperty('marello.order.payment_method.label'|trans, entity.order.paymentMethod) }} - {{ UI.renderProperty('marello.order.payment_reference.label'|trans, entity.order.paymentReference) }}
{{ totals }}
diff --git a/src/Marello/Bundle/RefundBundle/Resources/views/Refund/view.html.twig b/src/Marello/Bundle/RefundBundle/Resources/views/Refund/view.html.twig index b5145d7d2..3f53e0642 100644 --- a/src/Marello/Bundle/RefundBundle/Resources/views/Refund/view.html.twig +++ b/src/Marello/Bundle/RefundBundle/Resources/views/Refund/view.html.twig @@ -38,7 +38,6 @@ )}} {{ UI.renderProperty('marello.order.order_reference.label'|trans, entity.order.orderReference) }} {{ UI.renderProperty('marello.order.payment_method.label'|trans, entity.order.paymentMethod) }} - {{ UI.renderProperty('marello.order.payment_reference.label'|trans, entity.order.paymentReference) }} {{ UI.renderProperty('oro.ui.created_at'|trans, entity.order.createdAt|date) }} {{ UI.renderProperty('oro.ui.updated_at'|trans, entity.order.updatedAt|date) }} @@ -74,7 +73,6 @@ {{ UI.renderProperty('oro.ui.created_at'|trans, entity.createdAt|date) }} {{ UI.renderProperty('oro.ui.updated_at'|trans, entity.updatedAt|date) }} {{ UI.renderProperty('marello.order.payment_method.label'|trans, entity.order.paymentMethod) }} - {{ UI.renderProperty('marello.order.payment_reference.label'|trans, entity.order.paymentReference) }} {{ totals }} diff --git a/src/Marello/Bundle/RefundBundle/Tests/Functional/Controller/RefundControllerTest.php b/src/Marello/Bundle/RefundBundle/Tests/Functional/Controller/RefundControllerTest.php index a9f8a63c0..9108151b0 100644 --- a/src/Marello/Bundle/RefundBundle/Tests/Functional/Controller/RefundControllerTest.php +++ b/src/Marello/Bundle/RefundBundle/Tests/Functional/Controller/RefundControllerTest.php @@ -55,8 +55,9 @@ public function testUpdateRefund() $this->assertHtmlResponseStatusCodeEquals($result, Response::HTTP_OK); $form = $crawler->selectButton('Save and Close')->form(); - $form['marello_refund[items][0][quantity]'] = 1; - $form['marello_refund[items][0][refundAmount]'] = 100; + $key = array_key_first ($form->get('marello_refund[items]')); + $form[sprintf('marello_refund[items][%d][quantity]', $key)] = 1; + $form[sprintf('marello_refund[items][%d][refundAmount]', $key)] = 100; $result = $this->client->getResponse(); $this->assertHtmlResponseStatusCodeEquals($result, Response::HTTP_OK); diff --git a/src/Marello/Bundle/ReportBundle/Resources/config/oro/datagrids.yml b/src/Marello/Bundle/ReportBundle/Resources/config/oro/datagrids.yml index 680f51a55..ef58d9cbb 100644 --- a/src/Marello/Bundle/ReportBundle/Resources/config/oro/datagrids.yml +++ b/src/Marello/Bundle/ReportBundle/Resources/config/oro/datagrids.yml @@ -96,13 +96,9 @@ datagrids: select: - oi.productName - oi.productSku - - product.createdAt as createdAt - SUM(oi.quantity) AS quantitySold from: - { table: MarelloOrderBundle:OrderItem, alias: oi } - join: - left: - - { join: oi.product, alias: product } groupBy: oi.productSku, oi.productName columns: productSku: @@ -111,9 +107,6 @@ datagrids: productName: label: marello.product.name.label frontend_type: string - createdAt: - label: oro.ui.created_at - frontend_type: datetime quantitySold: label: marello.report.datagrid.columns.quantity_sold.label frontend_type: number @@ -122,7 +115,6 @@ datagrids: columns: productSku: { data_name: oi.productSku } productName: { data_name: oi.productName } - createdAt: { data_name: createdAt } quantitySold: { data_name: quantitySold } default: quantitySold: 'DESC' @@ -144,13 +136,9 @@ datagrids: select: - oi.productName - oi.productSku - - product.createdAt as createdAt - SUM(oi.quantity) AS quantitySold from: - { table: MarelloOrderBundle:OrderItem, alias: oi } - join: - left: - - { join: oi.product, alias: product } groupBy: oi.productSku, oi.productName columns: productSku: @@ -159,9 +147,6 @@ datagrids: productName: label: marello.product.name.label frontend_type: string - createdAt: - label: oro.ui.created_at - frontend_type: datetime quantitySold: label: marello.report.datagrid.columns.quantity_sold.label frontend_type: number @@ -170,7 +155,6 @@ datagrids: columns: productSku: { data_name: oi.productSku } productName: { data_name: oi.productName } - createdAt: { data_name: createdAt } quantitySold: { data_name: quantitySold } default: quantitySold: 'ASC' @@ -253,7 +237,7 @@ datagrids: from: - { table: MarelloOrderBundle:OrderItem, alias: oi } join: - left: + inner: - { join: MarelloReturnBundle:ReturnItem, alias: ri, conditionType: 'WITH', condition: 'oi.id = ri.orderItem' } groupBy: oi.productSku, oi.productName columns: diff --git a/src/Marello/Bundle/ReturnBundle/Controller/ReturnController.php b/src/Marello/Bundle/ReturnBundle/Controller/ReturnController.php index 80ba0d1c6..df1003b5a 100644 --- a/src/Marello/Bundle/ReturnBundle/Controller/ReturnController.php +++ b/src/Marello/Bundle/ReturnBundle/Controller/ReturnController.php @@ -81,10 +81,9 @@ public function createAction(Order $order, Request $request) } return [ - 'form' => $form->createView(), + 'form' => $form->createView() ]; } else { - throw new AccessDeniedException( $this->get('translator')->trans( 'marello.return.returnentity.messages.error.return.cannot_be_returned_without_shipment' diff --git a/src/Marello/Bundle/SalesBundle/Entity/Repository/SalesChannelRepository.php b/src/Marello/Bundle/SalesBundle/Entity/Repository/SalesChannelRepository.php index e376fafa2..a4b2269e0 100644 --- a/src/Marello/Bundle/SalesBundle/Entity/Repository/SalesChannelRepository.php +++ b/src/Marello/Bundle/SalesBundle/Entity/Repository/SalesChannelRepository.php @@ -5,6 +5,7 @@ use Doctrine\ORM\EntityRepository; use Doctrine\ORM\QueryBuilder; use Marello\Bundle\PricingBundle\Entity\ProductChannelPrice; +use Marello\Bundle\ProductBundle\Entity\Product; use Marello\Bundle\SalesBundle\Entity\SalesChannel; use Oro\Bundle\SecurityBundle\ORM\Walker\AclHelper; @@ -122,4 +123,17 @@ public function getDefaultActiveChannels() return $this->aclHelper->apply($qb)->getResult(); } + + /** + * @param Product $product + * @return SalesChannel[] + */ + public function findByProduct(Product $product) + { + $qb = $this->createQueryBuilder('sc') + ->where(':product MEMBER OF sc.products') + ->setParameters(['product' => $product]); + + return $qb->getQuery()->getResult(); + } } diff --git a/src/Marello/Bundle/SalesBundle/Entity/SalesChannel.php b/src/Marello/Bundle/SalesBundle/Entity/SalesChannel.php index 0575137e8..c2e2e3d39 100644 --- a/src/Marello/Bundle/SalesBundle/Entity/SalesChannel.php +++ b/src/Marello/Bundle/SalesBundle/Entity/SalesChannel.php @@ -2,11 +2,13 @@ namespace Marello\Bundle\SalesBundle\Entity; +use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; use Marello\Bundle\CoreBundle\Model\EntityCreatedUpdatedAtTrait; use Marello\Bundle\LocaleBundle\Model\LocalizationAwareInterface; use Marello\Bundle\LocaleBundle\Model\LocalizationTrait; use Marello\Bundle\PricingBundle\Model\CurrencyAwareInterface; +use Marello\Bundle\ProductBundle\Entity\Product; use Marello\Bundle\SalesBundle\Model\ExtendSalesChannel; use Oro\Bundle\EntityConfigBundle\Metadata\Annotation as Oro; use Oro\Bundle\IntegrationBundle\Entity\Channel; @@ -198,6 +200,28 @@ class SalesChannel extends ExtendSalesChannel implements */ protected $integrationChannel; + /** + * @var ArrayCollection + * @ORM\ManyToMany(targetEntity="Marello\Bundle\ProductBundle\Entity\Product", mappedBy="channels") + * @Oro\ConfigField( + * defaultValues={ + * "dataaudit"={ + * "auditable"=true + * }, + * "importexport"={ + * "excluded"=true + * }, + * "attribute"={ + * "is_attribute"=true + * }, + * "extend"={ + * "owner"="System" + * } + * } + * ) + */ + protected $products; + /** * @param string|null $name */ @@ -206,6 +230,15 @@ public function __construct($name = null) parent::__construct(); $this->name = $name; + $this->products = new ArrayCollection(); + } + + public function __clone() + { + if ($this->id) { + $this->id = null; + $this->products = new ArrayCollection(); + } } /** @@ -409,4 +442,29 @@ public function setIntegrationChannel(Channel $integrationChannel = null) return $this; } + + /** + * @return bool + */ + public function hasProducts() + { + return count($this->products) > 0; + } + + /** + * @param Product $product + * @return bool + */ + public function hasProduct(Product $product) + { + return $this->products->contains($product); + } + + /** + * @return ArrayCollection|SalesChannel|Product[] + */ + public function getProducts() + { + return $this->products; + } } diff --git a/src/Marello/Bundle/SalesBundle/EventListener/Datagrid/SalesChannelsDatagridListener.php b/src/Marello/Bundle/SalesBundle/EventListener/Datagrid/SalesChannelsDatagridListener.php deleted file mode 100644 index d5dd24d18..000000000 --- a/src/Marello/Bundle/SalesBundle/EventListener/Datagrid/SalesChannelsDatagridListener.php +++ /dev/null @@ -1,172 +0,0 @@ -relatedEntityClass = $relatedEntityClass; - $this->salesChannelsChoicesProvider = $salesChannelsChoicesProvider; - - $this->expressionBuilder = new Expr(); - } - - /** - * @param BuildBefore $event - */ - public function onBuildBefore(BuildBefore $event) - { - $config = $event->getConfig(); - - $this->addSelect($config); - $this->addJoin($config); - $this->addColumn($config); - $this->addSorter($config); - $this->addFilter($config); - } - - /** - * @param DatagridConfiguration $configuration - * @return string - * @throws \InvalidArgumentException when a root entity not found in the grid - */ - protected function getAlias(DatagridConfiguration $configuration) - { - $rootAlias = $configuration->getOrmQuery()->getRootAlias(); - if (!$rootAlias) { - throw new \InvalidArgumentException( - sprintf( - 'A root entity is missing for grid "%s"', - $configuration->getName() - ) - ); - } - - return $rootAlias; - } - - /** - * @return string - */ - protected function getColumnLabel() - { - return 'marello.product.channels.label'; - } - - /** - * @return string - */ - protected function getDataName() - { - return self::DATA_NAME; - } - - /** - * @return string - */ - protected function getJoinAlias() - { - return self::JOIN_ALIAS; - } - - /** - * @param DatagridConfiguration $config - */ - protected function addSelect(DatagridConfiguration $config) - { - $config->getOrmQuery() - ->addSelect( - sprintf( - 'GROUP_CONCAT( - DISTINCT CONCAT_WS(\'|\', %1$s.name, %1$s.code) SEPARATOR \';\' - ) as channels', - $this->getJoinAlias() - ) - ) - ->addSelect( - sprintf('count(%s.code) AS channelsCount', $this->getJoinAlias()) - ); - } - - /** - * @param DatagridConfiguration $config - */ - protected function addJoin(DatagridConfiguration $config) - { - $config->getOrmQuery()->addLeftJoin( - $this->getAlias($config).'.channels', - $this->getJoinAlias() - ); - } - - /** - * @param DatagridConfiguration $config - */ - protected function addColumn(DatagridConfiguration $config) - { - $config->offsetSetByPath(sprintf('[columns][%s]', $this->getDataName()), [ - 'label' => $this->getColumnLabel(), - 'type' => 'twig', - 'frontend_type' => 'html', - 'template' => 'MarelloSalesBundle:SalesChannel/Datagrid/Property:channels.html.twig', - 'renderable' => true, - 'inline_editing' => ['enable' => false] - ]); - } - - /** - * @param DatagridConfiguration $config - */ - protected function addSorter(DatagridConfiguration $config) - { - $config->offsetSetByPath( - sprintf('[sorters][columns][%s]', $this->getDataName()), - ['data_name' => 'channelsCount'] - ); - } - - /** - * @param DatagridConfiguration $config - */ - protected function addFilter(DatagridConfiguration $config) - { - $config->offsetSetByPath( - sprintf('[filters][columns][%s]', $this->getDataName()), - [ - 'type' => 'choice', - 'data_name' => $this->getJoinAlias() . '.code', - 'enabled' => false, - 'options' => [ - 'field_options' => [ - 'multiple' => true, - 'choices' => $this->salesChannelsChoicesProvider->getChannels() - ] - ] - ] - ); - } -} diff --git a/src/Marello/Bundle/SalesBundle/Resources/config/services.yml b/src/Marello/Bundle/SalesBundle/Resources/config/services.yml index 3603147bf..7e9f7ebe2 100644 --- a/src/Marello/Bundle/SalesBundle/Resources/config/services.yml +++ b/src/Marello/Bundle/SalesBundle/Resources/config/services.yml @@ -119,14 +119,6 @@ services: tags: - { name: kernel.event_listener, event: oro_datagrid.orm_datasource.result.after.marello-sales-channel-groups, method: onResultAfter } - marello_sales.event_listener.datagrid.products_grid: - class: 'Marello\Bundle\SalesBundle\EventListener\Datagrid\SalesChannelsDatagridListener' - arguments: - - 'Marello\Bundle\ProductBundle\Entity\Product' - - '@marello_sales.provider.basic_sales_channels_choices' - tags: - - { name: kernel.event_listener, event: oro_datagrid.datagrid.build.before.marello-products-grid, method: onBuildBefore } - marello_sales.datagrid.saleschannelgroup.action_permission_provider: class: 'Marello\Bundle\SalesBundle\Datagrid\SalesChannelGroupActionPermissionProvider' public: true diff --git a/src/Marello/Bundle/SalesBundle/Resources/translations/messages.en.yml b/src/Marello/Bundle/SalesBundle/Resources/translations/messages.en.yml index ffeac0c76..fc869bebd 100644 --- a/src/Marello/Bundle/SalesBundle/Resources/translations/messages.en.yml +++ b/src/Marello/Bundle/SalesBundle/Resources/translations/messages.en.yml @@ -19,6 +19,7 @@ marello: channel_type.label: Type owner.label: Owner localization.label: Localization + products.label: Products controller.message.saved: Sales Channel saved form.select_saleschannels: Select Sales Channels form.select_saleschannel: Select Sales Channel diff --git a/src/Marello/Bundle/SalesBundle/Resources/views/SalesChannel/Datagrid/Property/channels.html.twig b/src/Marello/Bundle/SalesBundle/Resources/views/SalesChannel/Datagrid/Property/channels.html.twig deleted file mode 100644 index 95cd7252c..000000000 --- a/src/Marello/Bundle/SalesBundle/Resources/views/SalesChannel/Datagrid/Property/channels.html.twig +++ /dev/null @@ -1,7 +0,0 @@ -{% set channels = record.getValue('channels')|split(';') %} -{% for index, channelSet in channels %} - {% set values = channelSet|split('|') %} - {% if values|length > 0 %} - {{ values[0] }}
- {% endif %} -{% endfor %} \ No newline at end of file diff --git a/src/Marello/Bundle/SalesBundle/Tests/Unit/Twig/SalesExtensionTest.php b/src/Marello/Bundle/SalesBundle/Tests/Unit/Twig/SalesExtensionTest.php index 88ce57f1f..eda508a65 100644 --- a/src/Marello/Bundle/SalesBundle/Tests/Unit/Twig/SalesExtensionTest.php +++ b/src/Marello/Bundle/SalesBundle/Tests/Unit/Twig/SalesExtensionTest.php @@ -35,6 +35,10 @@ public function testGetFunctions() new TwigFunction( 'marello_sales_has_active_channels', [$this->extension, 'checkActiveChannels'] + ), + new TwigFunction( + 'marello_get_sales_channel_name_by_code', + [$this->extension, 'getChannelNameByCode'] ) ], $this->extension->getFunctions() @@ -81,4 +85,41 @@ public function checkActiveChannelsDataProvider() ], ]; } + + /** + * @param $expectedChannel + * @param $code + * @param $expectedResult + * @dataProvider getChannelNameByCodeDataProvider + */ + public function testGetChannelNameByCode($expectedChannel, $code, $expectedResult) + { + $this->salesChannelRepository + ->expects(static::once()) + ->method('findOneBy') + ->willReturn($expectedChannel); + + static::assertEquals($expectedResult, $this->extension->getChannelNameByCode($code)); + } + + /** + * @return array[] + */ + public function getChannelNameByCodeDataProvider() + { + $channel = new SalesChannel('channel1'); + $channel->setCode('test'); + return [ + 'with active channels' => [ + 'expectedChannel' => $channel, + 'code' => 'test', + 'expectedResult' => 'channel1', + ], + 'without active channels' => [ + 'expectedChannel' => null, + 'code' => 'MySalesChannelCode', + 'expectedResult' => 'MySalesChannelCode' + ], + ]; + } } diff --git a/src/Marello/Bundle/SalesBundle/Twig/SalesExtension.php b/src/Marello/Bundle/SalesBundle/Twig/SalesExtension.php index dc1926c1b..df7d8e28a 100644 --- a/src/Marello/Bundle/SalesBundle/Twig/SalesExtension.php +++ b/src/Marello/Bundle/SalesBundle/Twig/SalesExtension.php @@ -32,6 +32,10 @@ public function getFunctions() new TwigFunction( 'marello_sales_has_active_channels', [$this, 'checkActiveChannels'] + ), + new TwigFunction( + 'marello_get_sales_channel_name_by_code', + [$this, 'getChannelNameByCode'] ) ]; } @@ -48,6 +52,21 @@ public function checkActiveChannels() return false; } + /** + * @param string $code + * @return string + */ + public function getChannelNameByCode($code) + { + $channel = $this->salesChannelRepository + ->findOneBy(['code' => $code]); + if ($channel) { + return $channel->getName(); + } + + return $code; + } + /** * Returns the name of the extension. * diff --git a/src/Marello/Bundle/TaxBundle/EventListener/Datagrid/TaxCodeDatagridListener.php b/src/Marello/Bundle/TaxBundle/EventListener/Datagrid/TaxCodeDatagridListener.php index d1976f7cd..0a529b546 100644 --- a/src/Marello/Bundle/TaxBundle/EventListener/Datagrid/TaxCodeDatagridListener.php +++ b/src/Marello/Bundle/TaxBundle/EventListener/Datagrid/TaxCodeDatagridListener.php @@ -96,7 +96,7 @@ protected function addSelect(DatagridConfiguration $config) { $config->getOrmQuery()->addSelect( sprintf('%s.code AS %s', $this->getJoinAlias(), $this->getDataName()) - ); + )->addGroupBy(sprintf('%s.code', $this->getJoinAlias())); } /**