src/Service/Xero/InvoiceService.php line 33

Open in your IDE?
  1. <?php
  2. // src/Service/UserService.php
  3. namespace App\Service\Xero;
  4. use App\Entity\OrderDetails;
  5. use App\Authenticator\XeroAuthenticator;
  6. use App\Entity\Donation;
  7. use App\Entity\FilmProject;
  8. use App\Entity\User;
  9. use App\Repository\XeroTrackingCategoryRepository;
  10. use App\Repository\XeroTrackingOptionRepository;
  11. use App\Serializer\XeroObjectConverter;
  12. use App\Service\Xero\XeroService;
  13. use App\String\Constant;
  14. use DateTime;
  15. use Exception;
  16. use Stripe\Order;
  17. use App\Utility\UidGenerator;
  18. use XeroAPI\XeroPHP\AccountingObjectSerializer;
  19. use XeroAPI\XeroPHP\ApiException;
  20. use XeroAPI\XeroPHP\Models\Accounting\Invoice;
  21. use XeroAPI\XeroPHP\Models\Accounting\Payments;
  22. final class InvoiceService extends XeroService
  23. {
  24.     private const SUMMARIZE_ERRORS true;
  25.     private const UNIT_DP 4;
  26.     private const INVOICE_STATUS_PAID "PAID";
  27.     private $xeroObjectConverter;
  28.     public function __construct(XeroAuthenticator $xeroAuthenticatorXeroObjectConverter $xeroObjectConverter)
  29.     {        
  30.         parent::__construct($xeroAuthenticator);
  31.         $this->xeroObjectConverter $xeroObjectConverter;
  32.     }
  33.     /**
  34.      * Create Xero Invoice
  35.      *
  36.      * @param OrderDetails $orderDetails
  37.      * @param [type] $xeroContactId
  38.      * @return OrderDetails
  39.      */
  40.     public function createFilmInvoice(FilmProject $filmProject$product$xeroContactIdOrderDetails $order, ?User $user null): OrderDetails
  41.     {
  42.         $contact $this->xeroObjectConverter->createContactObj($xeroContactId);
  43.         $lineItems $this->xeroObjectConverter->CreateLineItemObjFromEntity($filmProject$product);
  44.         if ($user->isAdmin()) {
  45.             $lineItems $this->xeroObjectConverter->createFreeLineItemObjFromProject($filmProject$product);
  46.         }
  47.         $invoices $this->xeroObjectConverter->createInvoiceObj($contact$lineItems$orderConstant::XERO_INVOICE_THEME_APPLICATION);
  48.   
  49.         $apiResponse $this->xeroAccountingManager->createInvoices($this->xeroTenantId$invoices$this::SUMMARIZE_ERRORS$this::UNIT_DP);
  50.         if ($apiResponse[0]['has_validation_errors']) {
  51.             $this->throwExceptionMessage($apiResponse[0]['validation_errors'][0]['message']);
  52.         }
  53.         
  54.         $orderDetails $filmProject->getOrderDetails();
  55.         $orderDetails
  56.             ->setXeroId($apiResponse[0]['invoice_id'])
  57.             ->setInvoiceNumber($apiResponse[0]['invoice_number'])
  58.         ;
  59.         return $orderDetails;
  60.     }
  61.     /**
  62.      * Create invoice based on percentage splits donation
  63.      *
  64.      * @param OrderDetails $orderDetails
  65.      * @param [type] $xeroContactId
  66.      * @return OrderDetails
  67.      */
  68.     public function createDonationInvoice(Donation $donation$xeroContactId): OrderDetails
  69.     {
  70.         $contact $this->xeroObjectConverter->createContactObj($xeroContactId);
  71.         $lineItems $this->xeroObjectConverter->CreateLineItemObjFromEntity($donation);
  72.         $invoices $this->xeroObjectConverter->createInvoiceObj($contact$lineItems$donation->getOrderDetails(), Constant::XERO_INVOICE_THEME_DONATION);
  73.         try {
  74.             $apiResponse $this->xeroAccountingManager->createInvoices($this->xeroTenantId$invoicesself::SUMMARIZE_ERRORSself::UNIT_DPUidGenerator::guidv4());
  75.         } catch(Exception $e) {
  76.             $this->throwExceptionMessage('Exception when creating invoices: '$e->getMessage());
  77.         } catch(ApiException $e) {
  78.             $this->throwXeroException($e);
  79.         } 
  80.         if ($apiResponse[0]['has_validation_errors']) {
  81.             $this->throwExceptionMessage($apiResponse[0]['validation_errors'][0]['message']);
  82.         }
  83.         
  84.         $orderDetails $donation->getOrderDetails();
  85.         $orderDetails
  86.             ->setXeroId($apiResponse[0]['invoice_id'])
  87.             ->setInvoiceNumber($apiResponse[0]['invoice_number'])
  88.         ;
  89.         // if ($apiResponse[0]['invoice_id']) {
  90.         //     $arr_payments = $this->xeroObjectConverter->createDonationPaymentObj($donation);
  91.         //     if ($arr_payments) {
  92.         //         $payments = (new Payments())->setPayments($arr_payments);
  93.         //         $apiResponse = $this->xeroAccountingManager->createPayments($this->xeroTenantId, $payments, $this::SUMMARIZE_ERRORS);
  94.         //     }
  95.         // }
  96.         return $orderDetails;
  97.     }
  98.     /**
  99.      * Get invoice pdf
  100.      *
  101.      * @param [type] $invoiceId
  102.      * @return string
  103.      */
  104.     public function getInvoiceAsPdf($invoiceId): string
  105.     {
  106.         $result $this->xeroAccountingManager->getInvoiceAsPdf($this->xeroTenantId$invoiceId'application/pdf');                         
  107.         return $result->getPathName();
  108.     }
  109.     /**
  110.      * Get invoices by contact id
  111.      *
  112.      * @param [type] $contactId
  113.      * @return array
  114.      */
  115.     public function getInvoicesByContactId($contactId)
  116.     {
  117.         $ifModifiedSince = new \DateTime("2022-06-01T12:00:00.202-08:00");
  118.         $where 'Type=="' Invoice::TYPE_ACCREC '"';
  119.         $order 'InvoiceNumber ASC';
  120.         $iDs null;
  121.         $invoiceNumbers null;
  122.         $contactIDs = [$contactId]; // website donation, Jane Rybarz, Website Donation - credit cards
  123.         $statuses = [Invoice::STATUS_PAID]; // PAID UNTIL PAGE 65
  124.         $page 15;
  125.         $includeArchived true;
  126.         $createdByMyApp false;
  127.         $unitdp 2;
  128.         $summaryOnly false;
  129.         try {
  130.             $invoices $this->xeroAccountingManager->getInvoices($this->xeroTenantId$ifModifiedSince$where$order$iDs$invoiceNumbers$contactIDs$statuses$page$includeArchived$createdByMyApp$unitdp$summaryOnly);
  131.         }
  132.         catch (Exception $e) {
  133.             $this->throwExceptionMessage($e->getMessage());
  134.         }
  135.         $unpermittedItemCodes = [4112];
  136.         $result = [];
  137.         foreach ($invoices as $invoice) {
  138.             $lineItems $invoice['line_items'];
  139.             array_push($result$invoice);
  140.         }
  141.         return $result;
  142.     
  143.     }
  144.     /**
  145.      * Get invoices by contact id
  146.      *
  147.      * @param [type] $contactId
  148.      * @return array
  149.      */
  150.     public function getDonationInvoicesWithPage($pageNumber)
  151.     {
  152.         $ifModifiedSince = new \DateTime("2022-06-01T12:00:00.202-08:00");
  153.         $where 'Type=="' Invoice::TYPE_ACCREC '"';
  154.         $order 'InvoiceNumber ASC';
  155.         $iDs null;
  156.         $invoiceNumbers null;
  157.         $contactIDs = ['4e5843b1-0847-4073-9b87-b54d9826e97c']; // website donation, Jane Rybarz, Website Donation - credit cards
  158.         $statuses = [Invoice::STATUS_PAID]; // PAID UNTIL PAGE 65
  159.         $page $pageNumber;
  160.         $includeArchived true;
  161.         $createdByMyApp false;
  162.         $unitdp 2;
  163.         $summaryOnly false;
  164.         try {
  165.             $invoices $this->xeroAccountingManager->getInvoices($this->xeroTenantId$ifModifiedSince$where$order$iDs$invoiceNumbers$contactIDs$statuses$page$includeArchived$createdByMyApp$unitdp$summaryOnly);
  166.         }
  167.         catch (Exception $e) {
  168.             $this->throwExceptionMessage($e->getMessage());
  169.         }
  170.         
  171.         if ($invoices) {
  172.             return $invoices;
  173.         }
  174.     
  175.     }
  176.     /**
  177.      * get invoices by start date
  178.      *
  179.      * @param DateTime $ifModifiedSince
  180.      * @return array
  181.      */
  182.     public function getInvoicesByStartDate(DateTime $ifModifiedSince): array
  183.     {
  184.         $where 'Type=="' Invoice::TYPE_ACCREC '"';
  185.         $order 'InvoiceNumber ASC';
  186.         $iDs null;
  187.         $invoiceNumbers null;
  188.         $contactIDs null;
  189.         $statuses = [Invoice::STATUS_PAID]; // PAID UNTIL PAGE 65
  190.         $page 1;
  191.         $includeArchived true;
  192.         $createdByMyApp false;
  193.         $unitdp 2;
  194.         $summaryOnly false;
  195.         try {
  196.             $invoices $this->xeroAccountingManager->getInvoices($this->xeroTenantId$ifModifiedSince$where$order$iDs$invoiceNumbers$contactIDs$statuses$page$includeArchived$createdByMyApp$unitdp$summaryOnly);
  197.         }
  198.         catch (Exception $e) {
  199.             $this->throwExceptionMessage($e->getMessage());
  200.         }
  201.         $permittedItemCodes = [4112];
  202.         $result = [];
  203.         $result['4112'] = [];
  204.         foreach ($invoices as $invoice) {
  205.             $projectName $invoice['name'];
  206.             $fromContact $invoice['contact_id'];
  207.             $invoiceNumber $invoice['invoice_number'];
  208.             $invoiceId $invoice['invoice_id'];
  209.             $lineItems $invoice['line_items'];
  210.             foreach ($lineItems as $lineItem) {
  211.                 $subTotal $lineItem['total'];
  212.                 $itemCode $lineItem['item_code'];
  213.                 $lineItemTracking $lineItem['trakcing'];
  214.                 
  215.                 if (in_array($itemCode$permittedItemCodes)) {
  216.                     array_push($result['4112'], $invoice);
  217.                     continue;
  218.                 }
  219.             }
  220.         }
  221.         return $result;
  222.     }
  223.     /**
  224.      * Get Invoice
  225.      */
  226.     public function getInvoice($invoiceId): mixed {
  227.         $unitdp 2;
  228.         $apiResponse $this->xeroAccountingManager->getInvoice($this->xeroTenantId$invoiceId$unitdp);
  229.         return $apiResponse;
  230.     }
  231.     /**
  232.      * Update Invoice pdf
  233.      *
  234.      * @param [type] $invoiceId
  235.      * @return string
  236.      */
  237.     public function updateInvoice(Donation $donation$invoiceId$amount$oldProjectId null): void
  238.     {
  239.         $unitdp 2;
  240.         $lineItems = [];
  241.         $apiResponse $this->xeroAccountingManager->getInvoice($this->xeroTenantId$invoiceId$unitdp);
  242.         if (!isset($apiResponse[0])) return;
  243.         if ($apiResponse[0]['status'] == self::INVOICE_STATUS_PAID) {
  244.             $lineItems $this->xeroObjectConverter->createLineItemsFromApi($apiResponse[0]['line_items'], $donation);
  245.         } else {
  246.             $lineItems $this->xeroObjectConverter->CreateLineItemObjFromEntity($donation); 
  247.         }
  248.         $isPaid false;
  249.         if (isset($apiResponse[0]['status']) && $apiResponse[0]['status'] == 'PAID'$isPaid true;
  250.         
  251.         $invoices $this->xeroObjectConverter->createUpdateInvoiceObj($donation$lineItems$isPaid);
  252.         try {
  253.             $result $this->xeroAccountingManager->updateInvoice($this->xeroTenantId$invoiceId$invoices$unitdp);                         
  254.         } catch(ApiException $e) {
  255.             $this->throwXeroException($e);
  256.         } 
  257.         
  258.         return;
  259.     }
  260.     /**
  261.      * Create Xero REFUND FILM APPLICATION Invoice
  262.      *
  263.      * @param OrderDetails $orderDetails
  264.      * @param [type] $xeroContactId
  265.      * @return OrderDetails
  266.      */
  267.     public function createFilmRefundInvoice(FilmProject $filmProject$product$xeroContactIdOrderDetails $order): OrderDetails
  268.     {
  269.         $contact $this->xeroObjectConverter->createContactObj($xeroContactId);
  270.         $lineItems $this->xeroObjectConverter->createRefundLineItemObjFromEntity($filmProject$product);
  271.         $invoices $this->xeroObjectConverter->createRefundInvoiceObj($contact$lineItems$orderConstant::XERO_INVOICE_THEME_APPLICATION);
  272.   
  273.         $apiResponse $this->xeroAccountingManager->createInvoices($this->xeroTenantId$invoices$this::SUMMARIZE_ERRORS$this::UNIT_DP);
  274.         if ($apiResponse[0]['has_validation_errors']) {
  275.             $this->throwExceptionMessage($apiResponse[0]['validation_errors'][0]['message']);
  276.         }
  277.         
  278.         $orderDetails $filmProject->getOrderDetails();
  279.         $order
  280.             ->setIsRefund(true)
  281.             ->setRefundXeroId($apiResponse[0]['invoice_id'])
  282.             // ->setInvoiceNumber($apiResponse[0]['invoice_number'])
  283.         ;
  284.         return $orderDetails;
  285.     }
  286.     /**
  287.      * Create Xero REFUND Invoice
  288.      *
  289.      * @param OrderDetails $orderDetails
  290.      * @param [type] $xeroContactId
  291.      * @return OrderDetails
  292.      */
  293.     public function createDonationRefundInvoice(Donation $donation$xeroContactId): OrderDetails
  294.     {
  295.         $order $donation->getOrderDetails();
  296.         $contact $this->xeroObjectConverter->createContactObj($xeroContactId);
  297.         $lineItems $this->xeroObjectConverter->createRefundLineItemObjFromEntity($donation);
  298.         $invoices $this->xeroObjectConverter->createRefundInvoiceObj($contact$lineItems$orderConstant::XERO_INVOICE_THEME_APPLICATION);
  299.   
  300.         $apiResponse $this->xeroAccountingManager->createInvoices($this->xeroTenantId$invoices$this::SUMMARIZE_ERRORS$this::UNIT_DP);
  301.         if ($apiResponse[0]['has_validation_errors']) {
  302.             $this->throwExceptionMessage($apiResponse[0]['validation_errors'][0]['message']);
  303.         }
  304.         
  305.         $order
  306.             ->setIsRefund(true)
  307.             ->setRefundXeroId($apiResponse[0]['invoice_id'])
  308.             // ->setInvoiceNumber($apiResponse[0]['invoice_number'])
  309.         ;
  310.         return $order;
  311.     }
  312.     /**
  313.      * Create Xero Invoice
  314.      *
  315.      * @param OrderDetails $orderDetails
  316.      * @param [type] $xeroContactId
  317.      * @return OrderDetails
  318.      */
  319.     public function createPartialDonationRefundInvoice(Donation $donation$xeroContactId): OrderDetails
  320.     {
  321.         $order $donation->getOrderDetails();
  322.         $contact $this->xeroObjectConverter->createContactObj($xeroContactId);
  323.         $lineItems $this->xeroObjectConverter->createSupportDafLineItem($donation);
  324.         $invoices $this->xeroObjectConverter->createRefundInvoiceObj($contact$lineItems$orderConstant::XERO_INVOICE_THEME_APPLICATION);
  325.   
  326.         $apiResponse $this->xeroAccountingManager->createInvoices($this->xeroTenantId$invoices$this::SUMMARIZE_ERRORS$this::UNIT_DP);
  327.         if ($apiResponse[0]['has_validation_errors']) {
  328.             $this->throwExceptionMessage($apiResponse[0]['validation_errors'][0]['message']);
  329.         }
  330.         
  331.         $order
  332.             ->setIsRefund(true)
  333.             ->setRefundXeroId($apiResponse[0]['invoice_id'])
  334.             // ->setInvoiceNumber($apiResponse[0]['invoice_number'])
  335.         ;
  336.         return $order;
  337.     }
  338.     private function throwXeroException(ApiException $e) {
  339.         $error AccountingObjectSerializer::deserialize(
  340.             $e->getResponseBody(),
  341.             '\XeroAPI\XeroPHP\Models\Accounting\Error',
  342.             []
  343.         );
  344.         // var_dump($error);
  345.         $message "ApiException - " $error->getElements()[0]["validation_errors"][0]["message"];
  346.         $this->throwExceptionMessage($message);
  347.     }
  348. }