@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add a basic invoice view for printing to Phortune

Summary: Makes a more complete PDF looking invoice form for printing in Phortune.

Test Plan: Make an invoice, click print view, print.

Reviewers: epriestley

Reviewed By: epriestley

Subscribers: Korvin

Differential Revision: https://secure.phabricator.com/D16762

+419 -40
+2
resources/celerity/map.php
··· 89 89 'rsrc/css/application/pholio/pholio-inline-comments.css' => '8e545e49', 90 90 'rsrc/css/application/pholio/pholio.css' => 'ca89d380', 91 91 'rsrc/css/application/phortune/phortune-credit-card-form.css' => '8391eb02', 92 + 'rsrc/css/application/phortune/phortune-invoice.css' => '476055e2', 92 93 'rsrc/css/application/phortune/phortune.css' => '5b99dae0', 93 94 'rsrc/css/application/phrequent/phrequent.css' => 'ffc185ad', 94 95 'rsrc/css/application/phriction/phriction-document-css.css' => '4282e4ad', ··· 840 841 'phortune-credit-card-form' => '2290aeef', 841 842 'phortune-credit-card-form-css' => '8391eb02', 842 843 'phortune-css' => '5b99dae0', 844 + 'phortune-invoice-css' => '476055e2', 843 845 'phrequent-css' => 'ffc185ad', 844 846 'phriction-document-css' => '4282e4ad', 845 847 'phui-action-panel-css' => '91c7b835',
+5
resources/sql/autopatches/20161029.phortune.invoice.1.sql
··· 1 + ALTER TABLE {$NAMESPACE}_phortune.phortune_merchant 2 + ADD invoiceEmail VARCHAR(255) COLLATE {$COLLATE_TEXT} NOT NULL; 3 + 4 + ALTER TABLE {$NAMESPACE}_phortune.phortune_merchant 5 + ADD invoiceFooter LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL;
+2
src/__phutil_library_map__.php
··· 4174 4174 'PhortuneCurrencyTestCase' => 'applications/phortune/currency/__tests__/PhortuneCurrencyTestCase.php', 4175 4175 'PhortuneDAO' => 'applications/phortune/storage/PhortuneDAO.php', 4176 4176 'PhortuneErrCode' => 'applications/phortune/constants/PhortuneErrCode.php', 4177 + 'PhortuneInvoiceView' => 'applications/phortune/view/PhortuneInvoiceView.php', 4177 4178 'PhortuneLandingController' => 'applications/phortune/controller/PhortuneLandingController.php', 4178 4179 'PhortuneMemberHasAccountEdgeType' => 'applications/phortune/edge/PhortuneMemberHasAccountEdgeType.php', 4179 4180 'PhortuneMemberHasMerchantEdgeType' => 'applications/phortune/edge/PhortuneMemberHasMerchantEdgeType.php', ··· 9422 9423 'PhortuneCurrencyTestCase' => 'PhabricatorTestCase', 9423 9424 'PhortuneDAO' => 'PhabricatorLiskDAO', 9424 9425 'PhortuneErrCode' => 'PhortuneConstants', 9426 + 'PhortuneInvoiceView' => 'AphrontTagView', 9425 9427 'PhortuneLandingController' => 'PhortuneController', 9426 9428 'PhortuneMemberHasAccountEdgeType' => 'PhabricatorEdgeType', 9427 9429 'PhortuneMemberHasMerchantEdgeType' => 'PhabricatorEdgeType',
+1
src/applications/phortune/application/PhabricatorPhortuneApplication.php
··· 61 61 'cart/(?P<id>\d+)/' => array( 62 62 '' => 'PhortuneCartViewController', 63 63 'checkout/' => 'PhortuneCartCheckoutController', 64 + '(?P<action>print)/' => 'PhortuneCartViewController', 64 65 '(?P<action>cancel|refund)/' => 'PhortuneCartCancelController', 65 66 'update/' => 'PhortuneCartUpdateController', 66 67 ),
+69 -26
src/applications/phortune/controller/PhortuneCartViewController.php
··· 3 3 final class PhortuneCartViewController 4 4 extends PhortuneCartController { 5 5 6 + private $action = null; 7 + 6 8 public function handleRequest(AphrontRequest $request) { 7 9 $viewer = $request->getViewer(); 8 10 $id = $request->getURIData('id'); 11 + $this->action = $request->getURIData('action'); 9 12 10 13 $authority = $this->loadMerchantAuthority(); 11 14 require_celerity_resource('phortune-css'); ··· 129 132 130 133 $header = id(new PHUIHeaderView()) 131 134 ->setUser($viewer) 132 - ->setHeader(pht('Order Detail')) 135 + ->setHeader($cart->getName()) 133 136 ->setHeaderIcon('fa-shopping-cart'); 134 137 135 138 if ($cart->getStatus() == PhortuneCart::STATUS_PURCHASED) { ··· 188 191 $crumbs->addTextCrumb(pht('Cart %d', $cart->getID())); 189 192 $crumbs->setBorder(true); 190 193 191 - $timeline = $this->buildTransactionTimeline( 192 - $cart, 193 - new PhortuneCartTransactionQuery()); 194 - $timeline 195 - ->setShouldTerminate(true); 194 + if (!$this->action) { 195 + $class = 'phortune-cart-page'; 196 + $timeline = $this->buildTransactionTimeline( 197 + $cart, 198 + new PhortuneCartTransactionQuery()); 199 + $timeline 200 + ->setShouldTerminate(true); 201 + 202 + $view = id(new PHUITwoColumnView()) 203 + ->setHeader($header) 204 + ->setCurtain($curtain) 205 + ->setMainColumn(array( 206 + $error_view, 207 + $details, 208 + $cart_box, 209 + $description, 210 + $charges, 211 + $timeline, 212 + )); 213 + 214 + } else { 215 + $class = 'phortune-invoice-view'; 216 + $crumbs = null; 217 + $merchant_phid = $cart->getMerchantPHID(); 218 + $buyer_phid = $cart->getAuthorPHID(); 219 + $merchant = id(new PhortuneMerchantQuery()) 220 + ->setViewer($viewer) 221 + ->withPHIDs(array($merchant_phid)) 222 + ->needProfileImage(true) 223 + ->executeOne(); 224 + $buyer = id(new PhabricatorPeopleQuery()) 225 + ->setViewer($viewer) 226 + ->withPHIDs(array($buyer_phid)) 227 + ->needProfileImage(true) 228 + ->executeOne(); 229 + // TODO: Add account "Contact" info 230 + 231 + $merchant_contact = new PHUIRemarkupView( 232 + $viewer, $merchant->getContactInfo()); 233 + $description = null; 196 234 197 - $view = id(new PHUITwoColumnView()) 198 - ->setHeader($header) 199 - ->setCurtain($curtain) 200 - ->setMainColumn(array( 201 - $error_view, 202 - $details, 203 - $cart_box, 204 - $description, 205 - $charges, 206 - $timeline, 207 - )); 235 + $view = id(new PhortuneInvoiceView()) 236 + ->setMerchantName($merchant->getName()) 237 + ->setMerchantLogo($merchant->getProfileImageURI()) 238 + ->setMerchantContact($merchant_contact) 239 + ->setMerchantFooter($merchant->getInvoiceFooter()) 240 + ->setAccountName($buyer->getRealName()) 241 + ->setStatus($error_view) 242 + ->setContent(array( 243 + $description, 244 + $details, 245 + $cart_box, 246 + $charges, 247 + )); 248 + } 208 249 209 - return $this->newPage() 250 + $page = $this->newPage() 210 251 ->setTitle(pht('Cart %d', $cart->getID())) 211 - ->setCrumbs($crumbs) 212 - ->addClass('phortune-cart-page') 252 + ->addClass($class) 213 253 ->appendChild($view); 214 254 255 + if ($crumbs) { 256 + $page->setCrumbs($crumbs); 257 + } 258 + return $page; 215 259 } 216 260 217 261 private function buildDetailsView(PhortuneCart $cart) { 218 - 219 262 $viewer = $this->getViewer(); 220 - 221 263 $view = id(new PHUIPropertyListView()) 222 264 ->setUser($viewer) 223 265 ->setObject($cart); ··· 229 271 $cart->getMerchantPHID(), 230 272 )); 231 273 232 - $view->addProperty( 233 - pht('Order Name'), 234 - $cart->getName()); 274 + if ($this->action == 'print') { 275 + $view->addProperty(pht('Order Name'), $cart->getName()); 276 + } 277 + 235 278 $view->addProperty( 236 279 pht('Account'), 237 280 $handles[$cart->getAccountPHID()]->renderLink()); ··· 276 319 $refund_uri = $this->getApplicationURI("{$prefix}cart/{$id}/refund/"); 277 320 $update_uri = $this->getApplicationURI("{$prefix}cart/{$id}/update/"); 278 321 $accept_uri = $this->getApplicationURI("{$prefix}cart/{$id}/accept/"); 279 - $print_uri = $this->getApplicationURI("{$prefix}cart/{$id}/?__print__=1"); 322 + $print_uri = $this->getApplicationURI("{$prefix}cart/{$id}/print/"); 280 323 281 324 $curtain->addAction( 282 325 id(new PhabricatorActionView())
+16
src/applications/phortune/controller/PhortuneMerchantViewController.php
··· 129 129 130 130 $view->addProperty(pht('Status'), $status_view); 131 131 132 + $invoice_from = $merchant->getInvoiceEmail(); 133 + if (!$invoice_from) { 134 + $invoice_from = pht('No email address set'); 135 + $invoice_from = phutil_tag('em', array(), $invoice_from); 136 + } 137 + $view->addProperty(pht('Invoice From'), $invoice_from); 138 + 132 139 $description = $merchant->getDescription(); 133 140 if (strlen($description)) { 134 141 $description = new PHUIRemarkupView($viewer, $description); ··· 145 152 pht('Contact Info'), 146 153 PHUIPropertyListView::ICON_SUMMARY); 147 154 $view->addTextContent($contact_info); 155 + } 156 + 157 + $footer_info = $merchant->getInvoiceFooter(); 158 + if (strlen($footer_info)) { 159 + $footer_info = new PHUIRemarkupView($viewer, $footer_info); 160 + $view->addSectionHeader( 161 + pht('Invoice Footer'), 162 + PHUIPropertyListView::ICON_SUMMARY); 163 + $view->addTextContent($footer_info); 148 164 } 149 165 150 166 return id(new PHUIObjectBoxView())
+31 -14
src/applications/phortune/editor/PhortuneMerchantEditEngine.php
··· 84 84 ->setTransactionType(PhortuneMerchantTransaction::TYPE_NAME) 85 85 ->setValue($object->getName()), 86 86 87 + id(new PhabricatorUsersEditField()) 88 + ->setKey('members') 89 + ->setAliases(array('memberPHIDs')) 90 + ->setLabel(pht('Members')) 91 + ->setUseEdgeTransactions(true) 92 + ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) 93 + ->setMetadataValue( 94 + 'edge:type', 95 + PhortuneMerchantHasMemberEdgeType::EDGECONST) 96 + ->setDescription(pht('Initial merchant members.')) 97 + ->setConduitDescription(pht('Set merchant members.')) 98 + ->setConduitTypeDescription(pht('New list of members.')) 99 + ->setInitialValue($object->getMemberPHIDs()) 100 + ->setValue($member_phids), 101 + 87 102 id(new PhabricatorRemarkupEditField()) 88 103 ->setKey('description') 89 104 ->setLabel(pht('Description')) ··· 100 115 ->setTransactionType(PhortuneMerchantTransaction::TYPE_CONTACTINFO) 101 116 ->setValue($object->getContactInfo()), 102 117 103 - id(new PhabricatorUsersEditField()) 104 - ->setKey('members') 105 - ->setAliases(array('memberPHIDs')) 106 - ->setLabel(pht('Members')) 107 - ->setUseEdgeTransactions(true) 108 - ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) 109 - ->setMetadataValue( 110 - 'edge:type', 111 - PhortuneMerchantHasMemberEdgeType::EDGECONST) 112 - ->setDescription(pht('Initial merchant members.')) 113 - ->setConduitDescription(pht('Set merchant members.')) 114 - ->setConduitTypeDescription(pht('New list of members.')) 115 - ->setInitialValue($object->getMemberPHIDs()) 116 - ->setValue($member_phids), 118 + id(new PhabricatorTextEditField()) 119 + ->setKey('invoiceEmail') 120 + ->setLabel(pht('Invoice From Email')) 121 + ->setDescription(pht('Email address invoices are sent from.')) 122 + ->setConduitTypeDescription( 123 + pht('Email address invoices are sent from.')) 124 + ->setTransactionType(PhortuneMerchantTransaction::TYPE_INVOICEEMAIL) 125 + ->setValue($object->getInvoiceEmail()), 126 + 127 + id(new PhabricatorRemarkupEditField()) 128 + ->setKey('invoiceFooter') 129 + ->setLabel(pht('Invoice Footer')) 130 + ->setDescription(pht('Footer on invoice forms.')) 131 + ->setConduitTypeDescription(pht('Footer on invoice forms.')) 132 + ->setTransactionType(PhortuneMerchantTransaction::TYPE_INVOICEFOOTER) 133 + ->setValue($object->getInvoiceFooter()), 117 134 118 135 ); 119 136 }
+39
src/applications/phortune/editor/PhortuneMerchantEditor.php
··· 18 18 $types[] = PhortuneMerchantTransaction::TYPE_DESCRIPTION; 19 19 $types[] = PhortuneMerchantTransaction::TYPE_CONTACTINFO; 20 20 $types[] = PhortuneMerchantTransaction::TYPE_PICTURE; 21 + $types[] = PhortuneMerchantTransaction::TYPE_INVOICEEMAIL; 22 + $types[] = PhortuneMerchantTransaction::TYPE_INVOICEFOOTER; 21 23 $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; 22 24 $types[] = PhabricatorTransactions::TYPE_EDGE; 23 25 ··· 34 36 return $object->getDescription(); 35 37 case PhortuneMerchantTransaction::TYPE_CONTACTINFO: 36 38 return $object->getContactInfo(); 39 + case PhortuneMerchantTransaction::TYPE_INVOICEEMAIL: 40 + return $object->getInvoiceEmail(); 41 + case PhortuneMerchantTransaction::TYPE_INVOICEFOOTER: 42 + return $object->getInvoiceFooter(); 37 43 case PhortuneMerchantTransaction::TYPE_PICTURE: 38 44 return $object->getProfileImagePHID(); 39 45 } ··· 49 55 case PhortuneMerchantTransaction::TYPE_NAME: 50 56 case PhortuneMerchantTransaction::TYPE_DESCRIPTION: 51 57 case PhortuneMerchantTransaction::TYPE_CONTACTINFO: 58 + case PhortuneMerchantTransaction::TYPE_INVOICEEMAIL: 59 + case PhortuneMerchantTransaction::TYPE_INVOICEFOOTER: 52 60 case PhortuneMerchantTransaction::TYPE_PICTURE: 53 61 return $xaction->getNewValue(); 54 62 } ··· 70 78 case PhortuneMerchantTransaction::TYPE_CONTACTINFO: 71 79 $object->setContactInfo($xaction->getNewValue()); 72 80 return; 81 + case PhortuneMerchantTransaction::TYPE_INVOICEEMAIL: 82 + $object->setInvoiceEmail($xaction->getNewValue()); 83 + return; 84 + case PhortuneMerchantTransaction::TYPE_INVOICEFOOTER: 85 + $object->setInvoiceFooter($xaction->getNewValue()); 86 + return; 73 87 case PhortuneMerchantTransaction::TYPE_PICTURE: 74 88 $object->setProfileImagePHID($xaction->getNewValue()); 75 89 return; ··· 86 100 case PhortuneMerchantTransaction::TYPE_NAME: 87 101 case PhortuneMerchantTransaction::TYPE_DESCRIPTION: 88 102 case PhortuneMerchantTransaction::TYPE_CONTACTINFO: 103 + case PhortuneMerchantTransaction::TYPE_INVOICEEMAIL: 104 + case PhortuneMerchantTransaction::TYPE_INVOICEFOOTER: 89 105 case PhortuneMerchantTransaction::TYPE_PICTURE: 90 106 return; 91 107 } ··· 115 131 116 132 $error->setIsMissingFieldError(true); 117 133 $errors[] = $error; 134 + } 135 + break; 136 + case PhortuneMerchantTransaction::TYPE_INVOICEEMAIL: 137 + foreach ($xactions as $xaction) { 138 + switch ($xaction->getTransactionType()) { 139 + case PhortuneMerchantTransaction::TYPE_INVOICEEMAIL: 140 + $new_email = $xaction->getNewValue(); 141 + break; 142 + } 143 + } 144 + if (strlen($new_email)) { 145 + $email = new PhutilEmailAddress($new_email); 146 + $domain = $email->getDomainName(); 147 + 148 + if (!$domain) { 149 + $error = new PhabricatorApplicationTransactionValidationError( 150 + $type, 151 + pht('Invalid'), 152 + pht('%s is not a valid email.', $new_email), 153 + nonempty(last($xactions), null)); 154 + 155 + $errors[] = $error; 156 + } 118 157 } 119 158 break; 120 159 }
+4
src/applications/phortune/storage/PhortuneMerchant.php
··· 9 9 protected $viewPolicy; 10 10 protected $description; 11 11 protected $contactInfo; 12 + protected $invoiceEmail; 13 + protected $invoiceFooter; 12 14 protected $profileImagePHID; 13 15 14 16 private $memberPHIDs = self::ATTACHABLE; ··· 27 29 'name' => 'text255', 28 30 'description' => 'text', 29 31 'contactInfo' => 'text', 32 + 'invoiceEmail' => 'text255', 33 + 'invoiceFooter' => 'text', 30 34 'profileImagePHID' => 'phid?', 31 35 ), 32 36 ) + parent::getConfiguration();
+16
src/applications/phortune/storage/PhortuneMerchantTransaction.php
··· 6 6 const TYPE_NAME = 'merchant:name'; 7 7 const TYPE_DESCRIPTION = 'merchant:description'; 8 8 const TYPE_CONTACTINFO = 'merchant:contactinfo'; 9 + const TYPE_INVOICEEMAIL = 'merchant:invoiceemail'; 10 + const TYPE_INVOICEFOOTER = 'merchant:invoicefooter'; 9 11 const TYPE_PICTURE = 'merchant:picture'; 10 12 11 13 public function getApplicationName() { ··· 48 50 return pht( 49 51 '%s updated the contact information for this merchant.', 50 52 $this->renderHandleLink($author_phid)); 53 + case self::TYPE_INVOICEEMAIL: 54 + return pht( 55 + '%s updated the invoice email for this merchant.', 56 + $this->renderHandleLink($author_phid)); 57 + case self::TYPE_INVOICEFOOTER: 58 + return pht( 59 + '%s updated the invoice footer for this merchant.', 60 + $this->renderHandleLink($author_phid)); 51 61 } 52 62 53 63 return parent::getTitle(); ··· 58 68 switch ($this->getTransactionType()) { 59 69 case self::TYPE_DESCRIPTION: 60 70 case self::TYPE_CONTACTINFO: 71 + case self::TYPE_INVOICEEMAIL: 72 + case self::TYPE_INVOICEFOOTER: 61 73 return ($old === null); 62 74 } 63 75 return parent::shouldHide(); ··· 68 80 case self::TYPE_DESCRIPTION: 69 81 return ($this->getOldValue() !== null); 70 82 case self::TYPE_CONTACTINFO: 83 + return ($this->getOldValue() !== null); 84 + case self::TYPE_INVOICEEMAIL: 85 + return ($this->getOldValue() !== null); 86 + case self::TYPE_INVOICEFOOTER: 71 87 return ($this->getOldValue() !== null); 72 88 } 73 89
+159
src/applications/phortune/view/PhortuneInvoiceView.php
··· 1 + <?php 2 + 3 + final class PhortuneInvoiceView extends AphrontTagView { 4 + 5 + private $merchantName; 6 + private $merchantLogo; 7 + private $merchantContact; 8 + private $merchantFooter; 9 + private $accountName; 10 + private $accountContact; 11 + private $status; 12 + private $content; 13 + 14 + public function setMerchantName($name) { 15 + $this->merchantName = $name; 16 + return $this; 17 + } 18 + 19 + public function setMerchantLogo($logo) { 20 + $this->merchantLogo = $logo; 21 + return $this; 22 + } 23 + 24 + public function setMerchantContact($contact) { 25 + $this->merchantContact = $contact; 26 + return $this; 27 + } 28 + 29 + public function setMerchantFooter($footer) { 30 + $this->merchantFooter = $footer; 31 + return $this; 32 + } 33 + 34 + public function setAccountName($name) { 35 + $this->accountName = $name; 36 + return $this; 37 + } 38 + 39 + public function setAccountContact($contact) { 40 + $this->accountContact = $contact; 41 + return $this; 42 + } 43 + 44 + public function setStatus($status) { 45 + $this->status = $status; 46 + return $this; 47 + } 48 + 49 + public function setContent($content) { 50 + $this->content = $content; 51 + return $this; 52 + } 53 + 54 + protected function getTagAttributes() { 55 + $classes = array(); 56 + $classes[] = 'phortune-invoice-view'; 57 + 58 + return array( 59 + 'class' => implode(' ', $classes), 60 + ); 61 + } 62 + 63 + protected function getTagContent() { 64 + require_celerity_resource('phortune-invoice-css'); 65 + 66 + $logo = phutil_tag( 67 + 'div', 68 + array( 69 + 'class' => 'phortune-invoice-logo', 70 + ), 71 + phutil_tag( 72 + 'img', 73 + array( 74 + 'height' => '50', 75 + 'width' => '50', 76 + 'alt' => $this->merchantName, 77 + 'src' => $this->merchantLogo, 78 + ))); 79 + 80 + $to_title = phutil_tag( 81 + 'div', 82 + array( 83 + 'class' => 'phortune-mini-header', 84 + ), 85 + pht('To:')); 86 + 87 + $bill_to = phutil_tag( 88 + 'td', 89 + array( 90 + 'class' => 'phortune-invoice-to', 91 + 'width' => '50%', 92 + ), 93 + array( 94 + $to_title, 95 + phutil_tag('strong', array(), $this->accountName), 96 + phutil_tag('br', array()), 97 + $this->accountContact, 98 + )); 99 + 100 + $from_title = phutil_tag( 101 + 'div', 102 + array( 103 + 'class' => 'phortune-mini-header', 104 + ), 105 + pht('From:')); 106 + 107 + $bill_from = phutil_tag( 108 + 'td', 109 + array( 110 + 'class' => 'phortune-invoice-from', 111 + 'width' => '50%', 112 + ), 113 + array( 114 + $from_title, 115 + phutil_tag('strong', array(), $this->merchantName), 116 + phutil_tag('br', array()), 117 + $this->merchantContact, 118 + )); 119 + 120 + $contact = phutil_tag( 121 + 'table', 122 + array( 123 + 'class' => 'phortune-invoice-contact', 124 + 'width' => '100%', 125 + ), 126 + phutil_tag( 127 + 'tr', 128 + array(), 129 + array( 130 + $bill_to, 131 + $bill_from, 132 + ))); 133 + 134 + $status = null; 135 + if ($this->status) { 136 + $status = phutil_tag( 137 + 'div', 138 + array( 139 + 'class' => 'phortune-invoice-status', 140 + ), 141 + $this->status); 142 + } 143 + 144 + $footer = phutil_tag( 145 + 'div', 146 + array( 147 + 'class' => 'phortune-invoice-footer', 148 + ), 149 + $this->merchantFooter); 150 + 151 + return array( 152 + $logo, 153 + $contact, 154 + $status, 155 + $this->content, 156 + $footer, 157 + ); 158 + } 159 + }
+75
webroot/rsrc/css/application/phortune/phortune-invoice.css
··· 1 + /** 2 + * @provides phortune-invoice-css 3 + */ 4 + 5 + .phortune-invoice-view { 6 + max-width: 800px; 7 + margin: 16px auto; 8 + background: #fff; 9 + } 10 + 11 + .phortune-invoice-view .phabricator-main-menu { 12 + display: none; 13 + } 14 + 15 + .phortune-invoice-view .phabricator-standard-page-footer { 16 + display: none; 17 + } 18 + 19 + .device-desktop .phortune-invoice-view .phui-property-list-key { 20 + width: 16%; 21 + } 22 + 23 + .device-desktop .phortune-invoice-view .phui-property-list-value { 24 + width: 80%; 25 + } 26 + 27 + .phortune-invoice-logo { 28 + margin-bottom: 24px; 29 + } 30 + 31 + .phortune-invoice-logo img { 32 + margin: 0 auto; 33 + } 34 + 35 + .phortune-invoice-contact { 36 + margin-bottom: 32px; 37 + } 38 + 39 + .phortune-invoice-contact td { 40 + padding: 4px 16px; 41 + } 42 + 43 + .phortune-invoice-to { 44 + border-right: 1px solid {$lightblueborder}; 45 + } 46 + 47 + .phortune-mini-header { 48 + color: {$lightbluetext}; 49 + font-weight: bold; 50 + text-transform: uppercase; 51 + margin-bottom: 4px; 52 + letter-spacing: 0.3em; 53 + } 54 + 55 + .phortune-invoice-status { 56 + margin-bottom: 24px; 57 + } 58 + 59 + .phortune-invoice-status .phui-info-view { 60 + margin: 0; 61 + } 62 + 63 + .phortune-invoice-view .phui-box.phui-object-box { 64 + margin-bottom: 24px; 65 + } 66 + 67 + .phortune-invoice-footer { 68 + color: {$lightgreytext}; 69 + margin: 48px 0 64px; 70 + text-align: center; 71 + } 72 + 73 + .phortune-invoice-footer strong { 74 + color: #000; 75 + }