unimapper / flexibee
UniMapper的Flexibee实现
v1.2.2
2016-01-12 15:48 UTC
Requires
- php: >=5.4.0
- ext-curl: *
Requires (Dev)
- bauer01/unimapper: ~1.2.0
- mockery/mockery: ~0.9.0
- nette/tester: ~1.0
- squizlabs/php_codesniffer: ~2.0
README
Flexibee API与UniMapper集成。
使用方法
$config = [ // Required "host" => "https://:5434" "company" => "name" // Optional authentization "user" => , "password" => , // Optional SSL version "ssl_version" => 3 ]; $adapter = new UniMapper\Flexibee\Adapter($config); // Create new contacts $response = $adapter->put("adresar.json", ["adresar" => ["sumCelkem" => ....]); // Read every created contact detail foreach ($response->results as $result) { $adapter->get("adresar/" . $result->id . ".json"); }
更多详情请参阅官方Flexibee网站上的文档。
实践案例
例如,可以这样定义证据objednavka-prijata。所有证据列表可以在https://demo.flexibee.eu/c/demo/evidence-list找到。
实体
<?php
namespace ProjectName\Entity;
/**
* @adapter Flexibee(objednavka-prijata)
*
* @property string $id m:primary m:map-by(id)
* @property string $code m:map-by(kod)
* @property string $status m:map-by(stavUzivK) m:enum(self::STATE_*)
* @property string $staff m:map-by(zodpOsoba)
* @property-read string $staffFullName m:map-by(zodpOsoba@showAs)
* @property Date $dateCreated m:map-by(datVyst)
* @property-read double $basePrice m:map-by(sumZklCelkem)
* @property boolean $cancel m:map-by(storno)
* @property Attachment[] $attachments m:map-by(prilohy)
* @property boolean $itemsRemoveAll m:map-by(polozkyObchDokladu@removeAll)
* @property EvidenceItem[] $evidenceItems m:map-by(polozkyObchDokladu)
* @property boolean $tagsRemoveAll m:map-by(stitky@removeAll)
* @property array $tags m:map-by(stitky) m:map-filter(mapStitky|unmapStitky)
* @property string $addressBookId m:map-by(firma)
* @property string $city m:map-by(mesto)
* @property string $email m:map-by(kontaktEmail)
* @property string $companyName m:map-by(nazFirmy)
* @property string $phone m:map-by(kontaktTel)
* @property string $postCity m:map-by(faMesto)
* @property string $postCompanyName m:map-by(faNazev)
* @property string $postStreet m:map-by(faUlice)
* @property string $postZipCode m:map-by(faPsc)
* @property string $street m:map-by(ulice)
* @property string $zipCode m:map-by(psc)
* @property string $companyId m:map-by(ic)
* @property string $vatId m:map-by(dic)
* @property boolean $mainAddress m:map-by(postovniShodna)
* @property array $externalIds m:map-by(external-ids)
* @property Offer[] $offers m:assoc(M:N) m:assoc-by(vazby|typVazbyDokl.obchod_obchod_hla|a)
* @property Invoice[] $advanceInvoices m:assoc(M:N) m:assoc-by(vazby|typVazbyDokl.obchod_zaloha_hla|b)
* @property Invoice[] $cashInvoices m:assoc(M:N) m:assoc-by(vazby|typVazbyDokl.obchod_faktura_hla|b)
* @property-read Invoice[] $invoices m:computed
* @property-read Attachment[] $attachments m:assoc(1:N) m:assoc-by(prilohy)
*/
class Order extends \UniMapper\Flexibee\Entity
{
const STATE_NEW = null,
STATE_UNSPECIFIED = "stavDoklObch.nespec",
STATE_FORAPPROVAL = "stavDoklObch.pripraveno",
STATE_APPROVED = "stavDoklObch.schvaleno",
STATE_ACCEPTED_PARTIALLY = "stavDoklObch.castVydano",
STATE_ACCEPTED = "stavDoklObch.vydano",
STATE_FINISHED_PARTIALLY = "stavDoklObch.castHotovo",
STATE_FINISHED = "stavDoklObch.hotovo",
STATE_CANCELED = "stavDoklObch.storno",
/**
* Compute invoice
*
* @return \UniMapper\EntityCollection
*/
public function computeInvoices()
{
$invoices = new \UniMapper\EntityCollection("Invoice");
foreach ($this->cashInvoices as $invoice) {
$invoices[] = $invoice;
}
foreach ($this->advanceInvoices as $invoice) {
$invoices[] = $invoice;
}
return $invoices;
}
建议
- 标识符(例如订单ID、addressBookId等)始终定义为字符串类型。Unimapper优先使用Flexibee的文本标识符,而不是数字标识符。也就是说,如果我们从Flexibee中列出订单,ID将以code:OBP0001/2015这样的风格返回。如果Flexibee在特定证据中没有保留文本标识符,则返回数字(但类型为字符串)。
- Flexibee自行计算(例如整个订单的总金额)或禁止发送到Flexibee的变量(请参阅Flexibee文档)应标记为@property-read。然后Unimapper不会将这些属性写入Flexibee,而只会从Flexibee中读取它们。
- 如果Flexibee文档中将变量定义为date,请在此处也将其类型设置为Date。不要使用DateTime,以免在按日期过滤记录时出现问题(例如,列出所有昨天的订单)。
技巧
- 使用m:enum可以监视枚举类型中的值。如果值不在Flexibee返回的数据中或发送到Flexibee中,Unimapper将抛出异常。
- 标签(此处为tags)可以通过m:map-filter(mapStitky|unmapStitky)轻松转换为数组,然后可以更轻松地处理它们。相反,在写入时,最好将数组转换为Flexibee接受的格式。
- 如果要加载外部标识符,可以使用类似于示例的$externalIds。
- 使用m:assoc(M:N)可以实现几乎任何操作。例如,在$advanceInvoices中,您将直接拥有与该订单相关联的预付款单集合,在$cashInvoices中拥有相关联的发票集合。如果您希望将它们合并到一个集合中(例如,预付款单和发票),则可以使用Unimapper的另一个技巧,即“computed”属性。
- 使用m:computed可以确保属性包含所需的确切内容。在示例中与此相关的方法是computeInvoices()。
- 如果正在修改现有订单,则建议将$itemsRemoveAll设置为TRUE,同时重新发送所有订单项($evidenceItems)。否则,每次修改都会在订单上增加项目(请参阅Flexibee文档)。
存储库
如果存储库按如下方式定义
namespace ProjectName\Repository;
class OrderRepository extends \UniMapper\Repository
{
我们可以在其中创建一些方法
- 如果当前所有者属于管理员且处于特定状态,则覆盖“所有者”。
public function assignStaffToOrder($orderId, $staff)
{
$this->query()
->update(array("staff" => $staff))
->where("id", "=", $orderId)
->where("status", "=", Order::STATE_FORAPPROVAL)
->where("staff", "=", "code:admin")
->run($this->connection);
}
- 如果您想以标签的形式记录取消订单的原因,可以使用以下方法来获取标签列表。在这方面,启用Unimapper缓存非常有用!为什么总是询问不变的数字表?每个Flexibee查询都有某种程度的性能开销。
public function getCancelReasons()
{
return \Fik\Entity\Tag::query()
->select()
->where("tagGroup", "=", "code:STORNO")
->cached(
true,
[\UniMapper\Cache\ICache::TAGS => [self::CACHE_TAG_CODEBOOK]]
)
->run($this->connection);
}
- 如果标准save()不符合要求,我们可以重载它并执行一些额外的操作。例如,如果这是一个新订单(ID === null),则设置订单的创建日期。
public function save(\UniMapper\Entity $order)
{
if ($order->id === null) {
$order->dateCreated = new \DateTime();
}
parent::save($order);
}
- 某些Flexibee工作流程需要更多努力。如果我们想将订单转换为发票,我们需要这段代码(Flexibee文档中有说明)
$structure = array(
"objednavka-prijata" => array(
"@id" => "{$orderId}",
"realizaceObj" =>
array("@type" => "faktura-vydana",
"polozkyObchDokladu" => $polozkyDokladu
)
)
);
$invoiceCreated = $this->getAdapter("Flexibee")->put(
"objednavka-prijata.json",
$structure
);
- 待批准订单的数量?没问题 :-)
public function getTotalCountForApprove()
{
$result = $this->query()
->count()
->where("status", "=", Order::STATE_FORAPPROVAL)
->where("staff", "=", "code:admin")
->run($this->connection);
return $result + $this->query()
->count()
->where("documentType", "=", Order::DOCTYPE_CARD)
->where("staff", "=", "code:admin")
->run($this->connection);
}
- 创建简单的订单
public function createTestOrder()
{
$order = new Order;
$order->documentType = Order::DOCTYPE_CONSIGNMENT;
$order->addressBookId = "code:FIRMA";
$items = [];
$item = new EvidenceItem; // entita vázaná na evidenci "objednavka-prijata-polozka"
$item->itemPriceList = "code:KRABICE_DROG"; // property objednavka-prijata-polozka.cenik
$item->itemAmount = 2.0; // property objednavka-prijata-polozka.mnozMj
$items[] = $item;
$item = new EvidenceItem;
$item->itemPriceList = "code:KRABICE_ALKOHOLU";
$item->itemAmount = 1.0;
$items[] = $item;
$order->evidenceItems = new \UniMapper\EntityCollection(
"EvidenceItem", $items
);
$this->save($order);
// v $order->id budu mít v tento moment identifikátor objednávky z Flexibee, tj. třeba "code:OBP0001/2015"
}
- 返回定义的订单PDF
public function getOrderPdf($orderId)
{
return $this->getAdapter("Flexibee")->get(
"objednavka-vydana/" . rawurlencode($orderId) . ".pdf",
"application/pdf"
);
}
- 获取包括关联的订单
public function getOrder($orderId)
{
$query = $this->query()->selectOne($orderId)->associate(["advanceInvoices", "cashInvoices"]);
$order = $query->run($this->connection);
return $order;
}
- 搜索特定订单中的文本
use UniMapper\Entity\Filter;
$invoices = $this->query()
->where(
[
"note" => [Filter::CONTAIN => $tentoTextHledame]
"documentType" => [Filter::EQUAL => ["code:PRIMA", "code:NEPRIMA"]]
]
->orderBy("id", "desc")
->limit(10)
->run($this->connection);
存储库操作
这里有很多选择。例如,这可以成为发送未付款形式的基础脚本
// vyber vsechny, co nejsou uhrazene a stornovane
$filter = [
"canceled" => ["=" => false], // = faktura-vydana.storno
"paymentStatus" => [ // = faktura-vydana.stavUhrK
"!" => [
Entity\Invoice::PAYMENT_STATUS_PAIDMANUALLY, // = faktura-vydana.stavUhr.uhrazenoRucne
Entity\Invoice::PAYMENT_STATUS_PAID // = faktura-vydana.stavUhr.uhrazeno
]
]
];
// prvni upominka dva dny po splatnosti
foreach ($this->invoiceRepository->find(
$filter + [
"documentType" => ["=" => Entity\Invoice::DOCTYPE_PROFORMA], // = faktura-vydana.typDokl = "code:ZÁLOHA"
"firstReminder" => ["=" => null], // faktura-vydana.datUp1
"dueDate" => [
"<" => new \DateTime("-1 day") // faktura-vydana.datSplat
]
]
) as $invoice) {
实体状态调整建议
有时我们可能会遇到这种情况,例如,我们加载了整个订单实体,并且在执行了一些操作后,我们只会调整订单的状态
$order = $this->orderRepository->findOne("code:OBP0001/2015);
...
nějaké ty operace
...
$order->status = "stavDoklObch.hotovo";
$this->orderRepository->save($order);
然而,上述方法是不合适的!
相反,我们建议这样处理
$order = $this->orderRepository->findOne("code:OBP0001/2015);
...
nějaké ty operace
...
$this->orderRepository->save(
new ProjectName\Entity\Order(
["id" => $order->id, "status" => "stavDoklObch.hotovo"]
)
);
这样我们可以确保Flexibee不会重新计算整个订单(因为$order->evidenceItems中还会包含其项目!)并且确实只会更改定义的订单(id)的状态。