У меня довольно странная ситуация. У меня есть кусок кода, который никогда не давал проблем в прошлом. С прошлой ночи так себя ведет.
Перед обновлением модели идентификатор этой модели становится истинным. Функция ниже из контроллера и вызывается с запросом POST. Запрос проверяется, а когда модель не экспортируется, он экспортируется в другую систему. Если экспорт выполнен успешно, модель обновляется с соответствующими значениями. Идентификатор не устанавливается на любой стадии этого процесса.
Я добавил комментарии к коду, чтобы дать вам представление, где, что происходит.
public function export(Request $request, VeniceService $service, Invoice $invoice)
{
$invoice = $invoice->load([
'user', 'customer', 'extension.referenceValues.definition', 'lines'
]);
$this->enforce([
new CheckCstNum($invoice->customer),
new CheckReferences($invoice->extension),
], 432);
if ($invoice->to_export) {
DB::beginTransaction();
try {
var_dump($invoice->id); // returns the id
$data = $service->export($invoice);
var_dump($invoice->id); // returns the true
$invoice->book_date = Carbon::now();
$invoice->doc_num = $data['doc_num'];
$invoice->sys_num = $data['sys_num'];
$invoice->tsm_num = $data['tsm_num'];
$invoice->to_export = false;
$invoice->is_ticked = false;
var_dump($invoice->id); // This returns true
var_dump($invoice); // All the values are correct, except the id, this is set to true
$invoice->save(); // With the id as true, this throws an exception. Duplicate entries for PRIMARY key id, '1'
DB::commit();
$service->attachPdf($invoice, Printer::print($invoice)->output());
} catch (VeniceException $e) {
DB::rollBack();
return $e->render($request);
} catch (\Exception $e) {
DB::rollBack();
return response()->json($e->getMessage(), 500);
}
}
return new InvoiceResource($invoice->refresh()); // returns the invoice, but the id is still true
}
$this->service->export()
разрешает эту функцию. До того, как это произойдет, идентификатор все еще является исходным идентификатором модели.
public function export($model)
{
return $this->call($model, __FUNCTION__);
}
protected function call($model, $function)
{
$class = $this->getClassName($model);
$method = "{$function}{$class}";
return $this->$method($model);
}
public function exportInvoice($invoice)
{
var_dump($invoice->id); // Returns the id
$veniceInvoice = (new VeniceInvoiceResource($invoice))->toArray(request());
var_dump($invoice->id); // Returns true...
return $this->request('POST', 'venice/invoices/' . $this->bookSales, [
RequestOptions::JSON => $veniceInvoice
]);
}
$veniceInvoice = (new VeniceInvoice($invoice))->toArray(request());
После этой строки идентификатор устанавливается как true. Это действительно не имеет никакого смысла, поскольку это всегда работало, и модель никак не манипулируется.
Последний бит кода. Но я не думаю, что это имеет какое-либо отношение к проблеме.
VeniceInvoiceResource.php
public function toArray($request)
{
$pdf = Printer::print($this->resource)->output();
$lines = $this->customer->standard_base == 10 ? VeniceInvoiceLineIC::collection($this->lines) : VeniceInvoiceLine::collection($this->lines);
$refs = $this->extension->referenceValues->map(function ($item) {
return [
'index' => 0,
'quantity' => 0,
'unit_price' => 0,
'description' => $item->definition->name . ' ' . $item->value,
'vat_code' => 0,
'ic_code' => 0,
];
})->toArray();
$details = array_merge($refs, $lines->toArray($request));
return [
'cst_num' => $this->customer->cst_num,
'book' => ($this->book === 'VKPCN') ? $this->book : config('venice.config.sales.book'),
'amount' => $this->total,
'vat_amount' => $this->total,
'exp_date' => carbon(config('venice.config.sales.date'))->addDays($this->customer->exp_term)->format('d/m/Y'),
'doc_date' => carbon(config('venice.config.sales.date'))->format('d/m/Y'),
'vat_system' => $this->customer->vat_system,
'bf_code' => $this->customer->bf_code,
'doc_type' => ($this->doc_type === 'slsCreditnote') ? 1 : 0,
'pdf' => base64_encode($pdf),
'pdfName' => $this->date->format('Ym') . '-' . $this->id . '.pdf',
'remark' => 'Clockwork ' . $this->date->format('Y F') . ' ' . $this->user->name,
'details' => $details,
];
}
На данный момент я добавил временное исправление, чтобы смягчить проблему. Я создал клон счета $. позже я установил идентификатор оригинальной накладной для клонированного идентификатора накладной.
...
$invoice_copy = clone $invoice;
if ($invoice->to_export) {
DB::beginTransaction();
try {
$data = $service->export($invoice);
$invoice->book_date = Carbon::now();
$invoice->doc_num = $data['doc_num'];
$invoice->sys_num = $data['sys_num'];
$invoice->tsm_num = $data['tsm_num'];
$invoice->to_export = false;
$invoice->is_ticked = false;
$invoice->id = $invoice_copy->id;
$invoice->save();
DB::commit();
...
После большой отладки я определил, где id установлен в true. Я до сих пор не знаю почему.
В VeniceInvoiceResource $this->id
до генерации PDF идентификатор остается исходным идентификатором счета. После принтера идентификатор: true
.
Если я смотрю на конструктор для ресурсов, найденных в Illuminat\Http\Resources\JsonResource
(Resource расширяет JsonResource), я вижу, что для $this->resource
установлено значение в качестве входящего, в данном случае $invoice
.
/**
* Create a new resource instance.
*
* @param mixed $resource
* @return void
*/
public function __construct($resource)
{
$this->resource = $resource;
}
В то время как в VeniceInvoiceResource
ресурс $ this-> передается экземпляру Printer. В ресурсе $this
также есть значения счета-фактуры.
/**
* Load items to print.
*
* @param $items
* @return $this
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
public function print($items, $toPrint = null)
{
$items = is_array($items) || $items instanceof Collection ? $items : func_get_args();
foreach ($items as $item) {
if ($item instanceof Printable) {
foreach ($item->printData($toPrint) as $key => $data) {
switch($key) {
case 'merge':
$this->mergeOutput($data);
break;
case 'mergeFile':
$this->mergeFile($data);
break;
default:
$this->toPrint[] = $this->view->make($key, $data)->render();
}
}
} elseif ($item instanceof Renderable) {
$this->toPrint[] = $item->render();
} elseif (is_string($item)) {
$this->toPrint[] = $item;
} else {
throw new \InvalidArgumentException('Invalid argument');
}
}
return $this;
}
В методе печати в этом случае используется $this->toPrint[] = $this->view->make($key, $data)->render();
. Метод вывода выглядит следующим образом.
/**
* Get the output as string.
*
* @return string
* @throws \iio\libmergepdf\Exception
*/
public function output()
{
return $this->generate();
}
/**
* Generate and merge.
*
* @return string
* @throws \iio\libmergepdf\Exception
*/
protected function generate()
{
$data = !empty($this->toPrint) ? $this->toPrint : [''];
$result = $this->pdf->getOutputFromHtml($data);
if (!empty($this->toMerge)) {
$this->merger->addRaw($result);
foreach ($this->toMerge as $item) {
$this->merger->addRaw($item);
}
$result = $this->merger->merge();
}
$this->toPrint = null;
$this->toMerge = null;
return $result;
}
В сервисе печати ничем не манипулируют, он просто печатает коллекции и элементы в формате PDF.
Последнее редактирование, потому что я нашел строку, которая вызвала все это. Но я не до конца понимаю, почему он устанавливает id в true.
В Printer::print
есть вызов метода в модели, printData()
у этого метода есть оператор if для решения проблемы, с которой мы столкнулись, с двумя счетами, которые нуждались в особой обработке. Времени было немного, поэтому мы решили, что для такой ситуации достаточно заявления.
if ($this->id = 4128 || $this->id === 4217) {
$vat_amount = 0;
$vat_label = '';
}
если вы присмотритесь, то увидите, что первое условие не является условием ... Проблема есть, и решение было простым. Удалите это утверждение if, так как оно нам больше не нужно. Счета 4128 & 4217
уже распечатаны и заархивированы. Их больше не нужно обрабатывать.