1

目前我可以进行更新,但不是自动更新,我觉得它很难看,我四处搜索,我认为还有另一种方法可以自动更新“参考”字段并计算每件商品的总价格(价格 * 数量)和存储到数据库中,例如

一个客户可以有很多发票,一张发票可以有很多项目

表结构:

客户端 - id(AI)、用户名、[……]

发票 - id(AI),client_id(refenrece(client.id)), [......]

invoice_item - id(AI),invoice_id(reference(invoice.id)), product, [.....]

我想要的是,每次我创建一个新发票时,我可以在页面中添加很多项目,然后当我提交时,插入新发票的操作,插入所有发票项目并更新invoice_item. invoice_id场地

目前我已经这样做了,但是用一种非常愚蠢的方式,我认为有更好的方法

$client = $this->findClientById($id);

if (null == $client) {
    return $this->handleNotFound();
}
$invoice = new Invoice();
$invoice->setClient($client);
$invoice->setStat(0);
$form = $this->createCreateForm($invoice, $id);
$form->handleRequest($request);
if ($form->isValid()) {
    $em = $this->get('doctrine')->getManager();
    $data = $form->getData();
    //Here i loop all the invoice item
    //set the related id
    //Count the total
    foreach ($data->getItem() as $key => $var) {
        $var->setInvoice($invoice);
        $var->countTotalAmount();

        if ($var->getId() != null) {
            $ids[] = $var->getId();
        }
    }
    $em->persist($form->getData());
    $em->flush();

    $this->addFlash('success', 'Invoice is created.');

    return $this->redirectToRoute('client_invoice_list', array('id' => $id));

我用谷歌搜索,我发现可以做以下事情,所以我试一试

发票实体:

/**
 * @ORM\OneToMany(targetEntity="InvoiceItem", mappedBy="invoice", cascade={"all"}, orphanRemoval=true)
 */
protected $item;

cascade是我通过搜索谷歌找到的,这也在发票实体中

/**
 * Add item
 *
 * @param \Webulous\EcocrmBundle\Entity\InvoiceItem $item
 * @return Invoice
*/
public function addItem(\Webulous\EcocrmBundle\Entity\InvoiceItem $item)
{
    $item->setInvoice($this);
        
    $this->item[] = $item;

    return $this;
}

$item->setInvoice($this);我也是从谷歌那里得到的,

我从控制器操作中删除循环并尝试,但没有运气(可能是我错过了什么),有一个错误

insert into invoice_item([.....], invoice_id) values([......], null), invoice_id cannot be null

控制器:

class InvoiceController extends Controller {
private function findClientById($id) {
    return $this->get('doctrine')->getRepository('WebulousEcocrmBundle:Client')->find($id);
}

private function findInvoiceById($id) {
    return $this->get('doctrine')->getRepository('WebulousEcocrmBundle:Invoice')->find($id);
}

private function handleNotFound() {
    $this->addFlash('danger', 'Client not found.');

    return $this->redirectToRoute('client_list');
}

private function handleInvoiceNotFound($uid) {
    $this->addFlash('danger', 'Invoice not found.');

    return $this->redirectToRoute('client_invoice_list', array('id' => $uid));
}

private function handleInvoiceCompleted($id) {
    $this->addFlash('danger', 'for invoice status is Paid cannot be edit.');

    return $this->redirectToRoute('client_invoice_list', array('id' => $id));
}

public function listAction($id, Request $request) {
    $client = $this->findClientById($id);

    if (null === $client) {
        return $this->handleNotFound();
    }

    $invoice = $this->get('knp_paginator')->paginate(
            $client->getInvoice(), $request->query->get('page', 1), 30
    );

    return $this->render('WebulousEcocrmBundle:Invoice:list.html.twig', array(
                '_action' => 'clients',
                'invoice' => $invoice,
                'client' => $client,
    ));
}

private function getProduct() {
    return $this->getDoctrine()->getRepository('Webulous\EcocrmBundle\Entity\Product')->findBy(array('deleted' => 1));
}

public function createAction($id, Request $request) {
    $client = $this->findClientById($id);

    if (null == $client) {
        return $this->handleNotFound();
    }

    $invoice = new Invoice();
    $invoice->setClient($client);
    $invoice->setStat(0);

    $form = $this->createCreateForm($invoice, $id);

    $form->handleRequest($request);

    if ($form->isValid()) {
        $em = $this->get('doctrine')->getManager();
        
        $data = $form->getData();
        foreach ($data->getItem() as $key => $var) {
            $var->setInvoice($invoice);
            $var->countTotalAmount();

            if ($var->getId() != null) {
                $ids[] = $var->getId();
            }
        }
        
        $em->persist($form->getData());
        $em->flush();

        $this->addFlash('success', 'Invoice is created.');

        return $this->redirectToRoute('client_invoice_list', array('id' => $id));
    } else {
        $errors = (string) $form->getErrors(true);
        $form->addError(new FormError($errors));
    }

    return $this->render('WebulousEcocrmBundle:Invoice:create.html.twig', array(
                '_action' => 'clients',
                'form' => $form->createView(),
                'product' => $this->getProduct(),
    ));
}

public function createFormAction($id, Request $request) {
    $client = $this->findClientById($id);

    if (null == $client) {
        return $this->handleNotFound();
    }

    $invoice = new Invoice();
    $form = $this->createCreateForm($invoice, $id);

    return $this->render('WebulousEcocrmBundle:Invoice:create.html.twig', array(
                '_action' => 'clients',
                'form' => $form->createView(),
                'product' => $this->getProduct(),
    ));
}

private function createCreateForm(Invoice $invoice, $id) {
    $form = $this->createForm(new InvoiceType, $invoice, array(
        'method' => 'POST',
        'action' => $this->generateUrl('client_invoice_create_form', array('id' => $id)),
    ));
    $form->add('stat', 'hidden', array('data' => 0));
    $form->add('submit', 'submit');

    return $form;
}

public function updateAction($uid, $id, Request $request) {
    $client = $this->findClientById($uid);

    if (null === $client) {
        return $this->handleNotFound();
    }

    $invoice = $this->findInvoiceById($id);

    if (null === $invoice || $invoice->getClient()->getId() != $uid) {
        return $this->handleInvoiceNotFound($uid);
    }

    $em = $this->get('doctrine')->getManager();

    $submittedData = $request->get('webulous_ecocrmbundle_invoice', null, true);

    $form = $this->createUpdateForm($invoice, $uid, $id);

    $form->handleRequest($request);

    if ($form->isValid()) {
        $em = $this->get('doctrine')->getManager();
        $data = $form->getData();
        foreach ($data->getItem() as $key => $var) {
            $var->setInvoice($invoice);
            $var->countTotalAmount();

            if ($var->getId() != null) {
                $ids[] = $var->getId();
            }
        }

        // Delete all the non exists row
        $items = $em->getRepository('WebulousEcocrmBundle:InvoiceItem')->findMissingItemInInvoice($ids);
        foreach ($items as $item) {
            //Delete the item
            $em->remove($item);
            $em->flush();
        }

        $em->persist($form->getData());
        $em->flush();

        $this->addFlash('success', 'Invoice is updated.');

        return $this->redirectToRoute('client_invoice_list', array('id' => $uid));
    } else {
        $errors = (string) $form->getErrors(true);
        $form->addError(new FormError($errors));
    }

    $form = $this->createUpdateForm($invoice, $uid, $id);

    return $this->render('WebulousEcocrmBundle:Invoice:update.html.twig', array(
                '_action' => 'clients',
                'invoice' => $invoice,
                'form' => $form->createView(),
                'client' => $client,
                'update' => true,
    ));
}

public function updateFormAction($uid, $id, Request $request) {
    $client = $this->findClientById($uid);

    if (null === $client) {
        return $this->handleNotFound();
    }

    $invoice = $this->findInvoiceById($id);

    if (null === $invoice || $invoice->getClient()->getId() != $uid) {
        return $this->handleInvoiceNotFound($uid);
    }

    if (Invoice::STATUS_PAID == $invoice->getStat()) {
        return $this->handleInvoiceCompleted($uid);
    }

    $form = $this->createUpdateForm($invoice, $uid, $id);

    return $this->render('WebulousEcocrmBundle:Invoice:update.html.twig', array(
                '_action' => 'clients',
                'invoice' => $invoice,
                'form' => $form->createView(),
                'client' => $client,
                'update' => true,
                'product' => $this->getProduct(),
    ));
}

private function createUpdateForm(Invoice $invoice, $uid, $id) {
    $form = $this->createForm(new InvoiceType, $invoice, array(
        'method' => 'POST',
        'action' => $this->generateUrl('client_invoice_update_form', array('uid' => $uid, 'id' => $id)),
    ));
    $form->add('stat', 'choice', array(
        'label' => 'Payment Status',
        'choices' => Invoice::getPaymentChoices()
    ));
    $form->add('submit', 'submit');

    return $form;
}
}

发票实体:

<?php

namespace Webulous\EcocrmBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Invoice
 *
 * @ORM\Table("invoice")
 * @ORM\Entity(repositoryClass="Webulous\EcocrmBundle\Entity\InvoiceRepository")
 * @ORM\HasLifecycleCallbacks()
 */
class Invoice
{
    const STATUS_UNPAID = 0;
    const STATUS_PAID = 1;
    const STATUS_CANCELLED = 2;
    
    const TAX_CHARGE_PERCENTAGE = 1;
    const TAX_CHARGE_FIXED = 2;
    
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
    
    /**
     * @ORM\ManyToOne(targetEntity="Client", inversedBy="invoice")
     * @ORM\JoinColumn(name="client_id", referencedColumnName="id", nullable=false)
     */
    protected $client;
    
    /**
     * @ORM\OneToMany(targetEntity="InvoiceItem", mappedBy="invoice", cascade={"all"}, orphanRemoval=true)
     */
    protected $item;

    /**
     * @var integer
     *
     * @ORM\Column(name="stat", type="smallint")
     */
    private $stat;

    /**
     * @var integer
     *
     * @ORM\Column(name="created", type="integer")
     */
    private $created;

    /**
     * @var integer
     *
     * @ORM\Column(name="updated", type="integer")
     */
    private $updated;

    [......]
    
    /**
     * @var integer
     * 
     */
    private $total;
    
    /**
     * Constructor
     */
    public function __construct()
    {
        $this->item = new \Doctrine\Common\Collections\ArrayCollection();
    }
    
    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }
    
    public function getInvoiceId() {
        return 'MPN#' . str_pad($this->id, 6, '0', STR_PAD_LEFT);
    }

    /**
     * Set stat
     *
     * @param integer $stat
     * @return Invoice
     */
    public function setStat($stat)
    {
        $this->stat = $stat;

        return $this;
    }

    /**
     * Get stat
     *
     * @return integer 
     */
    public function getStat()
    {
        return $this->stat;
    }

    /**
     * Set created
     *
     * @param integer $created
     * @return Invoice
     */
    public function setCreated($created)
    {
        $this->created = $created;

        return $this;
    }

    /**
     * Get created
     *
     * @return integer 
     */
    public function getCreated()
    {
        return $this->created;
    }

    /**
     * Set updated
     *
     * @param integer $updated
     * @return Invoice
     */
    public function setUpdated($updated)
    {
        $this->updated = $updated;

        return $this;
    }

    /**
     * Get updated
     *
     * @return integer 
     */
    public function getUpdated()
    {
        return $this->updated;
    }

    [......]
    
    public function getStatExplain() {
        return $this->transformStat($this->getStat());
    }

    private function transformStat($value) {
        switch ($value) {
            case self::STATUS_UNPAID:
                return 'Unpaid';
            case self::STATUS_PAID:
                return 'Paid';
            case self::STATUS_CANCELLED:
                return 'Cancelled';
            default:
                return 'Unpaid';
        }
    }

    private function reverseTransformStat($value) {
        switch ($value) {
            case 'Unpaid':
                return self::STATUS_UNPAID;
            case 'Paid':
                return self::STATUS_PAID;
            case 'Cancelled':
                return self::STATUS_CANCELLED;
            default:
                return self::STATUS_UNPAID;
        }
    }
    
    /** @ORM\PrePersist */
    public function prePresist() {
        $this->created = time();
        $this->updated = time();
    }

    /** @ORM\PreUpdate */
    public function preUpdate() {
        $this->updated = time();
    }

    /**
     * Set client
     *
     * @param \Webulous\EcocrmBundle\Entity\Client $client
     * @return Invoice
     */
    public function setClient(\Webulous\EcocrmBundle\Entity\Client $client = null)
    {
        $this->client = $client;

        return $this;
    }

    /**
     * Get client
     *
     * @return \Webulous\EcocrmBundle\Entity\Client 
     */
    public function getClient()
    {
        return $this->client;
    }
    
    /**
     * Set total
     *
     * @param integer $total
     * @return Invoice
     */
    public function setTotal($total) {
        $this->total = $total;

        return $this;
    }
    
    /**
     * Get item count
     * 
     * @return integer
     */
    public function getTotalItemCount() {
        $total = 0;
        foreach($this->getItem() as $item) {
            $total += $item->getQuantity();
        }
        return $total;
    }
    
    public static function getPaymentChoices() {
        return array(
            self::STATUS_UNPAID => 'Unpaid',
            self::STATUS_PAID => 'Paid',
            self::STATUS_CANCELLED => 'Cancelled'
        );
    }
    
    /**
     * Set item
     * 
     * @param \Webulous\EcocrmBundle\Entity\InvoiceItem $item
     * @return Invoice
     */
    public function setItem(\Webulous\EcocrmBundle\Entity\InvoiceItem $item = null)
    {
        if (null === $item) {
            return $this;
        }
        
        $this->addItem($item);
        
        return $this;
    }
    
    /**
     * Add item
     *
     * @param \Webulous\EcocrmBundle\Entity\InvoiceItem $item
     * @return Invoice
     */
    public function addItem(\Webulous\EcocrmBundle\Entity\InvoiceItem $item)
    {
        $item->setInvoice($this);
        
        $this->item[] = $item;

        return $this;
    }

    /**
     * Remove item
     *
     * @param \Webulous\EcocrmBundle\Entity\InvoiceItem $item
     */
    public function removeItem(\Webulous\EcocrmBundle\Entity\InvoiceItem $item)
    {
        $this->item->removeElement($item);
    }

    /**
     * Get item
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getItem()
    {
        return $this->item;
    }
    
    /**
     * Count all item total
     * 
     * @return float
     */
    public function getTotalPrice()
    {
        $sum = 0;
        foreach($this->getItem() as $key => $var) {
            $sum += $var->getTotalAmount();
        }
        
        return $this->roundNumber($sum);
    }
    
    /**
     * Count total tax
     * 
     * @return float
     */
    public function getTotalTax()
    {
        if($this->getTax() != NULL && in_array($this->getTaxType(), array(self::TAX_CHARGE_FIXED, self::TAX_CHARGE_PERCENTAGE))) {
            $tax = $this->getTaxExplain();
        }
        
        switch($this->getTaxType()) {
            case self::TAX_CHARGE_FIXED:
                return $tax;
            break;
            case self::TAX_CHARGE_PERCENTAGE:
                return ($this->getTotalPrice() / 100) * $tax;
            break;
            default:
                return NULL;
            break;
        }
    }
    
    /**
     * Count all item total with tax
     * 
     * @return float
     */
    public function getTotalPriceWithTax()
    {
        return $this->roundNumber($this->getTotalPrice() + $this->getTotalTax());
    }
    
    /**
     * Round the number
     * 
     * @return float
     */
    public function roundNumber($float)
    {
        return number_format((float)$float, 2, '.', '');
    }
}

