diff --git a/.travis.yml b/.travis.yml index b58c5e2b..23270935 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,6 @@ cache: - $HOME/.composer/cache php: - - '5.6' - '7.0' - '7.1' diff --git a/README.md b/README.md index 7d7c1384..acedbaa8 100644 --- a/README.md +++ b/README.md @@ -8,16 +8,11 @@ ## Installation -The following will ask you to setup the database info, so make sure you have one -ready. +Make sure you have [composer](https://getcomposer.org/) installed. +Then run the following (it will ask you for database info, so make sure you have one ready): $ composer create-project --stability=dev siwapp/siwapp-sf3 my_siwapp; cd my_siwapp -You will need to have Java installed and available in your path (for yuicompressor). -On Debian/Ubuntu-based systems you can install it using the following: - - $ sudo apt-get install default-jre-headless - Then you can dump the assets: $ php bin/console assetic:dump --env=prod @@ -92,6 +87,8 @@ Just add a cronjob that runs `php bin/console siwapp:recurring:generate-pending` ### Interface language -To have the siwapp interface in another language you will need the php intl extension installed. -Then visit your profile page, change your locale and then log out. When you log back in the interface language should be switched. +To have the siwapp interface in another language you will need the php-intl extension installed. + +Visit your profile page, change your locale and then log out. When you log back in the interface language should be switched. + Siwapp is translated only to Spanish for now, feel free to contribute more translations! diff --git a/app/Resources/java/yuicompressor-2.4.7.jar b/app/Resources/java/yuicompressor-2.4.7.jar deleted file mode 100644 index 3c9a408a..00000000 Binary files a/app/Resources/java/yuicompressor-2.4.7.jar and /dev/null differ diff --git a/app/config/config.yml b/app/config/config.yml index 6f0f0ab5..ee84673e 100644 --- a/app/config/config.yml +++ b/app/config/config.yml @@ -45,10 +45,16 @@ assetic: use_controller: '%kernel.debug%' filters: cssrewrite: ~ - yui_js: - jar: '%kernel.root_dir%/Resources/java/yuicompressor-2.4.7.jar' - yui_css: - jar: '%kernel.root_dir%/Resources/java/yuicompressor-2.4.7.jar' + bundles: + - SiwappConfigBundle + - SiwappCoreBundle + - SiwappInvoiceBundle + - SiwappCustomerBundle + - SiwappProductBundle + - SiwappDashboardBundle + - SiwappEstimateBundle + - SiwappRecurringInvoiceBundle + - SiwappUserBundle # Doctrine Configuration doctrine: diff --git a/composer.json b/composer.json index 70c05542..ce778b36 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,7 @@ } }, "require": { - "php": ">=5.6", + "php": ">=7.0", "symfony/symfony": "3.2.*", "doctrine/orm": "^2.5", "doctrine/doctrine-bundle": "^1.6", diff --git a/composer.lock b/composer.lock index 5891bc4a..ec5be31d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "a47e5600b24af75f1b3db6752a2db641", - "content-hash": "97f245b1afc25908b25452f327dd96ce", + "hash": "c2427e4696c9acd17874c3fed4d788df", + "content-hash": "f3a76118644f3b5758a89d30ca9da1ff", "packages": [ { "name": "behat/transliterator", @@ -937,12 +937,12 @@ "source": { "type": "git", "url": "https://github.com/FriendsOfSymfony/FOSUserBundle.git", - "reference": "7261f7aa143b4bfdb0b7ddc5df208067fa7be698" + "reference": "03ce036476ac45fac6f84cec7542062b12900ecb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfSymfony/FOSUserBundle/zipball/7261f7aa143b4bfdb0b7ddc5df208067fa7be698", - "reference": "7261f7aa143b4bfdb0b7ddc5df208067fa7be698", + "url": "https://api.github.com/repos/FriendsOfSymfony/FOSUserBundle/zipball/03ce036476ac45fac6f84cec7542062b12900ecb", + "reference": "03ce036476ac45fac6f84cec7542062b12900ecb", "shasum": "" }, "require": { @@ -1004,7 +1004,7 @@ "keywords": [ "User management" ], - "time": "2016-12-03 17:42:44" + "time": "2016-12-08 14:40:38" }, { "name": "gedmo/doctrine-extensions", @@ -1188,16 +1188,16 @@ }, { "name": "knplabs/knp-components", - "version": "1.3.3", + "version": "1.3.4", "source": { "type": "git", "url": "https://github.com/KnpLabs/knp-components.git", - "reference": "bc49e739d1cce94d783b1e23bc5b263b38dc47da" + "reference": "f98bcc6d348fbe863a224b468e11fb5e91e28f2a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/KnpLabs/knp-components/zipball/bc49e739d1cce94d783b1e23bc5b263b38dc47da", - "reference": "bc49e739d1cce94d783b1e23bc5b263b38dc47da", + "url": "https://api.github.com/repos/KnpLabs/knp-components/zipball/f98bcc6d348fbe863a224b468e11fb5e91e28f2a", + "reference": "f98bcc6d348fbe863a224b468e11fb5e91e28f2a", "shasum": "" }, "require": { @@ -1255,7 +1255,7 @@ "pager", "paginator" ], - "time": "2016-04-21 06:26:20" + "time": "2016-12-06 18:10:24" }, { "name": "knplabs/knp-paginator-bundle", @@ -1738,16 +1738,16 @@ }, { "name": "sensio/distribution-bundle", - "version": "v5.0.14", + "version": "v5.0.15", "source": { "type": "git", "url": "https://github.com/sensiolabs/SensioDistributionBundle.git", - "reference": "e64947de9ebc37732a62f5115164484a9bee7fa6" + "reference": "d294b0665cf09c799e9c1993d5c776a5bf55cb85" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sensiolabs/SensioDistributionBundle/zipball/e64947de9ebc37732a62f5115164484a9bee7fa6", - "reference": "e64947de9ebc37732a62f5115164484a9bee7fa6", + "url": "https://api.github.com/repos/sensiolabs/SensioDistributionBundle/zipball/d294b0665cf09c799e9c1993d5c776a5bf55cb85", + "reference": "d294b0665cf09c799e9c1993d5c776a5bf55cb85", "shasum": "" }, "require": { @@ -1786,7 +1786,7 @@ "configuration", "distribution" ], - "time": "2016-10-30 23:18:01" + "time": "2016-12-06 07:29:27" }, { "name": "sensio/framework-extra-bundle", @@ -3235,16 +3235,16 @@ }, { "name": "phpunit/phpunit", - "version": "5.7.2", + "version": "5.7.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "336aff0ac52e306c98e7455bc3e8d7b0bf777a5e" + "reference": "de164acc2f2bb0b79beb892a36260264b2a03233" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/336aff0ac52e306c98e7455bc3e8d7b0bf777a5e", - "reference": "336aff0ac52e306c98e7455bc3e8d7b0bf777a5e", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/de164acc2f2bb0b79beb892a36260264b2a03233", + "reference": "de164acc2f2bb0b79beb892a36260264b2a03233", "shasum": "" }, "require": { @@ -3255,7 +3255,7 @@ "ext-xml": "*", "myclabs/deep-copy": "~1.3", "php": "^5.6 || ^7.0", - "phpspec/prophecy": "^1.3.1", + "phpspec/prophecy": "^1.6.2", "phpunit/php-code-coverage": "^4.0.3", "phpunit/php-file-iterator": "~1.4", "phpunit/php-text-template": "~1.2", @@ -3313,20 +3313,20 @@ "testing", "xunit" ], - "time": "2016-12-03 08:33:00" + "time": "2016-12-09 02:48:53" }, { "name": "phpunit/phpunit-mock-objects", - "version": "3.4.2", + "version": "3.4.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "90a08f5deed5f7ac35463c161f2e8fa0e5652faf" + "reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/90a08f5deed5f7ac35463c161f2e8fa0e5652faf", - "reference": "90a08f5deed5f7ac35463c161f2e8fa0e5652faf", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", + "reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", "shasum": "" }, "require": { @@ -3372,7 +3372,7 @@ "mock", "xunit" ], - "time": "2016-11-27 07:52:03" + "time": "2016-12-08 20:27:08" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -3889,28 +3889,28 @@ }, { "name": "sensio/generator-bundle", - "version": "v3.1.1", + "version": "v3.1.2", "source": { "type": "git", "url": "https://github.com/sensiolabs/SensioGeneratorBundle.git", - "reference": "0d3c9c4864142dc6a368fa0d952a8b83215e8740" + "reference": "ec278c0bd530edf155c4a00900577b5cb80f559e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sensiolabs/SensioGeneratorBundle/zipball/0d3c9c4864142dc6a368fa0d952a8b83215e8740", - "reference": "0d3c9c4864142dc6a368fa0d952a8b83215e8740", + "url": "https://api.github.com/repos/sensiolabs/SensioGeneratorBundle/zipball/ec278c0bd530edf155c4a00900577b5cb80f559e", + "reference": "ec278c0bd530edf155c4a00900577b5cb80f559e", "shasum": "" }, "require": { "symfony/console": "~2.7|~3.0", "symfony/framework-bundle": "~2.7|~3.0", "symfony/process": "~2.7|~3.0", - "symfony/yaml": "~2.7|~3.0" + "symfony/yaml": "~2.7|~3.0", + "twig/twig": "^1.28.2|^2.0" }, "require-dev": { "doctrine/orm": "~2.4", - "symfony/doctrine-bridge": "~2.7|~3.0", - "twig/twig": "~1.18" + "symfony/doctrine-bridge": "~2.7|~3.0" }, "type": "symfony-bundle", "extra": { @@ -3937,7 +3937,7 @@ } ], "description": "This bundle generates code for you", - "time": "2016-11-07 19:48:31" + "time": "2016-12-05 16:01:19" }, { "name": "symfony/phpunit-bridge", @@ -4056,7 +4056,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=5.6" + "php": ">=7.0" }, "platform-dev": [] } diff --git a/src/Siwapp/ConfigBundle/Controller/ConfigController.php b/src/Siwapp/ConfigBundle/Controller/ConfigController.php index c2e3e9a9..8f3bb8d7 100644 --- a/src/Siwapp/ConfigBundle/Controller/ConfigController.php +++ b/src/Siwapp/ConfigBundle/Controller/ConfigController.php @@ -34,7 +34,7 @@ public function globalSettingsAction(Request $request) if ($request->getMethod() == 'POST') { $form->handleRequest($request); - if ($form->isSubmitted()) { + if ($form->isSubmitted() && $form->isValid()) { $data = $form->getData(); $series = $data['series']; $taxes = $data['taxes']; diff --git a/src/Siwapp/CoreBundle/Controller/AbstractInvoiceController.php b/src/Siwapp/CoreBundle/Controller/AbstractInvoiceController.php new file mode 100644 index 00000000..b32afacc --- /dev/null +++ b/src/Siwapp/CoreBundle/Controller/AbstractInvoiceController.php @@ -0,0 +1,65 @@ +getDoctrine()->getRepository('SiwappConfigBundle:Property'); + $pdfSize = $config->get('pdf_size'); + $pdfOrientation = $config->get('pdf_orientation'); + $config = []; + if ($pdfSize) { + $config['page-size'] = $pdfSize; + } + if ($pdfOrientation) { + $config['orientation'] = $pdfOrientation; + } + + return $this->get('knp_snappy.pdf')->getOutputFromHtml($html, $config); + } + + protected function getInvoiceTotalsFromPost(array $post, AbstractInvoice $invoice, string $locale): array + { + $em = $this->getDoctrine()->getManager(); + $taxRepo = $em->getRepository('SiwappCoreBundle:Tax'); + $currency = $em->getRepository('SiwappConfigBundle:Property')->get('currency'); + $formatter = new \NumberFormatter($locale, \NumberFormatter::CURRENCY); + + $totals = []; + foreach ($post['items'] as $index => $postItem) { + $item = new Item; + $item->setUnitaryCost($postItem['unitary_cost']); + $item->setQuantity($postItem['quantity']); + $item->setDiscount($postItem['discount_percent']); + if (isset($postItem['taxes'])) { + foreach($postItem['taxes'] as $taxId) { + $tax = $taxRepo->find($taxId); + if (!$tax) { + continue; + } + $item->addTax($tax); + } + } + $totals['items'][$index] = [ + 'gross_amount' => $formatter->formatCurrency($item->getGrossAmount(), $currency), + ]; + $invoice->addItem($item); + } + $invoice->checkAmounts(); + + $totals += [ + 'invoice_base_amount' => $formatter->formatCurrency($invoice->getBaseAmount(), $currency), + 'invoice_tax_amount' => $formatter->formatCurrency($invoice->getTaxAmount(), $currency), + 'invoice_gross_amount' => $formatter->formatCurrency($invoice->getGrossAmount(), $currency), + ]; + + return $totals; + } +} diff --git a/src/Siwapp/CoreBundle/Controller/CoreController.php b/src/Siwapp/CoreBundle/Controller/CoreController.php index ae559bba..811ba0d7 100644 --- a/src/Siwapp/CoreBundle/Controller/CoreController.php +++ b/src/Siwapp/CoreBundle/Controller/CoreController.php @@ -2,9 +2,9 @@ namespace Siwapp\CoreBundle\Controller; -use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; +use Symfony\Bundle\FrameworkBundle\Controller\Controller; class CoreController extends Controller { diff --git a/src/Siwapp/CoreBundle/DataFixtures/ORM/LoadSettingsData.php b/src/Siwapp/CoreBundle/DataFixtures/ORM/LoadSettingsData.php new file mode 100644 index 00000000..35bec204 --- /dev/null +++ b/src/Siwapp/CoreBundle/DataFixtures/ORM/LoadSettingsData.php @@ -0,0 +1,40 @@ + 'My Company', + 'company_identification' => 'XX123456789', + 'company_address' => 'My street name, 12', + 'company_email' => 'info@mycompany.com', + 'company_phone' => '+01 234 567 89', + 'company_fax' => '+01 234 567 89', + 'company_url' => 'https://www.mycompany.com', + 'currency' => 'EUR', + ]; + foreach ($settings as $name => $value) { + $setting = new Property(); + $setting->setKey($name); + $setting->setValue($value); + + $manager->persist($setting); + $manager->flush(); + $this->addReference($name, $setting); + } + } + + public function getOrder() + { + return '0'; + } +} diff --git a/src/Siwapp/CoreBundle/DataFixtures/ORM/LoadTaxData.php b/src/Siwapp/CoreBundle/DataFixtures/ORM/LoadTaxData.php index 76bccc36..269c4659 100644 --- a/src/Siwapp/CoreBundle/DataFixtures/ORM/LoadTaxData.php +++ b/src/Siwapp/CoreBundle/DataFixtures/ORM/LoadTaxData.php @@ -21,32 +21,32 @@ public function setContainer(ContainerInterface $container = null) public function load(ObjectManager $manager) { - $taxes = array( - 'Tax_1'=>array( - 'name'=>'IVA 16%', - 'value'=>16, - 'active'=>true, - 'is_default'=>true - ), - 'Tax_2'=>array( - 'name'=>'IVA 4%', - 'value'=>4, - 'active'=>true, - 'is_default'=>false - ), - 'Tax_3'=>array( - 'name'=>'IVA 7%', - 'value'=>7, - 'active'=>false, - 'is_default'=>false - ), - 'Tax_4'=>array( - 'name'=>'IRPF', - 'value'=>-15, - 'active'=>true, - 'is_default'=>true - ) - ); + $taxes = [ + 'Tax_1' => [ + 'name' => 'IVA', + 'value' => 16, + 'active' => true, + 'is_default' => true, + ], + 'Tax_2' => [ + 'name' => 'IVA', + 'value' => 4, + 'active' => true, + 'is_default' => false, + ], + 'Tax_3' => [ + 'name'=>'IVA', + 'value'=>7, + 'active'=>false, + 'is_default'=>false + ], + 'Tax_4' => [ + 'name' => 'IRPF', + 'value' => -15, + 'active' => true, + 'is_default' => true, + ], + ]; foreach ($taxes as $ref => $values) { $tax = new Tax(); foreach ($values as $fname => $fvalue) { @@ -60,7 +60,7 @@ public function load(ObjectManager $manager) $this->addReference($ref, $tax); } } - + public function getOrder() { return '0'; diff --git a/src/Siwapp/CoreBundle/Entity/Item.php b/src/Siwapp/CoreBundle/Entity/Item.php index d57a154c..650ba111 100644 --- a/src/Siwapp/CoreBundle/Entity/Item.php +++ b/src/Siwapp/CoreBundle/Entity/Item.php @@ -326,7 +326,7 @@ public function __get($name) public function __isset($name) { $classVars = array_keys(get_object_vars($this)); - $extraVars = ['discount_amount', 'base_amount', 'discount_amount', 'net_amount', 'tax_amount', 'gross_amount']; + $extraVars = ['discount_amount', 'base_amount', 'net_amount', 'tax_amount', 'gross_amount']; if (in_array($name, array_merge($classVars, $extraVars))) { return true; } diff --git a/src/Siwapp/CoreBundle/Entity/Tax.php b/src/Siwapp/CoreBundle/Entity/Tax.php index c21d89d9..209eba0c 100644 --- a/src/Siwapp/CoreBundle/Entity/Tax.php +++ b/src/Siwapp/CoreBundle/Entity/Tax.php @@ -143,8 +143,13 @@ public function getId() return $this->id; } - public function __toString() + public function label(): string { - return $this->getName(); + return $this->getName() . ' (' . $this->getValue() . '%)'; + } + + public function __toString(): string + { + return $this->label(); } } diff --git a/src/Siwapp/CoreBundle/Form/ItemType.php b/src/Siwapp/CoreBundle/Form/ItemType.php index 871e777f..513d154c 100644 --- a/src/Siwapp/CoreBundle/Form/ItemType.php +++ b/src/Siwapp/CoreBundle/Form/ItemType.php @@ -3,6 +3,7 @@ namespace Siwapp\CoreBundle\Form; use Doctrine\Common\Persistence\ObjectManager; +use Siwapp\CoreBundle\Entity\Tax; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\CallbackTransformer; @@ -34,7 +35,9 @@ public function buildForm(FormBuilderInterface $builder, array $options) $builder->add('taxes', EntityType::class, array( 'class' => 'SiwappCoreBundle:Tax', - 'choice_label' => 'name', + 'choice_label' => function (Tax $value, $key, $index) { + return $value->label(); + }, 'multiple' => true, 'required' => false, )); diff --git a/src/Siwapp/CoreBundle/Form/TaxType.php b/src/Siwapp/CoreBundle/Form/TaxType.php index 35578a4b..d25b47b9 100644 --- a/src/Siwapp/CoreBundle/Form/TaxType.php +++ b/src/Siwapp/CoreBundle/Form/TaxType.php @@ -25,10 +25,12 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'translation_domain' => 'SiwappCoreBundle', ]) ->add('active', CheckboxType::class, [ + 'required' => false, 'label' => 'tax.form.active', 'translation_domain' => 'SiwappCoreBundle', ]) ->add('is_default', CheckboxType::class, [ + 'required' => false, 'label' => 'tax.form.is_default', 'translation_domain' => 'SiwappCoreBundle', ]) diff --git a/src/Siwapp/CoreBundle/Resources/public/css/siwapp.layout.css b/src/Siwapp/CoreBundle/Resources/public/css/siwapp.layout.css index 25bd8e52..4a1b8e20 100644 --- a/src/Siwapp/CoreBundle/Resources/public/css/siwapp.layout.css +++ b/src/Siwapp/CoreBundle/Resources/public/css/siwapp.layout.css @@ -132,6 +132,7 @@ a.btn-primary:active:hover, background-color: #ffffff; border: 1px solid #ddd; border-bottom-color: transparent; + cursor: pointer; } #bd { padding: 0; diff --git a/src/Siwapp/CoreBundle/Resources/public/js/global.js b/src/Siwapp/CoreBundle/Resources/public/js/global.js index 1a6a81e4..72ef4438 100644 --- a/src/Siwapp/CoreBundle/Resources/public/js/global.js +++ b/src/Siwapp/CoreBundle/Resources/public/js/global.js @@ -1,4 +1,4 @@ -jQuery(function($){ +jQuery(function($) { // HTML5 Placeholders for forms $('input, textarea').placeholder(); diff --git a/src/Siwapp/CoreBundle/Resources/public/js/invoices-common.js b/src/Siwapp/CoreBundle/Resources/public/js/invoices-common.js new file mode 100644 index 00000000..ca33da62 --- /dev/null +++ b/src/Siwapp/CoreBundle/Resources/public/js/invoices-common.js @@ -0,0 +1,14 @@ +function updateInvoiceTotals(path, $changedItem) { + $.post(path, $changedItem.parents('form').serialize()) + .done(function(data) { + $('td.base-amount').text(data.invoice_base_amount); + $('td.tax-amount').text(data.invoice_tax_amount); + $('td.gross-amount').text(data.invoice_gross_amount); + for (index in data.items) { + $('input[name*="[items][' + index + ']"]') + .parents('tr') + .find('.item-gross-amount') + .text(data.items[index].gross_amount); + } + }); +} diff --git a/src/Siwapp/CoreBundle/Resources/translations/SiwappCoreBundle.es.yml b/src/Siwapp/CoreBundle/Resources/translations/SiwappCoreBundle.es.yml index 709c9465..311d4afb 100644 --- a/src/Siwapp/CoreBundle/Resources/translations/SiwappCoreBundle.es.yml +++ b/src/Siwapp/CoreBundle/Resources/translations/SiwappCoreBundle.es.yml @@ -1,5 +1,5 @@ html: - title: 'Aplicación de facturación' + title: 'Sistema de facturación' menu: settings: 'Ajustes' diff --git a/src/Siwapp/CoreBundle/Resources/views/AbstractInvoice/edit.html.twig b/src/Siwapp/CoreBundle/Resources/views/AbstractInvoice/edit.html.twig index a0470c02..a4568837 100644 --- a/src/Siwapp/CoreBundle/Resources/views/AbstractInvoice/edit.html.twig +++ b/src/Siwapp/CoreBundle/Resources/views/AbstractInvoice/edit.html.twig @@ -6,7 +6,6 @@ {% stylesheets 'bundles/siwappinvoice/css/invoice.css' filter='cssrewrite' - filter='?yui_css' %} {% endstylesheets %} @@ -115,6 +114,10 @@ var prototype = collectionHolder.attr('data-prototype'); form = prototype.replace(/__name__/g, collectionHolder.children().length); collectionHolder.append(form); + {% if bundle_exists('SiwappProductBundle') %} + addProductNameAutocomplete('{{ path('product_autocomplete_description') }}'); + addProductDescriptionAutocomplete('{{ path('product_autocomplete_description') }}'); + {% endif %} }); @@ -124,15 +127,15 @@ {% trans %}abstract_invoice.form.subtotal{% endtrans %} - {{ entity.baseAmount|localizedcurrency(currency, app.request.locale) }} + {{ entity.baseAmount|localizedcurrency(currency, app.request.locale) }} {% trans %}abstract_invoice.form.total_taxes{% endtrans %} - {{ entity.taxAmount|localizedcurrency(currency, app.request.locale) }} + {{ entity.taxAmount|localizedcurrency(currency, app.request.locale) }} {% trans with {'%currency%': currency} %}abstract_invoice.form.total{% endtrans %} - {{ entity.grossAmount|localizedcurrency(currency, app.request.locale) }} + {{ entity.grossAmount|localizedcurrency(currency, app.request.locale) }} @@ -180,3 +183,16 @@ {% endif %} {% endblock %} + +{% block javascripts %} + {{ parent() }} + + {% if bundle_exists('SiwappProductBundle') %} + {% javascripts + 'bundles/siwappproduct/js/products.js' + 'bundles/siwappcore/js/invoices-common.js' + %} + + {% endjavascripts %} + {% endif %} +{% endblock %} diff --git a/src/Siwapp/CoreBundle/Resources/views/AbstractInvoice/show.html.twig b/src/Siwapp/CoreBundle/Resources/views/AbstractInvoice/show.html.twig index 70eeae0f..665ad028 100644 --- a/src/Siwapp/CoreBundle/Resources/views/AbstractInvoice/show.html.twig +++ b/src/Siwapp/CoreBundle/Resources/views/AbstractInvoice/show.html.twig @@ -6,7 +6,6 @@ {% stylesheets 'bundles/siwappinvoice/css/invoice.css' filter='cssrewrite' - filter='?yui_css' %} {% endstylesheets %} diff --git a/src/Siwapp/CoreBundle/Resources/views/Item/edit.html.twig b/src/Siwapp/CoreBundle/Resources/views/Item/edit.html.twig index b6e3c848..8e17e52a 100644 --- a/src/Siwapp/CoreBundle/Resources/views/Item/edit.html.twig +++ b/src/Siwapp/CoreBundle/Resources/views/Item/edit.html.twig @@ -1,38 +1,33 @@ - + {# TODO: Make this pretty for row actions (add tax, add item before, add item after...) #} {% if bundle_exists('SiwappProductBundle') %} - {{ form_widget(form.product, {'attr': {'class': 'product-autocomplete'}}) }} + {{ form_widget(form.product, {'attr': {'class': 'product-autocomplete-name'}}) }} {{ form_errors(form.product) }} + + {% if bundle_exists('SiwappProductBundle') %} + {% endif %} {% endif %} - {{ form_widget(form.description) }} + {{ form_widget(form.description, {'attr': {'class': 'product-autocomplete-description'}}) }} {{ form_errors(form.description) }} + + {% if bundle_exists('SiwappProductBundle') %} + + {% endif %} {{ form_widget(form.quantity) }} @@ -55,7 +50,7 @@ }); - + {{ entity.grossAmount|localizedcurrency(currency, app.request.locale) }} diff --git a/src/Siwapp/CoreBundle/Resources/views/Item/show.html.twig b/src/Siwapp/CoreBundle/Resources/views/Item/show.html.twig index 68d4bc83..10475aa2 100644 --- a/src/Siwapp/CoreBundle/Resources/views/Item/show.html.twig +++ b/src/Siwapp/CoreBundle/Resources/views/Item/show.html.twig @@ -6,14 +6,14 @@ {{ item.quantity }} - {{ item.unitaryCost|localizedcurrency(currency, app.request.locale) }} + {{ item.unitary_cost|localizedcurrency(currency, app.request.locale) }} {{ item.discount }}% {% for tax in item.taxes %} - {{ tax.name }} + {{ tax.label() }} {% endfor %} diff --git a/src/Siwapp/CoreBundle/Resources/views/base.html.twig b/src/Siwapp/CoreBundle/Resources/views/base.html.twig index eedd5ebd..0bcd748e 100644 --- a/src/Siwapp/CoreBundle/Resources/views/base.html.twig +++ b/src/Siwapp/CoreBundle/Resources/views/base.html.twig @@ -14,7 +14,6 @@ 'bundles/siwappcore/css/siwapp.patterns.css' 'bundles/siwappcore/css/siwapp.autocomplete.css' filter='cssrewrite' - filter='?yui_css' %} {% endstylesheets %} @@ -24,7 +23,6 @@ 'bundles/siwappcore/vendor/jquery-2.2.3.min.js' 'bundles/siwappcore/vendor/modernizr-custom.js' output='js/core.js' - filter='?yui_js' %} {% endjavascripts %} @@ -145,7 +143,6 @@ 'bundles/siwappcore/vendor/select2/js/select2.min.js' 'bundles/siwappcore/js/global.js' output='js/frameworks.js' - filter='?yui_js' %} {% endjavascripts %} diff --git a/src/Siwapp/CoreBundle/Resources/views/base_minimal.html.twig b/src/Siwapp/CoreBundle/Resources/views/base_minimal.html.twig index c4c9ae99..19862b6f 100644 --- a/src/Siwapp/CoreBundle/Resources/views/base_minimal.html.twig +++ b/src/Siwapp/CoreBundle/Resources/views/base_minimal.html.twig @@ -9,7 +9,6 @@ 'bundles/siwappcore/css/siwapp.layout.css' 'bundles/siwappcore/css/siwapp.forms.css' filter='cssrewrite' - filter='?yui_css' %} {% endstylesheets %} diff --git a/src/Siwapp/CustomerBundle/Controller/CustomerController.php b/src/Siwapp/CustomerBundle/Controller/CustomerController.php index 36d6cb78..c0251453 100644 --- a/src/Siwapp/CustomerBundle/Controller/CustomerController.php +++ b/src/Siwapp/CustomerBundle/Controller/CustomerController.php @@ -31,7 +31,7 @@ public function indexAction(Request $request) 'method' => 'GET', ]); $form->handleRequest($request); - if ($form->isSubmitted()) { + if ($form->isSubmitted() && $form->isValid()) { $pagination = $repo->paginatedSearch($form->getData(), $limit, $request->query->getInt('page', 1)); } else { $pagination = $repo->paginatedSearch([], $limit, $request->query->getInt('page', 1)); @@ -45,7 +45,7 @@ public function indexAction(Request $request) 'action' => $this->generateUrl('customer_index'), ]); $listForm->handleRequest($request); - if ($listForm->isSubmitted()) { + if ($listForm->isSubmitted() && $listForm->isValid()) { $data = $listForm->getData(); if ($request->request->has('delete')) { if (empty($data['customers'])) { @@ -98,7 +98,7 @@ public function addAction(Request $request) ]); $form->handleRequest($request); - if ($form->isSubmitted()) { + if ($form->isSubmitted() && $form->isValid()) { $em->persist($customer); $em->flush(); $this->addTranslatedMessage('flash.added'); @@ -129,7 +129,7 @@ public function editAction(Request $request, $id) ]); $form->handleRequest($request); - if ($form->isSubmitted()) { + if ($form->isSubmitted() && $form->isValid()) { $em->persist($customer); $em->flush(); $this->addTranslatedMessage('flash.updated'); diff --git a/src/Siwapp/CustomerBundle/Resources/translations/SiwappCustomerBundle.en.yml b/src/Siwapp/CustomerBundle/Resources/translations/SiwappCustomerBundle.en.yml index 2be02e78..fc48a4fb 100644 --- a/src/Siwapp/CustomerBundle/Resources/translations/SiwappCustomerBundle.en.yml +++ b/src/Siwapp/CustomerBundle/Resources/translations/SiwappCustomerBundle.en.yml @@ -15,6 +15,7 @@ search: reset: 'Reset' form: + customer: 'Customer' name: 'Name' identification: 'Identification' email: 'E-mail' diff --git a/src/Siwapp/CustomerBundle/Resources/translations/SiwappCustomerBundle.es.yml b/src/Siwapp/CustomerBundle/Resources/translations/SiwappCustomerBundle.es.yml index a2eeddeb..1899105c 100644 --- a/src/Siwapp/CustomerBundle/Resources/translations/SiwappCustomerBundle.es.yml +++ b/src/Siwapp/CustomerBundle/Resources/translations/SiwappCustomerBundle.es.yml @@ -15,6 +15,7 @@ search: reset: 'Limpiar' form: + customer: 'Cliente' name: 'Nombre' identification: 'Identificación' email: 'Correo electrónico' diff --git a/src/Siwapp/CustomerBundle/Resources/views/Customer/edit.html.twig b/src/Siwapp/CustomerBundle/Resources/views/Customer/edit.html.twig index 9fdfd0d2..547022bc 100644 --- a/src/Siwapp/CustomerBundle/Resources/views/Customer/edit.html.twig +++ b/src/Siwapp/CustomerBundle/Resources/views/Customer/edit.html.twig @@ -15,7 +15,7 @@
-

