<?php
// src/Service/UserService.php
namespace App\Service\Xero;
use App\Entity\OrderDetails;
use App\Authenticator\XeroAuthenticator;
use App\Entity\Donation;
use App\Entity\User;
use App\Entity\FilmProject;
use App\Repository\XeroTrackingCategoryRepository;
use App\Repository\XeroTrackingOptionRepository;
use App\Serializer\XeroObjectConverter;
use App\Service\Xero\XeroService;
use App\String\Constant;
use DateTime;
use Exception;
use Stripe\Order;
use XeroAPI\XeroPHP\Models\Accounting\Invoice;
use XeroAPI\XeroPHP\Models\Accounting\Payments;
final class InvoiceService extends XeroService
{
private const SUMMARIZE_ERRORS = true;
private const UNIT_DP = 4;
private $xeroObjectConverter;
public function __construct(XeroAuthenticator $xeroAuthenticator, XeroObjectConverter $xeroObjectConverter)
{
parent::__construct($xeroAuthenticator);
$this->xeroObjectConverter = $xeroObjectConverter;
}
/**
* Create Xero Invoice
*
* @param OrderDetails $orderDetails
* @param [type] $xeroContactId
* @return OrderDetails
*/
public function createFilmInvoice(FilmProject $filmProject, $product, $xeroContactId, OrderDetails $order, ?User $user = null): OrderDetails
{
$contact = $this->xeroObjectConverter->createContactObj($xeroContactId);
$lineItems = $this->xeroObjectConverter->CreateLineItemObjFromEntity($filmProject, $product);
if ($user->isAdmin()) {
$lineItems = $this->xeroObjectConverter->createFreeLineItemObjFromProject($filmProject, $product);
}
$invoices = $this->xeroObjectConverter->createInvoiceObj($contact, $lineItems, $order, Constant::XERO_INVOICE_THEME_APPLICATION);
$apiResponse = $this->xeroAccountingManager->createInvoices($this->xeroTenantId, $invoices, $this::SUMMARIZE_ERRORS, $this::UNIT_DP);
if ($apiResponse[0]['has_validation_errors']) {
$this->throwExceptionMessage($apiResponse[0]['validation_errors'][0]['message']);
}
$orderDetails = $filmProject->getOrderDetails();
$orderDetails
->setXeroId($apiResponse[0]['invoice_id'])
->setInvoiceNumber($apiResponse[0]['invoice_number'])
;
return $orderDetails;
}
/**
* Create invoice based on percentage splits donation
*
* @param OrderDetails $orderDetails
* @param [type] $xeroContactId
* @return OrderDetails
*/
public function createDonationInvoice(Donation $donation, $xeroContactId): OrderDetails
{
$contact = $this->xeroObjectConverter->createContactObj($xeroContactId);
$lineItems = $this->xeroObjectConverter->CreateLineItemObjFromEntity($donation);
$invoices = $this->xeroObjectConverter->createInvoiceObj($contact, $lineItems, $donation->getOrderDetails(), Constant::XERO_INVOICE_THEME_DONATION);
$apiResponse = $this->xeroAccountingManager->createInvoices($this->xeroTenantId, $invoices, $this::SUMMARIZE_ERRORS, $this::UNIT_DP);
if ($apiResponse[0]['has_validation_errors']) {
$this->throwExceptionMessage($apiResponse[0]['validation_errors'][0]['message']);
}
$orderDetails = $donation->getOrderDetails();
$orderDetails
->setXeroId($apiResponse[0]['invoice_id'])
->setInvoiceNumber($apiResponse[0]['invoice_number'])
;
// if ($apiResponse[0]['invoice_id']) {
// $arr_payments = $this->xeroObjectConverter->createDonationPaymentObj($donation);
// if ($arr_payments) {
// $payments = (new Payments())->setPayments($arr_payments);
// $apiResponse = $this->xeroAccountingManager->createPayments($this->xeroTenantId, $payments, $this::SUMMARIZE_ERRORS);
// }
// }
return $orderDetails;
}
/**
* Get invoice pdf
*
* @param [type] $invoiceId
* @return string
*/
public function getInvoiceAsPdf($invoiceId): string
{
$result = $this->xeroAccountingManager->getInvoiceAsPdf($this->xeroTenantId, $invoiceId, 'application/pdf');
return $result->getPathName();
}
/**
* Get invoices by contact id
*
* @param [type] $contactId
* @return array
*/
public function getInvoicesByContactId($contactId)
{
$ifModifiedSince = new \DateTime("2022-06-01T12:00:00.202-08:00");
$where = 'Type=="' . Invoice::TYPE_ACCREC . '"';
$order = 'InvoiceNumber ASC';
$iDs = null;
$invoiceNumbers = null;
$contactIDs = [$contactId]; // website donation, Jane Rybarz, Website Donation - credit cards
$statuses = [Invoice::STATUS_PAID]; // PAID UNTIL PAGE 65
$page = 15;
$includeArchived = true;
$createdByMyApp = false;
$unitdp = 2;
$summaryOnly = false;
try {
$invoices = $this->xeroAccountingManager->getInvoices($this->xeroTenantId, $ifModifiedSince, $where, $order, $iDs, $invoiceNumbers, $contactIDs, $statuses, $page, $includeArchived, $createdByMyApp, $unitdp, $summaryOnly);
}
catch (Exception $e) {
$this->throwExceptionMessage($e->getMessage());
}
$unpermittedItemCodes = [4112];
$result = [];
foreach ($invoices as $invoice) {
$lineItems = $invoice['line_items'];
array_push($result, $invoice);
}
return $result;
}
/**
* Get invoices by contact id
*
* @param [type] $contactId
* @return array
*/
public function getDonationInvoicesWithPage($pageNumber)
{
$ifModifiedSince = new \DateTime("2022-06-01T12:00:00.202-08:00");
$where = 'Type=="' . Invoice::TYPE_ACCREC . '"';
$order = 'InvoiceNumber ASC';
$iDs = null;
$invoiceNumbers = null;
$contactIDs = ['4e5843b1-0847-4073-9b87-b54d9826e97c']; // website donation, Jane Rybarz, Website Donation - credit cards
$statuses = [Invoice::STATUS_PAID]; // PAID UNTIL PAGE 65
$page = $pageNumber;
$includeArchived = true;
$createdByMyApp = false;
$unitdp = 2;
$summaryOnly = false;
try {
$invoices = $this->xeroAccountingManager->getInvoices($this->xeroTenantId, $ifModifiedSince, $where, $order, $iDs, $invoiceNumbers, $contactIDs, $statuses, $page, $includeArchived, $createdByMyApp, $unitdp, $summaryOnly);
}
catch (Exception $e) {
$this->throwExceptionMessage($e->getMessage());
}
if ($invoices) {
return $invoices;
}
}
/**
* get invoices by start date
*
* @param DateTime $ifModifiedSince
* @return array
*/
public function getInvoicesByStartDate(DateTime $ifModifiedSince): array
{
$where = 'Type=="' . Invoice::TYPE_ACCREC . '"';
$order = 'InvoiceNumber ASC';
$iDs = null;
$invoiceNumbers = null;
$contactIDs = null;
$statuses = [Invoice::STATUS_PAID]; // PAID UNTIL PAGE 65
$page = 1;
$includeArchived = true;
$createdByMyApp = false;
$unitdp = 2;
$summaryOnly = false;
try {
$invoices = $this->xeroAccountingManager->getInvoices($this->xeroTenantId, $ifModifiedSince, $where, $order, $iDs, $invoiceNumbers, $contactIDs, $statuses, $page, $includeArchived, $createdByMyApp, $unitdp, $summaryOnly);
}
catch (Exception $e) {
$this->throwExceptionMessage($e->getMessage());
}
$permittedItemCodes = [4112];
$result = [];
$result['4112'] = [];
foreach ($invoices as $invoice) {
$projectName = $invoice['name'];
$fromContact = $invoice['contact_id'];
$invoiceNumber = $invoice['invoice_number'];
$invoiceId = $invoice['invoice_id'];
$lineItems = $invoice['line_items'];
foreach ($lineItems as $lineItem) {
$subTotal = $lineItem['total'];
$itemCode = $lineItem['item_code'];
$lineItemTracking = $lineItem['trakcing'];
if (in_array($itemCode, $permittedItemCodes)) {
array_push($result['4112'], $invoice);
continue;
}
}
}
return $result;
}
/**
* Update Invoice pdf
*
* @param [type] $invoiceId
* @return string
*/
public function updateInvoice(Donation $donation, $invoiceId, $amount): void
{
$unitdp = 2;
$lineItems = $this->xeroObjectConverter->CreateLineItemObjFromEntity($donation);
$invoices = $this->xeroObjectConverter->createUpdateInvoiceObj($donation, $lineItems);
$result = $this->xeroAccountingManager->updateInvoice($this->xeroTenantId, $invoiceId, $invoices, $unitdp);
return;
}
/**
* Create Xero REFUND FILM APPLICATION Invoice
*
* @param OrderDetails $orderDetails
* @param [type] $xeroContactId
* @return OrderDetails
*/
public function createFilmRefundInvoice(FilmProject $filmProject, $product, $xeroContactId, OrderDetails $order): OrderDetails
{
$contact = $this->xeroObjectConverter->createContactObj($xeroContactId);
$lineItems = $this->xeroObjectConverter->createRefundLineItemObjFromEntity($filmProject, $product);
$invoices = $this->xeroObjectConverter->createRefundInvoiceObj($contact, $lineItems, $order, Constant::XERO_INVOICE_THEME_APPLICATION);
$apiResponse = $this->xeroAccountingManager->createInvoices($this->xeroTenantId, $invoices, $this::SUMMARIZE_ERRORS, $this::UNIT_DP);
if ($apiResponse[0]['has_validation_errors']) {
$this->throwExceptionMessage($apiResponse[0]['validation_errors'][0]['message']);
}
$orderDetails = $filmProject->getOrderDetails();
$order
->setIsRefund(true)
->setRefundXeroId($apiResponse[0]['invoice_id'])
// ->setInvoiceNumber($apiResponse[0]['invoice_number'])
;
return $orderDetails;
}
/**
* Create Xero REFUND Invoice
*
* @param OrderDetails $orderDetails
* @param [type] $xeroContactId
* @return OrderDetails
*/
public function createDonationRefundInvoice(Donation $donation, $xeroContactId): OrderDetails
{
$order = $donation->getOrderDetails();
$contact = $this->xeroObjectConverter->createContactObj($xeroContactId);
$lineItems = $this->xeroObjectConverter->createRefundLineItemObjFromEntity($donation);
$invoices = $this->xeroObjectConverter->createRefundInvoiceObj($contact, $lineItems, $order, Constant::XERO_INVOICE_THEME_APPLICATION);
$apiResponse = $this->xeroAccountingManager->createInvoices($this->xeroTenantId, $invoices, $this::SUMMARIZE_ERRORS, $this::UNIT_DP);
if ($apiResponse[0]['has_validation_errors']) {
$this->throwExceptionMessage($apiResponse[0]['validation_errors'][0]['message']);
}
$order
->setIsRefund(true)
->setRefundXeroId($apiResponse[0]['invoice_id'])
// ->setInvoiceNumber($apiResponse[0]['invoice_number'])
;
return $order;
}
/**
* Create Xero Invoice
*
* @param OrderDetails $orderDetails
* @param [type] $xeroContactId
* @return OrderDetails
*/
public function createPartialDonationRefundInvoice(Donation $donation, $xeroContactId): OrderDetails
{
$order = $donation->getOrderDetails();
$contact = $this->xeroObjectConverter->createContactObj($xeroContactId);
$lineItems = $this->xeroObjectConverter->createSupportDafLineItem($donation);
$invoices = $this->xeroObjectConverter->createRefundInvoiceObj($contact, $lineItems, $order, Constant::XERO_INVOICE_THEME_APPLICATION);
$apiResponse = $this->xeroAccountingManager->createInvoices($this->xeroTenantId, $invoices, $this::SUMMARIZE_ERRORS, $this::UNIT_DP);
if ($apiResponse[0]['has_validation_errors']) {
$this->throwExceptionMessage($apiResponse[0]['validation_errors'][0]['message']);
}
$order
->setIsRefund(true)
->setRefundXeroId($apiResponse[0]['invoice_id'])
// ->setInvoiceNumber($apiResponse[0]['invoice_number'])
;
return $order;
}
}