InvoiceItem 实体:

<?php

namespace Webulous\EcocrmBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Webulous\EcocrmBundle\Entity\Invoice;

/**
 * InvoiceItem
 *
 * @ORM\Entity(repositoryClass="Webulous\EcocrmBundle\Entity\InvoiceItemRepository")
 * @ORM\HasLifecycleCallbacks()
 * @ORM\Table(name="invoice_item")
 */
class InvoiceItem
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var integer
     *
     * @ORM\ManyToOne(targetEntity="Webulous\EcocrmBundle\Entity\Invoice", inversedBy="item")
     * @ORM\JoinColumn(name="invoice_id", referencedColumnName="id", nullable=false)
     */
    private $invoice;

    /**
     * @var integer
     *
     * @ORM\ManyToOne(targetEntity="Webulous\EcocrmBundle\Entity\Product")
     * @ORM\JoinColumn(name="product_id", referencedColumnName="id", nullable=false)
     */
    private $product;

    /**
     * @var string
     *
     * @ORM\Column(name="description", type="text", nullable=true)
     */
    private $description;

    [......]

    /**
     * @var float
     *
     * @ORM\Column(name="price", type="float", scale=2)
     */
    private $price;

    /**
     * @var float
     *
     * @ORM\Column(name="total_amount", type="float", scale=2)
     */
    private $totalAmount;

    /**
     * @ORM\Column(name="created_at", type="datetime")
     * @Gedmo\Timestampable(on="create")
     */
    private $createdAt;

    /**
     * @ORM\Column(name="updated_at", type="datetime")
     * @Gedmo\Timestampable(on="update")
     */
    private $updatedAt;

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set invoice
     *
     * @param Invoice
     * @return InvoiceItem
     */
    public function setInvoice($invoice)
    {
        $this->invoice = $invoice;

        return $this;
    }

    /**
     * Get invoice
     *
     * @return Invoice
     */
    public function getInvoice()
    {
        return $this->invoice;
    }

    /**
     * Set product
     *
     * @param Product
     * @return InvoiceItem
     */
    public function setProduct($product)
    {
        $this->product = $product;

        return $this;
    }

    /**
     * Get product
     *
     * @return Product
     */
    public function getProduct()
    {
        return $this->product;
    }

    [......]

    /**
     * Set quantity
     *
     * @param float $quantity
     * @return InvoiceItem
     */
    public function setQuantity($quantity)
    {
        $this->quantity = $quantity;

        return $this;
    }

    /**
     * Get quantity
     *
     * @return float 
     */
    public function getQuantity()
    {
        return $this->quantity;
    }

    /**
     * Set price
     *
     * @param float $price
     * @return InvoiceItem
     */
    public function setPrice($price)
    {
        $this->price = $price;

        return $this;
    }

    /**
     * Get price
     *
     * @return float 
     */
    public function getPrice()
    {
        return $this->price;
    }

    /**
     * Set totalAmount
     *
     * @param float $totalAmount
     * @return InvoiceItem
     */
    public function setTotalAmount($totalAmount)
    {
        $this->totalAmount = $totalAmount;

        return $this;
    }

    /**
     * Get totalAmount
     *
     * @return float 
     */
    public function getTotalAmount()
    {
        return $this->totalAmount;
    }

    /**
     * Set createdAt
     *
     * @param \DateTime $createdAt
     * @return Invoice
     */
    public function setCreatedAt($createdAt)
    {
        $this->createdAt = $createdAt;

        return $this;
    }

    /**
     * Get createdAt
     *
     * @return \DateTime
     */
    public function getCreatedAt()
    {
        return $this->createdAt;
    }

    /**
     * Get updatedAt
     *
     * @return \DateTime
     */
    public function getUpdatedAt()
    {
        return $this->updatedAt;
    }

    /**
     * Set updatedAt
     *
     * @param \DateTime $updatedAt
     * @return Invoice
     */
    public function setUpdatedAt($updatedAt)
    {
        $this->updatedAt = $updatedAt;

        return $this;
    }
    
    /** @ORM\PrePersist */
    public function prePresist() {
        $this->setCreatedAt(new \DateTime);
        $this->setUpdatedAt(new \DateTime);
    }

    /** @ORM\PreUpdate */
    public function preUpdate() {
        $this->setUpdatedAt(new \DateTime);
    }
    
    public function getProductName() {
        return $this->getProduct()->getProductName();
    }
    
    public function countTotalAmount() {
        $price = $this->getPrice();
        $quantity = $this->getQuantity();
        
        $total = $this->getInvoice()->roundNumber(($price * $quantity));
        $this->setTotalAmount($total);
        return $this->getTotalAmount();
    }
}

发票表格类型:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    [......]
    ->add('item', 'collection', array(
        'type' => new InvoiceItemType(),
        'allow_add' => true,
        'allow_delete' => true,
        'options' => array(
        )
    ))
}
4

0 回答 0