Customer {{ entity.label() }}

+

{% trans %}form.customer{% endtrans %} {{ entity.label() }}

{{ form_start(form, {'attr': {'class': 'form-stacked' } }) }} diff --git a/src/Siwapp/DashboardBundle/Controller/DashboardController.php b/src/Siwapp/DashboardBundle/Controller/DashboardController.php index a51fc651..814b30dd 100644 --- a/src/Siwapp/DashboardBundle/Controller/DashboardController.php +++ b/src/Siwapp/DashboardBundle/Controller/DashboardController.php @@ -30,7 +30,7 @@ public function indexAction(Request $request) 'method' => 'GET', ]); $form->handleRequest($request); - if ($form->isSubmitted()) { + if ($form->isSubmitted() && $form->isValid()) { $params = $form->getData(); } else { $params = []; diff --git a/src/Siwapp/DashboardBundle/Resources/translations/SiwappDashboardBundle.es.yml b/src/Siwapp/DashboardBundle/Resources/translations/SiwappDashboardBundle.es.yml index 7dec0c07..2e1e5d8f 100644 --- a/src/Siwapp/DashboardBundle/Resources/translations/SiwappDashboardBundle.es.yml +++ b/src/Siwapp/DashboardBundle/Resources/translations/SiwappDashboardBundle.es.yml @@ -10,6 +10,6 @@ list: balance_total: 'Total' balance_net: 'Neto' balance_taxes: 'Impuestos' - taxes: 'Retención de impuestos' + taxes: 'Impuestos retenidos' invoices_latest: 'Facturas recientes' invoices_due: 'Facturas vencidas' diff --git a/src/Siwapp/DashboardBundle/Resources/views/Dashboard/index.html.twig b/src/Siwapp/DashboardBundle/Resources/views/Dashboard/index.html.twig index 2c88be66..3fc1e8ed 100644 --- a/src/Siwapp/DashboardBundle/Resources/views/Dashboard/index.html.twig +++ b/src/Siwapp/DashboardBundle/Resources/views/Dashboard/index.html.twig @@ -6,7 +6,6 @@ {% stylesheets 'bundles/siwappdashboard/css/dashboard.css' filter='cssrewrite' - filter='?yui_css' %} {% endstylesheets %} @@ -16,7 +15,6 @@ {{ parent() }} {% javascripts 'bundles/siwappinvoice/js/invoice-payments.js' - filter='?yui_js' %} {% endjavascripts %} diff --git a/src/Siwapp/EstimateBundle/Controller/EstimateController.php b/src/Siwapp/EstimateBundle/Controller/EstimateController.php index 7d64c0bb..d3bc65dd 100644 --- a/src/Siwapp/EstimateBundle/Controller/EstimateController.php +++ b/src/Siwapp/EstimateBundle/Controller/EstimateController.php @@ -2,13 +2,14 @@ namespace Siwapp\EstimateBundle\Controller; -use Symfony\Bundle\FrameworkBundle\Controller\Controller; +use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; +use Siwapp\CoreBundle\Controller\AbstractInvoiceController; use Siwapp\CoreBundle\Entity\Item; use Siwapp\EstimateBundle\Entity\Estimate; use Siwapp\EstimateBundle\Form\EstimateType; @@ -16,7 +17,7 @@ /** * @Route("/estimate") */ -class EstimateController extends Controller +class EstimateController extends AbstractInvoiceController { /** * @Route("", name="estimate_index") @@ -35,7 +36,7 @@ public function indexAction(Request $request) 'method' => 'GET', ]); $form->handleRequest($request); - if ($form->isSubmitted()) { + if ($form->isSubmitted() && $form->isValid()) { $pagination = $repo->paginatedSearch($form->getData(), $limit, $request->query->getInt('page', 1)); } else { $pagination = $repo->paginatedSearch([], $limit, $request->query->getInt('page', 1)); @@ -45,7 +46,7 @@ public function indexAction(Request $request) 'action' => $this->generateUrl('estimate_index'), ]); $listForm->handleRequest($request); - if ($listForm->isSubmitted()) { + if ($listForm->isSubmitted() && $listForm->isValid()) { $data = $listForm->getData(); if (empty($data['estimates'])) { $this->addTranslatedMessage('flash.nothing_selected', 'warning'); @@ -151,7 +152,7 @@ public function addAction(Request $request) ]); $form->handleRequest($request); - if ($form->isSubmitted()) { + if ($form->isSubmitted() && $form->isValid()) { $em->persist($estimate); $em->flush(); $this->addTranslatedMessage('flash.added'); @@ -182,7 +183,7 @@ public function editAction(Request $request, $id) ]); $form->handleRequest($request); - if ($form->isSubmitted()) { + if ($form->isSubmitted() && $form->isValid()) { if ($request->request->has('save_draft')) { $entity->setStatus(Estimate::DRAFT); } elseif ($request->request->has('save_close')) { @@ -267,6 +268,21 @@ public function deleteAction($id) return $this->redirect($this->generateUrl('estimate_index')); } + /** + * @Route("/form-totals", name="estimate_form_totals") + */ + public function getInvoiceFormTotals(Request $request) + { + $post = $request->request->get('estimate'); + if (!$post) { + throw new NotFoundHttpException; + } + + $response = $this->getInvoiceTotalsFromPost($post, new Estimate, $request->getLocale()); + + return new JsonResponse($response); + } + protected function addTranslatedMessage($message, $status = 'success') { $translator = $this->get('translator'); @@ -356,8 +372,9 @@ protected function getEmailMessage($estimate) )); $pdf = $this->getPdf($html); $attachment = new \Swift_Attachment($pdf, $estimate->getId().'.pdf', 'application/pdf'); + $subject = '[' . $this->get('translator')->trans('estimate.estimate', [], 'SiwappEstimateBundle') . ': ' . $estimate->label() . ']'; $message = \Swift_Message::newInstance() - ->setSubject($estimate->label()) + ->setSubject($subject) ->setFrom($configRepo->get('company_email'), $configRepo->get('company_name')) ->setTo($estimate->getCustomerEmail(), $estimate->getCustomerName()) ->setBody($html, 'text/html') @@ -365,20 +382,4 @@ protected function getEmailMessage($estimate) return $message; } - - protected function getPdf($html) - { - $config = $this->getDoctrine()->getRepository('SiwappConfigBundle:Property'); - $pdfSize = $config->get('pdf_size'); - $pdfOrientation = $config->get('pdf_orientation'); - $config = []; - if ($pdfSize) { - $config['page-size'] = $pdfSize; - } - if ($pdfOrientation) { - $config['orientation'] = $pdfOrientation; - } - - return $this->get('knp_snappy.pdf')->getOutputFromHtml($html, $config); - } } diff --git a/src/Siwapp/EstimateBundle/Form/EstimateType.php b/src/Siwapp/EstimateBundle/Form/EstimateType.php index c233c8f2..2063d739 100644 --- a/src/Siwapp/EstimateBundle/Form/EstimateType.php +++ b/src/Siwapp/EstimateBundle/Form/EstimateType.php @@ -21,6 +21,10 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'label' => 'form.issue_date', 'translation_domain' => 'SiwappEstimateBundle', ]) + ->add('sent_by_email', null, [ + 'label' => 'form.sent_by_email', + 'translation_domain' => 'SiwappInvoiceBundle', + ]) ; if (!$builder->getData()->isDraft()) { diff --git a/src/Siwapp/EstimateBundle/Resources/translations/SiwappEstimateBundle.en.yml b/src/Siwapp/EstimateBundle/Resources/translations/SiwappEstimateBundle.en.yml index ca51f441..50a43802 100644 --- a/src/Siwapp/EstimateBundle/Resources/translations/SiwappEstimateBundle.en.yml +++ b/src/Siwapp/EstimateBundle/Resources/translations/SiwappEstimateBundle.en.yml @@ -5,6 +5,7 @@ estimate: rejected: 'Rejected' not_sent_by_email: 'Not Sent by Email' sent_by_email: 'Sent by Email' + estimate: 'Estimate' menu: estimate_index: 'Estimates' @@ -34,7 +35,7 @@ search: list: bulk_delete: 'Remove selected' bulk_print: 'Print selected' - bulk_pdf: 'Download as PDF' + bulk_pdf: 'Download selected as PDF' bulk_email: 'Email selected' series: 'Series' customer_name: 'Customer' @@ -42,7 +43,6 @@ list: status: 'Status' gross_amount: 'Total' no_results: 'No estimates found.' - bulk_delete: 'Remove selected' show: print: 'Print' @@ -57,6 +57,7 @@ show: form: issue_date: 'Issue date' + sent_by_email: 'Mark as sent by email' status: 'Status' submit: 'Save' submit_draft: 'Save as draft' diff --git a/src/Siwapp/EstimateBundle/Resources/translations/SiwappEstimateBundle.es.yml b/src/Siwapp/EstimateBundle/Resources/translations/SiwappEstimateBundle.es.yml index 3afbf224..19840503 100644 --- a/src/Siwapp/EstimateBundle/Resources/translations/SiwappEstimateBundle.es.yml +++ b/src/Siwapp/EstimateBundle/Resources/translations/SiwappEstimateBundle.es.yml @@ -5,6 +5,7 @@ estimate: rejected: 'Rechazado' not_sent_by_email: 'No enviado por correo electrónico' sent_by_email: 'Enviado por correo electrónico' + estimate: 'Presupuesto' menu: estimate_index: 'Presupuestos' @@ -42,7 +43,6 @@ list: status: 'Estado' gross_amount: 'Total' no_results: 'No se han encontrado presupuestos.' - bulk_delete: 'Borrar seleccionados' show: print: 'Imprimir' diff --git a/src/Siwapp/EstimateBundle/Resources/views/Estimate/edit.html.twig b/src/Siwapp/EstimateBundle/Resources/views/Estimate/edit.html.twig index 5e91200b..d401b0a2 100644 --- a/src/Siwapp/EstimateBundle/Resources/views/Estimate/edit.html.twig +++ b/src/Siwapp/EstimateBundle/Resources/views/Estimate/edit.html.twig @@ -29,7 +29,7 @@ {% block invoice_label %} -

Estimate {{ entity.label() }}

+

{% trans %}estimate.estimate{% endtrans %} {{ entity.label() }}